fontservices/fontstore/src/OPENFONT.CPP
changeset 46 6124ff6478cc
parent 40 91ef7621b7fc
child 53 11e2bb0d14ba
equal deleted inserted replaced
45:662fa7de7023 46:6124ff6478cc
   387         glyphCache = (COpenFontGlyphCache*) iHeap->Alloc(sizeof(COpenFontGlyphCache));
   387         glyphCache = (COpenFontGlyphCache*) iHeap->Alloc(sizeof(COpenFontGlyphCache));
   388         if (glyphCache == NULL) // no memory
   388         if (glyphCache == NULL) // no memory
   389             {
   389             {
   390             return NULL;
   390             return NULL;
   391             }
   391             }
   392         new (glyphCache) COpenFontGlyphCache;
   392         new (glyphCache) COpenFontGlyphCache(iHeap);
   393         SetGlyphCache(glyphCache);
   393         SetGlyphCache(glyphCache);
   394         }
   394         }
   395     // If there is no sentinel present, i.e. new cache
   395     // If there is no sentinel present, i.e. new cache
   396     if (glyphCache->iShaperCacheSentinel == NULL)
   396     if (glyphCache->iShaperCacheSentinel == NULL)
   397         {
   397         {
   530 	File()->GetFontStore()->CleanupCacheOnOpenFontRemoval(this);
   530 	File()->GetFontStore()->CleanupCacheOnOpenFontRemoval(this);
   531 	
   531 	
   532 	COpenFontGlyphCache* glyphCache = GetGlyphCache();
   532 	COpenFontGlyphCache* glyphCache = GetGlyphCache();
   533 	if (glyphCache != NULL)
   533 	if (glyphCache != NULL)
   534 		{
   534 		{
   535 		COpenFontGlyphTreeEntry* next = NULL;
   535 		glyphCache->iGlyphTreeById.ResetAndDestroy();
   536 		for (COpenFontGlyphTreeEntry* g = glyphCache->iGlyphList; g != NULL; g = next)
   536 		glyphCache->iGlyphTreeByUnicode.ResetAndDestroy();
   537 			{
       
   538 			next = g->iNext;
       
   539 			COpenFontGlyph::Delete(iHeap, g);
       
   540 			}
       
   541 
   537 
   542 		// Delete the shaper cache as well
   538 		// Delete the shaper cache as well
   543 		if (glyphCache->iShaperCacheSentinel)
   539 		if (glyphCache->iShaperCacheSentinel)
   544 			{
   540 			{
   545 			COpenFontShaperCacheEntry* previous  = NULL;
   541 			COpenFontShaperCacheEntry* previous  = NULL;
   571         {
   567         {
   572         file->RemoveFontFromList(this);
   568         file->RemoveFontFromList(this);
   573         }
   569         }
   574 	}
   570 	}
   575 
   571 
   576 COpenFontGlyph::~COpenFontGlyph()
       
   577 	{
       
   578 	}
       
   579 
       
   580 void COpenFontGlyph::Delete(RHeap* aHeap, COpenFontGlyph* aGlyph)
       
   581 	{
       
   582 	if (aGlyph != NULL)
       
   583 		{
       
   584 		aHeap->Free(aGlyph->Bitmap());
       
   585 		aHeap->Free(aGlyph);
       
   586 		}
       
   587 	}
       
   588 
       
   589 EXPORT_C void COpenFont::operator delete(TAny *aFont)
   572 EXPORT_C void COpenFont::operator delete(TAny *aFont)
   590 	{
   573 	{
   591 	if(aFont != NULL)
   574 	if(aFont != NULL)
   592 		{
   575 		{
   593 		COpenFont* f = (COpenFont*)aFont;
   576 		COpenFont* f = (COpenFont*)aFont;
   622         glyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache));
   605         glyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache));
   623 		if (glyphCache == NULL) // no memory
   606 		if (glyphCache == NULL) // no memory
   624 			{
   607 			{
   625 			return EFalse;
   608 			return EFalse;
   626 			}
   609 			}
   627 		new(glyphCache) COpenFontGlyphCache;
   610 		new(glyphCache) COpenFontGlyphCache(iHeap);
   628 		SetGlyphCache(glyphCache);
   611 		SetGlyphCache(glyphCache);
   629 		}
   612 		}
   630 
   613 
   631 	// Look in the Font Cache	
   614 	// Look in the Font Cache	
   632 	TInt* nodeInsertPtr = NULL;	
   615 	const COpenFontGlyph* g = FontCacheGlyph(aCode);		 	
   633 	const COpenFontGlyph* g = FontCacheGlyph(aCode, nodeInsertPtr);		 	
       
   634 
       
   635 	// If it is not found there look in the session cache.
       
   636 	COpenFontSessionCache* cache = NULL;
       
   637 	TInt index = 0;
       
   638 	if (g == NULL)
       
   639 		{
       
   640 		g = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, EFalse);
       
   641 		}
       
   642 
   616 
   643 	// If it has already been rasterized return it.
   617 	// If it has already been rasterized return it.
   644 	if (g != NULL)
   618 	if (g != NULL)
   645 		{
   619 		{
   646 		if (aGlyphData != NULL)
   620 		if (aGlyphData != NULL)
   662 		return EFalse;
   636 		return EFalse;
   663 		}
   637 		}
   664 
   638 
   665 	TBool glyph_data_valid = ETrue;
   639 	TBool glyph_data_valid = ETrue;
   666 	const TOpenFontGlyphData* cur_glyph_data = temp_glyph_data ? temp_glyph_data : aGlyphData;
   640 	const TOpenFontGlyphData* cur_glyph_data = temp_glyph_data ? temp_glyph_data : aGlyphData;
   667 	const COpenFontGlyph* new_glyph = NULL;
   641 	COpenFontGlyph* new_glyph = NULL;
   668 
   642 
   669 	// If the maximum per-font cache memory will not be exceeded, put the glyph into the font cache.
   643 	// If the maximum per-font cache memory will not be exceeded, put the glyph into the font cache.
   670 	TInt bytes = sizeof(COpenFontGlyphTreeEntry) + cur_glyph_data->BytesNeeded();	
   644 	TInt bytes = sizeof(COpenFontGlyph) + cur_glyph_data->BytesNeeded();	
   671 	if(glyphCache != NULL && bytes + glyphCache->iGlyphCacheMemory <= KMaxGlyphCacheMemory)
   645 	if(glyphCache != NULL && bytes + glyphCache->iGlyphCacheMemory <= KMaxGlyphCacheMemory)
   672 		{
   646 		{
   673 		COpenFontGlyphTreeEntry* new_entry = COpenFontGlyphTreeEntry::New(iHeap, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
   647 		new_glyph = COpenFontGlyph::New(iHeap, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
   674 		new_glyph=new_entry;
   648 		if (new_glyph != NULL)
   675 		if (new_entry != NULL)
       
   676             {
   649             {
   677             // Add the glyph to a leaf node using the nodeInsertPtr that was returned by FontCacheGlyph()
   650 			if ((aCode & 0x80000000) != 0)
   678             // This is the first node if the glyph cache is empty. This updates the cache atomically.
   651 				{
   679             *nodeInsertPtr = PointerToThisOffset(new_entry);
   652 				error = glyphCache->iGlyphTreeById.SetAt(aCode & 0x7FFFFFFF, new_glyph);
   680 
   653 				}
   681             // If new_entry is not the first in the cache, set the previous 
   654 			else
   682             // entry to link to this so that a linked-list of entries can be
   655 				{
   683             // maintained to simplify deletion.
   656 				error = glyphCache->iGlyphTreeByUnicode.SetAt(aCode, new_glyph);
   684             COpenFontGlyphTreeEntry* tree = static_cast<COpenFontGlyphTreeEntry*> (ThisOffsetToPointer(glyphCache->iGlyphTreeOffset));
   657 				}
   685             __ASSERT_DEBUG(tree != NULL, User::Invariant());
   658 			if (error == KErrNone)
   686             if (new_entry != tree)
   659 			    {
   687                 {
   660                 glyphCache->iGlyphCacheMemory += bytes;
   688                 while (tree->iNext != NULL)
   661 			    }
   689                     {
   662 			else
   690                     tree = tree->iNext;
   663 			    {
   691                     }
   664                 iHeap->Free(new_glyph);
   692                 tree->iNext = new_entry;
   665                 new_glyph = NULL;
   693                 }
   666 			    }
   694             else
   667             }
   695                 {
   668 		}
   696                 // First entry in tree, initialise iGlyphList
   669 	// Otherwise put the glyph into the per-session cache.
   697                 glyphCache->iGlyphList = new_entry;
       
   698                 }
       
   699 
       
   700             glyphCache->iGlyphCacheMemory += bytes;
       
   701             }//if (new_entry)
       
   702 		}
       
   703 	else
   670 	else
   704 		{
   671 		{
   705 		error = KErrGeneral;
   672 		// Look in the session cache. Do not expect to find the glyph here
   706 		}
   673 		// since the session cache has already been searched client-side.
   707 
   674 		// However, SessionCacheGlyph() is called so that the session cache is
   708 	// Otherwise put the glyph into the per-session cache.
   675 		// created if needed and an index is found where the new glyph will be
   709 	if (error != KErrNone)
   676 		// placed when added to the session cache.
   710 		{
   677 		COpenFontSessionCache* cache = NULL;
   711 		// If the session cache is not yet known find it or create one.
   678 		TInt index = 0;
   712 		if (cache == NULL)
   679 		(void)SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, ETrue);
   713 			{
       
   714 			SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, TRUE);
       
   715 			}
       
   716 		if (cache == NULL)
   680 		if (cache == NULL)
   717 			{			
   681 			{			
       
   682 			iHeap->Free(temp_glyph_data);
   718 			return EFalse;
   683 			return EFalse;
   719 			}
   684 			}
   720 
   685 
   721 		COpenFontSessionCacheEntry* new_entry =
   686 		COpenFontSessionCacheEntry* new_entry =
   722 			COpenFontSessionCacheEntry::New(iHeap, this, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
   687 			COpenFontSessionCacheEntry::New(iHeap, this, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
   875                 aHinted, aOutline, aLength);
   840                 aHinted, aOutline, aLength);
   876         }
   841         }
   877     return ret;
   842     return ret;
   878     }
   843     }
   879 
   844 
   880 /** Given the passed pointer aAny, return an offset from it to the "this" pointer
       
   881 of this COpenFont object.
       
   882 @param aAny A pointer to an object that exists on the shared heap, i.e. the same heap
       
   883 that this CCOpenFont object was created on.
       
   884 @return An offset relative to the "this" pointer for this object, this offset can
       
   885 be converted back to a pointer using ThisOffsetToPointer().
       
   886 @see ThisOffsetToPointer().
       
   887 @internalComponent 
       
   888  */
       
   889 TInt COpenFont::PointerToThisOffset(const TAny* aAny)
       
   890 	{
       
   891 	if (aAny != NULL)
       
   892 		{
       
   893 		return ((TInt)aAny - (TInt)this);
       
   894 		}
       
   895 	return 0;
       
   896 	}
       
   897 
       
   898 /** Given the passed passed offset aThisOffset, convert it to a pointer relative to
       
   899 the "this" pointer for this object.
       
   900 @param aThisOffset An offset that was generated using PointerToThisOffset().
       
   901 @return A pointer that has been created by adding (this+aThisOffset).
       
   902 @see PointerToThisOffset().
       
   903 @internalComponent 
       
   904  */
       
   905 TAny* COpenFont::ThisOffsetToPointer(const TInt aThisOffset)
       
   906 	{
       
   907 	if (aThisOffset)
       
   908 		{
       
   909 		return (TAny*)((TInt)this + aThisOffset);
       
   910 		}
       
   911 	return NULL;
       
   912 	}		
       
   913 
   845 
   914 /**
   846 /**
   915 A constructor initialised with a TCharacterMetrics object.
   847 A constructor initialised with a TCharacterMetrics object.
   916 
   848 
   917 This is the old-style character metrics object. As for other T classes, there 
   849 This is the old-style character metrics object. As for other T classes, there 
  1016 The cache is now created in COpenFont::Rasterize which can only be called within the context of FBSERV
   948 The cache is now created in COpenFont::Rasterize which can only be called within the context of FBSERV
  1017 @param aCode The code for the glpyh to look for in the cache
   949 @param aCode The code for the glpyh to look for in the cache
  1018 @return A pointer to the requested glyph if it was found in the glyph cache, NULL if it was not found.
   950 @return A pointer to the requested glyph if it was found in the glyph cache, NULL if it was not found.
  1019 */
   951 */
  1020 const COpenFontGlyph* COpenFont::FontCacheGlyph(TInt aCode)
   952 const COpenFontGlyph* COpenFont::FontCacheGlyph(TInt aCode)
  1021 	{		
   953 	{
  1022 	if (COpenFontGlyphCache* glyphCache = GetGlyphCache())
   954 	if (COpenFontGlyphCache* glyphCache = GetGlyphCache())
  1023 		{		
   955 		{
  1024 		COpenFontGlyphTreeEntry* node = NULL;		
   956 		if ((aCode & 0x80000000) != 0)
  1025 		if (glyphCache->iGlyphTreeOffset)
   957 			{
  1026 			{			
   958 			return glyphCache->iGlyphTreeById.At(aCode & 0x7FFFFFFF);
  1027 			node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(glyphCache->iGlyphTreeOffset));
   959 			}
  1028 			}
   960 		else
  1029 				
   961 			{
  1030 		while (node != NULL)
   962 			return glyphCache->iGlyphTreeByUnicode.At(aCode);
  1031 			{
   963 			}
  1032 			TInt code = node->iCode;
       
  1033 			if(code == aCode)
       
  1034 				{
       
  1035 				// Found the glyph
       
  1036 				return node;
       
  1037 				}		
       
  1038 			else if(code > aCode)
       
  1039 				{									
       
  1040 				node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(node->iLeftOffset));			
       
  1041 				}
       
  1042 			else
       
  1043 				{										
       
  1044 				node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(node->iRightOffset));			
       
  1045 				}
       
  1046 			}		
       
  1047 		}
       
  1048 	// No glyph found
       
  1049 	return NULL;
       
  1050 	}
       
  1051 	
       
  1052 /**
       
  1053 Retrieve glyph data from the per-font glyph cache.
       
  1054 If it is not found return NULL and place the address of the node pointer
       
  1055 to receive a new glyph in aNodeInsertPtr. 
       
  1056 If the cache hasn't been created, then return NULL.
       
  1057 Previous versions of this function created the cache, but as this function can potentially
       
  1058 run in the context of threads other than FBSERV the alloc could panic if iHeap's chunk had to 
       
  1059 be resized - this is not allowed by the kernel.
       
  1060 The cache is now created in COpenFont::Rasterize which can only be called within the context of FBSERV
       
  1061 @param aCode The code for the glpyh to look for in the cache
       
  1062 @param aNodeInsertPtr Returns a pointer to a final empty left or right leaf node
       
  1063 in the glpyh tree where the searched for glyph can be inserted if necessary.
       
  1064 @return A pointer to the requested glyph if it was found in the glyph cache, NULL if it was not found.
       
  1065 */
       
  1066 const COpenFontGlyph* COpenFont::FontCacheGlyph(TInt aCode, TInt*& aNodeInsertPtr)
       
  1067 	{		
       
  1068 	aNodeInsertPtr = NULL;	
       
  1069 
       
  1070 	if (COpenFontGlyphCache* glyphCache = GetGlyphCache())
       
  1071 		{		
       
  1072         COpenFontGlyphTreeEntry* node = NULL;
       
  1073         if (glyphCache->iGlyphTreeOffset)
       
  1074             {
       
  1075             node = static_cast<COpenFontGlyphTreeEntry*> (ThisOffsetToPointer(glyphCache->iGlyphTreeOffset));
       
  1076             }
       
  1077         else
       
  1078             {
       
  1079             aNodeInsertPtr = &glyphCache->iGlyphTreeOffset;
       
  1080             }
       
  1081 
       
  1082         while (node != NULL)
       
  1083 			{
       
  1084 			TInt code = node->iCode;
       
  1085 			if(code == aCode)
       
  1086 				{
       
  1087 				// Found the glyph
       
  1088 				return node;
       
  1089 				}		
       
  1090 			else if(code > aCode)
       
  1091 				{					
       
  1092 				aNodeInsertPtr = &node->iLeftOffset;
       
  1093 				node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(node->iLeftOffset));			
       
  1094 				}
       
  1095 			else
       
  1096 				{						
       
  1097 				aNodeInsertPtr = &node->iRightOffset;
       
  1098 				node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(node->iRightOffset));			
       
  1099 				}
       
  1100 			}		
       
  1101 		}
   964 		}
  1102 
   965 
  1103 	// No glyph found
   966 	// No glyph found
  1104 	return NULL;
   967 	return NULL;
  1105 	}
   968 	}
  1129 const COpenFontGlyph* COpenFont::SessionCacheGlyph(RHeap* aHeap,
   992 const COpenFontGlyph* COpenFont::SessionCacheGlyph(RHeap* aHeap,
  1130 	TInt aSessionHandle, TInt aCode, COpenFontSessionCache*& aCache,
   993 	TInt aSessionHandle, TInt aCode, COpenFontSessionCache*& aCache,
  1131 	TInt& aIndex, TBool aCreate) const
   994 	TInt& aIndex, TBool aCreate) const
  1132 	{
   995 	{
  1133 	aIndex = 0;
   996 	aIndex = 0;
  1134 	COpenFontSessionCacheListItem* prev = NULL;
   997 	COpenFontSessionCacheList* cacheList = SessionCacheList();
  1135 
   998 	aCache = cacheList->FindCache(aSessionHandle);
  1136 	COpenFontSessionCacheList* cachelist = const_cast<COpenFont*>(this)->SessionCacheList();
   999 	if (aCache != NULL)
  1137 	RSemaphore sem;
  1000 		{
  1138 	if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
  1001 		return aCache->Glyph(this, aCode, aIndex);
  1139 	    {
  1002 		}
  1140 	    RDebug::Print(_L("COpenFont::SessionCacheGlyphe() can't open SessionCacheSemaphore"));
       
  1141 	    return NULL;
       
  1142 	    }
       
  1143 	sem.Wait();
       
  1144 	COpenFontSessionCacheListItem* cacheListStart=cachelist->Start();
       
  1145 	if(cacheListStart != NULL)
       
  1146 		{
       
  1147 		for (COpenFontSessionCacheListItem* p = cacheListStart; p; p = p->Next())
       
  1148 			{
       
  1149 			COpenFontSessionCache* cache=p->Cache();
       
  1150 			if (cache->iSessionHandle == aSessionHandle)
       
  1151 				{
       
  1152 				aCache = cache;
       
  1153 				sem.Signal();
       
  1154 				sem.Close();
       
  1155 				return aCache->Glyph(this,aCode,aIndex);
       
  1156 				}
       
  1157 			prev = p;
       
  1158 			}
       
  1159 		}
       
  1160 	sem.Signal();
       
  1161 	sem.Close();
       
  1162 	
  1003 	
  1163 	if (aCreate)
  1004 	if (aCreate)
  1164 		{
  1005 		{
  1165 		COpenFontSessionCache* new_cache = NULL;
  1006 		COpenFontSessionCache* new_cache = NULL;
  1166 		TRAPD(error, new_cache = COpenFontSessionCache::NewL(aHeap, aSessionHandle, KSessionCacheEntries));
  1007 		TRAPD(error, new_cache = COpenFontSessionCache::NewL(aHeap, aSessionHandle, KSessionCacheEntries));
  1167 		
  1008 		
  1168 		if ((!error) && new_cache != NULL)
  1009 		if ((!error) && new_cache != NULL)
  1169 			{
  1010 			{
  1170 			COpenFontSessionCacheListItem* new_item = (COpenFontSessionCacheListItem*)aHeap->Alloc(sizeof(COpenFontSessionCacheListItem));
  1011 			if (cacheList->AddCache(new_cache) != KErrNone)
  1171 			if (new_item == NULL)
       
  1172 				{
  1012 				{
  1173 				new_cache->Delete(aHeap);	
  1013 				new_cache->Delete(aHeap);	
  1174 				aHeap->Free(new_cache);
  1014 				aHeap->Free(new_cache);
  1175 				return NULL;
  1015 				return NULL;
  1176 				}
  1016 				}
  1177 
  1017 
  1178 			new(new_item) COpenFontSessionCacheListItem(new_cache);
       
  1179 
       
  1180 			if (prev != NULL)
       
  1181 				{
       
  1182 				prev->SetNext(new_item);
       
  1183 				}
       
  1184 			else
       
  1185 				{
       
  1186 				cachelist->SetStart(new_item);
       
  1187 				}
       
  1188 
       
  1189 			aCache = new_cache;
  1018 			aCache = new_cache;
  1190 			aIndex = GLYPH_CODE(aCode) % KSessionCacheEntries;
  1019 			aIndex = GLYPH_CODE(aCode) % KSessionCacheEntries;
  1191 			}
  1020 			}
  1192 		}
  1021 		}
  1193 	return NULL;
  1022 	return NULL;
  1220 
  1049 
  1221 /**
  1050 /**
  1222 Create a glyph data object on the shared heap, given the code, metrics and the data bytes.
  1051 Create a glyph data object on the shared heap, given the code, metrics and the data bytes.
  1223 The data is copied; ownership remains with the caller.
  1052 The data is copied; ownership remains with the caller.
  1224 */
  1053 */
  1225 COpenFontGlyph* COpenFontGlyph::NewL(RHeap* aHeap, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap)
  1054 COpenFontGlyph* COpenFontGlyph::New(RHeap* aHeap, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap)
  1226 	{
  1055 	{
  1227 	COpenFontGlyph* glyph = (COpenFontGlyph*)aHeap->AllocL(sizeof(COpenFontGlyph));
  1056 	COpenFontGlyph* glyph = (COpenFontGlyph*)aHeap->Alloc(sizeof(COpenFontGlyph) + aBitmap.Size());
  1228 	new(glyph) COpenFontGlyph(aCode, aGlyphIndex, aMetrics);
  1057     if (glyph == NULL)
  1229 	if (!glyph->SetBitmap(aHeap, aBitmap))
  1058         {
  1230 		{
  1059         return NULL;
  1231 		aHeap->Free(glyph);
  1060         }
  1232 		User::Leave(KErrNoMemory);
  1061     new(glyph) COpenFontGlyph(aCode, aGlyphIndex, aMetrics);
  1233 		}
  1062 	glyph->SetBitmap(glyph + 1);
       
  1063 	Mem::Copy(glyph + 1, aBitmap.Ptr(), aBitmap.Size());
  1234 	return glyph;
  1064 	return glyph;
  1235 	}	
  1065 	}
  1236 
  1066 
  1237 COpenFontGlyphTreeEntry* COpenFontGlyphTreeEntry::New(RHeap* aHeap, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap)
  1067 COpenFontSessionCacheEntry* COpenFontSessionCacheEntry::New(RHeap* aHeap, const COpenFont* aFont, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap) 
  1238 	{
  1068 	{
  1239 	COpenFontGlyphTreeEntry* entry = (COpenFontGlyphTreeEntry*)aHeap->Alloc(sizeof(COpenFontGlyphTreeEntry));
  1069 	COpenFontSessionCacheEntry* entry = (COpenFontSessionCacheEntry*)aHeap->Alloc(sizeof(COpenFontSessionCacheEntry) + aBitmap.Size());
  1240 	if (entry == NULL)
  1070 	if (entry == NULL)
       
  1071 		{
  1241 		return NULL;
  1072 		return NULL;
  1242 	new(entry) COpenFontGlyphTreeEntry(aCode, aGlyphIndex, aMetrics);
  1073 		}
  1243 	if (!entry->SetBitmap(aHeap, aBitmap))
  1074 	new(entry) COpenFontSessionCacheEntry(aFont, aCode, aGlyphIndex, aMetrics);
  1244 		{
  1075 	entry->SetBitmap(entry + 1);
  1245 		aHeap->Free(entry);
  1076 	Mem::Copy(entry + 1, aBitmap.Ptr(), aBitmap.Size());
  1246 		entry = NULL;
       
  1247 		}
       
  1248 	return entry;
  1077 	return entry;
  1249 	}
  1078 	}
  1250 
  1079 
  1251 COpenFontSessionCacheEntry* COpenFontSessionCacheEntry::New(RHeap* aHeap, const COpenFont* aFont, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap) 
  1080 void COpenFontGlyph::SetBitmap(const TAny* aBitmap)
  1252 	{
  1081 	{
  1253 	COpenFontSessionCacheEntry* entry = (COpenFontSessionCacheEntry*)aHeap->Alloc(sizeof(COpenFontSessionCacheEntry));
  1082 	iBitmapOffset = reinterpret_cast<TInt>(aBitmap) - reinterpret_cast<TInt>(this);
  1254 	if (entry == NULL)
       
  1255 		return NULL;
       
  1256 	new(entry) COpenFontSessionCacheEntry(aFont, aCode, aGlyphIndex, aMetrics);
       
  1257 	if (!entry->SetBitmap(aHeap, aBitmap))
       
  1258 		{
       
  1259 		aHeap->Free(entry);
       
  1260 		entry = NULL;
       
  1261 		}
       
  1262 	return entry;
       
  1263 	}
       
  1264 
       
  1265 /**
       
  1266 @return A pointer to the run-length-encoded bitmap stored with this glyph, or NULL
       
  1267 if no bitmap has been stored with this glyph.
       
  1268  */
       
  1269 TUint8* COpenFontGlyph::Bitmap() const
       
  1270 	{
       
  1271 	if (iBitmapOffset)
       
  1272 		{
       
  1273 		return reinterpret_cast<TUint8*>(reinterpret_cast<TInt>(this) + iBitmapOffset);
       
  1274 		}
       
  1275 	return NULL;
       
  1276 	}
       
  1277 
       
  1278 TBool COpenFontGlyph::SetBitmap(RHeap* aHeap, const TDesC8& aBitmap)
       
  1279 	{
       
  1280 	TUint8* bitmap = (TUint8*)aHeap->Alloc(aBitmap.Length());
       
  1281 	if (bitmap == NULL)
       
  1282 		return EFalse;
       
  1283 	Mem::Copy(bitmap, aBitmap.Ptr(), aBitmap.Length());	
       
  1284 	aHeap->Free(Bitmap());
       
  1285 	iBitmapOffset = reinterpret_cast<TInt>(bitmap) - reinterpret_cast<TInt>(this);
       
  1286 	return ETrue;
       
  1287 	}
  1083 	}
  1288 
  1084 
  1289 COpenFontSessionCache* COpenFontSessionCache::NewL(RHeap* aHeap, TInt aSessionHandle, TInt aEntries)
  1085 COpenFontSessionCache* COpenFontSessionCache::NewL(RHeap* aHeap, TInt aSessionHandle, TInt aEntries)
  1290 	{
  1086 	{
  1291     COpenFontSessionCache* c = (COpenFontSessionCache*)aHeap->AllocL(sizeof(COpenFontSessionCache));
  1087     COpenFontSessionCache* c = (COpenFontSessionCache*)aHeap->AllocL(sizeof(COpenFontSessionCache));
  1299 	}
  1095 	}
  1300 
  1096 
  1301 
  1097 
  1302 void COpenFontSessionCache::Delete(RHeap* aHeap)
  1098 void COpenFontSessionCache::Delete(RHeap* aHeap)
  1303     {
  1099     {
  1304     TInt entries = iEntryArray.Count();
  1100     TInt numEntries = iEntryArray.Count();
  1305     for (TInt i = 0; i < entries; ++i)
  1101     for (TInt i = 0; i < numEntries; ++i)
  1306         {
  1102         {
  1307         COpenFontSessionCacheEntry* e = iEntryArray[i];
  1103         COpenFontSessionCacheEntry* entry = iEntryArray[i];
  1308         if (e != NULL)
  1104         if (entry != NULL)
  1309             {
  1105             {
  1310             COpenFont* font=const_cast<COpenFont*>(e->Font());
  1106             COpenFont* font=const_cast<COpenFont*>(entry->Font());
  1311             if (font != NULL)
  1107             if (font != NULL)
  1312                 font->DecrementCachedRefCount(iSessionHandle,NULL,ETrue);
  1108                 font->DecrementCachedRefCount(iSessionHandle,NULL,ETrue);
  1313             aHeap->Free(e->Bitmap());
  1109             COpenFontSessionCacheEntry::Delete(aHeap, entry);
  1314             aHeap->Free(e);
       
  1315             }
  1110             }
  1316         }
  1111         }
  1317     iEntryArray.Close(aHeap);
  1112     iEntryArray.Close(aHeap);
  1318     }
  1113     }
  1319 
  1114 
  1320 const COpenFontGlyph* COpenFontSessionCache::Glyph(const COpenFont* aFont, TInt aCode, TInt& aIndex)
  1115 const COpenFontGlyph* COpenFontSessionCache::Glyph(const COpenFont* aFont, TInt aCode, TInt& aIndex)
  1321 	{
  1116 	{
  1322     aIndex = -1;
  1117     aIndex = -1;
  1323     TInt oldest = KMaxTInt;
  1118     TInt oldest = KMaxTInt;
  1324     TInt oldest_index = 0;
  1119     TInt oldest_index = 0;
  1325     TInt entries = iEntryArray.Count();
  1120     TInt numEntries = iEntryArray.Count();
  1326     TInt index = GLYPH_CODE(aCode) % entries;   // simple hash function to shorten searches
  1121     TInt index = GLYPH_CODE(aCode) % numEntries;   // simple hash function to shorten searches
  1327     for (TInt i = 0; i < entries; ++i, ++index)
  1122     for (TInt i = 0; i < numEntries; ++i, ++index)
  1328         {
  1123         {
  1329         if (index >= entries)
  1124         if (index >= numEntries)
  1330             index = 0;
  1125             index = 0;
  1331         COpenFontSessionCacheEntry* e = iEntryArray[index];
  1126         COpenFontSessionCacheEntry* entry = iEntryArray[index];
  1332         if (e == NULL)
  1127         if (entry == NULL)
  1333             {
  1128             {
  1334             if (aIndex == -1)
  1129             if (aIndex == -1)
  1335                 aIndex = index;
  1130                 aIndex = index;
  1336             }
  1131             }
  1337         else
  1132         else
  1338             { 
  1133             { 
  1339             if (e->Font() == aFont && e->iCode == aCode)
  1134             if (entry->Font() == aFont && entry->iCode == aCode)
  1340                 {
  1135                 {
  1341                 e->iLastAccess = iLastAccess++;
  1136                 entry->iLastAccess = iLastAccess++;
  1342                 return e;
  1137                 return entry;
  1343                 }
  1138                 }
  1344             if (e->iLastAccess < oldest)
  1139             if (entry->iLastAccess < oldest)
  1345                 {
  1140                 {
  1346                 oldest = e->iLastAccess;
  1141                 oldest = entry->iLastAccess;
  1347                 oldest_index = index;
  1142                 oldest_index = index;
  1348                 }
  1143                 }
  1349             }
  1144             }
  1350         }
  1145         }
  1351     if (aIndex == -1)
  1146     if (aIndex == -1)
  1355 
  1150 
  1356 
  1151 
  1357 void COpenFontSessionCache::Insert(RHeap* aHeap, COpenFontSessionCacheEntry* aEntry, TInt aIndex)
  1152 void COpenFontSessionCache::Insert(RHeap* aHeap, COpenFontSessionCacheEntry* aEntry, TInt aIndex)
  1358 	{
  1153 	{
  1359     if (aIndex < 0 || aIndex >= iEntryArray.Count())
  1154     if (aIndex < 0 || aIndex >= iEntryArray.Count())
       
  1155         {
  1360         Panic(EFntSessionCacheIndexOutOfRange);
  1156         Panic(EFntSessionCacheIndexOutOfRange);
  1361     COpenFontGlyph::Delete(aHeap, iEntryArray[aIndex]);
  1157         }
       
  1158     COpenFontSessionCacheEntry::Delete(aHeap, iEntryArray[aIndex]);
  1362     iEntryArray.SetAt(aIndex, aEntry);
  1159     iEntryArray.SetAt(aIndex, aEntry);
  1363     aEntry->iLastAccess = iLastAccess++;
  1160     aEntry->iLastAccess = iLastAccess++;
  1364 	}
  1161 	}
  1365 
  1162 
  1366 COpenFontSessionCache::COpenFontSessionCache(TInt aSessionHandle):
  1163 COpenFontSessionCache::COpenFontSessionCache(TInt aSessionHandle):
  1367     iSessionHandle(aSessionHandle),
  1164     iSessionHandle(aSessionHandle),
  1368     iLastAccess(0)
  1165     iLastAccess(0)
  1369     {    
  1166     {    
  1370     }
  1167     }
  1371 
  1168 
  1372 /*COpenFontSessionCacheListItem*/
  1169 TInt COpenFontSessionCacheList::AddCache(COpenFontSessionCache* aCache)
  1373 COpenFontSessionCacheListItem::COpenFontSessionCacheListItem(COpenFontSessionCache* aCache):
  1170 	{
  1374 	iNextOffset(NULL)
  1171 	for (TInt index = 0; index < EMaxNumCaches; ++index)
  1375 	{
  1172 		{
  1376     if(aCache != NULL)
  1173 		if (iSessionHandleArray[index] == 0)
  1377         {
  1174 			{
  1378         iCacheOffset = reinterpret_cast<TInt>(aCache) - reinterpret_cast<TInt>(this);
  1175 			iSessionHandleArray[index] = aCache->SessionHandle();
  1379         }
  1176 			iCacheOffsetArray[index] = reinterpret_cast<TInt>(aCache) - reinterpret_cast<TInt>(this);
  1380     else
  1177 			return KErrNone;
  1381         {
  1178 			}
  1382         iCacheOffset = NULL;
  1179 		}
  1383         }
  1180 	return KErrNoMemory;
  1384 	}
  1181 	}
  1385 
  1182 
  1386 COpenFontSessionCacheListItem::~COpenFontSessionCacheListItem()
  1183 COpenFontSessionCache* COpenFontSessionCacheList::FindCache(TInt aSessionHandle) const
  1387 	{
  1184 	{
  1388 	}
  1185 	if (aSessionHandle == 0)
  1389 
       
  1390 /** Delete a COpenFontSessionCacheListItem from the passed heap.
       
  1391 
       
  1392 @param aHeap The heap to delete the COpenFontSessionCacheListItem from.
       
  1393  */
       
  1394 void COpenFontSessionCacheListItem::Delete(RHeap* aHeap)
       
  1395 	{
       
  1396     COpenFontSessionCache* cache = Cache();
       
  1397     if (cache != NULL)
       
  1398         {
       
  1399         cache->Delete(aHeap);   
       
  1400         aHeap->Free(cache);
       
  1401         }
       
  1402     iCacheOffset=NULL;
       
  1403     iNextOffset=NULL;
       
  1404 	}	
       
  1405 
       
  1406 /** Get the next item to this cache list item.
       
  1407 
       
  1408 @return A pointer to the next item to this one in the session cache, or NULL
       
  1409 if there is no next item.
       
  1410  */
       
  1411 COpenFontSessionCacheListItem* COpenFontSessionCacheListItem::Next()
       
  1412 	{
       
  1413 	if(iNextOffset)
       
  1414 		{
       
  1415 		COpenFontSessionCacheListItem* next = reinterpret_cast<COpenFontSessionCacheListItem*>(reinterpret_cast<TInt>(this) + iNextOffset);
       
  1416 		return next;
       
  1417 		}
       
  1418 	else
       
  1419 		{
  1186 		{
  1420 		return NULL;
  1187 		return NULL;
  1421 		}
  1188 		}
  1422 	}
  1189 	for (TInt index = 0; index < EMaxNumCaches; ++index)
  1423 
  1190 		{
  1424 /** Sets the next item to this in the session cache.
  1191 		if (iSessionHandleArray[index] == aSessionHandle)
  1425 
  1192 			{
  1426 @param aNext Set this cache list item as the next item to this one in the session cache list.
  1193 			return reinterpret_cast<COpenFontSessionCache*>(reinterpret_cast<TInt>(this) + iCacheOffsetArray[index]);
  1427  */
  1194 			}
  1428 void COpenFontSessionCacheListItem::SetNext(COpenFontSessionCacheListItem* aNext)
  1195 		}
  1429 	{
  1196 	return NULL;
  1430 	if(aNext != NULL)
       
  1431 		{
       
  1432 		iNextOffset = reinterpret_cast<TInt>(aNext) - reinterpret_cast<TInt>(this);
       
  1433 		}
       
  1434 	else
       
  1435 		{
       
  1436 		iNextOffset = NULL;
       
  1437 		}
       
  1438 	}
       
  1439 
       
  1440 /** Get a pointer to the session cache that this cache list item is in.
       
  1441 
       
  1442 @return A pointer to the session cache that this cache list item is part of.
       
  1443  */
       
  1444 COpenFontSessionCache* COpenFontSessionCacheListItem::Cache()
       
  1445 	{
       
  1446 	if(iCacheOffset)
       
  1447 		{
       
  1448 		COpenFontSessionCache* cache = reinterpret_cast<COpenFontSessionCache*>(reinterpret_cast<TInt>(this) + iCacheOffset);
       
  1449 		return cache;
       
  1450 		}
       
  1451 	else
       
  1452 		{
       
  1453 		return NULL;
       
  1454 		}
       
  1455 	}
       
  1456 
       
  1457 /** Get a pointer to the first item in the session cache.
       
  1458 
       
  1459 @return A pointer to the first item in the session cache.
       
  1460  */
       
  1461 COpenFontSessionCacheListItem* COpenFontSessionCacheList::Start()
       
  1462 	{
       
  1463 	if(iStartOffset)
       
  1464 		{
       
  1465 		COpenFontSessionCacheListItem* start = reinterpret_cast<COpenFontSessionCacheListItem*>(reinterpret_cast<TInt>(this) + iStartOffset);
       
  1466 		return start;
       
  1467 		}
       
  1468 	else
       
  1469 		{
       
  1470 		return NULL;
       
  1471 		}
       
  1472 
       
  1473 	}
       
  1474 
       
  1475 /** Set the passed item as the first item in the session cache. 
       
  1476 
       
  1477 @param aItem An item to be added to the session cache
       
  1478  */
       
  1479 void COpenFontSessionCacheList::SetStart(COpenFontSessionCacheListItem* aItem)
       
  1480 	{
       
  1481 	if(aItem != NULL)
       
  1482 		{
       
  1483 		iStartOffset = reinterpret_cast<TInt>(aItem) - reinterpret_cast<TInt>(this);
       
  1484 		}
       
  1485 	else
       
  1486 		{
       
  1487 		iStartOffset = 0;
       
  1488 		}
       
  1489 	}
  1197 	}
  1490 
  1198 
  1491 /** Delete all the items in the session cache if the current cache session handle
  1199 /** Delete all the items in the session cache if the current cache session handle
  1492 matches the passed session handle.
  1200 matches the passed session handle.
  1493 
  1201 
  1494 @param aHeap The heap base of the current process.
  1202 @param aHeap The heap base of the current process.
  1495 @param aSessionHandle The session handle of the cache to be deleted.
  1203 @param aSessionHandle The session handle of the cache to be deleted.
  1496  */
  1204  */
  1497 void COpenFontSessionCacheList::DeleteCache(RHeap* aHeap, TInt aSessionHandle)
  1205 void COpenFontSessionCacheList::DeleteCache(RHeap* aHeap, TInt aSessionHandle)
  1498 	{
  1206 	{
  1499     RSemaphore sem;
  1207 	if (aSessionHandle == 0)
  1500     if (KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
  1208 		{
  1501         {
  1209 		return;
  1502         RDebug::Print(_L("COpenFontSessionCacheList::DeleteCache() can't open SessionCacheSemaphore"));
  1210 		}
  1503         return;
  1211 	for (TInt index = 0; index < EMaxNumCaches; ++index)
  1504         }
  1212 		{
  1505     
  1213 		if (iSessionHandleArray[index] == aSessionHandle)
  1506     COpenFontSessionCacheListItem* prev = NULL;
  1214 			{
  1507     for (COpenFontSessionCacheListItem* curr = Start(); curr; prev = curr, curr
  1215 			COpenFontSessionCache* cache = reinterpret_cast<COpenFontSessionCache*>(PtrAdd(this, iCacheOffsetArray[index]));
  1508             = curr->Next())
  1216 			cache->Delete(aHeap);
  1509         {
  1217 			aHeap->Free(cache);
  1510         COpenFontSessionCache* cache = curr->Cache();
  1218 			iSessionHandleArray[index] = 0;
  1511         if (cache != NULL && cache->iSessionHandle == aSessionHandle)
  1219 			iCacheOffsetArray[index] = 0;
  1512             {
  1220 			return;
  1513             for (TInt i = 0; i < KSessionCacheSemaphoreCount; i++)
  1221 			}
  1514                 {
  1222         }
  1515                 //coverity[lock]
       
  1516                 //coverity[double_lock]
       
  1517                 sem.Wait();
       
  1518                 }
       
  1519 
       
  1520             if (curr == Start())
       
  1521                 {
       
  1522                 SetStart(curr->Next());
       
  1523                 }
       
  1524             else
       
  1525                 {
       
  1526                 __ASSERT_DEBUG(prev != NULL, User::Invariant());
       
  1527                 prev->SetNext(curr->Next());
       
  1528                 }
       
  1529 
       
  1530             curr->Delete(aHeap);
       
  1531             aHeap->Free(curr);
       
  1532 
       
  1533             sem.Signal(KSessionCacheSemaphoreCount);
       
  1534             sem.Close();
       
  1535             return;
       
  1536             }
       
  1537         }
       
  1538     sem.Close();    
       
  1539 	}
  1223 	}
  1540 
  1224 
  1541 /** Delete all the items in the current session cache.
  1225 /** Delete all the items in the current session cache.
  1542 
  1226 
  1543 @param aHeap The heap base of the current process.
  1227 @param aHeap The heap base of the current process.
  1544  */
  1228  */
  1545 void COpenFontSessionCacheList::Delete(RHeap* aHeap)
  1229 void COpenFontSessionCacheList::Delete(RHeap* aHeap)
  1546 	{
  1230 	{
  1547     RSemaphore sem;
  1231 	for (TInt index = 0; index < EMaxNumCaches; ++index)
  1548     if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
  1232 		{
  1549         {
  1233 		if (iCacheOffsetArray[index] != 0)
  1550         RDebug::Print(_L("COpenFontSessionCacheList::Delete() can't open SessionCacheSemaphore"));
  1234 			{
  1551         return;
  1235 			COpenFontSessionCache* cache = reinterpret_cast<COpenFontSessionCache*>(PtrAdd(this, iCacheOffsetArray[index]));
  1552         }		
  1236 			cache->Delete(aHeap);
  1553     
  1237 			aHeap->Free(cache);
  1554 	COpenFontSessionCacheListItem* cur = Start();
  1238 			}
  1555 	COpenFontSessionCacheListItem* next = NULL;
  1239 		}
  1556 	
  1240 	Mem::FillZ(this, sizeof(COpenFontSessionCacheList));
  1557     for(TInt i=0; i<KSessionCacheSemaphoreCount; i++)
       
  1558      {
       
  1559 	//coverity[lock]
       
  1560 	//coverity[double_lock]
       
  1561      sem.Wait();     
       
  1562      }
       
  1563     
       
  1564 	while (cur != NULL)
       
  1565 		{
       
  1566 		next = cur->Next();
       
  1567 		cur->Delete(aHeap);
       
  1568 		aHeap->Free(cur);
       
  1569 		cur = next;
       
  1570 		}
       
  1571     sem.Signal(KSessionCacheSemaphoreCount);
       
  1572     sem.Close();
       
  1573 	}
  1241 	}
  1574 
  1242 
  1575 /**
  1243 /**
  1576 Delete all glyphs belonging to a particular font.
  1244 Delete all glyphs belonging to a particular font.
  1577 */
  1245 */
  1578 void COpenFontSessionCacheList::DeleteFontGlyphs(RHeap* aHeap, const COpenFont* aFont)
  1246 void COpenFontSessionCacheList::DeleteFontGlyphs(RHeap* aHeap, const COpenFont* aFont)
  1579 	{
  1247 	{
  1580     RSemaphore sem;
  1248 	for (TInt index = 0; index < EMaxNumCaches; ++index)
  1581     if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
  1249 		{
  1582         {
  1250 		if (iCacheOffsetArray[index] != 0)
  1583         RDebug::Print(_L("COpenFontSessionCacheList::DeleteFontGlyphs can't global open SessionCacheSemaphore"));
  1251 			{
  1584         return;
  1252 			COpenFontSessionCache* cache = reinterpret_cast<COpenFontSessionCache*>(PtrAdd(this, iCacheOffsetArray[index]));
  1585         }
  1253 			TInt numEntries = cache->iEntryArray.Count();
  1586     sem.Wait();      
  1254 			for (TInt i = 0; i < numEntries; ++i)
  1587 	for (COpenFontSessionCacheListItem* p = Start(); p; p = p->Next())
  1255 				{
  1588         {
  1256 				COpenFontSessionCacheEntry* entry = cache->iEntryArray[i];
  1589         COpenFontSessionCache* cache = p->Cache();
  1257 				if (entry != NULL && entry->Font() == aFont)
  1590         if (cache != NULL)
  1258 					{
  1591             {
  1259 					COpenFontSessionCacheEntry::Delete(aHeap, entry);
  1592             TInt entries = cache->iEntryArray.Count();
  1260 					cache->iEntryArray.SetAt(i, NULL);
  1593             for (TInt i = 0; i < entries; ++i)
  1261 					}
  1594                 {
  1262 				}
  1595                 COpenFontSessionCacheEntry* e = cache->iEntryArray[i];
  1263 			}
  1596                 if (e != NULL && e->Font() == aFont)
  1264         }
  1597                     {
       
  1598                     COpenFontSessionCacheEntry::Delete(aHeap, e);
       
  1599                     cache->iEntryArray.SetAt(i, NULL);
       
  1600                     }
       
  1601                 }
       
  1602             } //if(cache != NULL)
       
  1603         }
       
  1604 	sem.Signal();
       
  1605 	sem.Close();
       
  1606 	}
  1265 	}
  1607 
  1266 
  1608 /**
  1267 /**
  1609 C++ constructor with a CFont parameter.
  1268 C++ constructor with a CFont parameter.
  1610 
  1269