webengine/osswebengine/WebCore/platform/FontCache.cpp
changeset 0 dd21522fd290
child 13 10e98eab6f85
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebCore/platform/FontCache.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * 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 "StringHash.h"
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+struct FontPlatformDataCacheKey {
+    FontPlatformDataCacheKey(const AtomicString& family = AtomicString(), unsigned size = 0, bool bold = false, bool italic = false,
+                             bool isPrinterFont = false)
+        : m_family(family)
+        , m_size(size)
+        , m_bold(bold)
+        , m_italic(italic)
+        , m_printerFont(isPrinterFont)
+    {
+    }
+
+    bool operator==(const FontPlatformDataCacheKey& other) const
+    {
+        return equalIgnoringCase(m_family, other.m_family) && m_size == other.m_size && 
+               m_bold == other.m_bold && m_italic == other.m_italic && m_printerFont == other.m_printerFont;
+    }
+    
+    AtomicString m_family;
+    unsigned m_size;
+    bool m_bold;
+    bool m_italic;
+    bool m_printerFont;
+};
+
+inline unsigned computeHash(const FontPlatformDataCacheKey& fontKey)
+{
+    unsigned hashCodes[3] = {
+        CaseInsensitiveHash<String>::hash(fontKey.m_family),
+        fontKey.m_size,
+        static_cast<unsigned>(fontKey.m_bold) << 2 | static_cast<unsigned>(fontKey.m_italic) << 1 | static_cast<unsigned>(fontKey.m_printerFont)
+    };
+    return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), 3 * sizeof(unsigned) / 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;
+    }
+};
+
+struct FontPlatformDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformDataCacheKey> {
+    static const bool emptyValueIsZero = true;
+    static const bool needsDestruction = false;
+    static const FontPlatformDataCacheKey& deletedValue()
+    {
+        static FontPlatformDataCacheKey key(nullAtom, 0xFFFFFFFFU, false, false);
+        return key;
+    }
+    static const FontPlatformDataCacheKey& emptyValue()
+    {
+        static FontPlatformDataCacheKey key(nullAtom, 0, false, false);
+        return key;
+    }
+};
+
+typedef HashMap<FontPlatformDataCacheKey, FontPlatformData*, FontPlatformDataCacheKeyHash, FontPlatformDataCacheKeyTraits> FontPlatformDataCache;
+
+static FontPlatformDataCache* gFontPlatformDataCache = 0;
+
+static const AtomicString& alternateFamilyName(const AtomicString& familyName)
+{
+#if PLATFORM(SYMBIAN)
+    return FontCache::systemFontFamilyName( familyName );
+#else
+    // Alias Courier <-> Courier New
+    static AtomicString courier("Courier"), courierNew("Courier New");
+    if (equalIgnoringCase(familyName, courier))
+        return courierNew;
+    if (equalIgnoringCase(familyName, courierNew))
+        return courier;
+
+    // Alias Times and Times New Roman.
+    static AtomicString times("Times"), timesNewRoman("Times New Roman");
+    if (equalIgnoringCase(familyName, times))
+        return timesNewRoman;
+    if (equalIgnoringCase(familyName, timesNewRoman))
+        return times;
+    
+    // Alias Arial and Helvetica
+    static AtomicString arial("Arial"), helvetica("Helvetica");
+    if (equalIgnoringCase(familyName, arial))
+        return helvetica;
+    if (equalIgnoringCase(familyName, helvetica))
+        return arial;
+
+    return emptyAtom;
+#endif
+}
+
+FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fontDescription, 
+                                                       const AtomicString& familyName,
+                                                       bool checkingAlternateName)
+{
+    if (!gFontPlatformDataCache) {
+        gFontPlatformDataCache = new FontPlatformDataCache;
+        platformInit();
+    }
+
+    FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.bold(), fontDescription.italic(),
+                                 fontDescription.usePrinterFont());
+    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.
+    }
+
+    key.m_family = AtomicString();
+    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;
+    }
+};
+
+struct FontDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformData> {
+    static const bool emptyValueIsZero = true;
+    static const bool needsDestruction = false;
+    static const FontPlatformData& deletedValue()
+    {
+        static FontPlatformData key = FontPlatformData::Deleted();
+        return key;
+    }
+    static const FontPlatformData& emptyValue()
+    {
+        static FontPlatformData key;
+        return key;
+    }
+};
+
+typedef HashMap<FontPlatformData, FontData*, FontDataCacheKeyHash, FontDataCacheKeyTraits> FontDataCache;
+
+static FontDataCache* gFontDataCache = 0;
+
+FontData* FontCache::getCachedFontData(const FontPlatformData* platformData)
+{
+    if (!platformData)
+        return 0;
+
+    if (!gFontDataCache)
+        gFontDataCache = new FontDataCache;
+    
+    FontData* result = gFontDataCache->get(*platformData);
+    if (!result) {
+        result = new FontData(*platformData);
+        gFontDataCache->set(*platformData, result);
+    }
+        
+    return result;
+}
+
+const FontData* FontCache::getFontData(const Font& font, int& familyIndex)
+{
+    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())
+            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)
+        // We still don't have a result.  Hand back our last resort fallback font.  We only do the last resort fallback
+        // when trying to find the primary font.  Otherwise our fallback will rely on the actual characters used.
+        result = getLastResortFallbackFont(font);
+
+    // Now that we have a result, we need to go from FontPlatformData -> FontData.
+    return getCachedFontData(result);
+}
+
+} // namespace WebCore