fontservices/fontstore/src/FNTSTORE.CPP
branchRCL_3
changeset 11 6971d1c87c9a
parent 5 e96e8a131979
child 15 9a2be90ac9a2
equal deleted inserted replaced
5:e96e8a131979 11:6971d1c87c9a
    33 #include <graphics/openfontlinkedtypefaceextension.h>
    33 #include <graphics/openfontlinkedtypefaceextension.h>
    34 #include <graphics/openfontlinkedtypefacespecification.h>
    34 #include <graphics/openfontlinkedtypefacespecification.h>
    35 #include <graphics/openfontrasterizer.h>
    35 #include <graphics/openfontrasterizer.h>
    36 #include <graphics/openfontconstants.h>
    36 #include <graphics/openfontconstants.h>
    37 
    37 
    38 static const TUint32 KOutlineGlyphIdHashMask = 0x0000ffff;
       
    39 static const TUint32 KOutlineFileUidHashMask = 0x00ff0000;
       
    40 static const TUint32 KOutlineFaceIndexHashMask = 0x0f000000;
       
    41 static const TUint32 KOutlineFontPtrHashMask = 0x0fff0000;
       
    42 
    38 
    43 // uncomment to enable some verbose debug prints
    39 // uncomment to enable some verbose debug prints
    44 //#define VERBOSE_DEBUG 1
    40 //#define VERBOSE_DEBUG 1
    45 
    41 
    46 
    42 
  1109         return reinterpret_cast<CFontBitmap*>(reinterpret_cast<TInt>(this)+iFontBitmapOffset);
  1105         return reinterpret_cast<CFontBitmap*>(reinterpret_cast<TInt>(this)+iFontBitmapOffset);
  1110     else
  1106     else
  1111         return NULL;
  1107         return NULL;
  1112 	}
  1108 	}
  1113 
  1109 
  1114 /** Gets a font table.
       
  1115 @param aTag: Input. The name of the font table.
       
  1116 @param aTableContent: Output. To return the address of the table content.
       
  1117 @param aLength: Output. To return the length (in bytes) of the table.
       
  1118 @param aSessionHandle: Input. A handle to the session requesting this table.
       
  1119 @return KErrNone on success, specific error code on failure.
       
  1120 @internalTechnology
       
  1121 */
       
  1122 EXPORT_C TInt CBitmapFont::GetFontTable(TUint32 aTag, TAny *&aTableContent, 
       
  1123         TInt &aLength, TInt aSessionHandle) 
       
  1124     {
       
  1125     COpenFont *fontPtr = NULL;
       
  1126     if (IsOpenFont())
       
  1127         fontPtr = OpenFont();
       
  1128     else
       
  1129         return KErrNotSupported;
       
  1130     
       
  1131     // try to find it in cache.
       
  1132     CFontStore *fntStore = fontPtr->File()->GetFontStore();
       
  1133     TUid fileUid = fontPtr->File()->Uid();
       
  1134     TInt ret = fntStore->FindFontTableInCache(fileUid, aTag, aTableContent, aLength);
       
  1135     if (KErrNone == ret)
       
  1136         {
       
  1137         ret = fntStore->IncFontTableRefCount(fileUid, aTag, aSessionHandle);
       
  1138         return ret;
       
  1139         }
       
  1140     
       
  1141     // font table not found in cache.
       
  1142     ret = fontPtr->GetFontTable(aTag, aTableContent, aLength);
       
  1143     if (KErrNone == ret)
       
  1144         {
       
  1145         ret = fntStore->CacheFontTable(fileUid, aTag, aTableContent, aLength);
       
  1146         if (KErrNone == ret)
       
  1147             {
       
  1148             ret = fntStore->IncFontTableRefCount(fileUid, aTag, aSessionHandle);
       
  1149             }
       
  1150         else 
       
  1151             {
       
  1152             aTableContent = NULL;
       
  1153             }
       
  1154         }
       
  1155     
       
  1156     return ret;
       
  1157     }
       
  1158 
       
  1159 /** Release a font table. Decrement its reference count. Remove from cache if 
       
  1160  * reference decreases to zero.
       
  1161 @param aTag: Input. The name of the font table to be released.
       
  1162 @param aSessionHandle: Input. Handle to the session releasing this table.
       
  1163 @return KErrNone on success, specific error code on failure.
       
  1164 @internalTechnology
       
  1165 */
       
  1166 EXPORT_C void CBitmapFont::ReleaseFontTable(TUint32 aTag, 
       
  1167         TInt aSessionHandle)
       
  1168     {
       
  1169     COpenFont *fontPtr = NULL;
       
  1170     if (IsOpenFont())
       
  1171         fontPtr = OpenFont();
       
  1172     else
       
  1173         return;
       
  1174     
       
  1175     CFontStore *fntStore = fontPtr->File()->GetFontStore();
       
  1176     TUid fileUid = fontPtr->File()->Uid();
       
  1177     fntStore->ReleaseFontTable(fileUid, aTag, aSessionHandle);
       
  1178     }
       
  1179 
       
  1180 
       
  1181 /** Release a number of glyph outlines. Decrement their reference count.
       
  1182  * Remove it from cache if reference count decreases to zero.
       
  1183 @param aCount: Input. Number of outlines to be released.
       
  1184 @param aCodes: Input. An array of codes. Its interpretation depends on the parameter
       
  1185     'aIsGlyphId' (see below).
       
  1186 @param aIsGlyphId: Input. When aIsGlyphId==ETrue, 'aCodes' is an array of glyph ID's.
       
  1187     When aIsGlyphId==EFalse, 'aCodes' is an array of Unicode values.
       
  1188 @param aHinted: Input. To indicate if the outlines are hinted or unhinted.
       
  1189 @param aSessionHandle: Input. Handle to the session releasing the outlines.
       
  1190 @return KErrNone on success, specific error code on failure.
       
  1191 @internalTechnology
       
  1192 */
       
  1193 EXPORT_C void CBitmapFont::ReleaseGlyphOutlines(TInt aCount, const TUint *aCodes, 
       
  1194         TBool aHinted, TInt aSessionHandle)
       
  1195     {
       
  1196     COpenFont *fontPtr = NULL;
       
  1197         if (IsOpenFont())
       
  1198             fontPtr = OpenFont();
       
  1199         else
       
  1200             return;
       
  1201     
       
  1202     CFontStore *fontStore = fontPtr->File()->GetFontStore();
       
  1203     
       
  1204     for (TInt i = 0; i < aCount; ++i)
       
  1205         {
       
  1206         if (aHinted)
       
  1207             {
       
  1208             THintedOutlineId outlineId(fontPtr, aCodes[i]);
       
  1209             fontStore->ReleaseHintedOutline(outlineId, aSessionHandle);
       
  1210             }
       
  1211         else
       
  1212             {
       
  1213             TInt faceId = fontPtr->FaceIndex();
       
  1214             TUnhintedOutlineId outlineId(fontPtr->File()->Uid(), faceId, aCodes[i]);
       
  1215             fontStore->ReleaseUnhintedOutline(outlineId, aSessionHandle);
       
  1216             }
       
  1217         }
       
  1218     }
       
  1219 
       
  1220 /** Gets a font table.
       
  1221 @param aCode: Input. An glyph code. Its interpretation depends on the parameter
       
  1222     'aIsGlyphId' (see below).
       
  1223 @param aIsGlyphId: Input. When aIsGlyphId==ETrue, 'aCode' is a glyph ID.
       
  1224     When aIsGlyphId==EFalse, 'aCode' is a Unicode values.
       
  1225 @param aHinted: Input. To indicate if hinted or unhinted outline is needed.
       
  1226 @param aOutline: Output. A 'void*' pointer, pointing to the outline in memory.
       
  1227 @param aLength: Output. A TInt, recording the lenght (in bytes) of the outline.
       
  1228 @param aSessionHandle: Input. Handle to the session requesting this outline.
       
  1229 @return KErrNone on success, specific error code on failure.
       
  1230 @internalTechnology
       
  1231 */
       
  1232 EXPORT_C TInt CBitmapFont::GetGlyphOutline(TUint aCode, 
       
  1233         TBool aHinted, TAny *&aOutline, TInt &aLength, TInt aSessionHandle)
       
  1234     {
       
  1235     COpenFont *fontPtr = NULL;
       
  1236         if (IsOpenFont())
       
  1237             fontPtr = OpenFont();
       
  1238         else
       
  1239             return KErrNotSupported;
       
  1240     
       
  1241     CFontStore *fontStore = fontPtr->File()->GetFontStore();
       
  1242     TAny *outlineData = NULL; 
       
  1243     TInt len = KErrGeneral;
       
  1244     TInt ret = KErrNone;
       
  1245     if (!aHinted)
       
  1246         {
       
  1247         TInt faceId = fontPtr->FaceIndex();
       
  1248         TUnhintedOutlineId outlineId(fontPtr->File()->Uid(), faceId, aCode);
       
  1249         ret = fontStore->FindUnhintedOutlineInCache(outlineId, outlineData, len);
       
  1250         if (KErrNotFound == ret)
       
  1251             {
       
  1252             TAny* tmpOutline = 0; 
       
  1253             TInt tmpLen = 0;
       
  1254             ret = fontPtr->GetGlyphOutline(aCode, aHinted, tmpOutline, tmpLen);
       
  1255             if (KErrNone == ret)
       
  1256                 {
       
  1257                 fontStore->CacheUnhintedOutline(outlineId,
       
  1258                         tmpOutline, (TInt)tmpLen, outlineData, len);
       
  1259                 }
       
  1260             User::Free(tmpOutline);
       
  1261             }
       
  1262         if (KErrNone == ret)
       
  1263             {
       
  1264             fontStore->IncreaseUnhintedOutlineRefCount(outlineId, aSessionHandle);
       
  1265             }
       
  1266         }
       
  1267     else 
       
  1268         {
       
  1269         THintedOutlineId outlineId(fontPtr, aCode);
       
  1270         ret = fontStore->FindHintedOutlineInCache(outlineId, outlineData, len);
       
  1271         if (KErrNotFound == ret)
       
  1272             {
       
  1273             TAny* tmpOutline = 0; 
       
  1274             TInt tmpLen = 0;
       
  1275             ret = fontPtr->GetGlyphOutline(aCode, aHinted, tmpOutline, tmpLen);
       
  1276             if (KErrNone == ret)
       
  1277                 {
       
  1278                 fontStore->CacheHintedOutline(outlineId,
       
  1279                         tmpOutline, (TInt)tmpLen, outlineData, len);
       
  1280                 }
       
  1281             User::Free(tmpOutline);
       
  1282             }
       
  1283         if (KErrNone == ret)
       
  1284             {
       
  1285             fontStore->IncreaseHintedOutlineRefCount(outlineId, aSessionHandle);
       
  1286             }
       
  1287         }
       
  1288     
       
  1289     aOutline = outlineData;
       
  1290     aLength = len;    
       
  1291     return KErrNone;
       
  1292     }
       
  1293 
  1110 
  1294 EXPORT_C TUint32 CBitmapFont::UniqueFontId()
  1111 EXPORT_C TUint32 CBitmapFont::UniqueFontId()
  1295 	{
  1112 	{
  1296 	return iUniqueFontId;
  1113 	return iUniqueFontId;
  1297 	}
  1114 	}
  1336 		return Height(IsOpenFont() ? OpenFont()->FontLineGap() : FontBitmap()->FontLineGap());
  1153 		return Height(IsOpenFont() ? OpenFont()->FontLineGap() : FontBitmap()->FontLineGap());
  1337 		}
  1154 		}
  1338 	
  1155 	
  1339 	return CFont::DoExtendedFunction(aFunctionId, aParam);
  1156 	return CFont::DoExtendedFunction(aFunctionId, aParam);
  1340 	}
  1157 	}
  1341 
       
  1342 
       
  1343 CFontTableCacheItem::CFontTableCacheItem(TUid &aFileUid, const TUint32 aTag, 
       
  1344         TInt aOffset, TInt aLength): iFileUid(aFileUid), iTag(aTag),
       
  1345         iOffset(aOffset), iLength(aLength)
       
  1346     {
       
  1347     // a null constructor
       
  1348     }
       
  1349 
       
  1350 CFontTableCacheItem::~CFontTableCacheItem()
       
  1351     {
       
  1352     iUsers.ResetAndDestroy();
       
  1353     iUsers.Close();
       
  1354     }
       
  1355     
       
  1356 TBool CFontTableCacheItem::HasOutstandingRefCount()
       
  1357     {
       
  1358     TInt count = iUsers.Count();
       
  1359     for (TInt j = 0; j < count; ++j)
       
  1360         {
       
  1361         if (iUsers[j]->iRefCount > 0) 
       
  1362             {
       
  1363             return ETrue;
       
  1364             }
       
  1365         }
       
  1366     return EFalse;
       
  1367     }
       
  1368 
       
  1369 
       
  1370 TInt CFontTableCacheItem::FindUser(TInt aSessionHandle, TInt *id) 
       
  1371     {
       
  1372     TInt len = iUsers.Count();
       
  1373     for (TInt i = 0; i < len; ++i)
       
  1374         {
       
  1375         if (aSessionHandle == iUsers[i]->iSessionHandle)
       
  1376             {
       
  1377             *id = i;
       
  1378             return KErrNone;
       
  1379             }
       
  1380         }
       
  1381     return KErrNotFound;
       
  1382     }
       
  1383 
       
  1384 TInt CFontTableCacheItem::DecRefCount(TInt aSessionHandle)
       
  1385     {
       
  1386     TInt id = 0; 
       
  1387     TInt ret = FindUser(aSessionHandle, &id);
       
  1388     if (KErrNone == ret)
       
  1389         {
       
  1390         iUsers[id]->iRefCount--;
       
  1391         if (0 == iUsers[id]->iRefCount) 
       
  1392             {
       
  1393             delete iUsers[id];
       
  1394             iUsers.Remove(id);
       
  1395             }
       
  1396         return iUsers.Count();
       
  1397         }
       
  1398     return KErrNotFound;
       
  1399     }
       
  1400 
       
  1401 TInt CFontTableCacheItem::IncRefCount(TInt aSessionHandle)
       
  1402     {
       
  1403     TInt id = 0; 
       
  1404     TInt ret = FindUser(aSessionHandle, &id);
       
  1405     if (KErrNone == ret)
       
  1406         {
       
  1407         iUsers[id]->iRefCount++;
       
  1408         }
       
  1409     else
       
  1410         {
       
  1411         TCacheUserInfo *newUser = new TCacheUserInfo(aSessionHandle, 1);
       
  1412         if (NULL != newUser)
       
  1413             {
       
  1414             TRAP(ret, iUsers.AppendL(newUser));
       
  1415             }
       
  1416         else 
       
  1417             {
       
  1418             ret = KErrNoMemory;
       
  1419             }
       
  1420         //coverity[leaked_storage]
       
  1421         // The 'newUser' is kept in iUsers. It will be deleted in DecRefCount(). 
       
  1422         }
       
  1423     return ret;
       
  1424     }
       
  1425 
       
  1426 TInt CFontTableCache::Append(TUid aFileUid, TUint32 aTag, 
       
  1427         TAny *&aContent, TInt aLength) 
       
  1428     {
       
  1429     TInt ret = 0;
       
  1430     if ((TUint32)iCacheMemMon.GetMemUsage() >= KFontTable_GlyphOutline_CacheMaxMem)
       
  1431         {
       
  1432         RDebug::Printf("Table/Glyph cache full. Unable to add new item.");
       
  1433         return KErrNoMemory;
       
  1434         }
       
  1435     // make a copy of the table content on the shared heap.
       
  1436     TAny *sharedCopy = iHeap->Alloc(aLength);
       
  1437     if (NULL == sharedCopy) 
       
  1438         {
       
  1439         return KErrNoMemory;
       
  1440         }
       
  1441     
       
  1442     Mem::Copy(sharedCopy, aContent, aLength);
       
  1443 
       
  1444     CFontTableCacheItem *newItem = NULL;
       
  1445     TInt offset = PointerToOffset(sharedCopy, iHeap->Base());
       
  1446     TRAP(ret, newItem = new(ELeave) CFontTableCacheItem(aFileUid, aTag, offset, aLength));
       
  1447     if (KErrNone != ret)
       
  1448         {
       
  1449         iHeap->Free(sharedCopy);
       
  1450         return ret;
       
  1451         }
       
  1452     
       
  1453     TRAP(ret, iCacheItems.AppendL(newItem));
       
  1454     if (KErrNone == ret)
       
  1455         {
       
  1456         // do not free 'aContent', because the mem is managed by
       
  1457         // rasterizer cache.
       
  1458         aContent = sharedCopy;
       
  1459         iCacheMemMon.Inc(aLength);
       
  1460         }
       
  1461     else 
       
  1462         {
       
  1463         iHeap->Free(sharedCopy);
       
  1464         }
       
  1465 #ifdef _DEBUG
       
  1466     GetCacheState(__func__);
       
  1467 #endif
       
  1468     return ret;
       
  1469     }
       
  1470 
       
  1471 TInt CFontTableCache::Find(TUid aFileUid, TUint32 aTag, TAny *&aContent, 
       
  1472         TInt &aLength, TInt *id)
       
  1473     {
       
  1474     *id = KErrNotFound;
       
  1475     TInt len = iCacheItems.Count();
       
  1476     
       
  1477     TInt ret = KErrNotFound;
       
  1478     for (TInt i = 0; i < len; ++i)
       
  1479         {
       
  1480         CFontTableCacheItem *item = iCacheItems[i]; 
       
  1481         if (item->iFileUid == aFileUid && item->iTag == aTag) 
       
  1482             {
       
  1483             aContent = OffsetToPointer(item->iOffset, iHeap->Base());
       
  1484             aLength = item->iLength;
       
  1485             *id = i;
       
  1486             ret = KErrNone;
       
  1487             break;
       
  1488             }
       
  1489         }
       
  1490     
       
  1491 #ifdef _DEBUG
       
  1492     GetCacheState(__func__);
       
  1493 #endif
       
  1494     return ret;
       
  1495     }
       
  1496 
       
  1497 CFontTableCache::CFontTableCache(RHeap *aHeap, TFontTableGlyphOutlineCacheMemMonitor &aMon): 
       
  1498     iCacheMemMon(aMon), iHeap(aHeap) 
       
  1499     {
       
  1500     // null constructor
       
  1501     }
       
  1502 
       
  1503 CFontTableCache::~CFontTableCache()
       
  1504     {
       
  1505     for (TInt i = 0; i < iCacheItems.Count(); ++i)
       
  1506         {
       
  1507         iHeap->Free(OffsetToPointer(iCacheItems[i]->iOffset, iHeap->Base()));
       
  1508         }
       
  1509     iCacheItems.ResetAndDestroy();
       
  1510     iCacheItems.Close();
       
  1511     }
       
  1512 
       
  1513 TInt CFontTableCache::IncRefCount(TUid aFileUid, TUint32 aTag, TInt aSessionHandle)
       
  1514     {
       
  1515     TAny *outline = NULL;
       
  1516     TInt len = 0;
       
  1517     TInt id = 0;
       
  1518     
       
  1519     TInt ret = Find(aFileUid, aTag, outline, len, &id);
       
  1520     if (KErrNone == ret)
       
  1521         {
       
  1522         ret = iCacheItems[id]->IncRefCount(aSessionHandle);
       
  1523         }
       
  1524     
       
  1525 #ifdef _DEBUG
       
  1526     GetCacheState(__func__);
       
  1527 #endif
       
  1528     return ret;
       
  1529     }
       
  1530 
       
  1531 TInt CFontTableCache::DecRefCount(TUid aFileUid, TUint32 aTag, TInt aSessionHandle)
       
  1532     {
       
  1533     TAny *outline = NULL;
       
  1534     TInt len = 0;
       
  1535     TInt id = 0;
       
  1536     
       
  1537     TInt ret = Find(aFileUid, aTag, outline, len, &id);
       
  1538     if (KErrNone == ret) 
       
  1539         {
       
  1540         TInt numUsers = iCacheItems[id]->DecRefCount(aSessionHandle);
       
  1541         if (0 == numUsers) 
       
  1542             {
       
  1543             // There is no outstanding reference to the cache item.
       
  1544             iHeap->Free(outline);
       
  1545             iCacheMemMon.Dec(len);
       
  1546             delete (iCacheItems[id]);
       
  1547             iCacheItems.Remove(id);
       
  1548             }
       
  1549         }
       
  1550     
       
  1551 #ifdef _DEBUG
       
  1552     GetCacheState(__func__);
       
  1553 #endif
       
  1554     return ret;
       
  1555     }
       
  1556 
       
  1557 TBool CFontTableCache::HasOutstandingRefCount() 
       
  1558     {
       
  1559     TInt len = iCacheItems.Count();
       
  1560    
       
  1561     for (TInt i = 0; i < len; ++i)
       
  1562         {
       
  1563         if (iCacheItems[i]->HasOutstandingRefCount())
       
  1564             {
       
  1565             return ETrue;
       
  1566             }
       
  1567         }
       
  1568     return EFalse;
       
  1569     }
       
  1570 
       
  1571 TBool CFontTableCache::HasOutstandingRefCountWithUid(TUid aFileUid)
       
  1572     {
       
  1573     TInt len = iCacheItems.Count();
       
  1574    
       
  1575     for (TInt i = 0; i < len; ++i)
       
  1576         {
       
  1577         if (iCacheItems[i]->iFileUid == aFileUid) 
       
  1578             {
       
  1579             if (iCacheItems[i]->HasOutstandingRefCount())
       
  1580                 {
       
  1581                 return ETrue;
       
  1582                 }
       
  1583             }
       
  1584         }
       
  1585     return EFalse;
       
  1586     }
       
  1587 
       
  1588 void CFontTableCache::CleanupCacheOnOpenFontFileRemoval(COpenFontFile *)
       
  1589     {
       
  1590     // In CFontStore::RemoveFile(), a font file is not allowed to be removed if
       
  1591     // there are outstanding ref counts on any table in it. If that check passed 
       
  1592     // and this function is called, there shall be no cache item for that file.
       
  1593     
       
  1594     // Currently a cache item having a refcount of 0 is removed immediately.
       
  1595     // If this strategy is changed in the future, we may need to do some
       
  1596     // cleanup here.
       
  1597     }
       
  1598 
       
  1599 void CFontTableCache::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle)
       
  1600     {
       
  1601     TInt len = iCacheItems.Count();
       
  1602    
       
  1603     for (TInt i = 0; i < len; ++i)
       
  1604         {
       
  1605         TInt id = -1;
       
  1606         if (KErrNone == iCacheItems[i]->FindUser(aSessionHandle, &id))
       
  1607             {
       
  1608             iCacheItems[i]->iUsers.Remove(id);
       
  1609             if (iCacheItems[i]->iUsers.Count() == 0)
       
  1610                 {
       
  1611                 iHeap->Free(OffsetToPointer(iCacheItems[i]->iOffset, iHeap->Base()));
       
  1612                 iCacheMemMon.Dec(iCacheItems[i]->iLength);
       
  1613                 delete iCacheItems[i];
       
  1614                 iCacheItems.Remove(i);
       
  1615                 }
       
  1616             }
       
  1617         }
       
  1618     }
       
  1619 
       
  1620 
       
  1621 #ifdef _DEBUG
       
  1622 TInt CFontTableCache::GetCacheState(const char *func) 
       
  1623     {
       
  1624     RDebug::Printf("%s called from %s: ", __func__, func);
       
  1625     TBuf<256> buf;
       
  1626     
       
  1627     int len = iCacheItems.Count();
       
  1628     int numTables = 0, numSessions = 0, totalRef = 0;
       
  1629     buf.Append(_L("Table cache: "));
       
  1630     for (int i = 0; i < len; ++i)
       
  1631         {
       
  1632         ++numTables;
       
  1633         TInt abc = iCacheItems[i]->iUsers.Count();
       
  1634         numSessions += abc;
       
  1635         for (int j = 0; j < abc; ++j)
       
  1636             {
       
  1637             totalRef += iCacheItems[i]->iUsers[j]->iRefCount;
       
  1638             }
       
  1639         }
       
  1640     if (0 == iCacheItems.Count())
       
  1641         {
       
  1642         buf.Append(_L("cache empty. "));
       
  1643         }
       
  1644     else 
       
  1645         {
       
  1646         buf.AppendFormat(_L("%d tables referenced by %d sessions, total ref count %d"),
       
  1647                 numTables, numSessions, totalRef);
       
  1648         }
       
  1649     RDebug::RawPrint(buf);
       
  1650     return 0;
       
  1651     }
       
  1652 #endif
       
  1653 
       
  1654 
       
  1655 
       
  1656 TInt COutlineCacheItem::FindUser(TInt aSessionHandle, TInt *id) 
       
  1657     {
       
  1658     TInt len = iUsers.Count();
       
  1659     for (TInt i = 0; i < len; ++i)
       
  1660         {
       
  1661         if (aSessionHandle == iUsers[i]->iSessionHandle)
       
  1662             {
       
  1663             *id = i;
       
  1664             return KErrNone;
       
  1665             }
       
  1666         }
       
  1667     return KErrNotFound;
       
  1668     }
       
  1669 
       
  1670 COutlineCacheItem::~COutlineCacheItem() 
       
  1671     { 
       
  1672     iUsers.ResetAndDestroy(); 
       
  1673     }
       
  1674 
       
  1675 COutlineCacheItem::COutlineCacheItem(TInt aOffset, TInt aLength):
       
  1676     iOffset(aOffset), iLength(aLength)
       
  1677     {
       
  1678     // a null constructor.
       
  1679     }
       
  1680 
       
  1681 TInt COutlineCacheItem::DecRefCount(TInt aSessionHandle)
       
  1682     {
       
  1683     TInt id = 0; 
       
  1684     TInt ret = FindUser(aSessionHandle, &id);
       
  1685     if (KErrNone == ret)
       
  1686         {
       
  1687         iUsers[id]->iRefCount--;
       
  1688         if (0 == iUsers[id]->iRefCount) 
       
  1689             {
       
  1690             delete iUsers[id];
       
  1691             iUsers.Remove(id);
       
  1692             }
       
  1693         return iUsers.Count();
       
  1694         }
       
  1695     return KErrNotFound;
       
  1696     }
       
  1697 
       
  1698 TInt COutlineCacheItem::IncRefCount(TInt aSessionHandle)
       
  1699     {
       
  1700     TInt id = 0; 
       
  1701     TInt ret = FindUser(aSessionHandle, &id);
       
  1702     if (KErrNone == ret)
       
  1703         {
       
  1704         iUsers[id]->iRefCount++;
       
  1705         }
       
  1706     else
       
  1707         {
       
  1708         TCacheUserInfo *newUser = new TCacheUserInfo(aSessionHandle, 1);
       
  1709         if (NULL != newUser)
       
  1710             {
       
  1711             TRAP(ret, iUsers.AppendL(newUser));
       
  1712             }
       
  1713         else 
       
  1714             {
       
  1715             ret = KErrNoMemory;
       
  1716             }
       
  1717         //coverity[leaked_storage]
       
  1718         // The 'newUser' is kept in iUsers. It will be deleted in DecRefCount().
       
  1719         }
       
  1720     return ret;
       
  1721     }
       
  1722 
       
  1723 #ifdef _DEBUG
       
  1724 TInt CUnhintedOutlineCache::GetCacheState(const char *func)
       
  1725     {
       
  1726     RDebug::Printf("%s called from %s: ", __func__, func);
       
  1727     int numSessions = 0, totalRef = 0;
       
  1728     THashMapIter<TUnhintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
       
  1729     it.NextValue();
       
  1730     while (it.CurrentValue())
       
  1731         {
       
  1732         COutlineCacheItem **data = it.CurrentValue();
       
  1733         int len = (*data)->iUsers.Count();
       
  1734         numSessions += len;
       
  1735         for (int j = 0; j < len; ++j)
       
  1736             {
       
  1737             totalRef += (*data)->iUsers[j]->iRefCount;
       
  1738             }
       
  1739         it.NextValue();
       
  1740         }
       
  1741     
       
  1742     TBuf<256> buf;
       
  1743     buf.Append(_L("Unhinted outline cache: "));
       
  1744     TInt numItems = iItemIdMap.Count();
       
  1745     if (0 == numItems)
       
  1746         {
       
  1747         buf.Append(_L("empty. "));
       
  1748         }
       
  1749     else 
       
  1750         {
       
  1751         buf.AppendFormat(_L("%d glyphs, %d sessions, total refcount %d"),
       
  1752                 numItems, numSessions, totalRef);
       
  1753         }
       
  1754         
       
  1755     RDebug::RawPrint(buf);
       
  1756             
       
  1757     return 0;
       
  1758     }
       
  1759 #endif
       
  1760 
       
  1761 CUnhintedOutlineCache::CUnhintedOutlineCache(RHeap *aHeap, TFontTableGlyphOutlineCacheMemMonitor &aMon):
       
  1762     iCacheMemMon(aMon), iHeap(aHeap), 
       
  1763     iItemIdMap(THashFunction32<TUnhintedOutlineId>(CUnhintedOutlineCache::IdHash),
       
  1764         TIdentityRelation<TUnhintedOutlineId>(CUnhintedOutlineCache::IdIdentity))
       
  1765     { 
       
  1766     
       
  1767     }
       
  1768 
       
  1769 CUnhintedOutlineCache::~CUnhintedOutlineCache()
       
  1770     {
       
  1771     THashMapIter<TUnhintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
       
  1772     it.NextValue();
       
  1773     while (it.CurrentValue())
       
  1774         {
       
  1775         const TUnhintedOutlineId *outlineId = it.CurrentKey();
       
  1776         COutlineCacheItem **data = it.CurrentValue();
       
  1777         
       
  1778         // loop body here!
       
  1779         iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
       
  1780         delete (*data);
       
  1781         iItemIdMap.Remove(*outlineId);
       
  1782         // end loop body
       
  1783         
       
  1784         it.NextValue();
       
  1785         }
       
  1786     return;
       
  1787     }
       
  1788 
       
  1789 
       
  1790 TInt CUnhintedOutlineCache::CleanupCacheOnOpenFontFileRemoval(COpenFontFile *aFontFile)
       
  1791     {
       
  1792     TUid fileUid = aFontFile->Uid();
       
  1793     
       
  1794     THashMapIter<TUnhintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
       
  1795     it.NextValue();
       
  1796     while (it.CurrentValue())
       
  1797         {
       
  1798         const TUnhintedOutlineId *outlineId = it.CurrentKey();
       
  1799         COutlineCacheItem **data = it.CurrentValue();
       
  1800         
       
  1801         // loop body here!
       
  1802         if (outlineId->iFileUid == fileUid)
       
  1803             {
       
  1804             iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
       
  1805             iCacheMemMon.Dec((*data)->iLength);
       
  1806             delete (*data);
       
  1807             iItemIdMap.Remove(*outlineId);
       
  1808             }
       
  1809         // end loop body
       
  1810         
       
  1811         it.NextValue();
       
  1812         }
       
  1813     return KErrNone;
       
  1814     }
       
  1815 
       
  1816 TInt CUnhintedOutlineCache::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle)
       
  1817     {
       
  1818     THashMapIter<TUnhintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
       
  1819     it.NextValue();
       
  1820     while (it.CurrentValue())
       
  1821         {
       
  1822         const TUnhintedOutlineId *outlineId = it.CurrentKey();
       
  1823         COutlineCacheItem **data = it.CurrentValue();
       
  1824         
       
  1825         // loop body here!
       
  1826         TInt id = 0;
       
  1827         TInt ret = (*data)->FindUser(aSessionHandle, &id);
       
  1828         if (KErrNone == ret)
       
  1829             {
       
  1830             delete (*data)->iUsers[id];
       
  1831             (*data)->iUsers.Remove(id);
       
  1832             if (0 == (*data)->iUsers.Count())
       
  1833                 {
       
  1834                 iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
       
  1835                 iCacheMemMon.Dec((*data)->iLength);
       
  1836                 delete (*data);
       
  1837                 iItemIdMap.Remove(*outlineId);
       
  1838                 }
       
  1839             }
       
  1840         // end loop body
       
  1841         
       
  1842         it.NextValue();
       
  1843         }
       
  1844     return KErrNone;
       
  1845     }
       
  1846 
       
  1847 
       
  1848 TInt CUnhintedOutlineCache::CacheUnhintedOutline(const TUnhintedOutlineId &aOutlineId, 
       
  1849         TAny* const aData, const TInt aLength, TAny *&aOutline, TInt &aLen)
       
  1850     {
       
  1851 #ifdef _DEBUG
       
  1852     GetCacheState(__func__);
       
  1853 #endif
       
  1854     if ((TUint32)iCacheMemMon.GetMemUsage() >= KFontTable_GlyphOutline_CacheMaxMem)
       
  1855         {
       
  1856         RDebug::Printf("Table/Glyph cache full. Unable to add new item.");
       
  1857         return KErrNoMemory;
       
  1858         }
       
  1859     
       
  1860     aLen = KErrGeneral;
       
  1861     TInt ret1= KErrNone;
       
  1862 
       
  1863     // make a copy of the outline data on the shared heap.
       
  1864     TAny *sharedCopy = iHeap->Alloc(aLength);
       
  1865     if (NULL == sharedCopy) 
       
  1866         {
       
  1867         return KErrNoMemory;
       
  1868         }
       
  1869     
       
  1870     Mem::Copy(sharedCopy, aData, aLength);
       
  1871 
       
  1872     COutlineCacheItem *newItem = NULL;
       
  1873     TInt offset = PointerToOffset(sharedCopy, iHeap->Base());
       
  1874     TRAP(ret1, newItem = new(ELeave) COutlineCacheItem(offset, aLength));
       
  1875     if (KErrNone != ret1)
       
  1876         {
       
  1877         iHeap->Free(sharedCopy);
       
  1878         sharedCopy = NULL;
       
  1879         }
       
  1880     else 
       
  1881         {
       
  1882         TRAP(ret1, iItemIdMap.InsertL(aOutlineId, newItem));
       
  1883         if (KErrNone != ret1)
       
  1884             {
       
  1885             delete newItem;
       
  1886             iHeap->Free(sharedCopy);
       
  1887             sharedCopy = NULL;
       
  1888             }
       
  1889         else
       
  1890             {
       
  1891             iCacheMemMon.Inc(aLength);
       
  1892             aLen = aLength;
       
  1893             }
       
  1894         }
       
  1895     aOutline = sharedCopy;
       
  1896     return ret1;  
       
  1897     }
       
  1898 
       
  1899 TInt CUnhintedOutlineCache::IncRefCount(const TUnhintedOutlineId &aOutlineId,
       
  1900         TInt aSessionHandle)
       
  1901     {
       
  1902 #ifdef _DEBUG
       
  1903     GetCacheState(__func__);
       
  1904 #endif
       
  1905     COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId);
       
  1906     if (NULL != ret)
       
  1907         {
       
  1908         (*ret)->IncRefCount(aSessionHandle);
       
  1909         }
       
  1910     return (NULL==ret?KErrNotFound:KErrNone);
       
  1911     }
       
  1912 
       
  1913 TInt CUnhintedOutlineCache::DecRefCount(const TUnhintedOutlineId &aOutlineId,
       
  1914         TInt aSessionHandle)
       
  1915     {
       
  1916 #ifdef _DEBUG
       
  1917     GetCacheState(__func__);
       
  1918 #endif
       
  1919     COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId); 
       
  1920     if (NULL != ret) 
       
  1921         {
       
  1922         TInt numUsers = (*ret)->DecRefCount(aSessionHandle);
       
  1923         if (0 == numUsers) 
       
  1924             {
       
  1925             // There is no outstanding reference to the cache item.
       
  1926             iHeap->Free(OffsetToPointer((*ret)->iOffset, iHeap->Base()));
       
  1927             iCacheMemMon.Dec((*ret)->iLength);
       
  1928             delete (*ret);
       
  1929             iItemIdMap.Remove(aOutlineId);
       
  1930             }
       
  1931         }
       
  1932     return (NULL==ret?KErrNotFound:KErrNone);
       
  1933     }
       
  1934 
       
  1935 TInt CUnhintedOutlineCache::Find(const TUnhintedOutlineId &aOutlineId, TAny *&aData, 
       
  1936         TInt &aLength)
       
  1937     {
       
  1938     COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId);
       
  1939     TInt ret2 = KErrNone;
       
  1940     if (NULL != ret)
       
  1941         {
       
  1942         aData = OffsetToPointer((*ret)->iOffset, iHeap->Base());
       
  1943         aLength = (*ret)->iLength;
       
  1944         }
       
  1945     else
       
  1946         {
       
  1947         ret2 = KErrNotFound;
       
  1948         }
       
  1949     return ret2;
       
  1950     }
       
  1951     
       
  1952   
       
  1953 TUint32 CUnhintedOutlineCache::IdHash(const TUnhintedOutlineId &outlineId)
       
  1954     {
       
  1955     // The hash value: 
       
  1956     // bits 0-15: glyph id; 
       
  1957     // bits 16-23: lower 8 bit of font file uid
       
  1958     // bits 24-27: lower 4 bit of the face index
       
  1959     // bit 28: 'isGlyphId'
       
  1960     TUint32 ret = 0;
       
  1961     ret |= (outlineId.iId & KOutlineGlyphIdHashMask);
       
  1962     ret |= (KOutlineFileUidHashMask & (outlineId.iFileUid.iUid << 16));
       
  1963     ret |= (KOutlineFaceIndexHashMask & (outlineId.iFaceIndex << 24));
       
  1964     ret = (ret % 701);
       
  1965     return ret;
       
  1966     }
       
  1967 
       
  1968 TBool CUnhintedOutlineCache::IdIdentity(const TUnhintedOutlineId &id1, const TUnhintedOutlineId &id2)
       
  1969     {
       
  1970     return id1.iId == id2.iId && id1.iFaceIndex == id2.iFaceIndex &&
       
  1971             id1.iFileUid == id2.iFileUid;
       
  1972     }
       
  1973 
       
  1974 // hinted outline cache
       
  1975 #ifdef _DEBUG
       
  1976 TInt CHintedOutlineCache::GetCacheState(const char *func)
       
  1977     {
       
  1978     RDebug::Printf("%s called from %s: ", __func__, func);
       
  1979     int numSessions = 0, totalRef = 0;
       
  1980     THashMapIter<THintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
       
  1981     it.NextValue();
       
  1982     while (it.CurrentValue())
       
  1983         {
       
  1984         COutlineCacheItem **data = it.CurrentValue();
       
  1985         int len = (*data)->iUsers.Count();
       
  1986         numSessions += len;
       
  1987         for (int j = 0; j < len; ++j)
       
  1988             {
       
  1989             totalRef += (*data)->iUsers[j]->iRefCount;
       
  1990             }
       
  1991         it.NextValue();
       
  1992         }
       
  1993     
       
  1994     TBuf<256> buf;
       
  1995     buf.Append(_L("Hinted outline cache: "));
       
  1996     TInt numItems = iItemIdMap.Count();
       
  1997     if (0 == numItems)
       
  1998         {
       
  1999         buf.Append(_L("empty. "));
       
  2000         }
       
  2001     else 
       
  2002         {
       
  2003         buf.AppendFormat(_L("%d glyphs, %d sessions, total refcount %d"),
       
  2004                 numItems, numSessions, totalRef);
       
  2005         }
       
  2006         
       
  2007     RDebug::RawPrint(buf);
       
  2008             
       
  2009     return 0;
       
  2010     }
       
  2011 #endif
       
  2012 
       
  2013 TInt CHintedOutlineCache::CleanupCacheOnOpenFontRemoval(COpenFont *aFont)
       
  2014     {
       
  2015     THashMapIter<THintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
       
  2016     it.NextValue();
       
  2017     while (it.CurrentValue())
       
  2018         {
       
  2019         const THintedOutlineId *outlineId = it.CurrentKey();
       
  2020         COutlineCacheItem **data = it.CurrentValue();
       
  2021         
       
  2022         // loop body here!
       
  2023         if (outlineId->iFont == aFont)
       
  2024             {
       
  2025             iCacheMemMon.Dec((*data)->iLength);
       
  2026             iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
       
  2027             delete (*data);
       
  2028             iItemIdMap.Remove(*outlineId);
       
  2029             }
       
  2030         // end loop body
       
  2031         
       
  2032         it.NextValue();
       
  2033         }
       
  2034     return KErrNone;
       
  2035     }
       
  2036 
       
  2037 TInt CHintedOutlineCache::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle)
       
  2038     {
       
  2039     THashMapIter<THintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
       
  2040     it.NextValue();
       
  2041     while (it.CurrentValue())
       
  2042         {
       
  2043         const THintedOutlineId *outlineId = it.CurrentKey();
       
  2044         COutlineCacheItem **data = it.CurrentValue();
       
  2045         
       
  2046         // loop body here!
       
  2047         TInt id = 0; 
       
  2048         TInt ret = (*data)->FindUser(aSessionHandle, &id);
       
  2049         if (KErrNone == ret)
       
  2050             {
       
  2051             delete (*data)->iUsers[id];
       
  2052             (*data)->iUsers.Remove(id);
       
  2053             if (0 == (*data)->iUsers.Count())
       
  2054                 {
       
  2055                 iCacheMemMon.Dec((*data)->iLength);
       
  2056                 iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
       
  2057                 delete (*data);
       
  2058                 iItemIdMap.Remove(*outlineId);
       
  2059                 }
       
  2060             }
       
  2061         // end loop body
       
  2062         
       
  2063         it.NextValue();
       
  2064         }
       
  2065 
       
  2066     return KErrNone;
       
  2067     }
       
  2068 
       
  2069 
       
  2070 CHintedOutlineCache::CHintedOutlineCache(RHeap *aHeap, TFontTableGlyphOutlineCacheMemMonitor &aMon):
       
  2071     iCacheMemMon(aMon), iHeap(aHeap), 
       
  2072     iItemIdMap(THashFunction32<THintedOutlineId>(CHintedOutlineCache::IdHash),
       
  2073         TIdentityRelation<THintedOutlineId>(CHintedOutlineCache::IdIdentity)) 
       
  2074     { 
       
  2075     // a null constructor
       
  2076     }
       
  2077 
       
  2078 TInt CHintedOutlineCache::CacheHintedOutline(const THintedOutlineId &aOutlineId,
       
  2079         TAny* aData, TInt aLength, TAny *&aOutline, TInt &aLen)
       
  2080     {
       
  2081 #ifdef _DEBUG
       
  2082     GetCacheState(__func__);
       
  2083 #endif
       
  2084     if ((TUint32)iCacheMemMon.GetMemUsage() >= KFontTable_GlyphOutline_CacheMaxMem)
       
  2085         {
       
  2086         RDebug::Printf("Table/Glyph cache full. Unable to add new item.");
       
  2087         return KErrNoMemory;
       
  2088         }
       
  2089     
       
  2090     aLen = KErrGeneral;
       
  2091     TInt ret = KErrNone;
       
  2092     // make a copy of the outline data on the shared heap.
       
  2093     TAny *sharedCopy = iHeap->Alloc(aLength);
       
  2094     if (NULL == sharedCopy) 
       
  2095         {
       
  2096         return KErrNoMemory;
       
  2097         }
       
  2098     
       
  2099     Mem::Copy(sharedCopy, aData, aLength);
       
  2100 
       
  2101     COutlineCacheItem *newItem = NULL;
       
  2102     TInt offset = PointerToOffset(sharedCopy, iHeap->Base());
       
  2103     TRAP(ret, newItem = new(ELeave) COutlineCacheItem(offset, aLength));
       
  2104     if (KErrNone != ret)
       
  2105         {
       
  2106         iHeap->Free(sharedCopy);
       
  2107         sharedCopy = NULL;
       
  2108         }
       
  2109     else 
       
  2110         {
       
  2111         TRAP(ret, iItemIdMap.InsertL(aOutlineId, newItem));
       
  2112         if (KErrNone != ret)
       
  2113             {
       
  2114             delete newItem;
       
  2115             iHeap->Free(sharedCopy);
       
  2116             sharedCopy = NULL;
       
  2117             }
       
  2118         else
       
  2119             {
       
  2120             iCacheMemMon.Inc(aLength);
       
  2121             aLen = aLength;
       
  2122             }
       
  2123         }
       
  2124     aOutline = sharedCopy;
       
  2125     return ret;
       
  2126     }
       
  2127 
       
  2128 TInt CHintedOutlineCache::IncRefCount(const THintedOutlineId &aOutlineId, 
       
  2129         TInt aSessionHandle)
       
  2130     {
       
  2131 #ifdef _DEBUG
       
  2132     GetCacheState(__func__);
       
  2133 #endif
       
  2134     COutlineCacheItem **data = iItemIdMap.Find(aOutlineId);
       
  2135     if (NULL != data)
       
  2136         {
       
  2137         (*data)->IncRefCount(aSessionHandle);
       
  2138         }
       
  2139     return (NULL==data?KErrNotFound:KErrNone);
       
  2140     }
       
  2141 
       
  2142 TInt CHintedOutlineCache::DecRefCount(const THintedOutlineId &aOutlineId,
       
  2143         TInt aSessionHandle)
       
  2144     {
       
  2145 #ifdef _DEBUG
       
  2146     GetCacheState(__func__);
       
  2147 #endif
       
  2148     COutlineCacheItem **data = iItemIdMap.Find(aOutlineId);
       
  2149     if (NULL != data) 
       
  2150         {
       
  2151         TInt numUsers = (*data)->DecRefCount(aSessionHandle);
       
  2152         if (0 == numUsers) 
       
  2153             {
       
  2154             // There is no outstanding reference to the cache item.
       
  2155             iCacheMemMon.Dec((*data)->iLength);
       
  2156             iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
       
  2157             delete (*data);
       
  2158             iItemIdMap.Remove(aOutlineId);
       
  2159             }
       
  2160         }
       
  2161     return (NULL==data?KErrNotFound:KErrNone);
       
  2162     }
       
  2163 
       
  2164 TInt CHintedOutlineCache::Find(const THintedOutlineId &aOutlineId, 
       
  2165         TAny *&aData, TInt &aLength)
       
  2166     {
       
  2167     COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId);
       
  2168     TInt ret2 = KErrNone;
       
  2169     if (NULL != ret)
       
  2170         {
       
  2171         aData = OffsetToPointer((*ret)->iOffset, iHeap->Base());
       
  2172         aLength = (*ret)->iLength;
       
  2173         }
       
  2174     else
       
  2175         {
       
  2176         ret2 = KErrNotFound;
       
  2177         }
       
  2178     return ret2;
       
  2179     }
       
  2180 
       
  2181 
       
  2182 TUint32 CHintedOutlineCache::IdHash(const THintedOutlineId &outlineId)
       
  2183     {
       
  2184     // The hash value:
       
  2185     // bits 0-15: the outline id
       
  2186     // bits 16-27: the lower 12 bits of the font pointer
       
  2187     // bit 28: 'isGlyphId'
       
  2188     
       
  2189     TUint32 ret = 0;
       
  2190     ret |= (KOutlineGlyphIdHashMask & outlineId.iId);
       
  2191     ret |= (KOutlineFontPtrHashMask & (((TUint32)outlineId.iFont) << 16));
       
  2192     ret = ret % 701;
       
  2193     return ret;
       
  2194     }
       
  2195 
       
  2196 TBool CHintedOutlineCache::IdIdentity(const THintedOutlineId &id1, const THintedOutlineId &id2)
       
  2197     {
       
  2198     return id1.iId == id2.iId && id1.iFont == id2.iFont;
       
  2199     }
       
  2200 // hinted cache
       
  2201 
  1158 
  2202 
  1159 
  2203 CFontStore::CFontStore(RHeap* aHeap):
  1160 CFontStore::CFontStore(RHeap* aHeap):
  2204 	iKPixelWidthInTwips(KDefaultPixelWidthInTwips),
  1161 	iKPixelWidthInTwips(KDefaultPixelWidthInTwips),
  2205 	iKPixelHeightInTwips(KDefaultPixelHeightInTwips),
  1162 	iKPixelHeightInTwips(KDefaultPixelHeightInTwips),
  2259 	if (twipSize.iWidth > 0 && pixelSize.iWidth > 0)
  1216 	if (twipSize.iWidth > 0 && pixelSize.iWidth > 0)
  2260 		iKPixelWidthInTwips = twipSize.iWidth * 1000 / pixelSize.iWidth;
  1217 		iKPixelWidthInTwips = twipSize.iWidth * 1000 / pixelSize.iWidth;
  2261 
  1218 
  2262 	if (twipSize.iHeight > 0 && pixelSize.iHeight > 0)
  1219 	if (twipSize.iHeight > 0 && pixelSize.iHeight > 0)
  2263 		iKPixelHeightInTwips = twipSize.iHeight * 1000 / pixelSize.iHeight;
  1220 		iKPixelHeightInTwips = twipSize.iHeight * 1000 / pixelSize.iHeight;
  2264 	
       
  2265 	iCacheMemMon = new(ELeave) TFontTableGlyphOutlineCacheMemMonitor;
       
  2266 	iUnhintedOutlineCache = new(ELeave) CUnhintedOutlineCache(iHeap, *iCacheMemMon);
       
  2267 	iHintedOutlineCache = new(ELeave) CHintedOutlineCache(iHeap, *iCacheMemMon);
       
  2268 	iFontTableCache = new(ELeave) CFontTableCache(iHeap, *iCacheMemMon);
       
  2269 	
       
  2270 	}
  1221 	}
  2271 
  1222 
  2272 /** Creates a new CFontStore object.
  1223 /** Creates a new CFontStore object.
  2273 
  1224 
  2274 Sets iKPixelWidthInTwips and iKPixelHeightInTwips.
  1225 Sets iKPixelWidthInTwips and iKPixelHeightInTwips.
  2309             }
  1260             }
  2310         iHandleArray->Close();
  1261         iHandleArray->Close();
  2311         delete iHandleArray;
  1262         delete iHandleArray;
  2312         }
  1263         }
  2313 	iFs.Close();
  1264 	iFs.Close();
  2314 	
       
  2315     delete iFontTableCache;
       
  2316     delete iUnhintedOutlineCache;
       
  2317     delete iHintedOutlineCache;
       
  2318     delete iCacheMemMon;
       
  2319 	}
  1265 	}
  2320 
  1266 
  2321 
  1267 
  2322 // local utility functions
  1268 // local utility functions
  2323 // reads bytes from file, if the requested number of bytes are not available it leaves
  1269 // reads bytes from file, if the requested number of bytes are not available it leaves
  2793 			TInt count = iFontAccess->Count();		
  1739 			TInt count = iFontAccess->Count();		
  2794 			for (TInt i = 0; i < count; i++)
  1740 			for (TInt i = 0; i < count; i++)
  2795 				if((*iFontAccess)[i].iAccessCount)
  1741 				if((*iFontAccess)[i].iAccessCount)
  2796 					return;
  1742 					return;
  2797 			}
  1743 			}
  2798 		if (iFontTableCache && iFontTableCache->HasOutstandingRefCount())
       
  2799 		    {
       
  2800 		    // disallow font file removal if any font tables are still cached
       
  2801 		    return;
       
  2802 		    }
       
  2803 		
  1744 		
  2804 		iTypefaceList.ResetAndDestroy();
  1745 		iTypefaceList.ResetAndDestroy();
  2805 		count = iFontBitmapList.Count();
  1746 		count = iFontBitmapList.Count();
  2806 		for (TInt i = 0; i < count; i++)
  1747 		for (TInt i = 0; i < count; i++)
  2807 			iFontBitmapList[i]->Release();
  1748 			iFontBitmapList[i]->Release();
  2832 		  	  	  			if ((*iFontAccess)[kk].iAccessCount > 0) 
  1773 		  	  	  			if ((*iFontAccess)[kk].iAccessCount > 0) 
  2833 		  	  	  				return; // Outstanding reference found, so ignoring file removal request
  1774 		  	  	  				return; // Outstanding reference found, so ignoring file removal request
  2834 		  	  	  			}
  1775 		  	  	  			}
  2835 						}
  1776 						}
  2836 					} // Safe to proceed with removing file
  1777 					} // Safe to proceed with removing file
  2837 				// also check if there are outstanding references to any 
       
  2838 				// table in that file.
       
  2839 				if (iFontTableCache && iFontTableCache->HasOutstandingRefCountWithUid(aFileUid))
       
  2840 				    {
       
  2841 				    return; // outstanding reference to font table found.
       
  2842 				    }
       
  2843 				
       
  2844 				// Safe to proceed with removing file
       
  2845 				if (iOpenFontFileList[i]->DecRefCount())
  1778 				if (iOpenFontFileList[i]->DecRefCount())
  2846 					{ // unload the font file
  1779 					{ // unload the font file
  2847 					RemoveTypefacesFromSupportList(iOpenFontFileList[i]);
  1780 					RemoveTypefacesFromSupportList(iOpenFontFileList[i]);
  2848 					//linked fonts deleted from this destructor
  1781 					//linked fonts deleted from this destructor
  2849 					delete iOpenFontFileList[i];
  1782 					delete iOpenFontFileList[i];
  4899 			}
  3832 			}
  4900 		}
  3833 		}
  4901 	return EFalse;	
  3834 	return EFalse;	
  4902 	}
  3835 	}
  4903 
  3836 
  4904 TInt CFontStore::CacheFontTable(TUid aFileUid, TUint32 aTag, 
       
  4905         TAny *&aContent, TInt aLength)
       
  4906     {
       
  4907     return iFontTableCache->Append(aFileUid, aTag, aContent, aLength);
       
  4908     }
       
  4909 
       
  4910 TInt CFontStore::FindFontTableInCache(TUid aFileUid, TUint32 aTag, 
       
  4911         TAny *&aContent, TInt &aLength)
       
  4912     {
       
  4913     TInt id;
       
  4914     return iFontTableCache->Find(aFileUid, aTag, aContent, aLength, &id);
       
  4915     }
       
  4916 
       
  4917 TInt CFontStore::IncreaseUnhintedOutlineRefCount(const TUnhintedOutlineId &aOutlineId, 
       
  4918         TInt aSessionHandle)
       
  4919     {
       
  4920     return iUnhintedOutlineCache->IncRefCount(aOutlineId, aSessionHandle);
       
  4921     }
       
  4922 
       
  4923 TInt CFontStore::IncreaseHintedOutlineRefCount(const THintedOutlineId &aOutlineId,
       
  4924         TInt aSessionHandle)
       
  4925     {
       
  4926     return iHintedOutlineCache->IncRefCount(aOutlineId, aSessionHandle);
       
  4927     }
       
  4928 
       
  4929 TInt CFontStore::IncFontTableRefCount(TUid aFileUid, TUint32 aTag, 
       
  4930         TInt aSessionHandle)
       
  4931     {
       
  4932     return iFontTableCache->IncRefCount(aFileUid, aTag, aSessionHandle);
       
  4933     }
       
  4934 
       
  4935 TInt CFontStore::DecFontTableRefCount(TUid aFileUid, TUint32 aTag, 
       
  4936         TInt aSessionHandle)
       
  4937     {
       
  4938     return iFontTableCache->DecRefCount(aFileUid, aTag, aSessionHandle);
       
  4939     }
       
  4940 
       
  4941 TInt CFontStore::CacheUnhintedOutline(const TUnhintedOutlineId &aOutlineId, TAny * aData, 
       
  4942         TInt aLength, TAny *&aOutline, TInt &aLen)
       
  4943     {
       
  4944     return iUnhintedOutlineCache->CacheUnhintedOutline(aOutlineId, aData, aLength, 
       
  4945             aOutline, aLen);
       
  4946     }
       
  4947 
       
  4948 TInt CFontStore::CacheHintedOutline(const THintedOutlineId &aOutlineId,
       
  4949         TAny * aData, TInt aLength, TAny *&aOutline, TInt &aLen)
       
  4950     {
       
  4951     return iHintedOutlineCache->CacheHintedOutline(aOutlineId, aData, aLength,
       
  4952             aOutline, aLen);
       
  4953     }
       
  4954 
       
  4955 TInt CFontStore::ReleaseUnhintedOutline(const TUnhintedOutlineId &aOutlineId, 
       
  4956         TInt aSessionHandle)
       
  4957     {
       
  4958     return iUnhintedOutlineCache->DecRefCount(aOutlineId, aSessionHandle);    
       
  4959     }
       
  4960 
       
  4961 TInt CFontStore::ReleaseHintedOutline(const THintedOutlineId &aOutlineId,
       
  4962         TInt aSessionHandle)
       
  4963     {
       
  4964     return iHintedOutlineCache->DecRefCount(aOutlineId, aSessionHandle);    
       
  4965     }
       
  4966 
       
  4967 TInt CFontStore::ReleaseFontTable(TUid aFileUid, TUint32 aTag, 
       
  4968         TInt aSessionHandle)
       
  4969     {
       
  4970     return iFontTableCache->DecRefCount(aFileUid, aTag, aSessionHandle);
       
  4971     }
       
  4972 
       
  4973 TInt CFontStore::FindUnhintedOutlineInCache(const TUnhintedOutlineId &aOutlineId, TAny *&aData, 
       
  4974         TInt &aLength)
       
  4975     {
       
  4976     return iUnhintedOutlineCache->Find(aOutlineId, aData, aLength);
       
  4977     }
       
  4978 
       
  4979 TInt CFontStore::FindHintedOutlineInCache(const THintedOutlineId &aOutlineId, 
       
  4980         TAny *&aData, TInt &aLength)
       
  4981     {
       
  4982     return iHintedOutlineCache->Find(aOutlineId, aData, aLength);
       
  4983     }
       
  4984 
       
  4985 void CFontStore::CleanupCacheOnOpenFontRemoval(COpenFont *aFont)
       
  4986     {
       
  4987     iHintedOutlineCache->CleanupCacheOnOpenFontRemoval(aFont);
       
  4988     //iUnhintedOutlineCache.OnOpenFontRemoval(aFont);
       
  4989     }
       
  4990 
       
  4991 void CFontStore::CleanupCacheOnOpenFontFileRemoval(COpenFontFile *aFontFile) 
       
  4992     {
       
  4993     iUnhintedOutlineCache->CleanupCacheOnOpenFontFileRemoval(aFontFile);
       
  4994     iFontTableCache->CleanupCacheOnOpenFontFileRemoval(aFontFile);
       
  4995     }
       
  4996 
       
  4997 /** Clean up font table and glyph outline caches when an FBS session is terminated.
       
  4998  * All the reference counts related to that session are cleared.
       
  4999 @param aSession: Input. A pointer to the terminating session.
       
  5000 @return always returns KErrNone.
       
  5001 @internalTechnology
       
  5002 */
       
  5003 EXPORT_C
       
  5004 void CFontStore::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle)
       
  5005     {
       
  5006     iHintedOutlineCache->CleanupCacheOnFbsSessionTermination(aSessionHandle);
       
  5007     iUnhintedOutlineCache->CleanupCacheOnFbsSessionTermination(aSessionHandle);
       
  5008     iFontTableCache->CleanupCacheOnFbsSessionTermination(aSessionHandle);
       
  5009     }
       
  5010 
       
  5011 
       
  5012 void TFontTableGlyphOutlineCacheMemMonitor::Inc(TInt aBytes)
       
  5013     {
       
  5014     iBytes += aBytes;
       
  5015     }
       
  5016 
       
  5017 void TFontTableGlyphOutlineCacheMemMonitor::Dec(TInt aBytes)
       
  5018     {
       
  5019     iBytes -= aBytes;
       
  5020     }
       
  5021 
       
  5022 TInt TFontTableGlyphOutlineCacheMemMonitor::GetMemUsage()
       
  5023     {
       
  5024     return iBytes;
       
  5025     }
       
  5026 
       
  5027 TFontTableGlyphOutlineCacheMemMonitor::TFontTableGlyphOutlineCacheMemMonitor(): 
       
  5028     iBytes(0) 
       
  5029     {
       
  5030     // null constructor
       
  5031     }
       
  5032 
       
  5033 TUnhintedOutlineId::TUnhintedOutlineId(TUid aFileUid, TInt aFaceIndex, TUint aId):
       
  5034 iFileUid(aFileUid), iFaceIndex(aFaceIndex), iId(aId)
       
  5035     {
       
  5036     // a null constructor;
       
  5037     }
       
  5038 
       
  5039 THintedOutlineId::THintedOutlineId(COpenFont *aFont, TUint aId):
       
  5040 iFont(aFont), iId(aId)
       
  5041     {
       
  5042     // a null constructor;
       
  5043     }
       
  5044 
       
  5045 #ifdef _DEBUG
  3837 #ifdef _DEBUG
  5046 /**
  3838 /**
  5047 Returns a timestamp for use by FinishTimingL().
  3839 Returns a timestamp for use by FinishTimingL().
  5048 @return The timestamp.
  3840 @return The timestamp.
  5049 @see FinishTimingL
  3841 @see FinishTimingL