📄 fontcache.cpp
字号:
static const bool safeToCompareToEmptyOrDeleted = true;};struct FontDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformData> { static const bool emptyValueIsZero = true; static const bool needsDestruction = true; static const FontPlatformData& emptyValue() { DEFINE_STATIC_LOCAL(FontPlatformData, key, (0.f, false, false)); return key; } static void constructDeletedValue(FontPlatformData& slot) { new (&slot) FontPlatformData(HashTableDeletedValue); } static bool isDeletedValue(const FontPlatformData& value) { return value.isHashTableDeletedValue(); }};typedef HashMap<FontPlatformData, pair<SimpleFontData*, unsigned>, FontDataCacheKeyHash, FontDataCacheKeyTraits> FontDataCache;static FontDataCache* gFontDataCache = 0;const int cMaxInactiveFontData = 120; // Pretty Low Thresholdconst float cTargetInactiveFontData = 100;static ListHashSet<const SimpleFontData*>* gInactiveFontData = 0;SimpleFontData* FontCache::getCachedFontData(const FontPlatformData* platformData){ if (!platformData) return 0; if (!gFontDataCache) { gFontDataCache = new FontDataCache; gInactiveFontData = new ListHashSet<const SimpleFontData*>; } FontDataCache::iterator result = gFontDataCache->find(*platformData); if (result == gFontDataCache->end()) { pair<SimpleFontData*, unsigned> newValue(new SimpleFontData(*platformData), 1); gFontDataCache->set(*platformData, newValue); return newValue.first; } if (!result.get()->second.second++) { ASSERT(gInactiveFontData->contains(result.get()->second.first)); gInactiveFontData->remove(result.get()->second.first); } return result.get()->second.first;}void FontCache::releaseFontData(const SimpleFontData* fontData){ ASSERT(gFontDataCache); ASSERT(!fontData->isCustomFont()); FontDataCache::iterator it = gFontDataCache->find(fontData->platformData()); ASSERT(it != gFontDataCache->end()); if (!--it->second.second) { gInactiveFontData->add(fontData); if (gInactiveFontData->size() > cMaxInactiveFontData) purgeInactiveFontData(gInactiveFontData->size() - cTargetInactiveFontData); }}void FontCache::purgeInactiveFontData(int count){ if (!gInactiveFontData) return; static bool isPurging; // Guard against reentry when e.g. a deleted FontData releases its small caps FontData. if (isPurging) return; isPurging = true; ListHashSet<const SimpleFontData*>::iterator end = gInactiveFontData->end(); ListHashSet<const SimpleFontData*>::iterator it = gInactiveFontData->begin(); for (int i = 0; i < count && it != end; ++it, ++i) { const SimpleFontData* fontData = *it.get(); gFontDataCache->remove(fontData->platformData()); delete fontData; } if (it == end) { // Removed everything gInactiveFontData->clear(); } else { for (int i = 0; i < count; ++i) gInactiveFontData->remove(gInactiveFontData->begin()); } Vector<FontPlatformDataCacheKey> keysToRemove; keysToRemove.reserveInitialCapacity(gFontPlatformDataCache->size()); FontPlatformDataCache::iterator platformDataEnd = gFontPlatformDataCache->end(); for (FontPlatformDataCache::iterator platformData = gFontPlatformDataCache->begin(); platformData != platformDataEnd; ++platformData) { if (platformData->second && !gFontDataCache->contains(*platformData->second)) keysToRemove.append(platformData->first); } size_t keysToRemoveCount = keysToRemove.size(); for (size_t i = 0; i < keysToRemoveCount; ++i) delete gFontPlatformDataCache->take(keysToRemove[i]); isPurging = false;}size_t FontCache::fontDataCount(){ if (gFontDataCache) return gFontDataCache->size(); return 0;}size_t FontCache::inactiveFontDataCount(){ if (gInactiveFontData) return gInactiveFontData->size(); return 0;}const FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontSelector* fontSelector){ FontPlatformData* result = 0; int startIndex = familyIndex; const FontFamily* startFamily = &font.fontDescription().family(); for (int i = 0; startFamily && i < startIndex; i++) startFamily = startFamily->next(); const FontFamily* currFamily = startFamily; while (currFamily && !result) { familyIndex++; if (currFamily->family().length()) { if (fontSelector) { FontData* data = fontSelector->getFontData(font.fontDescription(), currFamily->family()); if (data) return data; } result = getCachedFontPlatformData(font.fontDescription(), currFamily->family()); } currFamily = currFamily->next(); } if (!currFamily) familyIndex = cAllFamiliesScanned; if (!result) // We didn't find a font. Try to find a similar font using our own specific knowledge about our platform. // For example on OS X, we know to map any families containing the words Arabic, Pashto, or Urdu to the // Geeza Pro font. result = getSimilarFontPlatformData(font); if (!result && startIndex == 0) { // If it's the primary font that we couldn't find, we try the following. In all other cases, we will // just use per-character system fallback. if (fontSelector) { // Try the user's preferred standard font. if (FontData* data = fontSelector->getFontData(font.fontDescription(), "-webkit-standard")) return data; } // Still no result. Hand back our last resort fallback font. result = getLastResortFallbackFont(font.fontDescription()); } // Now that we have a result, we need to go from FontPlatformData -> FontData. return getCachedFontData(result);}static HashSet<FontSelector*>* gClients;void FontCache::addClient(FontSelector* client){ if (!gClients) gClients = new HashSet<FontSelector*>; ASSERT(!gClients->contains(client)); gClients->add(client);}void FontCache::removeClient(FontSelector* client){ ASSERT(gClients); ASSERT(gClients->contains(client)); gClients->remove(client);}static unsigned gGeneration = 0;unsigned FontCache::generation(){ return gGeneration;}void FontCache::invalidate(){ if (!gClients) { ASSERT(!gFontPlatformDataCache); return; } if (gFontPlatformDataCache) { deleteAllValues(*gFontPlatformDataCache); delete gFontPlatformDataCache; gFontPlatformDataCache = new FontPlatformDataCache; } gGeneration++; Vector<RefPtr<FontSelector> > clients; size_t numClients = gClients->size(); clients.reserveInitialCapacity(numClients); HashSet<FontSelector*>::iterator end = gClients->end(); for (HashSet<FontSelector*>::iterator it = gClients->begin(); it != end; ++it) clients.append(*it); ASSERT(numClients == clients.size()); for (size_t i = 0; i < numClients; ++i) clients[i]->fontCacheInvalidated(); purgeInactiveFontData();}} // namespace WebCore
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -