201026
authorhgs
Fri, 24 Sep 2010 16:14:28 +0300
changeset 187 9f66f99ee56f
parent 103 2717213c588a
child 188 1b081cb0800b
201026
egl/eglinterface/include/1.4/eglext.h
egl/egltest/group/egltest_helium.pkg
egl/egltest/src/egltest_image.cpp
egl/egltest/src/egltest_image_multiprocess.cpp
fbs/fontandbitmapserver/bwins/FBSCLI2U.DEF
fbs/fontandbitmapserver/bwins/fbservu.def
fbs/fontandbitmapserver/eabi/FBSCLI2U.DEF
fbs/fontandbitmapserver/eabi/fbservu.def
fbs/fontandbitmapserver/group/FBSCLI.MMP
fbs/fontandbitmapserver/group/FBSERV.MMP
fbs/fontandbitmapserver/group/FbservTest.iby
fbs/fontandbitmapserver/group/TFbsServer.mmp
fbs/fontandbitmapserver/group/bld.inf
fbs/fontandbitmapserver/group/fbserv.iby
fbs/fontandbitmapserver/group/fbservtest_helium.pkg
fbs/fontandbitmapserver/group/fbsoogmplugin.iby
fbs/fontandbitmapserver/group/fbsoogmplugin.mmp
fbs/fontandbitmapserver/inc/FBS.H
fbs/fontandbitmapserver/inc/FbsMessage.H
fbs/fontandbitmapserver/sfbs/FBSCLI.CPP
fbs/fontandbitmapserver/sfbs/FBSFONT.CPP
fbs/fontandbitmapserver/sfbs/FBSTOP.CPP
fbs/fontandbitmapserver/sfbs/SERVER.CPP
fbs/fontandbitmapserver/sfbs/SERVER.H
fbs/fontandbitmapserver/sfbs/SESSION.CPP
fbs/fontandbitmapserver/sfbs/UTILS.H
fbs/fontandbitmapserver/sfbs/fbsglyphdataiterator.cpp
fbs/fontandbitmapserver/sfbs/fbsglyphdataiterator.h
fbs/fontandbitmapserver/sfbs/fbsglyphmetricsarray.cpp
fbs/fontandbitmapserver/sfbs/fbsglyphmetricsarray.h
fbs/fontandbitmapserver/sfbs/fbsoogmmessage.h
fbs/fontandbitmapserver/sfbs/fbsoogmmessage.inl
fbs/fontandbitmapserver/sfbs/fbsoogmplugin.cpp
fbs/fontandbitmapserver/sfbs/fbsoogmplugin.h
fbs/fontandbitmapserver/sfbs/fbsoogmplugin.rss
fbs/fontandbitmapserver/sfbs/glyphatlas.cpp
fbs/fontandbitmapserver/sfbs/glyphatlas.h
fbs/fontandbitmapserver/sfbs/patchableconstants.cpp
fbs/fontandbitmapserver/tfbs/TALLOC.H
fbs/fontandbitmapserver/tfbs/TBitmap.h
fbs/fontandbitmapserver/tfbs/TCLEAN.H
fbs/fontandbitmapserver/tfbs/TFBS.CPP
fbs/fontandbitmapserver/tfbs/TFBSDefect.h
fbs/fontandbitmapserver/tfbs/TFbsServer.cpp
fbs/fontandbitmapserver/tfbs/TGetAllBitmapsCapability.h
fbs/fontandbitmapserver/tfbs/TRalc.h
fbs/fontandbitmapserver/tfbs/TSecureFBS.h
fbs/fontandbitmapserver/tfbs/TStreamIdCache.h
fbs/fontandbitmapserver/tfbs/glyphatlastestwrapper.cpp
fbs/fontandbitmapserver/tfbs/glyphatlastestwrapper.h
fbs/fontandbitmapserver/tfbs/scripts/fbstest_T_IPCTest.script
fbs/fontandbitmapserver/tfbs/scripts/fbstest_run.bat
fbs/fontandbitmapserver/tfbs/scripts/fbstest_t_fonttable.script
fbs/fontandbitmapserver/tfbs/scripts/fbstest_t_glyphdata.script
fbs/fontandbitmapserver/tfbs/scripts/fbstest_t_glyphdataoutlineshadow.script
fbs/fontandbitmapserver/tfbs/scripts/fbstest_t_oogm.script
fbs/fontandbitmapserver/tfbs/scripts/glyphdata_config.ini
fbs/fontandbitmapserver/tfbs/scripts/ipctest_config.ini
fbs/fontandbitmapserver/tfbs/tcompressed.h
fbs/fontandbitmapserver/tfbs/textendedbitmapcommon.h
fbs/fontandbitmapserver/tfbs/tfbsbase.h
fbs/fontandbitmapserver/tfbs/tfbsglyphdata.cpp
fbs/fontandbitmapserver/tfbs/tfbsglyphdata.h
fbs/fontandbitmapserver/tfbs/tfbsglyphdataoutlineshadow.cpp
fbs/fontandbitmapserver/tfbs/tfbsglyphdataoutlineshadow.h
fbs/fontandbitmapserver/tfbs/tfbsglyphdatapanic.cpp
fbs/fontandbitmapserver/tfbs/tfbsglyphdatapanic.h
fbs/fontandbitmapserver/tfbs/tfbsoogm.cpp
fbs/fontandbitmapserver/tfbs/tfbsoogm.h
fbs/fontandbitmapserver/tfbs/tfonttableandglyph.h
fbs/fontandbitmapserver/tfbs/tglyphatlas.cpp
fbs/fontandbitmapserver/tfbs/tglyphatlas.h
fbs/fontandbitmapserver/tfbs/tipctest.CPP
fbs/fontandbitmapserver/tfbs/tipctest.h
fbs/fontandbitmapserver/tfbs/trfile.h
fbs/fontandbitmapserver/tfbs/twdp.h
fbs/fontandbitmapserver/traces/OstTraceDefinitions.h
fbs/fontandbitmapserver/traces/fixed_id.definitions
graphicsdeviceinterface/bitgdi/sbit/FONTBMP.CPP
graphicsdeviceinterface/bitgdi/sbit/MAIN.CPP
graphicsdeviceinterface/gdi/bwins/GDI2U.def
graphicsdeviceinterface/gdi/inc/GDI.H
graphicsdeviceinterface/gdi/inc/gdiconsts.h
graphicsdeviceinterface/gdi/inc/gdiplatapi.h
graphicsdeviceinterface/screendriver/sbit/Cdsb.cpp
graphicsdeviceinterface/screendriver/sgeneric/scdraw.h
graphicsdeviceinterface/screendriver/sgeneric/scdraw.inl
graphicsdeviceinterface/screendriver/sgeneric/scnew.cpp
graphicstest/graphicstestharness/automation/h4/tests_00b.txt
graphicstest/graphicstestharness/automation/h4/tests_01.txt
graphicstest/graphicstestharness/automation/h4/tests_01a.txt
graphicstest/graphicstestharness/automation/h6/tests_00b.txt
graphicstest/graphicstestharness/automation/h6/tests_01.txt
graphicstest/graphicstestharness/automation/h6/tests_01a.txt
graphicstest/graphicstestharness/automation/ne1/tests_01.txt
graphicstest/graphicstestharness/automation/ne1/tests_01a.txt
graphicstest/graphicstestharness/automation/winscw/tests.txt
graphicstest/graphicstestharness/bwins/tprofileru.def
graphicstest/graphicstestharness/eabi/tprofileru.def
graphicstest/graphicstestharness/inc/TGraphicsHarness.h
graphicstest/graphicstestharness/inc/tprofiler.h
graphicstest/graphicstestharness/src/tprofiler.cpp
graphicstest/uibench/group/bld.inf
graphicstest/uibench/group/te_uibench.iby
graphicstest/uibench/group/te_uibench.mmp
graphicstest/uibench/group/te_uibench_gce.mmp
graphicstest/uibench/group/te_uibench_helium.pkg
graphicstest/uibench/s60/group/te_uibench_s60.mmp
graphicstest/uibench/scripts/te_uibench.ini
graphicstest/uibench/scripts/te_uibench.script
graphicstest/uibench/scripts/te_uibench_gce.ini
graphicstest/uibench/scripts/te_uibench_gce.script
graphicstest/uibench/src/te_graphicsperformanceSuiteDefs.h
graphicstest/uibench/src/te_graphicsperformanceSuiteServer.cpp
graphicstest/uibench/src/tfbsglyphdata.cpp
graphicstest/uibench/src/tfbsglyphdata.h
graphicstest/uibench/src/tgcesuiteserver.cpp
m3g/m3gcore11/src/m3g_loader.c
m3g/m3gcore11/src/m3g_sprite.c
m3g/m3gcore11/src/m3g_vertexarray.c
m3g/m3gcore11/src/m3g_vertexbuffer.c
windowing/windowserver/inc/Graphics/openwfc/WSGRAPHICDRAWERINTERFACE.H
windowing/windowserver/nga/SERVER/openwfc/WINDOW.CPP
windowing/windowserver/nga/SERVER/openwfc/cliwin.cpp
windowing/windowserver/nga/SERVER/wsdisplaychangeao.cpp
windowing/windowserver/nonnga/SERVER/WSTOP.CPP
windowing/windowserver/test/tauto/talphawin.cpp
windowing/windowserver/test/tauto/tgc.cpp
windowing/windowserver/test/tdynamicres/group/bld.inf
windowing/windowserver/test/tdynamicres/group/wstestdynamicres.iby
windowing/windowserver/test/tdynamicres/group/wstestdynamicres_helium.pkg
windowing/windowserver/test/tdynamicres/inc/wsdynamicresbase.h
windowing/windowserver/test/tdynamicres/scripts/wsdynamicresbasic_sirocco.script
windowing/windowserver/test/tdynamicres/src/t_wsdynamicreswinbase.cpp
windowing/windowserver/test/tdynamicres/src/wsdynamicresbase.cpp
windowing/windowserver/test/tdynamicres/src/wsdynamicresbasic.cpp
windowing/windowserverplugins/openwfc/group/stdplugin.mmp
windowing/windowserverplugins/openwfc/src/displayrenderstage.cpp
windowing/windowserverplugins/openwfc/src/fbrenderstage.cpp
--- a/egl/eglinterface/include/1.4/eglext.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/egl/eglinterface/include/1.4/eglext.h	Fri Sep 24 16:14:28 2010 +0300
@@ -263,17 +263,17 @@
 EGLAPI EGLBoolean EGLAPIENTRY eglEndpointCancelNotificationNOK(EGLDisplay dpy, EGLEndpointNOK endpoint);
 #endif
 
-typedef EGLEndpointNOK ( *PFNEGLCREATEENDPOINTNOKPROC) (EGLDisplay dpy, EGLenum type, EGLenum source_type, EGLEndpointSourceNOK source, const EGLint* attrib_list);
-typedef EGLBoolean ( *PFNEGLDESTROYENDPOINTNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint);
-typedef EGLint ( *PFNEGLGETENDPOINTATTRIBNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint, EGLint attrib);
-typedef EGLBoolean ( *PFNEGLSETENDPOINTATTRIBNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint, EGLint attrib, EGLint value);
-typedef EGLBoolean ( *PFNEGLENDPOINTBEGINSTREAMINGNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint);
-typedef EGLBoolean ( *PFNEGLENDPOINTENDSTREAMINGNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint);
-typedef EGLImageKHR  ( *PFNEGLACQUIREIMAGENOKPROC)(EGLDisplay dpy, EGLEndpointNOK endpoint);
-typedef EGLBoolean ( *PFNEGLRELEASEIMAGENOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint, EGLImageKHR image, EGLenum api);
-typedef EGLint ( *PFNEGLGETENDPOINTDIRTYAREANOKPROC) (EGLDisplay dpy,  EGLEndpointNOK endpoint, EGLint* rects, EGLint start_rect, EGLint max_rects,  EGLBoolean collapse); 
-typedef EGLBoolean ( *PFNEGLENDPOINTREQUESTNOTIFICATIONNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint, EGLTRequestStatusNOK sync);
-typedef EGLBoolean ( *PFNEGLENDPOINTCANCELNOTIFICATIONNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint);
+typedef EGLEndpointNOK (EGLAPIENTRYP PFNEGLCREATEENDPOINTNOKPROC) (EGLDisplay dpy, EGLenum type, EGLenum source_type, EGLEndpointSourceNOK source, const EGLint* attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYENDPOINTNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint);
+typedef EGLint (EGLAPIENTRYP PFNEGLGETENDPOINTATTRIBNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint, EGLint attrib);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETENDPOINTATTRIBNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint, EGLint attrib, EGLint value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLENDPOINTBEGINSTREAMINGNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLENDPOINTENDSTREAMINGNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint);
+typedef EGLImageKHR  (EGLAPIENTRYP PFNEGLACQUIREIMAGENOKPROC)(EGLDisplay dpy, EGLEndpointNOK endpoint);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLRELEASEIMAGENOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint, EGLImageKHR image, EGLenum api);
+typedef EGLint (EGLAPIENTRYP PFNEGLGETENDPOINTDIRTYAREANOKPROC) (EGLDisplay dpy,  EGLEndpointNOK endpoint, EGLint* rects, EGLint start_rect, EGLint max_rects,  EGLBoolean collapse); 
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLENDPOINTREQUESTNOTIFICATIONNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint, EGLTRequestStatusNOK sync);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLENDPOINTCANCELNOTIFICATIONNOKPROC) (EGLDisplay dpy, EGLEndpointNOK endpoint);
 #endif
 
 #ifndef EGL_SYMBIAN_COMPOSITION
--- a/egl/egltest/group/egltest_helium.pkg	Tue Jun 22 15:21:29 2010 +0300
+++ b/egl/egltest/group/egltest_helium.pkg	Fri Sep 24 16:14:28 2010 +0300
@@ -49,4 +49,6 @@
 "\epoc32\data\z\egltest\egltest_t_image_negative.script"-"c:\egltest\egltest_t_image_negative.script"
 "\epoc32\data\z\egltest\egltest_t_benchmark_sgimage.script"-"c:\egltest\egltest_t_benchmark_sgimage.script"
 "\epoc32\data\z\egltest\egltest_t_benchmark_swapbuffers.script"-"c:\egltest\egltest_t_benchmark_swapbuffers.script"
+"\epoc32\data\z\egltest\egltest_t_oom_sgimage.script"-"c:\egltest\egltest_t_oom_sgimage.script"
+"\epoc32\data\z\egltest\egltest_t_stress_sgimage.script"-"c:\egltest\egltest_t_stress_sgimage.script"
 
--- a/egl/egltest/src/egltest_image.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/egl/egltest/src/egltest_image.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2007-2010 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"
@@ -146,6 +146,7 @@
 	address += (bitmapSize.iHeight - 1) * stride;
 	vgWritePixels(address, -stride, KDefaultSurfaceFormat,0,0, bitmapSize.iWidth, bitmapSize.iHeight);
 	ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
+	eglWaitClient();   // wait for writing to finish
    	ASSERT_EGL_TRUE(eglDestroySurface(iDisplay, surface));				//Destroying Surface handle
 
 	INFO_PRINTF1(_L("Create a EGLImage out of the SgImage"));
--- a/egl/egltest/src/egltest_image_multiprocess.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/egl/egltest/src/egltest_image_multiprocess.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -1468,6 +1468,7 @@
     	TInt stride = bitmap->DataStride();
     	address += (bitmapSize.iHeight - 1) * stride;
     	vgWritePixels(address, -stride, iSurfaceFormat, 0,0, bitmapSize.iWidth, bitmapSize.iHeight);
+   	    eglWaitClient();   // wait for writing to finish
 		delete bitmap;
 		bitmap = NULL;
 		ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
--- a/fbs/fontandbitmapserver/bwins/FBSCLI2U.DEF	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/bwins/FBSCLI2U.DEF	Fri Sep 24 16:14:28 2010 +0300
@@ -229,4 +229,19 @@
 	?CreateExtendedBitmap@CFbsBitmap@@QAEHABVTSize@@W4TDisplayMode@@VTUid@@PBXH@Z @ 228 NONAME ; int CFbsBitmap::CreateExtendedBitmap(class TSize const &, enum TDisplayMode, class TUid, void const *, int)
 	?UpdateLinkedTypeface@CFbsTypefaceStore@@QAEHABVCLinkedTypefaceSpecification@@@Z @ 229 NONAME ; int CFbsTypefaceStore::UpdateLinkedTypeface(class CLinkedTypefaceSpecification const &)
 	?GetExtraBuffer@CFbsBitmap@@SAPAVHBufC8@@H@Z @ 230 NONAME ; class HBufC8 * CFbsBitmap::GetExtraBuffer(int)
+	?Rect@RFbsGlyphDataIterator@@QBEABVTRect@@XZ @ 231 NONAME ; class TRect const & RFbsGlyphDataIterator::Rect(void) const
+	?Image@RFbsGlyphDataIterator@@QBEABVRSgImage@@XZ @ 232 NONAME ; class RSgImage const & RFbsGlyphDataIterator::Image(void) const
+	??0RFbsGlyphMetricsArray@@QAE@XZ @ 233 NONAME ; RFbsGlyphMetricsArray::RFbsGlyphMetricsArray(void)
+	?Count@RFbsGlyphMetricsArray@@QBEHXZ @ 234 NONAME ; int RFbsGlyphMetricsArray::Count(void) const
+	?Next@RFbsGlyphDataIterator@@QAEHXZ @ 235 NONAME ; int RFbsGlyphDataIterator::Next(void)
+	?Metrics@RFbsGlyphDataIterator@@QBEABVTOpenFontCharMetrics@@XZ @ 236 NONAME ; class TOpenFontCharMetrics const & RFbsGlyphDataIterator::Metrics(void) const
+	?Close@RFbsGlyphMetricsArray@@QAEXXZ @ 237 NONAME ; void RFbsGlyphMetricsArray::Close(void)
+	??0RFbsGlyphDataIterator@@QAE@XZ @ 238 NONAME ; RFbsGlyphDataIterator::RFbsGlyphDataIterator(void)
+	??ARFbsGlyphMetricsArray@@QBEABVTOpenFontCharMetrics@@H@Z @ 239 NONAME ; class TOpenFontCharMetrics const & RFbsGlyphMetricsArray::operator[](int) const
+	?GlyphCode@RFbsGlyphDataIterator@@QBEIXZ @ 240 NONAME ; unsigned int RFbsGlyphDataIterator::GlyphCode(void) const
+	?Close@RFbsGlyphDataIterator@@QAEXXZ @ 241 NONAME ; void RFbsGlyphDataIterator::Close(void)
+	?Get@RFbsGlyphMetricsArray@@QAEHAAVCFbsFont@@PBIH@Z @ 242 NONAME ; int RFbsGlyphMetricsArray::Get(class CFbsFont &, unsigned int const *, int)
+	?Open@RFbsGlyphDataIterator@@QAEHAAVCFbsFont@@PBIH@Z @ 243 NONAME ; int RFbsGlyphDataIterator::Open(class CFbsFont &, unsigned int const *, int)
+	?GetGlyphCacheMetrics@RFbsSession@@QAEHAAVTGlyphCacheMetrics@@@Z @ 244 NONAME ; int RFbsSession::GetGlyphCacheMetrics(class TGlyphCacheMetrics &)
+	?ConveyOogmMessage@RFbsSession@@QAEHAAVTFbsOogmMessage@@@Z @ 245 NONAME ; int RFbsSession::ConveyOogmMessage(class TFbsOogmMessage &)
 
--- a/fbs/fontandbitmapserver/bwins/fbservu.def	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/bwins/fbservu.def	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,5 @@
 EXPORTS
 	?KFbServSharedHeapMaxSize@@3HB @ 1 NONAME ; int const KFbServSharedHeapMaxSize
 	?KFbServWritableDataPagingMode@@3HB @ 2 NONAME ; int const KFbServWritableDataPagingMode
+	?KFbServGlyphAtlasCacheLimit@@3HB @ 3 NONAME ; int const KFbServGlyphAtlasCacheLimit
 
--- a/fbs/fontandbitmapserver/eabi/FBSCLI2U.DEF	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/eabi/FBSCLI2U.DEF	Fri Sep 24 16:14:28 2010 +0300
@@ -264,4 +264,21 @@
 	_ZNK10CFbsBitmap8DataSizeEv @ 263 NONAME
 	_ZN17CFbsTypefaceStore20UpdateLinkedTypefaceERK28CLinkedTypefaceSpecification @ 264 NONAME
 	_ZN10CFbsBitmap14GetExtraBufferEi @ 265 NONAME
+	_ZN21RFbsGlyphDataIterator4NextEv @ 266 NONAME
+	_ZN21RFbsGlyphDataIterator4OpenER8CFbsFontPKji @ 267 NONAME
+	_ZN21RFbsGlyphDataIterator5CloseEv @ 268 NONAME
+	_ZN21RFbsGlyphDataIteratorC1Ev @ 269 NONAME
+	_ZN21RFbsGlyphDataIteratorC2Ev @ 270 NONAME
+	_ZN21RFbsGlyphMetricsArray3GetER8CFbsFontPKji @ 271 NONAME
+	_ZN21RFbsGlyphMetricsArray5CloseEv @ 272 NONAME
+	_ZN21RFbsGlyphMetricsArrayC1Ev @ 273 NONAME
+	_ZN21RFbsGlyphMetricsArrayC2Ev @ 274 NONAME
+	_ZNK21RFbsGlyphDataIterator4RectEv @ 275 NONAME
+	_ZNK21RFbsGlyphDataIterator5ImageEv @ 276 NONAME
+	_ZNK21RFbsGlyphDataIterator7MetricsEv @ 277 NONAME
+	_ZNK21RFbsGlyphDataIterator9GlyphCodeEv @ 278 NONAME
+	_ZNK21RFbsGlyphMetricsArray5CountEv @ 279 NONAME
+	_ZNK21RFbsGlyphMetricsArrayixEi @ 280 NONAME
+	_ZN11RFbsSession20GetGlyphCacheMetricsER18TGlyphCacheMetrics @ 281 NONAME
+	_ZN11RFbsSession17ConveyOogmMessageER15TFbsOogmMessage @ 282 NONAME
 
--- a/fbs/fontandbitmapserver/eabi/fbservu.def	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/eabi/fbservu.def	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,5 @@
 EXPORTS
 	KFbServSharedHeapMaxSize @ 1 NONAME DATA 4
 	KFbServWritableDataPagingMode @ 2 NONAME DATA 4
+	KFbServGlyphAtlasCacheLimit @ 3 NONAME DATA 4
 
--- a/fbs/fontandbitmapserver/group/FBSCLI.MMP	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/group/FBSCLI.MMP	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1998-2010 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"
@@ -28,8 +28,9 @@
 SOURCEPATH      ../sfbs
 
 userinclude     ../inc
-userinclude		../../../../textandloc/fontservices/fontstore/src
+userinclude     ../traces
 
+OS_LAYER_SYSTEMINCLUDE
 OS_LAYER_SYSTEMINCLUDE_SYMBIAN
 
 source          BITBMP.CPP
@@ -47,6 +48,8 @@
 source          ShiftedFileStore.cpp
 source          BitmapCompr.cpp
 source          patchableconstantscli.cpp
+source          fbsglyphdataiterator.cpp
+source          fbsglyphmetricsarray.cpp
 
 library         euser.lib
 library         efsrv.lib
@@ -57,6 +60,7 @@
 library         palette.lib
 library         lookuptable.lib
 library         hal.lib
+library         sgresource.lib
 #if !defined(WINS)
 library         fbsrasterizer.lib
 #endif
--- a/fbs/fontandbitmapserver/group/FBSERV.MMP	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/group/FBSERV.MMP	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1998-2010 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"
@@ -35,7 +35,9 @@
 
 userinclude     ../inc
 userinclude     ../sfbs
+userinclude     ../traces
 
+OS_LAYER_SYSTEMINCLUDE
 OS_LAYER_SYSTEMINCLUDE_SYMBIAN
 OS_LAYER_ESTLIB_SYSTEMINCLUDE
 
@@ -49,7 +51,8 @@
 source          FBSMBMC.CPP
 source          ShiftedFileStore.cpp
 source          HASHMAP.CPP
-source			patchableconstants.cpp
+source		patchableconstants.cpp
+source          glyphatlas.cpp
 
 library         euser.lib
 library         efsrv.lib
@@ -59,6 +62,7 @@
 library         estor.lib
 library         ecom.lib
 library         hal.lib
+library         sgresource.lib
 
 start wins
 baseaddress     0x41500000
--- a/fbs/fontandbitmapserver/group/FbservTest.iby	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/group/FbservTest.iby	Fri Sep 24 16:14:28 2010 +0300
@@ -19,36 +19,44 @@
 #define __FBSERVTEST_IBY__
 
 #include <graphics_testharness.iby>
-#include <internaltestfonts.iby>  
+#include <internaltestfonts.iby>
+#include <egl.iby>
+#include <openvg.iby>
 
 // batch file that runs all automatic fbserv tests
 data=DATAZ_\fbstest\fbstest_run.bat		\fbstest_run.bat
 data=DATAZ_\fbstest\fbstest.bat			\fbstest.bat
 
 //script files
-data=DATAZ_\fbstest\fbstest_T_All.script						\fbstest\fbstest_T_All.script
-data=DATAZ_\fbstest\fbstest_T_Alloc.script						\fbstest\fbstest_T_Alloc.script
+data=DATAZ_\fbstest\fbstest_T_All.script					\fbstest\fbstest_T_All.script
+data=DATAZ_\fbstest\fbstest_T_Alloc.script					\fbstest\fbstest_T_Alloc.script
 data=DATAZ_\fbstest\fbstest_T_Alloc.ini						\fbstest\fbstest_T_Alloc.ini
-data=DATAZ_\fbstest\fbstest_T_Bitmap.script						\fbstest\fbstest_T_Bitmap.script
-data=DATAZ_\fbstest\fbstest_T_Fbs.script						\fbstest\fbstest_T_Fbs.script
+data=DATAZ_\fbstest\fbstest_T_Bitmap.script					\fbstest\fbstest_T_Bitmap.script
+data=DATAZ_\fbstest\fbstest_T_Fbs.script					\fbstest\fbstest_T_Fbs.script
 data=DATAZ_\fbstest\fbstest_T_Compressed.script					\fbstest\fbstest_T_Compressed.script
-data=DATAZ_\fbstest\fbstest_T_Ralc.script						\fbstest\fbstest_T_Ralc.script
-data=DATAZ_\fbstest\fbstest_T_Defect.script						\fbstest\fbstest_T_Defect.script
+data=DATAZ_\fbstest\fbstest_T_Ralc.script					\fbstest\fbstest_T_Ralc.script
+data=DATAZ_\fbstest\fbstest_T_Defect.script					\fbstest\fbstest_T_Defect.script
 data=DATAZ_\fbstest\fbstest_T_StreamIdCache.script				\fbstest\fbstest_T_StreamIdCache.script
-data=DATAZ_\fbstest\fbstest_T_Secure.script						\fbstest\fbstest_T_Secure.script
-data=DATAZ_\fbstest\fbstest_T_File.script						\fbstest\fbstest_T_File.script
-data=DATAZ_\fbstest\fbstest_t_getallbitmapscapability.script	\fbstest\fbstest_t_getallbitmapscapability.script
-data=DATAZ_\fbstest\fbstest_T_Clean.script						\fbstest\fbstest_T_Clean.script
+data=DATAZ_\fbstest\fbstest_T_Secure.script					\fbstest\fbstest_T_Secure.script
+data=DATAZ_\fbstest\fbstest_T_File.script					\fbstest\fbstest_T_File.script
+data=DATAZ_\fbstest\fbstest_t_getallbitmapscapability.script			\fbstest\fbstest_t_getallbitmapscapability.script
+data=DATAZ_\fbstest\fbstest_T_Clean.script					\fbstest\fbstest_T_Clean.script
 data=DATAZ_\fbstest\fbstest_t_fonttable.script					\fbstest\fbstest_t_fonttable.script
 data=DATAZ_\fbstest\fbstest_T_IPCTest.script					\fbstest\fbstest_T_IPCTest.script
-data=DATAZ_\fbstest\ipctest_config.ini							\fbstest\ipctest_config.ini
+data=DATAZ_\fbstest\ipctest_config.ini						\fbstest\ipctest_config.ini
 data=DATAZ_\fbstest\fbstest_t_extendedbitmap.script				\fbstest\fbstest_t_extendedbitmap.script
 data=DATAZ_\fbstest\extendedbitmap_config.ini					\fbstest\extendedbitmap_config.ini
 data=DATAZ_\fbstest\fbstest_T_WDP_pagedata.script				\fbstest\fbstest_T_WDP_pagedata.script
 data=DATAZ_\fbstest\fbstest_T_WDP_unpagedata.script				\fbstest\fbstest_T_WDP_unpagedata.script
-data=DATAZ_\fbstest\fbstest_T_WDP_page_bitmap_data_only.script	\fbstest\fbstest_T_WDP_page_bitmap_data_only.script
-data=DATAZ_\fbstest\fbstest_T_WDP_page_bitmap_data_and_shared_heap_only.script		\fbstest\fbstest_T_WDP_page_bitmap_data_and_shared_heap_only.script
-data=DATAZ_\fbstest\wdptest_config.ini						    \fbstest\wdptest_config.ini
+data=DATAZ_\fbstest\fbstest_T_WDP_page_bitmap_data_only.script			\fbstest\fbstest_T_WDP_page_bitmap_data_only.script
+data=DATAZ_\fbstest\fbstest_t_oogm.script					\fbstest\fbstest_t_oogm.script
+data=DATAZ_\fbstest\fbstest_T_WDP_page_bitmap_data_and_shared_heap_only.script	\fbstest\fbstest_T_WDP_page_bitmap_data_and_shared_heap_only.script
+data=DATAZ_\fbstest\wdptest_config.ini						\fbstest\wdptest_config.ini
+
+REM GPU Glyph caching tests
+data=DATAZ_\fbstest\fbstest_t_glyphdata.script		\fbstest\fbstest_t_glyphdata.script
+data=DATAZ_\fbstest\glyphdata_config.ini					\fbstest\glyphdata_config.ini
+data=DATAZ_\fbstest\fbstest_t_glyphdataoutlineshadow.script		\fbstest\fbstest_t_glyphdataoutlineshadow.script
 
 // Fbserv WDP Alloc stress test
 data=DATAZ_\fbstest\fbstest_T_WDP_Alloc_Stress.script				\fbstest\fbstest_T_WDP_Alloc_Stress.script
--- a/fbs/fontandbitmapserver/group/TFbsServer.mmp	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/group/TFbsServer.mmp	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2006-2010 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"
@@ -27,14 +27,15 @@
 
 CAPABILITY       All -Tcb -AllFiles
 
-userinclude		../../../graphicstest/graphicstestharness/inc
-userinclude		../tfbs ../sfbs ../inc 
+userinclude		../tfbs 
+userinclude		../sfbs 
+userinclude		../inc 
 userinclude		../trasterizer/src
+userinclude		../traces
 
 OS_LAYER_SYSTEMINCLUDE_SYMBIAN
 OS_LAYER_ESTLIB_SYSTEMINCLUDE
 
-SOURCEPATH  .
 SOURCEPATH  ../tfbs
 SOURCE		TFbsServer.cpp
 SOURCE		TALLOC.CPP
@@ -56,12 +57,19 @@
 SOURCE 		textendedbitmappanic.cpp
 SOURCE 		twdp.cpp
 SOURCE		tfonttableandglyph.cpp
+SOURCE  	tfbsglyphdata.cpp
+SOURCE 		tfbsglyphdatapanic.cpp 
+SOURCE 		tfbsglyphdataoutlineshadow.cpp
+SOURCE  	tglyphatlas.cpp
+SOURCE		tfbsoogm.cpp
+SOURCE  	glyphatlastestwrapper.cpp
 
 
 SOURCEPATH		../sfbs
 SOURCE			FbsRalc.cpp
 SOURCE			FBSMBMC.CPP
 SOURCE			ShiftedFileStore.cpp
+SOURCE			glyphatlas.cpp
 
 
 LIBRARY			euser.lib
@@ -78,6 +86,9 @@
 LIBRARY	    	testexecutelogclient.lib
 library			lookuptable.lib
 LIBRARY			hal.lib
+LIBRARY			sgresource.lib
+LIBRARY			libEGL.lib
+LIBRARY			libOpenVG.lib
 
 #if defined(WINS)
 LIBRARY			fontinjector.lib
@@ -87,3 +98,5 @@
 EPOCSTACKSIZE	0xf000
 
 SMPSAFE
+
+
--- a/fbs/fontandbitmapserver/group/bld.inf	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/group/bld.inf	Fri Sep 24 16:14:28 2010 +0300
@@ -34,13 +34,18 @@
 ../inc/fbsrasterizerclearcache.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(graphics/fbsrasterizerclearcache.h)
 ../inc/bitmapuid.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(graphics/bitmapuid.h)
 ../inc/fbsdefs.h    SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(graphics/fbsdefs.h)
+../sfbs/fbsglyphdataiterator.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(graphics/fbsglyphdataiterator.h)
+../sfbs/fbsglyphmetricsarray.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(graphics/fbsglyphmetricsarray.h)
+../sfbs/fbsoogmmessage.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(graphics/fbsoogmmessage.h)
+../sfbs/fbsoogmmessage.inl SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(graphics/fbsoogmmessage.inl)
+
 
 ../bwins/fbsrasterizeru.def /epoc32/include/graphics/def/bwins/fbsrasterizeru.def
 ../eabi/fbsrasterizeru.def /epoc32/include/graphics/def/eabi/fbsrasterizeru.def
 
 ../group/fbserv.iby        	/epoc32/rom/include/fbserv.iby
 ../group/fbsrasterizer_stub.iby	/epoc32/rom/include/fbsrasterizer_stub.iby
-
+../group/fbsoogmplugin.iby	/epoc32/rom/include/fbsoogmplugin.iby
 
 PRJ_MMPFILES
 
@@ -48,6 +53,7 @@
 ../group/FBSERV.MMP
 ../group/fbsrasterizerlib.mmp
 ../group/stubrasterizer.mmp
+//../group/fbsoogmplugin.mmp
 
 PRJ_TESTEXPORTS
 
@@ -84,6 +90,11 @@
 ../tfbs/scripts/fbstest_T_WDP_page_bitmap_data_and_shared_heap_only.script	z:/fbstest/fbstest_t_wdp_page_bitmap_data_and_shared_heap_only.script
 ../tfbs/scripts/extendedbitmap_config.ini						z:/fbstest/extendedbitmap_config.ini
 ../tfbs/scripts/wdptest_config.ini								z:/fbstest/wdptest_config.ini
+../tfbs/scripts/fbstest_t_glyphdata.script						z:/fbstest/fbstest_t_glyphdata.script
+../tfbs/scripts/glyphdata_config.ini						z:/fbstest/glyphdata_config.ini
+../tfbs/scripts/fbstest_t_glyphdataoutlineshadow.script				z:/fbstest/fbstest_t_glyphdataoutlineshadow.script
+../tfbs/scripts/fbstest_t_oogm.script						z:/fbstest/fbstest_t_oogm.script
+
 
 // Fbserv WDP Alloc stress test
 ../tfbs/scripts/fbstest_T_WDP_Alloc_Stress.script			z:/fbstest/fbstest_t_wdp_alloc_stress.script
--- a/fbs/fontandbitmapserver/group/fbserv.iby	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/group/fbserv.iby	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1998-2010 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"
@@ -47,8 +47,8 @@
 		#define FBSERV_PAGEDDATA_CONFIG unpageddata
 	#endif
 
-	file=ABI_DIR\BUILD_DIR\fbserv_fmm.exe 	\sys\bin\fbserv.exe	FBSERV_PAGEDDATA_CONFIG
-	file=ABI_DIR\BUILD_DIR\fbscli_fmm.dll 	\sys\bin\fbscli.dll
+	file=ABI_DIR\BUILD_DIR\fbserv.exe 	\sys\bin\fbserv.exe	FBSERV_PAGEDDATA_CONFIG
+	file=ABI_DIR\BUILD_DIR\fbscli.dll 	\sys\bin\fbscli.dll
 #else
 	file=ABI_DIR\DEBUG_DIR\fbserv.exe 	sys\bin\fbserv.exe
 	file=ABI_DIR\DEBUG_DIR\fbscli.dll 	sys\bin\fbscli.dll
@@ -58,4 +58,6 @@
 #include <graphics_adaptation.hby>
 #include FBSRASTERIZER_DRV
 
+//#include <fbsoogmplugin.iby>
+
 #endif //__FBSERV_IBY__
--- a/fbs/fontandbitmapserver/group/fbservtest_helium.pkg	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/group/fbservtest_helium.pkg	Fri Sep 24 16:14:28 2010 +0300
@@ -49,4 +49,7 @@
 "\epoc32\data\z\fbstest\ipctest_config.ini"-"c:\fbstest\ipctest_config.ini"
 "\epoc32\data\z\fbstest\fbstest_t_extendedbitmap.script"-"c:\fbstest\fbstest_t_extendedbitmap.script"
 "\epoc32\data\z\fbstest\extendedbitmap_config.ini"-"c:\fbstest\extendedbitmap_config.ini"
+"\epoc32\data\z\fbstest\fbstest_t_glyphdata.script"-"c:\fbstest\fbstest_t_glyphdata.script"
+"\epoc32\data\z\fbstest\glyphdata_config.ini"-"c:\fbstest\glyphdata_config.ini"
+"\epoc32\data\z\fbstest\fbstest_t_glyphdataoutlineshadow.script"-"c:\fbstest\fbstest_t_glyphdataoutlineshadow.script"
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/group/fbsoogmplugin.iby	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,23 @@
+/*
+* Copyright (c) 2010 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: 
+*
+*/
+
+#ifndef __FBSOOGMPLUGIN_IBY__
+#define __FBSOOGMPLUGIN_IBY__
+
+ECOM_PLUGIN(fbsoogmplugin.dll, fbsoogmplugin.rsc)
+
+#endif // __FBSOOGMPLUGIN_IBY__
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/group/fbsoogmplugin.mmp	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2010 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 is the .mmp for building font and bitmap server  out-of-graphics-memory Plugin
+*/
+
+
+
+#include <data_caging_paths.hrh>
+#include <platform_paths.hrh>
+
+
+TARGET      		fbsoogmplugin.dll
+TARGETTYPE 		PLUGIN
+UID			0x10009d8d 0x2002B638
+
+CAPABILITY  		CAP_ECOM_PLUGIN 
+VENDORID    		0x70000001
+
+// This is a SYSTEMINCLUDE macro containing the middleware
+// layer specific include directories
+MW_LAYER_SYSTEMINCLUDE
+
+USERINCLUDE		.
+USERINCLUDE		../inc
+USERINCLUDE		../sfbs 
+USERINCLUDE		../traces
+
+TARGETPATH		 /sys/bin  
+SOURCEPATH		../sfbs
+
+SOURCE			fbsoogmplugin.cpp
+
+START RESOURCE		fbsoogmplugin.rss
+TARGET			fbsoogmplugin.rsc
+END
+
+LIBRARY			ecom.lib
+LIBRARY			euser.lib
+LIBRARY			goommonitor.lib
+LIBRARY			fbscli.lib
+
--- a/fbs/fontandbitmapserver/inc/FBS.H	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/inc/FBS.H	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1995-2010 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"
@@ -40,6 +40,15 @@
 */
 #define SYMBIAN_FBSERV_V2
 
+/**
+Indicates version of FBS that provides the CFbsFont extension 
+interfaces RFbsGlyphDataIterator for using hardware glyphs, and
+RFbsGlyphMetricsArray.
+@publishedAll
+@prototype
+*/
+//#define SYMBIAN_FBSERV_GLYPHDATA
+
 /** 
 Character width and adjustment information. 
 @publishedAll
@@ -61,6 +70,8 @@
 class CFbsRalCache;
 class CFbsSessionHelper;
 class CFbsRasterizer;
+class TGlyphCacheMetrics;
+class TFbsOogmMessage;
 
 /** 
 A session with the font and bitmap server. 
@@ -101,6 +112,9 @@
 	HBufC8* GetDecompressionBuffer(TInt aSize);
 	HBufC8* GetExtraBuffer(TInt aSize);
     TInt ServerSessionHandle() const;
+    IMPORT_C TInt GetGlyphCacheMetrics(TGlyphCacheMetrics& aGlyphCacheMetrics);
+    IMPORT_C TInt ConveyOogmMessage( TFbsOogmMessage& aOogmMessage );
+
 public:
 	/** WARNING: For internal use ONLY.  Compatibility is not guaranteed in future releases.	 
 	Used for testing server side out of memory failures.	
@@ -149,6 +163,8 @@
 class CFbsFont: public CFont
 	{
 	friend class CFbsTypefaceStore;
+	friend class RFbsGlyphDataIterator;
+	friend class RFbsGlyphMetricsArray;
 
 private:
 	// From CFont
@@ -208,7 +224,7 @@
 	RFbsSession* iFbs;
 	CBitmapFont* iAddressPointer;
 	TInt iHandle;
-	TInt iServerHandle;
+    TInt iServerHandle;
 	};
 
 /**
@@ -505,4 +521,22 @@
 	CDitherColor256* iDither;
 	};
 
-#endif
+
+/**
+ A class encapsulating the current state of the glyph cache.
+
+ @publishedAll
+ @released
+*/
+class TGlyphCacheMetrics
+    {
+public:
+    TInt iMaxCacheSizeInBytes;
+    TInt iMaxCacheSizeHigh;
+    TInt iMaxCacheSizeLow;
+    TInt iCacheSizeInBytes;
+    TBool iGpuCacheSizeLimitIsMax;
+    };
+
+#endif // __FBS_H__
+
--- a/fbs/fontandbitmapserver/inc/FbsMessage.H	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/inc/FbsMessage.H	Fri Sep 24 16:14:28 2010 +0300
@@ -74,7 +74,7 @@
 	EFbsMessSetHeapReset, //for memory testing only
 	EFbsMessSetHeapCheck, //for memory testing only
 	EFbsMessHeap, //for memory testing only
-	EFbsMessUnused2, //to put a character in the linked fonts cache
+	EFbsMessUnused2, //Implementation removed
 	EFbsMessBitmapClean, // replace a dirty bitmap with the clean one
 	EFbsMessBitmapLoadFast, // for loading bitmap from mbm or rsc file not opened by the client
 	EFbsMessBitmapNotifyDirty, // notify when any bitmap becomes dirty
@@ -87,6 +87,13 @@
 	EFbsMessReleaseFontTable,
 	EFbsMessGetGlyphOutline,
 	EFbsMessReleaseGlyphOutline,
+	EFbsMessGetGlyphs, // Retrieve rasterised glyphs from glyph atlas and closes last glyph retrieved
+	EFbsMessNoOp, // No-op call; used to ensure that the RSgImage of the last glyph retrieved from glyph atlas has been closed
+	EFbsMessGetGlyphMetrics, // Retrieve metrics of multiple glyph codes in one message
+	EFbsMessAtlasFontCount, // (Debug-only) Retrieve the number of fonts with glyphs in the H/W Glyph cache
+	EFbsMessAtlasGlyphCount, // (Debug-only) Retrieve the number of glyphs (optionally, given a specific font) stored in the H/W Glyph cache
+	EFbsMessOogmNotification, // An action requested by the GOoM framework. Reduce or re-instate graphics memory usage.
+	EFbsMessGetGlyphCacheMetrics, // Retrieve the glyph-cache size, its maximum limit and whether the maximum is the reduced value used in OoGm situations.
 	// If you are adding new messages don't forget to check that the 
 	// security permissions are set correctly (KRanges & KElementsIndex in server.cpp)
 	};
--- a/fbs/fontandbitmapserver/sfbs/FBSCLI.CPP	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/sfbs/FBSCLI.CPP	Fri Sep 24 16:14:28 2010 +0300
@@ -16,11 +16,20 @@
 #include <fntstore.h>
 #include <bitmap.h>
 #include <openfont.h>
+#include <graphics/fbsoogmmessage.h>
 #include "FbsMessage.H"
 #include "SERVER.H"
 #include "BackGroundCompression.h"
 #include <shapeinfo.h>
 #include <graphics/shaperparams.h>
+#include "glyphatlas.h"
+
+
+/**
+Bitwise mask that sets the MSB to indicate to a font rasterizer
+that a code is a glyphcode and not a character code
+*/
+const TUint32 KTreatAsGlyphCodeFlag = 1UL << 31;
 
 /** Helper function for converting a pointer to an offset from the passed
 heap base. Use OffsetToPointer() to convert the returned offset back to a
@@ -33,11 +42,12 @@
  */
 LOCAL_C TInt PointerToOffset(const TAny* aAny, TInt aHeapBase)
 	{
+	TInt offset = 0;
 	if (aAny && aHeapBase)
 		{
-		return reinterpret_cast<TInt>(aAny) - aHeapBase;
+		offset = reinterpret_cast<TInt>(aAny) - aHeapBase;
 		}
-	return 0;
+	return offset;
 	}
 
 /** Helper function for converting an offset (that was calculated using
@@ -58,9 +68,6 @@
 
 CFbClient::CFbClient(RHeap* aHeap):
 	CSession2(),
-	iConnectionHandle(0),
-	iIx(NULL),
-	iResourceCount(0),
 	iHeap(aHeap)
 #ifdef _DEBUG
 	,iOwnHeapFailNumber(-1),
@@ -71,14 +78,24 @@
 
 CFbClient* CFbClient::NewL(RHeap* aHeap)
 	{
-	CFbClient* c = new(ELeave) CFbClient(aHeap);
-	c->iOpenFontGlyphData = TOpenFontGlyphData::New(aHeap,4 * 1024);
-	if (!c->iOpenFontGlyphData)
+	CFbClient* self = new (ELeave) CFbClient(aHeap);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(); // self;
+	return self;
+	}
+
+/**
+Two-phase constructor.
+@leave KErrNoMemory if TOpenFontGlyphData construction failed.
+*/
+void CFbClient::ConstructL()
+	{
+	iOpenFontGlyphData = TOpenFontGlyphData::New(iHeap, 4 * 1024);
+	if (!iOpenFontGlyphData)
 		{
-		delete c;
 		User::Leave(KErrNoMemory);
 		}
-	return c;
 	}
 
 CFbClient::~CFbClient()
@@ -103,24 +120,32 @@
 		iHeap->Free(iOpenFontGlyphData);
 		}
 	
-	// delete fonts hold by the client
+	// delete fonts held by the client
 	delete iIx;
 	
-	// delete font files hold by the client
+	// delete font files held by the client
 	if (iFontFileIndex)
 		{
 		TInt count = iFontFileIndex->Count();
 		for (TInt index = 0;index < count; index++)
 			{
 			if (font_store)
+				{
 				font_store->RemoveFile(iFontFileIndex->At(0).iUid);
+				}
 			iFontFileIndex->Delete(0);
 			}
 		delete iFontFileIndex;
 		}
 
-	// Close the buffer used to hold the text thats needs shaping.
+	// Close the buffer used to hold the text that needs shaping.
 	iTextToShape.Close();
+
+	for (TInt i = iGlyphImagesInTransit.Count() - 1; i >= 0; --i)
+		{
+		iGlyphImagesInTransit[i].Close();
+		}
+	iGlyphImagesInTransit.Close();
 	}
 
 void CFbClient::Init(TUint aConnectionHandle)
@@ -143,9 +168,13 @@
 	{
 	CFontBitmapServer* server = FontBitmapServer();
 	if (server)
+		{
 		return server->TopLevelStore();
+		}
 	else
+		{
 		return NULL;
+		}
 	}
 
 void CFbClient::CopyFontInfo(CFontObject* aFontObjPtr,TInt aHandle,TFontInfo& aFontInfo)
@@ -158,6 +187,7 @@
 
 void CFbClient::ServiceL(const RMessage2& aMessage)
 	{
+
 #ifdef _DEBUG
 	TBool resetOwnHeap=EFalse;
 	TBool resetSharedHeap=EFalse;
@@ -189,6 +219,14 @@
 		__RHEAP_MARK(iHeap);
 		}		
 #endif		
+	//Call close on RSgImage handles being used to share glyph data with clients.
+	//The glyph images are held open to prevent the GlyphAtlas from closing them
+	//before a client can use them.
+	for (TInt i = iGlyphImagesInTransit.Count() - 1; i >= 0; --i)
+		{
+		iGlyphImagesInTransit[i].Close();
+		iGlyphImagesInTransit.Remove(i);
+		}
 	
 	switch(aMessage.Function())
 		{
@@ -246,6 +284,7 @@
 	case EFbsMessFetchLinkedTypeface:
 	case EFbsMessRegisterLinkedTypeface:
 	case EFbsMessUpdateLinkedTypeface:
+
 #ifdef _DEBUG
 		FontBitmapServer()->ProcMessage(aMessage,iSessionHandle,iRet);
 #else
@@ -277,6 +316,8 @@
 #if (_DEBUG)
 	case EFbsMessSetDuplicateFail:
 #endif
+	case EFbsMessGetGlyphs:
+	case EFbsMessGetGlyphMetrics:
 		ProcFontMessage(aMessage);
 		break;
 // bitmap messages
@@ -305,6 +346,31 @@
 		aMessage.Complete(KErrNone);
 #endif	
 		break;
+// Glyph Atlas messages (debug-only)
+	case EFbsMessAtlasFontCount:
+	case EFbsMessAtlasGlyphCount:
+#ifdef _DEBUG
+		ProcAtlasMessage(aMessage);
+#else
+		aMessage.Complete(KErrNotSupported);
+#endif
+		break;
+    case EFbsMessOogmNotification:
+
+        aMessage.Complete( HandleMesgOogmStatus( aMessage ) );
+        break;
+    case EFbsMessGetGlyphCacheMetrics:
+
+        HandleMesgGlyphCacheMetrics( aMessage );
+        break;
+
+//No-op message
+	case EFbsMessNoOp:
+#ifdef _DEBUG
+		iRet = KErrNone;
+#endif
+		aMessage.Complete(KErrNone);
+		break;
 	default:
 		aMessage.Panic(KFBSERVPanicCategory,KErrArgument);
 		break;
@@ -372,7 +438,9 @@
 	{
 #if _DEBUG
 	if (iFontDuplicateToFail)
+		{
 		return KErrNoMemory; //return with this error since this error is possible
+		}
 #endif
 	CFontObject* fontptr = (CFontObject*) aMessage.Int0();
 	if(!TopLevelStore()->ValidFontHandle((TInt)fontptr))
@@ -380,7 +448,7 @@
 		return KErrUnknown;
 		}
 
-	TPckgBuf<TFontInfo> foninfo;
+	TPckgBuf<TFontInfo> fontinfo;
 	TInt localhandle = 0;
 	TInt ret = fontptr->Open();
 	if (ret != KErrNone)
@@ -393,9 +461,9 @@
 		fontptr->Close();
 		return ret;
 		}
-	CopyFontInfo(fontptr,localhandle,foninfo());
+	CopyFontInfo(fontptr,localhandle,fontinfo());
 	fontptr->iHeightInTwips = ((fontptr->iAddressPointer->HeightInPixels() * fontptr->iFontStore->iKPixelHeightInTwips) + 667) / 1000;
-	ret = aMessage.Write(1, foninfo);
+	ret = aMessage.Write(1, fontinfo);
 	if(ret != KErrNone)
 		{
 		iIx->Remove(localhandle);
@@ -422,14 +490,14 @@
 	TInt pckgMaxHeight;
 	TPckgBuf<TSizeInfo> info;
 
-	const TFbsMessage	fbsMessage = static_cast<TFbsMessage>(aMessage.Function());
+	const TFbsMessage fbsMessage = static_cast<TFbsMessage>(aMessage.Function());
 
 	TInt ret = aMessage.Read(0, pckgFontSpec);
 	TFontSpec& fontSpec = pckgFontSpec();
 	if (ret == KErrNone )
 		{
 		TInt length = fontSpec.iTypeface.iName.Length();
-		if(length < 0 || length > TOpenFontFaceAttribBase::ENameLength)
+		if((length < 0) || (length > TOpenFontFaceAttribBase::ENameLength))
 			{
 			aPanicRequired = ETrue;
 			return KErrArgument;
@@ -644,6 +712,183 @@
 	return EFalse;
 	}
 
+/** Handler for EFbsMessGetGlyphs message.
+Reads a batch of up to KMaxGlyphBatchSize glyph codes, and on success returns
+the corresponding TGlyphImageInfo objects.
+ @param aMessage input parameters
+ @param aPanicRequired flag that is set if a client panic is required
+ @return KErrNone if successful, otherwise any system-wide error code.
+ */
+TInt CFbClient::HandleMesgGetGlyphs(const RMessage2& aMessage, TBool& aPanicRequired)
+	{
+	CFbTop* fbtop = TopLevelStore();
+	// Previously requested glyphs were closed in ServiceL()
+	CGlyphAtlas* glyphAtlas = fbtop->GlyphAtlas();
+	if (!glyphAtlas)
+		{
+		return KErrNotSupported;
+		}
+	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID()));
+	if(!fontptr)
+		{
+		aPanicRequired = ETrue;
+		return KErrBadHandle;
+		}
+
+	TUint glyphCodes[KMaxGlyphBatchSize];
+	TGlyphImageInfo glyphImageInfo[KMaxGlyphBatchSize];
+	TPckg<TUint[KMaxGlyphBatchSize]> glyphBatchPckg(glyphCodes);
+
+	TInt err = aMessage.Read(1, glyphBatchPckg);
+	if (err != KErrNone)
+		{
+		aPanicRequired = ETrue;
+		return err;
+		}
+	TInt glyphCodesCount = glyphBatchPckg.Length() / sizeof(TUint);
+	if (glyphCodesCount > KMaxGlyphBatchSize)
+		{
+		aPanicRequired = ETrue;
+		return KErrOverflow;
+		}
+
+	TInt glyphsProcessed = 0;
+	CBitmapFont* font = fontptr->iAddressPointer;
+	for (; (glyphsProcessed < glyphCodesCount); ++glyphsProcessed)
+		{
+		TUint32 glyphCode = glyphCodes[glyphsProcessed];
+		err = glyphAtlas->GetGlyph(*font, glyphCode, glyphImageInfo[glyphsProcessed]);
+		// Search for glyph in glyph atlas
+		if (KErrNone != err)
+			{
+			const TUint8* bitmapData = NULL;
+			TOpenFontCharMetrics metrics;
+			// search for glyph in font glyph cache and session cache.
+			if (!font->GetCharacterData(iSessionHandle, glyphCode | KTreatAsGlyphCodeFlag, metrics, bitmapData))
+				{
+				// Rasterize the glyph
+				if(!font->Rasterize(iSessionHandle, glyphCode | KTreatAsGlyphCodeFlag, iOpenFontGlyphData))
+					{
+					err = KErrNoMemory;
+					break;
+					}
+				metrics = *(iOpenFontGlyphData->Metrics());
+				bitmapData = iOpenFontGlyphData->BitmapPointer();
+				}
+			CGlyphAtlas::TAddGlyphArgs args(bitmapData, glyphCode, metrics);
+			err = glyphAtlas->AddGlyph(*font, args, glyphImageInfo[glyphsProcessed]);
+			}
+		if ((err == KErrNone) && (glyphImageInfo[glyphsProcessed].iImageId != KSgNullDrawableId))
+			{
+			// To prevent other threads closing the glyph image in the glyph atlas 
+			// before client has had chance to open the drawable id, open a local
+			// handle to the glyph image for the session, which will be closed either
+			// next time a request is made or when EFbsMessCloseGlyphs is handled.
+			RSgImage glyphImage;
+			err = glyphImage.Open(glyphImageInfo[glyphsProcessed].iImageId);
+			if (err == KErrNone)
+				{
+				err = iGlyphImagesInTransit.Append(glyphImage);
+				}
+			}
+		// If an error occurred during this iteration, abort now before the glyphsProcessed
+		// counter is incremented, which would give one too many processed glyphs.
+		if (KErrNone != err)
+			{
+			break;
+			}
+		}
+
+	// Even if there was an error, if at least one glyph was processed successfully
+	// send that back to the client, and reset the error code.
+	if (glyphsProcessed > 0)
+		{
+		TPckg<TGlyphImageInfo[KMaxGlyphBatchSize]> glyphImageInfoPckg(glyphImageInfo);
+		glyphImageInfoPckg.SetLength(glyphsProcessed * sizeof(TGlyphImageInfo));
+		err = aMessage.Write(2, glyphImageInfoPckg);
+		if (err != KErrNone)
+			{
+			aPanicRequired = ETrue;
+			return err;
+			}
+		}
+	else
+		{
+		// No glyphs being returned, so an error code must be returned.
+		__ASSERT_DEBUG(err != KErrNone, User::Panic(KFBSERVPanicCategory, err));
+		}
+	return err;
+	}
+
+/**
+Handler for EFbsMessGetGlyphMetrics message.
+Reads an array of glyph codes, and returns the offset from the heap base for the 
+corresponding metrics object.
+@pre The glyph codes have already been searched client-side in the font glyph
+	cache and the session cache.
+@param aMessage input parameters
+@param aPanicRequired flag that is set if a client panic is required
+@return KErrNone if successful, otherwise any system-wide error code.
+ */
+TInt CFbClient::HandleMesgGetGlyphMetrics(const RMessage2& aMessage, TBool& aPanicRequired)
+	{
+	CFbTop* fbtop = TopLevelStore();
+	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID()));
+	if(!fontptr)
+		{
+		aPanicRequired = ETrue;
+		return KErrBadHandle;
+		}
+	
+	TInt err = KErrNone;
+	TUint glyphCodes[KMaxMetricsBatchSize];
+	TPckg<TUint[KMaxMetricsBatchSize]> glyphBatchPckg(glyphCodes);
+	err = aMessage.Read(1, glyphBatchPckg);
+	if (err != KErrNone)
+		{
+		aPanicRequired = ETrue;
+		return err;
+		}
+	
+	TInt numGlyphCodes = glyphBatchPckg.Length() / sizeof(TUint);	
+	if (numGlyphCodes > KMaxMetricsBatchSize)
+		{
+		aPanicRequired = ETrue;
+		return KErrOverflow;
+		}
+	
+	CBitmapFont* font = fontptr->iAddressPointer;
+	const TInt heapbase = fbtop->HeapBase();
+
+	TInt glyphProcessed;
+	TInt glyphMetricsOffsets[KMaxMetricsBatchSize];
+	for (glyphProcessed = 0; (glyphProcessed < numGlyphCodes) && (err == KErrNone); ++glyphProcessed)
+		{
+		if (font->Rasterize(iSessionHandle, glyphCodes[glyphProcessed] | KTreatAsGlyphCodeFlag, iOpenFontGlyphData))
+			{
+			// Convert all pointers to be passed back to the client to offsets from
+			// the heap base so that they can be recreated client side relative to the
+			// client's heap base
+			glyphMetricsOffsets[glyphProcessed] = PointerToOffset(iOpenFontGlyphData->Metrics(), heapbase);
+			}
+		else
+			{
+			err = KErrNoMemory;
+			}
+		}
+
+	if (err == KErrNone)
+		{
+		TPckg<TInt[KMaxMetricsBatchSize]> glyphMetricsOffsetsPckg(glyphMetricsOffsets);
+		glyphMetricsOffsetsPckg.SetLength(glyphProcessed * sizeof(TInt));
+		err = aMessage.Write(2, glyphMetricsOffsetsPckg);
+		if (err != KErrNone)
+			{
+			aPanicRequired = ETrue;
+			}
+		}	
+	return err;
+	}
 
 /** Handler for EFbsMessFaceAttrib message
  @param aMessage Input and output parameters
@@ -661,21 +906,21 @@
 		}
 	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
 
+	TInt ret = EFalse;
 	TPckgBuf<TOpenFontFaceAttrib> package;
 	if ( (bitmapFont != NULL) && (bitmapFont->GetFaceAttrib(package())) )
 		{
-		TInt ret = aMessage.Write(1,package);
+		ret = aMessage.Write(1,package);
 		if (ret == KErrNone)
 			{
-			return ETrue;
+			ret = ETrue;
 			}
 		else
 			{
 			aPanicRequired = ETrue;
-			return ret;
 			}
 		}
-	return EFalse;
+	return ret;
 	}
 
 
@@ -717,7 +962,6 @@
 	{
 	TInt error = KErrNone;
 	TShapeHeader* shape = 0;
-	TPckgBuf<TShapeMessageParameters> sp;
 	if (aMessage.GetDesLength(2) != sizeof(TShapeMessageParameters))
 		{
 		aPanicRequired = ETrue;
@@ -731,7 +975,6 @@
 		aPanicRequired = ETrue;
 		return KErrArgument;
 		}
-	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
 
 	TInt inputTextLength = aMessage.GetDesLength(1);
 	if (inputTextLength < 0)
@@ -744,7 +987,9 @@
 		{
 		iTextToShape.Zero();
 		if (iTextToShape.MaxLength() < inputTextLength)
+			{
 			error = iTextToShape.ReAlloc(inputTextLength);
+			}
 		}
 	if (error == KErrNone)
 		{
@@ -754,12 +999,14 @@
 			aPanicRequired = ETrue;
 			return error;
 			}
+		TPckgBuf<TShapeMessageParameters> sp;
 		error = aMessage.Read(2, sp);
 		if (error != KErrNone)
 			{
 			aPanicRequired = ETrue;
 			return error;
 			}
+		CBitmapFont* bitmapFont = fontptr->iAddressPointer;
 		TRAP(error, shape = bitmapFont->ShapeTextL(iTextToShape, iSessionHandle, sp()) );
 		if (error == KErrNone)
 			{
@@ -953,9 +1200,70 @@
 	return ret;
 	}
 
+
+/**
+ Called in response to the GoomMonitor framework's call into FbsOogmPlugin.
+ We wish to either free some GPU memory, or reinstate its normal usage.
+
+@param  aMessage The IPC message.
+@return KErrNone If the value contained in the TFbsOogmMessage enumeration member is meaningful and the glyph atlas is present.
+        KErrNotSupported if there is no glyph atlas.
+        KErrUnknown if the value contained in the TFbsOogmMessage enumeration member is not meaningful.
+ */
+TInt CFbClient::HandleMesgOogmStatus( const RMessage2& aMessage )
+    {
+    TInt ret = KErrNone;
+    CGlyphAtlas* glyphAtlas = TopLevelStore()->GlyphAtlas();
+
+    if ( NULL == glyphAtlas )
+        {
+        return KErrNotSupported;
+        }
+
+
+    TPckgBuf<TFbsOogmMessage> oogmMessage;
+    aMessage.Read( 0, oogmMessage );
+
+    switch( oogmMessage().iOogmNotification )
+        {
+    case TFbsOogmMessage::EFbsOogmNoAction:
+        break;
+
+    case TFbsOogmMessage::EFbsOogmLowNotification:
+        {
+        glyphAtlas->ReleaseGpuMemory( oogmMessage().iBytesToFree, oogmMessage().iFlags );
+        }
+         break;
+
+    case TFbsOogmMessage::EFbsOogmOkayNotification:
+        {
+        glyphAtlas->InstateGpuMemory( oogmMessage().iFlags );
+        }
+        break;
+
+    default:
+        ret = KErrUnknown;
+        break;
+        }
+
+    return ret;
+    }
+
+
+void CFbClient::HandleMesgGlyphCacheMetrics( const RMessage2& aMessage )
+    {
+    CGlyphAtlas* glyphAtlas = TopLevelStore()->GlyphAtlas();
+    TPckgBuf<TGlyphCacheMetrics>  metrics;
+
+    glyphAtlas->GetGlyphCacheMetrics( metrics() );
+
+    aMessage.Complete( aMessage.Write(0, metrics) );
+    }
+
+
 void CFbClient::ProcFontMessage(const RMessage2& aMessage)
 	{
-	TInt ret = KErrUnknown;
+	TInt ret = KErrNone;
 	TBool panicRequired = EFalse;
 
 	switch(aMessage.Function())
@@ -1082,9 +1390,20 @@
 			ret = HandleMesgReleaseFontTable(aMessage, panicRequired);
 			break;
 			}
+		case EFbsMessGetGlyphs:
+			{
+			ret = HandleMesgGetGlyphs(aMessage, panicRequired);
+			break;
+			}
+		case EFbsMessGetGlyphMetrics:
+			{
+			ret = HandleMesgGetGlyphMetrics(aMessage, panicRequired);
+			break;
+			}
 
 #ifdef _DEBUG
 		case EFbsMessSetDuplicateFail:
+			{
 			TInt argument =aMessage.Int0();
 			if (argument)
 				{
@@ -1096,7 +1415,10 @@
 				}
 			ret=KErrNone;
 			break;
+			}
 #endif
+		default:
+			ret = KErrUnknown;
 		}
 
 	// either have a result or an error code to panic the client with
@@ -1120,7 +1442,7 @@
 	{
 	CBitmapObject* bmpptr=NULL;
 	TInt localhandle=0;
-	TInt ret=KErrUnknown;
+	TInt ret = KErrNone;
 	switch(aMessage.Function())
 		{
 	case EFbsMessBitmapCreate:
@@ -1283,14 +1605,18 @@
 			}
 		ret = fbtop->GetCleanBitmap(bmpptr);
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		TSize newsize(aMessage.Int1(),aMessage.Int2());
  		const TBool compressedInRam = bmpptr->Address()->IsCompressedInRAM();  //It must be set before the resizing is done.
 		const TDisplayMode dispMode = bmpptr->Address()->DisplayMode();
 		CBitmapObject* newbmpptr = NULL;
 		TRAP(ret, newbmpptr = fbtop->CreateBitmapL(newsize, dispMode, KUidCFbsBitmapCreation, ETrue));
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		ret = newbmpptr->Address()->CopyData(*bmpptr->Address());
 		if (ret != KErrNone)
 			{
@@ -1325,7 +1651,9 @@
 			}
 		bmpptr->SetCleanBitmap(newbmpptr);
 		if (bmpptr->AccessCount() >= 2)
+			{
 			fbtop->NotifyDirtyBitmap(*bmpptr, this);
+			}
 		iIx->Remove(localhandle);
 		TPckgBuf<TBmpHandles> handlebuffer;
 		handlebuffer().iHandle = newlocalhandle;
@@ -1353,7 +1681,9 @@
 		TopLevelStore()->GetCleanBitmap(bmpptr);
 		ret = bmpptr->Open();
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		TPckgBuf<TBmpHandles> handlebuffer;
 		TRAP(ret,localhandle=iIx->AddL(bmpptr));
 		if(ret!=KErrNone)
@@ -1386,13 +1716,17 @@
 			}
 		ret = fbtop->GetCleanBitmap(bmpptr);
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		const TSize size = bmpptr->Address()->SizeInPixels();
 		const TDisplayMode dispMode = bmpptr->Address()->DisplayMode();
 		CBitmapObject* newbmpptr = NULL;
 		TRAP(ret, newbmpptr = fbtop->CreateBitmapL(size, dispMode, KUidCFbsBitmapCreation, ETrue));
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		ret = newbmpptr->Address()->CopyData(*bmpptr->Address());
 		if (ret != KErrNone)
 			{
@@ -1420,7 +1754,9 @@
 			}
 		bmpptr->SetCleanBitmap(newbmpptr);
 		if (bmpptr->AccessCount() >= 2)
+			{
 			fbtop->NotifyDirtyBitmap(*bmpptr, this);
+			}
 		iIx->Remove(localhandle);
 		TPckgBuf<TBmpHandles> handlebuffer;
 		handlebuffer().iHandle = newlocalhandle;
@@ -1451,7 +1787,9 @@
 		if (ret != KErrNone)
 			{
 			if (!async)
+				{
 				ret = KErrNone;
+				}
 			break;
 			}
 		ret = bmpptr->Address()->CheckBackgroundCompressData();
@@ -1459,10 +1797,14 @@
 			{
 			ret = fbtop->BackgroundCompression()->AddToCompressionQueue(bmpptr, scheme, async ? &aMessage : NULL);
 			if (ret == KErrNone && async)
+				{
 				return; // do not complete the client's request - that will be done by the background compression thread
+				}
 			}
 		if (KErrAlreadyExists == ret)
+			{
 			ret = KErrNone;
+			}
 		break;
 		}
 	case EFbsMessBitmapClean:
@@ -1477,10 +1819,14 @@
 			}
 		ret = fbtop->GetCleanBitmap(bmpptr);
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		ret = bmpptr->Open();
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		TInt cleanlocalhandle = 0;
 		TRAP(ret, cleanlocalhandle = iIx->AddL(bmpptr));
 		if (ret != KErrNone)
@@ -1530,17 +1876,19 @@
 			iHelper->iMessage = aMessage;
 			return; // do not complete the client's request yet - that will be done when a bitmap becomes dirty
 			}
-		ret = KErrNone;
 		iHelper->iDirty = EFalse;
 		}
 		break;
 	case EFbsMessBitmapCancelNotifyDirty:
 		{
 		if (iHelper != NULL && !iHelper->iMessage.IsNull())
+			{
 			iHelper->iMessage.Complete(KErrCancel);
-		ret = KErrNone;
+			}
 		}
 		break;
+	default:
+		ret = KErrUnknown;
 		}
 		
 	if(!aMessage.IsNull())
@@ -1616,7 +1964,9 @@
 	if (iHelper)
 		{
 		if (!iHelper->iMessage.IsNull())
+			{
 			iHelper->iMessage.Complete(KErrDisconnected);
+			}
 		iHelper->Deque();
 		delete iHelper;
 		iHelper = NULL;
@@ -1678,7 +2028,58 @@
 			break;
 		case EFbsMessHeap:
 			ret=(TInt)iHeap;
-			break;			
+			break;
+		default:
+			ret = KErrUnknown;
+		}
+	aMessage.Complete(ret);
+	iRet=ret;
+	}
+
+/**
+Processes messages associated with the Glyph Atlas.
+@param aMessage The message used to perform IPC to the client.
+ */
+void CFbClient::ProcAtlasMessage(const RMessage2 &aMessage)
+	{
+	TInt ret = KErrNone;
+	CFbTop* fbtop = TopLevelStore();
+	CGlyphAtlas* glyphAtlas = fbtop->GlyphAtlas();
+	if (!glyphAtlas)
+		{
+		ret = KErrNotSupported;
+		}
+	else
+		{
+		switch(aMessage.Function())
+			{
+			case EFbsMessAtlasFontCount:
+				ret = glyphAtlas->FontCount();
+				break;
+			case EFbsMessAtlasGlyphCount:
+				{
+				TInt fontHandle = aMessage.Int0();
+				if (fontHandle != 0)
+					{
+					if (fbtop->ValidFontHandle(fontHandle))
+						{
+						CFontObject* fontptr = reinterpret_cast<CFontObject*>(fontHandle);
+						ret = glyphAtlas->GlyphCount(static_cast<CBitmapFont&>(*(fontptr->iAddressPointer)));
+						}
+					else
+						{
+						ret = KErrNotFound;
+						}
+					}
+				else
+					{
+					ret = glyphAtlas->GlyphCount();
+					}
+				}
+				break;
+			default:
+				ret = KErrUnknown;
+			}
 		}
 	aMessage.Complete(ret);
 	iRet=ret;
--- a/fbs/fontandbitmapserver/sfbs/FBSFONT.CPP	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/sfbs/FBSFONT.CPP	Fri Sep 24 16:14:28 2010 +0300
@@ -85,7 +85,9 @@
 EXPORT_C void CFbsFont::Reset()
 	{
 	if (iHandle)
+	    {
 		iFbs->SendCommand(EFbsMessClose,iHandle);
+	    }
 	iHandle = 0;
 	}
 	
@@ -115,7 +117,7 @@
 	if (!aFontHandle)
 		return KErrUnknown;
 	// close any existing handle
-	Reset();
+	Reset();	
 	// ask server to create the duplicate handle
 	TPckgBuf<TFontInfo> tfpckg;
 	TIpcArgs args(aFontHandle,&tfpckg);
@@ -137,7 +139,9 @@
 EXPORT_C TInt CFbsFont::Handle() const
 	{
 	if (!iHandle)
+		{
 		return 0;
+		}
 	return iServerHandle;
 	}
 
@@ -727,6 +731,9 @@
 provide and/or return information to/from the particular extension function,
 defaults to NULL.
 @return Integer return value from extension function, a system wide error code.
+@panic FBSCLI 31, in debug builds only, if iExtra is NULL when it must not be.
+@panic FBSCLI 38, in debug builds only, if a reserved error code is returned 
+	from an extended function.
 @internalTechnology
 @released
 */
--- a/fbs/fontandbitmapserver/sfbs/FBSTOP.CPP	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/sfbs/FBSTOP.CPP	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1995-2010 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"
@@ -18,7 +18,6 @@
 #include <fntstore.h>
 #include <bitmap.h>
 #include <ecom/ecom.h>
-#include "FbsMessage.H"
 #include <graphics/bitmapuid.h>
 #include "SERVER.H"
 #include "BackGroundCompression.h"
@@ -27,6 +26,8 @@
 #include <graphics/openfontconstants.h>
 #include <graphics/openfontrasterizer.h>
 #include <graphics/gdi/glyphsample.h>
+#include "glyphatlas.h"
+#include "FbsMessage.H"
 
 // Local utility functions
 void ListImplementationsWithRetry(TUid& aInterfaceUid, RImplInfoPtrArray &aImplementationArray, TBool aRomOnly);
@@ -61,6 +62,7 @@
 #endif
 	iFontNameAlias.ResetAndDestroy();
 	iBitmapObjectIndex.Reset();
+	delete iGlyphAtlas;
 	REComSession::FinalClose();
 	}
 
@@ -140,9 +142,15 @@
 	iMBMCache=new (ELeave) CFbTopStreamIdCache(30,30,5);
 
 	LoadOpenFontLibraries();
-	
 	iFontStore->LoadFontsAtStartupL();
 	LoadShaperFactories();
+	TRAP_IGNORE(iGlyphAtlas = CGlyphAtlas::NewL(KFbServGlyphAtlasCacheLimit);)
+#ifdef _DEBUG
+	if (!iGlyphAtlas)
+	    {
+        RDebug::Printf("FBSERV failed to initialize Glyph Atlas");
+	    }
+#endif
 
 	// start a new thread for background compression after all the other objects have been created
 	iBackgroundCompression = CFbsBackgroundCompression::NewL(*this);
@@ -307,8 +315,8 @@
 		{
 		return ret;
 		}
-
-	return CreateFontObjectFromFont(aFontObjPtr, font);
+	
+	return GetFontObjectFromFont(aFontObjPtr, font);
 	}
 	
 /**
@@ -349,9 +357,27 @@
 	return ret;
 	}
 
-TInt CFbTop::CreateFontObjectFromFont(CFontObject*& aFontObjPtr, CFont* aFont)
+TInt CFbTop::GetFontObjectFromFont(CFontObject*& aFontObjPtr, CFont* aFont)
 	{
-	CFontObject* fontObjPtr = new CFontObject(iFontStore);
+	// First, check if a CFontObject exists for this CFont.
+	// If so, increment its reference count and return it.
+	for (TInt ii = iFontCon->Count() - 1; ii >= 0; --ii)
+		{
+		CFontObject* fontObjPtr = reinterpret_cast<CFontObject*>((*iFontCon)[ii]);
+		if (fontObjPtr->iAddressPointer == reinterpret_cast<CBitmapFont*>(aFont))
+			{
+			aFontObjPtr = fontObjPtr;
+			// The CFontObject instance keeps the reference count of the CBitmapFont, 
+			// not the font store. There is only one CFontObject instance
+			// per CBitmapFont, so to keep the reference count at 1 in the fontstore
+			// call ReleaseFont(). 
+			iFontStore->ReleaseFont(aFont);
+			return fontObjPtr->Open();
+			}
+		}
+	
+	// Existing FontObject not found, so create new one.
+	CFontObject* fontObjPtr = new CFontObject(iFontStore, iGlyphAtlas);
 	if (!fontObjPtr)
 		{
 		iFontStore->ReleaseFont(aFont);
@@ -389,7 +415,7 @@
 		{
 		return ret;
 		}
-	return CreateFontObjectFromFont(aFontObjPtr, font);
+	return GetFontObjectFromFont(aFontObjPtr, font);
 	}
 
 
@@ -561,18 +587,6 @@
 	return(EFalse);
 	}
 	
-TBool CFbTop::ValidBitmapFont(TInt aHandle)
-	{
-	TInt limit=iFontCon->Count();
-	for(TInt count=0;count<limit;count++)
-		{
-		CFontObject* fontObjPtr = reinterpret_cast<CFontObject*>((*iFontCon)[count]);
-		if(aHandle==(TInt)(fontObjPtr->iAddressPointer))
-			return(ETrue);
-		}
-	return(EFalse);
-	}
-
 CFontStore* CFbTop::FontStore() const
 	{
 	return(iFontStore);
@@ -724,3 +738,8 @@
 	{
 	return iFontCon->UniqueID();
 	}
+
+CGlyphAtlas* CFbTop::GlyphAtlas() const
+	{
+	return iGlyphAtlas;
+	}
--- a/fbs/fontandbitmapserver/sfbs/SERVER.CPP	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/sfbs/SERVER.CPP	Fri Sep 24 16:14:28 2010 +0300
@@ -22,7 +22,7 @@
 #include "BitwiseBitmap.inl"
 
 const TInt KFbsPriority = 0;
-
+const TInt KFbsGoomMonitorSid = 0x10207218;
 // Setup security policies
 const TInt KRanges[] = 
 	{
@@ -37,7 +37,10 @@
 	EFbsMessFetchLinkedTypeface,
 	EFbsMessUpdateLinkedTypeface,
 	EFbsMessGetFontTable,
+    EFbsMessOogmNotification,
+    EFbsMessGetGlyphCacheMetrics,
 	};
+
 const TUint KRangeCount = sizeof(KRanges)/sizeof(TInt);
 const TUint8 KElementsIndex[KRangeCount] = 
 	{
@@ -52,14 +55,19 @@
 	2, // ECapabilityReadDeviceData for EFbsMessFetchLinkedTypeface
 	1, // ECapabilityWriteDeviceData for EFbsMessUpdateLinkedTypeface
 	0, // ECapability_None for EFbsMessGetFontTable and beyond
+    4, // SID for EFbsMessOogmNotification.
+    0, // For EFbsMessGetGlyphCacheMetrics and on.
 	};
+
 const CPolicyServer::TPolicyElement KElements[] = 
 	{
 	{_INIT_SECURITY_POLICY_C1(ECapability_None), CPolicyServer::EFailClient},
 	{_INIT_SECURITY_POLICY_C1(ECapabilityWriteDeviceData), CPolicyServer::EFailClient},
 	{_INIT_SECURITY_POLICY_C1(ECapabilityReadDeviceData), CPolicyServer::EFailClient},
-	{_INIT_SECURITY_POLICY_C1(ECapabilityPowerMgmt), CPolicyServer::EFailClient},	
+	{_INIT_SECURITY_POLICY_C1(ECapabilityPowerMgmt), CPolicyServer::EFailClient},
+	{_INIT_SECURITY_POLICY_S0(KFbsGoomMonitorSid), CPolicyServer::EFailClient}
  	};
+
 const CPolicyServer::TPolicy KFbsPolicy =
 	{
 	CPolicyServer::EAlwaysPass, //specifies all connect attempts should pass
@@ -70,9 +78,7 @@
 	};
 
 CFontBitmapServer::CFontBitmapServer():
-	CPolicyServer(KFbsPriority, KFbsPolicy),
-	iConnectionId(0),
-	iTopLevelStore(NULL)
+	CPolicyServer(KFbsPriority, KFbsPolicy)
 	{
 	}
 
@@ -85,25 +91,33 @@
 
 CFontBitmapServer* CFontBitmapServer::NewL()
 	{
-	CFontBitmapServer* fbs=new(ELeave) CFontBitmapServer;
-	CleanupStack::PushL(fbs);
-	fbs->iTopLevelStore=CFbTop::NewL();
+	CFontBitmapServer* self = new(ELeave) CFontBitmapServer;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(); //self
+	return self;
+	}
+
+/**
+Two-phase constructor.
+*/
+void CFontBitmapServer::ConstructL()
+	{
+	iTopLevelStore=CFbTop::NewL();
 	
 	// If fbserv data paging is configured as unpaged, automatically pin client descriptors 
 	if(!RProcess().DefaultDataPaged())
 		{
-		fbs->SetPinClientDescriptors(ETrue);
+		SetPinClientDescriptors(ETrue);
 		}
-
-	fbs->StartL(KFBSERVGlobalThreadName);
-	CleanupStack::Pop();
-	return(fbs);
+	StartL(KFBSERVGlobalThreadName);
 	}
 
 CFbTop* CFontBitmapServer::TopLevelStore()
 	{
 	return(iTopLevelStore);
 	}
+
 CSession2* CFontBitmapServer::NewSessionL(const TVersion& aVersion,const RMessage2& /*aMessage*/ ) const
 	{
 	TVersion v(KFbsMajorVersionNumber,KFbsMinorVersionNumber,KFbsBuildVersionNumber);
@@ -127,7 +141,7 @@
 	TPckgBuf<TSize> pixelSize;
 	TInt index=aMessage.Int0();
 	TInt limit=iTopLevelStore->FontStore()->NumTypefaces();
-	if(index<0 || index>limit)
+	if(index < 0 || index > limit)
 		{
 		return KErrArgument;
 		}
@@ -195,7 +209,7 @@
 void CFontBitmapServer::ProcMessage(const RMessage2& aMessage, TInt aSession)
 #endif
 	{
-	TInt ret=KErrNone;
+    TInt ret=KErrNone;
 	TBool clientPanicRequired = EFalse;
 #ifdef _DEBUG
 	TInt num=0;
@@ -346,6 +360,7 @@
 #ifdef _DEBUG
 	aRet=ret;
 #endif	
+
 	}
 
 /**
@@ -363,9 +378,9 @@
 void CFontBitmapServer::GetHeapSizesL(const RMessage2& aMessage)
 	{
 	TPckgBuf<THeapSizes> data;
-	TInt defaultHeapSize;
-	TInt smallBmpHeapSize;		
-	TInt bigBmpHeapSize;		
+	TInt defaultHeapSize = 0;
+	TInt smallBmpHeapSize = 0;		
+	TInt bigBmpHeapSize = 0;		
 	
 	User::Heap().AllocSize(defaultHeapSize);
 	bigBmpHeapSize = iTopLevelStore->iLargeBitmapChunk.Size();
@@ -385,18 +400,24 @@
 #endif
 
 
-CFontObject::CFontObject(CFontStore* aFontStore):
+CFontObject::CFontObject(CFontStore* aFontStore, CGlyphAtlas* aGlyphAtlas):
 	CObject(),
-	iAddressPointer(NULL),
-	iFontStore(aFontStore)
+	iFontStore(aFontStore),
+	iGlyphAtlas(aGlyphAtlas)
 	{
 	}
 
 CFontObject::~CFontObject()
 	{
 	if (AccessCount()==1)
+		{
 		Dec();
+		}
 	iFontStore->ReleaseFont(iAddressPointer);
+	if (iGlyphAtlas)
+		{
+		iGlyphAtlas->FontReleased(*iAddressPointer);
+		}
 	}
 
 // CBitmapObject constructor - takes ownership of aBmp
@@ -426,7 +447,9 @@
 		{
 		iHandle = reinterpret_cast<TInt>(this);
 		while (iFbTop->iBitmapObjectIndex.FindInOrder(this, Compare) != KErrNotFound)
+			{
 			++iHandle;
+			}
 		User::LeaveIfError(iFbTop->iBitmapObjectIndex.InsertInOrder(this, Compare));
 		}
 	}
@@ -471,9 +494,13 @@
 			if (index != KErrNotFound)
 				{
 				if (iCleanBitmap)
+					{
 					iFbTop->iBitmapObjectIndex[index] = iCleanBitmap;
+					}
 				else
+					{
 					iFbTop->iBitmapObjectIndex.Remove(index);
+					}
 				}
 			}
 		if (iCleanBitmap != NULL)
@@ -502,7 +529,7 @@
 
 void CBitmapObject::Close()
 	{
-	if (iCleanBitmap != NULL && Owner() != NULL && AccessCount() == 2)
+	if ((iCleanBitmap != NULL) && (Owner() != NULL) && (AccessCount() == 2))
 		{
 		static_cast<CBitmapObject*>(Owner())->iCleanBitmap = iCleanBitmap;
 		iCleanBitmap->SetOwner(Owner());
@@ -525,8 +552,7 @@
 // CSharedBitmapObject constructor - takes ownership of aBmp and aKey
 CSharedBitmapObject::CSharedBitmapObject(CFbTop& aFbTop, CBitwiseBitmap* aBmp, TDesC* aKey):
 	CBitmapObject(aFbTop, aBmp),
-	iKey(aKey),
-	iNext(NULL)
+	iKey(aKey)
 	{
 	__ASSERT_DEBUG(iKey, User::Invariant());	
 	}
--- a/fbs/fontandbitmapserver/sfbs/SERVER.H	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/sfbs/SERVER.H	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1995-2010 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"
@@ -13,33 +13,37 @@
 // Description:
 //
 
-#ifndef __FBSERV_H__
-#define __FBSERV_H__
+#ifndef SERVER_H
+#define SERVER_H
 
 #include <e32base.h>
 #include <f32file.h>
 #include <fbs.h>
+#include <sgresource/sgimage.h>
 #include "UTILS.H"
 #include "FBSMBMC.H"
 #include "FbsMessage.H"
+#include "glyphatlas.h"
 
 class CFbTop;
 class CFbsBackgroundCompression;
 class CFbsBackgroundCompressionQueueElement;
 class TOpenFontGlyphData;
 
+
 NONSHARABLE_CLASS(CFontObject): public CObject
 /**
 @internalComponent
 */
 	{
 public:
-	CFontObject(CFontStore* aFontStore);
+	CFontObject(CFontStore* aFontStore, CGlyphAtlas* aGlyphAtlas);
 	~CFontObject();
 public:
 	CBitmapFont* iAddressPointer;
 	CFontStore* iFontStore;
 	TInt iHeightInTwips;
+	CGlyphAtlas* iGlyphAtlas;
 	};
 
 NONSHARABLE_CLASS(CBitmapObject): public CObject
@@ -113,6 +117,7 @@
 	CFbTop* TopLevelStore();
 
 private:
+	void ConstructL();
 	void GetHeapSizesL(const RMessage2& aMessage);
 	TInt HandleMesgTypefaceSupport(const RMessage2& aMessage, TBool& aClientPanicRequired);
 	TInt HandleMesgFontHeight(const RMessage2& aMessage, TBool aInTwips);
@@ -171,8 +176,10 @@
 	void Disconnect(const RMessage2 &aMessage);
 #ifdef _DEBUG
 	void ProcMemMessage (const RMessage2& aMessage);
+	void ProcAtlasMessage (const RMessage2& aMessage);
 #endif	
 private:
+	void ConstructL();
 	CFbClient(RHeap* aHeap);
 	TInt HandleMesgFontDuplicate(const RMessage2& aMessage, TBool& aPanicRequired);
 	TInt HandleMesgGetNearestFont(const RMessage2& aMessage, TBool& aPanicRequired);
@@ -189,6 +196,10 @@
 	TInt HandleMesgGetGlyphOutline(const RMessage2& aMessage, TBool& aPanicRequired);
 	TInt HandleMesgReleaseGlyphOutline(const RMessage2& aMessage, TBool& aPanicRequired);
 	TInt HandleMesgReleaseFontTable(const RMessage2& aMessage, TBool& aPanicRequired);
+	TInt HandleMesgGetGlyphs(const RMessage2& aMessage, TBool& aPanicRequired);
+	TInt HandleMesgGetGlyphMetrics(const RMessage2& aMessage, TBool& aPanicRequired);
+	TInt HandleMesgOogmStatus(const RMessage2& aMessage);
+	void HandleMesgGlyphCacheMetrics(const RMessage2& aMessage);
 
 protected:
 	TUint iConnectionHandle;
@@ -202,6 +213,7 @@
 
 private:
 	RBuf16 iTextToShape;						// buffer used to hold incoming text that needs shaping
+	RArray<RSgImage> iGlyphImagesInTransit;	// last glyph images retrieved from glyph atlas
 #ifdef _DEBUG	
 	TBool iOwnHeapCheck; //for the process heap - current state
 	TBool iHeapCheck;	//for iHeap - current state
@@ -250,6 +262,7 @@
 
 
 IMPORT_C extern const TInt KFbServSharedHeapMaxSize;
+IMPORT_C extern const TInt KFbServGlyphAtlasCacheLimit;
 
 
 NONSHARABLE_CLASS(CFbTop): public CBase
@@ -271,7 +284,6 @@
 	TInt GetCleanBitmap(CBitmapObject*& aBmpObjPtr);
 	CBitmapObject* FindBitmap(TInt aHandle);
 	TBool ValidFontHandle(TInt aHandle);
-	TBool ValidBitmapFont(TInt aHandle);
 	CFontStore* FontStore() const;
 	RHeap* Heap() const;
 	CChunkPile* Pile() const;
@@ -287,6 +299,7 @@
 	void NotifyDirtyBitmap(CBitmapObject& aBmpObj, CFbClient* aClient);
 	TInt BitmapConUniqueID() const;
 	TInt FontConUniqueID() const;
+	CGlyphAtlas* GlyphAtlas() const;
 private:
 	CFbTop();
 	void ConstructL();
@@ -296,7 +309,7 @@
 	TInt FindFontNameAlias(const TDesC& aAlias);
 	void LoadShaperFactories();
 	void SafeInstallOfShaperFactoryL(TUid aInterfaceImplUid);
-	TInt CreateFontObjectFromFont(CFontObject*& aFontObjPtr, CFont* aFont);
+	TInt GetFontObjectFromFont(CFontObject*& aFontObjPtr, CFont* aFont);
 	TInt GetNearestNonAliasedFont(CFont*& aFont, TFbsMessage aMessage, const TFontSpec&	aFontSpec, TInt	aMaxHeight);
 private:
 	RFs iFilesys;
@@ -318,6 +331,7 @@
 	TBuf<KMaxTypefaceNameLength> iSystemDefaultFontTypefaceName;
 	TDblQue<TFbClientHelper> iClientHelpers;
 	TInt64 iNextAvailableSerialNumber;
+	CGlyphAtlas* iGlyphAtlas;
 	};
 
 inline CBitwiseBitmap* CBitmapObject::Address() const
@@ -360,5 +374,5 @@
 	return iFilesys;
 	}
 
-#endif
+#endif // SERVER_H
 
--- a/fbs/fontandbitmapserver/sfbs/SESSION.CPP	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/sfbs/SESSION.CPP	Fri Sep 24 16:14:28 2010 +0300
@@ -20,6 +20,7 @@
 #include "FbsRalc.h"
 #include "fbshelper.h"
 #include "FbsMessage.H"
+#include <graphics/fbsoogmmessage.h>
 
 GLDEF_C void Panic(TFbsPanic aPanic)
 	{
@@ -238,6 +239,7 @@
 EXPORT_C TInt RFbsSession::SendCommand(TInt aMessage,TInt aInt0,TInt aInt1,TInt aInt2,TInt aInt3) const
    {
 	__ASSERT_ALWAYS(iConnections>0,Panic(EFbsPanicBadConnection));
+
 	switch(aMessage)
 		{
 	case EFbsMessShutdown:
@@ -247,7 +249,9 @@
 	default:
 		break;
 		}
+
 	TInt ret = SendReceive(aMessage, TIpcArgs(aInt0,aInt1,aInt2,aInt3));
+
 	return(ret);
 	}
 
@@ -486,6 +490,36 @@
 	return iHelper->iServerSessionHandle;
 	}
 
+EXPORT_C TInt RFbsSession::GetGlyphCacheMetrics( TGlyphCacheMetrics& aGlyphCacheMetrics )
+    {
+    TPckgBuf<TGlyphCacheMetrics> metrics;
+    TIpcArgs args( &metrics );
+
+    TInt ret = SendReceive( EFbsMessGetGlyphCacheMetrics, args );
+    aGlyphCacheMetrics = metrics();
+
+    return ret;
+    }
+
+/**
+ Perform the IPC to convey the desired OoGM action to the glyph atlas.
+
+ @return KErrNone if IPC was successful. One of the system-wide error
+         codes, as described for RSessionBase::SendReceive(), if not.
+
+ @note The server-side platform security policy applied to this method is such that it is only useable by the GOoM framework.
+
+ @param aOogmMessage. A reference to the class encapsulating the OoGM action required of the glyph atlas.
+*/
+EXPORT_C TInt RFbsSession::ConveyOogmMessage( TFbsOogmMessage& aOogmMessage )
+    {
+    TPckgBuf<TFbsOogmMessage> oogmMessage;
+    oogmMessage() = aOogmMessage;
+    TIpcArgs args( &oogmMessage );
+
+    return SendReceive( EFbsMessOogmNotification, args );
+    }
+
 /**
 Returns the current sizes of the FBServ default heap, the heap for large bitmaps, 
 and the heap for small bitmaps.
--- a/fbs/fontandbitmapserver/sfbs/UTILS.H	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/sfbs/UTILS.H	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1998-2010 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"
@@ -20,8 +20,9 @@
 #include <gdi.h>
 #include <fntstore.h>
 #include <bitmap.h>
+#include <sgresource/sgimage.h>
 
-
+class RFbsSession;
 
 /**
 @internalComponent
@@ -43,35 +44,43 @@
 */
 enum TFbsPanic
 	{
-	EFbsPanicNoConnection=1,
-	EFbsPanicBadConnection,
-	EFbsPanicUnknownMessage,
-	EFbsPanicActiveSchedulerError,
-	EFbsPanicStartupFailed,
-	EFbsTypefaceStoreError,
-	EFbsFontCreateFailed,
-	EFbsFontAddressViolation,
-	EFbsBitmapInvalidFormat,
-	EFbsBitmapInvalidMode,
-	EFbsBitmapInvalidCompression,
-	EFbsBitmapDecompressionError,
-	EFbsPanicChunkError,
-	EFbsColor256UtilError,
-	EFbsHardwareBitmapError,
-	EFbsNotSupportedForCompression,
-	EFbsBitmapAlignment,
-	EFbsBitmapInvalidScanLinePtr,
-	EFbsBitmapInvalidMode2,
-	EFbsBitmapInvalidMode3,
-	EFbsBitmapSwappingImpossible,
-	EFbsPanicBadHeapLock,
-	EFbsShaperNotYetCalled,
-	EFbsShaperInvalidArguments,
-	EFbsInvalidCompressionThreshold,
-	EFbsTypefaceIndexOutOfRange,
-	EFbsPanicBitmapDataCopy,
-	EFbsPanicBitmapReadOnly,
-	EFbsPanicInvalidBitmapType
+	EFbsPanicNoConnection = 1,
+	EFbsPanicBadConnection = 2,
+	EFbsPanicUnknownMessage = 3,
+	EFbsPanicActiveSchedulerError = 4,
+	EFbsPanicStartupFailed = 5,
+	EFbsTypefaceStoreError = 6,
+	EFbsFontCreateFailed = 7,
+	EFbsFontAddressViolation = 8,
+	EFbsBitmapInvalidFormat = 9,
+	EFbsBitmapInvalidMode = 10,
+	EFbsBitmapInvalidCompression = 11,
+	EFbsBitmapDecompressionError = 12,
+	EFbsPanicChunkError = 13,
+	EFbsColor256UtilError = 14,
+	EFbsHardwareBitmapError = 15,
+	EFbsNotSupportedForCompression = 16,
+	EFbsBitmapAlignment = 17,
+	EFbsBitmapInvalidScanLinePtr = 18,
+	EFbsBitmapInvalidMode2 = 19,
+	EFbsBitmapInvalidMode3 = 20,
+	EFbsBitmapSwappingImpossible = 21,
+	EFbsPanicBadHeapLock = 22,
+	EFbsShaperNotYetCalled = 23,
+	EFbsShaperInvalidArguments = 24,
+	EFbsInvalidCompressionThreshold = 25,
+	EFbsTypefaceIndexOutOfRange = 26,
+	EFbsPanicBitmapDataCopy = 27,
+	EFbsPanicBitmapReadOnly = 28,
+	EFbsPanicFontNullHandle = 29,
+    EFbsPanicGlyphDataIteratorClosed = 31,
+	EFbsPanicGlyphMetricsArrayOutOfBounds = 32,
+	EFbsPanicGlyphDataIteratorIndexOutOfRange = 33,
+	EFbsPanicInvalidBitmapType = 35,
+	EFbsPanicGlyphAtlasInconsistentState = 36,
+	EFbsPanicGlyphDataIteratorFailedToOpenImage = 37,
+	EFbsPanicGlyphDataIteratorInvalidState = 39,
+	EFbsPanicGlyphMetricsArrayInvalidState = 40,
 	};
 
 class TScanLine
@@ -125,9 +134,9 @@
 @internalComponent
 */
 	{
-	public:
-		TSizeInfo(){}
-		TSizeInfo(TInt aMaxHeight,TSize aDevSize):iMaxHeight(aMaxHeight),iDevSize(aDevSize) {}
+public:
+	TSizeInfo(){}
+	TSizeInfo(TInt aMaxHeight,TSize aDevSize):iMaxHeight(aMaxHeight),iDevSize(aDevSize) {}
 
 	TInt iMaxHeight;
 	TSize iDevSize;
@@ -182,7 +191,8 @@
 	void ShrinkSmallSection(TInt aShrinkBy);
 private:
 	RChunk iChunk;
-	TInt iPageSize, iPageMask;
+	TInt iPageSize;
+	TInt iPageMask;
 	RPointerArray<TUint8> iSmallCells; // last address is not a cell but the top of the small section
 	RArray<TInt> iFreeSmallCellLinks; // index of Nth free small cell is element 0 + element 1 + ... + element N-1
 	TInt iLargeSectionBottom; // boundary between small & large sections
@@ -264,6 +274,74 @@
     TInt iLen;
     };
 
-#endif
+/**
+Maximum number of glyphs to be sent to server/received from client at a time, 
+when retrieval of glyphs is necessary for implementation of RFbsGlyphDataIterator.
+*/
+const TInt KMaxGlyphBatchSize = 8;
+
+/**
+Maximum number of TOpenFontCharMetrics structures to be sent to server/received
+from client at a time, when retrieval of glyph metrics is necessary for
+implementation of RFbsGlyphMetricsArray.
+*/
+const TInt KMaxMetricsBatchSize = 16;
+
+/**
+Used by RFbsGlyphDataIterator for client/server communication of glyph info.
+Contains all the data necessary to retrieve a glyph from server and recreate
+glyph in client process.
+@internalComponent 
+ */
+class TGlyphImageInfo
+    {
+public:
+    inline TGlyphImageInfo() : iImageId(KSgNullDrawableId), iPosX(0), iPosY(0) {}
+public:
+    TSgDrawableId iImageId;
+    TInt16 iPosX;
+    TInt16 iPosY;
+    TOpenFontCharMetrics iMetrics;
+    };
 
+/**
+Used by CGlyphDataIteratorImpl. It is a container to group the 
+metadata and the image data of an individual glyph recevied from the
+server, all together. A collection of these is stored in the font,
+received from the server in batches.
+@internalComponent 
+*/
+struct TGlyphBatchItem
+    {
+    TSglQueLink iLink;
+    RSgImage iImage;
+    TGlyphImageInfo iInfo;
+    };
 
+/**
+Implementor class of RFbsGlyphDataIterator. This class contains all
+state information and contains much of the implementation of the
+behaviour.
+@internalComponent 
+ */
+NONSHARABLE_CLASS(CGlyphDataIteratorImpl) : public CBase
+    {
+public:
+    CGlyphDataIteratorImpl(TInt aFbsFontHandle, const TUint* aGlyphCodes, TInt aCount);
+    ~CGlyphDataIteratorImpl();
+    TInt Initialise();
+    TInt Next();
+    void UpdateGlyphRect();
+    TInt UpdateGlyphBatch(TInt aIndex);
+    
+public:    
+    TSglQue<TGlyphBatchItem> iGlyphBatch;   // Linked-list of the current batch of received glyphs.
+    const TUint* iGlyphDataIterCodes;       // An array of glyph codes
+    TInt  iGlyphDataIterCodeCount;          // The number of glyph codes in the array
+    TInt  iGlyphDataIterCodeIndex;          // The index of the current glyph code in the array
+    TRect iGlyphDataIterRect;               // The current glyph rectangle.
+    TInt  iFbsFontHandle;                   // The Font Handle the iterator was opened with  
+    RFbsSession* iFbs;
+    };
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/fbsglyphdataiterator.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,465 @@
+// Copyright (c) 2009-2010 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:
+//
+
+#include <e32def.h>
+#include <gdi.h>
+#include <graphics/gdi/gdistructs.h>
+#include <graphics/gdi/gdiconsts.h>
+#include <graphics/fbsglyphdataiterator.h>
+#include "FbsMessage.h"
+#include "UTILS.H"
+
+const TInt KFbsGlyphDataIterCodeInvalid = -1;
+
+extern void Panic(TFbsPanic aPanic);
+
+/**
+The default constructor sets the iterator to a closed and empty state. It 
+is the only way of constructing an iterator as instances cannot be copied by 
+assignment or passed by value.
+ */
+EXPORT_C RFbsGlyphDataIterator::RFbsGlyphDataIterator() :
+    iImpl(NULL)
+    {
+    }
+
+/**
+For a given font (aFont), this method retrieves the glyph data for a list of 
+glyph codes (aGlyphCodes), containing a number (aCount) of codes. On success, 
+the iterator is initialised with the data for the first glyph in aGlyphCodes.
+
+The memory allocated to aGlyphCodes must not be freed or altered while the 
+iterator is in use (i.e. until the iterator has been closed). 
+
+Open() may not be called on an already open iterator. In order to re-open an 
+iterator, it must first be closed by a call tor Close().
+
+If a glyph code is passed in that is not a recognised glyph code for the 
+associated font, an empty-box glyph will be returned. This behaviour is 
+consistent with CFbsFont::GetCharacterData().
+
+@pre The iterator is not already open. 
+
+@param aFont The font to provide the glyph code data for.
+@param aGlyphCodes An array of glyph codes that the iterator will 
+	provide data for. This memory allocated for this array must not be 
+	freed before the iterator is closed.
+@param aCount The number of glyph codes in aGlyphCodes.
+
+@return 
+	KErrNone, if the iterator is successfully initialised to retrieve 
+		the glyph data;
+	KErrInUse, if the iterator is already open, in which case the state of
+        the iterator is left unchanged;
+	KErrNoMemory, if the iterator cannot be opened due to insufficient 
+		system memory;
+	KErrNotSupported, if aFont refers to a bitmap font or an outline & shadow
+        font, if the required version of the hardware driver is not available
+        (EGL 1.3 or later is required), or if RSgImages are not supported by
+        the system;
+	KErrArgument, if aCount is negative or zero, or if aGlyphCodes is null.
+ */
+EXPORT_C TInt RFbsGlyphDataIterator::Open(CFbsFont& aFont, const TUint* aGlyphCodes, TInt aCount)
+	{  
+	if (iImpl)
+		{
+		return KErrInUse;
+		}
+	if ((aCount <= 0) || !aGlyphCodes)
+		{
+		return KErrArgument;
+		}
+	if (!aFont.Address()->IsOpenFont())
+        {
+        return KErrNotSupported;
+        }
+    TInt glyphBitmapType = aFont.Address()->GlyphBitmapType();
+    if (!( (glyphBitmapType == EMonochromeGlyphBitmap) || (glyphBitmapType == EAntiAliasedGlyphBitmap) ))
+        {
+        //Only supported bitmap types can be used i.e. EMonochromeGlyphBitmap or EAntiAliasedGlyphBitmap
+        return KErrNotSupported;
+        }
+    // Check that the max width and height of the font are both no more than 2048.
+    // This is the smallest maximum size an RSgImage can be created with.
+    // This limit is arbitrarily set as it should cover nearly all use cases.
+    const TInt KMaxFontSizeInPixels = 2048;
+    TInt maxHeight = aFont.FontMaxHeight();
+    TInt maxWidth = aFont.MaxCharWidthInPixels();
+    if ( (KMaxFontSizeInPixels < maxHeight) || (KMaxFontSizeInPixels < maxWidth) )
+        {
+        return KErrTooBig;
+        }
+    // Construct implementor object that holds the state for the iterator.
+	iImpl = new CGlyphDataIteratorImpl(aFont.iHandle, aGlyphCodes, aCount);
+	if (!iImpl)
+	    {
+	    return KErrNoMemory;
+	    }
+	TInt err = iImpl->Initialise();
+	if (err != KErrNone)
+	    {
+        Close();
+	    }
+	return err;   
+	}
+
+/**
+Moves the iterator to the data for the next glyph code in the array passed 
+into RFbsGlyphDataIterator::Open(). Data for the glyph can then be accessed 
+using the Image(), Rect() and Metrics() methods.
+
+Once Next() has been called, the references returned by Image(), Rect() and 
+Metrics() methods during the previous iteration should be considered invalid 
+and must be discarded. 
+
+Calling Next() repeatedly will iterate through the glyph data for all the glyph
+codes, until it has reached the last glyph code in the array (assuming no errors
+are encountered), at which point KErrNotFound is returned, and the array of glyph
+codes passed to RFbsGlyphDataIterator::Open() can safely be deleted.
+
+If the call was successful, KErrNone is returned. If an error is encountered an
+error code will be returned and the state of the iterator is left unchanged.
+
+@pre The iterator has been opened by a successful call to Open().
+@post The properties of the iterator are of the glyph corresponding
+	to the next code passed in the array to Open().	However, if an error code 
+	was returned, the state of the iterator	is unchanged.
+	
+@return 
+	KErrNone, if the iterator was successfully advanced;
+	KErrNotFound, if the iterator is already at the last element and cannot
+		be advanced any further;
+	KErrNoMemory, if there is insufficient system memory available;
+	KErrNoGraphicsMemory, if there is insufficient graphics memory available.
+	
+@panic FBSCLI 31, if the iterator is not open.
+@panic FBSERV -8, if as a result of this call, communication with the 
+    server is invoked, and the associated CFbsFont has been destroyed.
+ */
+EXPORT_C TInt RFbsGlyphDataIterator::Next()
+    {
+    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
+    return iImpl->Next();
+    }
+
+/**
+Closes the iterator and releases its internal resources. After calling, all data 
+retrieved by the iterator is no longer safe to use. Once closed, this iterator 
+can be re-opened. Calling Close() on an already closed iterator has no effect.
+
+Once an iterator is closed, the array of glyphs (aGlyphCodes) passed to
+RFbsGlyphDataIterator::Open() can safely be deleted.
+
+@post The iterator is closed.
+ */
+EXPORT_C void RFbsGlyphDataIterator::Close()
+    {
+    delete iImpl;
+    iImpl = NULL;
+    }
+
+/**
+Returns a reference to the RSgImage that contains the glyph for the current 
+iteration. The image representation of the glyph is the same as the image 
+returned by the existing CFbsFont::GetCharacterData() method (i.e. an alpha mask). 
+
+The RSgImage should only be considered a temporary handle for use in this 
+iteration, and should not be used after a call to Next() or Close() has 
+been made.
+
+Note: For glyphs such as space which have no visible representation, Image() 
+will return a null image handle (i.e. RSgImage::IsNull() returns ETrue). This 
+cannot be used for drawing. In this case Rect() will be empty however 
+Metrics() will still be valid. 
+
+@pre The iterator has been initialised by successfully calling Open().
+     
+@return A handle to the image where the glyph for this iteration is stored.
+     
+@panic FBSCLI 31, if the iterator is not open.
+ */
+EXPORT_C const RSgImage& RFbsGlyphDataIterator::Image() const
+    {
+    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
+    __ASSERT_DEBUG(!iImpl->iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
+    return iImpl->iGlyphBatch.First()->iImage;
+    }
+
+/**
+Returns the area within the RSgImage where the glyph for the current
+iteration is located. The reference returned by Rect() should be considered 
+temporary for use within this iteration and should not be used after a call to 
+Next() or Close() has been made.
+ 
+@pre The iterator has been initialised by successfully calling Open().
+     
+@return A rectangle representing the position and size in pixels, 
+	of the glyph for this iteration on the RSgImage provided by Image().
+     
+@panic FBSCLI 31, if the iterator is not open.
+ */
+EXPORT_C const TRect& RFbsGlyphDataIterator::Rect() const
+    {
+    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
+    __ASSERT_DEBUG(!iImpl->iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
+    return iImpl->iGlyphDataIterRect;
+    }
+
+/**
+Returns the glyph metrics for the current iteration. The reference returned by 
+Metrics() should be considered temporary for use within this iteration and 
+should not be used after a call to Next() or Close() has been made.
+
+@pre The iterator has been initialised by successfully calling Open().
+ 
+@return The metrics for the glyph at the current iteration.
+
+@panic FBSCLI 31, if the iterator is not open.
+ */
+EXPORT_C const TOpenFontCharMetrics& RFbsGlyphDataIterator::Metrics() const
+    {
+    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
+    __ASSERT_DEBUG(!iImpl->iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
+    return iImpl->iGlyphBatch.First()->iInfo.iMetrics;
+    }
+
+/**
+Returns the glyph code associated with the data for the current iteration.
+
+@pre The iterator has been initialised by successfully calling Open().
+ 
+@return The glyph code of the glyph at the current iteration.
+
+@panic FBSCLI 31, if the iterator is not open.
+ */
+EXPORT_C TUint RFbsGlyphDataIterator::GlyphCode() const
+    {
+    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
+    __ASSERT_DEBUG(!iImpl->iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
+    return iImpl->iGlyphDataIterCodes[iImpl->iGlyphDataIterCodeIndex];
+    }
+
+
+/**
+Constructs a CGlyphDataIteratorImpl. 
+@param aFbsFontHandle The handle of the FbsFont that the iterator is working with.
+@param aGlyphCodes The array of glyph codes sent to RFbsGlyphDataIterator::Open()
+@param aCount The number of glyph codes in aGlyphCodes.
+ */
+CGlyphDataIteratorImpl::CGlyphDataIteratorImpl(TInt aFbsFontHandle, const TUint* aGlyphCodes, TInt aCount) :
+    iGlyphBatch(_FOFF(TGlyphBatchItem, iLink)),
+    iGlyphDataIterCodes(aGlyphCodes),
+    iGlyphDataIterCodeCount(aCount),
+    iGlyphDataIterCodeIndex(KFbsGlyphDataIterCodeInvalid),
+    iFbsFontHandle(aFbsFontHandle)
+    {
+    }
+
+/** 
+Destructor. Releases all resources, disconnects from server and frees any
+items in the list of batched items.
+ */
+CGlyphDataIteratorImpl::~CGlyphDataIteratorImpl()
+    {
+    if (iFbs)
+        {
+        if (iGlyphDataIterCodeIndex != KFbsGlyphDataIterCodeInvalid)
+            {
+            //Send the No-Op command to ensure that the "In Transit" RSgImage(s) are closed.
+            iFbs->SendCommand(EFbsMessNoOp);
+            }
+        RFbsSession::Disconnect();
+        iFbs = NULL;
+        }
+    while (!iGlyphBatch.IsEmpty())
+        {
+        TGlyphBatchItem* item = iGlyphBatch.First();
+        item->iImage.Close();
+        iGlyphBatch.Remove(*item);
+        delete item;
+        }
+    iGlyphBatch.Reset();
+    }
+
+/**
+Sets up the CGlyphDataIteratorImpl, populating the first batch of glyphs.
+Should only be called once, immediately after construction.
+ */
+TInt CGlyphDataIteratorImpl::Initialise()
+    {
+    __ASSERT_DEBUG(iFbsFontHandle, Panic(EFbsPanicGlyphDataIteratorInvalidState));    
+    __ASSERT_DEBUG(iGlyphDataIterCodes, Panic(EFbsPanicGlyphDataIteratorInvalidState));
+    __ASSERT_DEBUG(iGlyphDataIterCodeCount, Panic(EFbsPanicGlyphDataIteratorInvalidState));
+    __ASSERT_DEBUG(iGlyphDataIterCodeIndex == KFbsGlyphDataIterCodeInvalid, Panic(EFbsPanicGlyphDataIteratorInvalidState));
+    
+    // If the client already has a session open, this is just a reference counting exercise and should incur no performance impact.
+    TInt err = RFbsSession::Connect();
+    if (err == KErrNone)
+        {
+        iFbs = RFbsSession::GetSession();
+        err = UpdateGlyphBatch(0);
+        }
+    if (err == KErrNone)
+        {
+        iGlyphDataIterCodeIndex = 0;
+        UpdateGlyphRect();
+        }
+    return err;
+    }
+
+/**
+Increments the current iteration if possible, re-sending the request
+for more glyphs if the current batch of glyphs is down to the last
+item.
+@see RFbsGlyphDataIterator::Next()
+ */
+TInt CGlyphDataIteratorImpl::Next()
+    {
+    __ASSERT_DEBUG(!iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
+    if ( (iGlyphDataIterCodeIndex + 1) >= iGlyphDataIterCodeCount) 
+        {
+        return KErrNotFound; 
+        }
+    TInt err = UpdateGlyphBatch(iGlyphDataIterCodeIndex + 1);
+    if (err == KErrNone)
+        {
+        ++iGlyphDataIterCodeIndex;
+        // Close the current image and pop the head of the batch.
+        TGlyphBatchItem* item = iGlyphBatch.First();
+        item->iImage.Close();
+        iGlyphBatch.Remove(*item);
+        delete item;
+        __ASSERT_DEBUG(!iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
+        UpdateGlyphRect();
+        }
+    return err;
+    }
+
+/**
+Checks whether a call to the server is required to get a new batch of glyph 
+info, and processes the response from the server as necessary.
+
+@param aIndex Specifies the index into the glyph array which needs to be in
+the active glyph batch. If it is not there, a request is made to the server
+to get it.
+@return KErrNone if getting at least one glyph succeeded or a call to the
+    server was not necessary, otherwise one of the system wide error codes.
+@panic FBSCLI 31 (debug only), if the iterator is not open
+@panic FBSCLI 33 (debug only), if an unexpected number of glyphs was received
+    as a result of requesting glyphs from the server, or if the current batch
+    of glyphs is empty when there should be at least one item.
+ */
+TInt CGlyphDataIteratorImpl::UpdateGlyphBatch(TInt aIndex)
+    {
+    __ASSERT_DEBUG(Rng(0, aIndex, iGlyphDataIterCodeCount - 1), Panic(EFbsPanicGlyphDataIteratorIndexOutOfRange));
+
+    TInt err = KErrNone;
+    
+    TBool needMoreGlyphs = EFalse;
+    if (iGlyphBatch.IsEmpty())
+        {
+        // Current batch is empty, must request more. Should only get here when the iterator 
+        // is first opened, since one item should always be in the list from then on.
+        __ASSERT_DEBUG(aIndex == 0, Panic(EFbsPanicGlyphDataIteratorInvalidState));
+        needMoreGlyphs = ETrue;
+        }
+    else if (iGlyphBatch.IsLast(iGlyphBatch.First()))
+        {
+        // Only one item in the list. 
+        needMoreGlyphs = ETrue;
+        }
+    
+    if (needMoreGlyphs)
+        {
+        // If the array of batched images is empty OR only one left, means we need to request a new batch.
+        // We make sure there is at least one glyph in the batch so the iterator is always usable even
+        // when a failure to move to the next iteration occurs.
+    
+        TBool glyphAddedToBatch = EFalse;
+        TUint glyphCodes[KMaxGlyphBatchSize];
+        
+        TInt numGlyphsToRequest = Min(iGlyphDataIterCodeCount - aIndex, KMaxGlyphBatchSize);        
+        (void)Mem::Copy(glyphCodes, &(iGlyphDataIterCodes[aIndex]), sizeof(TUint) * numGlyphsToRequest);
+        TPckg<TUint[KMaxGlyphBatchSize]> argGlyphCodes(glyphCodes);
+        
+        TGlyphImageInfo rcvdGlyphInfo[KMaxGlyphBatchSize];
+        TPckg<TGlyphImageInfo[KMaxGlyphBatchSize]> argGlyphInfo(rcvdGlyphInfo);
+        
+        if (numGlyphsToRequest < KMaxGlyphBatchSize)
+            {
+            argGlyphCodes.SetLength(numGlyphsToRequest * sizeof(TUint));
+            argGlyphInfo.SetLength(numGlyphsToRequest * sizeof(TGlyphImageInfo));
+            }
+        
+        err = iFbs->SendCommand(EFbsMessGetGlyphs, TIpcArgs(iFbsFontHandle, &argGlyphCodes, &argGlyphInfo));
+        if (err == KErrNone)
+            {
+            __ASSERT_DEBUG(argGlyphInfo.Length() % sizeof(TGlyphImageInfo) == 0, Panic(EFbsPanicGlyphDataIteratorInvalidState));
+            TInt numRcvdGlyphs = argGlyphInfo.Length() / sizeof(TGlyphImageInfo);
+            __ASSERT_DEBUG(numRcvdGlyphs > 0, Panic(EFbsPanicGlyphDataIteratorInvalidState));
+            __ASSERT_DEBUG(numRcvdGlyphs <= KMaxGlyphBatchSize, Panic(EFbsPanicGlyphDataIteratorInvalidState));
+            
+            // Store the received glyph data, and open the image handles so that the IDs
+            // will not be released by FbServ between now and the client using them.
+            // If a failure occurs while processing one of the recevied glyphs,
+            // abort the rest but keep the ones that succeeded.
+            for (TInt i = 0; (i < numRcvdGlyphs) && (err == KErrNone); ++i)
+                {
+                TGlyphBatchItem* glyphEntry = new TGlyphBatchItem;
+                if (!glyphEntry)
+                    {
+                    err = KErrNoMemory;
+                    }
+                else
+                    {
+                    glyphEntry->iInfo = rcvdGlyphInfo[i];
+                    
+                    RSgImage glyphImage;
+                    if (rcvdGlyphInfo[i].iImageId != KSgNullDrawableId)
+                        {
+                        err = glyphEntry->iImage.Open(rcvdGlyphInfo[i].iImageId);
+                        }
+                    if (err == KErrNone)
+                        {
+                        iGlyphBatch.AddLast(*glyphEntry);
+                        glyphAddedToBatch = ETrue;
+                        }
+                    else
+                        {
+                        delete glyphEntry;
+                        }
+                    }
+                }
+            }
+        if (err != KErrNone && glyphAddedToBatch)
+            {
+            // There was an error adding an item to the batch. Rather than return the
+            // error to the client, ignore it and use what glyphs we successfully batched.
+            err = KErrNone; 
+            }
+        }    
+    return err;
+    }
+
+/**
+Updates the glyph rectangle member based on the current glyph metrics.
+@post The iGlyphDataIterRect member is updated to reflect the position
+    and size of the currently active glyph.
+ */
+void CGlyphDataIteratorImpl::UpdateGlyphRect()
+    {
+    iGlyphDataIterRect.iTl = TPoint(iGlyphBatch.First()->iInfo.iPosX, iGlyphBatch.First()->iInfo.iPosY);
+    iGlyphDataIterRect.SetSize(TSize(iGlyphBatch.First()->iInfo.iMetrics.Width(), iGlyphBatch.First()->iInfo.iMetrics.Height()));
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/fbsglyphdataiterator.h	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,53 @@
+// Copyright (c) 2009-2010 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:
+//
+
+
+#ifndef FBSGLYPHDATAITERATOR_H
+#define FBSGLYPHDATAITERATOR_H
+
+#include <e32def.h>
+#include <fbs.h>
+#include <sgresource/sgimage.h>
+
+class CGlyphDataIteratorImpl;
+class TOpenFontCharMetrics;
+
+/**
+An iterator class to provide access to glyph image data and metrics, 
+one glyph per iteration.
+@publishedPartner
+@prototype
+*/
+NONSHARABLE_CLASS(RFbsGlyphDataIterator)
+	{
+public:
+	IMPORT_C RFbsGlyphDataIterator();
+	IMPORT_C TInt Open(CFbsFont& aFont, const TUint* aGlyphCodes, TInt aCount);
+	IMPORT_C TInt Next();
+	IMPORT_C void Close();
+	IMPORT_C const RSgImage& Image() const;
+	IMPORT_C const TRect& Rect() const;
+	IMPORT_C const TOpenFontCharMetrics& Metrics() const;
+	IMPORT_C TUint GlyphCode() const;
+	
+private:
+	RFbsGlyphDataIterator(const RFbsGlyphDataIterator&);
+	const RFbsGlyphDataIterator& operator =(const RFbsGlyphDataIterator&);
+	
+private:
+    CGlyphDataIteratorImpl* iImpl;
+	};
+
+#endif /* FBSGLYPHDATAITERATOR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/fbsglyphmetricsarray.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,274 @@
+// Copyright (c) 2009-2010 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:
+//
+
+
+#include <e32def.h>
+#include <gdi.h>
+#include <graphics/gdi/gdistructs.h>
+#include <graphics/gdi/gdiconsts.h>
+#include <graphics/fbsglyphmetricsarray.h>
+#include "UTILS.H"
+#include "FbsMessage.h"
+
+// 'most significant bit' flag to ensure value is interpreted as a glyph code rather than an ascii code
+const TUint KGlyphCodeFlag = 0x80000000;      
+
+extern void Panic(TFbsPanic aPanic);
+
+/** Helper function for converting an offset (that was calculated using
+PointerToOffset()) back to a pointer relative to the passed heap base.
+@param aOffset The offset to be converted to a pointer.
+@param aHeapBase A pointer to the heap base of the current process.
+@return A pointer relative to the passed heap base.
+*/
+static TAny* OffsetToPointer(const TInt aOffset, TUint8* aHeapBase)
+    {
+    if ( (aOffset != 0) && (aHeapBase != NULL) )
+        {
+        return (TAny*)(aOffset + aHeapBase);
+        }
+    return NULL;
+    }
+
+/**
+Constructs an empty RFbsGlyphMetricsArray instance. This will not allocate any memory.
+ */
+EXPORT_C RFbsGlyphMetricsArray::RFbsGlyphMetricsArray() :
+    iGlyphCodes(NULL)
+    {
+    }
+
+/**
+Allocates the memory for the array if it has not already been allocated, and 
+populates the RFbsGlyphMetricsArray with the metrics information for aCount glyph 
+codes passed in as the array aGlyphCodes, for the font aFont. If the operation 
+is successful, KErrNone is returned and the array is populated with glyph 
+metrics data. Each entry in the array will be in the same order as the 
+corresponding codes in aGlyphCodes.
+
+The memory allocated to aGlyphCodes can be freed after the call to Get().
+
+Get() can be called on an RFbsGlyphMetricsArray multiple times without calling 
+Close(), since the memory for the array is not de-allocated until a call to 
+Close(). Calls to Get() will cause the previous content of the array to be 
+overwritten.
+
+In the event of an error code other than KErrNone, the state of the array
+will remain unchanged.
+ 
+@param aFont A font which to retrieve the glyph metrics for.
+@param aGlyphCodes An array of glyph codes to retrieve the metrics for.
+@param aCount The number of glyph codes in aGlyphCodes.
+
+@return
+	KErrNone, if the array is successfully populated with glyph metrics;
+	KErrNoMemory, if insufficient system memory is available;
+	KErrArgument, if aCount is negative or zero, or if aGlyphCodes is null;
+	KErrNotSupported, if aFont is a bitmap font.
+*/
+EXPORT_C TInt RFbsGlyphMetricsArray::Get(CFbsFont& aFont, const TUint* aGlyphCodes, TInt aCount)
+	{
+    if ((aCount <= 0) || !aGlyphCodes)
+        {
+        return KErrArgument;
+        }
+    if (iMetrics.Reserve(aCount) != KErrNone)
+        {
+        return KErrNoMemory;
+        }
+    if (!aFont.Address()->IsOpenFont())
+        {
+        return KErrNotSupported;
+        }
+    
+    iGlyphCodes = aGlyphCodes;
+    iCount = aCount;
+    TInt err = KErrNone;
+    
+    
+    // If iMetrics array already has a count greater than aCount, remove entries
+    // until count is same as aCount so that we can reuse the existing entries.
+    TInt numEntriesToRemove = iMetrics.Count() - aCount;
+    while (0 < numEntriesToRemove)
+        {
+        --numEntriesToRemove;
+        iMetrics.Remove(aCount + numEntriesToRemove);
+        }
+    const TInt indexToGrowArrayAt = iMetrics.Count();
+    
+    CBitmapFont* font = aFont.Address();
+    TUint ipcGlyphArrayIndex[KMaxMetricsBatchSize];
+    TInt ipcGlyphArrayIndexCount = 0;   
+    const TUint8* dummyBitmap;
+    TOpenFontCharMetrics charDataMetrics;
+            
+    for (TInt i = 0; i < aCount && (err == KErrNone); ++i)
+        {
+        // First check the cache in shared memory - if present it will avoid using IPC.
+        if (font->GetCharacterData(aFont.iFbs->ServerSessionHandle(), aGlyphCodes[i] | KGlyphCodeFlag, charDataMetrics, dummyBitmap))
+            {
+            if (i < indexToGrowArrayAt)
+                {
+                iMetrics[i] = charDataMetrics;
+                }
+            else
+                {
+                // Extending the size of the array, but memory is already reserved.
+                (void) iMetrics.Append(charDataMetrics);    
+                }
+            }            
+        else
+            {
+            // Not found in shared memory - instead add the index to index array, which will
+            // be processed when the array is full or at the end of the loop.
+            ipcGlyphArrayIndex[ipcGlyphArrayIndexCount++] = i;
+            if (ipcGlyphArrayIndexCount == KMaxMetricsBatchSize)
+                {
+                err = SendRecvGlyphMetrics(aFont, ipcGlyphArrayIndex, ipcGlyphArrayIndexCount, &iMetrics);
+                ipcGlyphArrayIndexCount = 0;
+                }
+            else if (i >= indexToGrowArrayAt)
+                {
+                // Add a metrics placeholder to keep the size of the array and the currently
+                // processed glyph in sync. It will later get overwritten when it is received
+                // from the server.
+                (void) iMetrics.Append(charDataMetrics);
+                }
+            }
+        }
+    if ((err == KErrNone) && (ipcGlyphArrayIndexCount != 0))
+        {
+        err = SendRecvGlyphMetrics(aFont, ipcGlyphArrayIndex, ipcGlyphArrayIndexCount, &iMetrics);
+        }
+    
+    __ASSERT_DEBUG((err != KErrNone) || (aCount == iMetrics.Count()), Panic(EFbsPanicGlyphMetricsArrayInvalidState));  
+    
+    return err;    
+	}
+/**
+Helper function for Get(). 
+Given a list of indices into a glyph code array, the corresponding glyph
+codes are made into a single list sent to the server, and the received glyph
+metrics are set in the array of metrics at the corresponding indices.
+
+@param aFont The font to receive the glyph metrics of.
+@param aArrayIndices An array of indices into the glyphcode array which
+    will be sent for requesting of metrics to the server.
+@param aArrayIndicesCount The number of glyphs in aGlyphArrayIndices.
+@param aMetrics The array which will store the resulting metrics objects upon
+    completion.
+@return KErrNone if successful, otherwise one of the system-wide error codes. 
+
+@panic FBSCLI 39 in debug builds only, if the parameters to this method are
+    invalid, or if the output array is of the wrong size when appending to it.
+ */
+TInt RFbsGlyphMetricsArray::SendRecvGlyphMetrics(CFbsFont& aFont, TUint* aArrayIndices, TInt aArrayIndicesCount, RArray<TOpenFontCharMetrics>* aMetrics) const
+    {
+    __ASSERT_DEBUG(aArrayIndicesCount > 0, Panic(EFbsPanicGlyphDataIteratorInvalidState)); 
+    __ASSERT_DEBUG(aArrayIndicesCount <= KMaxMetricsBatchSize, Panic(EFbsPanicGlyphDataIteratorInvalidState)); 
+    __ASSERT_DEBUG(aArrayIndices, Panic(EFbsPanicGlyphDataIteratorInvalidState));
+    TInt err = KErrNone;
+    
+    TUint glyphCodes[KMaxMetricsBatchSize];
+    for (TInt i = 0; i < aArrayIndicesCount; ++i)
+        {
+        glyphCodes[i] = iGlyphCodes[aArrayIndices[i]];
+        }
+    
+    TInt rcvdGlyphMetricsOffsets[KMaxMetricsBatchSize];
+    TPckg<TUint[KMaxMetricsBatchSize]> argGlyphCodes(glyphCodes);
+    TPckg<TInt[KMaxMetricsBatchSize]> argGlyphMetricsOffsets(rcvdGlyphMetricsOffsets);
+    if (aArrayIndicesCount < KMaxMetricsBatchSize)
+        {
+        argGlyphCodes.SetLength(aArrayIndicesCount * sizeof(TUint));
+        argGlyphMetricsOffsets.SetLength(aArrayIndicesCount * sizeof(TInt));
+        }   
+    err = aFont.iFbs->SendCommand(EFbsMessGetGlyphMetrics, TIpcArgs(aFont.iHandle, &argGlyphCodes, &argGlyphMetricsOffsets));
+    
+    if (err == KErrNone)
+        {
+        TInt numRcvdMetrics = argGlyphMetricsOffsets.Length() / sizeof(TInt);
+        __ASSERT_DEBUG(argGlyphMetricsOffsets.Length() % sizeof(TInt) == 0, Panic(EFbsPanicGlyphMetricsArrayInvalidState));
+        __ASSERT_DEBUG(numRcvdMetrics == aArrayIndicesCount, Panic(EFbsPanicGlyphMetricsArrayInvalidState));
+        
+        if (numRcvdMetrics == aArrayIndicesCount)
+            {
+            TInt arrayCount = aMetrics->Count();
+            TUint8* heapBase = aFont.iFbs->HeapBase();
+            for (TInt rcvdMetricsItem = 0; rcvdMetricsItem < numRcvdMetrics; ++rcvdMetricsItem)
+                {
+                TInt arrayIndex = aArrayIndices[rcvdMetricsItem];
+                // The array should never need to grow more than one item. If the difference is larger, 
+                // it means the glyph and the metrics are not in sync.
+                __ASSERT_DEBUG(arrayIndex <= arrayCount, Panic(EFbsPanicGlyphMetricsArrayInvalidState));
+                
+                TInt metricsOffset = rcvdGlyphMetricsOffsets[rcvdMetricsItem];              
+                const TOpenFontCharMetrics* metrics = (const TOpenFontCharMetrics*)(OffsetToPointer(metricsOffset, heapBase));
+                
+                if (arrayIndex < arrayCount)
+                    {
+                    // Copy metrics into existing element
+                    (*aMetrics)[arrayIndex] = *metrics;
+                    }
+                else if (arrayIndex == arrayCount)
+                    {
+                    // Memory should already be reserved by GetGlyphMetricsArray()
+                    (void) aMetrics->Append(*metrics);    
+                    ++arrayCount;
+                    }
+                }
+            }
+        else
+            {
+            // did not receive the same number of glyphs as was asked.
+            err = KErrGeneral;
+            }
+        }
+    return err;
+    }
+
+/**
+Closes the array, and releases the memory for the array. Calling Close() on an 
+already closed RFbsGlyphMetricsArray has no effect. 
+
+In the typical case where the array is a member of a class, Close() should only 
+be called in the destructor of that class.
+ */
+EXPORT_C void RFbsGlyphMetricsArray::Close()
+	{
+	iMetrics.Close();
+	}
+
+/**
+Retrieves the glyph metrics for the glyph which was at position aIndex in the 
+array passed to Get().
+
+@param aIndex The index of the entry in the array to access.
+@return The metrics for the glyph at the requested index.
+@panic FBSCLI 32, if aIndex is out of bounds.
+ */
+EXPORT_C const TOpenFontCharMetrics& RFbsGlyphMetricsArray::operator[](TInt aIndex) const
+	{
+	__ASSERT_ALWAYS(aIndex >= 0 && aIndex < iMetrics.Count(), Panic(EFbsPanicGlyphMetricsArrayOutOfBounds));
+	return (iMetrics)[aIndex];
+	}
+
+/**
+@return The number of glyph metrics held in the array.
+ */
+EXPORT_C TInt RFbsGlyphMetricsArray::Count() const
+	{
+	return iMetrics.Count();
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/fbsglyphmetricsarray.h	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,47 @@
+// Copyright (c) 2009-2010 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:
+//
+
+#ifndef FBSGLYPHMETRICSARRAY_H
+#define FBSGLYPHMETRICSARRAY_H
+
+#include <e32def.h>
+#include <openfont.h>
+#include <fbs.h>
+
+/**
+@publishedPartner
+@prototype
+*/
+NONSHARABLE_CLASS(RFbsGlyphMetricsArray)
+	{
+public:
+	IMPORT_C RFbsGlyphMetricsArray();
+	IMPORT_C TInt Get(CFbsFont& aFont, const TUint* aGlyphCodes, TInt aCount);
+	IMPORT_C void Close();
+	IMPORT_C TInt Count() const;
+	IMPORT_C const TOpenFontCharMetrics& operator[](TInt aIndex) const;
+	
+private:
+	RFbsGlyphMetricsArray(const RFbsGlyphMetricsArray&);
+	const RFbsGlyphMetricsArray& operator =(const RFbsGlyphMetricsArray&);
+	TInt SendRecvGlyphMetrics(CFbsFont& aFont, TUint* aArrayIndices, TInt aArrayIndicesCount, RArray<TOpenFontCharMetrics>* aMetrics) const;    
+	
+private:
+	RArray<TOpenFontCharMetrics> iMetrics;
+	const TUint* iGlyphCodes;
+	TInt iCount;
+	};
+
+#endif /* FBSGLYPHMETRICSARRAY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/fbsoogmmessage.h	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,45 @@
+// Copyright (c) 2010 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:
+//
+// Message class defining the action desired in response to a notification from
+// FBserv's Out-of-Graphics-Memory plug-in.
+//
+#ifndef FBSOOGMMESSAGE_H
+#define FBSOOGMMESSAGE_H
+
+
+class TFbsOogmMessage
+    {
+public:
+
+    enum TOogmAction
+        {
+        EFbsOogmNoAction = 0,
+        EFbsOogmLowNotification,
+        EFbsOogmOkayNotification
+        };
+
+public:
+    inline TFbsOogmMessage();
+    inline TFbsOogmMessage( TOogmAction aOogmAction, TInt aBytesToFree, TInt aFlags );
+
+public:
+    TOogmAction iOogmNotification;
+    TInt iBytesToFree;
+    TInt iFlags;
+    };
+
+
+#include <graphics/fbsoogmmessage.inl>
+#endif // FBSOOGMMESSAGE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/fbsoogmmessage.inl	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,33 @@
+// Copyright (c) 2010 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:
+//
+#ifndef FBSOOGMMESSAGE_INL
+#define FBSOOGMMESSAGE_INL
+
+const TInt KFbsOogmBytesToFreeNone = 0;
+const TInt KFbsOogmFlagsClear = 0;
+
+
+inline TFbsOogmMessage::TFbsOogmMessage()
+: iOogmNotification( EFbsOogmNoAction ), iBytesToFree( KFbsOogmBytesToFreeNone ), iFlags( KFbsOogmFlagsClear )
+    {
+    }
+
+
+inline TFbsOogmMessage::TFbsOogmMessage( TOogmAction aOogmAction, TInt aBytesToFree, TInt aFlags )
+: iOogmNotification( aOogmAction ), iBytesToFree( aBytesToFree), iFlags( aFlags )
+    {
+    }
+
+#endif // FBSOOGMMESSAGE_INL
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/fbsoogmplugin.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,162 @@
+/*
+* Copyright (c) 2010 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:  Graphics-Out-Of-Memory plugin for Font and Bitmap server.
+*
+*/
+
+#include <ecom/ecom.h>
+#include <ecom/implementationproxy.h>
+#include <graphics/fbsoogmmessage.h>
+#include <w32std.h>
+#include <FBS.H>
+
+#include "fbsoogmplugin.h"
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "fbsoogmpluginTraces.h"
+#endif
+
+
+/**
+ Called by the GOoM monitor framework in the case of low GPU memory.
+
+ Note: In the case of failure, this framework method will do so silently.
+
+ @param aBytesToFree The amount of GPU memory to be freed.
+ */
+void CFbsOogmMonitorPlugin::FreeRam( TInt aBytesToFree, TInt aFlags )
+    {
+    OstTrace0( TRACE_NORMAL, CFBSOOGMMONITORPLUGIN_FREERAM, "> " );
+
+    if ( (NULL == RFbsSession::GetSession()) )
+         {
+         if ( KErrNone != RFbsSession::Connect() )
+             {
+             OstTrace0( TRACE_NORMAL, DUP2_CFBSOOGMMONITORPLUGIN_FREERAM, "< No FbsSession" );
+
+             return;
+             }
+
+         }
+
+    TFbsOogmMessage oogmMessage( TFbsOogmMessage::EFbsOogmLowNotification, aBytesToFree, aFlags );
+    (void)RFbsSession::GetSession()->ConveyOogmMessage( oogmMessage );
+
+    OstTrace0( TRACE_NORMAL, DUP1_CFBSOOGMMONITORPLUGIN_FREERAM, "< " );
+    }
+
+
+
+/**
+ Called by the GOoM monitor framework in the case of normal GPU memory-usage being permissible.
+
+ Note: In the case of failure, this framework method will do so silently.
+ */
+void CFbsOogmMonitorPlugin::MemoryGood( TInt aFlags )
+    {
+    OstTrace0( TRACE_NORMAL, CFBSOOGMMONITORPLUGIN_MEMORYGOOD, ">" );
+
+    if ( (NULL == RFbsSession::GetSession()) )
+         {
+        if ( KErrNone != RFbsSession::Connect() )
+            {
+            OstTrace0( TRACE_NORMAL, DUP2_CFBSOOGMMONITORPLUGIN_MEMORYGOOD, "< No FbsSession" );
+
+            return;
+            }
+
+         }
+
+    const TInt KOogmDummyIntegerArgument = 0;
+    TFbsOogmMessage oogmMessage( TFbsOogmMessage::EFbsOogmOkayNotification, KOogmDummyIntegerArgument, aFlags );
+    (void)RFbsSession::GetSession()->ConveyOogmMessage( oogmMessage );
+
+	OstTrace0( TRACE_NORMAL, DUP1_CFBSOOGMMONITORPLUGIN_MEMORYGOOD, "<" );
+    }
+
+
+
+/**
+
+ */
+CFbsOogmMonitorPlugin::CFbsOogmMonitorPlugin()
+    {
+    }
+
+
+
+/**
+
+ */
+CFbsOogmMonitorPlugin::~CFbsOogmMonitorPlugin()
+    {
+    RFbsSession::Disconnect();
+    }
+
+
+
+/**
+
+ */
+void CFbsOogmMonitorPlugin::ConstructL()
+    {
+    CGOomMonitorPluginBase::ConstructL();
+    }
+
+
+
+/**
+
+ */
+TAny* CreatePlugin()
+    {
+    CFbsOogmMonitorPlugin* self = new CFbsOogmMonitorPlugin;
+    if ( self )
+        {
+        TRAPD( err, self->ConstructL() );
+        if ( err != KErrNone )
+            {
+            delete self;
+            self = NULL;
+            }
+        }
+
+    return self;
+    }
+
+
+
+/**
+
+ */
+const TImplementationProxy ImplementationTable[] =
+    {
+    { {0x2002B638}, ::CreatePlugin }
+    };
+
+
+
+/**
+
+ */
+EXPORT_C const TImplementationProxy* ImplementationGroupProxy( TInt& aTableCount )
+    {
+    OstTrace0( TRACE_NORMAL, _IMPLEMENTATIONGROUPPROXY, "> ::ImplementationGroupProxy" );
+    
+    aTableCount = sizeof( ImplementationTable ) / sizeof( TImplementationProxy ) ;
+    return ImplementationTable;
+    }
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/fbsoogmplugin.h	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,35 @@
+/*
+* Copyright (c) 2010 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:  Graphics-Out-Of-Memory plugin for Font and Bitmap server.
+*
+*/
+
+#ifndef FBSOOGMPLUGIN_H
+#define FBSOOGMPLUGIN_H
+
+#include <goommonitorplugin.h>
+
+class CFbsOogmMonitorPlugin : public CGOomMonitorPlugin
+    {
+public:
+    CFbsOogmMonitorPlugin();
+    ~CFbsOogmMonitorPlugin();
+    void ConstructL();
+
+public:
+    void FreeRam( TInt aBytesToFree, TInt aFlags );
+    void MemoryGood( TInt aFlags );
+    };
+
+#endif /* FBSOOGMPLUGIN_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/fbsoogmplugin.rss	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,53 @@
+/*
+* ============================================================================
+*  Name        : FbsOogmPlugin.rss
+*  Part of     : FbSrv OOGM Plugin
+*  Interface   :  
+*  Description : ECOM Resource file for Font and bitmap server OOGM Framework Plugin
+*
+*  Copyright © 2010 Nokia.  All rights reserved.
+*  This material, including documentation and any related computer
+*  programs, is protected by copyright controlled by Nokia.  All
+*  rights are reserved.  Copying, including reproducing, storing,
+*  adapting or translating, any or all of this material requires the
+*  prior written consent of Nokia.  This material also contains
+*  confidential information which may not be disclosed to others
+*  without the prior written consent of Nokia.
+* ============================================================================
+* Template version: 4.0
+*/
+
+#include <ecom/registryinfov2.rh>
+#include <goommonitorplugin.hrh>
+
+
+
+
+// ---------------------------------------------------------------------------
+// Registration info for ECOM framework.
+// ---------------------------------------------------------------------------
+//
+RESOURCE REGISTRY_INFO theInfo
+    {
+    resource_format_version = RESOURCE_FORMAT_VERSION_2; 
+    dll_uid = 0x2002B638;
+    interfaces = 
+        {
+        INTERFACE_INFO
+            {
+            interface_uid = KGOomPluginInterfaceUidValue;
+            implementations = 
+                {
+                IMPLEMENTATION_INFO
+                    {
+                    implementation_uid = 0x2002B638;
+                    version_no = 1;
+                    display_name = "FbsOogmPlugin";
+                    opaque_data = "";
+					default_data = "FbsOogmPlugin";
+                    }
+                };       
+            }
+        };
+    }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/glyphatlas.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,1060 @@
+// Copyright (c) 2009-2010 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:
+//
+
+#include "glyphatlas.h"
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "glyphatlasTraces.h"
+#endif
+
+
+extern void Panic(TFbsPanic aPanic);
+
+static TInt16 Load16(const TUint8* aPtr);
+static void DecodeBinaryData(const TSize& aGlyphSize, const TUint8* aEncodedData, TUint8* aByteData);
+static void DecodeBinaryDataExLarge(const TSize& aGlyphSize, const TUint8* aEncodedData, TUint8* aByteData);
+static void Convert1BppTo8Bpp(TUint32 aSrcData, TUint8*& aDestDataPtr, const TUint8* aDestDataPtrLimit);
+static void CopyCharLine(TUint8*& aByteDataPtr, TInt aWidthInBytes, const TUint8* aSrcData, TInt aBitShift, TInt16 aRepeatCount);
+
+// === CGlyphAtlas Functions ===
+
+/**
+Glyph Atlas constructor.
+@param aMaxCacheSizeInBytes The maximum amount of specialised graphics memory 
+	that the glyph atlas should use. If this value is KGlyphAtlasNoCacheLimit,
+	then there is no limit and the atlas will use as much memory as is available
+	in the system.
+*/
+CGlyphAtlas::CGlyphAtlas(TInt aMaxCacheSizeInBytes)
+	:iLruPageList(_FOFF(CGlyphAtlasPage, iLink)),
+	 iFontEntryArray(32, _FOFF(TFontEntryMap, iFont)),
+	 iMaxCacheSizeInBytes(aMaxCacheSizeInBytes),
+	 iMaxCacheSizeHigh(aMaxCacheSizeInBytes),
+	 iGpuCacheSizeLimitIsMax(ETrue)
+	{
+    iMaxCacheSizeLow = ( KGlyphAtlasNoCacheLimit == aMaxCacheSizeInBytes )
+                     ? KGlyphAtlasLowMemCacheLimitDefault
+                     : ( aMaxCacheSizeInBytes / KGlyphAtlasLowMemCacheLimitDivisor );
+	}
+
+/**
+Glyph Atlas destructor.
+Frees all the RSgImage handles, frees all the allocated system memory, and
+closes the Graphics Resource driver. 
+*/
+CGlyphAtlas::~CGlyphAtlas()
+	{
+	// cycle through all the font entries and destroy them
+	for (TInt ii = iFontEntryArray.Count()-1; ii >= 0; --ii)
+		{
+		DeleteFontEntry(iFontEntryArray[ii].iEntry);
+		}
+	iFontEntryArray.Close();
+	__ASSERT_DEBUG(iLruPageList.IsEmpty(), Panic(EFbsPanicGlyphAtlasInconsistentState));
+	
+	// there shouldn't be any remaining pages, but if there are, destroy them.
+	while (!iLruPageList.IsEmpty())
+		{
+		delete iLruPageList.First();
+		}
+	iSgDriver.Close();
+	}
+
+/**
+Factory constructor method. Creates a new glyph atlas.
+
+@param aMaxCacheSizeInBytes The size in bytes, to use as the upper limit
+	for the size of memory used by the glyph images in the atlas. If this
+	value is KGlyphAtlasNoCacheLimit, then there is no limit and the atlas
+	will use as much memory as is available in the system.
+
+@return A pointer to the newly-constructed atlas
+
+@leave KErrNoMemory if there was insufficient memory to create the atlas, 
+	or a system wide error code if its RSgDriver failed to open.
+*/
+CGlyphAtlas* CGlyphAtlas::NewL(TInt aMaxCacheSizeInBytes)
+	{
+	CGlyphAtlas* self = new (ELeave) CGlyphAtlas(aMaxCacheSizeInBytes);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(); // self;
+	return self;
+	}
+
+/**
+Two-phase constructor.
+@leave A system wide error code if RSgDriver failed to open.
+*/
+void CGlyphAtlas::ConstructL()
+	{
+	User::LeaveIfError(iSgDriver.Open());
+	}
+
+/**
+Retrieves a glyph from the atlas.
+If the glyph is found, the glyph data passed in is populated.
+
+@param[in] aFont The font the glyph belongs to.
+@param[in] aGlyphCode The glyph code for the glyph being requested.
+@param[out] aGlyphImageInfo The glyph image information if this function is successful.
+@return KErrNone if the glyph is found, KErrNotFound if not. 
+*/
+TInt CGlyphAtlas::GetGlyph(const CBitmapFont& aFont, TUint aGlyphCode, TGlyphImageInfo& aGlyphImageInfo)
+	{
+    OstTraceExt2( TRACE_NORMAL, CGLYPHATLAS_GETGLYPH, "> f=%x; gc=%04x",(TUint)&aFont, aGlyphCode);
+    
+	CGlyphAtlasFontEntry* fontEntry = FindFontEntry(aFont);
+	if (!fontEntry)
+		{
+        OstTrace0( TRACE_NORMAL, CGLYPHATLAS_GETGLYPH_END2, "< KErrNotFound");
+		return KErrNotFound;
+		}
+	TInt err = fontEntry->GetGlyph(aGlyphCode, aGlyphImageInfo);
+	
+	OstTraceExt5( TRACE_NORMAL, CGLYPHATLAS_GETGLYPH_END1, "< id=%08x%08x; w=%u; h=%u; err=%d", 
+	        (TUint)I64HIGH(aGlyphImageInfo.iImageId.iId), (TUint)I64LOW(aGlyphImageInfo.iImageId.iId),
+	        (TUint)aGlyphImageInfo.iMetrics.Width(), (TUint)aGlyphImageInfo.iMetrics.Height(), (TInt)err);
+	
+	return err;
+	}
+
+/**
+Adds a glyph to the atlas from a bitmap glyph and retrieves the glyph data.
+If there is insufficient memory to create a RSgImage, then the least recently 
+used pages (and all the glyphs contained within) are removed until there is 
+enough memory to continue.
+
+@param[in] aFont The font the glyph belongs to.
+@param[in] aArgs The information needed to create a glyph.
+@param[out] aGlyphImageInfo Upon return contains all the glyph image information needed to use the 
+		glyph in another process.
+@return KErrNone if the glyph was successfully added or other system-wide error.
+*/
+TInt CGlyphAtlas::AddGlyph(const CBitmapFont& aFont, const TAddGlyphArgs& aArgs, TGlyphImageInfo& aGlyphImageInfo)
+	{
+	OstTraceDefExt5( OST_TRACE_CATEGORY_DEBUG, TRACE_NORMAL, CGLYPHATLAS_ADDGLYPH, "> f=%x; bp=%08x; gc=%04x; w=%u; h=%u", 
+	        (TUint)&aFont, (TUint)aArgs.iBitmapPointer, aArgs.iGlyphCode, 
+	        aArgs.iMetrics->Width(), aArgs.iMetrics->Height());
+	
+    // Find font entry and create if none found
+	CGlyphAtlasFontEntry* fontEntry = FindFontEntry(aFont);
+	TBool isNewFont = EFalse;
+	if (!fontEntry)
+		{
+		// Create a new font.
+		fontEntry = CreateFontEntry(aFont);
+		if (!fontEntry)
+			{
+            OstTraceDef0(OST_TRACE_CATEGORY_DEBUG, TRACE_NORMAL, CGLYPHATLAS_ADDGLYPH_END2, "< KErrNoMemory");
+			return KErrNoMemory;
+			}
+		isNewFont = ETrue;
+		}
+	TInt glyphSizeInBytes = 0;
+	TInt err = fontEntry->AddGlyph(aArgs, aGlyphImageInfo, glyphSizeInBytes);
+	if (KErrNone != err)
+		{
+		if (isNewFont)
+			{
+			DeleteFontEntry(fontEntry);
+			}
+		OstTraceDef1(OST_TRACE_CATEGORY_DEBUG, TRACE_NORMAL, CGLYPHATLAS_ADDGLYPH_END3, "< err=%d", err);
+		return err;
+		}
+	iCacheSizeInBytes += glyphSizeInBytes;
+
+	// If there is a cache limit and it is now exceeded, remove the least
+	// recently used pages until the cache size is within the upper limit. Do 
+	// not remove the page relating to the glyph which is being added, which is 
+	// now at the head of the LRU array.
+	if (iMaxCacheSizeInBytes != KGlyphAtlasNoCacheLimit)
+		{
+		TBool morePagesToDelete = ETrue;
+		while ((iCacheSizeInBytes > iMaxCacheSizeInBytes) && morePagesToDelete)
+			{
+			morePagesToDelete = DeleteLeastRecentlyUsedPage(EFalse);
+			}
+		}
+	
+	OstTraceDefExt2(OST_TRACE_CATEGORY_DEBUG, TRACE_NORMAL, CGLYPHATLAS_ADDGLYPH_END1, "< id=%08x%08x", 
+	            I64HIGH(aGlyphImageInfo.iImageId.iId), I64LOW(aGlyphImageInfo.iImageId.iId));
+    
+	return KErrNone;
+	}
+
+/**
+Releases all glyphs associated with a particular font when it has been
+released by the font system.
+
+@param aFont The font which is released.
+ */
+void CGlyphAtlas::FontReleased(const CBitmapFont& aFont)
+	{
+	OstTraceDef1(OST_TRACE_CATEGORY_DEBUG, TRACE_NORMAL, CGLYPHATLAS_FONTRELEASED, "> f=%x", (TUint)&aFont);
+	
+    TInt index = iFontEntryArray.FindInUnsignedKeyOrder(TFontEntryMap(&aFont, NULL));
+	if (KErrNotFound == index)
+		{
+        OstTraceDef0(OST_TRACE_CATEGORY_DEBUG, TRACE_NORMAL, CGLYPHATLAS_FONTRELEASED_END2, "< KErrNotFound");
+		return;
+		}
+	CGlyphAtlasFontEntry* fontEntry = iFontEntryArray[index].iEntry;
+	iCacheSizeInBytes -= fontEntry->SizeInBytes();
+	delete fontEntry;
+	iFontEntryArray.Remove(index);
+	OstTraceDef0(OST_TRACE_CATEGORY_DEBUG, TRACE_NORMAL, CGLYPHATLAS_FONTRELEASED_END3, "< KErrNone");
+	}
+
+/**
+Searches the array of font entries to find the entry for the given font.
+If the font entry is found, the entry is returned. If not a NULL pointer is 
+returned.
+
+@param aFont The font to match an entry with.
+@return The font entry if a match is found, NULL if not. 
+*/
+CGlyphAtlasFontEntry* CGlyphAtlas::FindFontEntry(const CBitmapFont& aFont) const
+	{
+	TFontEntryMap entryToMatch(&aFont, NULL);
+	TInt index = iFontEntryArray.FindInUnsignedKeyOrder(entryToMatch);
+	if (KErrNotFound == index)
+		{
+		return NULL;
+		}
+	return iFontEntryArray[index].iEntry;
+	}
+
+/**
+Deletes the given font entry.
+The mapping from the font to the font entry is removed.
+
+@param aFontEntry The entry to delete.
+*/
+void CGlyphAtlas::DeleteFontEntry(CGlyphAtlasFontEntry* aFontEntry)
+	{
+    __ASSERT_DEBUG(aFontEntry, Panic(EFbsPanicGlyphAtlasInconsistentState));
+    TInt index = iFontEntryArray.FindInUnsignedKeyOrder(TFontEntryMap(&aFontEntry->Font(), NULL));
+    __ASSERT_DEBUG(KErrNotFound != index, Panic(EFbsPanicGlyphAtlasInconsistentState));
+    if (KErrNotFound != index)
+        {
+        iFontEntryArray.Remove(index);
+        }
+    iCacheSizeInBytes -= aFontEntry->SizeInBytes();
+    delete aFontEntry;
+	}
+
+/**
+Moves the given page to the front (the position of the most recently used page) 
+of the usage order list.
+
+@param aPage The most recently used page.
+*/
+void CGlyphAtlas::MovePageToFront(CGlyphAtlasPage& aPage)
+	{
+	aPage.MoveToFirstInQueue(iLruPageList);
+	}
+
+/**
+Creates a font entry from the given font and adds a mapping from the font 
+to the font entry.
+If successful, the font entry is returned.
+If either the creation of the font entry or the adding the mapping fails, then 
+a NULL pointer is returned.
+
+@param aFont The font used to create a font entry from.
+@return A new font entry if successful, NULL if not.
+*/
+CGlyphAtlasFontEntry* CGlyphAtlas::CreateFontEntry(const CBitmapFont& aFont)
+	{
+	CGlyphAtlasFontEntry* fontEntry = new CGlyphAtlasFontEntry(aFont, *this);
+	if (!fontEntry)
+		{
+		return NULL;
+		}
+	// Add font entry to font entry array
+	TFontEntryMap fontEntryMap(&aFont, fontEntry);
+	TInt err = iFontEntryArray.InsertInUnsignedKeyOrder(fontEntryMap);
+	__ASSERT_DEBUG(KErrAlreadyExists != err, Panic(EFbsPanicGlyphAtlasInconsistentState));
+	if (KErrNone != err)
+		{
+		delete fontEntry;
+		fontEntry = NULL;
+		}
+	return fontEntry;
+	}
+
+/**
+Deletes the least recently used page and removes it from the list of pages
+held by the atlas.
+
+@param aAllowMruPageDeletion ETrue if the most recently used page can be deleted, 
+	EFalse otherwise.
+@return ETrue, if there are pages remaining in the atlas after the deletion, EFalse
+	otherwise. If there is only one page in the atlas and aAllowMruPageDeletion is EFalse,
+	EFalse is returned. 
+*/
+TBool CGlyphAtlas::DeleteLeastRecentlyUsedPage(TBool aAllowMruPageDeletion)
+	{
+    OstTraceDef1(OST_TRACE_CATEGORY_DEBUG, TRACE_NORMAL, CGLYPHATLAS_DELETELEASTRECENTLYUSEDPAGE, "> mru=%d", aAllowMruPageDeletion );
+    
+	CGlyphAtlasPage* lruPage = NULL;
+	if (!iLruPageList.IsEmpty())
+		{
+		lruPage = iLruPageList.Last();
+		if (!aAllowMruPageDeletion && (lruPage == iLruPageList.First()))
+			{
+			lruPage = NULL;
+			}
+		}
+	TBool canDeleteMorePages = EFalse;
+	if (lruPage)
+		{
+		iCacheSizeInBytes -= lruPage->SizeInBytes();
+		CGlyphAtlasFontEntry& fontEntry = lruPage->FontEntry();
+		fontEntry.DeletePage(lruPage);
+		lruPage = NULL;
+		if (fontEntry.IsEmpty())
+			{
+			DeleteFontEntry(&fontEntry);
+			}
+		canDeleteMorePages = !iLruPageList.IsEmpty();
+		}
+	OstTraceDefExt2(OST_TRACE_CATEGORY_DEBUG, TRACE_NORMAL, CGLYPHATLAS_DELETELEASTRECENTLYUSEDPAGE_END, "< more=%u; size=%u", (TUint)canDeleteMorePages, iCacheSizeInBytes);
+	return canDeleteMorePages;
+	}
+
+/**
+Utility function that calculates the number of unique fonts associated with the atlas.
+@return Number of fonts in the atlas.
+ */
+TInt CGlyphAtlas::FontCount() const
+	{
+	return iFontEntryArray.Count();
+	}
+
+/**
+Utility function that calculates the number of glyphs across all fonts stored in
+the atlas.
+@return Number of glyphs in the atlas.
+ */
+TInt CGlyphAtlas::GlyphCount() const
+	{
+	TInt glyphCount = 0;
+	for (TInt ii = iFontEntryArray.Count() - 1; ii >= 0; --ii)
+		{
+		glyphCount += iFontEntryArray[ii].iEntry->GlyphCount();
+		}
+	return glyphCount;
+	}
+
+/**
+Utility function that calculates the number of glyphs for a given font in the atlas.
+@param The font to return the number of glyphs for.
+@return Number of glyphs in the atlas.
+ */
+TInt CGlyphAtlas::GlyphCount(const CBitmapFont& aFont) const
+	{
+	CGlyphAtlasFontEntry* fontEntry = FindFontEntry(aFont);
+	return (fontEntry) ? fontEntry->GlyphCount() : 0;
+	}
+
+void CGlyphAtlas::GetGlyphCacheMetrics( TGlyphCacheMetrics& aGlyphCacheMetrics )
+    {
+    aGlyphCacheMetrics.iMaxCacheSizeInBytes = iMaxCacheSizeInBytes;
+    aGlyphCacheMetrics.iMaxCacheSizeHigh = iMaxCacheSizeHigh;
+    aGlyphCacheMetrics.iMaxCacheSizeLow = iMaxCacheSizeLow;
+    aGlyphCacheMetrics.iCacheSizeInBytes = iCacheSizeInBytes;
+    aGlyphCacheMetrics.iGpuCacheSizeLimitIsMax = iGpuCacheSizeLimitIsMax;
+    }
+
+/**
+ Function to release the GPU cache. Called in response to the GoomMonitor's
+ requirement to reduce GPU memory use.
+
+ @param aBytes. The amount of memory the GOoM framework would like us to relinquish.
+ @param aFlags. The flags conveyed from the GOoM monitor framework.
+*/
+void CGlyphAtlas::ReleaseGpuMemory( TInt /*aBytes*/, TInt /*aFlags*/ )
+    {
+    OstTraceDefExt2( OST_TRACE_CATEGORY_DEBUG, TRACE_NORMAL, CGLYPHATLAS_RELEASEGPUMEMORY, "> max=%d; size=%d", iMaxCacheSizeInBytes, iCacheSizeInBytes);
+
+    if ( iCacheSizeInBytes > 0 )
+        {
+        while( DeleteLeastRecentlyUsedPage(ETrue) )
+            {
+            // Do nothing
+            }
+        }
+
+    // If appropriate, reduce the cache-size limit.
+    if ( GpuCacheSizeLimitIsMax() )
+        {
+        SwitchGpuCacheSizeLimit();
+        }
+
+    OstTraceDefExt2( OST_TRACE_CATEGORY_DEBUG, TRACE_NORMAL, CGLYPHATLAS_RELEASEGPUMEMORY_EXIT, "< max=%d; size=%d", iMaxCacheSizeInBytes, iCacheSizeInBytes);
+    }
+
+/**
+ Function to establish GPU memory use. Called in response to the GoomMonitor's
+ notification that GPU memory may once more be utilised in the usual manner.
+
+ @param aFlags. The flags conveyed from the GOoM monitor framework.
+ */
+void CGlyphAtlas::InstateGpuMemory( TInt /*aFlags*/ )
+    {
+    OstTraceDef1(OST_TRACE_CATEGORY_DEBUG, TRACE_NORMAL, CGLYPHATLAS_INSTATEGPUMEMORY, "> max=%d", iMaxCacheSizeInBytes );
+
+    // If appropriate, reinstate the full cache-size limit.
+    if ( !GpuCacheSizeLimitIsMax() )
+        {
+        SwitchGpuCacheSizeLimit();
+        }
+
+    OstTraceDef1(OST_TRACE_CATEGORY_DEBUG, TRACE_NORMAL, CGLYPHATLAS_INSTATEGPUMEMORY_EXIT, "< max=%d", iMaxCacheSizeInBytes );
+    }
+
+/**
+ Utility function to toggle between full and reduced GPU cache-size limits.
+
+ Use in conjunction with TBool GpuCacheSizeLimitIsMax()
+ */
+void CGlyphAtlas::SwitchGpuCacheSizeLimit()
+    {
+    if ( GpuCacheSizeLimitIsMax() )
+        {
+        // The short-circuit operator obviates tautological conditionals.
+        while ( (iCacheSizeInBytes >= iMaxCacheSizeLow) && DeleteLeastRecentlyUsedPage(ETrue) )
+            {
+            // Do Nothing...
+            }
+
+        iMaxCacheSizeInBytes = iMaxCacheSizeLow;
+        iGpuCacheSizeLimitIsMax = EFalse;
+        }
+    else
+        {
+        iMaxCacheSizeInBytes = iMaxCacheSizeHigh;
+        iGpuCacheSizeLimitIsMax = ETrue;
+        }
+    }
+
+
+/**
+ Utility function to report whether the GPU cache-size limit is set to the maximum permissible
+ level, or to its reduced level.
+
+ @return ETrue if the cache-size is set to the maximum permissible limit.
+         EFalse if it is set to the reduced limit.
+ */
+TBool CGlyphAtlas::GpuCacheSizeLimitIsMax() const
+    {
+    return iGpuCacheSizeLimitIsMax;
+    }
+
+// === CGlyphAtlasFontEntry Functions ===
+/**
+Font entry constructor.
+
+@param aFont The font to which this font entry should be associated.
+@param aGlyphAtlas The glyph atlas to which this font entry belongs.
+*/
+CGlyphAtlasFontEntry::CGlyphAtlasFontEntry(const CBitmapFont& aFont, CGlyphAtlas& aGlyphAtlas)
+	:iFont(aFont),
+	 iPageArray(32, _FOFF(TPageMap, iGlyphCode)),
+	 iAtlas(aGlyphAtlas)
+	{
+	}
+
+/**
+Font entry destructor.
+Destroys the pages owned by the font entry.
+*/
+CGlyphAtlasFontEntry::~CGlyphAtlasFontEntry()
+	{
+	// cycle through all the font entries and destroy them
+	for (TInt ii = iPageArray.Count()-1; ii >= 0; --ii)
+		{
+		DeletePage(iPageArray[ii].iPage);
+		}
+	__ASSERT_DEBUG(iSizeInBytes == 0, Panic(EFbsPanicGlyphAtlasInconsistentState));
+	iPageArray.Close();
+	}
+
+/**
+Deletes the given page.
+The page mapping is removed and the page is deleted.
+
+@param aPage The page to delete.
+*/
+void CGlyphAtlasFontEntry::DeletePage(CGlyphAtlasPage* aPage)
+	{
+    __ASSERT_DEBUG(aPage, Panic(EFbsPanicGlyphAtlasInconsistentState));
+    __ASSERT_DEBUG(iPageArray.Count() > 0, Panic(EFbsPanicGlyphAtlasInconsistentState));
+		
+    TInt numGlyphsInPage = aPage->GlyphCount();
+
+    for (TInt ii = 0; ii < numGlyphsInPage; ++ii)
+        {
+        TInt index = iPageArray.FindInUnsignedKeyOrder(TPageMap(aPage->GlyphCodeAt(ii), NULL));
+
+        __ASSERT_DEBUG(KErrNotFound != index, Panic(EFbsPanicGlyphAtlasInconsistentState));
+
+        if (KErrNotFound != index)
+            {
+            iPageArray.Remove(index);
+            iPageArray.GranularCompress();
+            }
+        }
+    iSizeInBytes -= aPage->SizeInBytes();
+    delete aPage;
+
+	}
+
+/**
+Adds a glyph to the font from a bitmap glyph and gets the glyph image info back.
+
+@param[in] aArgs The information needed to create a glyph.
+@param[out] aGlyphImageInfo Upon return contains all the glyph image information needed to use the 
+		glyph in another process.
+@param[out] aSizeInBytes Upon return contains the size of the added glyph's image data in bytes.
+@return KErrNone if the glyph was successfully added or other system-wide error.
+*/
+TInt CGlyphAtlasFontEntry::AddGlyph(const CGlyphAtlas::TAddGlyphArgs& aArgs, TGlyphImageInfo& aGlyphImageInfo, TInt& aSizeInBytes)
+	{
+    CGlyphAtlasPage* newPage = new CGlyphAtlasPage(*this);
+	if (!newPage)
+		{
+		return KErrNoMemory;
+		}
+	
+	TInt err = newPage->AddGlyph(aArgs, aGlyphImageInfo, aSizeInBytes);
+	if (KErrNone != err)
+		{
+		delete newPage;
+		return err;
+		}
+
+	err = iPageArray.InsertInUnsignedKeyOrder(TPageMap(aArgs.iGlyphCode, newPage));
+	__ASSERT_DEBUG(KErrAlreadyExists != err, Panic(EFbsPanicGlyphAtlasInconsistentState));
+	if (KErrNone != err)
+		{
+		delete newPage;
+		return err;
+		}
+	iSizeInBytes += aSizeInBytes;
+	iAtlas.MovePageToFront(*newPage);
+	return err;
+	}
+
+/**
+Searches the array of pages to find the page containing the given glyph.
+If the page is found, the glyph image info is populated and the page is moved 
+to the front of the Glyph Atlas' LRU page array.
+
+@param[in] aGlyphCode The glyph code for the glyph being requested.
+@param[out] aGlyphImageInfo Upon return contains all the glyph image information needed to use the 
+		glyph in another process.
+@return KErrNone if the glyph was found, KErrNotFound if not. 
+*/
+TInt CGlyphAtlasFontEntry::GetGlyph(TUint aGlyphCode, TGlyphImageInfo& aGlyphImageInfo)
+	{
+	TInt index = iPageArray.FindInUnsignedKeyOrder(TPageMap(aGlyphCode, NULL));
+	if (KErrNotFound == index)
+		{
+		return KErrNotFound;
+		}
+	CGlyphAtlasPage* page = iPageArray[index].iPage;
+	page->GetGlyph(aGlyphCode, aGlyphImageInfo);
+	iAtlas.MovePageToFront(*page);
+	return KErrNone;
+	}
+
+/**
+Gets the font associated with the font entry.
+
+@return The font associated with this entry. 
+*/
+const CBitmapFont& CGlyphAtlasFontEntry::Font() const
+	{
+	return iFont;
+	}
+
+/**
+Gets the amount of memory allocated for all the image data for this font.
+
+@return The size of the font's image data in bytes.
+*/
+TInt CGlyphAtlasFontEntry::SizeInBytes() const
+	{
+	return iSizeInBytes;
+	}
+
+/**
+Tests whether the font entry has any pages.
+
+@return ETrue if the font entry does not contain any pages, EFalse if it does..
+*/
+TBool CGlyphAtlasFontEntry::IsEmpty() const
+	{
+	if (iPageArray.Count() == 0)
+		{
+		__ASSERT_DEBUG(iSizeInBytes == 0, Panic(EFbsPanicGlyphAtlasInconsistentState));
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+/**
+Gets the glyph atlas the font entry belongs to.
+
+@return The font entry's glyph atlas.
+*/
+CGlyphAtlas& CGlyphAtlasFontEntry::GlyphAtlas() const
+	{
+	return iAtlas;
+	}
+
+/** 
+@return The number of glyphs this font entry has.
+ */
+TInt CGlyphAtlasFontEntry::GlyphCount() const
+	{
+	TInt glyphCount = 0;
+	for (TInt ii = iPageArray.Count() - 1; ii >= 0; --ii)
+		{
+		glyphCount += iPageArray[ii].iPage->GlyphCount();
+		}
+	return glyphCount;
+	}
+
+
+// === CGlyphAtlasPage Functions ===
+
+/**
+Page constructor.
+
+@param aFontEntry The font entry to which the page is associated.
+*/
+CGlyphAtlasPage::CGlyphAtlasPage(CGlyphAtlasFontEntry& aFontEntry)
+	:iFontEntry(aFontEntry)
+	{
+	}
+
+/**
+Page destructor.
+Releases the RSgImage handles held by the page.
+Removes the page from the Glyph Atlas' LRU page array. 
+*/
+CGlyphAtlasPage::~CGlyphAtlasPage()
+	{
+	iLink.Deque();
+	iGlyphImage.Close();
+	}
+
+/**
+Adds a glyph to the page from a bitmap glyph and gets the glyph image info back.
+An RSgImage handle is acquired for the glyph. 
+If there is not enough specialised graphics memory to create a RSgImage, then the
+least recently used pages are deleted until there there is either enough memory 
+for the creation to be successful or if there are no more pages to delete (in 
+which case an appropriate out of memory error message is returned). 
+
+@param[in] aArgs The information needed to create a glyph.
+@param[out] aGlyphImageInfo Upon return contains all the glyph image information needed to use the 
+		glyph in another process.
+@param[out] aSizeInBytes Upon return contains the size of the added glyph's image data in bytes.
+@return KErrNone if the glyph was successfully added; 
+	KErrNoMemory if there is not enough system memory available;
+	KErrNoGraphicsMemory if there is not enough specialised graphics memory available.
+*/
+TInt CGlyphAtlasPage::AddGlyph(const CGlyphAtlas::TAddGlyphArgs& aArgs, TGlyphImageInfo& aGlyphImageInfo, TInt& aSizeInBytes)
+	{
+	const TSize glyphSize(aArgs.iMetrics->Width(), aArgs.iMetrics->Height());
+	// If glyph has zero size (e.g. space), set glyph data and return 
+	if (glyphSize.iWidth == 0 || glyphSize.iHeight == 0)
+		{
+		iPosX = 0;
+		iPosY = 0;
+		iMetrics = *aArgs.iMetrics;
+		iGlyphCode = aArgs.iGlyphCode;
+		iSizeInBytes = 0;
+		iNumGlyphs++;
+		aGlyphImageInfo.iImageId = KSgNullDrawableId;
+		aGlyphImageInfo.iPosX = iPosX;
+		aGlyphImageInfo.iPosY = iPosY;
+		aGlyphImageInfo.iMetrics = iMetrics;
+		return KErrNone;
+		}
+	TUint8* buf = NULL;
+	TSgImageInfo info;
+	info.iSizeInPixels = glyphSize;
+	info.iUsage = ESgUsageBitOpenVgImage;
+	info.iPixelFormat = EUidPixelFormatA_8;
+	TInt dataStride = 0;
+	const TInt KDataArraySize = 256;
+	TUint8 byteDataArray[KDataArraySize];
+	TUint8* tempBuf = NULL;
+	TUint8* byteDataBuf = NULL;
+	TGlyphBitmapType glyphBitmapType = iFontEntry.Font().GlyphBitmapType(); 
+
+	switch (glyphBitmapType)
+		{
+		case EMonochromeGlyphBitmap:
+			// Decompress to 8bpp buffer
+			dataStride = glyphSize.iWidth;
+			byteDataBuf = byteDataArray;
+			// If data too big to fit in byteDataArray, allocate memory on the heap
+			if (glyphSize.iHeight * glyphSize.iWidth > KDataArraySize)
+				{
+				tempBuf = (TUint8*) User::AllocZ(dataStride * glyphSize.iHeight);
+				if (!tempBuf)
+					{
+					return KErrNoMemory;
+					}
+				byteDataBuf = tempBuf;
+				}
+			else
+				{
+				// fill array with zeros.
+				Mem::FillZ(&byteDataArray, KDataArraySize);
+				}
+			
+			if (glyphSize.iWidth >32)
+				{
+				DecodeBinaryDataExLarge(glyphSize, aArgs.iBitmapPointer, byteDataBuf);
+				}
+			else
+				{
+				DecodeBinaryData(glyphSize, aArgs.iBitmapPointer, byteDataBuf);
+				}
+			buf = byteDataBuf;
+			break;
+		case EAntiAliasedGlyphBitmap:
+			buf = const_cast<TUint8*>(aArgs.iBitmapPointer);
+			dataStride = glyphSize.iWidth;
+			break;
+		default:
+			return KErrNotSupported;
+		}
+
+	TInt err = iGlyphImage.Create(info, buf, dataStride);
+
+	// If RSgImage creation fails due to out of memory, delete the least
+	// recently used pages to free up memory until either creation succeeds or 
+	// there are no more pages to remove.
+	TBool morePagesToDelete = ETrue;
+	while ((KErrNoGraphicsMemory == err || KErrNoMemory == err) && morePagesToDelete)
+		{
+		// Delete least used page.  Can delete all pages if necessary as this  
+		// page has not been added to the LRU array yet.
+		morePagesToDelete = iFontEntry.GlyphAtlas().DeleteLeastRecentlyUsedPage(ETrue);
+		err = iGlyphImage.Create(info, buf, dataStride);
+		}
+
+	User::Free(tempBuf);
+	
+	if (KErrNone != err)
+		{
+		return err;
+		}
+	aSizeInBytes = glyphSize.iHeight * glyphSize.iWidth;
+	iGlyphCode = aArgs.iGlyphCode;
+	iPosX = 0;
+	iPosY = 0;
+	iMetrics = *aArgs.iMetrics;
+	// As the image is stored as one byte per pixel, the size in bytes is 
+	// just the number of pixels.
+	// TODO: Replace estimating size with call to SgImage/SgDriver to get accurate size.
+	iSizeInBytes += aSizeInBytes;
+	iNumGlyphs++;
+	aGlyphImageInfo.iPosX = iPosX;
+	aGlyphImageInfo.iPosY = iPosY;
+	aGlyphImageInfo.iImageId = iGlyphImage.Id();
+	aGlyphImageInfo.iMetrics = iMetrics;
+	return err;
+	}
+
+/**
+Retrieves the glyph image information for the given glyph code necessary to be 
+able to use the glyph in another process.
+
+@param aGlyphCode The glyph code for the glyph being requested
+@param aGlyphImageInfo Upon return contains all the glyph image information needed to use the 
+		glyph in another process if the glyph is contained in the page.
+*/
+void CGlyphAtlasPage::GetGlyph(TUint aGlyphCode, TGlyphImageInfo& aGlyphImageInfo) const
+	{
+	__ASSERT_DEBUG(iGlyphCode == aGlyphCode, Panic(EFbsPanicGlyphAtlasInconsistentState));
+	aGlyphImageInfo.iMetrics = iMetrics;
+	aGlyphImageInfo.iPosX = iPosX;
+	aGlyphImageInfo.iPosY = iPosY;
+	aGlyphImageInfo.iImageId = iGlyphImage.Id();
+	}
+
+/**
+Gets the amount of memory allocated for the image data for this page.
+
+@return The size of the page's image data in bytes.
+*/
+TInt CGlyphAtlasPage::SizeInBytes() const
+	{
+	return iSizeInBytes;
+	}
+
+/**
+Gets the glyph code at the given index associated with the page.
+
+@param aIndex The index of the glyph code within the page.
+@return The glyph code at the given index.
+*/
+TUint CGlyphAtlasPage::GlyphCodeAt(TInt aIndex) const
+	{
+	__ASSERT_DEBUG(0 == aIndex, Panic(EFbsPanicGlyphAtlasInconsistentState));
+	return iGlyphCode;
+	}
+
+/**
+Gets the number of glyphs stored in the page.
+
+@return The number of glyphs in the page.
+*/
+TInt CGlyphAtlasPage::GlyphCount() const
+	{
+	return iNumGlyphs;
+	}
+
+/**
+Gets the font entry which owns the page.
+
+@return The font entry which owns the page. 
+*/
+CGlyphAtlasFontEntry& CGlyphAtlasPage::FontEntry() const
+	{
+	return iFontEntry;
+	}
+
+
+void CGlyphAtlasPage::MoveToFirstInQueue(TDblQue<CGlyphAtlasPage>& aList)
+	{
+	if(!aList.IsFirst(this))
+		{
+		iLink.Deque();
+		aList.AddFirst(*this);
+		}
+	}
+
+// === Static Utility Functions ===
+
+/**
+Combines 2 8-bit unsigned integers into a 16-bit integer.
+@param aPtr A pointer to a source buffer of 2 8-bit unsigned integers.
+@return The two 8-bit integers combined into a 16-bit integer.
+*/
+static TInt16 Load16(const TUint8* aPtr)
+	{
+	return TInt16(aPtr[0]+(aPtr[1]<<8)); 
+	}
+
+/**
+Decodes binary data for monochrome glyph bitmap.
+
+@param aGlyphSize size of glyph in pixels.
+@param aEncodedData Pointer to an encoded source buffer.
+@param aByteData Pointer to a destination buffer (8 bits per pixel).
+*/
+void DecodeBinaryData(const TSize& aGlyphSize, const TUint8* aEncodedData, TUint8* aByteData)
+	{
+	const TInt dataHeight = aGlyphSize.iHeight;
+	const TInt dataWidth = aGlyphSize.iWidth;
+	TUint32 binaryData = 0;
+	
+	// The data is encoded as follows:
+	// 1 bit for a multiple lines flag (1=yes)
+	// 4 bits for a repeat count which represents:
+	// -if the multiple line flag is 0 the number of lines whose data is repeated
+	// -if the flag is 1, the number of lines which differ from line to line.
+	// n bits representing the data at 1 bit per pixel, where:
+	// -if the multiple line flag is 0, n is the width of the glyph.
+	// -if the flag is 1, n is width of glyph multiplied by the repeat count for this block of data.
+	// This information presented in continuous packed blocks of:
+	// [data][reps][multiLineFlag]
+	TInt bitIndex = 0;
+	TInt16 repeatCount = 0;
+	TUint8* byteDataPtr = aByteData;
+	TUint8* byteDataPtrLimit = NULL;
+	for (TInt charLine = 0; charLine < dataHeight; charLine += repeatCount) // for lines in the character...
+		{
+		// Get first 5 bits of block
+		repeatCount = Load16(aEncodedData + (bitIndex >> 3));
+		repeatCount >>= bitIndex & 7;
+		// strip out multiple line flag (1st bit)
+		TInt multiLineFlag = repeatCount & 1;
+		// Get repeat count (last 4 bits)
+		repeatCount >>= 1;
+		repeatCount &= 0xf;
+		// move bit index to point to first bit of image data
+		bitIndex += 5;
+		// end pointer of destination buffer for this block of data to fill 
+		byteDataPtrLimit = aByteData + dataWidth * (charLine + repeatCount);
+		if (multiLineFlag)
+			{
+			while (byteDataPtr < byteDataPtrLimit)
+				{
+				// Pointer to beginning of data in source buffer for current scanline
+				TInt charDataOffsetPtr = TInt(aEncodedData) + (bitIndex >> 3);
+				// Pointer to beginning of current word.
+				TUint32* charDataWord = (TUint32*)(charDataOffsetPtr &~ 3);
+				// Number of bits to shift in current word to get to beginning of scanline
+				TInt bitShift = bitIndex & 7;
+				bitShift += (charDataOffsetPtr & 3) << 3;
+				// Copy scanline data into temporary buffer
+				binaryData = (*charDataWord++) >> bitShift;
+				// If data crosses a word boundary, get the rest of the data from next word.
+				if (bitShift)
+					{
+					binaryData |= (*charDataWord << (32-bitShift));
+					}
+				Convert1BppTo8Bpp(binaryData, byteDataPtr, byteDataPtr + dataWidth);
+				// Move bit index to beginning of next block
+				bitIndex += dataWidth;
+				}
+			}
+		else
+			{
+			TInt charDataOffsetPtr = TInt(aEncodedData) + (bitIndex >> 3);
+			TUint32* charDataWord = (TUint32*)(charDataOffsetPtr &~ 3);
+			TInt bitShift = bitIndex & 7;
+			bitShift += (charDataOffsetPtr & 3) << 3;
+			binaryData = (*charDataWord++) >> bitShift;
+			if (bitShift)
+				{
+				binaryData |= (*charDataWord << (32-bitShift));
+				}
+			TUint8* startByteDataPtr = byteDataPtr;
+			Convert1BppTo8Bpp(binaryData, byteDataPtr, byteDataPtr + dataWidth);
+			
+			while (byteDataPtr < byteDataPtrLimit)
+				{
+				Mem::Copy(byteDataPtr, startByteDataPtr, dataWidth);
+				byteDataPtr += dataWidth;
+				}
+			bitIndex += dataWidth;
+			}
+		}
+	}
+
+/**
+Converts binary data in 1 bit per pixel format to 8 bits per pixel format, where
+0 is converted to 0x00 and 1 is converted to 0xFF.
+
+@param aSrcData Pointer to a 1bpp source buffer.
+@param aDestDataPtr Pointer to a 8bpp destination buffer.
+@param aDestDataPtrLimit Pointer to the end position in destination buffer to convert to.
+*/
+void Convert1BppTo8Bpp(TUint32 aSrcData, TUint8*& aDestDataPtr, const TUint8* aDestDataPtrLimit)
+	{
+	for (; aDestDataPtr < aDestDataPtrLimit; ++aDestDataPtr, aSrcData >>= 1)
+		{
+		if (aSrcData&1)
+			{
+			*aDestDataPtr = 0xFF;
+			}
+		}
+	}
+
+/**
+Decodes binary data for extra large monochrome glyph bitmap.
+
+@param aGlyphSize Size of glyph in pixels.
+@param aEncodedData Pointer to an encoded source buffer.
+@param aByteData Pointer to a destination buffer (8 bits per pixel).
+*/
+void DecodeBinaryDataExLarge(const TSize& aGlyphSize, const TUint8* aEncodedData, TUint8* aByteData)
+	{
+	const TInt dataWidth = aGlyphSize.iWidth;
+	const TInt dataHeight = aGlyphSize.iHeight;
+	TInt bitIndex = 0;
+	TInt16 repeatCount = 0;
+
+	for (TInt charLine = 0; charLine < dataHeight; charLine += repeatCount) // for lines in the character...
+		{
+		repeatCount = Load16(aEncodedData + (bitIndex >> 3));
+		repeatCount >>= bitIndex & 7;
+		const TInt multiLineFlag = repeatCount & 1;
+		repeatCount >>= 1;
+		repeatCount &= 0xf;
+		bitIndex += 5;
+		if (multiLineFlag)
+			{
+			for (TInt currentline = 0; currentline < repeatCount; currentline++)
+				{
+				CopyCharLine(aByteData, dataWidth, aEncodedData + (bitIndex >> 3), bitIndex & 7, 1);
+				bitIndex += dataWidth;
+				}
+			}
+		else
+			{
+			CopyCharLine(aByteData, dataWidth, aEncodedData + (bitIndex >> 3), bitIndex & 7, repeatCount);
+			bitIndex += dataWidth;
+			}
+		}
+	}
+
+/**
+Copies glyph image data line(s)(1 bit per pixel) to an 8 bit per pixel
+destination buffer.
+
+@param aByteDataPtr Pointer to a destination buffer (8bpp).
+@param aWidthInBytes Stride of the image.
+@param aSrcData Pointer to a source buffer (1bpp).
+@param aBitShift Number of bits the source data pointer will be shifted. 
+@param aRepeatCount Number of lines to copy.
+*/
+void CopyCharLine(TUint8*& aByteDataPtr, TInt aWidthInBytes, const TUint8* aSrcData, TInt aBitShift, TInt16 aRepeatCount)
+	{
+	aBitShift &= 7;
+	TUint8* ptrLimit = aByteDataPtr + aWidthInBytes;
+	TUint32* dataWord = (TUint32*)(TInt(aSrcData) &~ 3);
+	aBitShift += (TInt(aSrcData) - TInt(dataWord)) << 3;
+
+	TUint8* startByteDataPtr = aByteDataPtr;
+	TUint32 binaryData = 0;
+	while (aByteDataPtr < ptrLimit)
+		{
+		binaryData = *dataWord++;
+		binaryData >>= aBitShift;
+		if (aBitShift)
+			{
+			binaryData |= (*dataWord << (32-aBitShift));
+			}
+		TUint8* wordLimit = aByteDataPtr + 32;
+		if (wordLimit > ptrLimit)
+			{
+			wordLimit = ptrLimit;
+			}
+		Convert1BppTo8Bpp(binaryData, aByteDataPtr, wordLimit);
+		}
+
+	while (aRepeatCount > 1)
+		{
+		Mem::Copy(aByteDataPtr, startByteDataPtr, aWidthInBytes);
+		aByteDataPtr += aWidthInBytes;
+		--aRepeatCount;
+		}
+	}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/glyphatlas.h	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,185 @@
+// Copyright (c) 2009-2010 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:
+// Font & Bitmap Server Glyph Atlas
+//
+
+#ifndef GLYPHATLAS_H
+#define GLYPHATLAS_H
+
+#include <e32base.h>
+#include <sgresource/sgimage.h>
+#include <fbs.h>
+#include "UTILS.H"
+
+class CGlyphAtlasFontEntry;
+class CGlyphAtlasPage;
+class TGlyphCacheMetrics;
+
+/**
+The Glyph Atlas manages the storing and retrieval of glyphs stored in GPU 
+memory as RSgImages.
+
+CGlyphAtlas is the main class which processes requests to add and retrieve
+glyphs. Only one instance of this class will exist throughout the lifetime of 
+the Font and Bitmap Server.
+@internalComponent
+*/
+NONSHARABLE_CLASS(CGlyphAtlas) : public CBase
+	{
+friend class CGlyphAtlasTestWrapper;
+public:
+	/**
+	Structure used to pass information required to create a new glyph so that it can 
+	be added to the glyph atlas.
+	@internalComponent 
+	*/
+	class TAddGlyphArgs
+		{
+	public:
+		inline TAddGlyphArgs(const TUint8* aBitmapPointer, TUint aGlyphCode, const TOpenFontCharMetrics& aMetrics)
+			: iBitmapPointer(aBitmapPointer), iGlyphCode(aGlyphCode), iMetrics(&aMetrics) {}
+	public:
+		const TUint8* iBitmapPointer;	/**< The address of the bitmap glyph. No ownership.*/
+		TUint iGlyphCode;	/**< The glyph code for the glyph being added. No ownership.*/
+		const TOpenFontCharMetrics* iMetrics;	/**< The metrics for the glyph being added. No ownership.*/
+		};
+
+public:
+	~CGlyphAtlas();
+	static CGlyphAtlas* NewL(TInt aMaxCacheSizeInBytes);
+	TInt GetGlyph(const CBitmapFont& aFont, TUint aGlyphCode, TGlyphImageInfo& aGlyphImageInfo);
+	TInt AddGlyph(const CBitmapFont& aFont, const TAddGlyphArgs& aArgs, TGlyphImageInfo& aGlyphImageInfo);
+	void FontReleased(const CBitmapFont& aFont);
+	void MovePageToFront(CGlyphAtlasPage& aPage);
+	TBool DeleteLeastRecentlyUsedPage(TBool aAllowMruPageDeletion);
+	TInt FontCount() const;
+	TInt GlyphCount() const;
+	TInt GlyphCount(const CBitmapFont& aFont) const;
+	void GlyphCacheMetrics(TInt& aSizeInBytes, TInt& aMaxSizeInBytes, TBool& aGpuCacheSizeLimitIsMax);
+	void ReleaseGpuMemory( TInt /*aBytes*/, TInt /*aFlags*/ );
+	void InstateGpuMemory( TInt /*aFlags*/ );
+	void GetGlyphCacheMetrics( TGlyphCacheMetrics& aGlyphCacheMetrics );
+
+private:
+	CGlyphAtlas(TInt aMaxCacheSizeInBytes);
+	void ConstructL();
+	CGlyphAtlasFontEntry* CreateFontEntry(const CBitmapFont& aFont);
+	CGlyphAtlasFontEntry* FindFontEntry(const CBitmapFont& aFont) const;
+	void DeleteFontEntry(CGlyphAtlasFontEntry* aFontEntry);
+    void SwitchGpuCacheSizeLimit();
+    TBool GpuCacheSizeLimitIsMax() const;
+
+private:
+	class TFontEntryMap
+		{
+	public:
+		inline TFontEntryMap(const CBitmapFont* aFont, CGlyphAtlasFontEntry* aEntry)
+				: iFont(aFont),iEntry(aEntry) {}
+	public:			
+		const CBitmapFont* iFont;
+		CGlyphAtlasFontEntry* iEntry;
+		};
+private:
+	RSgDriver iSgDriver;
+	TDblQue<CGlyphAtlasPage> iLruPageList; /**< Least-recently used ordered queue (most-recently used at head).*/
+	RArray<TFontEntryMap> iFontEntryArray; /**< Array of font entries maintained in unsigned ordered by font pointer.*/
+	TUint iMaxCacheSizeInBytes;	/**< Maximum specialised graphics memory the cache should use. If zero, there is no limit.*/
+	TInt iMaxCacheSizeHigh;                /**< The high cach-size threshold.*/
+	TInt iMaxCacheSizeLow;                 /**< The low cach-size threshold.*/
+	TUint iCacheSizeInBytes; 	/**< Actual amount of specialised graphics memory used by the entire atlas.*/
+	TBool iGpuCacheSizeLimitIsMax;         /**< Is the cache-size limit set to it's maximum value? */
+	};
+
+
+/**
+Each font entry manages the storing and retrieval of glyphs belonging to a font.
+@internalComponent
+*/
+NONSHARABLE_CLASS(CGlyphAtlasFontEntry): public CBase
+	{
+public:
+	CGlyphAtlasFontEntry(const CBitmapFont& aFont, CGlyphAtlas& aGlyphAtlas);
+	~CGlyphAtlasFontEntry();
+	const CBitmapFont& Font() const;
+	void DeletePage(CGlyphAtlasPage* aPage);
+	TInt GetGlyph(TUint aGlyphCode, TGlyphImageInfo& aGlyphImageInfo);
+	TInt AddGlyph(const CGlyphAtlas::TAddGlyphArgs& aArgs, TGlyphImageInfo& aGlyphImageInfo, TInt& aSizeInBytes);
+	TInt SizeInBytes() const;
+	TBool IsEmpty() const;
+	CGlyphAtlas& GlyphAtlas() const;
+	TInt GlyphCount() const;
+
+private:
+	// Class that handles association between glyph code and page the 
+	// image that glyph code resides on. Used in pointer arrays.
+	class TPageMap
+		{
+	public:
+		inline TPageMap(TUint aGlyphCode, CGlyphAtlasPage* aPage)
+				: iGlyphCode(aGlyphCode),iPage(aPage) {}
+	public:			
+		TUint iGlyphCode;
+		CGlyphAtlasPage* iPage;
+		};
+private:
+	const CBitmapFont& iFont;	/**< The font which the stored glyph belongs to.*/
+	RArray<TPageMap> iPageArray;	/**< Array of pages maintained in unsigned ordered by glyph code.*/
+	CGlyphAtlas& iAtlas;		/**< The glyph atlas the font entry belongs to.*/
+	TInt iSizeInBytes;			/**< The amount of specialised graphics memory used by all owned pages.*/
+	};
+
+
+/**
+Each page in the glyph atlas stores one glyph in one RSgImage.
+@internalComponent
+*/
+NONSHARABLE_CLASS(CGlyphAtlasPage): public CBase
+	{
+friend CGlyphAtlas::CGlyphAtlas(TInt);
+public:
+	CGlyphAtlasPage(CGlyphAtlasFontEntry& aFontEntry);
+	~CGlyphAtlasPage();
+	TInt AddGlyph(const CGlyphAtlas::TAddGlyphArgs& aArgs, TGlyphImageInfo& aGlyphImageInfo, TInt& aSizeInBytes);
+	void GetGlyph(TUint aGlyphCode, TGlyphImageInfo& aGlyphImageInfo) const;
+	TUint GlyphCodeAt(TInt aIndex) const;
+	TInt GlyphCount() const;
+	CGlyphAtlasFontEntry& FontEntry() const;
+	TInt SizeInBytes() const;
+	void MoveToFirstInQueue(TDblQue<CGlyphAtlasPage>& aList);
+
+private:
+	TDblQueLink iLink;
+	// Data for the stored glyph
+	CGlyphAtlasFontEntry& iFontEntry;	/**< The font entry asssociated with the page.*/
+	RSgImage iGlyphImage;		/**< The image which contains the stored glyph.*/
+	TInt16 iPosX;				/**< The x-coord of the position of the stored glyph within the image.*/
+	TInt16 iPosY;				/**< The y-coord of the position of the stored glyph within the image.*/
+	TOpenFontCharMetrics iMetrics;	/**< The character metrics for the stored glyph.*/
+	TUint iGlyphCode;			/**< The glyph code for the stored glyph.*/
+	TInt iSizeInBytes;			/**< The amount of specialised graphics memory used by this page.*/
+	TInt iNumGlyphs;			/**< The number of glyphs contained in the page.*/
+	};
+
+
+// If no limit to the size of the glyph atlas cache is desired, this
+// constant must be passed to CGlyphCache::NewL()
+// In this case the cache lower maximum limit, deployed in response to GooM,
+// will be set to KGlyphAtlasLowMemCacheLimitDefault
+const TInt KGlyphAtlasNoCacheLimit = 0;
+const TInt KGlyphAtlasLowMemCacheLimitDivisor = 2;
+const TInt KGlyphAtlasLowMemCacheLimitDefault = 0x40000;
+
+
+#endif // GLYPHATLAS_H
+
--- a/fbs/fontandbitmapserver/sfbs/patchableconstants.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/sfbs/patchableconstants.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2006-2010 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"
@@ -54,6 +54,19 @@
 */
 EXPORT_C extern const TInt KFbServWritableDataPagingMode = 0x00;
 
+/**
+@SYMPatchable
+@publishedPartner
+@prototype
+
+This constant determines the maximum size of the GPU memory that the font and 
+bitmap server's glyph atlas can use.
+The glyph atlas will store glyphs in this memory.  When the glyph atlas reaches 
+this limit, old glyphs will be evicted from the cache to make space for new glyphs.
+@note	Default value: 0.5 MB (0x00080000).
+*/
+EXPORT_C extern const TInt KFbServGlyphAtlasCacheLimit = 0x00080000;
+
 // Header files declaring these constants are included to confirm that the definition matches.
 // They are included at the end because otherwise the ARM compiler refuses to initialise the values.
 #if (__ARMCC_VERSION >= 310000)
--- a/fbs/fontandbitmapserver/tfbs/TALLOC.H	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/TALLOC.H	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2005-2010 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"
@@ -17,7 +17,7 @@
 #define __TALLOC_H__
 
 #include <fbs.h>
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 
 class CTAlloc : public CTGraphicsBase
 	{
--- a/fbs/fontandbitmapserver/tfbs/TBitmap.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/TBitmap.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2004-2010 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"
@@ -20,8 +20,8 @@
 
 #include <gdi.h>
 #include "TFBS.H"
-#include "TGraphicsHarness.h"
-#include "../sfbs/fbsbitmapasyncstreamer.h"
+#include "test/TGraphicsHarness.h"
+#include "fbsbitmapasyncstreamer.h"
 
 
 //The main test class. Add your test methods here.
--- a/fbs/fontandbitmapserver/tfbs/TCLEAN.H	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/TCLEAN.H	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1996-2010 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"
@@ -17,7 +17,7 @@
 #define __TCLEAN_H__
 
 #include <fbs.h>
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 
 enum TTestType
 	{
--- a/fbs/fontandbitmapserver/tfbs/TFBS.CPP	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/TFBS.CPP	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1995-2010 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"
@@ -84,7 +84,7 @@
 void CTFbs::ConstructL()
 	{
 	ExpandCleanupStackL();
-	
+	User::LeaveIfError(Logger().ShareAuto());
 	TestConstruction();
 	AllocScanLineBuf();
 	
@@ -187,7 +187,7 @@
 		TestSingletonServer();
 		break;
 	case 21:
-		((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0620"));
+		((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0623"));
 		TestFontSessionCacheLookupL();
 		break;
 	case 22:
@@ -649,7 +649,7 @@
 	CheckResourceCount();
 	TEST(fbsalt->ResourceCount()==iResourceCount);
 	font3->Reset();
-	User::Free(font3);
+	delete font3;
 	iResourceCount--;
 	CheckResourceCount();
 	TEST(fbsalt->ResourceCount()==iResourceCount);
@@ -2133,7 +2133,7 @@
 	}
 
 /**
-@SYMTestCaseID      GRAPHICS-FBSERV-0620
+@SYMTestCaseID      GRAPHICS-FBSERV-0623
 @SYMTestPriority    High
 @SYMTestStatus      Implemented
 @SYMDEF             DEF140138
@@ -2145,6 +2145,8 @@
 	are the same, thereby avoiding any unneccessary IPC calls.
 
 @SYMTestActions
+	Try to open a global semaphore called "FBSSessionCacheSemaphore" (this is a temporary measure to
+		ensure successful propagation of ou1cimx1#250526).
 	Create a large font which consumes a lot of memory.
 	Create a CFbsBitGc and a CFbsBitmap target.
 	Use the CFbsBitGc to render some text, thereby filling the font glyph cache. 
@@ -2156,6 +2158,7 @@
 		returned from CBitmapFont::GetCharacterData().
 
 @SYMTestExpectedResults
+	No global semaphore called "FBSSessionCacheSemaphore" should exist.
 	When using KNullHandle, CharacterNeedsToBeRasterized() with the first character, is expected to pass
 		proving that the font cache is working as expected when glyphs can fit into it.
 	When using KNullHandle, CharacterNeedsToBeRasterized() with the last character, it expected to fail, 
@@ -2172,6 +2175,11 @@
 	{
 	INFO_PRINTF1(_L("Test Font Session-cache Lookup"));
 
+	// Make sure the global semaphore is gone for good
+	_LIT(KSessionCacheSemaphoreName, "FBSSessionCacheSemaphore");
+	RSemaphore sem;
+	TEST(sem.OpenGlobal(KSessionCacheSemaphoreName) == KErrNotFound);
+
 	User::LeaveIfError(RFbsSession::Connect());    
 	RFbsSession* fbsSession = RFbsSession::GetSession();
 	CFbsTypefaceStore* ts = CFbsTypefaceStore::NewL(NULL);
@@ -2273,170 +2281,96 @@
 	TEST(KErrNone == iFbs->SendCommand(EFbsMessSetTwipsHeight, fontHandle, 49));
 	// In a second thread, send a IPC command to set the font's height with the 
 	// bitmap's handle.  Should panic with FBServ -6.
-	TFbsTestThreadInfo threadInfo = {EFbsSecondThreadInvalidHandleInIpcCall};
- 	TExitCategoryName exitCategoryName(KFbsPanicCategory);
 	_LIT(KTestName, "TestInvalidHandlesInIpcCall");
- 	CreateSecondThreadAndCheckPanicL(threadInfo, -6, exitCategoryName, KTestName);
+ 	CreateSecondThreadAndCheckPanicL(SecondThreadPanicInvalidHandleInIpcCallL, KErrArgument, KFbsPanicCategory, KTestName);
 
 	iTs->ReleaseFont(font);
 	delete bmp;
 	}
 
 /**
-Creates a second thread and do some panic tests in it.
-@param aTestInfo The information for the tests
-@param aPanicCode The expected panic code
-@param aExitCategory The expected panic category
-@param aThreadName The name of the new thread
-@leave Gets system wide error code
+Second thread function for test GRAPHICS-FBSERV-0650. It should panic with FBSERV -6 if the test is successful.
+ */
+void CTFbs::SecondThreadPanicInvalidHandleInIpcCallL()
+	{
+	User::LeaveIfError(RFbsSession::Connect());
+	RFbsSession* fbs = RFbsSession::GetSession();
+	CFbsBitmapEx* bmp = new(ELeave) CFbsBitmapEx();
+	CleanupStack::PushL(bmp);
+	User::LeaveIfError(bmp->Create(TSize(1,1), EGray2));
+	CFbsTypefaceStore* ts = CFbsTypefaceStore::NewL(NULL);
+	CleanupStack::PushL(ts);
+	CFbsFont* font=NULL;
+	User::LeaveIfError(ts->GetNearestFontToDesignHeightInPixels((CFont*&)font, TFontSpec(KTypefaceName, 15)));
+	TInt bitmapHandle = bmp->BitmapHandle();
+
+	// Send a IPC command to set twips height of font with a bitmap handle
+	(void)fbs->SendCommand(EFbsMessSetTwipsHeight, bitmapHandle, 49);
+
+	ts->ReleaseFont(font);
+	CleanupStack::PopAndDestroy(2);
+	RFbsSession::Disconnect();
+	}
+
+
+struct TFbsTestDelegator
+	{
+	CTFbs* iTestBase;
+	void (CTFbs::*iMethodPtr)();
+	};
+
+/**
+Creates a second thread and checks that it panics.
+@param aMethodL The leaving method of CTFbs that the second thread is going to execute.
+@param aPanicCode The expected panic code.
+@param aPanicCategory The expected panic category.
+@param aThreadName The name of the new thread.
 */
-void CTFbs::CreateSecondThreadAndCheckPanicL(TFbsTestThreadInfo& aTestInfo, TInt aPanicCode, TExitCategoryName aExitCategory, const TDesC &aThreadName)
+void CTFbs::CreateSecondThreadAndCheckPanicL(void (CTFbs::*aMethodL)(), TInt aPanicCode, const TDesC& aPanicCategory, const TDesC& aThreadName)
 	{
 	RThread secondThread;
-	User::LeaveIfError(secondThread.Create(aThreadName, SecondThreadStart, KDefaultStackSize, 0x1000, 0x1000, &aTestInfo));
+	TFbsTestDelegator delegator;
+	delegator.iTestBase = this;
+	delegator.iMethodPtr = aMethodL;
+	User::LeaveIfError(secondThread.Create(aThreadName, MethodDelegatorThreadFunction, KDefaultStackSize, 0x1000, 0x1000, &delegator));
 	// Launch second thread
 	TRequestStatus statusSecondThread;
 	secondThread.Logon(statusSecondThread);
-	secondThread.SetPriority(EPriorityLess);
-	secondThread.Resume();	
-	
+	secondThread.Resume();
+	// Wait until second thread is finished
 	User::WaitForRequest(statusSecondThread);
-	
-	if(EExitPanic != secondThread.ExitType())
+	// Check results
+	if (EExitPanic != secondThread.ExitType())
 		{
-		ERR_PRINTF3(_L("Expected exit type: %d, Actual exit type: %d"), EExitPanic, secondThread.ExitType());
+		ERR_PRINTF2(_L("Expected exit type: EExitPanic, actual exit type: %d"), secondThread.ExitType());
 		TEST(EFalse);
 		}
-	
-	if(aPanicCode != secondThread.ExitReason())
+	if (aPanicCode != secondThread.ExitReason())
 		{
-		ERR_PRINTF3(_L("Expected panic code: %d, Actual panic code: %d"), aPanicCode, secondThread.ExitReason());
+		ERR_PRINTF3(_L("Expected exit reason: %d, actual exit reason: %d"), aPanicCode, secondThread.ExitReason());
         TEST(EFalse);
 		}
-	
 	TExitCategoryName secondThreadExitCategory = secondThread.ExitCategory();
-	if(aExitCategory != secondThreadExitCategory)
+	if (aPanicCategory != secondThreadExitCategory)
 		{
-		ERR_PRINTF3(_L("Expected panic category: %S, Actual panic category: %S"), &aExitCategory, &secondThreadExitCategory);
+		ERR_PRINTF3(_L("Expected exit category: %S, actual exit category: %S"), &aPanicCategory, &secondThreadExitCategory);
         TEST(EFalse);
 		}
-	
-	//Close the handle
+	// Dispose of the remains of the second thread
 	secondThread.Close();
 	}
 
-/**
-Second thread entry function.
-*/
-TInt CTFbs::SecondThreadStart(TAny* aTestInfo)
+TInt CTFbs::MethodDelegatorThreadFunction(TAny* aDelegator)
 	{
-	
-	__UHEAP_MARK;
-    TInt procHandles1  =0;
-    TInt threadHandles1=0;
-    RThread().HandleCount(procHandles1, threadHandles1);
 	CTrapCleanup* cleanupStack = CTrapCleanup::New();
-	
 	if (!cleanupStack)
 	    {
-	    __UHEAP_MARKEND;
 	    return KErrNoMemory;
 	    }
-	
-	TInt result = KErrNone;
-	TRAP(result, SecondThreadMainL(static_cast<TFbsTestThreadInfo*>(aTestInfo)));
-	
+	TFbsTestDelegator* delegator = static_cast<TFbsTestDelegator*>(aDelegator);
+	TRAPD(err, (delegator->iTestBase->*delegator->iMethodPtr)());
 	delete cleanupStack;
-
-    TInt procHandles2  =0;
-    TInt threadHandles2=0;
-    RThread().HandleCount(procHandles2,threadHandles2);
-    if (threadHandles1 != threadHandles2)
-        {
-        result = KErrGeneral;  // Thread-owned handles not closed
-        }
-	__UHEAP_MARKEND;
-
-	return result;
-	}
-
-/**
-Run the test contained within the TFbsTestThreadInfo object. A new thread is
-created for each test and only one of the cases in the switch statements
-below will be used.
-
-@param aTestInfo The parameters for the test
-@return One of the system wide error codes or an enumeration of passed tests.
- */
-TInt CTFbs::SecondThreadMainL(TFbsTestThreadInfo* aTestInfo)
-    {
-    TInt result = 0;
-    TFbsMultiThreadTestCase testcase = aTestInfo->iTestCase;
-
-    //test cases without the need of an initialised driver
-    switch (testcase)
-    	{
-    case EFbsSecondThreadInvalidHandleInIpcCall:
-    	result = SecondThreadPanicInvalidHandleInIpcCall();
-        break;
-    	}
-    return result;
-    }
-
-/**
-Implementation of SecondThread test EFbsSecondThreadInvalidHandleInIpcCall
-
-@panic FBSERV -6 If the test is successful
-
-@return One of the system wide error codes.
- */
-TInt CTFbs::SecondThreadPanicInvalidHandleInIpcCall()
-	{
-	TInt result = RFbsSession::Connect();
-	if (KErrNone != result)
-		{
-		return result;
-		}
-	RFbsSession* fbs = RFbsSession::GetSession();
-	CFbsBitmapEx* bmp = new CFbsBitmapEx();
-	if (!bmp)
-		{
-		return KErrGeneral;
-		}
-	result = bmp->Create(TSize(1,1),EGray2);
-	if(KErrNone != result)
-		{
-		delete bmp;
-		return KErrGeneral;
-		}
-
-	CFbsTypefaceStore* ts = NULL;
-	ts = (CFbsTypefaceStore*)CFbsTypefaceStore::NewL(NULL);
-	if (!ts)
-		{
-		delete bmp;
-		return KErrGeneral;
-		}
-
-	CFbsFontEx* font=NULL;
-	result = ts->GetNearestFontToDesignHeightInPixels((CFont*&)font, TFontSpec(KTypefaceName, 15));
-	if (!font)
-		{
-		delete bmp;
-		delete ts;
-		return KErrGeneral;
-		}
-
-	TInt fontHandle = font->FontHandle();
-	TInt bitmapHandle = bmp->BitmapHandle();
-
-	// Send a IPC command to set twips height of font with a bitmap handle
-	result = fbs->SendCommand(EFbsMessSetTwipsHeight, bitmapHandle, 49);
-
-	ts->ReleaseFont(font);
-	delete bmp;
-	delete ts;
-	return result;
+	return err;
 	}
 
 /**
--- a/fbs/fontandbitmapserver/tfbs/TFBSDefect.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/TFBSDefect.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2004-2010 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"
@@ -17,7 +17,7 @@
 #define __TFBSDEFECT_H__
 
 #include <fbs.h>
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 
 class CTFbsDefect : public CTGraphicsBase
 	{
--- a/fbs/fontandbitmapserver/tfbs/TFbsServer.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/TFbsServer.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2005-2010 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"
@@ -38,8 +38,12 @@
 #include "textendedbitmappanic.h"
 #include "twdp.h"
 #include "tfonttableandglyph.h"
+#include "tfbsglyphdata.h"
+#include "tfbsglyphdatapanic.h"
+#include "tfbsglyphdataoutlineshadow.h"
+#include "tglyphatlas.h"
+#include "tfbsoogm.h"
 
- 
 /* Path to the script
 
 z:\GraphicsTest\fbstest.script
@@ -196,9 +200,29 @@
 		testStep = new CTWDPStep();
 		}
    	else if(aStepName == KTFontTableAndGlyphStep)
-        	{
-        	testStep = new CTFontAndGlyphStep();
-        	}
-	
+        {
+        testStep = new CTFontAndGlyphStep();
+        }
+	else if(aStepName == KTFbsGlyphDataStep)
+		{
+		testStep = new CTFbsGlyphDataStep();
+		}
+    else if(aStepName == KTFbsGlyphDataPanicStep)
+        {
+        testStep = new CTFbsGlyphDataPanicStep();
+        }
+    else if(aStepName == KTFbsGlyphDataOutlineAndShadowStep)
+        {
+        testStep = new CTFbsGlyphDataOutlineAndShadowStep();
+        }
+    else if(aStepName == KTGlyphAtlasStep)
+    	{
+		testStep = new CTGlyphAtlasStep();
+    	}
+    else if(aStepName == KTFbsOogmStep)
+        {
+        testStep = new CTFbsOogmStep();
+        }
+
 	return testStep;
 	}
--- a/fbs/fontandbitmapserver/tfbs/TGetAllBitmapsCapability.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/TGetAllBitmapsCapability.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2006-2010 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"
@@ -16,7 +16,7 @@
 #ifndef __TGETALLBITMAPSCAPABILITY_H__
 #define __TGETALLBITMAPSCAPABILITY_H__
 
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 
 // The main test class. Add your test methods here.
 class CTGetAllBitmapsCapability : public CTGraphicsBase
--- a/fbs/fontandbitmapserver/tfbs/TRalc.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/TRalc.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1997-2010 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"
@@ -17,7 +17,7 @@
 #define __TRALC_H__
 
 #include <fbs.h>
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 
 class CTRalc : public CTGraphicsBase
 	{
--- a/fbs/fontandbitmapserver/tfbs/TSecureFBS.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/TSecureFBS.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2004-2010 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"
@@ -17,7 +17,7 @@
 #define __TSECUREFBS_H__
 
 #include <fbs.h>
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 
 class CTFbsSecure : public CTGraphicsBase
 	{
--- a/fbs/fontandbitmapserver/tfbs/TStreamIdCache.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/TStreamIdCache.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2004-2010 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"
@@ -17,7 +17,7 @@
 #define __TSTREAMIDCACHE_H__
 
 #include <fbs.h>
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 
 class CTStreamIdCache : public CTGraphicsBase
 	{
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/glyphatlastestwrapper.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,167 @@
+// Copyright (c) 2009-2010 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:
+//
+
+/**
+ @file
+ @internalComponent - Internal Symbian test code
+*/
+
+#include "glyphatlastestwrapper.h"
+
+/**
+Panic function required for glyphatlas.cpp to compile in the test project.
+*/
+GLDEF_C void Panic(TFbsPanic aPanic)
+	{
+	_LIT(KFBSERVClientPanicCategory,"FBSCLI");
+	User::Panic(KFBSERVClientPanicCategory,aPanic);
+	}
+
+
+/**
+Glyph Atlas test wrapper constructor.
+*/
+CGlyphAtlasTestWrapper::CGlyphAtlasTestWrapper()
+	{
+	}
+
+/**
+Two-phase constructor.
+@leave A system wide error code if RSgDriver failed to open.
+*/
+void CGlyphAtlasTestWrapper::ConstructL(TInt aMaxCacheSizeInBytes)
+	{
+	iAtlas = CGlyphAtlas::NewL(aMaxCacheSizeInBytes);
+	}
+
+/**
+Factory constructor method. Creates a new glyph atlas test wrapper.
+
+@param aMaxCacheSizeInBytes The size in bytes, to use as the upper limit
+	for the size of memory used by the glyph images in the atlas. If this
+	value is KGlyphAtlasNoCacheLimit, then there is no limit and the atlas
+	will use as much memory as is available in the system.
+
+@return A pointer to the newly-constructed atlas test wrapper
+
+@leave KErrNoMemory if there was insufficient memory to create the atlas, 
+	or a system wide error code if its RSgDriver failed to open.
+*/
+CGlyphAtlasTestWrapper* CGlyphAtlasTestWrapper::NewL(TInt aMaxCacheSizeInBytes)
+    {
+    CGlyphAtlasTestWrapper* self = CGlyphAtlasTestWrapper::NewLC( aMaxCacheSizeInBytes );
+    CleanupStack::Pop(); // self;
+
+    return self;
+    }
+
+CGlyphAtlasTestWrapper* CGlyphAtlasTestWrapper::NewLC(TInt aMaxCacheSizeInBytes)
+    {
+    CGlyphAtlasTestWrapper* self = new (ELeave) CGlyphAtlasTestWrapper();
+    CleanupStack::PushL(self);
+    self->ConstructL(aMaxCacheSizeInBytes);
+
+    return self;
+    }
+
+TInt CGlyphAtlasTestWrapper::GetGlyph(const CBitmapFont& aFont, TUint aGlyphCode, TGlyphImageInfo& aGlyphImageInfo)
+	{
+	return iAtlas->GetGlyph(aFont, aGlyphCode, aGlyphImageInfo);
+	}
+
+TInt CGlyphAtlasTestWrapper::AddGlyph(const CBitmapFont& aFont, const CGlyphAtlas::TAddGlyphArgs& aArgs, TGlyphImageInfo& aGlyphImageInfo)
+	{
+	return iAtlas->AddGlyph(aFont, aArgs, aGlyphImageInfo);
+	}
+
+void CGlyphAtlasTestWrapper::FontReleased(const CBitmapFont& aFont)
+	{
+	iAtlas->FontReleased(aFont);
+	}
+
+/**
+Returns the current size of the glyph image memory used by the atlas in bytes.
+*/
+TInt CGlyphAtlasTestWrapper::SizeInBytes() const
+	{
+	return iAtlas->iCacheSizeInBytes;
+	}
+
+/**
+Tests whether the least recently used page contains the given glyph.
+@param aGlyphCode The glyph code to match.
+@return ETrue if the lru page contains the given glyph, EFalse if not.
+*/
+TBool CGlyphAtlasTestWrapper::LruPageContainsGlyph(TUint aGlyphCode) const
+	{
+	CGlyphAtlasPage* page = iAtlas->iLruPageList.Last();
+	TInt numGlyphsInPage = page->GlyphCount();
+	TBool glyphFound = EFalse;
+	for (TInt ii = 0; ii < numGlyphsInPage && !glyphFound; ++ii)
+		{
+		glyphFound = (aGlyphCode == page->GlyphCodeAt(ii));
+		}
+	return glyphFound;
+	}
+
+/**
+Returns the number of glyphs associated to the given font in the atlas.
+*/
+TInt CGlyphAtlasTestWrapper::GlyphCountByFont(const CBitmapFont* aFont)
+	{
+	TInt glyphCount = 0;
+	TDblQueIter<CGlyphAtlasPage> iter(iAtlas->iLruPageList);
+	CGlyphAtlasPage* page;
+	while((page=iter++) != NULL)
+		{
+		if (&page->FontEntry().Font() == aFont)
+			{
+			glyphCount += page->GlyphCount();
+			}
+		}
+	return glyphCount;
+	}
+
+/**
+Returns the number of glyphs in the atlas.
+*/
+TInt CGlyphAtlasTestWrapper::GlyphCount()
+	{
+	TInt glyphCount = 0;
+	TDblQueIter<CGlyphAtlasPage> iter(iAtlas->iLruPageList);
+	CGlyphAtlasPage* page;
+	while((page=iter++) != NULL)
+		{
+		glyphCount += page->GlyphCount();
+		}
+	return glyphCount;
+	}
+
+/**
+Returns the number of fonts in the atlas.
+*/
+TInt CGlyphAtlasTestWrapper::FontCount() const
+	{
+	return iAtlas->iFontEntryArray.Count();
+	}
+
+/**
+Glyph Atlas test wrapper destructor.
+*/
+CGlyphAtlasTestWrapper::~CGlyphAtlasTestWrapper()
+	{
+	delete iAtlas;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/glyphatlastestwrapper.h	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,48 @@
+// Copyright (c) 2009-2010 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:
+//
+
+#ifndef GLYPHATLASTESTWRAPPER_H
+#define GLYPHATLASTESTWRAPPER_H
+
+#include "glyphatlas.h"
+
+
+/**
+Class to provide access to glyph atlas metrics for test purposes
+*/
+NONSHARABLE_CLASS(CGlyphAtlasTestWrapper)
+    {
+public:
+	~CGlyphAtlasTestWrapper();
+	static CGlyphAtlasTestWrapper* NewL(TInt aMaxCacheSizeInBytes);
+	static CGlyphAtlasTestWrapper* NewLC(TInt aMaxCacheSizeInBytes);
+	TInt GetGlyph(const CBitmapFont& aFont, TUint aGlyphCode, TGlyphImageInfo& aGlyphImageInfo);
+	TInt AddGlyph(const CBitmapFont& aFont, const CGlyphAtlas::TAddGlyphArgs& aArgs, TGlyphImageInfo& aGlyphImageInfo);
+	void FontReleased(const CBitmapFont& aFont);
+	
+	// Utility functions providing access to internals of glyph atlas
+	TInt SizeInBytes() const;
+	TInt GlyphCountByFont(const CBitmapFont* aFont);
+	TInt GlyphCount();
+	TInt FontCount() const;
+	TBool LruPageContainsGlyph(TUint aGlyphCode) const;
+private:
+	CGlyphAtlasTestWrapper();
+	void ConstructL(TInt aMaxCacheSizeInBytes);
+private:
+	CGlyphAtlas* iAtlas;
+    };
+
+#endif /* GLYPHATLASTESTWRAPPER_H */
--- a/fbs/fontandbitmapserver/tfbs/scripts/fbstest_T_IPCTest.script	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/scripts/fbstest_T_IPCTest.script	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2008-2010 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"
@@ -46,7 +46,10 @@
 RUN_TEST_STEP !PanicCode=-6 100 TFbsServer TIPCTest z:\fbstest\ipctest_config.ini ShapeDelete
 RUN_TEST_STEP !PanicCode=-6 100 TFbsServer TIPCTest z:\fbstest\ipctest_config.ini SetTwipsHeight
 RUN_TEST_STEP !PanicCode=-6 100 TFbsServer TIPCTest z:\fbstest\ipctest_config.ini GetTwipsHeight
+RUN_TEST_STEP !PanicCode=-8 100 TFbsServer TIPCTest z:\fbstest\ipctest_config.ini GetGlyphs
+RUN_TEST_STEP !PanicCode=-8 100 TFbsServer TIPCTest z:\fbstest\ipctest_config.ini GetGlyphMetrics
 RUN_TEST_STEP !PanicCode=-6 100 TFbsServer TIPCTest z:\fbstest\ipctest_config.ini GetFontTableWrongMsg
 RUN_TEST_STEP !PanicCode=-6 100 TFbsServer TIPCTest z:\fbstest\ipctest_config.ini ReleaseFontTableWrongMsg
 RUN_TEST_STEP !PanicCode=-38 100 TFbsServer TIPCTest z:\fbstest\ipctest_config.ini GetGlyphOutlineWrongMsg
 RUN_TEST_STEP !PanicCode=-38 100 TFbsServer TIPCTest z:\fbstest\ipctest_config.ini ReleaseGlyphOutlineWrongMsg
+
--- a/fbs/fontandbitmapserver/tfbs/scripts/fbstest_run.bat	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/scripts/fbstest_run.bat	Fri Sep 24 16:14:28 2010 +0300
@@ -26,6 +26,9 @@
 testexecute.exe  z:\fbstest\fbstest_t_ipctest.script
 testexecute.exe  z:\fbstest\fbstest_t_extendedbitmap.script
 testexecute.exe  z:\fbstest\fbstest_t_fonttable.script
+testexecute.exe  z:\fbstest\fbstest_t_glyphdata.script		
+testexecute.exe  z:\fbstest\fbstest_t_glyphdataoutlineshadow.script	
+testexecute.exe  z:\fbstest\fbstest_t_oogm.script
 
 @echo off
 md e:\logs
--- a/fbs/fontandbitmapserver/tfbs/scripts/fbstest_t_fonttable.script	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/scripts/fbstest_t_fonttable.script	Fri Sep 24 16:14:28 2010 +0300
@@ -16,10 +16,10 @@
 PRINT Run TFontTableAndGlyphOutline Fbserv test 
 
 RUN_UTILS MakeReadWrite C:\DejaVuSans.ttf
-RUN_UTILS CopyFile z:\RESOURCE\FONTS\DejaVuSans.ttf C:\DejaVuSans.ttf
+RUN_UTILS CopyFile z:\RESOURCE\FONTS\DejaVuSansCondensed.ttf C:\DejaVuSans.ttf
 RUN_UTILS MakeReadWrite C:\DejaVuSans.TTF 
 RUN_UTILS MakeReadWrite C:\DejaVuSerif.ttf
-RUN_UTILS CopyFile z:\RESOURCE\FONTS\DejaVuSerif.ttf C:\DejaVuSerif.ttf
+RUN_UTILS CopyFile z:\RESOURCE\FONTS\DejaVuSerifCondensed.ttf C:\DejaVuSerif.ttf
 RUN_UTILS MakeReadWrite C:\DejaVuSerif.ttf
 
 // Set test server to have no Capabilitities
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/scripts/fbstest_t_glyphdata.script	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,32 @@
+// Copyright (c) 2009-2010 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:
+//
+
+PRINT Run TGlyphAtlas & TFbsGlyphData Fbserv tests 
+//
+LOAD_SUITE TFbsServer
+RUN_TEST_STEP 100 TFbsServer TGlyphAtlas
+RUN_TEST_STEP 800 TFbsServer TFbsGlyphData
+RUN_PANIC_STEP_RESULT 31 FBSCLI 100 TFbsServer TFbsGlyphDataPanic z:\fbstest\glyphdata_config.ini NotInitializedNext
+RUN_PANIC_STEP_RESULT 31 FBSCLI 100 TFbsServer TFbsGlyphDataPanic z:\fbstest\glyphdata_config.ini NotInitializedImage
+RUN_PANIC_STEP_RESULT 31 FBSCLI 100 TFbsServer TFbsGlyphDataPanic z:\fbstest\glyphdata_config.ini NotInitializedMetrics
+RUN_PANIC_STEP_RESULT 31 FBSCLI 100 TFbsServer TFbsGlyphDataPanic z:\fbstest\glyphdata_config.ini NotInitializedGlyphCode
+RUN_PANIC_STEP_RESULT 31 FBSCLI 100 TFbsServer TFbsGlyphDataPanic z:\fbstest\glyphdata_config.ini ClosedNext
+RUN_PANIC_STEP_RESULT 31 FBSCLI 100 TFbsServer TFbsGlyphDataPanic z:\fbstest\glyphdata_config.ini ClosedImage
+RUN_PANIC_STEP_RESULT 31 FBSCLI 100 TFbsServer TFbsGlyphDataPanic z:\fbstest\glyphdata_config.ini ClosedMetrics
+RUN_PANIC_STEP_RESULT 31 FBSCLI 100 TFbsServer TFbsGlyphDataPanic z:\fbstest\glyphdata_config.ini ClosedGlyphCode
+RUN_PANIC_STEP_RESULT -8 FBSERV 100 TFbsServer TFbsGlyphDataPanic z:\fbstest\glyphdata_config.ini DiscardUsedFont
+RUN_PANIC_STEP_RESULT 32 FBSCLI 100 TFbsServer TFbsGlyphDataPanic z:\fbstest\glyphdata_config.ini IndexNegative
+RUN_PANIC_STEP_RESULT 32 FBSCLI 100 TFbsServer TFbsGlyphDataPanic z:\fbstest\glyphdata_config.ini IndexTooHigh
+RUN_PANIC_STEP_RESULT 31 FBSCLI 100 TFbsServer TFbsGlyphDataPanic z:\fbstest\glyphdata_config.ini IteratorOpenFailed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/scripts/fbstest_t_glyphdataoutlineshadow.script	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,20 @@
+// Copyright (c) 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:
+//
+
+PRINT Run TFbsGlyphData Fbserv test 
+//
+LOAD_SUITE TFbsServer
+//the following test must be run with a rasterizer which supports outline and shadow
+RUN_TEST_STEP 300 TFbsServer TFbsGlyphDataOutlineAndShadow
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/scripts/fbstest_t_oogm.script	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,19 @@
+// Copyright (c) 2009-2010 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:
+//
+
+PRINT Run TFbsOogm Fbserv tests 
+//
+LOAD_SUITE TFbsServer
+RUN_TEST_STEP 100 TFbsServer TFbsOogm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/scripts/glyphdata_config.ini	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,36 @@
+[NotInitializedNext]
+CaseNumber = 1
+
+[NotInitializedImage]
+CaseNumber = 2
+
+[NotInitializedMetrics]
+CaseNumber = 3
+
+[NotInitializedGlyphCode]
+CaseNumber = 4
+
+[ClosedNext]
+CaseNumber = 5
+
+[ClosedImage]
+CaseNumber = 6
+
+[ClosedMetrics]
+CaseNumber = 7
+
+[ClosedGlyphCode]
+CaseNumber = 8
+
+[DiscardUsedFont]
+CaseNumber = 9
+
+[IndexNegative]
+CaseNumber = 10
+
+[IndexTooHigh]
+CaseNumber = 11
+
+[IteratorOpenFailed]
+CaseNumber = 12
+
--- a/fbs/fontandbitmapserver/tfbs/scripts/ipctest_config.ini	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/scripts/ipctest_config.ini	Fri Sep 24 16:14:28 2010 +0300
@@ -67,14 +67,21 @@
 [GetTwipsHeight]
 CaseNumber = 23
 
-[GetFontTableWrongMsg]
+[GetGlyphs]
 CaseNumber = 24
 
-[ReleaseFontTableWrongMsg]
+[GetGlyphMetrics]
 CaseNumber = 25
 
-[GetGlyphOutlineWrongMsg]
+[GetFontTableWrongMsg]
 CaseNumber = 26
 
+[ReleaseFontTableWrongMsg]
+CaseNumber = 27
+
+[GetGlyphOutlineWrongMsg]
+CaseNumber = 28
+
 [ReleaseGlyphOutlineWrongMsg]
-CaseNumber = 27
+CaseNumber = 29
+
--- a/fbs/fontandbitmapserver/tfbs/tcompressed.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/tcompressed.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2002-2010 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"
@@ -18,7 +18,7 @@
 
 #include <fbs.h>
 #include "TFBS.H"
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 
 class CTCompressed : public CTGraphicsBase
 	{
--- a/fbs/fontandbitmapserver/tfbs/textendedbitmapcommon.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/textendedbitmapcommon.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2008-2010 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"
@@ -16,7 +16,7 @@
 #ifndef TEXTENDEDBITMAPCOMMON_H
 #define TEXTENDEDBITMAPCOMMON_H
 
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 
 // Uid for use when testing an extended bitmap that does not need to be
 // drawn using the example rasterizer.
--- a/fbs/fontandbitmapserver/tfbs/tfbsbase.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/tfbsbase.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2008-2010 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"
@@ -16,7 +16,7 @@
 #ifndef TFBSBASE_H
 #define TFBSBASE_H
 
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 #include <f32file.h>
 
 #define INFO_PRINTF9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/tfbsglyphdata.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,3229 @@
+// Copyright (c) 2009-2010 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:
+//
+
+/**
+ @file
+ @internalComponent - Internal Symbian test code
+*/
+
+#include <EGL/egl.h>
+#include <VG/openvg.h>
+#include <graphics/fbsglyphmetricsarray.h> 
+#include <graphics/fbsglyphdataiterator.h>
+#include <sgresource/sgimage.h>
+#include <sgresource/sgdriver_test.h>
+#include <sgresource/sgdriver_profiling.h>
+#include "FbsMessage.h"
+#include "tfbsglyphdata.h"
+
+_LIT(KTypefaceName, "DejaVu Sans Condensed");
+//_LIT(KMonoTypefaceName, "DejaVu Sans Mono");
+const TInt KNumGlyphCodesLatin = 96;
+const TUint KDejaVuInvalidGlyphCode = 0;
+
+// Currently only used in debug. When TestMultithreadStressAtlas() test is enabled, #ifdef to be removed. 
+#ifdef _DEBUG
+const TInt KTestThreadMinHeapSize = 0x20000;
+const TInt KTestThreadMaxHeapSize = 0x20000;
+#endif
+
+// 'most significant bit' flag to ensure value is interpreted as a glyph code rather than an ascii code
+const TUint KGlyphCodeFlag = 0x80000000;      
+
+
+// Please note the following macros which enable helper functions, and are declared in the header.
+// SAVEGLYPHSTOMBMDURINGCOMPARISON and
+// SAVEGLYPHSTOMBMDEBUGFUNCTION
+
+/*
+Lookup table to convert from ascii code to
+glyph code for the Deja Vu family of fonts.
+ */
+const TUint DejaVuASCIIToGlyphCode[] = 
+	{
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 3, 4, 5, 6, 7, 8, 9, 10,
+	11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+	21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+	31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+	41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+	51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+	61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+	71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+	81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+	91, 92, 93, 94, 95, 96, 97, 98,
+	};
+
+// Utility function declations - utilities used by the tests
+static TFontSpec GenerateDejaVuFontSpec(TInt aSeed);
+static void CopyCharLine(TUint32*& aBinaryDataPtr,TInt aBufferWords,const TUint8* aData,TInt aBitShift,TInt aCharWidth, TInt16 aRepeatCount);
+static void DecodeBinaryData(const TSize& aDataSize, const TUint8* aData, TInt aStride,	TUint32* aBinaryData);
+static TInt CreateSgImageFromCharacterData(const TUint8* aData, const TSize& aSize, TGlyphBitmapType aType, RSgImage& aImage);
+static TInt CreateSgImageFromCharacterData(const TUint8* aData, const TSize& aSize, TGlyphBitmapType aType, RSgImage& aImage, TUint8* aBuffer1, TUint8* aBuffer2);
+// Following functions commented out because the tests which use these functions 
+// are currently commented out due to Broadcom defect 
+// ESLM-85LDV7 - TB10.1 Closing of RSgImage with duplicate handle used in same thread does not release GPU RAM
+//static TInt FillGraphicsMemoryWithImages(const TSize& aSize, RArray<RSgImage>& aImages);
+//static TInt NearlyFillGraphicsMemoryWithImages(const TSize& aSize, RArray<RSgImage>& aImages);
+
+#if defined (SAVEGLYPHSTOMBMDEBUGFUNCTION) || defined (SAVEGLYPHSTOMBMDURINGCOMPARISON)
+/**
+Static utility function. Converts an A8 RSgImage into a CFbsBitmap.
+To do this, the RSgImage is converted to an EGLImage, then to a VGImage,
+where the image memory is read into a CFbsBitmap.
+
+@param aEGL The EGL helper object that will read the SgImage into a memory buffer.
+@param aSgImage The RSgImage to convert.
+@param aRect A rectangular region of the RSgImage to convert.
+@param aBitmap On success, holds a pointer to a CFbsBitmap which contains the image
+	data of the RSgImage.
+@return One of the system-wide error codes.
+*/
+static TInt CreateBitmapFromSgImage(CEGLHelper* aEGL, const RSgImage& aSgImage, const TRect& aRect, CFbsBitmap*& aBitmap)
+	{
+	TInt err = KErrNone;
+	const TSize bufferSize = aRect.Size();
+	const TInt dataStride = bufferSize.iWidth;
+
+	TUint8* imageBuffer = reinterpret_cast<TUint8*>(User::AllocZ(bufferSize.iHeight * dataStride));
+	if (!imageBuffer)
+		{
+		return KErrNoMemory;
+		}
+	err = aEGL->GetSgImageData(aSgImage, aRect, imageBuffer);
+	if (err != KErrNone)
+		{
+		User::Free(imageBuffer);
+		return err;
+		}
+	aBitmap = new CFbsBitmap();
+	if (!aBitmap)
+		{
+		User::Free(imageBuffer);
+		return KErrNoMemory;
+		}
+
+	err = aBitmap->Create(bufferSize, EGray256);
+	if (KErrNone == err)
+		{
+		TUint8* buf = imageBuffer;
+		aBitmap->BeginDataAccess();
+		TUint8* dataAddress = reinterpret_cast<TUint8*>(aBitmap->DataAddress());
+		const TInt dataStride = aBitmap->DataStride();	
+		for (TInt scanline = 0; scanline < bufferSize.iHeight; scanline++)
+			{
+			Mem::Copy(dataAddress, buf, bufferSize.iWidth);
+			dataAddress += dataStride;
+			buf += bufferSize.iWidth;
+			}
+		aBitmap->EndDataAccess(EFalse);
+		}
+	else
+		{
+		delete aBitmap;
+		aBitmap = NULL;
+		}
+
+	User::Free(imageBuffer);
+	return err;
+	}
+
+/**
+Utility function to aid with debugging.
+Saves a bitmap to file.
+
+@param aBmp Bitmap to save
+@param aMeta Optional. If specified, it is added to the name of the bitmap file.
+@param aRef Flag to show whether bitmap is a reference bitmap (ETrue) or test bitmap (EFalse).
+*/
+static void SaveBmp(CFbsBitmap* aBmp, TPtrC* aMeta, TBool aRef)
+	{
+	if (!aBmp)
+		{
+		return;
+		}
+	
+	TBuf<256> testFileName;
+	if (aRef)
+		{
+		testFileName.Append(_L("Ref"));
+		}
+	else
+		{
+		testFileName.Append(_L("Test"));
+		}
+	if (aMeta)
+		{
+		testFileName.Append(*aMeta);
+		}
+
+	TFileName mbmFile;
+	TBuf<20> testPathName;
+	#ifdef __WINS__
+		testPathName.Append(_L("c:\\%S.mbm"));
+	#else
+		testPathName.Append(_L("e:\\%S.mbm"));
+	#endif
+	mbmFile.Format(testPathName, &testFileName);
+
+	// As this is for debugging purposes only, doesn't matter reporting whether
+	// saving succeeded or not.
+	aBmp->Save(mbmFile);
+	}
+#endif // SAVEGLYPHSTOMBMDEBUGFUNCTION OR SAVEGLYPHSTOMBMDURINGCOMPARISON
+
+
+#ifdef SAVEGLYPHSTOMBMDEBUGFUNCTION
+void CTFbsGlyphData::SaveRSgImagesAsMbms(CEGLHelper* aEGL, const RSgImage& aImageA, const TRect& aRectA, const RSgImage& aImageB, const TRect& aRectB )
+	{
+	static TInt countToAppend = 0;
+
+	CFbsBitmap* bitmap = NULL;
+	if (KErrNone == CreateBitmapFromSgImage(aEGL, aImageA, aRectA, bitmap))
+		{
+		TBuf<KMaxFileName> buf( _L("String") );
+		buf.AppendNum( countToAppend );
+		TPtrC nameAppend( buf );
+
+		SaveBmp(bitmap, &nameAppend, EFalse);
+		}
+	delete bitmap;  
+	bitmap = NULL;
+
+	if (KErrNone == CreateBitmapFromSgImage(aEGL, aImageB, aRectB, bitmap))
+		{
+		TBuf<KMaxFileName> buf( _L("String") );
+		buf.AppendNum( countToAppend );
+		TPtrC nameAppend( buf );
+
+		SaveBmp(bitmap, &nameAppend, ETrue);
+		}
+	delete bitmap;
+	bitmap = NULL;
+
+	countToAppend++;
+	}
+
+/**
+Static debug utility method that outputs the glyph images of the given glyph
+codes for the given font to a file.
+ */
+static void DumpFontGlyphs(CEGLHelper* aEGL, CFont* aFont, TInt aCodesCount)
+	{
+	TFontSpec fontSpec = aFont->FontSpecInTwips();
+	TOpenFontCharMetrics charMetrics;
+	TSize bitmapSize;
+	const TUint8* bitmapData = NULL;
+	
+	for (TInt glyphCode = 0; glyphCode < aCodesCount; glyphCode++)
+		{
+		CFont::TCharacterDataAvailability availability = aFont->GetCharacterData(glyphCode | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
+		if (availability == CFont::EAllCharacterData)
+			{
+			RSgImage characterDataImage;
+			TInt err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage);
+			if (err == KErrNone)
+				{
+				CFbsBitmap* bitmap = NULL;
+				err = CreateBitmapFromSgImage(aEGL, characterDataImage, TRect(TPoint(0, 0), bitmapSize), bitmap);
+				if (err == KErrNone)
+					{
+					TBuf<256> bitmapName;
+					bitmapName.AppendFormat(_L("%S-%i"), &(fontSpec.iTypeface.Name()), glyphCode);
+					TPtrC bitmapNamePtr(bitmapName);
+					SaveBmp(bitmap, &bitmapNamePtr, EFalse);
+					delete bitmap;
+					}
+				}
+			characterDataImage.Close();
+			}
+		}
+	}
+#endif // SAVEGLYPHSTOMBMDEBUGFUNCTION
+
+
+/**
+Utility to return a fontspec such that the font created from it will
+not match any other font generated by a different seed. The font
+will be useable by RFbsGlyphDataIterator and RFbsGlyphMetricsArray.
+It will always return a font based on the DejaVu fontspec, this is 
+so that the glyphcodes in DejaVuASCIIToGlyphCode are guaranteed to
+work.
+
+@param aSeed Specifies a variant of the fontspec to create. Passing the
+	same seed will cause the same TFontSpec to be returned.
+@return The generated fontspec. 
+ */
+static TFontSpec GenerateDejaVuFontSpec(TInt aSeed)
+	{
+	const TInt KFontHeightStep = 4;
+	const TInt KFontInitialHeight = 8;
+	
+	const TInt KNumFontTypefaces = 3;
+	const TInt KNumFontBitmapTypes = 2;
+	const TInt KNumFontStyles = 4;
+	
+	TInt fontBitmapTypeVariant = aSeed % KNumFontBitmapTypes;
+	TInt fontStyleVariant = (aSeed / KNumFontBitmapTypes) % KNumFontStyles;
+	TInt fontTypefaceVariant = (aSeed / ( KNumFontStyles * KNumFontBitmapTypes)) % KNumFontTypefaces;
+	TInt fontHeightVariant = aSeed / (KNumFontStyles * KNumFontTypefaces * KNumFontBitmapTypes);
+	
+	TFontSpec fontSpec;	
+	fontSpec.iHeight = KFontInitialHeight + (fontHeightVariant * KFontHeightStep);
+	// Set the typeface name
+	// Set the style.
+	switch (fontStyleVariant)
+		{
+		case 1: // italic
+			fontSpec.iFontStyle.SetPosture(EPostureItalic);
+			fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightNormal);
+			break;
+		case 2: // bold
+			fontSpec.iFontStyle.SetPosture(EPostureUpright);
+			fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
+			break;
+		case 3: // bold italic
+			fontSpec.iFontStyle.SetPosture(EPostureItalic);
+			fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
+			break;
+		default: // normal 
+			fontSpec.iFontStyle.SetPosture(EPostureUpright);
+			fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightNormal);
+			break;
+		}
+	switch (fontTypefaceVariant)
+		{
+		case 1:
+			fontSpec.iTypeface.SetName(_L("DejaVu Sans Mono"));
+			break;
+		case 2:
+			fontSpec.iTypeface.SetName(_L("DejaVu Serif Condensed"));
+			break;
+		case 3:
+			fontSpec.iTypeface.SetName(_L("DejaVu Sans Condensed"));
+			break;
+		}
+	switch(fontBitmapTypeVariant)
+		{
+		case 1:
+			fontSpec.iFontStyle.SetBitmapType(EMonochromeGlyphBitmap);
+			break;
+		default:
+			fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
+			break;
+		}
+
+	return fontSpec;
+	}
+
+
+/**
+ * 
+ EGL helper class to retrieve image data from an SgImage into a memory buffer.
+ */
+CEGLHelper::CEGLHelper() :
+	iDisplay(EGL_NO_DISPLAY),
+	iContext(EGL_NO_CONTEXT),
+	iSurface(EGL_NO_SURFACE)
+	{
+	}
+CEGLHelper::~CEGLHelper()
+	{
+	iMutex.Close();
+	eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+	eglDestroyContext(iDisplay, iContext);
+	eglDestroySurface(iDisplay, iSurface);
+	eglTerminate(iDisplay);
+	eglReleaseThread();
+	iSgDriver.Close();
+	}
+
+/**
+Factory method to create CEGLHelper.
+@return A pointer to an instance of CEGLHelper.
+ */
+CEGLHelper* CEGLHelper::NewL()
+	{
+	CEGLHelper* self = new CEGLHelper();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(1); // self
+	return self;
+	}
+
+/**
+Opens handle to the process-wide synchronisation semaphore,
+loads EGL and VG extension function pointers,
+sets up EGL resources so that EGLImages can be constructed. 
+ */
+void CEGLHelper::ConstructL()
+	{
+	_LIT(KEGLMutex, "TFbsGlyphDataEGLMutex");
+	User::LeaveIfError(iMutex.CreateGlobal(KEGLMutex, EOwnerProcess));
+	User::LeaveIfError(iSgDriver.Open());
+
+	iDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+	if (iDisplay == EGL_NO_DISPLAY)
+		{
+		User::Leave(KErrNotSupported);
+		}
+	if (EGL_TRUE != eglInitialize(iDisplay, NULL, NULL))
+		{
+		User::Leave(KErrNotSupported);
+		}
+	eglBindAPI(EGL_OPENVG_API);
+
+	// Load the necessary EGL extensions...
+	eglCreateImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
+	eglDestroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
+	vgCreateImageTargetKHR = reinterpret_cast<TvgCreateEGLImageTargetKHRTypefPtr>(eglGetProcAddress("vgCreateEGLImageTargetKHR"));
+	if (!eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateImageTargetKHR)
+		{
+		User::Leave(KErrExtensionNotSupported);
+		}
+
+	// In order to create VGImages from EGLImages, a context must be current.
+	// Therefore create an EGLContext and EGLSurface to make current, using
+	// a dummy RSgImage.
+
+	RSgImage dummySurface;
+	TSgImageInfo dummySurfaceInfo(TSize(1, 1), ESgPixelFormatRGB_565, ESgUsageBitOpenVgSurface);
+	User::LeaveIfError(dummySurface.Create(dummySurfaceInfo, NULL, 0));
+	CleanupClosePushL(dummySurface);
+
+	EGLint configAttribs[] = 
+		{
+		EGL_MATCH_NATIVE_PIXMAP, (EGLint)&dummySurface,
+		EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
+		EGL_NONE
+		};
+
+	EGLint configId = 0;
+	EGLint numConfigs = 0;
+	if (EGL_FALSE == eglChooseConfig(iDisplay, configAttribs, &configId, 1, &numConfigs) || numConfigs == 0)
+		{
+		User::Leave(KErrGeneral);
+		}
+	iContext = eglCreateContext(iDisplay, configId, EGL_NO_CONTEXT, NULL);
+	if (iContext == EGL_NO_CONTEXT)
+		{
+		User::Leave(KErrGeneral);
+		}
+	iSurface = eglCreatePixmapSurface(iDisplay, configId, &dummySurface, NULL);
+	if (iSurface == EGL_NO_SURFACE)
+		{
+		User::Leave(KErrGeneral);
+		}
+	CleanupStack::PopAndDestroy(1); // dummySurface
+	}
+
+/**
+Retrieves the data from an A8 RSgImage into a buffer.
+To do this, the RSgImage is converted to an EGLImage, then to a VGImage,
+where the image memory is read into the given buffer.
+The function can be called from multiple threads and synchronisation
+with EGL is controlled via a mutex.
+
+@param aSgImage The RSgImage to convert.
+@param aRect A rectangular region of the RSgImage to convert.
+@param aBuf On success, contains the image data of the RSgImage.
+@return One of the system-wide error codes.
+ */
+TInt CEGLHelper::GetSgImageData(const RSgImage& aSgImage, const TRect& aRect, TUint8*& aBuf)
+	{
+	const TSize bufferSize = aRect.Size();
+	const TInt dataStride = bufferSize.iWidth;
+
+	if (bufferSize == TSize(0,0))
+		{
+		return KErrNone;
+		}
+	iMutex.Wait();
+
+	TInt err = KErrNone;
+	EGLImageKHR eglImage;
+	if (EGL_FALSE == eglBindAPI(EGL_OPENVG_API))
+		{
+		err = KErrGeneral;
+		}
+	else if (EGL_FALSE == eglMakeCurrent(iDisplay, iSurface, iSurface, iContext))
+		{
+		err = KErrGeneral;
+		}
+	else
+		{
+		// Create EGLImages from the RSgImage.
+		EGLint imageAttribs[] =
+			{
+			EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, 
+			EGL_NONE
+			};
+		eglImage = eglCreateImageKHR(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, reinterpret_cast<EGLClientBuffer>(&aSgImage), imageAttribs);
+		if (eglImage == EGL_NO_IMAGE_KHR)
+			{
+			err = KErrArgument;
+			}
+		}
+	if (err == KErrNone)
+		{
+		// Create VGImages from the EGLImage.
+		VGImage vgImage = vgCreateImageTargetKHR(eglImage);
+		eglDestroyImageKHR(iDisplay, eglImage);
+		if (vgImage == VG_INVALID_HANDLE)
+			{
+			err = KErrArgument;
+			}
+		else
+			{
+			// Get the image data in 8bpp format
+			vgGetImageSubData(vgImage, aBuf, dataStride, VG_A_8, aRect.iTl.iX, aRect.iTl.iY, bufferSize.iWidth, bufferSize.iHeight);
+			vgDestroyImage(vgImage);
+			}
+		}
+	eglReleaseThread();
+	iMutex.Signal();
+	return err;
+	}
+
+CTFbsGlyphData::CTFbsGlyphData(CTestStep* aStep):
+	CTGraphicsBase(aStep)
+	{
+	}
+
+void CTFbsGlyphData::ConstructL()
+	{
+	User::LeaveIfError(Logger().ShareAuto());
+	User::LeaveIfError(RFbsSession::Connect());
+	iFbs = RFbsSession::GetSession();
+	iTs = (CFbsTypefaceStore*)CFbsTypefaceStore::NewL(NULL);
+	User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont, TFontSpec(KTypefaceName, 15)));
+	User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont2, TFontSpec(KTypefaceName, 8)));
+	
+	iGlyphCodesLatin = new(ELeave) TUint[KNumGlyphCodesLatin];
+	for (TInt ii = 0; ii < KNumGlyphCodesLatin; ++ii)
+		{
+		TUint asciiCode = ii+0x20; // ASCII characters from 0020 to 007F
+		iGlyphCodesLatin[ii] = DejaVuASCIIToGlyphCode[asciiCode];
+		}
+	
+	User::LeaveIfError(iSgDriver.Open());
+	iEGL = CEGLHelper::NewL();
+	
+	// Creating a CFbsBitmap will force the RFbsSession to allocate a scanline buffer
+	// now rather than in the middle of a test, thus avoiding heap check failure. 
+	CFbsBitmap* dummyBitmap = new (ELeave) CFbsBitmap;
+	CleanupStack::PushL(dummyBitmap);
+	User::LeaveIfError(dummyBitmap->Create(TSize(512, 1), EGray256));
+	CleanupStack::PopAndDestroy(dummyBitmap);
+
+	INFO_PRINTF1(_L("FBSERV Glyph Data Testing"));
+	}
+
+
+
+
+CTFbsGlyphData::~CTFbsGlyphData()
+	{
+	delete iEGL;
+	iSgDriver.Close();
+	if (iTs)
+		{
+		iTs->ReleaseFont(iFont);
+		iTs->ReleaseFont(iFont2);
+		}
+	delete iTs;
+	delete[] iGlyphCodesLatin;
+	User::Free(iTempBuf1);
+	User::Free(iTempBuf2);
+	RFbsSession::Disconnect();
+	}
+
+void CTFbsGlyphData::RunTestCaseL(TInt aCurTestCase)
+	{
+	((CTFbsGlyphDataStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
+	
+	TRAPD(leave, 
+
+	switch(aCurTestCase)
+		{
+	case 1:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0624"));
+		TestConsistencyWithGetCharacterData();
+		break;
+	case 2:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0625"));
+		TestInvalidGlyphCode();
+		break;
+	case 3:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0626"));
+		TestGlyphMetricsArrayParameters();
+		break;
+	case 4:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0627"));
+		TestGlyphMetricsArrayReuse();
+		break;
+	case 5:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0628"));
+		TestGlyphDataIteratorClose();
+		break;
+	case 6:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0629"));
+		TestGlyphDataIteratorSequence();
+		break;	
+	case 7:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0632"));
+		TestGlyphDataIteratorMultipleUsesOnMultipleFonts();
+		break;
+	case 8:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0633"));
+		TestGlyphDataIteratorImageValidity();
+		break;
+	case 9:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0634"));
+		TestGlyphDataIteratorOpenInvalidCode();
+		break;
+	case 10:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0636"));
+		TestGlyphDataIteratorOpenTwice();
+		break;
+	case 11:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0637"));
+		TestGlyphDataIteratorOpenTwiceWithDifferentFonts();
+		break;
+	case 12:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0638"));
+		TestGlyphDataIteratorOpenTooBigFont();
+		break;
+	case 13:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0640"));
+		TestGlyphDataIteratorOpenWithWrongArgument();
+		break;
+	case 14:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0641"));
+		TestGlyphDataIteratorImageMemoryLeak();
+		break;
+	case 15:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0662"));
+		TestGlyphDataIteratorNoGraphicsMemory();
+		break;
+	case 16: 
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0659"));
+		TestGlyphDataIteratorLargeFontStress();
+		break;
+	case 17: 
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0660"));
+		TestGlyphDataIteratorManyFontsStressL();
+		break;
+	case 18:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0666"));
+		TestGlyphDataIteratorNextIsAtomic();
+		break;
+	case 19:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0665"));
+		TestGlyphDataIteratorSameGlyphCodes();
+		break;
+	case 20:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0668"));
+		TestGlyphDataIteratorManyArraySizes();
+		break;
+	case 21:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0669"));
+		TestBitmapFontSupport();
+		break;
+	case 22:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0671"));
+		TestMultithreadShareSingleFont();
+		break;
+	case 23:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0672"));
+		TestMultithreadStressAtlas();
+		break;
+    case 24:
+        ((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0673"));
+        TestGlyphMetricsArrayHeapOOML();
+        break;
+    case 25:
+        ((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0674"));
+        TestGlyphDataIteratorHeapOOML();
+        break;
+	default:
+		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
+		((CTFbsGlyphDataStep*)iStep)->CloseTMSGraphicsStep();
+		TestComplete();
+		break;
+		}
+	
+	); // TRAPD
+
+	if (leave != KErrNone)
+		{
+		ERR_PRINTF2(_L("Leave %d occurred during test"), leave);
+		iStep->SetTestStepResult(EFail);
+		}
+
+	((CTFbsGlyphDataStep*)iStep)->RecordTestResultL();
+	}
+
+
+/**
+@SYMTestCaseID		GRAPHICS-FBSERV-0624
+@SYMTestPriority	High
+@SYMTestType		UT
+@SYMTestStatus		Implemented
+@SYMPREQ			PREQ2678
+
+@SYMTestCaseDesc
+	Shows that RFbsGlyphMetricsArray::Get() and CFont::GetCharacterData() all 
+	provide the same metrics for the same set of glyph codes when using a CFbsFont.
+	Shows that RFbsGlyphDataIterator::Metrics() and CFont::GetCharacterData()
+	provide the same metrics for the same set of glyph codes.
+
+@SYMTestActions
+	i. Call RFbsGlyphMetricsArray::Get() for a set of glyph codes with 1 glyph code per call.
+	ii. Call RFbsGlyphMetricsArray::Get() for a set of glyph codes all in 1 call.
+	iii. Call RFbsGlyphDataIterator::Open() for a set of glyph codes.
+	iv. Call CFont::GetCharacterData() for the same set of glyph codes.
+	v. Compare the metrics for each glyph code from all calls.
+
+@SYMTestExpectedResults
+	For each glyph code, metrics received from RFbsGlyphMetricsArray::Get() and
+	CFont::GetCharacterData() and RFbsGlyphDataIterator are all the same.
+*/
+void CTFbsGlyphData::TestConsistencyWithGetCharacterData()
+	{
+	INFO_PRINTF1(_L("Test RFbsGlyphMetricsArray::Get() with GetCharacterData()"));
+	
+	__UHEAP_MARK;
+
+	RFbsGlyphDataIterator iter;
+	RFbsGlyphMetricsArray glyphMetricsArray;
+	RFbsGlyphMetricsArray glyphMetricsArraySingle;
+	
+	TInt numMismatches = 0;
+	TOpenFontCharMetrics charMetrics;
+	TSize bitmapSize;
+	const TUint8* bitmapData = NULL;
+	
+	// Retrieve list of metrics for all glyph codes in one call
+	TInt err = glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
+	TESTNOERROR(err);
+	if (err == KErrNone)
+		{
+		TEST(KNumGlyphCodesLatin == glyphMetricsArray.Count());
+		
+		TInt index = 0;
+		TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
+		TESTNOERROR(iterErr);
+		for (; iterErr == KErrNone; iterErr = iter.Next(), index++)
+			{
+			iFont->GetCharacterData(iGlyphCodesLatin[index] | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
+			
+			// Retrieve the metrics for each glyph code, one at a time
+			TESTNOERROR(err = glyphMetricsArraySingle.Get(*iFont, &iGlyphCodesLatin[index], 1));
+			if (KErrNone == err)
+				{
+				// Compare GetCharacterData() metrics with single RFbsGlyphMetricsArray.
+				TUint32 comparison1 = CompareMetrics(charMetrics, glyphMetricsArraySingle[0]); 
+				// Compare GetCharacterData() metrics with large RFbsGlyphMetricsArray.
+				TUint32 comparison2 = CompareMetrics(charMetrics, glyphMetricsArray[index]);
+				// Compare GetCharacterData() metrics with RFbsGlyphDataIterator.
+				TUint32 comparison3 = CompareMetrics(charMetrics, iter.Metrics());
+				if (comparison1 != 0 || comparison2 != 0 || comparison3 != 0)
+					{
+					ERR_PRINTF5(_L("Glyphcode %i : Metrics mismatch: %d/%d/%d"), iGlyphCodesLatin[index], comparison1, comparison2, comparison3);
+					++numMismatches;
+					}
+				}
+			}
+			iter.Close();
+			glyphMetricsArray.Close();
+			glyphMetricsArraySingle.Close();
+			TESTE(iterErr == KErrNotFound, iterErr);
+			TEST(numMismatches == 0);
+			TEST(index == KNumGlyphCodesLatin);
+		}		
+	
+	__UHEAP_MARKEND;
+	}
+
+/**
+@return A series of success/fail booleans as a bitmask. A return value of zero
+	indicates all tests passed, a result of 1 indicates the first test case failed, 
+	a return of 3 indicates the first and second test failed, and so on.
+*/
+TUint32 CTFbsGlyphData::CompareMetrics(const TOpenFontCharMetrics& aMetrics1, const TOpenFontCharMetrics& aMetrics2)
+	{
+	TUint32 result = 0;
+	result |= (aMetrics1.Width() == aMetrics2.Width()) ? 0 : (1 << 0);
+	result |= (aMetrics1.Height() == aMetrics2.Height()) ? 0 : (1 << 1);
+	result |= (aMetrics1.HorizBearingX() == aMetrics2.HorizBearingX()) ? 0 : (1 << 2);
+	result |= (aMetrics1.HorizBearingY() == aMetrics2.HorizBearingY()) ? 0 : (1 << 3);
+	result |= (aMetrics1.HorizAdvance() == aMetrics2.HorizAdvance()) ? 0 : (1 << 4);
+	result |= (aMetrics1.VertBearingX() == aMetrics2.VertBearingX()) ? 0 : (1 << 5);
+	result |= (aMetrics1.VertBearingY() == aMetrics2.VertBearingY()) ? 0 : (1 << 6);
+	result |= (aMetrics1.VertAdvance() == aMetrics2.VertAdvance()) ? 0 : (1 << 7);
+	TRect rect1;
+	aMetrics1.GetHorizBounds(rect1);
+	TRect rect2;
+	aMetrics2.GetHorizBounds(rect2);
+	result |= (rect1 == rect2) ? 0 : (1 << 8);
+	aMetrics1.GetVertBounds(rect1);
+	aMetrics2.GetVertBounds(rect2);
+	result |= (rect1 == rect2) ? 0 : (1 << 9);
+	return result;
+	}
+
+
+/**
+@SYMTestCaseID		GRAPHICS-FBSERV-0625
+@SYMTestPriority	High
+@SYMTestType		UT
+@SYMTestStatus		Implemented
+@SYMPREQ			PREQ2678
+
+@SYMTestCaseDesc
+	Shows that RFbsGlyphMetricsArray::Get(), and CFont::GetCharacterData() show the same 
+	behaviour when asked for metrics for an invalid glyph code when using a	CFbsFont. 
+	An invalid glyph code is one for which there is no character equivalent, such as 
+	0.
+
+@SYMTestActions
+	i. Call CFont::GetCharacterData() for an invalid glyph code.
+	ii. Call RFbsGlyphMetricsArray::Get() for the same invalid glyph code, and either 
+		compare the metrics if i. was successful, or check an error code was returned
+	
+@SYMTestExpectedResults
+	If GetCharacterData() is successful, the metrics received from
+	RFbsGlyphMetricsArray::Get() and CFont::GetCharacterData()	are the same, otherwise
+	RFbsGlyphMetricsArray::Get() should return an error code.
+*/
+
+void CTFbsGlyphData::TestInvalidGlyphCode()
+	{
+	INFO_PRINTF1(_L("Test behaviour of RFbsGlyphMetricsArray::Get() with invalid glyph code is consistent with GetCharacterData"));
+	
+	__UHEAP_MARK;
+	TInt arrayErr = KErrNone;
+	RFbsGlyphMetricsArray glyphMetricsArray;
+	TOpenFontCharMetrics charMetrics;
+	TSize bitmapSize;
+	const TUint8* bitmapData = NULL;
+	
+	CFont::TCharacterDataAvailability availability = iFont->GetCharacterData(KDejaVuInvalidGlyphCode | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
+	if (availability == CFont::ENoCharacterData)
+		{
+		// Some rasterizers fail to return any data for KDejaVuInvalidGlyphCode, therefore
+		// rather than compare metrics, make sure RFbsGlyphDataIterator returns an error code.
+		WARN_PRINTF1(_L("Rasterizer failed to return data for invalid glyph code; not comparing glyph metrics"));
+		arrayErr = glyphMetricsArray.Get(*iFont, &KDejaVuInvalidGlyphCode, 1);
+		TESTE(arrayErr != KErrNone, arrayErr);
+		}
+	else
+		{
+		TESTNOERROR(arrayErr = glyphMetricsArray.Get(*iFont, &KDejaVuInvalidGlyphCode, 1));
+		if (KErrNone == arrayErr)
+			{
+			iFont->GetCharacterData(KDejaVuInvalidGlyphCode | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
+			TUint comparisonResult = CompareMetrics(charMetrics, glyphMetricsArray[0]);
+			TESTNOERROR( comparisonResult );
+			}
+		}
+	glyphMetricsArray.Close();
+
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID		GRAPHICS-FBSERV-0626
+@SYMTestPriority	High
+@SYMTestType		UT
+@SYMTestStatus		Implemented
+@SYMPREQ			PREQ2678
+
+@SYMTestCaseDesc
+	Shows that RFbsGlyphMetricsArray::Get() returns with the correct error code when passed
+	various combinations of parameters, and preserves the state of the array.
+
+@SYMTestActions
+	Populate the array with a single metrics entry.
+	Call RFbsGlyphMetricsArray::Get with the following parameter combinations:
+		1. A negative count
+		2. A positive count and null glyph code array pointer
+		3. A zero count and non-null glyph code array pointer
+		4. A zero count and null glyph code array pointer
+
+@SYMTestExpectedResults
+	The following return codes are expected for each call:
+		1. KErrArgument
+		2. KErrArgument
+		3. KErrArgument
+		4. KErrArgument	
+	For each case the glyph metrics array remains unchanged.
+*/
+void CTFbsGlyphData::TestGlyphMetricsArrayParameters()
+	{
+	INFO_PRINTF1(_L("Test the return values of GetGlyphMetrics with different parameters"));
+	__UHEAP_MARK;
+	TInt arrayErr = KErrNone;
+	TOpenFontCharMetrics dummyMetrics;
+	
+	RFbsGlyphMetricsArray glyphMetricsArray;
+	arrayErr = glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, 1);
+	TESTNOERROR(arrayErr);
+	TEST(1 == glyphMetricsArray.Count());
+	
+	// 1. Negative Count
+	arrayErr = glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, -1);
+	TESTE(KErrArgument == arrayErr, arrayErr);
+	TEST(1 == glyphMetricsArray.Count());
+	
+	// 2. Positive Count and NULL Array Pointer
+	arrayErr = glyphMetricsArray.Get(*iFont, NULL, 1);
+	TESTE(KErrArgument == arrayErr, arrayErr);
+	TEST(1 == glyphMetricsArray.Count());
+
+	// 3. Zero Count & Valid Array Pointer
+	arrayErr = glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, 0);
+	TESTE(KErrArgument == arrayErr, arrayErr);
+
+	// 4. Zero Count & NULL Array Pointer
+	arrayErr = glyphMetricsArray.Get(*iFont, NULL, 0);
+	TESTE(KErrArgument == arrayErr, arrayErr);
+
+	glyphMetricsArray.Close();
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID		GRAPHICS-FBSERV-0627
+@SYMTestPriority	High
+@SYMTestType		UT
+@SYMTestStatus		Implemented
+@SYMPREQ			PREQ2678
+
+@SYMTestCaseDesc
+	Shows that reusing an RFbsGlyphMetricsArray works correctly.
+	In particular when the array is reused and filled with fewer entries
+	and when the array is reused and filled with more entries than previously.
+	It also shows that when re-using an array that has been populated, memory 
+	is not de-allocated if the new array of glyphs is smaller.
+
+@SYMTestActions
+	i. Call RFbsGlyphMetricsArray::Get() for a set of 10 glyph codes.
+	ii. Check that the RFbsGlyphMetricsArray has 10 entries.
+	iii. Find the size of the heap-cell allocated to the array.
+	iii. Call RFbsGlyphMetricsArray::Get() for a set of 5 glyph codes.
+	iv. Check that the RFbsGlyphMetricsArray has 5 entries.
+	v. Call RFbsGlyphMetricsArray::Get() for a set of 20 glyph codes.
+	vi. Check that the RFbsGlyphMetricsArray has 20 entries.
+	vii. Call RFbsGlyphMetricsArray::Get() for a set of 0 glyph codes.
+	viii. Check that the RFbsGlyphMetricsArray has 0 entries.
+	ix. Call RFbsGlyphMetricsArray::Get() for 1 glyph code.
+	x. Check that the RFbsGlyphMetricsArray has 1 entries.
+	xi. Close the RFbsGlyphMetricsArray.
+	xii. Check that the RFbsGlyphMetricsArray has 0 entries.
+	During the test check that the size of the heap cell allocated to the array
+	does not shrink.
+
+@SYMTestExpectedResults
+	After each call to RFbsGlyphMetricsArray::Get(), the array has the expected number of entries.
+*/
+void CTFbsGlyphData::TestGlyphMetricsArrayReuse()
+	{
+	INFO_PRINTF1(_L("Test reuse of array with RFbsGlyphMetricsArray"));
+	__UHEAP_MARK;
+	
+	RFbsGlyphMetricsArray glyphMetricsArray;
+
+	// Retrieve list of metrics for 10 glyph codes
+	TESTNOERROR(glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, 10));
+	TEST(10 == glyphMetricsArray.Count());
+	
+	// Find the size of the heap cell allocated for the array.
+	TInt arrayHeapCellSize = User::Heap().AllocLen(&glyphMetricsArray[0]);
+	
+	// Retrieve list of metrics for 5 glyph codes.
+	// To ensure that different metrics are returned, use different glyph codes
+	TESTNOERROR(glyphMetricsArray.Get(*iFont, &iGlyphCodesLatin[10], 5));
+	TEST(5 == glyphMetricsArray.Count());
+	// Check that memory has not been de-allocated for a smaller array.
+	TEST(User::Heap().AllocLen(&glyphMetricsArray[0]) == arrayHeapCellSize);
+
+	// Retrieve list of metrics for 20 glyph codes.
+	// To ensure that different metrics are returned, use different glyph codes
+	TESTNOERROR(glyphMetricsArray.Get(*iFont, &iGlyphCodesLatin[15], 20));
+	TEST(20 == glyphMetricsArray.Count());
+	arrayHeapCellSize = User::Heap().AllocLen(&glyphMetricsArray[0]);
+		
+	// Retrieve list of metrics for 0 glyph codes.
+	TEST(KErrArgument == glyphMetricsArray.Get(*iFont, &iGlyphCodesLatin[35], 0));
+	// We can't check whether memory has been de-allocated as glyphMetricsArray[0]
+	// is null, therefore dereferencing it causes a panic.
+
+	// Retrieve list of metrics for 1 glyph code.
+	// To ensure that different metrics are returned, use different glyph code
+	TESTNOERROR(glyphMetricsArray.Get(*iFont, &iGlyphCodesLatin[35], 1));
+	TEST(1 == glyphMetricsArray.Count());
+	TEST(User::Heap().AllocLen(&glyphMetricsArray[0]) == arrayHeapCellSize);
+	
+	// Test that after closing a non-empty array, the array has 0 size.
+	glyphMetricsArray.Close();
+	TEST(0 == glyphMetricsArray.Count());
+	
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID		GRAPHICS-FBSERV-0628
+@SYMTestPriority	High
+@SYMTestType		UT
+@SYMTestStatus		Implemented
+@SYMPREQ			PREQ2678
+
+@SYMTestCaseDesc
+	Validates the behaviour of RFbsGlyphDataIterator::Close() in the following use cases:
+		1. When called on an iterator instance which has not been opened, has no effect.
+		2. When called on an open iterator closes the iterator 
+
+@SYMTestActions
+	Use case 1:
+		i. Create an RFbsGlyphDataIterator instance but do not open.
+		ii. Call RFbsGlyphDataIterator::Close().
+		
+	Use case 2:
+		i. Create an RFbsGlyphDataIterator instance and call RFbsGlyphDataIterator::Open().
+		ii. Call RFbsGlyphDataIterator::Next() to prove the iterator is open.
+		iii. Call RFbsGlyphDataIterator::Close().
+		iv. Check that RFbsGlyphDataIterator::IsOpen() returns false.
+	
+@SYMTestExpectedResults
+	Each call to RFbsGlyphDataIterator::IsOpen() returns the expected value.
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorClose()
+	{
+	INFO_PRINTF1(_L("Test closing an RFbsGlyphDataIterator"));
+	__UHEAP_MARK;
+
+	// Use case 1
+	RFbsGlyphDataIterator iter1;
+	iter1.Close();
+
+	// Use case 2
+	RFbsGlyphDataIterator iter2;
+	TESTNOERROR(iter2.Open(*iFont, iGlyphCodesLatin, 1));
+	TInt iterErr = iter2.Next();
+	TESTE(KErrNotFound == iterErr, iterErr);
+	iter2.Close();
+	
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID		GRAPHICS-FBSERV-0629
+@SYMTestPriority	High
+@SYMTestType		UT
+@SYMTestStatus		Implemented
+@SYMPREQ			PREQ2678
+
+@SYMTestCaseDesc
+	Show that the sequence of iterations when calling RFbsGlyphDataIterator::Next()
+	matches the order of the array of glyph codes.
+
+@SYMTestActions
+	i. Create an RFbsGlyphDataIterator instance and call RFbsGlyphDataIterator::Open()
+		with an array of different glyph codes.
+	ii. Iterate through all the glyph data.
+		For each iteration check that the glyph code returned from 
+		RFbsGlyphDataIterator::GlyphCode() matches the corresponding glyph code
+		passed into Open().
+
+@SYMTestExpectedResults
+	Each comparison of glyph code should match.
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorSequence()
+	{
+	INFO_PRINTF1(_L("Test the iterator sequence of RFbsGlyphDataIterator"));
+	__UHEAP_MARK;
+	
+	TBool matches = ETrue;
+	TInt index = 0;
+
+	RFbsGlyphDataIterator iter;
+	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
+	TESTNOERROR(iterErr);
+	for (; index < KNumGlyphCodesLatin && matches && (iterErr == KErrNone); iterErr = iter.Next(), index++)
+		{
+		if (iter.GlyphCode() != iGlyphCodesLatin[index])
+			{
+			ERR_PRINTF4(_L("Failed at iteration %d: wanted %d, got %d"), index, iGlyphCodesLatin[index], iter.GlyphCode());
+			matches = EFalse;
+			}
+		}
+	iter.Close();
+	TESTE(iterErr == KErrNotFound, iterErr);
+	TEST(matches);
+	TEST(index == KNumGlyphCodesLatin);
+	iter.Close();
+
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID		GRAPHICS-FBSERV-0632
+@SYMTestPriority	High
+@SYMTestType		UT
+@SYMTestStatus		Implemented
+@SYMPREQ			PREQ2678
+
+@SYMTestCaseDesc
+	Ensure it is possible to reuse a closed iterator on another CFbsFont.
+	
+@SYMTestActions
+	i. Open an RFbsGlyphDataIterator with sample data.
+	ii. Iterate through until the end of the iterator has been reached by calling 
+		Next() on the final element.
+	iii. Re-open the same RFbsGlyphDataIterator with sample data on a different CFbsFont.
+	iv. Iterate through a second time until the end has been reached by calling Next()
+		on the final element.
+	v. Close the iterator.
+	vi. During both iterations the bitmap data returned and metrics are compared with
+		the equivalent from GetCharacterData().
+
+@SYMTestExpectedResults
+	The iterator should be opened successfully for both fonts and the data returned
+	should match the data from GetCharacterData().
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorMultipleUsesOnMultipleFonts()
+	{
+	INFO_PRINTF1(_L("Reuse a closed iterator on a second CFbsFont"));
+	__UHEAP_MARK;
+	
+	const TUint8* bitmapData;
+	TSize bitmapSize;
+	TOpenFontCharMetrics charMetrics;
+	RFbsGlyphDataIterator iter;
+	
+	// Array of fonts to iterate through.
+	CFbsFont* font[2] = {iFont, iFont2};
+	
+	for (TInt fontId = 0; fontId < 2; fontId++)
+		{
+		// On the first iteration, open and use a font until all glyphs have been iterated through.
+		// On second iteration, use the same iterator on a different font and repeat.
+        CFbsFont* currentFont = font[fontId];
+
+		//Open the iterator on the first font and compare the returned bitmaps against GetCharacterData
+		TInt iterErr = iter.Open(*currentFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
+		TESTNOERROR(iterErr);
+		TFontSpec fontSpec = currentFont->FontSpecInTwips();
+		
+		TInt index = 0;
+		for (; (iterErr == KErrNone) && (index < KNumGlyphCodesLatin); iterErr = iter.Next(), ++index)
+			{
+			currentFont->GetCharacterData(iGlyphCodesLatin[index] | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
+			
+			TESTNOERROR(CompareMetrics(charMetrics, iter.Metrics()));
+			if (bitmapSize == TSize(0, 0))
+				{
+				TEST(bitmapSize == iter.Rect().Size());
+				}
+			else
+				{
+				// Compare images.
+				TBool match = EFalse;
+				RSgImage characterDataImage;
+				TInt err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage);
+				if (err == KErrNone)
+					{
+					err = CompareSgImages(iEGL, iter.Image(), iter.Rect(), characterDataImage, TRect(bitmapSize), match);
+					}
+				characterDataImage.Close();
+				if (err != KErrNone)
+					{
+					TESTNOERROR(err);
+					break;
+					}
+				TEST(match);
+				}		
+			}
+		iter.Close();
+		TESTE(iterErr == KErrNotFound, iterErr);
+		TEST(index == KNumGlyphCodesLatin);
+		}
+	
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID		GRAPHICS-FBSERV-0633
+@SYMTestPriority	High
+@SYMTestType		UT
+@SYMTestStatus		Implemented
+@SYMPREQ			PREQ2678
+
+@SYMTestCaseDesc
+	Check that for various Latin fonts, the images of the glyphs stored on the 
+	RSgImage matches those provided by GetCharacterData().
+
+@SYMTestActions
+	Create a selection of fonts, using various typefaces, sizes and bitmap types.
+	For each font:
+	i. Open the RFbsGlyphDataIterator and iterate each glyph.
+	ii. For each glyph, call GetCharacterData() with the expected glyph code.
+	iii. Convert the character data to an RSgImage.
+	iv. Perform a comparison between the character RSgImage and the iterator 
+		image. 
+	v. After all iterations, close the iterator and check all expected glyphs
+		were iterated through.
+
+@SYMTestExpectedResults
+	All glyph images should match.
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorImageValidity()
+	{
+	INFO_PRINTF1(_L("Test the glyph images of the iterator match GetCharacterData()"));
+	__UHEAP_MARK;
+	
+	const TInt KNumFonts = 20;
+	
+	// Create a new typeface store for this test so that heap checking will not
+	// be affected by cached CFbsFonts.
+	CFbsTypefaceStore* typefaceStore = NULL;
+	TRAPD(err, typefaceStore = CFbsTypefaceStore::NewL(NULL));
+	if (err != KErrNone)
+		{
+		ERR_PRINTF1(_L("Failed to construct typeface store. Test aborted."));
+		__UHEAP_RESET;
+		iStep->SetTestStepResult(EFail);
+		return;
+		}
+	
+	for (TInt font = 0; font < KNumFonts; ++font)
+		{
+		// Use either a pre-created bitmap-font TFontSpec, or generate a Deja-vu one.
+		TFontSpec fontSpec = GenerateDejaVuFontSpec(font);
+		CFbsFont* latinFont = NULL;
+		TESTNOERROR(typefaceStore->GetNearestFontToDesignHeightInPixels((CFont*&)latinFont, fontSpec));	
+		
+		fontSpec = latinFont->FontSpecInTwips();
+		InfoPrintFontSpec(*latinFont);
+				
+		RFbsGlyphDataIterator iter;
+		TInt iterErr = iter.Open(*latinFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
+		TESTNOERROR(iterErr);
+
+		err = KErrNone;
+		TInt index = 0;
+		TInt numMismatches = 0;
+		// For each iteration, get the character data of the expected glyph.
+		// Create RSgImage from character data, and compare iter image with constructed image.
+		for (; (iterErr == KErrNone) && (err == KErrNone) && (index < KNumGlyphCodesLatin); (iterErr = iter.Next()), ++index)
+			{
+			TBool glyphMatches = ETrue;
+			const RSgImage& iteratorImage = iter.Image();
+
+			const TUint8* bitmapData = NULL;
+			TSize bitmapSize;
+			TOpenFontCharMetrics metrics;
+			TInt characterDataAvailability = latinFont->GetCharacterData(iGlyphCodesLatin[index] | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
+			if (bitmapSize == TSize(0, 0))
+				{
+				glyphMatches = (bitmapSize == iter.Rect().Size());
+				}
+			else
+				{
+				RSgImage characterDataImage;
+				TESTNOERROR(CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage));
+				err = CompareSgImages(iEGL, iteratorImage, iter.Rect(), characterDataImage, TRect(bitmapSize), glyphMatches);
+				characterDataImage.Close();
+				}
+			if (err == KErrNone && !glyphMatches)
+				{
+				ERR_PRINTF2(_L("Glyphcode %i : Image mismatch"), iGlyphCodesLatin[index]);
+				++numMismatches;
+				}
+			}
+		iter.Close();
+		TESTNOERROR(err);
+		TESTE(iterErr == KErrNotFound, iterErr);
+		TEST(index == KNumGlyphCodesLatin);	
+		TEST(numMismatches == 0);
+		typefaceStore->ReleaseFont(latinFont);
+		}
+	delete typefaceStore;
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0634
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that if the glyph image iterator has a current invalid 
+	character code, the SgImage returned by the iterator will match 
+	to the image obtained from the GetCharacterData() function
+@SYMTestActions
+	i. Retrieve bitmap data and metrics by using GetCharacterData().
+	ii. Open a glyph data iterator passing an invalid character code.
+	iii. If i. was unsuccessful, check that opening the iterator returned
+		an error code and skip to ix.
+	iv. Create SgImage from bitmap data.
+	v. Get SgImage from the glyph data iterator.
+	vi. Compare SgImages obtained on iv and v steps.
+	vii. Get font metrics from the glyph data iterator.
+	viii. Compare metrics obtained on i and vii steps.
+	vii. Close the iterator.
+
+@SYMTestExpectedResults
+	If the request to get the character data failed, the return value of 
+	RFbsGlyphDataIterator::Open() must not be KErrNone.
+	Otherwise, images obtained from the iterator and GetCharacterData() should
+	match.
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorOpenInvalidCode()
+	{
+	INFO_PRINTF1(_L("Ensure that the image returned by the iterator will \
+match to the image obtained from GetCharacterData() if character code is invalid"));
+	__UHEAP_MARK;
+
+	const TUint8* bitmapData = NULL;
+	TSize bitmapSize;
+	TOpenFontCharMetrics metrics;
+	const TFontSpec fontSpec = iFont->FontSpecInTwips();
+	CFont::TCharacterDataAvailability availability = iFont->GetCharacterData(KDejaVuInvalidGlyphCode | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
+
+	RFbsGlyphDataIterator iter;
+	TInt err = iter.Open(*iFont, &KDejaVuInvalidGlyphCode, 1);
+	if (availability == CFont::ENoCharacterData)
+		{
+		// Some rasterizers fail to return any data for KDejaVuInvalidGlyphCode, therefore
+		// rather than compare image contents, make sure RFbsGlyphDataIterator returns an error code.
+		WARN_PRINTF1(_L("Rasterizer failed to return data for invalid glyph code; not comparing image contents"));
+		TESTE(err != KErrNone, err);
+		}
+	else
+		{
+		TESTNOERROR(err);
+		if (err == KErrNone)
+			{
+			TBool glyphMatches = EFalse;
+			if (bitmapSize == TSize(0, 0))
+				{
+				glyphMatches = (bitmapSize == iter.Rect().Size());
+				}
+			else
+				{
+				RSgImage characterDataImage;
+				TESTNOERROR(CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage));
+				TESTNOERROR(CompareSgImages(iEGL, iter.Image(), iter.Rect(), characterDataImage, TRect(bitmapSize), glyphMatches));
+				characterDataImage.Close();
+				}
+			TESTNOERROR(CompareMetrics(metrics, iter.Metrics()));
+			TEST(glyphMatches);
+			}
+		}
+	iter.Close();
+
+	__UHEAP_MARKEND;
+	}
+
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0636
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that opening the glyph data iterator which has already been opened with the same font
+	has no effect on the state of the iterator.
+@SYMTestActions
+	i. Open glyph data iterator on 2 glyph codes.
+	ii. Try to open the glyph data iterator again on the same font.
+	iii. Call RFbsGlyphDataIterator::Next() on the iterator and check error code, making the last
+		glyph code the current iteration.
+	iv. Call RFbsGlyphDataIterator::Next() again.
+@SYMTestExpectedResults
+	The second attempt to open the glyph data iterator will result an error with code KErrInUse.
+	The last two calls to RFbsGlyphDataIterator::Next() should return KErrNone and KErrNotFound
+	respectively, showing the iterator was not modified when the call to Open() failed.
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorOpenTwice()
+	{
+	INFO_PRINTF1(_L("Ensure that opening the glyph data iterator which has already been opened with the same font has no effect"));
+	__UHEAP_MARK;
+
+	RFbsGlyphDataIterator iter;
+	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, 2);
+	TESTNOERROR(iterErr);
+	
+	iterErr = iter.Open(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
+	TESTE(iterErr == KErrInUse, iterErr);
+	iterErr = iter.Next();
+	TESTNOERROR(iterErr);
+	iterErr = iter.Next();
+	TESTE(iterErr == KErrNotFound, iterErr);
+	iter.Close();
+
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0637
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that opening the glyph data iterator which has already been opened with different font
+	has no effect on the state of the iterator.
+@SYMTestActions
+	i. Open glyph data iterator on an 2 glyph codes
+	ii. Try to open the glyph data iterator again with a different font.
+	iii. Call RFbsGlyphDataIterator::Next() on the iterator and check error code, making the last
+		glyph code the current iteration.
+	iv. Call RFbsGlyphDataIterator::Next() again.
+@SYMTestExpectedResults
+	The second attempt to open the glyph data iterator will result an error with code KErrInUse.
+	The Next() call after this should return KErrNone, signifying the iterator is still open.
+	The last Next() call should return KErrNotFound, signifying the iterator has iterated 
+	through the two original glyph codes.
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorOpenTwiceWithDifferentFonts()
+	{
+	INFO_PRINTF1(_L("Ensure that opening the glyph data iterator which has already been opened with different font has no effect"));
+	__UHEAP_MARK;
+
+	RFbsGlyphDataIterator iter;
+	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, 2);
+	TESTNOERROR(iterErr);
+
+	iterErr = iter.Open(*iFont2, iGlyphCodesLatin, 2);
+	TESTE(iterErr == KErrInUse, iterErr);
+	iterErr = iter.Next();
+	TESTNOERROR(iterErr);
+	iterErr = iter.Next();
+	TESTE(iterErr == KErrNotFound, iterErr);
+	iter.Close();
+
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0638
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that opening of glyph data iterator with the font greater than 
+	2048 by 2048 will not be supported 
+@SYMTestActions
+	i. Create font with the height greater than 2048
+	ii. Try to open the glyph data iterator with the font created on previous step
+	iii Release the font
+@SYMTestExpectedResults
+	Must fail with error code KErrTooBig
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorOpenTooBigFont()
+	{
+	INFO_PRINTF1(_L("To ensure that opening of glyph data iterator with the font greater than 2048X2048 will not be supported"));
+	__UHEAP_MARK;
+
+	CFbsFont* bigFont;
+	const TInt maxHeight = 2048;
+	const TInt maxHeightLimit = maxHeight + 20; //max size after we stop trying to create the font
+	// the loop below will guarantee that if the font with the size greater than 2048 is available it will be created
+	for(TInt height = maxHeight + 1; height < maxHeightLimit; height++)
+		{
+		TESTNOERROR(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)bigFont, TFontSpec(KTypefaceName, height)));
+		TInt realHeight = bigFont->FontMaxHeight();
+		if(realHeight > maxHeight)
+			{
+			break;
+			}
+		iTs->ReleaseFont(bigFont);
+		bigFont = NULL;
+		}
+
+	if (bigFont)
+		{
+		RFbsGlyphDataIterator iter;
+		TInt iterErr = iter.Open(*bigFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
+		TESTE(iterErr == KErrTooBig, iterErr);
+		iTs->ReleaseFont(bigFont); 
+		}
+	else
+		{
+		//It is legitimate to fail to create the font, as there are no requirements for the rasterizer here to support such big font. 
+		//In this case we will skip the test.
+		WARN_PRINTF1(_L("Failed to create font with height greater than 2048"));
+		}
+
+	__UHEAP_MARKEND;
+	}
+
+
+
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0640
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that the glyph data iterator processes wrong arguments correctly
+@SYMTestActions
+	i. Try to open the glyph data iterator with the negative count passed in
+	ii. Try to open the glyph data iterator with the positive count and NULL 
+	glyph code array pointer passed in
+	iii. Try to open the glyph data iterator with a valid glyph code array and 
+	count equal to zero
+@SYMTestExpectedResults
+	At all steps the returned value is set to KErrArgument.
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorOpenWithWrongArgument()
+	{
+	INFO_PRINTF1(_L("To ensure that the glyph data iterator processes wrong arguments correctly"));
+	__UHEAP_MARK;
+
+	RFbsGlyphDataIterator iter;
+	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, -1);
+	TESTE(iterErr == KErrArgument, iterErr);
+	
+	iterErr = iter.Open(*iFont, NULL, 1);
+	TESTE(iterErr == KErrArgument, iterErr);
+	
+	iterErr = iter.Open(*iFont, iGlyphCodesLatin, 0);
+	TESTE(iterErr == KErrArgument, iterErr);
+	
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0641
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that all allocated RSgImages were released after the
+	glyph data iterator has been opened and closed multiple times.
+
+@SYMTestActions
+	i. Retrieve MSgDriver_Test interface from the SgDriver
+	ii. Mark alloc start and obtain resorce count from the interface
+	iii. Iterate through glyph data by calling RFbsGlyphDataIterator::Next() 
+	iv. Retrieve SgImage from the glyph data iterator instance
+	v. Repeate steps iii and iv multiple times
+	vi. Release font
+	vii.  Mark alloc end and obtain resorce count from the interface
+
+@SYMTestExpectedResults
+	Resorce count at the end matches resorce count at the beginning. 
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorImageMemoryLeak()
+	{
+	__UHEAP_MARK;
+	
+	MSgDriver_Test* sgDriverTestInterface = NULL; 
+	TInt err = iSgDriver.GetInterface(sgDriverTestInterface);
+	if(err != KErrNone)
+		{
+		__UHEAP_MARKEND;
+		WARN_PRINTF2(_L("Failed to obtain MSgDriver_Test interface with error code: %d, the test will be skipped"), err);
+		return;
+		}
+
+	TEST(sgDriverTestInterface != NULL);
+	sgDriverTestInterface->AllocMarkStart();
+
+	MSgDriver_Profiling* sgDriverProfilInterface = NULL;
+	err = iSgDriver.GetInterface(sgDriverProfilInterface);
+	if(err != KErrNone)
+		{
+		sgDriverTestInterface->AllocMarkEnd(0);
+		__UHEAP_MARKEND;
+		WARN_PRINTF2(_L("Failed to obtain MSgDriver_Profiling interface with error code: %d, the test will be skipped"), err);
+		return;
+		}
+	const TInt resCount = sgDriverProfilInterface->LocalResourceCount();
+
+	CFbsFont* font = NULL;
+	err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font, TFontSpec(KTypefaceName, 15));
+	TESTNOERROR(err);
+	if(err != KErrNone)
+		{
+		__UHEAP_MARKEND;
+		return;
+		}
+
+	for (TInt ii = 0; ii < 10; ii++)
+		{
+		TInt index = 0;
+		RFbsGlyphDataIterator iter;
+		TInt iterErr = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
+		TESTNOERROR(iterErr);
+		for (; (iterErr == KErrNone) && (index < KNumGlyphCodesLatin); iterErr = iter.Next(), ++index)
+			{
+			const RSgImage& image = iter.Image();
+			}
+		iter.Close();
+		TEST(index == KNumGlyphCodesLatin);
+		TESTE(iterErr == KErrNotFound, iterErr);
+		}
+	iTs->ReleaseFont(font);
+	const TInt resCountEnd = sgDriverProfilInterface->LocalResourceCount();
+	TEST(resCountEnd == resCount);
+	sgDriverTestInterface->AllocMarkEnd(0);
+
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0659
+@SYMTestPriority    Med
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	Uses the RFbsGlyphDataIterator to render a large amount of unique glyphs, at a very large 
+	size, to ensure that if graphics memory runs out while the iterator is in use, eviction 
+	takes place and does not corrupt the glyph images in any way.
+
+@SYMTestActions
+	i. Create a large CFbsFont from the typeface store (size 100+)
+	ii. Simulate a low graphics-memory situation by creating enough RSgImages to fill the memory,
+		releasing one image in order to allow some small amount for the test.
+	iii. Open a RFbsGlyphDataIterator on the font, using a large array of unique glyph codes.
+	iv. Iterate through the glyphs, comparing each returned SgImage against the system-memory
+		representation of the glyph as returned by CFont::GetCharacterData().
+	v. Check for errors and mismatches, and release all images created by ii.
+	
+@SYMTestExpectedResults
+	At each iteration, each glyph should match in size and contents. 
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorLargeFontStress()
+	{
+	INFO_PRINTF1(_L("Stress test using a RFbsGlyphDataIterator with a large font"));
+#ifdef __WINS__
+	// Cannot run test on emulator reliably - this is because on emulator
+	// system-memory is used for RSgImages, so using up RSgImage memory may 
+	// cause heap-allocation failures unrelated to the area being tested. 
+	// This test is specifically testing the behaviour when running out of
+	// RSgImage-based memory (i.e. graphics memory), but on emulator this 
+	// will cause a failed allocation anywhere.
+	INFO_PRINTF1(_L("Skipping test on emulator..."));
+#else
+	WARN_PRINTF1(_L("---Stress test TO BE REVISITED due to Broadcom defect ESLM-85LDV7 - TB10.1 Closing of RSgImage with duplicate handle used in same thread does not release GPU RAM"));
+	TEST(EFalse);
+/*	__UHEAP_MARK;
+
+	const TInt KFontSize = 128;
+
+	CFbsFont* font;
+	TInt err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font, TFontSpec(KMonoTypefaceName, KFontSize));
+	TESTNOERROR(err);
+	// Output the actual fontspec used in the test.
+	InfoPrintFontSpec(*font);
+	
+	// Create 2 buffers for use in comparing SgImages so that we don't run out 
+	// of system memory through allocating memory in the test
+	TInt maxFontWidth = font->MaxCharWidthInPixels();
+	TInt maxFontHeight = font->HeightInPixels();
+	iTempBuf1 = (TUint8*) User::AllocZ(maxFontWidth * maxFontHeight);
+	iTempBuf2 = (TUint8*) User::AllocZ(maxFontWidth * maxFontHeight);
+
+	// In order for the image comparisons to have enough memory to perform, keep 
+	// one large RSgImage which is created before the rest of the graphics memory 
+	// is filled.  This image can then be closed before doing the image comparison 
+	// and recreated after the image comparison to ensure that the graphics 
+	// memory is full.  Without this image, the image comparison could fail with 
+	// out of memory and the test would fail. 
+	RSgImage tempImage;
+	TESTNOERROR(tempImage.Create(TSgImageInfo(TSize(1000, 1000), ESgPixelFormatA_8, ESgUsageBitOpenVgImage)));
+
+	TFontSpec actualFontSpec;
+	actualFontSpec = font->FontSpecInTwips();
+	
+	// Create RSgImages from character data independently from using iterator.
+	// These will be used for comparing with RSgImages retrieved from iterator.
+	RArray <RSgImage> sgImageFromCharDataArray;
+	TInt index = 0;
+	for(; (index < KNumGlyphCodesLatin) && (err == KErrNone); ++index)
+		{
+		RSgImage characterDataSgImage;
+		TInt err = KErrNone;
+		const TUint8* bitmapData = NULL;
+		TSize bitmapSize;
+		TOpenFontCharMetrics metrics;
+		font->GetCharacterData(iGlyphCodesLatin[index] | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
+
+		if (bitmapSize != TSize(0, 0))
+			{
+			err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, actualFontSpec.iFontStyle.BitmapType(), characterDataSgImage, iTempBuf1, iTempBuf2);
+			}
+		if (KErrNone == err)
+			{
+			err = sgImageFromCharDataArray.Append(characterDataSgImage);
+			}
+		}
+	TESTNOERROR(err);
+	TEST(index == KNumGlyphCodesLatin);
+
+	// Simulate low OOGM situation by creating many RSgImages until out of memory.
+	RArray <RSgImage> sgImageArray;
+	if (err == KErrNone)
+		{
+		TESTNOERROR(NearlyFillGraphicsMemoryWithImages(TSize(256, 256), sgImageArray));
+		}
+	
+	// Open Iterator on long string of data...
+	RFbsGlyphDataIterator iter;
+	TInt iterErr = KErrNone;
+	if (err == KErrNone)
+		{
+		iterErr = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
+		TESTNOERROR(iterErr);
+		}
+
+	// For each glyph, compare it to the system-memory version from GetCharacterData().
+	TInt numMismatches = 0;
+	for(index = 0; (iterErr == KErrNone) && (index < sgImageFromCharDataArray.Count()) && (err == KErrNone); iterErr = iter.Next(), ++index)
+		{
+		const TUint8* bitmapData = NULL;
+		TSize bitmapSize;
+		TOpenFontCharMetrics metrics;
+		font->GetCharacterData(iter.GlyphCode() | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
+
+		if (iter.Rect().Size() == TSize(0, 0))
+			{
+			numMismatches += (bitmapSize != TSize(0, 0)) ? 1 : 0;
+			}
+		else
+			{
+			// Free up memory so that the image compariso succeeds
+			// Release all the images used to simulate OOGM.
+			for (TInt i = sgImageArray.Count() - 1; i >= 0; --i)
+				{
+				sgImageArray[i].Close();
+				sgImageArray.Remove(i);
+				}
+			
+			TBool match = ETrue;
+			err = CompareSgImages(iEGL, sgImageFromCharDataArray[index], TRect(bitmapSize), iTempBuf1, iter.Image(), iter.Rect(), iTempBuf2, match);
+			if (err == KErrNone && !match)
+				{
+				++numMismatches;
+				}
+			TInt result = FillGraphicsMemoryWithImages(TSize(256, 256), sgImageArray);
+			TESTE(result == KErrNoMemory || result == KErrNoGraphicsMemory, result);
+			}
+		}
+	iter.Close();
+
+	// Release all images created from character data.
+	for (TInt i = sgImageFromCharDataArray.Count()-1; i >= 0; --i)
+		{
+		sgImageFromCharDataArray[i].Close();
+		}
+	sgImageFromCharDataArray.Close();
+
+	// Release all the images used to simulate OOGM.
+	for (TInt i = sgImageArray.Count() - 1; i >= 0; --i)
+		{
+		sgImageArray[i].Close();
+		}
+	sgImageArray.Close();
+	tempImage.Close();
+	iTs->ReleaseFont(font);
+	User::Free(iTempBuf1);
+	User::Free(iTempBuf2);
+	iTempBuf1 = NULL;
+	iTempBuf2 = NULL;
+
+	// Log any errors only after memory is freed - this ensures there is enough
+	// memory for the logger.
+	TESTNOERROR(err);
+	TESTE(iterErr == KErrNotFound, iterErr);
+	TEST(index == KNumGlyphCodesLatin);
+	TEST(numMismatches == 0);
+
+	__UHEAP_MARKEND;*/
+#endif
+	}
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0660
+@SYMTestPriority    Med
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	Opens an RFbsGlyphDataIterator on many different fonts of different sizes and typefaces
+	and uses many fonts, in order to test that the iterator can cope with being used on many
+	fonts with many glyphs.
+
+@SYMTestActions
+	i. Perform test of 100 iterations, where:
+		1. A new Latin font is created every iteration in order to force the Typeface Store
+			to create a brand-new server-side font at each iteration. 
+		2. For this font, open an RFbsGlyphDataIterator and cycle through all Latin glyphs.
+		3. For each glyph, compare against the glyph image returned by CFont::GetCharacterData().
+		4. Keep a record of the number of mismatches, and carry on to next font.
+	ii. Perform i. again, but using the existing fonts.
+	iii. Check that there are no mismatches, all glyphs and fonts were successfully checked, 
+		and no error codes returned during the test.
+	iv. Clean up all resources.
+	
+@SYMTestExpectedResults
+	The glyphs provided by the iterator should match that returned by GetCharacterData()
+	for every font and every iteration. 
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorManyFontsStressL()
+	{
+	INFO_PRINTF1(_L("Stress test using a RFbsGlyphDataIterator with hundreds of fonts"));
+	WARN_PRINTF1(_L("---Stress test TO BE REVISITED due to Broadcom defect ESLM-85LDV7 - TB10.1 Closing of RSgImage with duplicate handle used in same thread does not release GPU RAM"));
+	TEST(EFalse);
+	/*__UHEAP_MARK;
+
+	const TInt KNumFonts = 100;
+	const TInt KNumRepeatsPerFont = 2;
+	TInt err = KErrNone;
+	TInt numGlyphMismatches = 0;
+
+	CFbsFont** font = new (ELeave) CFbsFont*[KNumFonts];
+	Mem::FillZ(font, sizeof(CFbsFont*) * KNumFonts);
+
+	// Do the whole thing KNumRepeatsPerFont times. The second+ repeats will 
+	// re-use the fonts created in the first repeat, to ensure that fonts that 
+	// may have been evicted are able to be re-used with the iterator.
+	for (TInt rep = 0; (rep < KNumRepeatsPerFont) && (err == KErrNone); ++rep)
+		{
+		// Iterate through all the font variants:
+		// Iterate all font styles, for all latin typefaces, at increasing sizes.
+		TInt i = 0;
+		for (; (i < KNumFonts) && (err == KErrNone); ++i)
+			{
+			// Only create this font if this font isn't already valid (i.e. when this is the 
+			// first rep) otherwise re-use it.
+			if (!font[i])
+				{
+				TFontSpec requestedFontSpec = GenerateDejaVuFontSpec(i);
+				err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font[i], requestedFontSpec);
+				}
+			if (err == KErrNone)
+				{
+				RFbsGlyphDataIterator iter;
+				TInt iterErr = iter.Open(*(font[i]), iGlyphCodesLatin, KNumGlyphCodesLatin);
+				if (iterErr != KErrNone)
+					{
+					ERR_PRINTF2(_L("Failed to open RFbsGlyphDataIterator [err=%d]"), iterErr);
+					InfoPrintFontSpec(*(font[i]));
+					iStep->SetTestStepResult(EFail);
+					}
+				else
+					{
+					TInt index = 0;
+					for(; (iterErr == KErrNone) && (index < KNumGlyphCodesLatin) && (err == KErrNone) ; iterErr = iter.Next(), index++)
+						{
+						const TUint8* bitmapData = NULL;
+						TSize bitmapSize;
+						TOpenFontCharMetrics metrics;
+						font[i]->GetCharacterData(iter.GlyphCode() | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
+						if (iter.Rect().Size() == TSize(0, 0))
+							{
+							numGlyphMismatches += (bitmapSize != TSize(0, 0)) ? 1 : 0;
+							}
+						else
+							{
+							TBool match = EFalse;
+							const TFontSpec fontSpec = font[i]->FontSpecInTwips();							
+							// Compare to system-memory version of glyph
+							RSgImage characterDataImage;
+							err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage);
+							if (err == KErrNone) 
+								{
+								err = CompareSgImages(iEGL, iter.Image(), iter.Rect(), characterDataImage, TRect(bitmapSize), match);
+								}
+							if (err == KErrNone && !match)
+								{
+								++numGlyphMismatches;
+								}
+							characterDataImage.Close();
+							}					
+						}
+					iter.Close();
+					TESTE(iterErr == KErrNotFound, iterErr);
+					TEST(index == KNumGlyphCodesLatin);					
+					}
+				}
+			}
+		// Check all the fonts were iterated through.
+		TEST(i == KNumFonts);
+		}
+	TESTNOERROR(err);
+	TEST(numGlyphMismatches == 0);
+
+	// Cleanup
+	for (TInt ii = 0; ii < KNumFonts; ii++)
+		{
+		iTs->ReleaseFont(font[ii]);
+		}
+	delete [] font;
+	__UHEAP_MARKEND;*/
+	}
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0662
+@SYMTestPriority    Low
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	Uses a RFbsGlyphDataIterator when there is no graphics memory available in the system.
+	It shows that when under low graphics memory, Next() returns the correct error code
+	as per the API (either KErrNoMemory or KErrNoGraphicsMemory, depending on the implementation 
+	of Graphics Resource being used).
+
+@SYMTestActions
+	i. Create a CFbsFont from the typeface store.
+	ii. Simulate a low graphics-memory situation by creating enough RSgImages to fill the memory,
+	iii. Open a RFbsGlyphDataIterator on the font.
+	iv. Attempt to use the iterator, calling Next(), checking the returned code.
+	v. Close the iterator and release all graphics memory from ii.
+
+@SYMTestExpectedResults
+	Next() should return either KErrNoMemory or KErrNoGraphicsMemory depending on the implmentation
+	of Graphics Resource used. It should return the same error as is returned when filling
+	the graphics memory reaches the limit.
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorNoGraphicsMemory()
+	{
+	INFO_PRINTF1(_L("Test that when there is no GPU memory available, Next() returns correct error"));
+	WARN_PRINTF1(_L("---Stress test TO BE REVISITED due to Broadcom defect ESLM-85LDV7 - TB10.1 Closing of RSgImage with duplicate handle used in same thread does not release GPU RAM"));
+	TEST(EFalse);
+	/*__UHEAP_MARK;
+	
+	const TInt KFontSize = 128;
+	CFbsFont* font = NULL;
+	RFbsGlyphDataIterator iter;
+	
+	TInt err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font, TFontSpec(KMonoTypefaceName, KFontSize));
+	TESTNOERROR(err);
+	
+	// Simulate low OOGM situation by creating many RSgImages until out of memory.
+	if (err == KErrNone)
+		{
+		InfoPrintFontSpec(*font);
+		RArray <RSgImage> sgImageArray;
+		TInt iterErr = KErrNone;
+		TInt gfxMemErr = FillGraphicsMemoryWithImages(TSize(KFontSize, KFontSize), sgImageArray);
+		TESTE(gfxMemErr == KErrNoMemory || gfxMemErr == KErrNoGraphicsMemory, gfxMemErr);
+		if (gfxMemErr == KErrNoMemory || gfxMemErr == KErrNoGraphicsMemory)
+			{
+			// Next() could either fail with KErrNoMemory or KErrNoGraphicsMemory, but should
+			// be the same error code as the last attempted creation of an SgImage, done in 
+			// FillGraphicsMemoryWithImages() so compare against that code.
+			iterErr = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
+			for (; iterErr == KErrNone; iterErr = iter.Next())
+				{
+				// no operation
+				}
+			iter.Close();
+			}
+	
+		// Release all the images used to simulate OOGM.
+		for (TInt i = sgImageArray.Count() - 1; i >= 0; --i)
+			{
+			sgImageArray[i].Close();
+			}
+		sgImageArray.Close();
+		
+		// Log any errors only after memory is freed - this ensures there is enough
+		// memory for the logger.
+		TESTE(iterErr == gfxMemErr, iterErr);
+		}
+
+	iTs->ReleaseFont(font);
+	
+	__UHEAP_MARKEND;*/
+	}
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0666
+@SYMTestPriority    Low
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	Uses a RFbsGlyphDataIterator after Next() returns an error, in order to show that 
+	an error does not invalidate the state of the iterator and it is still usable. 
+
+@SYMTestActions
+	i. Open the RFbsGlyphDataIterator on 1 glyph code.
+	ii. Store the data of the iterator and call Next() to reach the end of the iterator
+	iii. Access the glyph data repeatedly and check that the iterator members
+		 still match those in ii.
+
+@SYMTestExpectedResults
+	The calls to Next() should cause KErrNotFound since it is past the final glyph.
+	The iterator data should match at all times since the iterator is never moved.
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorNextIsAtomic()
+	{
+	INFO_PRINTF1(_L("To ensure that Next() is atomic, if it returns an error it is still useable"));
+	__UHEAP_MARK;
+
+	RFbsGlyphDataIterator iter;
+	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, 1);
+	TESTNOERROR(iterErr);
+	
+	TSgDrawableId id = iter.Image().Id();
+	TOpenFontCharMetrics metrics = iter.Metrics();
+	TUint glyphCode = iter.GlyphCode();
+	TRect rect = iter.Rect();
+	
+	for (TInt i = 0; i < 2; i++)
+		{
+		iterErr = iter.Next();
+		TESTE(iterErr == KErrNotFound, iterErr);
+		
+		TEST(id == iter.Image().Id());
+		TEST(glyphCode == iter.GlyphCode());
+		TEST(rect == iter.Rect());
+		TEST(CompareMetrics(metrics, iter.Metrics()) == 0);
+		}
+	iter.Close();
+		
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0665
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	Glyph Atlas white-box test.
+	To ensure that the same RSgImage is used for repeated requests for the 
+	same glyph in the same call to RFbsGlyphDataIterator:Open().
+@SYMTestActions
+	i Open the glyph data iterator with a list of glyph codes which are all the same
+	ii Retrieve the drawable id of each iteration 
+	iii Check that the same drawable id is retrieved in each iteration  
+@SYMTestExpectedResults
+	Each iteration returns the same drawable id. 
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorSameGlyphCodes()
+	{
+	INFO_PRINTF1(_L("White box test - Ensure that the same RSgImage is used for repeated requests for the same glyph in the same call to Open()"));
+	__UHEAP_MARK;
+
+	const TUint KSameRepeatedGlyphCode = DejaVuASCIIToGlyphCode[0x004B]; // 'K'
+	const TInt KNumGlyphs = 10;
+	TUint* sameRepeatedGlyphCodes = new TUint[KNumGlyphs];
+	for (TInt ii = 0; ii < KNumGlyphs; ++ii)
+		{
+		sameRepeatedGlyphCodes[ii] = KSameRepeatedGlyphCode;
+		}
+	RFbsGlyphDataIterator iter;
+	TInt err = iter.Open(*iFont, sameRepeatedGlyphCodes, KNumGlyphs);
+	
+	TESTNOERROR(err);
+	if (KErrNone == err)
+		{
+		// get the drawable id of the first glyph and check that the id is valid
+		TSgDrawableId referenceId = iter.Image().Id();
+		RSgImage image;
+		TESTNOERROR(image.Open(referenceId));
+		image.Close();
+		TESTNOERROR(iter.Next());
+
+		for (;KErrNone == err; err = iter.Next())
+			{
+			TEST(referenceId == iter.Image().Id());
+			}
+		TESTE(KErrNotFound == err, err);
+		}
+
+	iter.Close();
+	delete[] sameRepeatedGlyphCodes;
+
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0668
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that the iterator can successfully be opened on an array
+	of glyph codes of various array sizes. 
+@SYMTestActions
+	Perform many iterations of opening an array and cycling through the glyphs,
+	increasing the size of the array after each iteration. Some simple sanity-checking
+	of the glyphs is performed.
+@SYMTestExpectedResults
+	KErrNone should be returned at all times. 
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorManyArraySizes()
+	{
+	INFO_PRINTF1(_L("Ensure that the RFbsGlyphDataIterator successfully opens glyph code arrays of many sizes"));
+	__UHEAP_MARK;
+	
+	RFbsGlyphMetricsArray glyphMetricsArray;
+	
+	TESTNOERROR(glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin));
+	TInt iterErr = KErrNone;
+	
+	for (TInt arraySize = 1; (arraySize < KNumGlyphCodesLatin) && (iterErr == KErrNone); ++arraySize)
+		{
+		RFbsGlyphDataIterator iter;
+		TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, arraySize);
+		TESTNOERROR(iterErr);
+		
+		for (TInt index = 0; iterErr == KErrNone; iterErr = iter.Next(), ++index)
+			{
+			// sanity checking...
+			if (iter.GlyphCode() != iGlyphCodesLatin[index])
+				{
+				ERR_PRINTF4(_L("Test failed at array size %d - Wanted glyphcode %d, got %d"), arraySize, iGlyphCodesLatin[index], iter.GlyphCode());
+				iStep->SetTestStepResult(EFail);
+				}
+			if (CompareMetrics(iter.Metrics(), glyphMetricsArray[index]) != 0)
+				{
+				ERR_PRINTF3(_L("Test failed at array size %d, metrics check failed at glyphcode %d"), arraySize, iGlyphCodesLatin[index]);
+				iStep->SetTestStepResult(EFail);
+				}			
+			}
+		iter.Close();
+		}
+
+	glyphMetricsArray.Close();
+	TESTNOERROR(iterErr);
+
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0669
+@SYMTestPriority    Low
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	Negative test case to show that RFbsGlyphDataIterator and RFbsGlyphMetricsArray
+	do not support bitmap fonts.
+@SYMTestActions
+	i. Load a bitmap font.
+	ii. Attempt to open an RFbsGlyphDataIterator and RFbsGlyphMetricsArray with the font.
+@SYMTestExpectedResults
+	KErrNotSupported should be returned in both instances. 
+*/
+ void CTFbsGlyphData::TestBitmapFontSupport()
+	{
+	INFO_PRINTF1(_L("Test bitmap font not supported"));
+	__UHEAP_MARK;
+	
+	CFbsFont* bitmapFont = NULL;
+	TInt err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)bitmapFont, TFontSpec(_L("Digital"), 14));
+	TESTNOERROR(err);
+	TEST(!bitmapFont->IsOpenFont());
+	
+	RFbsGlyphDataIterator iter;
+	err = iter.Open(*bitmapFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
+	TEST(err == KErrNotSupported);
+	iter.Close();
+	
+	RFbsGlyphMetricsArray array;
+	err = array.Get(*bitmapFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
+	TEST(err == KErrNotSupported);
+	array.Close();
+	
+	iTs->ReleaseFont(bitmapFont);
+	__UHEAP_MARKEND;
+	}
+ 
+/**
+@SYMTestCaseID		GRAPHICS-FBSERV-0671
+@SYMTestPriority	High
+@SYMTestType		UT
+@SYMTestStatus		Implemented
+@SYMPREQ			PREQ2678
+
+@SYMTestCaseDesc
+	Shows that different threads (and therefore RFbsSessions) using fonts with the same
+	TFontSpec share the same glyphs	in the atlas and do not create duplicate entries
+	in the Glyph Atlas, and that releasing a font clears all associated glyphs in the
+	atlas.
+
+@SYMTestActions
+	i. Create a handle to a test font in the current process.
+	ii. Spawn a test thread and wait for it to complete. Within the thread :
+		1. Create a font with the same fontspec as the parent process.
+		2. Use the RFbsGlyphDataIterator API to force rasterization into the glyph atlas.
+		3. Release the iterator.
+	iii. Check there were no leaves from the thread.
+	iv. Repeat ii. and iii. several times. Before using RFbsGlyphDataIterator,
+		the thread checks that the glyphs are still in the atlas from the first thread.
+	v. Check that the number of fonts in the atlas has increased by one only.
+	vi. Check that the number of glyphs in the atlas has increased by the size of the 
+		glyph code array.
+	vii. Release the font in the parent process, thereby releasing the font and glyphs
+		in the glyph atlas, and check that the state of the atlas is the same as before
+		the test is run.
+
+@SYMTestExpectedResults
+	All threads should return no errors or leaves or panics.
+	After all threads have finished:
+		The glyph count should have increased by the size of the glyph code array used
+		in the RFbsGlyphDataIterator, showing that	glyphs are only being added to the atlas
+		once. The number of fonts in the atlas should have increased by one, showing
+		that only the single underlying font object is being added to the atlas, despite
+		different RFbsSessions and CFbsFont instances used.
+	After the test font is released in the main process:
+		The glyph count and font count return to the pre-test value, showing that when
+		the last handle to a TFontSpec is released, the atlas frees its associated data.
+*/
+void CTFbsGlyphData::TestMultithreadShareSingleFont()
+	{
+	INFO_PRINTF1(_L("Test glyphs shared between RFbsSessions/threads/processes"));
+#ifndef _DEBUG
+	// Test relies on debug-only FBS messages EFbsMessAtlasGlyphCount and EFbsMessAtlasFontCount
+	INFO_PRINTF1(_L("Skipping test in release mode"));
+#else	
+	__UHEAP_MARK;
+
+	_LIT(KThreadName, "GlyphDataTestThread");
+	const TInt KNumTestThreads = 5;
+	const TFontSpec KTestFontSpec(KTypefaceName, 50);	
+	const TInt atlasFontCountStart = iFbs->SendCommand(EFbsMessAtlasFontCount);
+	const TInt atlasGlyphCountStart = iFbs->SendCommand(EFbsMessAtlasGlyphCount);
+
+	CFbsFont* testFont;
+	TInt err = iTs->GetNearestFontToDesignHeightInPixels( (CFont*&)testFont, KTestFontSpec);
+	if (err != KErrNone)
+		{
+		ERR_PRINTF2(_L("Could not load font, err = %d"), err);
+		iStep->SetTestStepResult(EFail);
+		return;
+		}
+	
+	// Check there are no glyphs belonging to the test font before the test starts.
+	TInt atlasFontGlyphCount = iFbs->SendCommand(EFbsMessAtlasGlyphCount, testFont->Handle());
+	TEST(atlasFontGlyphCount == 0);
+
+	TGlyphDataMultithreadParams params = {KTestFontSpec, iGlyphCodesLatin, KNumGlyphCodesLatin, NULL};
+
+	// Run the test threads sequentially, and check its exit status.
+	RThread testThread;
+	TInt numThreadsPassed = 0;
+	for (TInt i = 0; i < KNumTestThreads; i++)
+		{
+		TBool threadPassed = ETrue;
+		TGlyphDataThreadInfo info = {EGlyphDataMultiSessionTestShareGlyphs, params, i, iStep};
+		err = testThread.Create(KThreadName, CTFbsGlyphData::ThreadFunction, KDefaultStackSize, KTestThreadMinHeapSize, KTestThreadMaxHeapSize, &info);
+		TESTNOERROR(err);
+
+		TRequestStatus statusThread;
+		testThread.Logon(statusThread);
+		testThread.Resume();
+		
+		User::WaitForRequest(statusThread);
+		TInt threadResult = testThread.ExitReason();
+		if (threadResult != KErrNone)
+			{
+			ERR_PRINTF3(_L("Thread %i: Terminated with reason %d"), i, threadResult);
+			threadPassed = EFalse; 
+			}
+		TExitCategoryName exitCategory = testThread.ExitCategory();
+		if (exitCategory.Compare(_L("Kill")) != 0)
+			{
+			ERR_PRINTF3(_L("Thread %i: Terminated with reason category '%S'"), i, &exitCategory);
+			threadPassed = EFalse;
+			}
+		testThread.Close();
+		numThreadsPassed += (threadPassed) ? 1 : 0;
+		}
+	TEST(numThreadsPassed == KNumTestThreads);
+
+	// Check that the atlas still contains the glyphs and the font created by the threads
+	// after they have died, since the font is still open in this process.
+	atlasFontGlyphCount = iFbs->SendCommand(EFbsMessAtlasGlyphCount, testFont->Handle());
+	TEST(atlasFontGlyphCount == params.iGlyphCodesCount);
+	TInt atlasFontCount = iFbs->SendCommand(EFbsMessAtlasFontCount);
+	TEST(atlasFontCount == (atlasFontCountStart + 1));
+
+	iTs->ReleaseFont(testFont);
+	testFont = NULL;
+
+	// Check the atlas state is now the same as it was before the test started,
+	// now that the last remaining handle to the font used in the threads is released.
+	TInt atlasGlyphCountEnd = iFbs->SendCommand(EFbsMessAtlasGlyphCount);
+	TEST(atlasGlyphCountStart == atlasGlyphCountEnd);
+	TInt atlasFontCountEnd = iFbs->SendCommand(EFbsMessAtlasFontCount);
+	TEST(atlasFontCountStart == atlasFontCountEnd);
+	__UHEAP_MARKEND;
+#endif
+	}
+
+/**
+Worker thread for TestMultithreadShareSingleFont().
+The thread uses RFbsGlyphDataIterator on a CFbsFont of the given TFontSpec.
+Once complete the atlas is queried for the number of associated glyphs.
+ */
+void CTFbsGlyphData::ThreadShareGlyphsL(TInt aThreadNum, TGlyphDataMultithreadParams& aParam, CTestStep* aStep)
+	{
+	User::LeaveIfError(RFbsSession::Connect());
+	CFbsTypefaceStore* ts = CFbsTypefaceStore::NewL(NULL);
+	CleanupStack::PushL(ts);
+	RFbsSession* fbs = RFbsSession::GetSession();
+
+	CFbsFont* font;
+	TInt err = ts->GetNearestFontToDesignHeightInPixels((CFont*&)font, aParam.iFontSpec);
+	User::LeaveIfError(err);
+
+	if (aThreadNum > 0)
+		{
+		// If this is not the first thread, it means the first thread has already executed and 
+		// populated the glyph atlas with the glyphs. The font created by this thread 
+		// should already have its glyphs in the atlas.
+		TInt fontGlyphCount = fbs->SendCommand(EFbsMessAtlasGlyphCount, font->Handle());
+		if (fontGlyphCount != aParam.iGlyphCodesCount)
+			{
+			aStep->ERR_PRINTF4(_L("Thread %d: Only %d glyphs in atlas before first iteration, expected %d"), aThreadNum, fontGlyphCount, aParam.iGlyphCodesCount);
+			aStep->SetTestStepResult(EFail);
+			}
+		}
+
+	RFbsGlyphDataIterator iter;
+	for (err = iter.Open(*font, aParam.iGlyphCodes, aParam.iGlyphCodesCount); err == KErrNone; err = iter.Next())
+		{
+		// no-op
+		}
+	iter.Close();
+
+	// Check that the glyphs of this font have been added to the atlas
+	TInt fontGlyphCount = fbs->SendCommand(EFbsMessAtlasGlyphCount, font->Handle());
+	if (fontGlyphCount != aParam.iGlyphCodesCount)
+		{
+		aStep->ERR_PRINTF5(_L("Thread %d: Only %d glyphs in atlas after last iteration, expected %d (err=%d)"), aThreadNum, fontGlyphCount, aParam.iGlyphCodesCount, err);
+		aStep->SetTestStepResult(EFail);
+		}
+	if (err != KErrNotFound)
+		{
+		aStep->ERR_PRINTF3(_L("Thread %d: Error during test = %d"), aThreadNum, err);
+		aStep->SetTestStepResult(EFail);
+		}
+
+	ts->ReleaseFont(font);
+	CleanupStack::PopAndDestroy(1); // ts
+	RFbsSession::Disconnect();
+	}
+
+
+/**
+@SYMTestCaseID		GRAPHICS-FBSERV-0672
+@SYMTestPriority	Medium
+@SYMTestType		UT
+@SYMTestStatus		Implemented
+@SYMPREQ			PREQ2678
+
+@SYMTestCaseDesc
+	Tests that with many concurrent sessions connected to Fbserv, the atlas successfully
+	returns the correct glyph images even if the atlas becomes full and has to evict glyphs.
+
+@SYMTestActions
+	i. Create 25 threads, each a unique session with Fbserv.
+	ii. Launch the threads simultaneously. In each thread:
+		1. Create a FBS typeface store and create a font which is unique in the process.
+		2. Use RFbsGlyphDataIterator to iterate through the latin glyph codes.
+		3. Check the image is correct for each glyph against the image returned by 
+			CFont::GetCharacterData().
+		4. Close the iterator.
+		5. Release the font and close the typeface store. 
+	iii. Once all threads have finished, check the exit status of each thread
+
+@SYMTestExpectedResults
+	Every glyph for every thread should match the image returned by GetCharacterData()
+	All threads should exit normally with no Leave code.
+*/
+_LIT(KTestMultithreadStressFinishSemaphore, "TestMultithreadStressAtlasFinish");
+
+void CTFbsGlyphData::TestMultithreadStressAtlas()
+	{
+	INFO_PRINTF1(_L("Stress test glyph atlas with multiple RFbsSessions"));
+	WARN_PRINTF1(_L("---Stress test TO BE REVISITED due to Broadcom defect ESLM-85NEFT - TB10.1 eglCreateImageKHR hangs during multithreading"));
+	TEST(EFalse);
+	/*__UHEAP_MARK;
+
+	TInt err = KErrNone;
+	const TInt KNumTestThreads = 25;
+	_LIT(KThreadNameFormat, "GlyphDataTestThread%i");
+
+	// Create a semaphore that is signalled by each test thread when it has finished.
+	RSemaphore threadFinishSemaphore;
+	err = threadFinishSemaphore.CreateGlobal(KTestMultithreadStressFinishSemaphore, 0, EOwnerThread);
+	TESTNOERROR(err);
+
+	// Prepare the testdata for the threads
+	// Each thread will have a TFontSpec which will cause unique CFbsFonts
+	// to be created in the server, and therefore the atlas.
+	RThread testThread[KNumTestThreads];
+	TGlyphDataThreadInfo testInfo[KNumTestThreads];	
+	for (TInt i = 0; i < KNumTestThreads; ++i)
+		{
+		testInfo[i].iStep = iStep;
+		testInfo[i].iTest = EGlyphDataMultiSessionTestStressAtlas;
+		testInfo[i].iParams.iFontSpec = GenerateDejaVuFontSpec(i);
+		testInfo[i].iParams.iGlyphCodes = iGlyphCodesLatin;
+		testInfo[i].iParams.iGlyphCodesCount = KNumGlyphCodesLatin;
+		testInfo[i].iParams.iEGL = iEGL;
+		testInfo[i].iThreadNum = i;	
+		TBuf<128> threadName;
+		threadName.AppendFormat(KThreadNameFormat, i);
+		err = testThread[i].Create(threadName, CTFbsGlyphData::ThreadFunction, KDefaultStackSize, KTestThreadMinHeapSize, KTestThreadMaxHeapSize, &testInfo[i]);
+		TESTNOERROR(err);
+		}
+
+	// All threads are created, start them simultaneously.
+	for (TInt i = 0; i < KNumTestThreads; ++i)
+		{
+		testThread[i].Resume();
+		}
+	// Wait for all threads to finish.
+	for (TInt i = 0; i < KNumTestThreads; ++i)
+		{
+		threadFinishSemaphore.Wait();
+		}
+	// Allow some time for remaining threads to finish tidy-up.
+	User::After(100000);
+	threadFinishSemaphore.Close();
+
+	TInt numThreadsPassed = 0;
+	for (TInt i = 0; i < KNumTestThreads; ++i)
+		{
+		TBool threadPassed = ETrue;
+		TInt threadResult = testThread[i].ExitReason();
+		if (threadResult != KErrNone)
+			{
+			ERR_PRINTF3(_L("Thread %i: Terminated with reason %d"), i, threadResult);
+			threadPassed = EFalse; 
+			}
+		TExitCategoryName exitCategory = testThread[i].ExitCategory();
+		if (exitCategory.Compare(_L("Kill")) != 0)
+			{
+			ERR_PRINTF3(_L("Thread %i: Terminated with reason category '%S'"), i, &exitCategory);
+			threadPassed = EFalse;
+			}
+		testThread[i].Close();
+		numThreadsPassed += (threadPassed) ? 1 : 0;
+		}
+	TEST(numThreadsPassed == KNumTestThreads);
+
+	__UHEAP_MARKEND;*/
+	}
+/**
+Worker thread for TestMultithreadStressAtlas().
+The thread uses RFbsGlyphDataIterator on a CFbsFont of the given TFontSpec.
+For each glyph, the image returned by the iterator is compared to the image 
+returned from CFont::GetCharacterData().
+Once complete, the semaphore is signalled to tell the parent process it has
+finished.
+ */
+void CleanupFinishSemaphore(TAny* aItem)
+    {
+    RSemaphore* semaphore = reinterpret_cast<RSemaphore*>(aItem);
+    semaphore->Signal();
+    semaphore->Close();
+    }
+void CTFbsGlyphData::ThreadStressAtlasL(TInt aThreadNum, TGlyphDataMultithreadParams& aParam, CTestStep* aStep)
+	{
+	TOpenFontCharMetrics charMetrics;
+	const TUint8* bitmapData;
+	TSize bitmapSize;
+	RSgImage charDataImage;
+
+	RSemaphore threadFinishSemaphore;
+	User::LeaveIfError(threadFinishSemaphore.OpenGlobal(KTestMultithreadStressFinishSemaphore));
+	CleanupStack::PushL(TCleanupItem(CleanupFinishSemaphore, &threadFinishSemaphore));
+
+	User::LeaveIfError(RFbsSession::Connect());
+	CFbsTypefaceStore* ts = CFbsTypefaceStore::NewL(NULL);
+	CleanupStack::PushL(ts);
+	
+	CFbsFont* font;
+	User::LeaveIfError(ts->GetNearestFontToDesignHeightInPixels((CFont*&)font, aParam.iFontSpec));
+
+	TInt numGlyphMatches = 0;
+	TInt index = 0;
+	TInt err = KErrNone;
+	RFbsGlyphDataIterator iter;
+	for (err = iter.Open(*font, aParam.iGlyphCodes, aParam.iGlyphCodesCount); err == KErrNone; err = iter.Next(), ++index)
+		{
+		TBool glyphMatch = EFalse;
+		font->GetCharacterData(aParam.iGlyphCodes[index] | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
+		if (bitmapSize == TSize(0, 0))
+			{
+			glyphMatch = (bitmapSize == iter.Rect().Size());
+			}
+		else
+			{
+			err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, font->FontSpecInTwips().iFontStyle.BitmapType(), charDataImage);
+			if (err == KErrNone)
+				{
+				err = CompareSgImages(aParam.iEGL, iter.Image(), iter.Rect(), charDataImage, TRect(bitmapSize), glyphMatch);
+				}
+			charDataImage.Close();
+			}
+		if (err != KErrNone)
+			{
+			break;
+			}
+		numGlyphMatches += (glyphMatch) ? 1 : 0;
+		}
+	iter.Close();
+	
+	if (index != aParam.iGlyphCodesCount)
+		{
+		aStep->ERR_PRINTF5(_L("Thread %d: Iterator terminated early - %d out of %d glyphs (err=%d)"), aThreadNum, index, aParam.iGlyphCodesCount, err);
+		aStep->SetTestStepResult(EFail);
+		}
+	if (index != numGlyphMatches)
+		{
+		aStep->ERR_PRINTF4(_L("Thread %d: Matched %d out of %d glyphs"), aThreadNum, numGlyphMatches, aParam.iGlyphCodesCount);
+		aStep->SetTestStepResult(EFail);
+		}
+
+	ts->ReleaseFont(font);
+	CleanupStack::PopAndDestroy(2); // ts, threadFinishSemaphore
+	RFbsSession::Disconnect();
+	}
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0673
+@SYMTestPriority    Medium
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+    Tests the robustness of using RFbsGlyphMetricsArray when the client heap and the
+    FbServ private heap experience failures allocating memory, causing no panics 
+    or leaves.
+
+@SYMTestActions
+    i. Set the default heap failure for the next heap allocation.
+    ii. Create a new CFbsFont using a TFontSpec not already in the glyph atlas.
+    iii. Call RFbsGlyphMetricsArray::Get(), and close the array.
+    iv. Release the font so that nothing is left in the cache as a result of
+        attempting to use it, and reset the heap failure state.
+    v. While iii returns KErrNoMemory, increment the failure count and repeat
+        step ii.
+    vi. Using a separate font so that the test is not affected by the earlier
+        run, repeat ii. to v., but rather than setting the default heap to 
+        fail, the FbServ private heap is set to fail, via IPC messages to Fbs.
+
+@SYMTestExpectedResults
+    If no errors occur, KErrNone should be returned after a certain number of
+    repetitions. Any other error code denotes a problem handling low-memory 
+    situtations.
+*/
+void CTFbsGlyphData::TestGlyphMetricsArrayHeapOOML()
+    {
+    INFO_PRINTF1(_L("Test RFbsGlyphMetricsArray during heap alloc failure"));
+    __UHEAP_MARK;
+
+    // Create a font that wont be in the cache already...
+    TInt rep = 0;
+    TInt err = KErrNoMemory;
+    CFbsFont* font = NULL;
+    
+    while (err == KErrNoMemory)
+        {
+        User::LeaveIfError(iTs->GetNearestFontInPixels((CFont*&)font, GenerateDejaVuFontSpec(10)));
+        __UHEAP_FAILNEXT(rep);
+        RFbsGlyphMetricsArray array;
+        err = array.Get(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
+        array.Close();
+        __UHEAP_RESET;
+        iTs->ReleaseFont(font);
+        font = NULL;
+        ++rep;
+        }
+
+	TESTE(err == KErrNone, err);
+    if (err == KErrNone)
+        {
+        INFO_PRINTF2(_L("Client Heap OOM : Test passed after rep %d"), rep);
+        }
+    else
+        {
+        ERR_PRINTF3(_L("Client Heap OOM : Test failed with err=%d, after rep %d"), err, rep);
+        }
+
+    // Now test when the server-side FbServ heap fails...
+    rep = 0;
+    err = KErrNoMemory;
+    
+    while (err == KErrNoMemory)
+        {
+        User::LeaveIfError(iTs->GetNearestFontInPixels((CFont*&)font, GenerateDejaVuFontSpec(11)));
+        iFbs->SendCommand(EFbsMessSetHeapFail, RFbsSession::EHeapFailTypeServerMemory, rep);
+        RFbsGlyphMetricsArray array;
+        err = array.Get(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
+        array.Close();
+        iFbs->SendCommand(EFbsMessSetHeapReset, RFbsSession::EHeapFailTypeServerMemory);
+        iTs->ReleaseFont(font);
+        font = NULL;
+        ++rep;
+        }
+
+	TESTE(err == KErrNone, err);
+    if (err == KErrNone)
+        {
+        INFO_PRINTF2(_L("FBServ Heap OOM : Test passed after rep %d"), rep);
+        }
+    else
+        {
+        ERR_PRINTF3(_L("FBServ Heap OOM : Test failed with err=%d, after rep %d"), err, rep);      
+        }
+    __UHEAP_MARKEND;
+    }
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0674
+@SYMTestPriority    Medium
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+    Tests the robustness of using RFbsGlyphDataIterator when the client heap and the
+    FbServ private heap experience failures allocating memory, causing no panics 
+    or leaves.
+
+@SYMTestActions
+    i. Set the default heap failure for the next heap allocation.
+    ii. Create a new CFbsFont using a TFontSpec not already in the glyph atlas.
+    iii. Call RFbsGlyphDataIterator::Open(), and close the array.
+    iv. Release the font so that nothing is left in the cache as a result of
+        attempting to use it, and reset the heap failure state.
+    v. While iii returns KErrNoMemory, increment the failure count and repeat
+        step ii.
+    vi. Using a separate font so that the test is not affected by the earlier
+        run, repeat ii. to v., but rather than setting the default heap to 
+        fail, the FbServ private heap is set to fail, via IPC messages to Fbs.
+
+@SYMTestExpectedResults
+    If no errors occur, KErrNone should be returned after a certain number of
+    repetitions. Any other error code denotes a problem handling low-memory 
+    situtations.
+*/
+void CTFbsGlyphData::TestGlyphDataIteratorHeapOOML()
+    {
+    INFO_PRINTF1(_L("Test RFbsGlyphDataIterator during heap alloc failure"));    
+    __UHEAP_MARK;
+
+    // Create a font that wont be in the cache already...
+    TInt rep = 0;
+    TInt err = KErrNoMemory;
+    CFbsFont* font = NULL;
+    
+    while (err == KErrNoMemory)
+        {
+        User::LeaveIfError(iTs->GetNearestFontInPixels((CFont*&)font, GenerateDejaVuFontSpec(10)));
+        __UHEAP_FAILNEXT(rep);
+        RFbsGlyphDataIterator iter;
+        err = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
+        if (err == KErrNone)
+            {
+            while (err == KErrNone) 
+               {
+               err = iter.Next();
+               }
+            err = (err == KErrNotFound) ? KErrNone : err;
+            }
+        iter.Close();
+        __UHEAP_RESET;
+        iTs->ReleaseFont(font);
+        font = NULL;
+        ++rep;
+        }
+
+	TESTE(err == KErrNone, err);
+    if (err == KErrNone)
+        {
+        INFO_PRINTF2(_L("Client Heap OOM : Test passed after rep %d"), rep);
+        }
+    else
+        {
+        ERR_PRINTF3(_L("Client Heap OOM : Test failed with err=%d, after rep %d"), err, rep);
+        }
+
+    // Now test when the server-side FbServ heap fails...
+    rep = 0;
+    err = KErrNoMemory;
+    
+    while (err == KErrNoMemory)
+        {
+        User::LeaveIfError(iTs->GetNearestFontInPixels((CFont*&)font, GenerateDejaVuFontSpec(11)));
+        iFbs->SendCommand(EFbsMessSetHeapFail, RFbsSession::EHeapFailTypeServerMemory, rep);
+        RFbsGlyphDataIterator iter;
+        err = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
+        if (err == KErrNone)
+            {
+            while (err == KErrNone) 
+               {
+               err = iter.Next();
+               }
+            err = (err == KErrNotFound) ? KErrNone : err;
+            }
+        iter.Close();
+        iFbs->SendCommand(EFbsMessSetHeapReset, RFbsSession::EHeapFailTypeServerMemory);
+        iTs->ReleaseFont(font);
+        font = NULL;
+        ++rep;
+        }
+
+	TESTE(err == KErrNone, err);
+    if (err == KErrNone)
+        {
+        INFO_PRINTF2(_L("FBServ Heap OOM : Test passed after rep %d"), rep);
+        }
+    else
+        {
+        ERR_PRINTF3(_L("FBServ Heap OOM : Test failed with err=%d, after rep %d"), err, rep);
+        }
+    __UHEAP_MARKEND;
+    }
+
+/**
+Utility function. Prints out a description of the font's fontspec to the log.
+ */
+void CTFbsGlyphData::InfoPrintFontSpec(const CFont& aFont)
+	{
+	_LIT(KMonochromeBitmap, "Mono");
+	_LIT(KAntiAliasedBitmap, "AA");
+	_LIT(KStyleItalic, "Italic");
+	_LIT(KStyleBold, "Bold");
+	_LIT(KStyleNormal, "Normal");
+	_LIT(KUnknown, "Unknown");
+	TBufC<9> bitmapType;
+	TBuf<12> fontStyle;
+	TFontSpec fontSpec = aFont.FontSpecInTwips();
+	switch(fontSpec.iFontStyle.BitmapType())
+		{
+		case EMonochromeGlyphBitmap:
+			bitmapType = KMonochromeBitmap;
+			break;
+		case EAntiAliasedGlyphBitmap:
+			bitmapType = KAntiAliasedBitmap;
+			break;
+		default:
+			bitmapType = KUnknown;
+		}
+
+	if (fontSpec.iFontStyle.StrokeWeight() == EStrokeWeightBold)
+		{
+		fontStyle.Append(KStyleBold);
+		}
+	if (fontSpec.iFontStyle.Posture() == EPostureItalic)
+		{
+		fontStyle.Append(KStyleItalic);
+		}
+	if (fontStyle.Length() == 0)
+		{
+		fontStyle = KStyleNormal;
+		}
+
+	INFO_PRINTF5(_L("Font: name=%S size=%dtw type=%S style=%S"), &(fontSpec.iTypeface.iName), fontSpec.iHeight, &bitmapType, &fontStyle);
+	}
+
+
+/**
+Static utility function. Performs a per-pixel comparison of two open RSgImages.
+To do this requires access to the binary data of the images, only accessable
+via EGL and Khronos APIs. This function will bind the RSgImages to VGImages 
+and uses OpenVG to retrieve the image data in 8bpp.
+@param aEGL An EGL Helper to read the SgImages into system memory.
+@param aImageA The first image to compare.
+@param aRectA A rectangular portion in pixels of the first image to compare.
+@param aImageB The second image to compare.
+@param aRectB A rectangular portion in pixels fo the second image to compare.
+@param aMatch A boolean value, which on return tells the caller whether the two
+	images were deemed to match.
+@return KErrNone, if the comparison took place, otherwise one of the system-wide
+	error codes.
+*/
+TInt CTFbsGlyphData::CompareSgImages(CEGLHelper* aEGL, const RSgImage& aImageA, const TRect& aRectA, const RSgImage& aImageB, const TRect& aRectB, TBool& aMatch)
+	{
+	return CTFbsGlyphData::CompareSgImages(aEGL, aImageA, aRectA, NULL, aImageB, aRectB, NULL, aMatch);
+	}
+
+/**
+Static utility function. Performs a per-pixel comparison of two open RSgImages.
+To do this requires access to the binary data of the images, only accessable
+via EGL and Khronos APIs. This function will bind the RSgImages to VGImages 
+and uses OpenVG to retrieve the image data in 8bpp.
+This version allows pre-created memory to be used in the comparison, to avoid
+allocation failure in low memory testing.
+@param aEGL An EGL Helper to read the SgImages into system memory buffers.
+@param aImageA The first image to compare.
+@param aRectA A rectangular portion in pixels of the first image to compare.
+@param aBufferA If non-NULL, specifies a memory buffer to read the data of
+	aImageA into, otherwise a buffer is dynamically allocated.
+@param aImageB The second image to compare.
+@param aRectB A rectangular portion in pixels fo the second image to compare.
+@param aBufferB If non-NULL, specifies a memory buffer to read the data of
+	aImageB into, otherwise a buffer is dynamically allocated.
+@param aMatch A boolean value, which on return tells the caller whether the two
+	images were deemed to match.
+@return KErrNone, if the comparison took place, otherwise one of the system-wide
+	error codes.
+*/
+TInt CTFbsGlyphData::CompareSgImages(CEGLHelper* aEGL, const RSgImage& aImageA, const TRect& aRectA, TUint8* aBufferA, const RSgImage& aImageB, const TRect& aRectB, TUint8* aBufferB, TBool& aMatch)
+	{
+	// By default, assume they do not match.
+	aMatch = EFalse;
+	
+#ifdef SAVEGLYPHSTOMBMDURINGCOMPARISON
+	
+	static TInt countToAppend = 0;
+	
+	CFbsBitmap* bitmap = NULL;
+	if (KErrNone == CreateBitmapFromSgImage(aEGL, aImageA, aRectA, bitmap))
+		{
+		TBuf<KMaxFileName> buf;
+		buf.AppendNum( countToAppend );
+		TPtrC nameAppend( buf );
+		
+		SaveBmp(bitmap, &nameAppend, EFalse);
+		}
+	delete bitmap;	
+	if (KErrNone == CreateBitmapFromSgImage(aEGL, aImageB, aRectB, bitmap))
+		{
+		TBuf<KMaxFileName> buf;
+		buf.AppendNum( countToAppend );
+		TPtrC nameAppend( buf );
+	
+		SaveBmp(bitmap, &nameAppend, ETrue);
+		}
+	delete bitmap;
+	
+	countToAppend++;
+	
+#endif // SAVEGLYPHSTOMBMDURINGCOMPARISON
+	
+	TSgImageInfo imageInfoA;
+	TSgImageInfo imageInfoB;
+	if (aImageA.GetInfo(imageInfoA) != KErrNone ||
+		aImageB.GetInfo(imageInfoB) != KErrNone)
+		{
+		return KErrBadHandle;
+		}
+		
+	// Check the sizes of the images match, and the rects reside on the images.
+	if (aRectA.Size() != aRectB.Size() ||
+		!TRect(imageInfoA.iSizeInPixels).Intersects(aRectA) ||
+		!TRect(imageInfoB.iSizeInPixels).Intersects(aRectB))
+		{
+		return KErrNone;		
+		}
+	const TSize KBufferSize = aRectA.Size();
+	const TInt KDataStride = KBufferSize.iWidth;
+
+	TBool freeTempBufA = EFalse;
+	TBool freeTempBufB = EFalse;
+	if (!aBufferA)
+		{
+		aBufferA = (TUint8*) User::AllocZ(KDataStride * KBufferSize.iHeight);
+		freeTempBufA = ETrue;
+		}
+	if (!aBufferA)
+		{
+		return KErrNoMemory;
+		}
+	TInt err = aEGL->GetSgImageData(aImageA, aRectA, aBufferA);
+	if (err != KErrNone)
+		{
+		if (freeTempBufA)
+			{
+			User::Free(aBufferA);
+			aBufferA = NULL;
+			}
+		return err;
+		}
+	if (!aBufferB)
+		{
+		aBufferB = (TUint8*) User::AllocZ(KDataStride * KBufferSize.iHeight);
+		freeTempBufB = ETrue;
+		}
+	if (!aBufferB)
+		{
+		if (freeTempBufA)
+			{
+			User::Free(aBufferA);
+			aBufferA = NULL;
+			}
+		return KErrNoMemory;
+		}
+	err = aEGL->GetSgImageData(aImageB, aRectB, aBufferB);
+	if (err != KErrNone)
+		{
+		if (freeTempBufA)
+			{
+			User::Free(aBufferA);
+			aBufferA = NULL;
+			}
+		if (freeTempBufB)
+			{
+			User::Free(aBufferB);
+			aBufferB = NULL;
+			}
+		return err;
+		}	
+
+	// Perform a per-pixel comparison, scanline by scanline.
+	// The loop will break as soon as a mismatch is detected.
+	aMatch = ETrue;
+	for (TInt scanline = 0; (scanline < KBufferSize.iHeight) && aMatch; ++scanline)
+		{
+		TUint8* scanlineImageA = aBufferA + (scanline * KDataStride);
+		TUint8* scanlineImageB = aBufferB + (scanline * KDataStride);
+		aMatch = (Mem::Compare(scanlineImageA, KBufferSize.iWidth, scanlineImageB, KBufferSize.iWidth) == 0);
+		}
+
+	if (freeTempBufA)
+		{
+		User::Free(aBufferA);
+		aBufferA = NULL;
+		}
+	if (freeTempBufB)
+		{
+		User::Free(aBufferB);
+		aBufferB = NULL;
+		}
+	
+	return KErrNone;
+	}
+
+/**
+Second thread entry function for multi-threaded tests.
+*/
+TInt CTFbsGlyphData::ThreadFunction(TAny* aParam)
+	{
+	__UHEAP_MARK;
+	CTrapCleanup* cleanupStack = CTrapCleanup::New();
+	if (!cleanupStack)
+		{
+		return KErrNoMemory;
+		}
+
+	TGlyphDataThreadInfo* info = static_cast<TGlyphDataThreadInfo*>(aParam);
+	TRAPD(result,
+	switch(info->iTest)
+		{
+		case EGlyphDataMultiSessionTestShareGlyphs:
+			CTFbsGlyphData::ThreadShareGlyphsL(info->iThreadNum, info->iParams, info->iStep);
+			break;
+		case EGlyphDataMultiSessionTestStressAtlas:
+			CTFbsGlyphData::ThreadStressAtlasL(info->iThreadNum, info->iParams, info->iStep);
+			break;
+		default:
+			User::Leave(KErrArgument);
+		}
+	);
+
+	delete cleanupStack;
+	__UHEAP_MARKEND;
+	return result;
+	}
+
+
+
+/*
+	-----------------------------------------
+	Static utility Methods used by the tests.
+	-----------------------------------------
+*/
+
+
+
+/**
+Utility method that fills the RSgImage memory with RSgImages until either KErrNoMemory
+or KErrNoGraphicsMemory is returned.
+
+@param aSize The size of the image used to fill the graphics memory - a form of granularity
+@param aImages Returns the array of the images used to fill the graphics memory.
+@return KErrNoGraphicsMemory or KErrNoMemory if successful, otherwise one of the system
+	wide error codes.
+ */
+/*static TInt FillGraphicsMemoryWithImages(const TSize& aSize, RArray<RSgImage>& aImages)
+	{
+	TInt err = KErrNone;
+	while (KErrNone == err)
+		{
+		RSgImage sgImage;
+		err = sgImage.Create(TSgImageInfo(aSize, ESgPixelFormatA_8, ESgUsageBitOpenVgImage));
+		if (KErrNone == err)
+			{
+			err = aImages.Append(sgImage);
+			}
+		}
+	return err;
+	}*/
+
+/**
+Utility method that fills the RSgImage memory with RSgImages until either KErrNoMemory
+or KErrNoGraphicsMemory is returned and then closes one RSgImage to free up some memory.
+
+@param aSize The size of the image used to fill the graphics memory - a form of granularity
+@param aImages Returns the array of the images used to fill the graphics memory.
+@return KErrNone if successful, otherwise one of the system	wide error codes.
+ */
+/*static TInt NearlyFillGraphicsMemoryWithImages(const TSize& aSize, RArray<RSgImage>& aImages)
+	{
+	TInt err = FillGraphicsMemoryWithImages(aSize, aImages);
+	if (err == KErrNoMemory || err == KErrNoGraphicsMemory)
+		{
+		if (aImages.Count() > 0)
+			{
+			// Remove an image to free up some memory.
+			TInt lastIndex = aImages.Count() - 1;
+			aImages[lastIndex].Close();
+			aImages.Remove(lastIndex);
+			}
+		err = KErrNone;
+		}
+	return err;
+	}*/
+
+/**
+Static utility function. Creates an 8bpp RSgImage from 1bpp or 8bpp character
+data, with VGImage usage flag set.
+@param aData The character image data. Either in 8bpp or 1bpp RLE format.
+@param aSize The size of the character image in pixels.
+@param aType The type of glyph - Monochrome or Antialiased. 
+@param aSgImage A closed image which will be populated with 8bpp image data.
+*/
+static TInt CreateSgImageFromCharacterData(const TUint8* aData, const TSize& aSize, TGlyphBitmapType aType, RSgImage& aImage)
+	{
+	return CreateSgImageFromCharacterData(aData, aSize, aType, aImage, NULL, NULL);
+	}
+
+/**
+Static utility function. Creates an 8bpp RSgImage from 1bpp or 8bpp character
+data, with VGImage usage flag set. 
+This overload allows the memory for the buffers to be pre-created to avoid
+memory allocation failure during low-memory testing.
+@param aData The character image data. Either in 8bpp or 1bpp RLE format.
+@param aSize The size of the character image in pixels.
+@param aType The type of glyph - Monochrome or Antialiased. 
+@param aSgImage A closed image which will be populated with 8bpp image data.
+@param aBuffer1 If non-NULL, used as a memory buffer for reading the decoded 
+	image data into for monochrome images.
+@param aBuffer2 If non-NULL, used as a memory buffer for the decoded image
+	data for monochrome images.
+*/
+static TInt CreateSgImageFromCharacterData(const TUint8* aData, const TSize& aSize, TGlyphBitmapType aType, RSgImage& aImage, TUint8* aBuffer1, TUint8* aBuffer2)
+	{
+	TInt err = KErrNone;	
+	if (aSize == TSize(0, 0))
+		{
+		return KErrArgument;
+		}
+	TUint8* dataBuf = NULL;
+	TInt dataStride = 0;
+	TBool freeDataBuf = EFalse;
+	if (aType == EAntiAliasedGlyphBitmap)
+		{
+		dataBuf = const_cast<TUint8*>(aData);
+		dataStride = aSize.iWidth;
+		}
+	else if (aType == EMonochromeGlyphBitmap)
+		{
+		TUint8* binaryData = NULL;
+		TUint8* tempBuf = NULL;
+		TInt binaryDataStride = ((aSize.iWidth + 31) / 32) << 2;
+		TInt binaryDataSize = binaryDataStride * aSize.iHeight;
+		if (aBuffer1 && User::AllocLen(aBuffer1) >= binaryDataSize)
+			{
+			binaryData = aBuffer1;
+			}
+		else
+			{
+			tempBuf = (TUint8*) User::AllocZ(binaryDataSize);
+			if (!tempBuf)
+				{
+				return KErrNoMemory;
+				}
+			binaryData = tempBuf;
+			}
+		// Unpack the run length encoded data into 1bpp
+		DecodeBinaryData(aSize, aData, binaryDataStride, reinterpret_cast<TUint32*&>(binaryData));
+		dataStride = aSize.iWidth;
+		TInt byteDataSize = dataStride * aSize.iHeight;
+		TUint8* byteData = NULL;
+		// If aByteBuf supplied, use that instead of allocating a new buffer here.
+		if (aBuffer2 && User::AllocLen(aBuffer2) >= byteDataSize)
+			{
+			byteData = aBuffer2;
+			}
+		else
+			{
+			byteData = (TUint8*) User::AllocZ(byteDataSize);
+			if (!byteData)
+				{
+				User::Free(tempBuf);
+				return KErrNoMemory;
+				}
+			freeDataBuf = ETrue;
+			}
+		dataBuf = byteData;
+		for (TInt scanline = 0; scanline < aSize.iHeight; ++scanline)
+			{
+			TUint8* srcByte = binaryData;
+			for (TInt pixel = 0; pixel < aSize.iWidth; pixel++)
+				{
+				*(byteData+pixel) = ((*srcByte & (1 << (pixel % 8))) == 0) ? 0 : 0xFF;
+				if (((pixel + 1) % 8) == 0) srcByte++;
+				}
+			byteData += dataStride;
+			binaryData += binaryDataStride;
+			}
+		User::Free(tempBuf);
+		}
+	else
+		{
+		return KErrArgument;
+		}
+
+	// Create RSgImage from CFbsBitmap.
+	TSgImageInfo sgImageInfo(aSize, ESgPixelFormatA_8, ESgUsageBitOpenVgImage);
+	err = aImage.Create(sgImageInfo, dataBuf, dataStride);
+	if (freeDataBuf)
+		{
+		User::Free(dataBuf);
+		}
+	return err;
+	}
+
+
+/**
+Static utility function, Copies image data line(s) to a destination.
+@param aBinaryDataPtr pointer to a destination buffer.
+@param aBufferWords Stride of the image.
+@param aData Pointer to a source buffer.
+@param aBitShift Number of bits, binary data will be shifted. 
+@param aCharWidth Width of the image.
+@param aRepeatCount Number of lines to copy.
+*/
+static void CopyCharLine(TUint32*& aBinaryDataPtr,TInt aBufferWords,const TUint8* aData,TInt aBitShift,TInt aCharWidth, TInt16 aRepeatCount)
+	{
+	aBitShift&=7;
+	TInt wordstocopy=(aCharWidth+31)>>5;
+	if(wordstocopy>aBufferWords) wordstocopy=aBufferWords;
+	TUint32* ptrlimit=aBinaryDataPtr+wordstocopy;
+	TUint32* dataword=(TUint32*)(TInt(aData)&~3);
+	aBitShift+=(TInt(aData)-TInt(dataword))<<3;
+	
+	TUint32* startBinaryDataPtr = aBinaryDataPtr;
+	while(aBinaryDataPtr<ptrlimit)
+		{
+		*aBinaryDataPtr=*dataword++;
+		*aBinaryDataPtr>>=aBitShift;
+		if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
+		aBinaryDataPtr++;
+		}
+	
+	TUint32* curStartBinaryDataPtr = aBinaryDataPtr;
+	TInt byteToCopy = wordstocopy << 2;
+	while(aRepeatCount > 1)
+		{
+		Mem::Copy(curStartBinaryDataPtr, startBinaryDataPtr, byteToCopy);
+		curStartBinaryDataPtr += wordstocopy;
+		
+		aRepeatCount--;
+		}
+	aBinaryDataPtr = curStartBinaryDataPtr;
+	}
+
+/**
+Static utility function. Decodes a monochrome glyph whose data is run length encoded, 
+into a 1bpp bitmap.
+@param aDataSize Image size in pixels.
+@param aData Pointer to a source buffer.
+@param aStride Image data stride.
+@param aBinaryData Pointer to a destination buffer. This buffer must be allocated 
+	by the caller.
+*/
+static void DecodeBinaryData(const TSize& aDataSize, const TUint8* aData, TInt aStride,
+											TUint32* aBinaryData)
+	{
+	const TInt datalength = aDataSize.iWidth;
+	const TInt dataheight = aDataSize.iHeight;
+	TInt bitindex=0;
+	TInt16 repeatcount=0;
+	TUint32* slbuffer=aBinaryData;
+	const TInt slwords=aStride;
+
+	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
+		{
+		repeatcount=CFbsBitGc::Load16(aData+(bitindex>>3));
+		repeatcount>>=bitindex&7;
+		const TInt multilineflag=repeatcount&1;
+		repeatcount>>=1;
+		repeatcount&=0xf;
+		bitindex+=5;
+		if(multilineflag)
+			{
+			for(TInt currentline=0;currentline<repeatcount;currentline++)
+				{
+				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength, 1);
+				bitindex+=datalength;
+				}
+			}
+		else
+			{
+			CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength, repeatcount);
+			bitindex+=datalength;
+			}
+		}
+	}
+//--------------
+__CONSTRUCT_STEP__(FbsGlyphData)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/tfbsglyphdata.h	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,199 @@
+// Copyright (c) 2009-2010 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:
+//
+
+#ifndef TFBSGLYPHDATA_H
+#define TFBSGLYPHDATA_H
+
+#include <EGL/eglext.h>
+#include <VG/openvg.h>
+#include <sgresource/sgresource.h>
+#include "test/TGraphicsHarness.h"
+class RSgImage;
+class CEGLHelper;
+
+//#define SAVEGLYPHSTOMBMDURINGCOMPARISON // Enable saving of glyphs in the CompareSgImages()function
+//#define SAVEGLYPHSTOMBMDEBUGFUNCTION //  Enable compilation of the member function SaveRSgImagesAsMbms(). Occasionally useful.
+
+typedef EGLBoolean (*TvgCreateEGLImageTargetKHRTypefPtr) (VGeglImageKHR image);
+
+/**
+Multi-thread test enum.
+ */
+enum EGlyphDataMultithreadTest
+	{
+	EGlyphDataMultiSessionTestShareGlyphs,
+	EGlyphDataMultiSessionTestStressAtlas
+	};
+
+/**
+Struct passed to multi-thread test functions.
+ */
+struct TGlyphDataMultithreadParams
+	{
+	TFontSpec iFontSpec;
+	TUint* iGlyphCodes;
+	TInt iGlyphCodesCount;
+	CEGLHelper* iEGL;
+	};
+
+/**
+Struct used to define the mutlithreaded test to run when launching a new thread.
+ */
+struct TGlyphDataThreadInfo
+	{
+	EGlyphDataMultithreadTest iTest;
+	TGlyphDataMultithreadParams iParams;
+	TInt iThreadNum;
+	CTestStep* iStep;
+	};
+
+
+/**
+ *
+ * Class to provide a dummy font for test purposes
+ * See CTFbsGlyphData::TestGlyphDataIteratorNotSupportedFontL()
+ */
+class CTestFont : public CFont
+	{
+public:
+	TUid DoTypeUid() const {return TUid::Uid(12345);}
+	TInt DoHeightInPixels() const {return 12;}
+	TInt DoAscentInPixels() const {return 10;}
+	TInt DoCharWidthInPixels(TChar /*aChar*/) const  {return 0;}
+	TInt DoTextWidthInPixels(const TDesC& /*aText*/) const {return 0;}
+	TInt DoBaselineOffsetInPixels() const {return 0;}
+	TInt DoTextCount(const TDesC& /*aText*/,TInt /*aWidthInPixels*/) const {return 0;}
+	TInt DoTextCount(const TDesC& /*aText*/,TInt /*aWidthInPixels*/,TInt& /*aExcessWidthInPixels*/) const {return 0;}
+	TInt DoMaxCharWidthInPixels() const  {return 0;}
+	TInt DoMaxNormalCharWidthInPixels() const  {return 0;}
+	TFontSpec DoFontSpecInTwips() const  {return TFontSpec();}
+	};
+
+/**
+Created by each process/thread that needs to do RSgImage image comparison.
+The class can be shared in a process between threads and handles synchronisation
+with EGL itself.
+ */
+class CEGLHelper : public CBase
+	{
+public:
+	~CEGLHelper();
+	static CEGLHelper* NewL();
+		
+	TInt GetSgImageData(const RSgImage& aSgImage, const TRect& aRect, TUint8*& aBuf);
+	
+private:
+	CEGLHelper();
+	void ConstructL();
+
+private:
+	RMutex iMutex;
+	RSgDriver iSgDriver;
+	EGLDisplay iDisplay;
+	EGLContext iContext;
+	EGLSurface iSurface;
+	// Function pointer for creation and destruction of EGLImages, and the creation
+	// of VGImages from EGLImages.
+	TvgCreateEGLImageTargetKHRTypefPtr vgCreateImageTargetKHR;
+	PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
+	PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
+	};
+
+/**
+Test class for the glyph data extensions RFbsGlyphDataIterator and 
+RFbsGlyphMetricsArray. Positive and negative tests
+*/
+class CTFbsGlyphData : public CTGraphicsBase
+	{
+public:
+	CTFbsGlyphData(CTestStep* aStep);
+	~CTFbsGlyphData();
+protected:
+//from 	CTGraphicsBase
+	virtual void RunTestCaseL(TInt aCurTestCase);
+	void ConstructL();
+	
+private:
+	// Test Cases
+	void TestConsistencyWithGetCharacterData();
+	void TestInvalidGlyphCode();
+	void TestGlyphMetricsArrayParameters();
+	void TestGlyphMetricsArrayReuse();
+	void TestGlyphDataIteratorClose();
+	void TestGlyphDataIteratorSequence();
+	void TestGlyphDataIteratorMultipleUsesOnMultipleFonts();
+	void TestGlyphDataIteratorImageValidity();
+	void TestGlyphDataIteratorOpenInvalidCode();
+	void TestGlyphDataIteratorOpenTwice();
+	void TestGlyphDataIteratorOpenTwiceWithDifferentFonts();
+	void TestGlyphDataIteratorOpenTooBigFont();
+	void TestGlyphDataIteratorOpenWithWrongArgument();
+	void TestGlyphDataIteratorImageMemoryLeak();
+	void TestGlyphDataIteratorLargeFontStress();
+	void TestGlyphDataIteratorManyFontsStressL();
+	void TestGlyphDataIteratorNoGraphicsMemory();
+	void TestGlyphDataIteratorNextIsAtomic();
+	void TestGlyphDataIteratorManyArraySizes();
+	void TestBitmapFontSupport();
+	// White-Box Test Cases
+	void TestGlyphDataIteratorSameGlyphCodes();
+	void TestMultithreadShareSingleFont();
+	void TestMultithreadStressAtlas();
+	// Out-of-system-memory tests
+	void TestGlyphMetricsArrayHeapOOML();
+	void TestGlyphDataIteratorHeapOOML();
+	// Multithread funtions
+	static void ThreadShareGlyphsL(TInt aThreadNum, TGlyphDataMultithreadParams& aParam, CTestStep* aStep);
+	static void ThreadStressAtlasL(TInt aThreadNum, TGlyphDataMultithreadParams& aParam, CTestStep* aStep);	
+
+	// Utility functions for the test cases.
+	static TInt ThreadFunction(TAny* aParam); 
+	TInt GetImageDataFromSgImage(const RSgImage& aSgImage, const TRect& aRect, TUint8*& aBuf);
+	TUint32 CompareMetrics(const TOpenFontCharMetrics& aMetrics1, const TOpenFontCharMetrics& aMetrics2);
+	static TInt CompareSgImages(CEGLHelper* aEGL, const RSgImage& aImageA, const TRect& aRectA, const RSgImage& aImageB, const TRect& aRectB, TBool& aMatch);
+	static TInt CompareSgImages(CEGLHelper* aEGL, const RSgImage& aImageA, const TRect& aRectA, TUint8* aBufferA, const RSgImage& aImageB, const TRect& aRectB, TUint8* aBufferB, TBool& aMatch);
+#ifdef SAVEGLYPHSTOMBMDEBUGFUNCTION
+	void SaveRSgImagesAsMbms( CEGLHelper* aEGL, const RSgImage& aImageA, const TRect& aRectA, const RSgImage& aImageB, const TRect& aRectB );
+#endif // SAVEGLYPHSTOMBMDEBUGFUNCTION
+	void InfoPrintFontSpec(const CFont& aFont);
+	void SetupEglL();
+	
+private:
+	RFbsSession* iFbs;
+	CFbsTypefaceStore* iTs;
+	TUint* iGlyphCodesLatin;
+	
+	CFbsFont* iFont;
+	CFbsFont* iFont2;
+
+	TUint8* iTempBuf1;
+	TUint8* iTempBuf2;
+	RSgDriver iSgDriver;
+	CEGLHelper* iEGL;
+	};
+
+
+class CTFbsGlyphDataStep : public CTGraphicsStep
+	{
+public:
+	CTFbsGlyphDataStep();
+protected:	
+	//from CTGraphicsStep
+	virtual CTGraphicsBase* CreateTestL();
+	};
+
+_LIT(KTFbsGlyphDataStep,"TFbsGlyphData");
+
+#endif /* TFBSGLYPHDATA_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/tfbsglyphdataoutlineshadow.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,93 @@
+// Copyright (c) 2009-2010 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:
+//
+
+/**
+ @file
+ @internalComponent - Internal Symbian test code
+*/
+
+#include <graphics/fbsglyphdataiterator.h>
+#include <sgresource/sgimage.h>
+
+#include "tfbsglyphdataoutlineshadow.h"
+
+_LIT(KTypefaceName, "DejaVu Sans Condensed");
+
+//Note: This test must be run with a rasterizer which supports EFourColourBlendGlyphBitmap (e.g. iType)
+//otherwise the test will fail.
+CTFbsGlyphDataOutlineAndShadow::CTFbsGlyphDataOutlineAndShadow(CTestStep* aStep) :
+    CTGraphicsBase(aStep)
+    {
+    }
+
+CTFbsGlyphDataOutlineAndShadow::~CTFbsGlyphDataOutlineAndShadow()
+    {
+    if (iTs)
+       {
+       iTs->ReleaseFont(iFont);
+       delete iTs;
+       }
+    }
+
+void CTFbsGlyphDataOutlineAndShadow::ConstructL()
+    {
+    iTs = (CFbsTypefaceStore*)CFbsTypefaceStore::NewL(NULL);
+    TFontSpec fontSpec;
+    fontSpec.iTypeface.iName = KTypefaceName;
+    fontSpec.iHeight = 15;
+    fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
+    fontSpec.iFontStyle.SetEffects(FontEffect::EDropShadow, EDropShadowOn);
+    fontSpec.iFontStyle.SetEffects(FontEffect::EOutline, EOutlineOn);
+    User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont, fontSpec));
+    //now check if the font is what we requested
+    if(iFont->FontSpecInTwips().iFontStyle.BitmapType()!=EFourColourBlendGlyphBitmap)
+        {
+        WARN_PRINTF1(_L("Monotype font is not installed, run iType\\binaries\\ityperast.cmd to install it"));
+        User::Leave(KErrNotSupported);
+        }
+    }
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0646
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+    To ensure that glyph iterator doesn't support outline-and-shadow font
+@SYMTestActions
+    i. Call RFbsGlyphDataIterator::Open() with an outline-and-shadow font.
+
+@SYMTestExpectedResults
+    RFbsGlyphDataIterator::Open() returns KErrNotSupported.
+*/
+void CTFbsGlyphDataOutlineAndShadow::RunTestCaseL(TInt /*aCurTestCase*/)
+    {
+    INFO_PRINTF1(_L("Ensure that glyph iterator doesn't support outline-and-shadow font"));
+    ((CTFbsGlyphDataOutlineAndShadowStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0646"));
+    RFbsGlyphDataIterator iter;
+    const TUint glyphCode = 50;
+    TInt err = iter.Open(*iFont, &glyphCode, 1);
+    TESTE(err == KErrNotSupported, err);
+    iter.Close();
+
+    ((CTFbsGlyphDataOutlineAndShadowStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);//_L("GRAPHICS-FBSERV-0645"));
+    ((CTFbsGlyphDataOutlineAndShadowStep*)iStep)->CloseTMSGraphicsStep();
+    TestComplete();     
+    ((CTFbsGlyphDataOutlineAndShadowStep*)iStep)->RecordTestResultL();
+    }
+
+__CONSTRUCT_STEP__(FbsGlyphDataOutlineAndShadow)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/tfbsglyphdataoutlineshadow.h	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,69 @@
+// Copyright (c) 2009-2010 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:
+//
+
+#ifndef TFBSGLYPHDATAOUTLINESHADOW_H
+#define TFBSGLYPHDATAOUTLINESHADOW_H
+
+#include "test/TGraphicsHarness.h"
+
+
+/** 
+Enumeration for the attributes to be set in fontspec and gc.
+See CTFbsGlyphDataOutlineAndShadow::ConstructL()
+*/
+enum TFontEffectsFlags
+    {
+    EDropShadowOn = 0x1,
+    EOutlineOn = 0x2,
+    };
+
+/**
+Test class which checks that glyph data extensions 
+RFbsGlyphDataIterator processes and returns correct error if outline-and-shadow
+font is supplied. 
+
+This test must be run with a rasterizer which supports EFourColourBlendGlyphBitmap (e.g. iType)
+otherwise the test will fail.
+
+Negative test
+*/
+class CTFbsGlyphDataOutlineAndShadow : public CTGraphicsBase
+    {
+public:
+    CTFbsGlyphDataOutlineAndShadow(CTestStep* aStep);
+    ~CTFbsGlyphDataOutlineAndShadow();
+protected:
+//from  CTGraphicsBase
+    virtual void RunTestCaseL(TInt aCurTestCase);
+    void ConstructL();
+    
+private:
+    CFbsTypefaceStore* iTs;
+    CFbsFont* iFont;
+   };
+
+class CTFbsGlyphDataOutlineAndShadowStep : public CTGraphicsStep
+    {
+public:
+    CTFbsGlyphDataOutlineAndShadowStep();
+protected:  
+    //from CTGraphicsStep
+    virtual CTGraphicsBase* CreateTestL();
+    };
+
+_LIT(KTFbsGlyphDataOutlineAndShadowStep,"TFbsGlyphDataOutlineAndShadow");
+
+
+#endif /* TFBSGLYPHDATAOUTLINESHADOW_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/tfbsglyphdatapanic.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,487 @@
+// Copyright (c) 2009-2010 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:
+//
+
+/**
+ @file
+ @internalComponent - Internal Symbian test code
+*/
+
+#include <graphics/fbsglyphmetricsarray.h> 
+#include <graphics/fbsglyphdataiterator.h>
+#include "tfbsglyphdatapanic.h"
+
+_LIT(KTypefaceName, "DejaVu Sans Condensed");
+const TInt KNumGlyphCodes = 96;
+
+/*
+Lookup table to convert from ascii code to
+glyph code for the Deja Vu family of fonts.
+ */
+const TUint DejaVuASCIIToGlyphCode[] = 
+    {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 3, 4, 5, 6, 7, 8, 9, 10, 
+    11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 
+    21, 22, 23, 24, 25, 26, 27, 28, 29, 30,     
+    31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+    51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 
+    61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+    71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+    81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+    91, 92, 93, 94, 95, 96, 97, 98, 
+    };
+
+CTFbsGlyphDataPanic::CTFbsGlyphDataPanic(CTestStep* aStep):
+    CTGraphicsBase(aStep)
+    {
+    }
+
+CTFbsGlyphDataPanic::~CTFbsGlyphDataPanic()
+    {
+    iSgDriver.Close();
+    if (iTs)
+         {
+         iTs->ReleaseFont(iFont);
+         delete iTs;
+         }
+    }
+
+void CTFbsGlyphDataPanic::ConstructL()
+    {
+    User::LeaveIfNull(iFbs = RFbsSession::GetSession());
+    User::LeaveIfNull(iTs = (CFbsTypefaceStore*)CFbsTypefaceStore::NewL(NULL));
+    User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont, TFontSpec(KTypefaceName, 15)));
+    User::LeaveIfError(iSgDriver.Open());
+    
+    //initialize the array with ASCII characters from 0020 to 007F
+    iGlyphCodes = new(ELeave) TUint[KNumGlyphCodes];
+    for (TInt i = 0; i < KNumGlyphCodes; ++i)
+        {
+        TUint asciiCode = i+0x20; 
+        iGlyphCodes[i] = DejaVuASCIIToGlyphCode[asciiCode];
+        }
+    }
+
+void CTFbsGlyphDataPanic::RunTestCaseL(TInt /*aCurTestCase*/)
+    {
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
+    TInt testCase = -1;
+    _LIT(KCaseNumber, "CaseNumber");
+    TEST(iStep->GetIntFromConfig(iStep->ConfigSection(), KCaseNumber, testCase));
+    
+    switch(testCase)
+        {
+    case 1:
+        TestGlyphDataIteratorNotInitializedNext();
+        break;
+    case 2:
+        TestGlyphDataIteratorNotInitializedImage();
+        break;
+    case 3:
+        TestGlyphDataIteratorNotInitializedMetrics();
+        break;
+    case 4:
+        TestGlyphDataIteratorNotInitializedGlyphCode();
+        break;
+    case 5:
+        TestGlyphDataIteratorClosedNext();
+        break;
+    case 6:
+        TestGlyphDataIteratorClosedImage();
+        break;
+    case 7:
+        TestGlyphDataIteratorClosedMetrics();
+        break;
+    case 8:
+        TestGlyphDataIteratorClosedGlyphCode();
+        break;
+    case 9:
+        TestGlyphDataIteratorDiscardUsedFont();
+        break;
+    case 10:
+        TestGlyphMetricsArrayIndexNegative();
+        break;
+    case 11:
+    	TestGlyphMetricsArrayIndexTooHigh();
+        break;
+    case 12:
+    	TestGlyphDataIteratorOpenFailed();
+    	break;
+    default:
+        break;
+        }
+    TEST(EFalse); // shouldn't reach this point as the test will panic at the end of each test case function
+    
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
+    ((CTFbsGlyphDataPanicStep*)iStep)->CloseTMSGraphicsStep();
+    TestComplete();     
+    ((CTFbsGlyphDataPanicStep*)iStep)->RecordTestResultL();
+    }
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0651
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that calling Next() on an unopened iterator will panic.
+
+@SYMTestActions
+	Call Next() on an RFbsGlyphDataIterator instance without opening it.
+
+@SYMTestExpectedResults
+	The call to Next() should panic with GDI 4.
+*/
+void CTFbsGlyphDataPanic::TestGlyphDataIteratorNotInitializedNext()
+    {
+    INFO_PRINTF1(_L("Ensure that Next() operation applied on null iterator will panic"));
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0651"));
+    RFbsGlyphDataIterator iter;
+    iter.Next(); //expect to panic here
+    }
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0652
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that Image() function applied on an unopened iterator will panic.
+
+@SYMTestActions
+	Call Image() on an RFbsGlyphDataIterator instance without opening it.
+
+@SYMTestExpectedResults
+	The call to Image() should panic with GDI 4.
+*/
+void CTFbsGlyphDataPanic::TestGlyphDataIteratorNotInitializedImage()
+    {
+    INFO_PRINTF1(_L("Ensure that Image() operation applied on null iterator will panic"));
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0652"));
+    RFbsGlyphDataIterator iter;
+    iter.Image(); //expect to panic here
+    }
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0653
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that Metrics() function applied on null iterator will panic.
+
+@SYMTestActions
+	Call Metrics() on an RFbsGlyphDataIterator instance without opening it.
+
+@SYMTestExpectedResults
+	The call to Metrics() should panic with GDI 4.
+*/
+void CTFbsGlyphDataPanic::TestGlyphDataIteratorNotInitializedMetrics()
+    {
+    INFO_PRINTF1(_L("Ensure that Metrics() operation applied on null iterator will panic"));
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0653"));
+    RFbsGlyphDataIterator iter;
+    iter.Metrics(); //expect to panic here
+    }
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0654
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that calling GlyphCode() on an unopened iterator will panic.
+
+@SYMTestActions
+	Call GlyphCode() on an RFbsGlyphDataIterator instance without opening it.
+
+@SYMTestExpectedResults
+	The call to GlyphCode() should panic with GDI 4.
+*/
+void CTFbsGlyphDataPanic::TestGlyphDataIteratorNotInitializedGlyphCode()
+    {
+    INFO_PRINTF1(_L("Ensure that GlyphCode() operation applied on null iterator will panic"));
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0654"));
+    RFbsGlyphDataIterator iter;
+    iter.GlyphCode(); //expect to panic here
+    }
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0655
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that calling Next() on an iterator which has been closed will panic.
+
+@SYMTestActions
+	i. Open the glyph data iterator with 1 glyph code.
+	ii. Call Next() to attempt to move the iterator past the end of the array of glyph codes.
+	iii. Call Close() and repeat ii.
+
+@SYMTestExpectedResults
+	The call to Next() should fail with KErrNotFound, signifying the iterator is still open.
+	The final call to Next() should panic with GDI 4.
+*/
+void CTFbsGlyphDataPanic::TestGlyphDataIteratorClosedNext()
+    {
+    INFO_PRINTF1(_L("Ensure that Next() operation applied on iterator which has been closed will panic"));
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0655"));
+    RFbsGlyphDataIterator iter;
+    TESTNOERROR(iter.Open(*iFont, iGlyphCodes, 1));
+    TInt iterErr = iter.Next();
+    TESTE(iterErr == KErrNotFound, iterErr);
+    iter.Close();
+    iter.Next(); //expect to panic here
+    }
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0656
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that calling Image() on an iterator which has been closed will panic.
+
+@SYMTestActions
+	i. Open the glyph data iterator.
+	ii. Close the glyph data iterator.
+	iii. Call Image() on an RFbsGlyphDataIterator instance which has been closed.
+
+@SYMTestExpectedResults
+	The call to Image() should panic with GDI 4.
+*/
+void CTFbsGlyphDataPanic::TestGlyphDataIteratorClosedImage()
+    {
+    INFO_PRINTF1(_L("Ensure that Image() operation applied on iterator which has been closed will panic"));
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0656"));
+    RFbsGlyphDataIterator iter;
+    OpenAndCloseIterator(iter);
+    iter.Image(); //expect to panic here
+    }
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0657
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that calling Metrics() on an iterator which has been closed will panic.
+
+@SYMTestActions
+	i. Open the glyph data iterator.
+	ii. Close the glyph data iterator.
+	iii. Call Metrics() on an RFbsGlyphDataIterator instance which has been closed.
+
+@SYMTestExpectedResults
+	The call to Metrics() should panic with GDI 4.
+*/
+void CTFbsGlyphDataPanic::TestGlyphDataIteratorClosedMetrics()
+    {
+    INFO_PRINTF1(_L("Ensure that Metrics()operation applied on iterator which has been closed will panic"));
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0657"));
+    RFbsGlyphDataIterator iter;
+    OpenAndCloseIterator(iter);
+    iter.Metrics(); //expect to panic here
+    }
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0658
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      In development
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that calling GlyphCode() on an iterator which has been closed will panic.
+
+@SYMTestActions
+	i. Open the glyph data iterator.
+	ii. Close the glyph data iterator.
+	iii. Call GlyphCode() on an RFbsGlyphDataIterator instance which has been closed.
+
+@SYMTestExpectedResults
+	The call to GlyphCode() should panic with GDI 4.
+*/
+void CTFbsGlyphDataPanic::TestGlyphDataIteratorClosedGlyphCode()
+    {
+    INFO_PRINTF1(_L("Ensure that GlyphCode() operation applied on iterator which has been closed will panic"));
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0658"));
+    RFbsGlyphDataIterator iter;
+    OpenAndCloseIterator(iter);
+    iter.GlyphCode(); //expect to panic here
+    }
+
+// the function opens and then closes an iterator
+void CTFbsGlyphDataPanic::OpenAndCloseIterator(RFbsGlyphDataIterator& aIterator) 
+    {
+    TESTNOERROR(aIterator.Open(*iFont, iGlyphCodes, 1));
+    aIterator.Close();
+    }
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0647
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that attempting to use an invalid Font handle will cause a panic when iterating through an RFbsGlyphDataIterator. 
+
+@SYMTestActions
+	i. Open the glyph data iterator.
+	ii. Release the font associated with the iterator.
+	iii. Attempt to use invalid Font handle by iterating through the iterator.
+
+@SYMTestExpectedResults
+	The call to Next() after the associated Font has been released should cause panic FBSERV -8 when the invalid Font handle is passed to FBServ.
+*/
+void CTFbsGlyphDataPanic::TestGlyphDataIteratorDiscardUsedFont()
+    {
+    INFO_PRINTF1(_L("Ensure that attempting to use an invalid Font handle will cause a panic when iterating through an RFbsGlyphDataIterator"));
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0647"));
+    
+    RFbsGlyphDataIterator iter;
+    TESTNOERROR(iter.Open(*iFont, iGlyphCodes, KNumGlyphCodes));
+    iTs->ReleaseFont(iFont);
+    
+    for (TInt i = 0; i < KNumGlyphCodes; i++)
+        {
+        //should panic when attempt is made to use invalid Font handle
+        iter.Next();
+        }
+
+    iter.Close(); //shouldn't reach this line. If for some reason the code doesn't panic test should fail.
+    TEST(EFalse);  
+    }
+    
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0648
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that accessing the glyph metrics entry with negative index will cause a panic.
+
+@SYMTestActions
+	i. Retrieve glyph metrics array.
+	ii. Try to access glyph metrics entry with a negative index.
+
+@SYMTestExpectedResults
+	Should panic with GDI 5.
+*/
+void CTFbsGlyphDataPanic::TestGlyphMetricsArrayIndexNegative()
+    {
+    INFO_PRINTF1(_L("Ensure that accessing the glyph metrics entry with negative index will cause a panic"));
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0648"));
+    RFbsGlyphMetricsArray glyphMetricsArray;
+
+    // Retrieve list of metrics
+    TESTNOERROR(glyphMetricsArray.Get(*iFont, iGlyphCodes, 2));
+    TEST(2 == glyphMetricsArray.Count());
+    glyphMetricsArray[-1];
+    }
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0649
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that accessing the glyph metrics entry with an index greater than number
+	of elements in array will cause a panic.
+
+@SYMTestActions
+	i. Retrieve a glyph metrics array with total number of elements equals 2 
+	ii. Try to access glyph metrics entry with index equals 2.
+
+@SYMTestExpectedResults
+	Should panic with GDI 5.
+*/
+void CTFbsGlyphDataPanic::TestGlyphMetricsArrayIndexTooHigh()
+    {
+    INFO_PRINTF1(_L("Ensure that accessing the glyph metrics entry with index greater than number of elemnets in array will cause a panic"));
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0649"));
+    RFbsGlyphMetricsArray glyphMetricsArray;
+
+    // Retrieve list of metrics
+    TESTNOERROR(glyphMetricsArray.Get(*iFont, iGlyphCodes, 2));
+    TEST(2 == glyphMetricsArray.Count());
+    glyphMetricsArray[2]; //expect to panic here as index varies 0..1
+    }
+
+/**
+@SYMTestCaseID      GRAPHICS-FBSERV-0667
+@SYMTestPriority    High
+@SYMTestType        UT
+@SYMTestStatus      Implemented
+@SYMPREQ            PREQ2678
+
+@SYMTestCaseDesc
+	To ensure that if RFbsGlyphDataIterator::Open() fails, it is still in the closed state
+	and cannot be used.
+
+@SYMTestActions
+	i. Open an RFbsGlyphDataIterator on a font.  
+	ii. Attempt to open a second RFbsGlyphDataIterator on the same font.
+	ii. Attempt to use the properties of the iterator.
+
+@SYMTestExpectedResults
+	The call to GlyphCode() should panic with FBSCLI 31 since the iterator should be in a closed state.
+*/
+void CTFbsGlyphDataPanic::TestGlyphDataIteratorOpenFailed()
+	{
+    INFO_PRINTF1(_L("Ensure that if RFbsGlyphDataIterator::Open() fails, it is still in the closed state and cannot be used"));
+    ((CTFbsGlyphDataPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0667"));
+   
+    CFbsFont* bitmapFont = NULL;
+    TInt err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)bitmapFont, TFontSpec(_L("Digital"), 14));
+    TESTNOERROR(err);
+    TEST(!bitmapFont->IsOpenFont());
+    
+    RFbsGlyphDataIterator iter;
+    err = iter.Open(*bitmapFont, iGlyphCodes, 2);
+    TEST(err == KErrNotSupported);
+        
+    iter.GlyphCode(); // Should panic here as iter should be closed.
+    TEST(EFalse);     //shouldn't reach this line. If for some reason the code doesn't panic test should fail.
+    
+	}
+//--------------
+__CONSTRUCT_STEP__(FbsGlyphDataPanic)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/tfbsglyphdatapanic.h	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,74 @@
+// Copyright (c) 2009-2010 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:
+//
+
+#ifndef TFBSGLYPHDATAPANIC_H
+#define TFBSGLYPHDATAPANIC_H
+
+#include <sgresource/sgresource.h>
+#include "test/TGraphicsHarness.h"
+class RFbsGlyphDataIterator;
+
+/**
+Test class which exercises all panics for the glyph data extensions 
+RFbsGlyphDataIterator and RFbsGlyphMetricsArray. 
+Negative tests
+*/
+class CTFbsGlyphDataPanic : public CTGraphicsBase
+    {
+public:
+    CTFbsGlyphDataPanic(CTestStep* aStep);
+    ~CTFbsGlyphDataPanic();
+protected:
+//from  CTGraphicsBase
+    virtual void RunTestCaseL(TInt aCurTestCase);
+    void ConstructL();
+    
+//test cases
+    void TestGlyphDataIteratorNotInitializedNext();
+    void TestGlyphDataIteratorNotInitializedImage();
+    void TestGlyphDataIteratorNotInitializedMetrics();
+    void TestGlyphDataIteratorNotInitializedGlyphCode();
+    void TestGlyphDataIteratorClosedNext();
+    void TestGlyphDataIteratorClosedImage();
+    void TestGlyphDataIteratorClosedMetrics();
+    void TestGlyphDataIteratorClosedGlyphCode();
+    void TestGlyphDataIteratorDiscardUsedFont();
+    void TestGlyphMetricsArrayIndexNegative();
+    void TestGlyphMetricsArrayIndexTooHigh();
+    void TestGlyphDataIteratorOpenFailed();
+
+    //helper function
+    void OpenAndCloseIterator(RFbsGlyphDataIterator& aIterator); // the function opens and then closes an iterator
+private:
+    RFbsSession* iFbs;
+    CFbsTypefaceStore* iTs;
+    CFbsFont* iFont;
+    RSgDriver iSgDriver;
+    TUint* iGlyphCodes;
+   };
+
+class CTFbsGlyphDataPanicStep : public CTGraphicsStep
+    {
+public:
+    CTFbsGlyphDataPanicStep();
+protected:  
+    //from CTGraphicsStep
+    virtual CTGraphicsBase* CreateTestL();
+    };
+
+_LIT(KTFbsGlyphDataPanicStep,"TFbsGlyphDataPanic");
+
+
+#endif /* TFBSGLYPHDATAPANIC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/tfbsoogm.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,370 @@
+// Copyright (c) 2009-2010 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: Test the operation of the Font and Bitmap Server's GOoM plug-in
+//
+
+
+#include <gdi.h>
+#include "tfbsoogm.h"
+
+
+
+const TInt KTFbsOogmFrameworkPause = 500000; // How long does this need to be in order to be reliable?
+const TInt KTFbsOogmImageSizeX = 2048;
+const TInt KTFbsOogmImageSizeY = 2048;
+
+
+void CTFbsOogm::RunTestCaseL( TInt aCurTestCase )
+    {
+    ( (CTFbsOogmStep*)iStep )->SetTestStepID( KUnknownSYMTestCaseIDName );
+
+    switch( aCurTestCase )
+        {
+    case 1:
+        ( (CTFbsOogmStep*)iStep )->SetTestStepID( _L("GRAPHICS-FBSERV-0675") );
+
+        CacheClearanceAndLimitAdjustments();
+        break;
+
+    default:
+        ( (CTFbsOogmStep*)iStep )->SetTestStepID( KNotATestSYMTestCaseIDName );
+        ( (CTFbsOogmStep*)iStep )->CloseTMSGraphicsStep();
+        TestComplete();
+
+        break;
+        }
+
+    ( (CTFbsOogmStep*)iStep )->RecordTestResultL();
+
+    }
+
+
+
+/**
+ 	@SYMTestCaseID
+	GRAPHICS-FBSERV-0675
+
+	@SYMTestCaseDesc
+	Tests the operation of Font and Bitmap server's  Out-Of-Graphics-Memory plugin.
+	ie Ensure that the hardware glyph cache is cleared in response to a low graphics 
+	memory notification, and that the cache's maximum size limit is reduced.
+
+
+	@SYMTestActions
+	Acquire the glyph cache's usage and other metrics.
+	
+	Populate the glyph-cache.
+
+	Acquire the glyph-cache's usage and other metrics.
+
+	Precipitate an Out-of-Graphics-Memory condition, triggering the GOOM monitor.
+
+	Acquire the glyph cache's usage and other metrics.
+
+	Ensure the glyph-cache has been cleared and its maximum limit reduced.
+
+	Precipitate a MemoryGood() call from the GOoM framework.
+
+	Establish that the cache-size limit has been reinstated.
+
+	@SYMTestExpectedResults
+    The glyph-cache should be cleared in response to OoGM condition and its upper limit reduced.
+
+    The Glyph-cache's upper limit should be reinstated in response to a memory-good notification.
+ */
+void CTFbsOogm::CacheClearanceAndLimitAdjustments()
+    {
+    __UHEAP_MARK;
+
+    RArray <RSgImage> sgImageArray;
+    RSgDriver sgDriver;
+    TInt err = sgDriver.Open();
+
+    if( KErrNone != err )
+        {
+		TEST( KErrNone == err );
+		INFO_PRINTF2( _L("SgDriver Open() returned error %d"), err );
+
+        return;
+        }
+
+    if( (NULL == RFbsSession::GetSession()) )
+         {
+        if( KErrNone != RFbsSession::Connect() )
+            {
+ 			TEST( -1 );
+			INFO_PRINTF1(_L("Failed to connect to FbServ"));
+
+            goto CleanupAndGo;
+            }
+         }
+
+
+	// Establish the initial condition of the glyph-cache.
+    TGlyphCacheMetrics initialGlyphCacheMetrics;
+    err = RFbsSession::GetSession()->GetGlyphCacheMetrics( initialGlyphCacheMetrics );
+    if( KErrNone != err )
+        {
+		TEST( KErrNone == err );
+		INFO_PRINTF2( _L("GetGlyphCacheMetrics() returned error %d"), err );
+
+        goto CleanupAndGo;
+        }
+
+	// Check that initial conditions are as expected.
+    // There was a test here for a cache-size of zero, but this was felt to be a hazardous assumption.
+	TEST( initialGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
+    INFO_PRINTF4( _L("Initial iMaxCacheSizeInBytes %d iCacheSizeInBytes %d iGpuCacheSizeLimitIsMax %d "),
+                      initialGlyphCacheMetrics.iMaxCacheSizeInBytes,
+                      initialGlyphCacheMetrics.iCacheSizeInBytes,
+                      initialGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
+
+
+    TRAP( err, UseGpuL() ); // Populate the glyph cache then acquire its usage metrics.
+    if( KErrNone != err )
+        {
+        TEST( KErrNone == err );
+        INFO_PRINTF2( _L("UseGpuL() left with %d"), err );
+
+        goto CleanupAndGo;
+        }
+
+
+    TGlyphCacheMetrics usageGlyphCacheMetrics;
+    err = RFbsSession::GetSession()->GetGlyphCacheMetrics( usageGlyphCacheMetrics );
+    if( KErrNone != err )
+        {
+		TEST( KErrNone == err );
+		INFO_PRINTF2( _L("GetGlyphCacheMetrics() returned %d"), err );
+
+        goto CleanupAndGo;
+        }
+
+    // Check that the glyph cache has been populated
+    TEST( usageGlyphCacheMetrics.iCacheSizeInBytes > initialGlyphCacheMetrics.iCacheSizeInBytes);
+    TEST( usageGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
+    INFO_PRINTF4( _L("Usage iMaxCacheSizeInBytes %d iCacheSizeInBytes %d iGpuCacheSizeLimitIsMax %d "),
+                       usageGlyphCacheMetrics.iMaxCacheSizeInBytes,
+                       usageGlyphCacheMetrics.iCacheSizeInBytes,
+                       usageGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
+
+
+
+    // Precipitate the GOoM framework's call into the Plug-in's FreeRam() method.
+    err = FillGraphicsMemoryWithImages( TSize(KTFbsOogmImageSizeX, KTFbsOogmImageSizeY), sgImageArray );
+    if( KErrNoGraphicsMemory != err )
+        {
+		TEST( KErrNoGraphicsMemory == err );
+		INFO_PRINTF2( _L("FillGraphicsMemoryWithImages() returned %d"), err );
+
+        goto CleanupAndGo;
+        }
+
+	// Await the GOOM framework's call into FbServ's OoGM plugin,
+    // then establish the cache's usage and other metrics.
+    User::After( KTFbsOogmFrameworkPause );
+    TGlyphCacheMetrics postOogmGlyphCacheMetrics;
+    err = RFbsSession::GetSession()->GetGlyphCacheMetrics( postOogmGlyphCacheMetrics );
+
+    if( KErrNone != err )
+        {
+		TEST( KErrNone == err );
+		INFO_PRINTF2( _L("GetGlyphCacheMetrics() returned %d"), err );
+
+        goto CleanupAndGo;
+        }
+
+    // The cache should have been cleared and the maximum size limit reduced.
+    TEST( 0 == postOogmGlyphCacheMetrics.iCacheSizeInBytes );
+    TEST( !postOogmGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
+    INFO_PRINTF4( _L("Post-Oogm iMaxCacheSizeInBytes %d iCacheSizeInBytes %d iGpuCacheSizeLimitIsMax %d "),
+                        postOogmGlyphCacheMetrics.iMaxCacheSizeInBytes,
+                        postOogmGlyphCacheMetrics.iCacheSizeInBytes,
+                        postOogmGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
+
+
+
+   // Remove the images. This should provoke a GOoM monitor call into the plug-in's MemoryGood().
+    for ( TInt i = sgImageArray.Count()-1; i >= 0; --i )
+        {
+        sgImageArray[i].Close();
+        }
+    sgImageArray.Reset();
+
+    // Await activity from the GOoM monitor
+    User::After( KTFbsOogmFrameworkPause );
+    TGlyphCacheMetrics reinstatedGlyphCacheMetrics;
+    err = RFbsSession::GetSession()->GetGlyphCacheMetrics( reinstatedGlyphCacheMetrics );
+    if( KErrNone != err )
+        {
+        TEST( KErrNone == err );
+        INFO_PRINTF2( _L("GetGlyphCacheMetrics() returned error %d"), err );
+
+        goto CleanupAndGo;
+        }
+
+    // Cache size limit should have been increased
+    TEST( reinstatedGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
+    INFO_PRINTF4( _L("After Mem Clear iMaxCacheSizeInBytes %d iCacheSizeInBytes %d iGpuCacheSizeLimitIsMax %d "),
+                      reinstatedGlyphCacheMetrics.iMaxCacheSizeInBytes,
+                      reinstatedGlyphCacheMetrics.iCacheSizeInBytes,
+                      reinstatedGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
+
+
+
+  CleanupAndGo:
+    // Release any images before closing the array.
+    // If the test was successful this should already be empty.
+    for (TInt i = sgImageArray.Count()-1; i >= 0; --i)
+        {
+        sgImageArray[i].Close();
+        }
+
+    // Allow GOoM to make any pending adjustments before proceeding with any further tests.
+    User::After( KTFbsOogmFrameworkPause );
+    sgImageArray.Close();
+    sgDriver.Close();
+
+    __UHEAP_MARKEND;
+    }
+
+
+
+CTFbsOogm::CTFbsOogm( CTestStep* aStep )
+: CTGraphicsBase(aStep)
+    {
+    }
+
+
+
+const TInt KNumGlyphCodesLatin = 96;
+/*
+ Lookup table to convert from ascii code to
+glyph code for the Deja Vu family of fonts.
+ */
+const TUint DejaVuASCIIToGlyphCode[] =
+    {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 3, 4, 5, 6, 7, 8, 9, 10,
+    11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+    21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+    31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+    51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+    61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+    71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+    81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+    91, 92, 93, 94, 95, 96, 97, 98,
+    };
+
+
+
+void CTFbsOogm::ConstructL()
+    {
+    }
+
+
+CTFbsOogm::~CTFbsOogm()
+    {
+    RFbsSession::Disconnect();
+    }
+
+
+
+/**
+ Utility function to fill the GPU memory.
+ */
+TInt CTFbsOogm::FillGraphicsMemoryWithImages( const TSize& aSize, RArray<RSgImage>& aImages )
+    {
+    TInt err = KErrNone;
+
+    // Loop should terminate with KErrNoGraphicsMemory
+    while( KErrNone == err )
+        {
+        RSgImage sgImage;
+        err = sgImage.Create( TSgImageInfo(aSize, ESgPixelFormatA_8, ESgUsageBitOpenVgImage) );
+        if( KErrNone == err )
+            {
+            err = aImages.Append( sgImage );
+            }
+        }
+
+    INFO_PRINTF2( _L("Images created %d"), aImages.Count() );
+    return err;
+    }
+
+
+
+/**
+ Utility function to populate the GPU with typeface glyphs.
+ */
+void CTFbsOogm::UseGpuL()
+    {
+    _LIT( KTKASTypefaceName, "DejaVu Sans Condensed" );
+
+    // Need to open one of these "in the context" of this process in order
+    // to manipulate RSgImages. Even though we are only calling 'Open', 'Next' and 'Close' on
+    // RFbsGlyphDataIterator
+    RSgDriver sgDriver;
+    User::LeaveIfError( sgDriver.Open() );
+
+    // CFbsTypefaceStore seems to need an fbserv session open.
+    if( (NULL == RFbsSession::GetSession()) )
+     {
+     User::LeaveIfError( RFbsSession::Connect() );
+     }
+
+    TUint* glyphCodesLatin = new(ELeave) TUint[ KNumGlyphCodesLatin ];
+
+    for ( TInt ii = 0; ii < KNumGlyphCodesLatin; ++ii )
+        {
+        TUint asciiCode = ii+0x20; // ASCII characters from 0020 to 007F
+        glyphCodesLatin[ii] = DejaVuASCIIToGlyphCode[asciiCode];
+        }
+
+    iTs = ( CFbsTypefaceStore* )CFbsTypefaceStore::NewL( NULL );
+    User::LeaveIfError( iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont, TFontSpec(KTKASTypefaceName, 15)) );
+
+    TInt iterErr = KErrNone;
+    TInt iterNextErr = KErrNone;
+
+    for( TInt arraySize = 1; (arraySize < KNumGlyphCodesLatin) && (iterErr == KErrNone); ++arraySize )
+        {
+        RFbsGlyphDataIterator iter;
+        iterErr = iter.Open( *iFont, glyphCodesLatin, arraySize );
+
+        if( KErrNone != iterErr )
+            {
+            continue;
+            }
+
+          for ( TInt index = 0; KErrNone == iterNextErr; iterNextErr = iter.Next(), ++index )
+              {
+              // Iterating through the glyphs should introduce them into the cache
+             if(iter.GlyphCode() != glyphCodesLatin[index])
+                {
+                 INFO_PRINTF4( _L("Wanted glyphcode %d, got %d"), arraySize, glyphCodesLatin[index], iter.GlyphCode() );
+                }
+              }
+
+        iterNextErr = KErrNone;
+        iter.Close();
+        }
+
+    sgDriver.Close();
+    }
+
+
+__CONSTRUCT_STEP__( FbsOogm )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/tfbsoogm.h	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,75 @@
+// Copyright (c) 2009-2010 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:
+//
+
+#ifndef TFBSOOGM_H
+#define TFBSOOGM_H
+#include <EGL/egl.h>
+
+#include <e32cmn.h>
+#include <EGL/eglext.h>
+#include <VG/openvg.h>
+#include <sgresource/sgresource.h>
+#include <sgresource/sgimage.h>
+#include <graphics/fbsglyphdataiterator.h>
+#include "FbsMessage.h"
+
+#include "test/TGraphicsHarness.h"
+
+
+/**
+Test class for the GPU 'Out of Graphics Memory' (OoGM) plug-in
+
+Hardware only as the GoomMonitor framework does not operate under WINSCW
+*/
+class CTFbsOogm : public CTGraphicsBase
+    {
+public:
+    CTFbsOogm( CTestStep* aStep );
+    ~CTFbsOogm();
+protected:
+    //from  CTGraphicsBase
+    virtual void RunTestCaseL( TInt aCurTestCase );
+    void ConstructL();
+
+private:
+    // Test Cases
+    void CacheClearanceAndLimitAdjustments();
+
+private:
+    void UseGpuL();
+    TInt FillGraphicsMemoryWithImages( const TSize& aSize, RArray<RSgImage>& aImages );
+
+private:
+    CFbsFont* iFont;
+    CFbsTypefaceStore* iTs;
+    };
+
+
+
+class CTFbsOogmStep : public CTGraphicsStep
+    {
+public:
+    CTFbsOogmStep();
+
+protected:
+    //from CTGraphicsStep
+    virtual CTGraphicsBase* CreateTestL();
+    };
+
+_LIT( KTFbsOogmStep,"TFbsOogm" );
+
+
+
+#endif // TFBSOOGM_H
--- a/fbs/fontandbitmapserver/tfbs/tfonttableandglyph.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/tfonttableandglyph.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2009-2010 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"
@@ -17,7 +17,7 @@
 #define TFONTTABLEANDGLYPH_H_
 
 #include <gdi.h>
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 
 class CTFontAndGlyphStep : public CTGraphicsStep
     {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/tglyphatlas.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,284 @@
+// Copyright (c) 2009-2010 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:
+//
+
+/**
+ @file
+ @internalComponent - Internal Symbian test code
+*/
+
+#include "tglyphatlas.h"
+#include "TFBS.H"
+#include "glyphatlastestwrapper.h"
+
+_LIT(KTypefaceName, "DejaVu Sans Condensed");
+_LIT(KMonoTypefaceName, "DejaVu Sans Mono");
+const TInt KNumGlyphCodesLatin = 96;
+
+
+CTGlyphAtlas::CTGlyphAtlas(CTestStep* aStep):
+	CTGraphicsBase(aStep),
+	iFbs(NULL),
+	iTs(NULL),
+	iGlyphCodesLatin(NULL),
+	iFont(NULL)
+	{
+	}
+
+void CTGlyphAtlas::ConstructL()
+	{
+	iFbs = RFbsSession::GetSession();
+	iTs = (CFbsTypefaceStore*)CFbsTypefaceStore::NewL(NULL);
+	User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont, TFontSpec(KTypefaceName, 15)));
+	User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont2, TFontSpec(KMonoTypefaceName, 8)));
+	
+	iGlyphCodesLatin = new(ELeave) TUint[KNumGlyphCodesLatin];
+	for (TInt ii = 0; ii < KNumGlyphCodesLatin; ++ii)
+		{
+		iGlyphCodesLatin[ii] = ii+32; // ASCII characters from 0020 to 007F
+		}
+
+	INFO_PRINTF1(_L("FBSERV Glyph Atlas Testing"));
+	}
+
+CTGlyphAtlas::~CTGlyphAtlas()
+	{
+	if (iTs)
+		{
+		iTs->ReleaseFont(iFont);
+		}
+	delete iTs;
+	delete[] iGlyphCodesLatin;
+	}
+
+void CTGlyphAtlas::RunTestCaseL(TInt aCurTestCase)
+	{
+	((CTGlyphAtlasStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
+	switch(aCurTestCase)
+		{
+	case 1:
+		((CTGlyphAtlasStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0663"));
+		TestFullCache();
+		break;
+	case 2:
+		((CTGlyphAtlasStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0664"));
+		TestFontReleased();
+		break;
+	default:
+		((CTGlyphAtlasStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
+		((CTGlyphAtlasStep*)iStep)->CloseTMSGraphicsStep();
+		TestComplete();		
+		break;
+		}
+	((CTGlyphAtlasStep*)iStep)->RecordTestResultL();
+	}
+
+/**
+@SYMTestCaseID		GRAPHICS-FBSERV-0663
+@SYMTestPriority	High
+@SYMTestType		UT
+@SYMTestStatus		Implemented
+@SYMPREQ			PREQ2678
+
+@SYMTestCaseDesc
+	Shows that when the glyph atlas reaches its memory limit, any new added 
+	glyphs will cause the eviction of the least recently used glyphs.
+	The new glyph will be added successfully.
+
+@SYMTestActions
+	i. Create a glyph atlas with a memory limit of 1000 bytes.
+	ii. Add glyphs to the atlas such that its memory consumption reaches the limit.
+	iii. Add one more glyph.
+	iv. Call CGlyphAtlas::GetGlyph() for the last glyph added.
+	v. Call CGlyphAtlas::GetGlyph() for the least recently used glyphs to check 
+		that it has been evicted.
+	vi. Delete glyph atlas
+
+@SYMTestExpectedResults
+	Each glyph is added successfully.
+	CGlyphAtlas::GetGlyph() returns KErrNone for the last glyph added.
+	CGlyphAtlas::GetGlyph() returns KErrNotFound for the least recently used glyph.
+*/
+void CTGlyphAtlas::TestFullCache()
+	{
+	INFO_PRINTF1(_L("Test full cache eviction"));
+
+	__UHEAP_MARK;
+	// Fill cache up using expected size of glyph using AddGlyph.
+	const TInt KMaxAtlasSizeInBytes = 1000;
+	CGlyphAtlasTestWrapper* atlas = NULL;
+	TRAPD(ret, atlas = CGlyphAtlasTestWrapper::NewL(KMaxAtlasSizeInBytes));
+	TESTNOERROR(ret);
+	if (KErrNone != ret)
+		{
+		return;
+		}
+	TOpenFontCharMetrics charMetrics;
+	TGlyphImageInfo imageInfo;
+	TSize bitmapSize;
+	const TUint8* bitmapData = NULL;
+	TInt glyphIndex = 0;
+	TBool atlasFull = EFalse;
+	CBitmapFont* bmFont = CTFbsFont::FontAddress(iFont);
+	// Fill up atlas by adding glyphs.
+	// Next glyph shold tip the atlas over the memory limit.
+	// Glyphs are added in ascending glyph code order.
+	// Leave at least one glyph so that we can guarantee that we can add one more unique glyph.
+	while (glyphIndex < KNumGlyphCodesLatin-1 && !atlasFull)
+		{
+		iFont->GetCharacterData(iGlyphCodesLatin[glyphIndex], charMetrics, bitmapData, bitmapSize);
+		TInt sizeInBytes = charMetrics.Height() * charMetrics.Width();
+		if (atlas->SizeInBytes() + sizeInBytes <= KMaxAtlasSizeInBytes)
+			{
+			CGlyphAtlas::TAddGlyphArgs args(bitmapData, iGlyphCodesLatin[glyphIndex++], charMetrics);
+			TESTNOERROR(atlas->AddGlyph(*bmFont, args, imageInfo));
+			}
+		else
+			{
+			atlasFull = ETrue;
+			}
+		}
+	TEST(atlasFull);
+
+	// check least recently used page contains the first glyph in glyph codes
+	TUint leastUsedGlyphCode = iGlyphCodesLatin[0];
+	TEST(atlas->LruPageContainsGlyph(leastUsedGlyphCode));
+
+	// To ensure that the test does not pass if a FIFO eviction policy occurs,
+	// get the least recently used glyph so that it is moved internally.
+	TESTNOERROR(atlas->GetGlyph(*bmFont, leastUsedGlyphCode, imageInfo));
+
+	// glyphIndex, bitmapData and charMetrics now current for next glyph which 
+	// will take the atlas over the cache limit.
+	CGlyphAtlas::TAddGlyphArgs args(bitmapData, iGlyphCodesLatin[glyphIndex], charMetrics);
+	TESTNOERROR(atlas->AddGlyph(*bmFont, args, imageInfo));
+
+	// check that searching for most recently added glyph is successful
+	TGlyphImageInfo newInfo;
+	TESTNOERROR(atlas->GetGlyph(*bmFont, iGlyphCodesLatin[glyphIndex], newInfo));
+
+	// check atlas size is still under the limit
+	TEST(atlas->SizeInBytes() <= KMaxAtlasSizeInBytes);
+
+	// check that the pages which were evicted contained the least used glyphs
+	// i.e. searching for these returns KErrNotFound
+	TInt err = KErrNotFound;
+	TInt index = 1;
+	for (; KErrNotFound == err && index <= glyphIndex; ++index)
+		{
+		err = atlas->GetGlyph(*bmFont, iGlyphCodesLatin[index], newInfo);
+		}
+	TESTNOERROR(err);
+	// first found glyph should be greater than glyph at index 1
+	TEST(index-1 > 1);
+	
+	// check that the remaining pages contained the least used glyphs
+	for (; index <= glyphIndex; ++index)
+		{
+		TESTNOERROR(atlas->GetGlyph(*bmFont, iGlyphCodesLatin[index], newInfo));
+		}
+
+	delete atlas;
+	__UHEAP_MARKEND;
+	}
+
+
+/**
+@SYMTestCaseID		GRAPHICS-FBSERV-0664
+@SYMTestPriority	High
+@SYMTestType		UT
+@SYMTestStatus		Implemented
+@SYMPREQ			PREQ2678
+
+@SYMTestCaseDesc
+	Shows that CGlyphAtlas::FontReleased() does actually delete all the glyphs 
+	associated with the released font and leaves glyphs associated with other 
+	fonts untouched.
+
+@SYMTestActions
+	i. Create a glyph atlas with no memory limit.
+	ii. Add glyphs for two different fonts to the atlas.
+	iii. Check all glyphs for both fonts were successfully added.
+	iv. Call CGlyphAtlas::ReleaseFont for one of the fonts.
+	v. Check that there are no glyphs associated with the released font.
+	vi. Call CGlyphAtlas::ReleaseFont for the remaining font.
+	vii Check that there are no glyphs associated with the released font and 
+		that the atlas is empty.
+	viii Delete the glyph atlas.
+	
+@SYMTestExpectedResults
+	After each font is released, there are no glyphs associated with that font 
+	left in the atlas.
+*/
+void CTGlyphAtlas::TestFontReleased()
+	{
+	INFO_PRINTF1(_L("Test behaviour of CGlyphAtlas::FontReleased()"));
+
+	__UHEAP_MARK;
+	CGlyphAtlasTestWrapper* atlas = NULL;
+	TRAPD(ret, atlas = CGlyphAtlasTestWrapper::NewL(KGlyphAtlasNoCacheLimit));
+	TESTNOERROR(ret);
+	if (KErrNone != ret)
+		{
+		return;
+		}
+	TOpenFontCharMetrics charMetrics;
+	TGlyphImageInfo imageInfo;
+	TSize bitmapSize;
+	const TUint8* bitmapData = NULL;
+	CBitmapFont* bmFont = CTFbsFont::FontAddress(iFont);
+	CBitmapFont* bmFont2 = CTFbsFont::FontAddress(iFont2);
+	for (TInt glyphIndex = 0; glyphIndex < KNumGlyphCodesLatin; ++glyphIndex)
+		{
+		iFont->GetCharacterData(iGlyphCodesLatin[glyphIndex], charMetrics, bitmapData, bitmapSize);
+		CGlyphAtlas::TAddGlyphArgs args(bitmapData, iGlyphCodesLatin[glyphIndex], charMetrics);
+		TESTNOERROR(atlas->AddGlyph(*bmFont, args, imageInfo));
+
+		iFont2->GetCharacterData(iGlyphCodesLatin[KNumGlyphCodesLatin-1-glyphIndex], charMetrics, bitmapData, bitmapSize);
+		CGlyphAtlas::TAddGlyphArgs args2(bitmapData, iGlyphCodesLatin[glyphIndex], charMetrics);
+		TESTNOERROR(atlas->AddGlyph(*bmFont2, args2, imageInfo));
+		}
+	// check there are font entries for these 2 fonts
+	TEST(2 == atlas->FontCount());
+
+	// check actual number of glyphs in atlas for each font is as expected
+	TEST(KNumGlyphCodesLatin == atlas->GlyphCountByFont(bmFont));
+	TEST(KNumGlyphCodesLatin == atlas->GlyphCountByFont(bmFont2));
+	TEST(2*KNumGlyphCodesLatin == atlas->GlyphCount());
+
+	// release one font and check number of glyphs in atlas for each font 
+	// is as expected
+	atlas->FontReleased(*bmFont);
+	TEST(1 == atlas->FontCount());
+	TEST(0 == atlas->GlyphCountByFont(bmFont));
+	TEST(KNumGlyphCodesLatin == atlas->GlyphCountByFont(bmFont2));
+	TEST(KNumGlyphCodesLatin == atlas->GlyphCount());
+
+	// release one font and check number of glyphs in atlas for each font 
+	// is as expected
+	atlas->FontReleased(*bmFont2);
+	TEST(0 == atlas->FontCount());
+	TEST(0 == atlas->GlyphCountByFont(bmFont));
+	TEST(0 == atlas->GlyphCountByFont(bmFont2));
+	TEST(0 == atlas->GlyphCount());
+
+	delete atlas;
+
+	__UHEAP_MARKEND;
+	}
+
+
+
+//--------------
+__CONSTRUCT_STEP__(GlyphAtlas)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/tglyphatlas.h	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,60 @@
+// Copyright (c) 2009-2010 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:
+//
+
+#ifndef TGLYPHATLAS_H
+#define TGLYPHATLAS_H
+
+#include "test/TGraphicsHarness.h"
+
+/**
+Test class for the glyph data extensions RFbsGlyphDataIterator and 
+RFbsGlyphMetricsArray. Positive and negative tests
+*/
+class CTGlyphAtlas : public CTGraphicsBase
+	{
+public:
+	CTGlyphAtlas(CTestStep* aStep);
+	~CTGlyphAtlas();
+protected:
+//from 	CTGraphicsBase
+	virtual void RunTestCaseL(TInt aCurTestCase);
+	void ConstructL();
+	
+private:
+	// Test Cases
+	void TestFullCache();
+	void TestFontReleased();
+	
+private:
+	RFbsSession* iFbs;
+	CFbsTypefaceStore* iTs;
+	TUint* iGlyphCodesLatin;
+	CFbsFont* iFont;
+	CFbsFont* iFont2;
+	};
+
+
+class CTGlyphAtlasStep : public CTGraphicsStep
+	{
+public:
+	CTGlyphAtlasStep();
+protected:	
+	//from CTGraphicsStep
+	virtual CTGraphicsBase* CreateTestL();
+	};
+
+_LIT(KTGlyphAtlasStep,"TGlyphAtlas");
+
+#endif /* TGLYPHATLAS_H */
--- a/fbs/fontandbitmapserver/tfbs/tipctest.CPP	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/tipctest.CPP	Fri Sep 24 16:14:28 2010 +0300
@@ -13,10 +13,10 @@
 // Description:
 //
 
-#include "fbsmessage.h"
 #include "../sfbs/UTILS.H"
 #include "tipctest.h"
 #include "fbsdefs.h"
+#include "fbsmessage.h"
 
 // Invalid parameters to be passed in SendCommand() calls.
 const TInt KInvalidParam1 = 963955448;
@@ -75,59 +75,6 @@
 	
 	}
 
-/**
-	@SYMTestCaseID
-	GRAPHICS-FBSERV-0603
-
-	@SYMTestCaseDesc
-	Tests the sending of commands to a FbsSession 
-	server thru Inter Process Communication. Sends
-	both valid and invalid commands.
-
-	@SYMTestActions
-	Commands sent to the server:
-	1. EFbsMessShutdown
-	2. EFbsMessFontHeightInTwips
-	3. EFbsMessFontHeightInTwips
-	4. EFbsMessFontHeightInPixels
-	5. EFbsMessFontHeightInPixels
-	6. EFbsMessAddFontStoreFile
-	7. EFbsMessAddFontStoreFile
-	8. EFbsMessInstallFontStoreFile
-	9. EFbsMessInstallFontStoreFile
-	10. EFbsMessInstallFontStoreFile
-	11. EFbsMessBitmapCreate
-	12. EFbsMessRasterize
-	13. EFbsMessFaceAttrib
-	14. EFbsMessHasCharacter
-	15. EFbsMessFontNameAlias
-	16. EFbsMessGetNearestFontToDesignHeightInTwips
-	17. EFbsMessGetNearestFontToMaxHeightInTwips
-	18. EFbsMessGetNearestFontToDesignHeightInPixels
-	19. EFbsMessGetNearestFontToMaxHeightInPixels
-	20. EFbsMessShapeText
-	21. EFbsMessShapeDelete
-	22. EFbsMessSetTwipsHeight
-	23. EFbsMessGetTwipsHeight	
-	@SYMTestExpectedResults
-    Test should pass
-
-    @SYMTestCaseID
-    TI18N-GDI-CIT-4086
-
-    @SYMTestCaseDesc
-    Test if FBS can handle invalid messages correctly
-    and panic the client as needed.
-
-    @SYMTestActions
-	24. EFbsMessGetFontTable
-	25. EFbsMessReleaseFontTable
-	26. EFbsMessGetGlyphOutline
-	27.EFbsMessReleaseGlyphOutline
-	
-	@SYMTestExpectedResults
-	Test should pass
-*/
 void CTIPCTest::RunTestCaseL(TInt aCurTestCase)
 	{
 	_LIT(KCaseNumber, "CaseNumber");
@@ -141,172 +88,254 @@
 		
 	switch(aCurTestCase)
 		{
+	/**
+		@SYMTestCaseID
+		GRAPHICS-FBSERV-0603
+
+		@SYMTestCaseDesc
+		Tests the sending of commands to a FbsSession 
+		server thru Inter Process Communication. Sends
+		both valid and invalid commands.
+
+		@SYMTestActions
+		Commands sent to the server:
+		1. EFbsMessShutdown
+		2. EFbsMessFontHeightInTwips
+		3. EFbsMessFontHeightInTwips
+		4. EFbsMessFontHeightInPixels
+		5. EFbsMessFontHeightInPixels
+		6. EFbsMessAddFontStoreFile
+		7. EFbsMessAddFontStoreFile
+		8. EFbsMessInstallFontStoreFile
+		9. EFbsMessInstallFontStoreFile
+		10. EFbsMessInstallFontStoreFile
+		11. EFbsMessBitmapCreate
+		12. EFbsMessRasterize
+		13. EFbsMessFaceAttrib
+		14. EFbsMessHasCharacter
+		15. EFbsMessFontNameAlias
+		16. EFbsMessGetNearestFontToDesignHeightInTwips
+		17. EFbsMessGetNearestFontToMaxHeightInTwips
+		18. EFbsMessGetNearestFontToDesignHeightInPixels
+		19. EFbsMessGetNearestFontToMaxHeightInPixels
+		20. EFbsMessShapeText
+		21. EFbsMessShapeDelete
+		22. EFbsMessSetTwipsHeight
+		23. EFbsMessGetTwipsHeight
+		
+		@SYMTestExpectedResults
+		Test should pass
+	*/
 	case 1:
-		INFO_PRINTF1(_L("Shutdown\r\n"));
+		INFO_PRINTF1(_L("Shutdown"));
 		iFbs->SendCommand(EFbsMessShutdown);
 		TestComplete();
 		break;
 	case 2:
-		INFO_PRINTF1(_L("Height in twips with negative typeface index\r\n"));
+		INFO_PRINTF1(_L("Height in twips with negative typeface index"));
 		iFbs->SendCommand(EFbsMessFontHeightInTwips, -1);	
 		TEST(EFalse); // Previous line should have paniced 
 		TestComplete();
 		break;	
 	case 3:
-		INFO_PRINTF1(_L("Height in twips with invalid size\r\n"));
+		INFO_PRINTF1(_L("Height in twips with invalid size"));
 		iClient.SendInvalidSize(EFbsMessFontHeightInTwips);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 4:
-		INFO_PRINTF1(_L("Height in pixels with negative typeface index\r\n"));
+		INFO_PRINTF1(_L("Height in pixels with negative typeface index"));
 		iFbs->SendCommand(EFbsMessFontHeightInPixels, -1);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 5:
-		INFO_PRINTF1(_L("Height in pixels with invalid size\r\n"));
+		INFO_PRINTF1(_L("Height in pixels with invalid size"));
 		iClient.SendInvalidSize(EFbsMessFontHeightInPixels);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 6:
-		INFO_PRINTF1(_L("Add font store file with negative length\r\n"));
+		INFO_PRINTF1(_L("Add font store file with negative length"));
 		iFbs->SendCommand(EFbsMessAddFontStoreFile, 0, -1);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 7:
-		INFO_PRINTF1(_L("Add font store file with huge length\r\n"));
+		INFO_PRINTF1(_L("Add font store file with huge length"));
 		iFbs->SendCommand(EFbsMessAddFontStoreFile, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 8:
-		INFO_PRINTF1(_L("Install font store file with negative length\r\n"));
+		INFO_PRINTF1(_L("Install font store file with negative length"));
 		iFbs->SendCommand(EFbsMessInstallFontStoreFile, 0, -1);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 9:
-		INFO_PRINTF1(_L("Install font store file with huge length\r\n"));
+		INFO_PRINTF1(_L("Install font store file with huge length"));
 		iFbs->SendCommand(EFbsMessInstallFontStoreFile, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 10:
-		INFO_PRINTF1(_L("Remove font store file with active references\r\n"));
+		INFO_PRINTF1(_L("Remove font store file with active references"));
 		iFbs->SendCommand(EFbsMessRemoveFontStoreFile, 11);
 		// With PDEF121246 (INC120690) fix in place, this test will always pass. Without the fix there will be a KERN 4 panic.
 		TEST(ETrue); 
 		TestComplete();
 		break;
 	case 11:
-		INFO_PRINTF1(_L("Bitmap create with invalid display mode\r\n"));
+		INFO_PRINTF1(_L("Bitmap create with invalid display mode"));
 		iClient.SendInvalidDisplayMode(EFbsMessBitmapCreate);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 12:
-		INFO_PRINTF1(_L("Rasterize with invalid bitmap handle\r\n"));
+		INFO_PRINTF1(_L("Rasterize with invalid bitmap handle"));
 		iFbs->SendCommand(EFbsMessRasterize, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 13:
-		INFO_PRINTF1(_L("Face Attribute with invalid bitmap handle\r\n"));
+		INFO_PRINTF1(_L("Face Attribute with invalid bitmap handle"));
 		iFbs->SendCommand(EFbsMessFaceAttrib, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 14:
-		INFO_PRINTF1(_L("Has Character with invalid bitmap handle\r\n"));
+		INFO_PRINTF1(_L("Has Character with invalid bitmap handle"));
 		iFbs->SendCommand(EFbsMessHasCharacter, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 15:
-		INFO_PRINTF1(_L("Name Alias with huge alias name length\r\n"));
+		INFO_PRINTF1(_L("Name Alias with huge alias name length"));
 		iFbs->SendCommand(EFbsMessFontNameAlias, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 16:
-		INFO_PRINTF1(_L("Get nearest font to design height in twips with invalid typeface name length\r\n"));
+		INFO_PRINTF1(_L("Get nearest font to design height in twips with invalid typeface name length"));
 		iClient.SendInvalidNameLength(EFbsMessGetNearestFontToDesignHeightInTwips);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 17:
-		INFO_PRINTF1(_L("Get nearest font to max height in twips with invalid typeface name length\r\n"));
+		INFO_PRINTF1(_L("Get nearest font to max height in twips with invalid typeface name length"));
 		iClient.SendInvalidNameLength(EFbsMessGetNearestFontToMaxHeightInTwips);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 18:
-		INFO_PRINTF1(_L("Get nearest font to design height in pixels with invalid typeface name length\r\n"));
+		INFO_PRINTF1(_L("Get nearest font to design height in pixels with invalid typeface name length"));
 		iClient.SendInvalidNameLength(EFbsMessGetNearestFontToDesignHeightInPixels);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 19:
-		INFO_PRINTF1(_L("Get nearest font to max height in pixels with invalid typeface name length\r\n"));
+		INFO_PRINTF1(_L("Get nearest font to max height in pixels with invalid typeface name length"));
 		iClient.SendInvalidNameLength(EFbsMessGetNearestFontToMaxHeightInPixels);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 20:
-		INFO_PRINTF1(_L("Shape text with invalid bitmap font handle\r\n"));
+		INFO_PRINTF1(_L("Shape text with invalid bitmap font handle"));
 		iFbs->SendCommand(EFbsMessShapeText, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 21:
-		INFO_PRINTF1(_L("Shape delete with invalid bitmap font handle\r\n"));
+		INFO_PRINTF1(_L("Shape delete with invalid bitmap font handle"));
 		iFbs->SendCommand(EFbsMessShapeDelete, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 22:
-		INFO_PRINTF1(_L("Set twips height with invalid font handle\r\n"));
+		INFO_PRINTF1(_L("Set twips height with invalid font handle"));
 		iFbs->SendCommand(EFbsMessSetTwipsHeight, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
 		TEST(EFalse);
 		TestComplete();
 		break;
 	case 23:
-		INFO_PRINTF1(_L("Get twips height with invalid font handle\r\n"));
-		((CTIPCTestStep*)iStep)->SetOverallTestStepID(_L("GRAPHICS-FBSERV-0603"));
-		((CTIPCTestStep*)iStep)->RecordTestResultL();
-		((CTIPCTestStep*)iStep)->CloseTMSGraphicsStep();
+		INFO_PRINTF1(_L("Get twips height with invalid font handle"));
 		iFbs->SendCommand(EFbsMessGetTwipsHeight, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
 		TEST(EFalse);
 		TestComplete();
 		break;	
 	case 24:
-		INFO_PRINTF1(_L("Get Font Table with wrong msg\r\n"));
-		iFbs->SendCommand(EFbsMessGetFontTable, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);   
-		TEST(EFalse); 
+		/**
+			@SYMTestCaseID	GRAPHICS-FBSERV-0630
+
+			@SYMTestCaseDesc
+			Tests that invalid font handle to EFbsMessGetGlyphs causes panic
+
+			@SYMTestExpectedResults
+			Client should panic with FBSERV -8
+		*/
+		INFO_PRINTF1(_L("Get glyphs from glyph atlas with invalid font handle"));
+		iFbs->SendCommand(EFbsMessGetGlyphs, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
+		TEST(EFalse);
 		TestComplete();
 		break;
 	case 25:
-		INFO_PRINTF1(_L("Release Font Table with wrong msg\r\n"));
-		iFbs->SendCommand(EFbsMessReleaseFontTable, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);   
-		TEST(EFalse); 
+		/**
+			@SYMTestCaseID	GRAPHICS-FBSERV-0670
+
+			@SYMTestCaseDesc
+			Tests that invalid font handle to EFbsMessGetGlyphMetrics causes panic
+
+			@SYMTestExpectedResults
+			Client should panic with FBSERV -8
+		*/
+		INFO_PRINTF1(_L("Get glyph metrics with invalid font handle"));
+		iFbs->SendCommand(EFbsMessGetGlyphMetrics, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
+		TEST(EFalse);
 		TestComplete();
-		break;    
+		break;
+	/**
+		@SYMTestCaseID
+		TI18N-GDI-CIT-4086
+
+		@SYMTestCaseDesc
+		Test if FBS can handle invalid messages correctly
+		and panic the client as needed.
+
+		@SYMTestActions
+		26. EFbsMessGetFontTable
+		27. EFbsMessReleaseFontTable
+		28. EFbsMessGetGlyphOutline
+		29. EFbsMessReleaseGlyphOutline
+	
+		@SYMTestExpectedResults
+		Test should pass
+	*/
 	case 26:
-		INFO_PRINTF1(_L("Get Glyph outline with wrong msg\r\n"));
-		iFbs->SendCommand(EFbsMessGetGlyphOutline,KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);   
+		INFO_PRINTF1(_L("Get Font Table with wrong msg"));
+		iFbs->SendCommand(EFbsMessGetFontTable, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
 		TEST(EFalse); 
 		TestComplete();
 		break;
 	case 27:
-		INFO_PRINTF1(_L("Release Glyph outline with wrong msg\r\n"));
-		iFbs->SendCommand(EFbsMessReleaseGlyphOutline, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);   
+		INFO_PRINTF1(_L("Release Font Table with wrong msg"));
+		iFbs->SendCommand(EFbsMessReleaseFontTable, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
 		TEST(EFalse); 
 		TestComplete();
 		break;
 	case 28:
+		INFO_PRINTF1(_L("Get Glyph outline with wrong msg"));
+		iFbs->SendCommand(EFbsMessGetGlyphOutline,KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
+		TEST(EFalse); 
+		TestComplete();
+		break;
+	case 29:
+		INFO_PRINTF1(_L("Release Glyph outline with wrong msg"));
+		iFbs->SendCommand(EFbsMessReleaseGlyphOutline, KInvalidParam1, KInvalidParam2, KInvalidParam3, KInvalidParam4);
+		TEST(EFalse); 
+		TestComplete();
+		break;
+	case 30:
 		TestComplete();
 		break;
 		}
--- a/fbs/fontandbitmapserver/tfbs/tipctest.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/tipctest.h	Fri Sep 24 16:14:28 2010 +0300
@@ -17,7 +17,7 @@
 #define __TIPCTest_H__
 
 #include <fbs.h>
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 
 class RIPCTestFbservClient : public RSessionBase
 	{
--- a/fbs/fontandbitmapserver/tfbs/trfile.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/trfile.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2005-2010 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"
@@ -20,7 +20,7 @@
 
 #include <fbs.h>
 #include <bitstd.h>
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 
 class CTFile : public CTGraphicsBase
 	{
--- a/fbs/fontandbitmapserver/tfbs/twdp.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/fbs/fontandbitmapserver/tfbs/twdp.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2008-2010 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"
@@ -17,7 +17,7 @@
 #define __TWDP_H__
 
 #include <fbs.h>
-#include "TGraphicsHarness.h"
+#include "test/TGraphicsHarness.h"
 
 class CTWDP : public CTGraphicsBase
 	{
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/traces/OstTraceDefinitions.h	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,7 @@
+#ifndef __OSTTRACEDEFINITIONS_H__
+#define __OSTTRACEDEFINITIONS_H__
+// OST_TRACE_COMPILER_IN_USE flag has been added by Trace Compiler
+// REMOVE BEFORE CHECK-IN TO VERSION CONTROL
+//#define OST_TRACE_COMPILER_IN_USE
+#include <opensystemtrace.h>
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/traces/fixed_id.definitions	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,18 @@
+#Fixed group and trace id definitions. If this file is removed, the identifiers are rebuilt.
+[GROUP]TRACE_NORMAL=0x86
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_ADDGLYPH=0x4
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_ADDGLYPH_END1=0x7
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_ADDGLYPH_END2=0x5
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_ADDGLYPH_END3=0x6
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_DELETELEASTRECENTLYUSEDPAGE=0xb
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_DELETELEASTRECENTLYUSEDPAGE_END=0xc
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_FONTRELEASED=0x8
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_FONTRELEASED_END2=0x9
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_FONTRELEASED_END3=0xa
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_GETGLYPH=0x1
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_GETGLYPH_END1=0x3
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_GETGLYPH_END2=0x2
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_INSTATEGPUMEMORY=0x16
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_INSTATEGPUMEMORY_EXIT=0x17
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_RELEASEGPUMEMORY=0x14
+[TRACE]TRACE_NORMAL[0x86]_CGLYPHATLAS_RELEASEGPUMEMORY_EXIT=0x15
--- a/graphicsdeviceinterface/bitgdi/sbit/FONTBMP.CPP	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicsdeviceinterface/bitgdi/sbit/FONTBMP.CPP	Fri Sep 24 16:14:28 2010 +0300
@@ -65,7 +65,9 @@
 EXPORT_C void CFbsBitGcFont::Reset()
 	{
 	if (!iCopy)
+		{
 		CFbsFont::Reset();
+		}
 	else
 		{
 		iAddressPointer = NULL;
--- a/graphicsdeviceinterface/bitgdi/sbit/MAIN.CPP	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicsdeviceinterface/bitgdi/sbit/MAIN.CPP	Fri Sep 24 16:14:28 2010 +0300
@@ -23,7 +23,6 @@
 #include <shapeinfo.h>
 #include "bitgcextradata.h"
 
-
 #define KDefaultShadowColor KRgbGray
 
 //CFbsBitGc streams - version numbers.
--- a/graphicsdeviceinterface/gdi/bwins/GDI2U.def	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicsdeviceinterface/gdi/bwins/GDI2U.def	Fri Sep 24 16:14:28 2010 +0300
@@ -301,20 +301,23 @@
 	??0RGlyphOutlineIterator@@QAE@XZ @ 300 NONAME ; RGlyphOutlineIterator::RGlyphOutlineIterator(void)
 	?Open@RGlyphOutlineIterator@@QAEHAAVCFont@@PBIHH@Z @ 301 NONAME ; int RGlyphOutlineIterator::Open(class CFont &, unsigned int const *, int, int)
 	??0RFontTable@@QAE@XZ @ 302 NONAME ; RFontTable::RFontTable(void)
-	?Image@RGlyphDataIterator@@QBEABVRSgImage@@XZ @ 303 NONAME ABSENT ; class RSgImage const & RGlyphDataIterator::Image(void) const
-	??0RGlyphMetricsArray@@QAE@XZ @ 304 NONAME ABSENT ; RGlyphMetricsArray::RGlyphMetricsArray(void)
-	?Count@RGlyphMetricsArray@@QBEHXZ @ 305 NONAME ABSENT ; int RGlyphMetricsArray::Count(void) const
-	?Metrics@RGlyphDataIterator@@QBEABVTOpenFontCharMetrics@@XZ @ 306 NONAME ABSENT ; class TOpenFontCharMetrics const & RGlyphDataIterator::Metrics(void) const
-	??0RGlyphDataIterator@@QAE@XZ @ 307 NONAME ABSENT ; RGlyphDataIterator::RGlyphDataIterator(void)
-	??ARGlyphMetricsArray@@QBEABVTOpenFontCharMetrics@@H@Z @ 308 NONAME ABSENT ; class TOpenFontCharMetrics const & RGlyphMetricsArray::operator[](int) const
-	?GlyphCode@RGlyphDataIterator@@QBEIXZ @ 309 NONAME ABSENT ; unsigned int RGlyphDataIterator::GlyphCode(void) const
-	?Rect@RGlyphDataIterator@@QBEABVTRect@@XZ @ 310 NONAME ABSENT ; class TRect const & RGlyphDataIterator::Rect(void) const
-	?Next@RGlyphDataIterator@@QAEHXZ @ 311 NONAME ABSENT ; int RGlyphDataIterator::Next(void)
-	?Close@RGlyphMetricsArray@@QAEXXZ @ 312 NONAME ABSENT ; void RGlyphMetricsArray::Close(void)
-	?Get@RGlyphMetricsArray@@QAEHAAVCFont@@PBIH@Z @ 313 NONAME ABSENT ; int RGlyphMetricsArray::Get(class CFont &, unsigned int const *, int)
-	?Close@RGlyphDataIterator@@QAEXXZ @ 314 NONAME ABSENT ; void RGlyphDataIterator::Close(void)
-	?Open@RGlyphDataIterator@@QAEHAAVCFont@@PBIH@Z @ 315 NONAME ABSENT ; int RGlyphDataIterator::Open(class CFont &, unsigned int const *, int)
+	?Image@RGlyphDataIterator@@QBEABVRSgImage@@XZ @ 303 NONAME ABSENT
+	??0RGlyphMetricsArray@@QAE@XZ @ 304 NONAME ABSENT
+	?Count@RGlyphMetricsArray@@QBEHXZ @ 305 NONAME ABSENT
+	?Metrics@RGlyphDataIterator@@QBEABVTOpenFontCharMetrics@@XZ @ 306 NONAME ABSENT
+	??0RGlyphDataIterator@@QAE@XZ @ 307 NONAME ABSENT
+	??ARGlyphMetricsArray@@QBEABVTOpenFontCharMetrics@@H@Z @ 308 NONAME ABSENT
+	?GlyphCode@RGlyphDataIterator@@QBEIXZ @ 309 NONAME ABSENT
+	?Rect@RGlyphDataIterator@@QBEABVTRect@@XZ @ 310 NONAME ABSENT
+	?Next@RGlyphDataIterator@@QAEHXZ @ 311 NONAME ABSENT
+	?Close@RGlyphMetricsArray@@QAEXXZ @ 312 NONAME ABSENT
+	?Get@RGlyphMetricsArray@@QAEHAAVCFont@@PBIH@Z @ 313 NONAME ABSENT
+	?Close@RGlyphDataIterator@@QAEXXZ @ 314 NONAME ABSENT
+	?Open@RGlyphDataIterator@@QAEHAAVCFont@@PBIH@Z @ 315 NONAME ABSENT
 	?SetName@TTypeface@@QAEXABVTDesC16@@@Z @ 316 NONAME ; void TTypeface::SetName(class TDesC16 const &)
 	?Name@TTypeface@@QBEABVTDesC16@@XZ @ 317 NONAME ; class TDesC16 const & TTypeface::Name(void) const
-	
+	?At@RHexTreeBase@@IBEPAXI@Z @ 318 NONAME ; void * RHexTreeBase::At(unsigned int) const
+	??0RHexTreeBase@@IAE@PAVRHeap@@@Z @ 319 NONAME ; RHexTreeBase::RHexTreeBase(class RHeap *)
+	?SetAt@RHexTreeBase@@IAEHIPAX@Z @ 320 NONAME ; int RHexTreeBase::SetAt(unsigned int, void *)
+	?ResetAndDestroy@RHexTreeBase@@QAEXXZ @ 321 NONAME ; void RHexTreeBase::ResetAndDestroy(void)
 
--- a/graphicsdeviceinterface/gdi/inc/GDI.H	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicsdeviceinterface/gdi/inc/GDI.H	Fri Sep 24 16:14:28 2010 +0300
@@ -141,9 +141,9 @@
 	EGdiPanic_OutOfText				= 2,
 	/** Internal failure. */
 	EGdiPanic_Invariant				= 3,
-	/** Reserved panic codes. Not to be used. */
-	EGdiPanic_Reserved1				= 4,
-	EGdiPanic_Reserved2				= 5,
+	/** Unused panic codes. Can be reused if needed. */
+	EGdiPanic_Unused1				= 4,
+	EGdiPanic_Unused2				= 5,
 	/** Setting a typeface name that is too long */
 	EGdiPanic_TypefaceNameOverflow	= 6,
 	};
--- a/graphicsdeviceinterface/gdi/inc/gdiconsts.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicsdeviceinterface/gdi/inc/gdiconsts.h	Fri Sep 24 16:14:28 2010 +0300
@@ -38,5 +38,4 @@
 const TUid KUidIsFbsBitmapGc = {0x10285BBE};
 
 
-
 #endif /* GDICONSTS_H */
--- a/graphicsdeviceinterface/gdi/inc/gdiplatapi.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicsdeviceinterface/gdi/inc/gdiplatapi.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1998-2010 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1998-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"
--- a/graphicsdeviceinterface/screendriver/sbit/Cdsb.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicsdeviceinterface/screendriver/sbit/Cdsb.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -348,9 +348,9 @@
 		case 24:
 		case 32:
 			iBitmapInfo.iPixelShift = 5;
-			iBitmapInfo.iDisplayMode = EColor16MAP;
+			iBitmapInfo.iDisplayMode = EColor16MA;
 #ifdef SYMBIAN_GRAPHICS_GCE
-			iPixelFormat = EUidPixelFormatARGB_8888_PRE;
+			iPixelFormat = EUidPixelFormatARGB_8888;
 			iBytesPerPixel = 4;
 #endif
 			break;
--- a/graphicsdeviceinterface/screendriver/sgeneric/scdraw.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicsdeviceinterface/screendriver/sgeneric/scdraw.h	Fri Sep 24 16:14:28 2010 +0300
@@ -63,7 +63,6 @@
 	void Update();
 	void Update(TRequestStatus& aStatus);
 
-	void Update(const TRegion& aRegion);
 	void UpdateRegion(const TRect& aRect);
 	void ResetUpdateRegion();
 	void NotifyWhenAvailable(TRequestStatus& aStatus);
--- a/graphicsdeviceinterface/screendriver/sgeneric/scdraw.inl	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicsdeviceinterface/screendriver/sgeneric/scdraw.inl	Fri Sep 24 16:14:28 2010 +0300
@@ -98,13 +98,30 @@
 
 template <class T> void CGenericScreenDevice<T>::Update(const TRegion& aRegion)
 	{
-	iHelper.Update(aRegion);
+    if(!aRegion.IsEmpty() && !aRegion.CheckError())
+        {
+        if (aRegion.Count()>KMaxUpdateRegionRectangles)
+            {
+            UpdateRegion(aRegion.BoundingRect());
+            }
+        else
+            {
+            TInt rcCnt = aRegion.Count();
+            for (TInt ii=0; ii < rcCnt; ++ii)
+                {  
+                UpdateRegion(aRegion[ii]);  //Applies deorientate (offset, scale, rotate)
+                }
+            }
+        }
+    Update();
 	}
 
 template <class T> void CGenericScreenDevice<T>::UpdateRegion(const TRect& aRect)
-	{
-	iHelper.UpdateRegion(aRect);
-	}
+    {
+    const TRect rect = CDrawXxxBppBitmap::DeOrientate(aRect);//rect - physical coordinates
+    
+    iHelper.UpdateRegion(rect);
+    }
 
 template <class T> TInt CGenericScreenDevice<T>::GetInterface(TInt aInterfaceId, TAny*& aInterface)
 	{
--- a/graphicsdeviceinterface/screendriver/sgeneric/scnew.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicsdeviceinterface/screendriver/sgeneric/scnew.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -276,7 +276,7 @@
 */
 EXPORT_C TDisplayMode CFbsDrawDevice::DisplayMode16M()
 	{
-	return EColor16MAP;
+	return EColor16MA;
 	}
 
 
@@ -372,24 +372,6 @@
 		}
 	}
 
-/**
-Implementation of corresponding function in CDrawDevice, utilizing a tracked
-update region. Adds the given region to the update region and updates the
-screen.
-@param aRegion	Additional region to be updated.
-*/
-void CScreenDeviceHelper::Update(const TRegion& aRegion)
-	{
-	if(!aRegion.IsEmpty() && !aRegion.CheckError())
-		{
-		TInt rcCnt = aRegion.Count();
-		for (TInt ii=0; ii < rcCnt; ++ii)
-			{
-			UpdateRegion(aRegion[ii]);
-			}
-		}
-	Update();
-	}
 
 /**
 Implementation of corresponding function in CDrawDevice, utilizing a tracked
--- a/graphicstest/graphicstestharness/automation/h4/tests_00b.txt	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/automation/h4/tests_00b.txt	Fri Sep 24 16:14:28 2010 +0300
@@ -20,4 +20,6 @@
 TESTEXECUTE, \logs\testexecute\fntstoretest_T_LinkedFontUpdateStage2.htm,	, z:\fntstoretest\fntstoretest_T_LinkedFontUpdateStage2.script, 600
 
 # PREQ1543 bitgdi
-TESTEXECUTE, \logs\testexecute\bitgdiTest_T_outlineandshadowfonts.htm,		, z:\bitgdiTest\bitgdiTest_T_outlineandshadowfonts.script,	2000
\ No newline at end of file
+TESTEXECUTE, \logs\testexecute\bitgdiTest_T_outlineandshadowfonts.htm,		, z:\bitgdiTest\bitgdiTest_T_outlineandshadowfonts.script,	2000
+
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdataoutlineshadow.htm,		, z:\fbstest\fbstest_t_glyphdataoutlineshadow.script,	600
--- a/graphicstest/graphicstestharness/automation/h4/tests_01.txt	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/automation/h4/tests_01.txt	Fri Sep 24 16:14:28 2010 +0300
@@ -32,6 +32,9 @@
 TESTEXECUTE, \logs\testexecute\fbstest_T_StreamIdCache.htm,				, z:\fbstest\fbstest_T_StreamIdCache.script, 800
 TESTEXECUTE, \logs\testexecute\fbstest_t_extendedbitmap.htm,			, z:\fbstest\fbstest_t_extendedbitmap.script, 1200
 TESTEXECUTE, \logs\testexecute\fbstest_t_fonttable.htm,			        , z:\fbstest\fbstest_t_fonttable.script, 800
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdata.htm,					, z:\fbstest\fbstest_t_glyphdata.script, 800
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdataoutlineshadow.htm,		, z:\fbstest\fbstest_t_glyphdataoutlineshadow.script, 800, ,z\ityperast_config.cmd install, z\ityperast_config.cmd uninstall
+
 
 # See also tests_95_hw00.txt
 # See also tests_95_hw02.txt
--- a/graphicstest/graphicstestharness/automation/h4/tests_01a.txt	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/automation/h4/tests_01a.txt	Fri Sep 24 16:14:28 2010 +0300
@@ -32,6 +32,8 @@
 TESTEXECUTE, \logs\testexecute\fbstest_T_StreamIdCache.htm,				, z:\fbstest\fbstest_T_StreamIdCache.script, 800
 TESTEXECUTE, \logs\testexecute\fbstest_t_extendedbitmap.htm,			, z:\fbstest\fbstest_t_extendedbitmap.script, 1200
 TESTEXECUTE, \logs\testexecute\fbstest_t_fonttable.htm,			        , z:\fbstest\fbstest_t_fonttable.script, 800
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdata.htm,					, z:\fbstest\fbstest_t_glyphdata.script, 800
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdataoutlineshadow.htm,		, z:\fbstest\fbstest_t_glyphdataoutlineshadow.script, 800, ,z\ityperast_config.cmd install, z\ityperast_config.cmd uninstall
 
 # See also tests_95_hw00.txt
 # See also tests_95_hw02.txt
--- a/graphicstest/graphicstestharness/automation/h6/tests_00b.txt	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/automation/h6/tests_00b.txt	Fri Sep 24 16:14:28 2010 +0300
@@ -21,3 +21,5 @@
 
 # PREQ1543 bitgdi
 TESTEXECUTE, \logs\testexecute\bitgdiTest_T_outlineandshadowfonts.htm,		, z:\bitgdiTest\bitgdiTest_T_outlineandshadowfonts.script,	2000
+
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdataoutlineshadow.htm,		, z:\fbstest\fbstest_t_glyphdataoutlineshadow.script,	600
--- a/graphicstest/graphicstestharness/automation/h6/tests_01.txt	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/automation/h6/tests_01.txt	Fri Sep 24 16:14:28 2010 +0300
@@ -33,6 +33,8 @@
 TESTEXECUTE, \logs\testexecute\fbstest_T_StreamIdCache.htm,				, z:\fbstest\fbstest_T_StreamIdCache.script, 800
 TESTEXECUTE, \logs\testexecute\fbstest_t_extendedbitmap.htm,			, z:\fbstest\fbstest_t_extendedbitmap.script, 1200
 TESTEXECUTE, \logs\testexecute\fbstest_t_fonttable.htm,			        , z:\fbstest\fbstest_t_fonttable.script, 800
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdata.htm,					, z:\fbstest\fbstest_t_glyphdata.script, 800
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdataoutlineshadow.htm,		, z:\fbstest\fbstest_t_glyphdataoutlineshadow.script, 800, ,z\ityperast_config.cmd install, z\ityperast_config.cmd uninstall
 
 # See also tests_95_hw00.txt
 # See also tests_95_hw02.txt
--- a/graphicstest/graphicstestharness/automation/h6/tests_01a.txt	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/automation/h6/tests_01a.txt	Fri Sep 24 16:14:28 2010 +0300
@@ -33,6 +33,8 @@
 TESTEXECUTE, \logs\testexecute\fbstest_T_StreamIdCache.htm,				, z:\fbstest\fbstest_T_StreamIdCache.script, 800
 TESTEXECUTE, \logs\testexecute\fbstest_t_extendedbitmap.htm,			, z:\fbstest\fbstest_t_extendedbitmap.script, 1200
 TESTEXECUTE, \logs\testexecute\fbstest_t_fonttable.htm,			        , z:\fbstest\fbstest_t_fonttable.script, 800
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdata.htm,					, z:\fbstest\fbstest_t_glyphdata.script, 800
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdataoutlineshadow.htm,		, z:\fbstest\fbstest_t_glyphdataoutlineshadow.script, 800, ,z\ityperast_config.cmd install, z\ityperast_config.cmd uninstall
 
 # See also tests_95_hw00.txt
 # See also tests_95_hw02.txt
--- a/graphicstest/graphicstestharness/automation/ne1/tests_01.txt	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/automation/ne1/tests_01.txt	Fri Sep 24 16:14:28 2010 +0300
@@ -32,6 +32,8 @@
 TESTEXECUTE, \logs\testexecute\fbstest_T_StreamIdCache.htm,				, z:\fbstest\fbstest_T_StreamIdCache.script, 800
 TESTEXECUTE, \logs\testexecute\fbstest_t_extendedbitmap.htm,			, z:\fbstest\fbstest_t_extendedbitmap.script, 1200
 TESTEXECUTE, \logs\testexecute\fbstest_t_fonttable.htm,			        , z:\fbstest\fbstest_t_fonttable.script, 800
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdata.htm,					, z:\fbstest\fbstest_t_glyphdata.script, 800
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdataoutlineshadow.htm,		, z:\fbstest\fbstest_t_glyphdataoutlineshadow.script, 800, ,z\ityperast_config.cmd install, z\ityperast_config.cmd uninstall
 
 # See also tests_95_hw00.txt
 # See also tests_95_hw02.txt
--- a/graphicstest/graphicstestharness/automation/ne1/tests_01a.txt	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/automation/ne1/tests_01a.txt	Fri Sep 24 16:14:28 2010 +0300
@@ -32,6 +32,8 @@
 TESTEXECUTE, \logs\testexecute\fbstest_T_StreamIdCache.htm,				, z:\fbstest\fbstest_T_StreamIdCache.script, 800
 TESTEXECUTE, \logs\testexecute\fbstest_t_extendedbitmap.htm,			, z:\fbstest\fbstest_t_extendedbitmap.script, 1200
 TESTEXECUTE, \logs\testexecute\fbstest_t_fonttable.htm,			        , z:\fbstest\fbstest_t_fonttable.script, 800
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdata.htm,					, z:\fbstest\fbstest_t_glyphdata.script, 800
+TESTEXECUTE, \logs\testexecute\fbstest_t_glyphdataoutlineshadow.htm,		, z:\fbstest\fbstest_t_glyphdataoutlineshadow.script, 800, ,z\ityperast_config.cmd install, z\ityperast_config.cmd uninstall
 
 # See also tests_95_hw00.txt
 # See also tests_95_hw02.txt
--- a/graphicstest/graphicstestharness/automation/winscw/tests.txt	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/automation/winscw/tests.txt	Fri Sep 24 16:14:28 2010 +0300
@@ -155,6 +155,8 @@
 TESTEXECUTE, C:\logs\testexecute\fbstest_T_Secure.htm,					, z:\fbstest\fbstest_T_Secure.script, 600
 TESTEXECUTE, C:\logs\testexecute\fbstest_T_StreamIdCache.htm,			, z:\fbstest\fbstest_T_StreamIdCache.script, 600
 TESTEXECUTE, C:\logs\testexecute\fbstest_T_FontTable.htm,			, z:\fbstest\fbstest_T_FontTable.script, 600
+TESTEXECUTE, C:\logs\testexecute\fbstest_t_glyphdata.htm,			, z:\fbstest\fbstest_t_glyphdata.script, 600, ,z\ityperast_config.cmd install, z\ityperast_config.cmd uninstall
+TESTEXECUTE, C:\logs\testexecute\fbstest_t_glyphdataoutlineshadow.htm,		, z:\fbstest\fbstest_t_glyphdataoutlineshadow.script, 600, ,z\ityperast_config.cmd install, z\ityperast_config.cmd uninstall
 
 # without extended bitmap example rasterizer
 TESTEXECUTE, C:\logs\testexecute\fbstest_t_extendedbitmap.htm,			, z:\fbstest\fbstest_t_extendedbitmap.script,		1200
--- a/graphicstest/graphicstestharness/bwins/tprofileru.def	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/bwins/tprofileru.def	Fri Sep 24 16:14:28 2010 +0300
@@ -23,4 +23,4 @@
 	?SetStoreResultInTimingOrder@CTProfiler@@QAEXH@Z @ 22 NONAME ; void CTProfiler::SetStoreResultInTimingOrder(int)
 	?ShowResultArrayInTimingOrder@CTProfiler@@QAEXXZ @ 23 NONAME ; void CTProfiler::ShowResultArrayInTimingOrder(void)
 	?SqlInsert@CTProfiler@@QAEXPBVTDesC16@@00J@Z @ 24 NONAME ; void CTProfiler::SqlInsert(class TDesC16 const *, class TDesC16 const *, class TDesC16 const *, long)
-
+	?ResultsAnalysisGlyphRate@CTProfiler@@QAEXABVTDesC16@@HHHHH@Z @ 25 NONAME ; void CTProfiler::ResultsAnalysisGlyphRate(class TDesC16 const &, int, int, int, int, int)
--- a/graphicstest/graphicstestharness/eabi/tprofileru.def	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/eabi/tprofileru.def	Fri Sep 24 16:14:28 2010 +0300
@@ -27,4 +27,4 @@
 	_ZN10CTProfiler27SetStoreResultInTimingOrderEi @ 26 NONAME
 	_ZN10CTProfiler28ShowResultArrayInTimingOrderEv @ 27 NONAME
 	_ZN10CTProfiler9SqlInsertEPK7TDesC16S2_S2_l @ 28 NONAME
-
+	_ZN10CTProfiler24ResultsAnalysisGlyphRateERK7TDesC16iiiii @ 29 NONAME
--- a/graphicstest/graphicstestharness/inc/TGraphicsHarness.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/inc/TGraphicsHarness.h	Fri Sep 24 16:14:28 2010 +0300
@@ -122,7 +122,17 @@
 CTGraphicsBase* CT##a##Step::CreateTestL() \
 	{ \
 	return new (ELeave) CT##a (this); \
-	} 
+	}
+
+// Macros to automatically test error condition and report when test fails.
+// Essentially same as TESTE(a,b) MACRO that CTestStep uses, except error to
+// check is also error that is reported.
+#define TESTNOERROR(a) \
+	{\
+	TInt b = a;\
+	TBool c = (b == KErrNone);\
+	testBooleanTrueWithErrorCode((c), (b), (TText8*)__FILE__, __LINE__);\
+	}
 	
 inline void CTGraphicsBase::testBooleanTrue(TBool aCondition, const TText8* aFile, TInt aLine) 
 	{
--- a/graphicstest/graphicstestharness/inc/tprofiler.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/inc/tprofiler.h	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2008-2010 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"
@@ -69,7 +69,7 @@
 	IMPORT_C void ShowResultArrayInTimingOrder();
 	IMPORT_C void SetStoreResultInTimingOrder(TBool aStoreResultInTimingOrder);
 	IMPORT_C void SqlInsert(const TDesC* aTestName, const TDesC* aTestAttribute, const TDesC* aTestUnit, TInt32 aTestResultValue);
-
+	IMPORT_C void ResultsAnalysisGlyphRate(const TDesC & aTestName, TInt aRotation, TInt aSrcScreenMode, TInt aDstScreenMode, TInt aIters, TInt aNumPixels);
 
 private:
     CTProfiler(CTestStep& aTestStep);
--- a/graphicstest/graphicstestharness/src/tprofiler.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/graphicstestharness/src/tprofiler.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -555,3 +555,27 @@
     {
     iStoreResultInTimingOrder = aStoreResultInTimingOrder;
     }
+
+/**
+Reports analysis results for glyph rates
+
+@param aTestName is the name of the test case
+@param aRotation is the screen rotation being used in the test
+@param aSrcScreenMode is the source screen mode being used, 
+i.e. for bitmap display conversion the source and destinations bitmaps maybe different
+@param aDstScreenMode is the destination screen mode (usually the display screen mode)
+@param aIters is the number of iterations used in the test
+@param aNumGlyphs is the number of glyphs used per iteration
+*/
+
+EXPORT_C void CTProfiler::ResultsAnalysisGlyphRate(const TDesC & aTestName, TInt aRotation, TInt aSrcScreenMode, TInt aDstScreenMode, TInt aIters, TInt aNumGlyphsPerIteration)
+    {
+    PROFILER_TEST(iResultsInitalised);
+
+    TReal time = (iResults.Count() > 0) ? (TReal)iResults[0] / 1000000 : 0;
+    TInt32 glyphRate = aNumGlyphsPerIteration*aIters/time;
+    PROFILER_INFO_PRINTF7(_L("TID:   %S  Rot:    %i  SrcMode:    %i  DestMode:   %i  Iters: %i   TrimmedMean:    %i  glyphs/second"), &aTestName, aRotation, aSrcScreenMode, aDstScreenMode, aIters, glyphRate);
+    PROFILER_INFO_PRINTF3(_L("Max:   %i  Min:    %i  "), TimeMax(), TimeMin());
+    iResultsInitalised = EFalse;
+  }
+
--- a/graphicstest/uibench/group/bld.inf	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/uibench/group/bld.inf	Fri Sep 24 16:14:28 2010 +0300
@@ -29,6 +29,7 @@
 
 ../scripts/te_uibench_gce.script		z:/uibench/te_uibench_gce.script
 ../scripts/te_uibench_gce.ini			z:/uibench/te_uibench_gce.ini
+
 ../scripts/mysql.pm						z:/uibench/mysql.pm
 ../scripts/uploadsqlfromtestrun.pl		z:/uibench/uploadsqlfromtestrun.pl
 ../scripts/te_uibench_legacy.bat		z:/uibench/te_uibench_legacy.bat
--- a/graphicstest/uibench/group/te_uibench.iby	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/uibench/group/te_uibench.iby	Fri Sep 24 16:14:28 2010 +0300
@@ -19,6 +19,11 @@
 #include <internaltestfonts.iby>
 #include <testexecute.iby>
 #include <graphics_tprofiler.iby>
+
+REM egl and openvg needed for tfbsglyphdata tests
+#include <egl.iby>
+#include <openvg.iby>
+
 #ifndef SMP
 // MCL profiler is not built for SMP
 #include <profiler.iby>
@@ -26,7 +31,6 @@
 #ifdef SYMBIAN_GRAPHICS_USE_GCE
 #include <directgdi.iby>
 #include <directgdiadapter.iby>
-#include <t_halattprovider.iby>
 #endif
 
 file=ABI_DIR\DEBUG_DIR\te_uibench.exe	System\bin\te_uibench.exe
@@ -41,7 +45,6 @@
 #endif
 data=DATAZ_\uibench\te_uibench.ini	uibench\te_uibench.ini
 
-
 data=DATAZ_\uibench\te_uibench_gdi.ini	uibench\te_uibench_gdi.ini
 data=DATAZ_\uibench\te_uibench_gdi.script uibench\te_uibench_gdi.script
 
--- a/graphicstest/uibench/group/te_uibench.mmp	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/uibench/group/te_uibench.mmp	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2005-2010 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"
@@ -42,6 +42,7 @@
 SOURCE  ttranslucent.cpp
 SOURCE	tspriteperf.cpp
 SOURCE	textendedbitmap.cpp
+SOURCE  tfbsglyphdata.cpp
 
 USERINCLUDE   ../src
 USERINCLUDE   ../../../fbs/fontandbitmapserver/inc
@@ -66,6 +67,11 @@
 LIBRARY		estor.lib
 LIBRARY	    	tgraphicsharness.lib
 LIBRARY	    	tprofiler.lib
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+LIBRARY		sgresource.lib
+LIBRARY		libEGL.lib
+LIBRARY		libOpenVG.lib
+#endif
 
 START BITMAP	16x16icon.mbm
 TARGETPATH		/system/data/
--- a/graphicstest/uibench/group/te_uibench_gce.mmp	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/uibench/group/te_uibench_gce.mmp	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2005-2010 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"
@@ -33,7 +33,6 @@
 SOURCE  tflipframerate.cpp
 
 USERINCLUDE   ../src
-USERINCLUDE   ../../../fbs/fontandbitmapserver/inc
 
 //system includes
 OS_LAYER_SYSTEMINCLUDE_SYMBIAN
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicstest/uibench/group/te_uibench_helium.pkg	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,38 @@
+; Copyright (c) 2010 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: 
+;
+;File: bitgdi.pkg;
+;
+;*Languages
+&EN
+;
+;*Standard SIS file header. This section specifies the package name,
+;application UID, and version/build numbers. Add the package TYPE here if needed.
+#{"UIBench"},(0x101FB3E8),1,0,1;
+;
+
+;*Unique (Non-Localized) Vendor name
+;This is used in combination with signing to prevent the unauthroized
+;upgrade of a a package by someone other than the rightful vendor.
+:"Nokia"
+
+;*Localized Vendor Name
+;This specifies the localized vendor name(s) corresponding to language(s).
+%{"Nokia Test EN"}
+
+;*Files To Copy...<src> <destination>
+
+"\epoc32\data\z\uibench\te_uibench.script"-"c:\uibench\te_uibench.script"
+"\epoc32\data\z\uibench\te_uibenchoutlineshadow.script"-"c:\uibench\te_uibenchoutlineshadow.script"
+
--- a/graphicstest/uibench/s60/group/te_uibench_s60.mmp	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/uibench/s60/group/te_uibench_s60.mmp	Fri Sep 24 16:14:28 2010 +0300
@@ -121,7 +121,7 @@
 LIBRARY     libGLESv1_CM.lib
 LIBRARY	    libopenvgu.lib
 LIBRARY	    libopenvg.lib
-LIBRARY     egltesthybrid.lib
+// this shouldn't be needed LIBRARY     egltesthybrid.lib
 LIBRARY     surfacemanager.lib
 LIBRARY     tgraphicsharness.lib
 LIBRARY     tprofiler.lib
Binary file graphicstest/uibench/scripts/te_uibench.ini has changed
--- a/graphicstest/uibench/scripts/te_uibench.script	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/uibench/scripts/te_uibench.script	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2005-2010 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"
@@ -46,6 +46,7 @@
 RUN_TEST_STEP 1000 te_uibench ttranslucent z:\uibench\te_uibench.ini
 RUN_TEST_STEP 200 te_uibench tspriteperf z:\uibench\te_uibench.ini
 RUN_TEST_STEP 1000 te_uibench textendedbitmap z:\uibench\te_uibench.ini
+RUN_TEST_STEP 2000 te_uibench tfbsglyphdata z:\uibench\te_uibench.ini
 
 // Performance tests Script  for Hindi text rendering
 RUN_SCRIPT z:\uibench\te_uibench_gdi.script
Binary file graphicstest/uibench/scripts/te_uibench_gce.ini has changed
--- a/graphicstest/uibench/scripts/te_uibench_gce.script	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/uibench/scripts/te_uibench_gce.script	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2005-2010 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"
@@ -47,6 +47,7 @@
 RUN_TEST_STEP 1000 te_uibench ttranslucent z:\uibench\te_uibench.ini
 RUN_TEST_STEP 200 te_uibench tspriteperf z:\uibench\te_uibench.ini
 RUN_TEST_STEP 1000 te_uibench textendedbitmap z:\uibench\te_uibench.ini
+RUN_TEST_STEP 2000 te_uibench tfbsglyphdata z:\uibench\te_uibench.ini
 
 // Performance tests Script  for Hindi text rendering
 RUN_SCRIPT z:\uibench\te_uibench_gdi.script
@@ -64,4 +65,5 @@
 RUN_TEST_STEP 1000 te_uibench_gce teventhandlingperf z:\uibench\te_uibench_gce.ini
 RUN_TEST_STEP 20000 te_uibench_gce tflipframerate z:\uibench\te_uibench_gce.ini
 
+
 PRINT Complete_te_uibench_gce_Tests
--- a/graphicstest/uibench/src/te_graphicsperformanceSuiteDefs.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/uibench/src/te_graphicsperformanceSuiteDefs.h	Fri Sep 24 16:14:28 2010 +0300
@@ -54,6 +54,17 @@
 	testBooleanTrueWithErrorCodeL((c), (b), (TText8*)__FILE__, __LINE__);\
 	}
 
+// Redefine TEST/TESTE as TEST1/TESTE1 so that all errors are logged, not
+// just the first error.
+#ifdef TEST
+#undef TEST
+#define TEST(a) TEST1(a, ETrue)
+#endif // TEST
+
+#ifdef TESTE
+#undef TESTE
+#define TESTE(a, b) TESTE1(a, b, ETrue)
+#endif // TESTE
 
 #ifdef _USE_PROFILER
 	#define __PROFILERMEMBERS RProcess iProcess; TInt iPErr; RFs iFSession; TBuf<256> iProfLog; TBuf<256> iProfLoE; CFileMan* iFileMan; 
--- a/graphicstest/uibench/src/te_graphicsperformanceSuiteServer.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/uibench/src/te_graphicsperformanceSuiteServer.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2005-2010 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"
@@ -40,6 +40,7 @@
 #include "ttranslucent.h"
 #include "tspriteperf.h"
 #include "textendedbitmap.h"
+#include "tfbsglyphdata.h"
 
 /**
 Same code for Secure and non-secure variants
@@ -158,5 +159,7 @@
 		testStep = new CTSpritePerf();
 	else if(aStepName == KTExtendedBitmap)
 		testStep = new CTExtendedBitmap();
+	else if(aStepName == KTFbsGlyphData)
+		testStep = new CTFbsGlyphData();
 	return testStep;
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicstest/uibench/src/tfbsglyphdata.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,1003 @@
+// Copyright (c) 2009-2010 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:
+//
+
+/**
+ @file
+ @test
+ @internalComponent - Internal Symbian test code 
+*/
+
+#include <graphics/fbsglyphdataiterator.h>
+#include <graphics/fbsglyphmetricsarray.h>
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+#include <sgresource/sgimage.h>
+#include <egl/egl.h>
+#include <vg/openvg.h>
+typedef EGLBoolean (*TvgCreateEGLImageTargetKHRTypefPtr) (VGeglImageKHR image);
+#endif
+#include "tfbsglyphdata.h"
+
+// When defined Hindi language tests are not run. 
+#define UIBENCH_NO_HINDI
+
+// Size of EGLSurface used for rendering to, in pixels.
+const TSize KEglTargetSize(512, 512);
+
+CTFbsGlyphData::CTFbsGlyphData()
+	{
+	SetTestStepName(KTFbsGlyphData);
+	}
+
+CTFbsGlyphData::~CTFbsGlyphData()
+	{
+	}
+
+TVerdict CTFbsGlyphData::doTestStepPreambleL()
+    {
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+    User::LeaveIfError(iFbs.Connect());
+	User::LeaveIfError(iSgDriver.Open());
+#endif
+    return CTe_graphicsperformanceSuiteStepBase::doTestStepPreambleL();
+    }
+
+TVerdict CTFbsGlyphData::doTestStepPostambleL()
+    {
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+    iSgDriver.Close();
+    iFbs.Disconnect();
+#endif
+    return CTe_graphicsperformanceSuiteStepBase::doTestStepPostambleL();
+    }
+
+TVerdict CTFbsGlyphData::doTestStepL()
+	{
+#ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+    INFO_PRINTF1(_L("CTFbsGlyphData can only be run with SgImage 'Lite'"));
+    return TestStepResult();
+#else
+	SetTestStepID(_L("GRAPHICS-UI-BENCH-0178"));
+	GlyphMetricsArrayL(ETestLanguageLatin, ETrue, 1000);
+	RecordTestResultL();
+
+	SetTestStepID(_L("GRAPHICS-UI-BENCH-0179"));
+	GlyphMetricsArrayL(ETestLanguageLatin, EFalse, 50000);
+	RecordTestResultL();
+	
+#ifndef UIBENCH_NO_HINDI
+    // Tests 180 and 181 require a CMap table in order to convert CharacterCodes to GlyphCodes.
+	SetTestStepID(_L("GRAPHICS-UI-BENCH-0180"));
+	GlyphMetricsArrayL(ETestLanguageHindi, ETrue, 25);
+	RecordTestResultL();
+	
+	SetTestStepID(_L("GRAPHICS-UI-BENCH-0181"));
+	GlyphMetricsArrayL(ETestLanguageHindi, EFalse, 50000);
+	RecordTestResultL();
+#endif
+	
+	SetTestStepID(_L("GRAPHICS-UI-BENCH-0182"));
+	GlyphMetricsQuerySingleGlyphL();
+	RecordTestResultL();
+	
+	SetTestStepID(_L("GRAPHICS-UI-BENCH-0183"));
+	GlyphDataIteratorOpenL(ETestLanguageLatin, ETrue, 50);
+	RecordTestResultL();
+
+	SetTestStepID(_L("GRAPHICS-UI-BENCH-0184"));
+	GlyphDataIteratorOpenL(ETestLanguageLatin, EFalse, 500);
+	RecordTestResultL();
+	
+#ifndef UIBENCH_NO_HINDI
+    // Tests 185 and 186 require a CMap table in order to convert CharacterCodes to GlyphCodes.
+	SetTestStepID(_L("GRAPHICS-UI-BENCH-0185"));
+	GlyphDataIteratorOpenL(ETestLanguageHindi, ETrue, 10);
+	RecordTestResultL();
+	
+	SetTestStepID(_L("GRAPHICS-UI-BENCH-0186"));
+	GlyphDataIteratorOpenL(ETestLanguageHindi, EFalse, 5000);
+	RecordTestResultL();
+#endif	
+	
+	SetTestStepID(_L("GRAPHICS-UI-BENCH-0187"));
+	GlyphDataIteratorOpenSingleFontL();
+	RecordTestResultL();
+	
+	SetTestStepID(_L("GRAPHICS-UI-BENCH-0188"));
+	GlyphMetricsQueryUnrasterizedL();
+	RecordTestResultL();
+	
+	SetTestStepID(_L("GRAPHICS-UI-BENCH-0189"));
+	GlyphMetricsQueryPreRasterizedL();
+	RecordTestResultL();
+	
+	SetTestStepID(_L("GRAPHICS-UI-BENCH-0190"));
+	GlyphRenderingL();
+	RecordTestResultL();
+
+	return TestStepResult();
+#endif
+    }
+
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+/**
+@SYMTestCaseID GRAPHICS-UI-BENCH-0178...0181
+
+@SYMTestType UT
+
+@SYMPREQ PREQ2678
+
+@SYMTestCaseDesc 
+Measures the performance of calling RFbsGlyphMetricsArray::Get() with different sample data.
+The sample data can be a single word, or a very long array of glyphs, in latin or non-latin
+alphabets. At each repetition a different font is used, cycled over nine fonts, to reduce the
+effect of having cached glyphs.
+
+@SYMTestActions
+i. Create some sample fonts to cycle through. 
+ii. Load sample data from config file, specified by aSampleDataKey.
+iii. Create RFbsGlyphMetricsArray, open on sample data.
+iv. For each repetition, call RFbsGlyphMetricsArray::Get(), adjusting font at each repetition.
+v. Measure time from from first to last repetition.
+
+@param aLanguage The language this test will use.
+@param aLongData If ETrue, tells the test to use the long sample data string for the test, EFalse
+	will make the test use the short string data.
+@param aReps The number of times to repeat the test.
+*/
+void CTFbsGlyphData::GlyphMetricsArrayL(TTestLanguage aLanguage, TBool aLongData, TInt aReps)
+	{
+	TBuf<128> KTestName;
+	TPtrC KTestVariant = ConfigKeyNameL(aLanguage, aLongData);
+	KTestName.Format(_L("GlyphMetricsArray %S"), &KTestVariant);
+	
+	// Create some test fonts using the font factory.
+	CTFontFactory* fontFactory = CTFontFactory::NewLC();
+	fontFactory->CreateFontsL(aLanguage, 9);
+
+	// Load the sample string data from the config file.
+	TInt numGlyphCodes = 0;
+	TUint* glyphCodes;
+	LoadConfigSampleDataL(aLanguage, aLongData, glyphCodes, numGlyphCodes);
+
+	// Run the test.
+	TInt err = KErrNone;
+	RFbsGlyphMetricsArray array;
+	CleanupClosePushL(array);
+	iProfiler->InitResults();
+	for (TInt rep = aReps; (rep != 0) && (err == KErrNone); --rep)
+		{
+		err = array.Get(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
+		}
+	iProfiler->MarkResultSetL();
+	TESTE(err == KErrNone, err);
+	iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, aReps, numGlyphCodes);
+	
+	CleanupStack::PopAndDestroy(2); // array, fontFactory
+	delete [] glyphCodes;
+	}
+
+/**
+@SYMTestCaseID GRAPHICS-UI-BENCH-0182
+
+@SYMTestType UT
+
+@SYMPREQ PREQ2678
+
+@SYMTestCaseDesc 
+Measures the performance of calling RFbsGlyphDataIterator::Get() with a single glyph,
+versus CFont::GetCharacterData(). Using a single glyph code is a very common use case.
+The glyph and the font is changed at each iteration.
+
+@SYMTestActions
+i. Create some sample fonts to cycle through. 
+ii. Create RFbsGlyphMetricsArray.
+iii. For each repetition, call RFbsGlyphMetricsArray::Get(), adjusting the glyph at 
+	each iteration.
+iv. Measure time from from first to last iteration.
+v. Repeat steps iii. and iv. with CFont::GetCharacterData().
+*/
+void CTFbsGlyphData::GlyphMetricsQuerySingleGlyphL()
+	{
+	_LIT(KTestName, "GlyphMetricsQuerySingleGlyph");
+	const TInt KNumIterations = 50000;
+	TInt err = KErrNone;
+	TBuf<128> KTestNameVariant;
+
+	// Create some test fonts using the font factory.
+	CTFontFactory* fontFactory = CTFontFactory::NewLC();
+	
+	// Run the test for RFbsGlyphMetricsArray, with a different character 
+	// and font for each iteration.
+	KTestNameVariant.Format(_L("%S RFbsGlyphMetricsArray"), &KTestName);
+	fontFactory->CreateFontsL(ETestLanguageLatin, 9);
+	RFbsGlyphMetricsArray array;
+	CleanupClosePushL(array);
+	iProfiler->InitResults();
+	for (TInt rep = KNumIterations; rep != 0 && (err == KErrNone); --rep)
+		{
+		const TUint KGlyphCode = 32 + (rep % 96);
+		err = array.Get(*(fontFactory->NextFont()), &KGlyphCode, 1);
+		}
+	iProfiler->MarkResultSetL();
+	TESTE(err == KErrNone, err);
+	CleanupStack::PopAndDestroy(1); // array
+	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, 1);
+	fontFactory->ReleaseFonts();
+	
+	// Run the test for GetCharacterData(), with a different character
+	// and font for each iteration.
+	KTestNameVariant.Format(_L("%S GetCharacterData"), &KTestName);
+	fontFactory->CreateFontsL(ETestLanguageLatin, 9);
+	TOpenFontCharMetrics metrics;
+	const TUint8* bitmapData = NULL;
+	TSize bitmapSize;
+	iProfiler->InitResults();
+	for (TInt rep = KNumIterations; rep != 0; --rep)
+		{
+		const TUint KGlyphCode = 32 + (rep % 96);
+		fontFactory->NextFont()->GetCharacterData(KGlyphCode, metrics, bitmapData, bitmapSize);
+		}
+	iProfiler->MarkResultSetL();
+	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, 1);
+	
+	CleanupStack::PopAndDestroy(1); // fontFactory
+	}
+
+/**
+@SYMTestCaseID GRAPHICS-UI-BENCH-0183...0186
+
+@SYMTestType UT
+
+@SYMPREQ PREQ2678
+
+@SYMTestCaseDesc 
+Measures the performance of calling RFbsGlyphDataIterator::Open() with different 
+sample data, and iterating through the data with RFbsGlyphDataIterator::Next(). 
+The sample data can be a single word, or a very long array of glyphs,
+in various languages. At each repetition a different font is used, cycled
+over nine fonts.
+
+@SYMTestActions
+i. Create some sample fonts to cycle through. 
+ii. Create RFbsGlyphDataIterator.
+iii. For each repetition, call RFbsGlyphDataIterator::Open(), adjusting the glyph at each 
+	iteration. The font is changed at each repetition.
+iv. Measure time from from first to last repetition.
+
+@param aLanguage The language this test will use.
+@param aLongData If ETrue, tells the test to use the long sample data string for the test, EFalse
+	will make the test use the short string data.
+@param aReps The number of times to repeat the test.
+ */
+void CTFbsGlyphData::GlyphDataIteratorOpenL(TTestLanguage aLanguage, TBool aLongData, TInt aReps)
+	{
+	TBuf<128> KTestName;
+	TPtrC KTestVariant = ConfigKeyNameL(aLanguage, aLongData);
+	KTestName.Format(_L("GlyphDataIteratorOpen %S"), &KTestVariant);
+	
+	// Create some test fonts using the font factory.
+	CTFontFactory* fontFactory = CTFontFactory::NewLC();
+	fontFactory->CreateFontsL(aLanguage, 9);
+	
+	// Load the sample string data from the config file.
+	TInt numGlyphCodes = 0;
+	TUint* glyphCodes;
+	LoadConfigSampleDataL(aLanguage, aLongData, glyphCodes, numGlyphCodes);
+
+	// Run the test.
+	TInt err = KErrNotFound;
+	RFbsGlyphDataIterator iter;
+	CleanupClosePushL(iter);
+	iProfiler->InitResults();
+	for (TInt rep = aReps; (rep != 0) && (err == KErrNotFound); --rep)
+		{
+		err = iter.Open(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
+		for (; err == KErrNone; err = iter.Next())
+			{
+			// no operation
+			}
+		iter.Close();
+		}
+	iProfiler->MarkResultSetL();
+	TESTE(err == KErrNotFound, err);
+
+	CleanupStack::PopAndDestroy(2); // iter, fontFactory
+	iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, aReps, numGlyphCodes);
+	delete [] glyphCodes;
+	}
+
+/**
+@SYMTestCaseID GRAPHICS-UI-BENCH-0187
+
+@SYMTestType UT
+
+@SYMPREQ PREQ2678
+
+@SYMTestCaseDesc 
+Measures the performance of calling RFbsGlyphDataIterator::Open() with different 
+lengthed arrays but the same font. The sample data is a long array of characters.
+
+@SYMTestActions
+i. Create a single test font 
+ii. Create RFbsGlyphDataIterator.
+iii. Pass an array to RFbsGlyphDataIterator::Open(), starting with a single glyph.
+	For each iteration, increase the length of the array by one until the entire
+	string has been opened.
+iv. Measure the time to perform all the iterations.
+
+@param aSampleDataKey The string key to lookup under the GlyphArraySampleText section of the 
+	config file where the sample data is read.
+@param aReps The number of times to repeat the test.
+ */
+void CTFbsGlyphData::GlyphDataIteratorOpenSingleFontL()
+	{
+	_LIT(KTestName, "GlyphDataIteratorOpenSingleFont");
+	// A cap on the max number of iterations to complete.
+	const TInt KMaxNumIterations = 200;
+#ifndef UIBENCH_NO_HINDI
+    const TTestLanguage KTestLanguage = ETestLanguageHindi;
+#else
+    const TTestLanguage KTestLanguage = ETestLanguageLatin;
+#endif
+	
+	// Create some test fonts using the font factory.
+	CTFontFactory* fontFactory = CTFontFactory::NewLC();
+	fontFactory->CreateFontsL(KTestLanguage, 1);
+	CFbsFont* font = fontFactory->NextFont();
+	
+	// Load the sample string data from the config file.
+	TInt numGlyphCodes = 0;
+	TUint* glyphCodes;
+	LoadConfigSampleDataL(KTestLanguage, ETrue, glyphCodes, numGlyphCodes); 
+	
+	const TInt KNumRepetitions = Min<TInt>(numGlyphCodes - 1, KMaxNumIterations);
+	RFbsGlyphDataIterator iter;
+	CleanupClosePushL(iter);
+	TInt iterErr = KErrNone;
+	TInt glyphCount = 0;
+	iProfiler->InitResults();
+	for (glyphCount = 1; (glyphCount < KNumRepetitions); ++glyphCount)
+		{
+		iterErr = iter.Open(*font, glyphCodes, glyphCount);
+		for (; iterErr == KErrNone; iterErr = iter.Next())
+			{
+			// no operation
+			}
+		iter.Close();
+		}
+	iProfiler->MarkResultSetL();
+	TEST(glyphCount == KNumRepetitions);
+	TESTE(iterErr == KErrNotFound, iterErr);
+	
+	const TInt KAvgNumCharsPerIteration = KNumRepetitions/2;
+	iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, KNumRepetitions, KAvgNumCharsPerIteration);
+	
+	CleanupStack::PopAndDestroy(2); // iter, fontFactory
+	delete [] glyphCodes;
+	}
+/**
+@SYMTestCaseID GRAPHICS-UI-BENCH-0188
+
+@SYMTestType UT
+
+@SYMPREQ PREQ2678
+
+@SYMTestCaseDesc 
+Measures the performance of querying the TOpenFontCharMetrics using the different
+available APIs. RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData()
+are compared against each other, using the same fonts, and same sample data.
+This test uses glyphs that have not been rasterized before, therefore for certain
+APIs this will mean rasterizing the glyphs.
+
+@SYMTestActions
+i. Load sample text data from config file.
+ii. For each of RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData():
+	1. Create 50 new fonts.
+	2. Run the test, calling the necessary API once per font/loop.
+	3. For GetCharacterData() and RFbsGlyphDataIterator(), cycle through each glyph
+		to ensure all metrics have been retrieved. This is not necessary for 
+		RFbsGlyphMetricsArray.
+	4. Measure time between first and last font/loop.
+	5. Destroy test fonts so that next test has to re-rasterize the glyphs.	
+
+@SYMTestExpectedResults
+Since this test uses non-rasterized fonts, RFbsGlyphMetricsArray should be faster than
+GetCharacterData() and RFbsGlyphDataIterator, which both rasterize the glyphs in order to 
+get their metrics information.
+ */
+void CTFbsGlyphData::GlyphMetricsQueryUnrasterizedL()
+	{
+	_LIT(KTestName, "GlyphMetricsQueryUnrasterized");
+	TBuf<128> KTestNameVariant;
+	const TInt KNumFonts = 50;
+	const TTestLanguage KTestLanguage = ETestLanguageLatin;
+	
+	// Load the sample string data from the config file. Both the iterator and the
+	// array will use this same sample data.
+	TInt numGlyphCodes = 0;
+	TUint* glyphCodes;
+	LoadConfigSampleDataL(KTestLanguage, ETrue, glyphCodes, numGlyphCodes); 
+	
+	// Create some test fonts using the font factory.
+	CTFontFactory* fontFactory = CTFontFactory::NewLC();
+	
+	// First do the test for the iterator. To ensure fair comparison with
+	// RFbsGlyphMetricsArray, cycle through each iteration to ensure the metrics
+	// for each glyph is found.
+	KTestNameVariant.Format(_L("%S RFbsGlyphDataIterator"), &KTestName);
+	fontFactory->CreateFontsL(KTestLanguage, KNumFonts);
+	RFbsGlyphDataIterator iter;
+	CleanupClosePushL(iter);
+	TInt iterErr = KErrNone;
+	TInt rep = 0;
+	iProfiler->InitResults();
+	for (rep = KNumFonts; (rep != 0); --rep)
+		{
+		iterErr = iter.Open(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
+		for (; iterErr == KErrNone; iterErr = iter.Next())
+			{
+			// no operation
+			}
+		iter.Close();
+		}
+	iProfiler->MarkResultSetL();
+	TEST(rep == 0);
+	TESTE(iterErr == KErrNotFound, iterErr);
+	CleanupStack::PopAndDestroy(1); // iter		
+	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumFonts, numGlyphCodes);
+	
+	// Second, do the test for the array. This should be faster.
+	// Destroy the fonts and re-create them so that they have to be re-rasterized
+	// for a fair comparison.
+	TInt arrayErr = KErrNone;
+	KTestNameVariant.Format(_L("%S RFbsGlyphMetricsArray"), &KTestName);
+	fontFactory->ReleaseFonts();
+	fontFactory->CreateFontsL(KTestLanguage, KNumFonts);
+	RFbsGlyphMetricsArray array;
+	CleanupClosePushL(array);
+	iProfiler->InitResults();	
+	for (TInt rep = KNumFonts; (rep != 0) && (arrayErr == KErrNone); --rep)
+		{
+		arrayErr = array.Get(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
+		}
+	iProfiler->MarkResultSetL();
+	CleanupStack::PopAndDestroy(1); // array
+	TEST(rep == 0);
+	TESTE(arrayErr == KErrNone, arrayErr);
+	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumFonts, numGlyphCodes);
+	
+	// Third, do the test using GetCharacterData() to get the metrics.
+	// Destroy the fonts and re-create them so that they have to be re-rasterized
+	// for a fair comparison.
+	KTestNameVariant.Format(_L("%S GetCharacterData"), &KTestName);
+	fontFactory->ReleaseFonts();
+	fontFactory->CreateFontsL(KTestLanguage, KNumFonts);	
+	iProfiler->InitResults();
+	const TUint8* bitmapData = NULL;
+	TSize bitmapSize;
+	TOpenFontCharMetrics metrics;	
+	for (TInt rep = KNumFonts; (rep != 0); --rep)
+		{
+		CFbsFont* font = fontFactory->NextFont(); 
+		for (TInt glyphIndex = 0; glyphIndex < numGlyphCodes; glyphIndex++)
+			{
+			font->GetCharacterData(glyphCodes[glyphIndex], metrics, bitmapData, bitmapSize);
+			}
+		}
+	iProfiler->MarkResultSetL();
+	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumFonts, numGlyphCodes);
+	
+	CleanupStack::PopAndDestroy(1); // fontFactory
+	delete [] glyphCodes;
+	}
+
+/**
+@SYMTestCaseID GRAPHICS-UI-BENCH-0189
+
+@SYMTestType UT
+
+@SYMPREQ PREQ2678
+
+@SYMTestCaseDesc 
+Measures the performance of querying the TOpenFontCharMetrics using the different
+available APIs. RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData()
+are compared against each other, using the same fonts, and same sample data.
+This test uses glyphs that have already been rasterized, thereby possibly reducing the 
+extra overhead this has.
+
+@SYMTestActions
+i. Load sample text data from config file.
+ii. Create test font.
+iii. Pre-rasterize glyphs using RFbsGlyphDataIterator. This will rasterize the glyphs 
+	and cause them to be cached for use by all the APIs tested here.
+iv. For each of RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData():
+	1. Begin the loop, calling the necessary API once per font/loop.
+	2. For each glyph, request the glyph metrics.
+	3. Measure time between first and last font/loop.
+v. Destroy test font.
+
+@SYMTestExpectedResults
+All results should be improved over GlyphMetricsQueryUnrasterized (GRAPHICS-UI-BENCH-0187).
+since no rasterizing should take place during these tests.
+ */
+void CTFbsGlyphData::GlyphMetricsQueryPreRasterizedL()
+	{
+	_LIT(KTestName, "GlyphMetricsQueryPreRasterized");
+	TBuf<128> KTestNameVariant;
+	const TInt KNumIterations = 500;
+	const TTestLanguage KTestLanguage = ETestLanguageLatin;
+		
+	TInt numGlyphCodes = 0;
+	TUint* glyphCodes;
+	LoadConfigSampleDataL(KTestLanguage, ETrue, glyphCodes, numGlyphCodes); 
+	
+	// Create a test font using the font factory.
+	CTFontFactory* fontFactory = CTFontFactory::NewLC();
+	fontFactory->CreateFontsL(ETestLanguageLatin, 1);	
+	CFbsFont* font = fontFactory->NextFont();
+	
+	TInt iterErr = KErrNone;
+	TInt rep = 0;
+	// Rasterize the glyphs first.
+	RFbsGlyphDataIterator iter;
+	CleanupClosePushL(iter);
+	for (rep = KNumIterations; (rep != 0) ; --rep)
+		{
+		iterErr = iter.Open(*font, glyphCodes, numGlyphCodes);
+		for (; iterErr == KErrNone; iterErr = iter.Next())
+			{
+			// no operation
+			}
+		iter.Close();
+		}
+	TEST(rep == 0);
+	TESTE(iterErr == KErrNotFound, iterErr);
+	
+	TOpenFontCharMetrics metrics;
+		
+	// First do the test for the iterator. To ensure fair comparison with
+	// RFbsGlyphMetricsArray, cycle through each iteration to ensure the metrics
+	// for each glyph is found.
+	iterErr = KErrNone;
+	KTestNameVariant.Format(_L("%S RFbsGlyphDataIterator"), &KTestName);
+	iProfiler->InitResults();
+	for (TInt rep = KNumIterations; (rep != 0); --rep)
+		{
+		for (iterErr = iter.Open(*font, glyphCodes, numGlyphCodes); iterErr == KErrNone; iterErr = iter.Next())
+			{
+			metrics = iter.Metrics();
+			}
+		iter.Close();
+		}
+	iProfiler->MarkResultSetL();
+	TESTE(iterErr == KErrNotFound, iterErr);
+	CleanupStack::PopAndDestroy(1); // iter
+	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, numGlyphCodes);
+	
+	
+	// Second, do the test for the array. This should be faster.
+	TInt arrayErr = KErrNone;
+	KTestNameVariant.Format(_L("%S RFbsGlyphMetricsArray"), &KTestName);
+	RFbsGlyphMetricsArray array;
+	CleanupClosePushL(array);
+	iProfiler->InitResults();
+	for (TInt rep = KNumIterations; (rep != 0) && (arrayErr == KErrNone); --rep)
+		{
+		arrayErr = array.Get(*font, glyphCodes, numGlyphCodes);
+		for (TInt i = 0; i < numGlyphCodes; ++i)
+			{
+			metrics = array[i];
+			}
+		}
+	iProfiler->MarkResultSetL();
+	TESTE(arrayErr == KErrNone, arrayErr);
+	CleanupStack::PopAndDestroy(1); // array
+	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, numGlyphCodes);
+	
+	
+	// Third, do the test using GetCharacterData() to get the metrics.
+	KTestNameVariant.Format(_L("%S GetCharacterData"), &KTestName);
+	const TUint8* bitmapData;
+	TSize bitmapSize;
+
+	iProfiler->InitResults();
+	for (TInt rep = KNumIterations; (rep != 0); --rep)
+		{
+		for (TInt glyphIndex = 0; glyphIndex < numGlyphCodes; glyphIndex++)
+			{
+			font->GetCharacterData(glyphCodes[glyphIndex], metrics, bitmapData, bitmapSize);
+			}
+		}
+	iProfiler->MarkResultSetL();
+	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, numGlyphCodes);
+	
+	CleanupStack::PopAndDestroy(1); // fontFactory
+	delete [] glyphCodes;
+	}
+
+/**
+@SYMTestCaseID GRAPHICS-UI-BENCH-0190
+
+@SYMTestType UT
+
+@SYMPREQ PREQ2678
+
+@SYMTestCaseDesc 
+Measures the end-to-end performance of using Khronos APIs to render glyphs using the
+RFbsGlyphDataIterator API. Positioning is very basic and is not reflective of a production-
+quality text-rendering algorithm, but serves as a useful benchmark of the overall
+text-rendering performance using this API.
+
+@SYMTestActions
+i. Create a sample font to use. 
+ii. Create a RSgImage to be used as a target for Khronos API rendering.
+iii. Set-up EGL and OpenVG.
+iv. Construct RFbsGlyphDataIterator, and open on sample data. At each iteration:
+	1. Create an EGLImage from the RSgImage.
+	2. Create a VGImage from the EGLImage.
+	3. Render the VGImage using vgDrawImage().
+	4. Destroy VGImage.
+	5. Destroy EGLImage.
+	6. Advance the current rendering position for the next glyph, ensuring that every glyph
+	will be within the bounds of the target surface.
+v. Measure time from from first to last iteration.
+*/
+void CTFbsGlyphData::GlyphRenderingL()
+	{
+	_LIT(KTestName, "GlyphRendering");
+	const TInt KNumIterations = 500;
+#ifndef UIBENCH_NO_HINDI
+    const TTestLanguage KTestLanguage = ETestLanguageHindi;
+#else
+    const TTestLanguage KTestLanguage = ETestLanguageLatin;
+#endif
+	
+	// Create some test fonts using the font factory.
+	CTFontFactory* fontFactory = CTFontFactory::NewLC();
+	fontFactory->CreateFontsL(KTestLanguage, 1, 20);
+	CFbsFont* font = fontFactory->NextFont();
+	const TInt KFontHeightInPixels = font->HeightInPixels();
+
+	// Create RSgImage to be used as OpenVG Pixmap Surface
+
+	RSgImage target;
+	TInt err = target.Create(TSgImageInfo(KEglTargetSize, ESgPixelFormatARGB_8888_PRE, ESgUsageBitOpenVgSurface));
+	TESTL(err == KErrNone);
+	CleanupClosePushL(target);
+	
+	// Initialize EGL/OpenVG for rendering.
+	EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+	if (display == EGL_NO_DISPLAY)
+		{
+		ERR_PRINTF2(_L("Failed to get EGLDisplay. [eglError=%X]"), eglGetError());
+		User::Leave(KErrGeneral);
+		}
+	TESTL(display != EGL_NO_DISPLAY);
+	if (EGL_FALSE == eglInitialize(display, NULL, NULL))
+		{
+		ERR_PRINTF2(_L("Failed to initialize EGLDisplay. [eglError=%X]"), eglGetError());
+		User::Leave(KErrGeneral);
+		}
+	eglBindAPI(EGL_OPENVG_API);
+	
+	EGLint imageAttribs[] =
+	    {
+	    EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, 
+	    EGL_NONE
+	    };
+	EGLint configAttribs[] = 
+		{
+		EGL_MATCH_NATIVE_PIXMAP, (EGLint)&target,
+		EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
+		EGL_SURFACE_TYPE, EGL_PIXMAP_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT, 
+		EGL_NONE
+		};
+	
+	const EGLint KPixmapAttribsVgAlphaFormatPre[] = 
+	    {
+	    EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE,
+	    EGL_NONE
+	    };
+		
+	EGLint configId = 0;
+	EGLint numConfigs = 0;
+	if (EGL_FALSE == eglChooseConfig(display, configAttribs, &configId, 1, &numConfigs) || numConfigs == 0)
+		{
+		ERR_PRINTF3(_L("Failed to find suitable EGLConfig. [eglError=%X, configs=%d]"), eglGetError(), numConfigs);
+		User::Leave(KErrGeneral);
+		}
+	EGLContext context = eglCreateContext(display, configId, EGL_NO_CONTEXT, NULL);
+	if (context == EGL_NO_CONTEXT)
+		{
+		ERR_PRINTF2(_L("Failed to create EGLContext. [eglError=%X]"), eglGetError());
+		User::Leave(KErrGeneral);
+		}
+	EGLSurface surface = eglCreatePixmapSurface(display, configId, &target, KPixmapAttribsVgAlphaFormatPre);
+	if (EGL_FALSE == eglMakeCurrent(display, surface, surface, context))
+		{
+		ERR_PRINTF2(_L("Failed to create make surface and context current. [eglError=%X]"), eglGetError());
+		eglDestroyContext(display, context);
+		User::Leave(KErrGeneral);
+		}
+	
+	// Load the necessary EGL extensions...
+	TvgCreateEGLImageTargetKHRTypefPtr vgCreateImageTargetKHR;
+	PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
+	PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
+	eglCreateImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
+	eglDestroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
+	vgCreateImageTargetKHR = reinterpret_cast<TvgCreateEGLImageTargetKHRTypefPtr>(eglGetProcAddress("vgCreateEGLImageTargetKHR"));
+	if (!eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateImageTargetKHR)
+		{
+		ERR_PRINTF1(_L("Failed to get EGL Image extension functions."));
+		User::Leave(KErrNotSupported);
+		}
+	// Now we have an OpenVG window to render to!
+	
+	TInt numGlyphCodes = 0;
+	TUint* glyphCodes;
+	LoadConfigSampleDataL(KTestLanguage, EFalse, glyphCodes, numGlyphCodes); 
+
+	// Set up an identity matrix compatible with the Symbian co-ordinate system.
+	vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+	vgScale(1.f, -1.f);
+	vgTranslate(0, -KFontHeightInPixels);	
+	VGfloat vgIdentityMatrix[16];
+	vgGetMatrix(vgIdentityMatrix);
+	
+	RFbsGlyphDataIterator iter;
+	CleanupClosePushL(iter);
+		
+	// Render some glyphs.
+	TInt iterErr = KErrNone;
+	TInt rep = 0;
+	vgClear(0, 0, KEglTargetSize.iWidth, KEglTargetSize.iHeight);
+	TPoint glyphOrigin(0, 0);
+	iProfiler->InitResults();
+	for (rep = 0; rep < KNumIterations; rep++)
+		{
+		iterErr = iter.Open(*font, glyphCodes, numGlyphCodes);
+		for (;iterErr == KErrNone; iterErr = iter.Next())
+			{
+			const TOpenFontCharMetrics& metrics = iter.Metrics();
+			const RSgImage& glyphSgImage = iter.Image();
+			EGLImageKHR eglImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, 
+					reinterpret_cast<EGLClientBuffer>(&glyphSgImage), imageAttribs);
+			VGImage vgImage = vgCreateImageTargetKHR(eglImage);
+			
+			// wrapped text placement.			
+			TInt horizAdvance = metrics.HorizAdvance();
+			if (glyphOrigin.iX + horizAdvance >= KEglTargetSize.iWidth)
+				{
+				vgLoadMatrix(vgIdentityMatrix);
+				glyphOrigin.iX = 0;
+				glyphOrigin.iY -= KFontHeightInPixels;
+				if (glyphOrigin.iY - KFontHeightInPixels < -KEglTargetSize.iHeight)
+					{
+					glyphOrigin.iY = 0;
+					}
+				vgTranslate(glyphOrigin.iX, glyphOrigin.iY);
+				}
+			
+			vgDrawImage(vgImage);
+			vgDestroyImage(vgImage);
+			eglDestroyImageKHR(display, eglImage);
+				
+			// Move to next glyph position.
+			glyphOrigin.iX += horizAdvance;
+			vgTranslate(horizAdvance, 0);
+			}
+		iter.Close();
+		eglSwapBuffers(display, surface);
+		}
+	iProfiler->MarkResultSetL();
+	iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, KNumIterations, numGlyphCodes);
+	TEST(rep == KNumIterations);
+	TESTE(iterErr == KErrNotFound, iterErr);	
+	WriteTargetOutput(KTestName());
+	
+	eglDestroySurface(display, surface);
+	eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+	eglTerminate(display);
+	eglReleaseThread();
+	
+	CleanupStack::PopAndDestroy(3); // iter, target, fontFactory
+	delete [] glyphCodes;
+	}
+#endif
+
+/**
+Captures the EGL Surface (it is assumed to be an OpenVG surface) to a 256-grey CFbsBitmap,
+used when sanity-checking bitmaps are enabled. 
+*/
+CFbsBitmap* CTFbsGlyphData::GetTargetAsBitmapL()
+	{
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+	// For debugging purposes only.
+	// Capture the final state of the EGL Pixmap surface as an mbm.
+	TSize KTargetSize;
+	const TSize KBufferSize = KEglTargetSize;
+	const TInt KDataStride = KEglTargetSize.iWidth;
+	
+	TUint8* imageBuffer = reinterpret_cast<TUint8*>(User::AllocZ(KBufferSize.iHeight * KDataStride));
+	CFbsBitmap* bitmap = new (ELeave) CFbsBitmap();
+	CleanupStack::PushL(bitmap);
+	User::LeaveIfError(bitmap->Create(KBufferSize, EGray256));
+	vgReadPixels(imageBuffer, KDataStride, VG_A_8, 0, 0, KBufferSize.iWidth, KBufferSize.iHeight);
+	TUint8* buf = imageBuffer;
+	bitmap->BeginDataAccess();
+	TUint8* dataAddress = reinterpret_cast<TUint8*>(bitmap->DataAddress());
+	const TInt dataStride = bitmap->DataStride();	
+	for (TInt scanline = 0; scanline < KBufferSize.iHeight; scanline++)
+		{
+		Mem::Copy(dataAddress, buf, KBufferSize.iWidth);
+		dataAddress += dataStride;
+		buf += KBufferSize.iWidth;
+		}
+	bitmap->EndDataAccess(EFalse);
+	User::Free(imageBuffer);
+	CleanupStack::Pop(1); // bitmap
+	return bitmap;
+#else
+	return NULL;
+#endif
+	}
+
+/**
+Utility method. Loads sample glyph code data from the config ini file
+into a TUint array.
+@param aKey The key string to look for when loading the sample data from the config file
+@param aGlyphCodes On success, holds an array of glyph codes, to be freed by the caller.
+@param aNumGlyphCodes On success, holds the count of the glyph code array.
+@leave KErrNotFound if the test data cannot be found or is empty in the config file.
+ */
+void CTFbsGlyphData::LoadConfigSampleDataL(TTestLanguage aLanguage, TBool aLongData, TUint*& aGlyphCodes, TInt& aNumGlyphCodes)
+	{
+	// The name of the section in the config file to look-up the sample data
+	_LIT(KConfigFileSampleData, "GlyphDataSampleText");
+	
+	TBuf<32> keyName = ConfigKeyNameL(aLanguage, aLongData);
+	
+	// Load the sample string data from the config file.
+	TPtrC sampleText;
+	TESTL(GetStringFromConfig(KConfigFileSampleData, keyName, sampleText));
+	aNumGlyphCodes = sampleText.Length();
+	if (aNumGlyphCodes <= 0)
+		{
+		User::Leave(KErrNotFound);
+		}
+	aGlyphCodes = new(ELeave) TUint[aNumGlyphCodes];
+	for (TInt code = 0; code < aNumGlyphCodes; ++code)
+		{
+		aGlyphCodes[code] = sampleText[code]; 
+		}
+	}
+
+/**
+Creates the name of the key to look for in the config file for the test
+with the specified parameters.
+@param aLanguage The language the test will use.
+@param aLongData Whether to use long or short sample data.
+@return A descriptor value of the language.
+@leave KErrNotSupported if aLanguage is not recognised.
+ */
+TBufC<32> CTFbsGlyphData::ConfigKeyNameL(TTestLanguage aLanguage, TBool aLongData)
+	{
+	if (aLanguage < 0 || aLanguage > 1)
+		{
+		User::Leave(KErrNotSupported);
+		}
+	TBuf<32> langName[2];
+	langName[ETestLanguageLatin].Append(_L("Latin"));
+	langName[ETestLanguageHindi].Append(_L("Hindi"));	
+	langName[aLanguage].Append((aLongData) ? _L("Long") : _L("Short"));
+	return langName[aLanguage];
+	}
+
+/**
+Font factory.
+Utiltiy class for providing fonts for the performance tests.
+*/
+
+CTFontFactory::CTFontFactory()
+	{
+	}
+
+CTFontFactory::~CTFontFactory()
+	{
+	ReleaseFonts();
+	delete iTs;
+	}
+
+/**
+@return A new Font Factory ready to create fonts.
+*/
+CTFontFactory* CTFontFactory::NewLC()
+	{
+	CTFontFactory* fontFactory = new (ELeave) CTFontFactory();
+	CleanupStack::PushL(fontFactory);
+	fontFactory->iTs = static_cast<CFbsTypefaceStore*>(CFbsTypefaceStore::NewL(NULL));
+	return fontFactory;
+	}
+
+/**
+Creates a number of fonts for use by tests. All the fonts are created up-front so 
+that NextFont() can be called as a very lightweight call, so it can be used inside
+tests with minimal impact.
+Once fonts are created, the factory must not be destroyed until the fonts it created
+are finished with.
+@param aLanaugeMask Which language needs to be supported by the returned fonts.
+@param aNumFonts The number of fonts to create
+@param aStartSizeInPixels The lower bound font height of the fonts that are created. All
+	fonts will be at least as big as this value.
+*/
+void CTFontFactory::CreateFontsL(TTestLanguage aLanguageMask, TInt aNumFonts, TInt aStartSizeInPixels)
+	{
+	ReleaseFonts();
+	
+	RArray <TPtrC> typefaceNames;
+	CleanupClosePushL(typefaceNames);
+	switch(aLanguageMask)
+		{
+		case ETestLanguageHindi:	
+			User::LeaveIfError(typefaceNames.Reserve(1));
+			typefaceNames.Append(_L("Devanagari OT Eval"));
+			break;
+		case ETestLanguageLatin:
+			User::LeaveIfError(typefaceNames.Reserve(3));
+			typefaceNames.Append(_L("DejaVu Sans Condensed"));
+			typefaceNames.Append(_L("DejaVu Serif"));
+			typefaceNames.Append(_L("DejaVu Sans Mono"));
+			break;
+		default:
+			User::Leave(KErrNotSupported);
+		}
+	const TInt KNumTypefaces = typefaceNames.Count();
+		
+	iFont = new CFbsFont*[aNumFonts];
+	for (TInt count = 0; count < aNumFonts; ++count)
+		{
+		// After every KNumTypefaces font, increase size by 5.
+		TInt size = aStartSizeInPixels + (5 *(count / KNumTypefaces));
+		TPtrC typefaceName = typefaceNames[count % KNumTypefaces];
+		TFontSpec fontSpec(typefaceName, size);
+		User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont[count], fontSpec));
+		++iNumFonts;
+		}
+	iCurFont = -1;
+	CleanupStack::PopAndDestroy(1); // typefaceNames
+	}
+/**
+Releases all created fonts and frees associated memory.
+*/
+void CTFontFactory::ReleaseFonts()
+	{
+	for (TInt font = 0; font < iNumFonts; ++font)
+		{
+		iTs->ReleaseFont(iFont[font]);
+		}
+	delete [] iFont;
+	iFont = NULL;
+	iNumFonts = 0;
+	}
+
+/**
+@return The next font to be used. If it reaches the last font, the next font will
+	cycle back around to the first font.
+*/
+CFbsFont* CTFontFactory::NextFont()
+	{
+	return iFont[++iCurFont%iNumFonts];
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicstest/uibench/src/tfbsglyphdata.h	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,98 @@
+// Copyright (c) 2009-2010 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:
+//
+
+/**
+ @file
+ @test
+ @internalComponent - Internal Symbian test code 
+*/
+
+#ifndef TFBSGLYPHDATA_H
+#define TFBSGLYPHDATA_H
+
+#include <fbs.h>
+#include <sgresource/sgresource.h>
+#include "te_graphicsperformanceSuiteStepBase.h"
+
+/**
+Enumeration of languages that are supported for testing in this framework.
+ */
+enum TTestLanguage
+	{
+	ETestLanguageLatin,
+	ETestLanguageHindi
+	};
+
+/**
+Test case to test the performance of RFbsGlyphDataIterator and RFbsGlyphMetricsArray.
+*/
+class CTFbsGlyphData : public CTe_graphicsperformanceSuiteStepBase
+    {
+public:
+	CTFbsGlyphData();
+	~CTFbsGlyphData();
+	
+	// From CTe_graphicsperformanceSuiteStepBase
+	virtual TVerdict doTestStepPreambleL();
+	virtual TVerdict doTestStepPostambleL();
+	virtual TVerdict doTestStepL();
+	virtual CFbsBitmap* GetTargetAsBitmapL();
+    
+private:
+	// Tests
+	void GlyphMetricsArrayL(TTestLanguage aLanguage, TBool aLongData, TInt aReps);
+	void GlyphMetricsQuerySingleGlyphL();
+	void GlyphDataIteratorOpenL(TTestLanguage aLanguage, TBool aLongData, TInt aReps);
+	void GlyphDataIteratorOpenSingleFontL();
+	void GlyphMetricsQueryUnrasterizedL();
+	void GlyphMetricsQueryPreRasterizedL();
+	void GlyphRenderingL();
+	
+	// Utility methods
+	void LoadConfigSampleDataL(TTestLanguage aLanguage, TBool aLongData, TUint*& aGlyphCodes, TInt& aNumGlyphCodes);
+	static TBufC<32> ConfigKeyNameL(TTestLanguage aLanguage, TBool aLongData);
+	
+private:
+	RFbsSession iFbs;
+	RSgDriver iSgDriver;
+    };
+
+_LIT(KTFbsGlyphData,"tfbsglyphdata");
+
+/**
+Utility class. Provides the tests with a number of different fonts to use.
+Manages their creation and destruction.
+ */
+class CTFontFactory : public CBase
+	{
+public:
+	static CTFontFactory* NewLC();
+	~CTFontFactory();
+	
+	void CreateFontsL(TTestLanguage aLanguageMask, TInt aNumFonts, TInt aStartSizeInPixels = 5);
+	TInt NumFonts() const;
+	CFbsFont* NextFont();
+	void ReleaseFonts();
+private:
+	CTFontFactory();
+private:
+	CFbsFont** iFont;
+	TInt iNumFonts;
+	TInt iCurFont;
+	CFbsTypefaceStore* iTs;
+	};
+
+
+#endif /* TFBSGLYPHDATA_H */
--- a/graphicstest/uibench/src/tgcesuiteserver.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/graphicstest/uibench/src/tgcesuiteserver.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2008-2010 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"
@@ -113,6 +113,6 @@
 	else if(aStepName == KEventHandlingPerfName)
 		testStep = new CTEventHandlingPerf();
 	else if(aStepName == KTFlipFramerate)
-	    testStep = new CTFlipFramerate;
+	    testStep = new CTFlipFramerate();
 	return testStep;
 	}
--- a/m3g/m3gcore11/src/m3g_loader.c	Tue Jun 22 15:21:29 2010 +0300
+++ b/m3g/m3gcore11/src/m3g_loader.c	Fri Sep 24 16:14:28 2010 +0300
@@ -781,9 +781,9 @@
             isCompatible = M3G_FALSE;
             break;
         case M3G_CLASS_MESH:
-            isCompatible = (classID == M3G_CLASS_MESH)
-                || (classID == M3G_CLASS_MORPHING_MESH)
-                || (classID == M3G_CLASS_SKINNED_MESH);
+            isCompatible = (objClassID == M3G_CLASS_MESH)
+                || (objClassID == M3G_CLASS_MORPHING_MESH)
+                || (objClassID == M3G_CLASS_SKINNED_MESH);
             break;
         default:
             isCompatible = (classID == objClassID);
--- a/m3g/m3gcore11/src/m3g_sprite.c	Tue Jun 22 15:21:29 2010 +0300
+++ b/m3g/m3gcore11/src/m3g_sprite.c	Fri Sep 24 16:14:28 2010 +0300
@@ -280,7 +280,9 @@
     }
 #ifndef M3G_USE_NGL_API
     /* Store w after projection */
-    eyeSpace->w = ot.w;
+    if (eyeSpace != NULL) {
+        eyeSpace->w = ot.w;
+    }
 #endif
     m3gScaleVec4(&ot, m3gRcp(ot.w));
     m3gScaleVec4(&x, m3gRcp(x.w));
--- a/m3g/m3gcore11/src/m3g_vertexarray.c	Tue Jun 22 15:21:29 2010 +0300
+++ b/m3g/m3gcore11/src/m3g_vertexarray.c	Fri Sep 24 16:14:28 2010 +0300
@@ -643,18 +643,12 @@
 
         switch (type) {
         case M3G_BYTE:
-        case M3G_UBYTE:
             /* always padded to 4 bytes */
             array->stride = 4;
             break;
         case M3G_SHORT:
-        case M3G_USHORT:
             array->stride = size * sizeof(M3Gshort);
             break;
-        default:
-            m3gFree(m3g, array);
-            m3gRaiseError(m3g, M3G_INVALID_ENUM);
-            return NULL;
         }
 
         /* Alloc and initialize all values to zero */
--- a/m3g/m3gcore11/src/m3g_vertexbuffer.c	Tue Jun 22 15:21:29 2010 +0300
+++ b/m3g/m3gcore11/src/m3g_vertexbuffer.c	Fri Sep 24 16:14:28 2010 +0300
@@ -350,8 +350,7 @@
     if (newArray != NULL) {
     	if (buffer->arrayCount == 0 || (buffer->arrayCount == 1
                                         && change == 0)) {
-    		buffer->vertexCount =
-                (newArray != NULL ? m3gGetArrayVertexCount(newArray) : 0);
+    		buffer->vertexCount = m3gGetArrayVertexCount(newArray);
     	}
     	else if (m3gGetArrayVertexCount(newArray) != buffer->vertexCount) {
             m3gRaiseError(M3G_INTERFACE(buffer), M3G_INVALID_VALUE);
--- a/windowing/windowserver/inc/Graphics/openwfc/WSGRAPHICDRAWERINTERFACE.H	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/inc/Graphics/openwfc/WSGRAPHICDRAWERINTERFACE.H	Fri Sep 24 16:14:28 2010 +0300
@@ -40,6 +40,7 @@
 class MEventHandler;
 class MWsElement;
 class MWsGraphicsContext;
+class MWsAnimationScheduler;
 
 /** 
 @publishedPartner
@@ -134,57 +135,6 @@
 	virtual TBool RedrawInvalid(const TArray<TGraphicDrawerId>& aInvalid) = 0;
 	};
 
-class MWsAnimationScheduler: public MWsObjectProvider
-/** A system mechanism for customising the animation timer to a particular hardware variant or to a
-	particular external compositor e.g. an out-of-scene transition engine.
-	The default animation scheduler in WSERV does not understand device-dependant parameters e.g.
-	screen refresh rates
-	@publishedPartner
-	@released
-	to be adapted when WSERV migrates to surfaces
-*/	{
-public:
-	/** Called to schedule an animation event for a screen to occur not before some point
-	A screen may be scheduled to animate several times without actually receiving an animation event from the scheduler
-	If the scheduler cannot honour the request e.g. device constraints, it ignores the request.
-	@param aScreen the screen to recieve the event
-	@param aWhen the point in time the event need not occur before
-	*/
-	virtual void ScheduleAnimation(MWsScreen& aScreen,const TTime& aWhen) = 0;
-	/** Called if a screen determines that it no longer needs to schedule any animation
-	@param aScreen the screen not needing to receive any animation events
-	*/
-	virtual void UnscheduleAnimation(MWsScreen& aScreen) = 0;
-	/** Called to schedule the redrawing of all screens containing this graphic.
-	The redrawing of affected screens can be deferred by the scheduler.
-	@param aId the ID of the graphic to be redrawn.  The graphic itself need not exist
-		(e.g. it has just been deleted, hence the need to redraw all potentially affected screens). */
-	virtual void Invalidate(const TGraphicDrawerId& aId) = 0;
-	/** Called when the Window Server receives a TRawEvent::EInactive  event, to signal power-saving */
-	virtual void OnInactive() = 0;
-	/** Called when the Window Server receives a TRawEvent::EActive event, to signal screen back on */
-	virtual void OnActive() = 0;
-
-	/** Called to schedule a redraw for a screen which is out of date
-	A screen may be scheduled to redraw several times without actually receiving aredraw event from the scheduler
-	If this request is ignored then the screen will be draw incorrectly untill a such a request is not ignored.
-	@param aScreen the screen to recieve the event
-	@param aWhen the point in time the event need not occur before
-	*/
-	virtual void ScheduleRedraw(MWsScreen& aScreen,const TTime& aWhen) = 0;
-	/** Called to force a previously scheduled redraw for a screen to happen synchronously
-	Used when we are about to loose our ability to perform the redraw correctly.
-	@param aScreen the screen to recieve the event
-	*/
-	virtual void DoRedrawNow(MWsScreen& aScreen) = 0;
-
-protected:
-	IMPORT_C void Animate(MWsScreen& aScreen);
-	IMPORT_C void Animate(MWsScreen& aScreen, TRequestStatus* aFinished);
-	IMPORT_C void Redraw(MWsScreen& aScreen);
-	IMPORT_C TBool RedrawInvalid(MWsScreen& aScreen,const TArray<TGraphicDrawerId>& aInvalid);
-	};
-
 /**
 @publishedPartner
 @prototype
@@ -245,7 +195,7 @@
 	/** Get a particular screen by ordinal
 	@return the screen, or NULL if aIndex is out of bounds */
 	virtual const MWsScreen* Screen(TInt aIndex) const = 0;
-	/** Set the animation scheduler; this can only be done once by custom code
+	/**  Not supported
 	@return success of overriding the default scheduler */
 	virtual TBool SetCustomAnimationScheduler(MWsAnimationScheduler* aScheduler) = 0;
 	/** Query whether a custom animation scheduler has been set
@@ -899,7 +849,11 @@
 		EAlphaChannelTransparencyEnabled,
 		/** True if a clipping rect should be applied when drawing a standard text cursor, false otherwise.
 		The default value is false. */
-		ECursorClipRectSet
+		ECursorClipRectSet,
+		/** Implicitly defaults to true. Will remain true as long as the application's primary screendevice 
+		is in the same orientation as the device. This information is only given for top-windows, 
+		i.e. children of group-windows, and only when wsini.ini is configured with SIZE_MODE > 0. */
+		EScreenDeviceValid
 		};
 	/**
 	 This enum encapsulates the set of non-boolean attribute changes that can be observed
--- a/windowing/windowserver/nga/SERVER/openwfc/WINDOW.CPP	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/openwfc/WINDOW.CPP	Fri Sep 24 16:14:28 2010 +0300
@@ -674,6 +674,11 @@
 		aWindowTreeObserver.FlagChanged(*this, MWsWindowTreeObserver::ENonFading, ETrue); 
 		}
 	
+	if(IsTopClientWindow() && (iFlags&EFlagScreenDeviceInvalid) )
+		{
+		aWindowTreeObserver.FlagChanged(*this, MWsWindowTreeObserver::EScreenDeviceValid, EFalse);
+		}
+	
 	if(iAnimList)
 		iAnimList->SendState(aWindowTreeObserver);
 	
--- a/windowing/windowserver/nga/SERVER/openwfc/cliwin.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/openwfc/cliwin.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -1426,6 +1426,13 @@
 			iFlags&=~EFlagScreenDeviceInvalid;
 		else
 			iFlags|=EFlagScreenDeviceInvalid;
+		
+		MWsWindowTreeObserver* windowTreeObserver = iScreen->WindowTreeObserver();
+		if (windowTreeObserver)
+			{
+			windowTreeObserver->FlagChanged(*this, MWsWindowTreeObserver::EScreenDeviceValid, aState);
+			}
+		
 		return ETrue;
 		}
 	return EFalse;
--- a/windowing/windowserver/nga/SERVER/wsdisplaychangeao.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/wsdisplaychangeao.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2008-2010 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"
@@ -243,6 +243,27 @@
 	Cancel();
 	}
 
+void CWsConfigChangeNotifier::UpdateLastSetConfiguration(TDisplayConfiguration& aNewConfig)
+    {
+    TSize resolution(0,0);
+    if (aNewConfig.GetResolution(resolution))
+        {
+        iLastSetConfig.SetResolution(resolution);
+        }
+    
+    TSize resolutionTwips(0,0);
+    if (aNewConfig.GetResolutionTwips(resolutionTwips))
+        {
+        iLastSetConfig.SetResolutionTwips(resolutionTwips);   
+        }
+    
+    TDisplayConfiguration1::TRotation rotation;
+    if (aNewConfig.GetRotation(rotation))
+        {
+        iLastSetConfig.SetRotation(rotation);
+        }
+    }
+
 void CWsConfigChangeNotifier::RunL()
 	{
 	if(iStatus == KErrNone)
@@ -259,6 +280,29 @@
 			iRetry->CancelRetry();
 			
 			iOwner->IncreaseConfigSpinner();
+			
+			//if the config change comes from a render stage then ensure screen device size 
+			//is also updated
+			TSize currentRes;
+			currentConfig.GetResolution(currentRes);
+			TBool disconnected = (currentRes.iHeight == 0 || currentRes.iWidth == 0) ? ETrue : EFalse;
+            
+			//if the config change is due to CScreen::SetConfiguration() being called then we
+			//don't want to update it again. Only update if the configs are different and the
+			//display is connected...
+			TDisplayConfiguration lastSetConfig(iLastSetConfig);
+			if (!((currentConfig == lastSetConfig) || (disconnected)))
+			    {
+                TDisplayConfiguration1::TRotation rotation;
+                if (lastSetConfig.GetRotation(rotation))
+                    {
+                    //use the latest rotation value to ensure we don't get any
+                    //inconsistencies with the layer extents
+                    currentConfig.SetRotation(rotation);
+                    }
+                iOwner->UpdateConfiguration(currentConfig);
+			    }		
+			
 			//put config change event on queue
 			RPointerArray<CWsClient> clientArray;
 			CleanupClosePushL(clientArray);
@@ -282,6 +326,7 @@
 				iRetry->Retry(KRetryInitialDelay);
 				}
 			}
+		iNextLevelInterface->GetConfiguration(iLastSetConfig);
 		}
 	else if(iStatus != KErrCancel && iStatus != KErrNotSupported)
 		{
--- a/windowing/windowserver/nonnga/SERVER/WSTOP.CPP	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/nonnga/SERVER/WSTOP.CPP	Fri Sep 24 16:14:28 2010 +0300
@@ -18,6 +18,7 @@
 #include "wstop.h"
 
 #include <hal.h>
+#include <graphics/fbsdefs.h>
 #include "ANIM.H"
 #include "gc.h"
 #include "playbackgc.h"
--- a/windowing/windowserver/test/tauto/talphawin.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/test/tauto/talphawin.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -371,7 +371,8 @@
 
 	theWin.SetExtent(TPoint(0,0), winSize);
 	theWin.SetBackgroundColor(TRgb(127,0,255,127));
-	TInt mode=theWin.SetRequiredDisplayMode(EColor16MA);
+	TDisplayMode mode = EColor16MAP;
+	theWin.SetRequiredDisplayMode(mode);
 	theWin.SetVisible(ETrue);
 	theWin.SetTransparencyAlphaChannel();
 	theWin.Activate();
@@ -447,7 +448,7 @@
 	CFbsBitmap *bitmapOne;
 	bitmapOne = new (ELeave)CFbsBitmap();
 	CleanupStack::PushL(bitmapOne);
-	User::LeaveIfError(bitmapOne->Create(winSize,static_cast<TDisplayMode>(mode)));
+	User::LeaveIfError(bitmapOne->Create(winSize,mode));
 
 	CFbsBitmapDevice *deviceOne=CFbsBitmapDevice::NewL(bitmapOne);
 	CleanupStack::PushL(deviceOne);
@@ -502,7 +503,7 @@
 	User::LeaveIfError(refWin.Construct(*(BaseWin->WinTreeNode()),(TUint32)&refWin));
 
 	refWin.SetExtent(TPoint(0,0), winSize);
-	refWin.SetRequiredDisplayMode(static_cast<TDisplayMode>(mode));
+	refWin.SetRequiredDisplayMode(mode);
 	refWin.SetVisible(ETrue);
 	refWin.SetTransparencyAlphaChannel();
 	refWin.Activate();
--- a/windowing/windowserver/test/tauto/tgc.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/test/tauto/tgc.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -1290,7 +1290,11 @@
 	 * that we use matching color depths for our off-screen bitmaps so that accuracy is
 	 * not lost since we compare bitmaps from the screen versus off-screen.
 	 */
-	const TDisplayMode displayMode = device->DisplayMode();
+	TDisplayMode displayMode = device->DisplayMode();
+	if (TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode) == 32)
+	    {
+	    displayMode = EColor16MAP;
+	    }
 		
 	_LIT(KText,"RemoteGc & MWsGraphicsContext");
 	TFontSpec fSpec(KTestFontTypefaceName,23);
--- a/windowing/windowserver/test/tdynamicres/group/bld.inf	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/test/tdynamicres/group/bld.inf	Fri Sep 24 16:14:28 2010 +0300
@@ -33,6 +33,7 @@
 ../scripts/wsdynamicresbasic_isotropic_scaling.script	z:/wstest/dynamicres/wsdynamicresbasic_isotropic_scaling.script
 ../scripts/wsdynamicresbasic_anisotropic_scaling.script	z:/wstest/dynamicres/wsdynamicresbasic_anisotropic_scaling.script
 ../scripts/wsdynamicresbasic_openvg_isotropic.script	z:/wstest/dynamicres/wsdynamicresbasic_openvg_isotropic.script
+../scripts/wsdynamicresbasic_sirocco.script	z:/wstest/dynamicres/wsdynamicresbasic_sirocco.script
 #endif // SYMBIAN_BUILD_GCE
 wstestdynamicres.iby	/epoc32/rom/include/wstestdynamicres.iby
 ../scripts/wsdynamicresclassic.script	z:/wstest/dynamicres/wsdynamicresclassic.script
--- a/windowing/windowserver/test/tdynamicres/group/wstestdynamicres.iby	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/test/tdynamicres/group/wstestdynamicres.iby	Fri Sep 24 16:14:28 2010 +0300
@@ -39,6 +39,7 @@
 data=DATAZ_\wstest\dynamicres\wsdynamicresbasic_isotropic_scaling.script	wstest\dynamicres\wsdynamicresbasic_isotropic_scaling.script
 data=DATAZ_\wstest\dynamicres\wsdynamicresbasic_no_scaling.script	wstest\dynamicres\wsdynamicresbasic_no_scaling.script
 data=DATAZ_\wstest\dynamicres\wsdynamicresbasic_openvg_isotropic.script	wstest\dynamicres\wsdynamicresbasic_openvg_isotropic.script
+data=DATAZ_\wstest\dynamicres\wsdynamicresbasic_sirocco.script	wstest\dynamicres\wsdynamicresbasic_sirocco.script
 #endif
 
 #endif
--- a/windowing/windowserver/test/tdynamicres/group/wstestdynamicres_helium.pkg	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/test/tdynamicres/group/wstestdynamicres_helium.pkg	Fri Sep 24 16:14:28 2010 +0300
@@ -36,11 +36,5 @@
 ;REM Window Server Dynamic Resolution Test Scripts [no plugins]
 
 ;//Please execute only the tests appropriate to your hardware capabilities.
-"\epoc32\data\z\wstest\dynamicres\wsdynamicresclassic.script"-"c:\wstest\dynamicres\wsdynamicresclassic.script"
+"\epoc32\data\z\wstest\dynamicres\wsdynamicresbasic_sirocco.script"-"c:\wstest\dynamicres\wsdynamicresbasic_sirocco.script"
 
-"\epoc32\data\z\wstest\dynamicres\wsdynamicresbasic_anisotropic_scaling.script"-"c:\wstest\dynamicres\wsdynamicresbasic_anisotropic_scaling.script"
-"\epoc32\data\z\wstest\dynamicres\wsdynamicresbasic_integer_scaling.script"-"c:\wstest\dynamicres\wsdynamicresbasic_integer_scaling.script"
-"\epoc32\data\z\wstest\dynamicres\wsdynamicresbasic_isotropic_scaling.script"-"c:\wstest\dynamicres\wsdynamicresbasic_isotropic_scaling.script"
-"\epoc32\data\z\wstest\dynamicres\wsdynamicresbasic_no_scaling.script"-"c:\wstest\dynamicres\wsdynamicresbasic_no_scaling.script"
-"\epoc32\data\z\wstest\dynamicres\wsdynamicresbasic_openvg_isotropic.script"-"c:\wstest\dynamicres\wsdynamicresbasic_openvg_isotropic.script"
-
--- a/windowing/windowserver/test/tdynamicres/inc/wsdynamicresbase.h	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/test/tdynamicres/inc/wsdynamicresbase.h	Fri Sep 24 16:14:28 2010 +0300
@@ -81,12 +81,7 @@
 	void CommonOverlayWindowSetupL(RWindow& aWindow, const TRgb& aColor);
 	void ResizeTestCommonSetupL(RWindow& aWindow, const TRgb& aColor);
 
-	void MakeTestWindowPairL(TRect aOuterRect,TRgb aOuterColor,TRect aInnerRect,TRgb aInnerColor);
 	void LargerTestWindow(TInt aPercentOfBack=80);
-	void DestroyTestWindowPair(TBool aKillTestBack=ETrue,TBool aKillTestFront=ETrue,TBool aKillTestChildren=ETrue);
-	void MakeTestWindowTripleL(TRect aOuterRect,TRgb aOuterColor,TRect aInnerRect,TRgb aInnerColor,TRect aChildRect,TRgb aChildColor,TRect aSecondChildRect,TRgb aSecondChildColor);
-	void CreateTestWindowQuadL(TRect aOuterRect,TRgb aOuterColor,TRect aInnerRect,TRgb aInnerColor,TRect aChildRect,TRgb aChildColor,TRect aSecondChildRect,TRgb aSecondChildColor);
-	void MakeTestWindowTripleL(TRect aOuterRect,TRgb aOuterColor,TRect aInnerRect,TRgb aInnerColor,TRect aChildRect,TRgb aChildColor);
 	void MakeExtraChildWindowL(const RWindowBase& aFromParent,TRect aChildRect,TRgb aChildColor);
 	struct LoopingGcPtr;
 	LoopingGcPtr	LoopBeginActivateWithWipe(const TRegion& aRegion,RWindow& aWin,TRgb aColor);
@@ -121,7 +116,7 @@
 		void				CreateSharedUtilityL()const ;
 		};
 	static const TPostTestCleanup& PostTestCleanupInstance();
-	RWindow	iTestBack;
+	RBlankWindow	iTestBack;
 	RWindow	iTestFront;
 	RWindow	iTestChild;
 	RWindow	iTestSecondChild;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/test/tdynamicres/scripts/wsdynamicresbasic_sirocco.script	Fri Sep 24 16:14:28 2010 +0300
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 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: 
+//
+
+LOAD_SUITE wsdynamicrestestserver 
+
+RUN_TEST_STEP 100 wsdynamicrestestserver TEFUnit.CGlobalSettings.SetScreenNoL.0
+
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0001L
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0002L
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0003L
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0004L
+// skipped for Sirocco builds
+// RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0005L
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0006L
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0007L
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0008L
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0009L
+//0010 skipped
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0011L
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0012L
+// skipped for Sirocco builds
+// RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0013L
+//0014 skipped
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0015L
+//0016 0017 skipped
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0018L
+
+//0021 skipped
+
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0031L
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0032L
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0033L
+//0034 skipped
+
+//RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0041L.0
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0042L.0
+//RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0041L.1
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0042L.1
+
+// skipped for Sirocco builds
+// RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0051L
+//0052 0053 skipped
+
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0101L
+RUN_TEST_STEP 200 wsdynamicrestestserver TEFUnit.CWsDynamicResBasic.GRAPHICS_WSERV_DYNAMICRES_0102L
+
--- a/windowing/windowserver/test/tdynamicres/src/t_wsdynamicreswinbase.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/test/tdynamicres/src/t_wsdynamicreswinbase.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -526,7 +526,9 @@
 		for (TInt index=0;index<KMaxInfoLines;index++)
 			{
 			if (iTestInfo[index].Length())
+			    {
 				iInfoGc->DrawText(iTestInfo[index],textRect,textRect.Size().iHeight*3/4,iInfoGc->ECenter);
+			    }
 			textRect.Move(0,rowHeight);
 			}
 		iInfoGc->DiscardFont();
--- a/windowing/windowserver/test/tdynamicres/src/wsdynamicresbase.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/test/tdynamicres/src/wsdynamicresbase.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -144,70 +144,6 @@
 	User::After(TTimeIntervalMicroSeconds32(aMilliseconds * 1000));
 	}
 
-/**	Creates the normal scenario used by these tests.
- *  With a large window behind and small window in front.
- *  If the windows already exist then they are just repositioned and redrawn.
- * 	@param	aOuterRect	Position of back window
- * 	@param	aOuterColor	Background colour for back window
- * 	@param	aInnerRect	Position of front window
- * 	@param	aInnerColor	Background colour for front window
- * 
- **/
-void CWsDynamicResBase::MakeTestWindowPairL(TRect aOuterRect,TRgb aOuterColor,TRect aInnerRect,TRgb aInnerColor)
-	{
-	if (!iTestBack.WsHandle())
-		{
-		iTestBack=RWindow(iSession);
-		ASSERT_EQUALS_X(iTestBack.Construct(iGroup, ++iWindowHandle), KErrNone);
-#ifdef  FLICKER
-		iTestBack.Activate();
-#endif
-		iTestBack.SetRequiredDisplayMode(iDisplayMode);
-		iTestBack.SetBackgroundColor(aOuterColor);
-		iTestBack.SetExtent(aOuterRect.iTl,aOuterRect.Size());
-#ifndef FLICKER
-		iTestBack.Activate();
-#endif
-		}
-	else
-		{
-		iTestBack.SetRequiredDisplayMode(iDisplayMode);
-		iTestBack.SetBackgroundColor(aOuterColor);
-		iTestBack.SetExtent(aOuterRect.iTl,aOuterRect.Size());
-		}
-	iTestBack.BeginRedraw();
-	ActivateWithWipe(iGc,iTestBack,aOuterColor);
-	iGc->Deactivate();
-	iTestBack.EndRedraw();
-	iTestBack.SetVisible(ETrue);
-	
-	if (!iTestFront.WsHandle())
-		{
-		iTestFront=RWindow(iSession);
-		ASSERT_EQUALS_X(iTestFront.Construct(iGroup, ++iWindowHandle), KErrNone);
-#ifdef FLICKER
-		iTestFront.Activate();
-#endif
-		iTestFront.SetRequiredDisplayMode(iDisplayMode);
-		iTestFront.SetBackgroundColor(aInnerColor);	
-		iTestFront.SetExtent(aInnerRect.iTl,aInnerRect.Size());
-
-#ifndef FLICKER
-		iTestFront.Activate();
-#endif
-		}
-	else
-		{
-		iTestFront.SetRequiredDisplayMode(iDisplayMode);
-		iTestFront.SetBackgroundColor(aInnerColor);
-		iTestFront.SetExtent(aInnerRect.iTl,aInnerRect.Size());
-		}
-	
-	DrawPlainUI(iTestFront,EFalse,aInnerColor);
-	iTestFront.SetVisible(ETrue);
-	
-	}
-
 void CWsDynamicResBase::LargerTestWindow(TInt aPercentOfBack)
 	{
 	TRect newPos=iTestPos;
@@ -221,72 +157,6 @@
 	
 	}
 
-/** Destroys some or all of the test windows so the test can loop (or test the state after destruction.
- *  The windows are destroyed when the test exits normally.
- * 	Child windows are automatically killed when parent window is killed!
- * 
- **/
-void CWsDynamicResBase::DestroyTestWindowPair(TBool aKillTestBack,TBool aKillTestFront,TBool aKillTestChildren)
-	{
-	if (aKillTestBack && iTestBack.WsHandle())
-		{
-		iTestBack.Close();
-		}
-	if (aKillTestFront && iTestFront.WsHandle())
-		{
-		iTestFront.Close();
-		}
-	if (aKillTestChildren)
-		{
-		if (iTestChild.WsHandle())
-			{
-			iTestChild.Close();
-			}
-		if (iTestSecondChild.WsHandle())
-			{
-			iTestSecondChild.Close();
-			}
-		}
-	}
-/**	Creates a child window inside the front window of the usual test scenario
-*  With a large window behind and small window in front.
- *  If the windows already exist then they are just repositioned and redrawn.
- * 	@param	aOuterRect	Position of back window
- * 	@param	aOuterColor	Background colour for back window
- * 	@param	aInnerRect	Position of front window
- * 	@param	aInnerColor	Background colour for front window
- * 	@param	aChildRect	Position of child window
- * 	@param	aChildColor	Background colour for child window
- * 	@param	aSecondChildRect	Position of Second child window
- * 	@param	aSecondChildColor	Background colour for Second child window
- * 
- **/
-void CWsDynamicResBase::MakeTestWindowTripleL(TRect aOuterRect,TRgb aOuterColor,TRect aInnerRect,TRgb aInnerColor,TRect aChildRect,TRgb aChildColor,TRect aSecondChildRect,TRgb aSecondChildColor)
-	{
-	MakeTestWindowTripleL(aOuterRect,aOuterColor,aInnerRect,aInnerColor,aChildRect,aChildColor);
-
-	MakeExtraChildWindowL(iTestChild,aSecondChildRect,aSecondChildColor);
-	}
-
-/**	Creates a child window inside the front window of the usual test scenario
-*  With a large window behind and small window in front.
- *  If the windows already exist then they are just repositioned and redrawn.
- * 	@param	aOuterRect	Position of back window
- * 	@param	aOuterColor	Background colour for back window
- * 	@param	aInnerRect	Position of front window
- * 	@param	aInnerColor	Background colour for front window
- * 	@param	aChildRect	Position of child window
- * 	@param	aChildColor	Background colour for child window
- *  @param	aSecondChildRect	Position of second child window
- * 	@param	aSecondChildColor	Background colour for second child window
- * 
- **/
-void CWsDynamicResBase::CreateTestWindowQuadL(TRect aOuterRect,TRgb aOuterColor,TRect aInnerRect,TRgb aInnerColor,TRect aChildRect,TRgb aChildColor,TRect aSecondChildRect,TRgb aSecondChildColor)
-	{
-	MakeTestWindowTripleL(aOuterRect,aOuterColor,aInnerRect,aInnerColor,aChildRect,aChildColor);
-	
-	MakeExtraChildWindowL(iTestFront,aSecondChildRect,aSecondChildColor);
-	}
 
 void CWsDynamicResBase::MakeExtraChildWindowL(const RWindowBase& aFromParent,TRect aChildRect,TRgb aChildColor)
 	{
@@ -347,39 +217,6 @@
 	return CWsDynamicResWinBase::BeginActivateWithWipe(aRegion,aWin,aColor);
 	}
 
-/**	Creates a child window inside the front window of the usual test scenario
-*  With a large window behind and small window in front.
- *  If the windows already exist then they are just repositioned and redrawn.
- * 	@param	aOuterRect	Position of back window
- * 	@param	aOuterColor	Background colour for back window
- * 	@param	aInnerRect	Position of front window
- * 	@param	aInnerColor	Background colour for front window
- * 	@param	aChildRect	Position of child window
- * 	@param	aChildColor	Background colour for child window
- * 
- **/
-void CWsDynamicResBase::MakeTestWindowTripleL(TRect aOuterRect,TRgb aOuterColor,TRect aInnerRect,TRgb aInnerColor,TRect aChildRect,TRgb aChildColor)
-	{
-	MakeTestWindowPairL(aOuterRect,aOuterColor,aInnerRect,aInnerColor);
-	ASSERT(iTestFront.WsHandle());
-	
-	if (!iTestChild.WsHandle())
-		{
-		iTestChild=RWindow(iSession);
-		ASSERT_EQUALS_X(iTestChild.Construct(iTestFront, ++iWindowHandle), KErrNone);
-		iTestChild.SetRequiredDisplayMode(iDisplayMode);
-		}
-	iTestChild.SetBackgroundColor(aChildColor);
-	iTestChild.SetExtent(aChildRect.iTl,aChildRect.Size());
-	iTestChild.Activate();
-	iTestChild.BeginRedraw();
-	iGc->Activate(iCompare);
-	iGc->SetBrushColor(iBlue);
-	iGc->Clear();
-	iGc->Deactivate();
-	iTestChild.EndRedraw();
-	iTestChild.SetVisible(ETrue);
-	}
 /**	
  * 	Generates a valid surfaceID for the current display mode.
  * 	This is then used in negative testing.
--- a/windowing/windowserver/test/tdynamicres/src/wsdynamicresbasic.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserver/test/tdynamicres/src/wsdynamicresbasic.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -509,6 +509,7 @@
 	For each, check if event has been received
 @SYMTestExpectedResults	
 	Based on type of change, check event
+	@note Test uses HAL to simulate display disconnection. Not supported on production platforms.
 */
 void	CWsDynamicResBasic::GRAPHICS_WSERV_DYNAMICRES_0005L()
 	{
@@ -683,16 +684,12 @@
 	TInt error;
 	MakeTitleAndCompareWindowsL(_L("GFX_WSERV_DYNAMICRES_0006L"),_L("Change Resolution"));
 
-	iTestBack=RWindow(iSession);
+	iTestBack=RBlankWindow(iSession);
 	ASSERT_EQUALS(iTestBack.Construct(iGroup, ++iWindowHandle), KErrNone);
 	iTestBack.SetRequiredDisplayMode(iDisplayMode);
-	iTestBack.SetBackgroundColor(TRgb(255,0,0));
+	iTestBack.SetColor(TRgb(255,0,0));
 	iTestBack.SetExtent(iTestPos.iTl,iTestPos.Size());
 	iTestBack.Activate();
-	iTestBack.BeginRedraw();
-	ActivateWithWipe(iGc,iTestBack,TRgb(255,0,0));
-	iGc->Deactivate();
-	iTestBack.EndRedraw();
 	iTestBack.SetVisible(ETrue);
 	
 	struct DrawCompare
@@ -902,17 +899,14 @@
 	TInt error;
 	MakeTitleAndCompareWindowsL(_L("GFX_WSERV_DYNAMICRES_0008L"),_L("Change Size Mode"));
 
-	iTestBack=RWindow(iSession);
-	ASSERT_EQUALS(iTestBack.Construct(iGroup, ++iWindowHandle), KErrNone);
-	iTestBack.SetRequiredDisplayMode(iDisplayMode);
-	iTestBack.SetBackgroundColor(TRgb(255,0,0));
-	iTestBack.SetExtent(iTestPos.iTl,iTestPos.Size());
-	iTestBack.Activate();
-	iTestBack.BeginRedraw();
-	ActivateWithWipe(iGc,iTestBack,TRgb(255,0,0));
-	iGc->Deactivate();
-	iTestBack.EndRedraw();
-	iTestBack.SetVisible(ETrue);
+    iTestBack=RBlankWindow(iSession);
+    ASSERT_EQUALS(iTestBack.Construct(iGroup, ++iWindowHandle), KErrNone);
+    iTestBack.SetRequiredDisplayMode(iDisplayMode);
+    iTestBack.SetColor(TRgb(255,0,0));
+    iTestBack.SetExtent(iTestPos.iTl,iTestPos.Size());
+    iTestBack.Activate();
+    iTestBack.SetVisible(ETrue);
+    iSession.Finish(ETrue);
 	
 	
 	if (CWindowGc*	gc=BeginActivateWithWipe(ETrue,iCompare,TRgb(128,128,128)))
@@ -1084,17 +1078,13 @@
 	MakeTitleAndCompareWindowsL(_L("GFX_WSERV_DYNAMICRES_0009L"),_L("Change Size Mode"));
 	iSession.Finish(ETrue);
 
-	iTestBack=RWindow(iSession);
-	ASSERT_EQUALS(iTestBack.Construct(iGroup, ++iWindowHandle), KErrNone);
-	iTestBack.SetRequiredDisplayMode(iDisplayMode);
-	iTestBack.SetBackgroundColor(TRgb(255,0,0));
-	iTestBack.SetExtent(iTestPos.iTl,iTestPos.Size());
-	iTestBack.Activate();
-	iTestBack.BeginRedraw();
-	ActivateWithWipe(iGc,iTestBack,TRgb(255,0,0));
-	iGc->Deactivate();
-	iTestBack.EndRedraw();
-	iTestBack.SetVisible(ETrue);
+    iTestBack=RBlankWindow(iSession);
+    ASSERT_EQUALS(iTestBack.Construct(iGroup, ++iWindowHandle), KErrNone);
+    iTestBack.SetRequiredDisplayMode(iDisplayMode);
+    iTestBack.SetColor(TRgb(255,0,0));
+    iTestBack.SetExtent(iTestPos.iTl,iTestPos.Size());
+    iTestBack.Activate();
+    iTestBack.SetVisible(ETrue);
 	iSession.Finish(ETrue);
 	
 	struct DrawCompare
@@ -1503,8 +1493,7 @@
 
 void CDSATestDrawing::Draw()
 	{
-	iWin->Invalidate();
-	iWin->BeginRedraw();
+	//Should not invalidate the window containing DSA drawing. That's the whole point!
 	CFbsBitGc* gc = iDSA->Gc();
 	gc->SetPenStyle(gc->ESolidPen);
 	gc->SetPenColor(TRgb(255,0,0));
@@ -1512,7 +1501,6 @@
 	iRect.Shrink(1, 1);
 	gc->DrawRect(iRect);
 	iDSA->ScreenDevice()->Update();
-	iWin->EndRedraw();
 	
 	}
 void CDSATestDrawing::Restart(RDirectScreenAccess::TTerminationReasons /*aReason*/) 
@@ -1637,8 +1625,6 @@
 			continue;
 			}
 		
-		//if my rectangle's iTl is (0,0) and iBr is (100,100). Why does it gives me the rect width and height
-		//both 100? 0 - 100 is 101 pixels drawn. Or does this indicates iBr is exclusive and iTl is inclusive?
 		//Ruo: Oh I almost believe iBr is exclusive now
 		TDisplayConfiguration dispConfigAfter2;
 		interface->GetConfiguration(dispConfigAfter2);
@@ -2722,12 +2708,16 @@
 		TInt completeCount = 0;
 		while (notComplete)
 			{
+            RDebug::Printf("iInfoScreenDevice->SetAppScreenMode");
 			iInfoScreenDevice->SetAppScreenMode(screenModeList[index]);
 			iSession.Finish(ETrue);
 			iSession.HeapSetFail(RHeap::EDeterministic,heapFail);
+            RDebug::Printf("iInfoScreenDevice->SetAppScreenMode");
 			iInfoScreenDevice->SetScreenMode(screenModeList[index]);
+            RDebug::Printf("SetScreenMode done");
 			iSession.HeapSetFail(RHeap::ENone,0);
 			iSession.Finish(ETrue);
+            RDebug::Printf("Finish done");
 			Pause(50);
 			TInt newMode = iInfoScreenDevice->CurrentScreenMode();
 
@@ -2736,7 +2726,7 @@
 				completeCount++;
 				if (completeCount == 5)
 					{
-					INFO_PRINTF2(_L("Succeeded with heapFail = %d"),heapFail);
+					INFO_PRINTF3(_L("Mode %i Succeeded with heapFail = %d"),index, heapFail);
 					notComplete = EFalse;
 					}
 				iInfoScreenDevice->SetAppScreenMode(screenModeList[0]);
@@ -3740,6 +3730,8 @@
 
 	if (aBitmapRegionPairArray.Count()>0)
 		{
+        RDebug::Printf("Checking");
+        TInt countchecks=0;
 		for (TInt i=0; i<width; i++)
 			{
 			for (TInt j=0; j<height; j++)
@@ -3822,6 +3814,7 @@
 				}
 			}
 		}
+	
 	ignoreDueToResizing.Close();
 	if (errorPixels+diffPixels < 2)
 		{
--- a/windowing/windowserverplugins/openwfc/group/stdplugin.mmp	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserverplugins/openwfc/group/stdplugin.mmp	Fri Sep 24 16:14:28 2010 +0300
@@ -75,6 +75,7 @@
 LIBRARY     wfcinterop.lib
 LIBRARY     surfacemanager.lib
 LIBRARY	 	libEGL.lib
+LIBRARY	 	bitgdi.lib
 //TODO Change the following line once eglsynchelper has been corrected
 //     to be available as a dynamic library
 STATICLIBRARY  eglsynchelper.lib
--- a/windowing/windowserverplugins/openwfc/src/displayrenderstage.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserverplugins/openwfc/src/displayrenderstage.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -312,7 +312,10 @@
 
 TDisplayMode CDisplayRenderStage::DisplayMode() const
 	{
-	return iRenderTarget->DisplayMode();
+	const TInt KThirtyTwoBpp = 32;
+	const TDisplayMode dm = iRenderTarget->DisplayMode();
+	const TInt bpp = TDisplayModeUtils::NumDisplayModeBitsPerPixel(dm);
+	return bpp == KThirtyTwoBpp ? CFbsDevice::DisplayMode16M() : dm;
 	}
 
 TSize CDisplayRenderStage::SizeInPixels() const
--- a/windowing/windowserverplugins/openwfc/src/fbrenderstage.cpp	Tue Jun 22 15:21:29 2010 +0300
+++ b/windowing/windowserverplugins/openwfc/src/fbrenderstage.cpp	Fri Sep 24 16:14:28 2010 +0300
@@ -18,6 +18,7 @@
 #include "panic.h"
 #include <graphics/wsdisplaycontrol.h>
 #include "displaypolicy.h"
+#include <graphics/sgutils.h>
 #include "utils.h"
 
 #if defined(__WINS__) && defined(_DEBUG)
@@ -154,7 +155,18 @@
 	if (iniFile->FindVar(iNextScreenDevice->ScreenNumber(), KFlickerBufferMode, flickerBufferModeName))
 		displayMode = ParseDisplayMode(flickerBufferModeName);
 	if (displayMode == ENone)
-		displayMode = iNextScreenDevice->DisplayMode();
+		{
+		// Display render stage MWsScreenDevice::DisplayMode now reports the supported screendriver display mode in 32bpp. 
+		// It is necessary in order to maintain BC with 3rd party apps and DSA framework.
+		// The reported display mode may be different from the actual UI surface pixel format, so flicker buffer
+	    // must not rely on DisplayMode() to determine pixel format for its rendering target.
+		//
+		MWsUiBuffer* uiBuf = aNextStage->ObjectInterface<MWsUiBuffer>();
+		if (uiBuf)
+			{
+			displayMode = SgUtils::PixelFormatToDisplayMode(uiBuf->PixelFormat());
+			}
+		}
 	STD_ASSERT_DEBUG(displayMode!=ENone, EPluginPanicNoDisplayModeFound);
 	
 	const TUint32 usage = ESgUsageDirectGdiTarget | ESgUsageWindowGcSource;