| Index: webkit/pending/FontCache.cpp
|
| ===================================================================
|
| --- webkit/pending/FontCache.cpp (revision 2884)
|
| +++ webkit/pending/FontCache.cpp (working copy)
|
| @@ -1,399 +0,0 @@
|
| -/*
|
| - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
|
| - * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
|
| - *
|
| - * Redistribution and use in source and binary forms, with or without
|
| - * modification, are permitted provided that the following conditions
|
| - * are met:
|
| - *
|
| - * 1. Redistributions of source code must retain the above copyright
|
| - * notice, this list of conditions and the following disclaimer.
|
| - * 2. Redistributions in binary form must reproduce the above copyright
|
| - * notice, this list of conditions and the following disclaimer in the
|
| - * documentation and/or other materials provided with the distribution.
|
| - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
|
| - * its contributors may be used to endorse or promote products derived
|
| - * from this software without specific prior written permission.
|
| - *
|
| - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
|
| - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
| - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
| - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
| - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
| - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
| - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
| - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| - */
|
| -
|
| -#include "config.h"
|
| -#include "FontCache.h"
|
| -
|
| -#include "Font.h"
|
| -#include "FontFallbackList.h"
|
| -#include "FontPlatformData.h"
|
| -#include "FontSelector.h"
|
| -#include "StringHash.h"
|
| -#include <wtf/HashMap.h>
|
| -#include <wtf/ListHashSet.h>
|
| -
|
| -using namespace WTF;
|
| -
|
| -namespace WebCore {
|
| -
|
| -struct FontPlatformDataCacheKey {
|
| - FontPlatformDataCacheKey(const AtomicString& family = AtomicString(), unsigned size = 0, unsigned weight = 0, bool italic = false,
|
| - bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode)
|
| - : m_family(family)
|
| - , m_size(size)
|
| - , m_weight(weight)
|
| - , m_italic(italic)
|
| - , m_printerFont(isPrinterFont)
|
| - , m_renderingMode(renderingMode)
|
| - {
|
| - }
|
| -
|
| - FontPlatformDataCacheKey(HashTableDeletedValueType) : m_size(hashTableDeletedSize()) { }
|
| - bool isHashTableDeletedValue() const { return m_size == hashTableDeletedSize(); }
|
| -
|
| - bool operator==(const FontPlatformDataCacheKey& other) const
|
| - {
|
| - return equalIgnoringCase(m_family, other.m_family) && m_size == other.m_size &&
|
| - m_weight == other.m_weight && m_italic == other.m_italic && m_printerFont == other.m_printerFont &&
|
| - m_renderingMode == other.m_renderingMode;
|
| - }
|
| -
|
| - AtomicString m_family;
|
| - unsigned m_size;
|
| - unsigned m_weight;
|
| - bool m_italic;
|
| - bool m_printerFont;
|
| - FontRenderingMode m_renderingMode;
|
| -
|
| -private:
|
| - static unsigned hashTableDeletedSize() { return 0xFFFFFFFFU; }
|
| -};
|
| -
|
| -inline unsigned computeHash(const FontPlatformDataCacheKey& fontKey)
|
| -{
|
| - unsigned hashCodes[4] = {
|
| - CaseFoldingHash::hash(fontKey.m_family),
|
| - fontKey.m_size,
|
| - fontKey.m_weight,
|
| - static_cast<unsigned>(fontKey.m_italic) << 2 | static_cast<unsigned>(fontKey.m_printerFont) << 1 | static_cast<unsigned>(fontKey.m_renderingMode)
|
| - };
|
| - return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar));
|
| -}
|
| -
|
| -struct FontPlatformDataCacheKeyHash {
|
| - static unsigned hash(const FontPlatformDataCacheKey& font)
|
| - {
|
| - return computeHash(font);
|
| - }
|
| -
|
| - static bool equal(const FontPlatformDataCacheKey& a, const FontPlatformDataCacheKey& b)
|
| - {
|
| - return a == b;
|
| - }
|
| -
|
| - static const bool safeToCompareToEmptyOrDeleted = true;
|
| -};
|
| -
|
| -struct FontPlatformDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformDataCacheKey> {
|
| - static const bool emptyValueIsZero = true;
|
| - static const FontPlatformDataCacheKey& emptyValue()
|
| - {
|
| - static FontPlatformDataCacheKey key(nullAtom);
|
| - return key;
|
| - }
|
| - static void constructDeletedValue(FontPlatformDataCacheKey& slot)
|
| - {
|
| - new (&slot) FontPlatformDataCacheKey(HashTableDeletedValue);
|
| - }
|
| - static bool isDeletedValue(const FontPlatformDataCacheKey& value)
|
| - {
|
| - return value.isHashTableDeletedValue();
|
| - }
|
| -};
|
| -
|
| -typedef HashMap<FontPlatformDataCacheKey, FontPlatformData*, FontPlatformDataCacheKeyHash, FontPlatformDataCacheKeyTraits> FontPlatformDataCache;
|
| -
|
| -static FontPlatformDataCache* gFontPlatformDataCache = 0;
|
| -
|
| -FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fontDescription,
|
| - const AtomicString& familyName,
|
| - bool checkingAlternateName)
|
| -{
|
| - if (!gFontPlatformDataCache) {
|
| - gFontPlatformDataCache = new FontPlatformDataCache;
|
| - platformInit();
|
| - }
|
| -
|
| - FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.weight(), fontDescription.italic(),
|
| - fontDescription.usePrinterFont(), fontDescription.renderingMode());
|
| - FontPlatformData* result = 0;
|
| - bool foundResult;
|
| - FontPlatformDataCache::iterator it = gFontPlatformDataCache->find(key);
|
| - if (it == gFontPlatformDataCache->end()) {
|
| - result = createFontPlatformData(fontDescription, familyName);
|
| - gFontPlatformDataCache->set(key, result);
|
| - foundResult = result;
|
| - } else {
|
| - result = it->second;
|
| - foundResult = true;
|
| - }
|
| -
|
| - if (!foundResult && !checkingAlternateName) {
|
| - // We were unable to find a font. We have a small set of fonts that we alias to other names,
|
| - // e.g., Arial/Helvetica, Courier/Courier New, etc. Try looking up the font under the aliased name.
|
| - const AtomicString& alternateName = alternateFamilyName(familyName);
|
| - if (!alternateName.isEmpty())
|
| - result = getCachedFontPlatformData(fontDescription, alternateName, true);
|
| - if (result)
|
| - gFontPlatformDataCache->set(key, new FontPlatformData(*result)); // Cache the result under the old name.
|
| - }
|
| -
|
| - return result;
|
| -}
|
| -
|
| -struct FontDataCacheKeyHash {
|
| - static unsigned hash(const FontPlatformData& platformData)
|
| - {
|
| - return platformData.hash();
|
| - }
|
| -
|
| - static bool equal(const FontPlatformData& a, const FontPlatformData& b)
|
| - {
|
| - return a == b;
|
| - }
|
| -
|
| - static const bool safeToCompareToEmptyOrDeleted = true;
|
| -};
|
| -
|
| -struct FontDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformData> {
|
| - static const bool emptyValueIsZero = true;
|
| - static const bool needsDestruction = true;
|
| - static const FontPlatformData& emptyValue()
|
| - {
|
| - static FontPlatformData key;
|
| - 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 Threshold
|
| -const 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.reserveCapacity(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.reserveCapacity(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
|
|
|