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()); |
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 |