2009-12-04 Benjamin Poulain <benjamin.poulain@nokia.com>
authoreric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Dec 2009 17:50:42 +0000 (17:50 +0000)
committereric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Dec 2009 17:50:42 +0000 (17:50 +0000)
        Reviewed by Kenneth Rohde Christiansen.

        [Qt] WebKit crashes when loading certain SVG images
        https://bugs.webkit.org/show_bug.cgi?id=29443

        Remove FontFallbackListQt and rely on the common FontFallbackList
        to handle the fonts. FontCache and FontPlatformData have been
        updated to work with the common FontFallbackList.

        In the previous implementation, FontPlatformDataCacheKey
        was a clone of FontPlatformData with the hashing
        capabilities added in order to use it as a key in the cache's
        hashmap. FontPlatformData has been modified to handle the hashing
        function directly so the data are not copied twice in memory.

        FontFallbackList::fontDataAt() from FontFallbackListQt was a copy of
        code from FontCache::getFontData() and FontFallbackList::fontDataAt().
        The behavior is similar except currFamily->family().length() was
        not tested and the fallback fonts selector were not used.

        Existing tests cover the change.

        * WebCore.pro:
        * platform/graphics/qt/FontCacheQt.cpp:
        (WebCore::FontCache::platformInit):
        (WebCore::FontCache::getFontDataForCharacters):
        (WebCore::FontCache::getSimilarFontPlatformData):
        (WebCore::FontCache::getLastResortFallbackFont):
        (WebCore::FontCache::getTraitsInFamily):
        (WebCore::FontCache::createFontPlatformData):
        * platform/graphics/qt/FontCustomPlatformData.cpp:
        (WebCore::FontCustomPlatformData::fontPlatformData):
        * platform/graphics/qt/FontFallbackListQt.cpp:
        Removed. We now use the implementation from FontFallbackList.cpp
        * platform/graphics/qt/FontPlatformData.h:
        Add hashing capabilities to be able to use the data with the FontCache.
        This was previously done in FontCacheQt.cpp
        (WebCore::FontPlatformDataPrivate::FontPlatformDataPrivate):
        (WebCore::FontPlatformData::FontPlatformData):
        (WebCore::FontPlatformData::isHashTableDeletedValue):
        (WebCore::FontPlatformData::font):
        (WebCore::FontPlatformData::size):
        (WebCore::FontPlatformData::family):
        (WebCore::FontPlatformData::bold):
        (WebCore::FontPlatformData::italic):
        (WebCore::FontPlatformData::smallCaps):
        (WebCore::FontPlatformData::pixelSize):
        * platform/graphics/qt/FontPlatformDataQt.cpp:
        (WebCore::FontPlatformData::FontPlatformData):
        (WebCore::FontPlatformData::~FontPlatformData):
        (WebCore::FontPlatformData::operator=):
        (WebCore::FontPlatformData::operator==):
        (WebCore::FontPlatformData::hash):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@51699 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/WebCore.pro
WebCore/platform/graphics/qt/FontCacheQt.cpp
WebCore/platform/graphics/qt/FontCustomPlatformData.cpp
WebCore/platform/graphics/qt/FontFallbackListQt.cpp [deleted file]
WebCore/platform/graphics/qt/FontPlatformData.h
WebCore/platform/graphics/qt/FontPlatformDataQt.cpp

index 7ab53dedb8e76fd6813704d3885a5bc777ddef3a..4f4864503796fcd35220e0178aeadfb986bdf63a 100644 (file)
@@ -1,3 +1,59 @@
+2009-12-04  Benjamin Poulain  <benjamin.poulain@nokia.com>
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        [Qt] WebKit crashes when loading certain SVG images
+        https://bugs.webkit.org/show_bug.cgi?id=29443
+
+        Remove FontFallbackListQt and rely on the common FontFallbackList
+        to handle the fonts. FontCache and FontPlatformData have been
+        updated to work with the common FontFallbackList.
+
+        In the previous implementation, FontPlatformDataCacheKey
+        was a clone of FontPlatformData with the hashing
+        capabilities added in order to use it as a key in the cache's
+        hashmap. FontPlatformData has been modified to handle the hashing
+        function directly so the data are not copied twice in memory.
+
+        FontFallbackList::fontDataAt() from FontFallbackListQt was a copy of
+        code from FontCache::getFontData() and FontFallbackList::fontDataAt().
+        The behavior is similar except currFamily->family().length() was
+        not tested and the fallback fonts selector were not used.
+
+        Existing tests cover the change.
+
+        * WebCore.pro:
+        * platform/graphics/qt/FontCacheQt.cpp:
+        (WebCore::FontCache::platformInit):
+        (WebCore::FontCache::getFontDataForCharacters):
+        (WebCore::FontCache::getSimilarFontPlatformData):
+        (WebCore::FontCache::getLastResortFallbackFont):
+        (WebCore::FontCache::getTraitsInFamily):
+        (WebCore::FontCache::createFontPlatformData):
+        * platform/graphics/qt/FontCustomPlatformData.cpp:
+        (WebCore::FontCustomPlatformData::fontPlatformData):
+        * platform/graphics/qt/FontFallbackListQt.cpp:
+        Removed. We now use the implementation from FontFallbackList.cpp
+        * platform/graphics/qt/FontPlatformData.h:
+        Add hashing capabilities to be able to use the data with the FontCache.
+        This was previously done in FontCacheQt.cpp
+        (WebCore::FontPlatformDataPrivate::FontPlatformDataPrivate):
+        (WebCore::FontPlatformData::FontPlatformData):
+        (WebCore::FontPlatformData::isHashTableDeletedValue):
+        (WebCore::FontPlatformData::font):
+        (WebCore::FontPlatformData::size):
+        (WebCore::FontPlatformData::family):
+        (WebCore::FontPlatformData::bold):
+        (WebCore::FontPlatformData::italic):
+        (WebCore::FontPlatformData::smallCaps):
+        (WebCore::FontPlatformData::pixelSize):
+        * platform/graphics/qt/FontPlatformDataQt.cpp:
+        (WebCore::FontPlatformData::FontPlatformData):
+        (WebCore::FontPlatformData::~FontPlatformData):
+        (WebCore::FontPlatformData::operator=):
+        (WebCore::FontPlatformData::operator==):
+        (WebCore::FontPlatformData::hash):
+
 2009-12-04  Adam Treat  <atreat@rim.com>
 
         Reviewed by Dan Bernstein.
index a8106c15b6fa9fed229f958b0bcd5b17ab1bea0e..a591dc0ebf0b6a53f49f9dcc4c92b6cbe9f9e4c4 100644 (file)
@@ -1195,6 +1195,7 @@ SOURCES += \
     platform/image-decoders/qt/RGBA32BufferQt.cpp \
     platform/graphics/filters/FEGaussianBlur.cpp \
     platform/graphics/FontDescription.cpp \
+    platform/graphics/FontFallbackList.cpp \
     platform/graphics/FontFamily.cpp \
     platform/graphics/BitmapImage.cpp \
     platform/graphics/Color.cpp \
@@ -1205,6 +1206,7 @@ SOURCES += \
     platform/graphics/FloatSize.cpp \
     platform/graphics/FontData.cpp \
     platform/graphics/Font.cpp \
+    platform/graphics/FontCache.cpp \
     platform/graphics/GeneratedImage.cpp \
     platform/graphics/Gradient.cpp \
     platform/graphics/GraphicsContext.cpp \
@@ -2392,7 +2394,6 @@ SOURCES += \
     platform/qt/SharedBufferQt.cpp \
     platform/graphics/qt/FontCacheQt.cpp \
     platform/graphics/qt/FontCustomPlatformData.cpp \
-    platform/graphics/qt/FontFallbackListQt.cpp \
     platform/graphics/qt/GlyphPageTreeNodeQt.cpp \
     platform/graphics/qt/SimpleFontDataQt.cpp \
     platform/qt/KURLQt.cpp \
index 4ef03a595ceee29f769b0d4af13672d2f865d944..648eed706aa01de45a7c0c6d844799acdccffe48 100644 (file)
@@ -38,256 +38,33 @@ using namespace WTF;
 
 namespace WebCore {
 
-FontCache* fontCache()
+void FontCache::platformInit()
 {
-    DEFINE_STATIC_LOCAL(FontCache, globalFontCache, ());
-    return &globalFontCache;
 }
 
-FontCache::FontCache()
-{
-}
-
-void FontCache::getTraitsInFamily(const AtomicString&, Vector<unsigned>&)
-{
-}
-
-// This type must be consistent with FontPlatformData's ctor - the one which
-// gets FontDescription as it's parameter.
-class FontPlatformDataCacheKey {
-public:
-    FontPlatformDataCacheKey(const FontDescription& description)
-        : m_familyName()
-        , m_size(description.computedPixelSize())
-        , m_bold(false)
-        , m_italic(description.italic())
-        , m_smallCaps(description.smallCaps())
-        , m_hash(0)
-    {
-        // FIXME: Map all FontWeight values to QFont weights in FontPlatformData's ctor and follow it here
-        if (FontPlatformData::toQFontWeight(description.weight()) > QFont::Normal)
-            m_bold = true;
-
-        const FontFamily* family = &description.family();
-        while (family) {
-            m_familyName.append(family->family());
-            family = family->next();
-            if (family)
-                m_familyName.append(',');
-        }
-
-        computeHash();
-    }
-
-    FontPlatformDataCacheKey(const FontPlatformData& fontData)
-        : m_familyName(static_cast<String>(fontData.family()))
-        , m_size(fontData.pixelSize())
-        , m_bold(fontData.bold())
-        , m_italic(fontData.italic())
-        , m_smallCaps(fontData.smallCaps())
-        , m_hash(0)
-    {
-        computeHash();
-    }
-
-    FontPlatformDataCacheKey(HashTableDeletedValueType) : m_size(hashTableDeletedSize()) { }
-    bool isHashTableDeletedValue() const { return m_size == hashTableDeletedSize(); }
-
-    enum HashTableEmptyValueType { HashTableEmptyValue };
-
-    FontPlatformDataCacheKey(HashTableEmptyValueType)
-        : m_familyName()
-        , m_size(0)
-        , m_bold(false)
-        , m_italic(false)
-        , m_smallCaps(false)
-        , m_hash(0)
-    {
-    }
-
-    bool operator==(const FontPlatformDataCacheKey& other) const
-    {
-        if (m_hash != other.m_hash)
-            return false;
-
-        return equalIgnoringCase(m_familyName, other.m_familyName) && m_size == other.m_size &&
-            m_bold == other.m_bold && m_italic == other.m_italic && m_smallCaps == other.m_smallCaps;
-    }
-
-    unsigned hash() const
-    {
-        return m_hash;
-    }
-
-    void computeHash()
-    {
-        unsigned hashCodes[] = {
-            CaseFoldingHash::hash(m_familyName),
-            m_size | static_cast<unsigned>(m_bold << (sizeof(unsigned) * 8 - 1))
-                | static_cast<unsigned>(m_italic) << (sizeof(unsigned) * 8 - 2)
-                | static_cast<unsigned>(m_smallCaps) << (sizeof(unsigned) * 8 - 3)
-        };
-        m_hash = StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar));
-    }
-
-private:
-    String m_familyName;
-    int m_size;
-    bool m_bold;
-    bool m_italic;
-    bool m_smallCaps;
-    unsigned m_hash;
-
-    static unsigned hashTableDeletedSize() { return 0xFFFFFFFFU; }
-};
-
-struct FontPlatformDataCacheKeyHash {
-    static unsigned hash(const FontPlatformDataCacheKey& key)
-    {
-        return key.hash();
-    }
-
-    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 needsDestruction = true;
-    static const FontPlatformDataCacheKey& emptyValue()
-    {
-        DEFINE_STATIC_LOCAL(FontPlatformDataCacheKey, key, (FontPlatformDataCacheKey::HashTableEmptyValue));
-        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;
-
-// using Q_GLOBAL_STATIC leads to crash. TODO investigate the way to fix this.
-static FontPlatformDataCache* gFontPlatformDataCache = 0;
-
-FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& description, const AtomicString&, bool)
-{
-    if (!gFontPlatformDataCache)
-        gFontPlatformDataCache = new FontPlatformDataCache;
-
-    FontPlatformDataCacheKey key(description);
-    FontPlatformData* platformData = gFontPlatformDataCache->get(key);
-    if (!platformData) {
-        platformData = new FontPlatformData(description);
-        gFontPlatformDataCache->add(key, platformData);
-    }
-    return platformData;
-}
-
-typedef HashMap<FontPlatformDataCacheKey, std::pair<SimpleFontData*, unsigned>, FontPlatformDataCacheKeyHash, FontPlatformDataCacheKeyTraits> FontDataCache;
-
-static FontDataCache* gFontDataCache = 0;
-
-static const int cMaxInactiveFontData = 40;
-static const int cTargetInactiveFontData = 32;
-
-static ListHashSet<const SimpleFontData*>* gInactiveFontDataSet = 0;
-
-SimpleFontData* FontCache::getCachedFontData(const FontPlatformData* fontPlatformData)
-{
-    if (!gFontDataCache) {
-        gFontDataCache = new FontDataCache;
-        gInactiveFontDataSet = new ListHashSet<const SimpleFontData*>;
-    }
-
-    FontPlatformDataCacheKey key(*fontPlatformData);
-    FontDataCache::iterator it = gFontDataCache->find(key);
-    if (it == gFontDataCache->end()) {
-        SimpleFontData* fontData = new SimpleFontData(*fontPlatformData);
-        gFontDataCache->add(key, std::pair<SimpleFontData*, unsigned>(fontData, 1));
-        return fontData;
-    }
-    if (!it->second.second++) {
-        ASSERT(gInactiveFontDataSet->contains(it->second.first));
-        gInactiveFontDataSet->remove(it->second.first);
-    }
-    return it->second.first;
-}
-
-FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription&)
+const SimpleFontData* FontCache::getFontDataForCharacters(const Font&, const UChar*, int)
 {
     return 0;
 }
 
-void FontCache::releaseFontData(const WebCore::SimpleFontData* fontData)
-{
-    ASSERT(gFontDataCache);
-    ASSERT(!fontData->isCustomFont());
-
-    FontPlatformDataCacheKey key(fontData->platformData());
-    FontDataCache::iterator it = gFontDataCache->find(key);
-    ASSERT(it != gFontDataCache->end());
-    if (!--it->second.second) {
-        gInactiveFontDataSet->add(it->second.first);
-        if (gInactiveFontDataSet->size() > cMaxInactiveFontData)
-            purgeInactiveFontData(gInactiveFontDataSet->size() - cTargetInactiveFontData);
-    }
-}
-
-void FontCache::purgeInactiveFontData(int count)
+FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
 {
-    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 it = gInactiveFontDataSet->begin();
-    ListHashSet<const SimpleFontData*>::iterator end = gInactiveFontDataSet->end();
-    for (int i = 0; i < count && it != end; ++i, ++it) {
-        FontPlatformDataCacheKey key = (*it)->platformData();
-        pair<SimpleFontData*, unsigned> fontDataPair = gFontDataCache->take(key);
-        ASSERT(fontDataPair.first != 0);
-        ASSERT(!fontDataPair.second);
-        delete fontDataPair.first;
-
-        FontPlatformData* platformData = gFontPlatformDataCache->take(key);
-        if (platformData)
-            delete platformData;
-    }
-
-    if (it == end) {
-        // Removed everything
-        gInactiveFontDataSet->clear();
-    } else {
-        for (int i = 0; i < count; ++i)
-            gInactiveFontDataSet->remove(gInactiveFontDataSet->begin());
-    }
-
-    isPurging = false;
+    return new FontPlatformData(font.fontDescription());
 }
 
-void FontCache::addClient(FontSelector*)
+FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription)
 {
+    return new FontPlatformData(fontDescription);
 }
 
-void FontCache::removeClient(FontSelector*)
+void FontCache::getTraitsInFamily(const AtomicString&, Vector<unsigned>&)
 {
 }
 
-void FontCache::invalidate()
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString&)
 {
-    if (!gFontPlatformDataCache || !gFontDataCache)
-        return;
-
-    purgeInactiveFontData();
+    // FIXME : we must take into account the familly name (second argument)
+    return new FontPlatformData(fontDescription);
 }
 
 } // namespace WebCore
index a19464ebd718aa1bb9116d0a2d5aa87ab985db83..6e9d0536158726c0fd31cb5efaa22b5d1ff1e43e 100644 (file)
@@ -43,7 +43,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
         font.setWeight(QFont::Bold);
     font.setItalic(italic);
 
-    return FontPlatformData(font, bold);
+    return FontPlatformData(font);
 }
 
 FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
diff --git a/WebCore/platform/graphics/qt/FontFallbackListQt.cpp b/WebCore/platform/graphics/qt/FontFallbackListQt.cpp
deleted file mode 100644 (file)
index 0306abf..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-    Copyright (C) 2008 Holger Hans Peter Freyther
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public License
-    along with this library; see the file COPYING.LIB.  If not, write to
-    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-    Boston, MA 02110-1301, USA.
-
-    Replacement of the stock FontFallbackList as Qt is going to find us a
-    replacement font, will do caching and the other stuff we implement in
-    WebKit.
-*/
-
-#include "config.h"
-#include "FontFallbackList.h"
-
-#include "Font.h"
-#include "FontCache.h"
-#include "SegmentedFontData.h"
-
-#include <QDebug>
-
-namespace WebCore {
-
-FontFallbackList::FontFallbackList()
-    : m_pageZero(0)
-    , m_cachedPrimarySimpleFontData(0)
-    , m_fontSelector(0)
-    , m_familyIndex(0)
-    , m_pitch(UnknownPitch)
-    , m_loadingCustomFonts(false)
-    , m_generation(0)
-{
-}
-
-void FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector> fontSelector)
-{
-    releaseFontData();
-    m_fontList.clear();
-    m_pageZero = 0;
-    m_pages.clear();
-    m_cachedPrimarySimpleFontData = 0;
-    m_familyIndex = 0;
-    m_pitch = UnknownPitch;
-    m_loadingCustomFonts = false;
-    m_fontSelector = fontSelector;
-    m_generation = 0;
-}
-
-void FontFallbackList::releaseFontData()
-{
-    unsigned numFonts = m_fontList.size();
-    for (unsigned i = 0; i < numFonts; ++i) {
-        if (m_fontList[i].second)
-            delete m_fontList[i].first;
-        else {
-            ASSERT(!m_fontList[i].first->isSegmented());
-            fontCache()->releaseFontData(static_cast<const SimpleFontData*>(m_fontList[i].first));
-        }
-    }
-}
-
-void FontFallbackList::determinePitch(const WebCore::Font* font) const
-{
-    const FontData* fontData = primaryFontData(font);
-    if (!fontData->isSegmented())
-        m_pitch = static_cast<const SimpleFontData*>(fontData)->pitch();
-    else {
-        const SegmentedFontData* segmentedFontData = static_cast<const SegmentedFontData*>(fontData);
-        unsigned numRanges = segmentedFontData->numRanges();
-        if (numRanges == 1)
-            m_pitch = segmentedFontData->rangeAt(0).fontData()->pitch();
-        else
-            m_pitch = VariablePitch;
-    }
-}
-
-const FontData* FontFallbackList::fontDataAt(const WebCore::Font* _font, unsigned index) const
-{
-    if (index != 0)
-        return 0;
-
-    // Search for the WebCore font that is already in the list
-    for (int i = m_fontList.size() - 1; i >= 0; --i) {
-        pair<const FontData*, bool> item = m_fontList[i];
-        // item.second means that the item was created locally or not
-        if (!item.second)
-            return item.first;
-    }
-
-    // Use the FontSelector to get a WebCore font and then fallback to Qt
-    const FontDescription& description = _font->fontDescription();
-    const FontFamily* family = &description.family();
-    while (family) {
-        if (family->family().length() && m_fontSelector) {
-            FontData* data = m_fontSelector->getFontData(description, family->family());
-            if (data) {
-                if (data->isLoading())
-                    m_loadingCustomFonts = true;
-                if (!data->isCustomFont()) {
-                    // Custom fonts can be freed anytime so we must not hold them
-                    m_fontList.append(pair<const FontData*, bool>(data, false));
-                }
-                return data;
-            }
-        }
-        family = family->next();
-    }
-
-    if (m_fontList.size())
-        return m_fontList[0].first;
-
-    const FontData* result = new SimpleFontData(FontPlatformData(description, _font->wordSpacing(), _font->letterSpacing()), true);
-    m_fontList.append(pair<const FontData*, bool>(result, true));
-    return result;
-}
-
-const FontData* FontFallbackList::fontDataForCharacters(const WebCore::Font* font, const UChar*, int) const
-{
-    return primaryFontData(font);
-}
-
-void FontFallbackList::setPlatformFont(const WebCore::FontPlatformData&)
-{
-    m_familyIndex = cAllFamiliesScanned;
-}
-
-}
index 5cd6ed2cd3f9700dfedf36a7d743cce7d8ab859c..306ada84dbe5d7aef6f5d9264783917c24ffbb43 100644 (file)
 
 #include "FontDescription.h"
 #include <QFont>
+#include <QHash>
 
 namespace WebCore {
 
 class String;
+class FontPlatformDataPrivate {
+public:
+    FontPlatformDataPrivate()
+        : refCount(1)
+        , size(font.pointSizeF())
+        , bold(font.bold())
+        , oblique(false)
+    {}
+    FontPlatformDataPrivate(const float size, const bool bold, const bool oblique)
+        : refCount(1)
+        , size(size)
+        , bold(bold)
+        , oblique(oblique)
+    {}
+    FontPlatformDataPrivate(const QFont& font)
+        : refCount(1)
+        , font(font)
+        , size(font.pointSizeF())
+        , bold(font.bold())
+        , oblique(false)
+    {}
+    unsigned refCount;
+    QFont font;
+    float size;
+    bool bold : 1;
+    bool oblique : 1;
+};
+
+
 
-class FontPlatformData : public FastAllocBase
-{
+class FontPlatformData : public FastAllocBase {
 public:
-#if ENABLE(SVG_FONTS)
     FontPlatformData(float size, bool bold, bool oblique);
-#endif
-    FontPlatformData();
+    FontPlatformData(const FontPlatformData &);
     FontPlatformData(const FontDescription&, int wordSpacing = 0, int letterSpacing = 0);
-    FontPlatformData(const QFont&, bool bold);
+    FontPlatformData(const QFont& font)
+        : m_data(new FontPlatformDataPrivate(font))
+    {}
+    FontPlatformData(WTF::HashTableDeletedValueType)
+        : m_data(reinterpret_cast<FontPlatformDataPrivate*>(-1))
+    {}
+
+    ~FontPlatformData();
+
+    FontPlatformData& operator=(const FontPlatformData&);
+    bool operator==(const FontPlatformData&) const;
+
+    bool isHashTableDeletedValue() const
+    {
+        return m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1);
+    }
 
     static inline QFont::Weight toQFontWeight(FontWeight fontWeight)
     {
@@ -62,22 +104,62 @@ public:
         }
     }
 
-    QFont font() const { return m_font; }
-    float size() const { return m_size; }
-    QString family() const { return m_font.family(); }
-    bool bold() const { return m_bold; }
-    bool italic() const { return m_font.italic(); }
-    bool smallCaps() const { return m_font.capitalization() == QFont::SmallCaps; }
-    int pixelSize() const { return m_font.pixelSize(); }
+    QFont font() const
+    {
+        Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+        if (m_data)
+            return m_data->font;
+        return QFont();
+    }
+    float size() const
+    {
+        Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+        if (m_data)
+            return m_data->size;
+        return 0.0f;
+    }
+    QString family() const
+    {
+        Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+        if (m_data)
+            return m_data->font.family();
+        return QString();
+    }
+    bool bold() const
+    {
+        Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+        if (m_data)
+            return m_data->bold;
+        return false;
+    }
+    bool italic() const
+    {
+        Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+        if (m_data)
+            return m_data->font.italic();
+        return false;
+    }
+    bool smallCaps() const
+    {
+        Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+        if (m_data)
+            return m_data->font.capitalization() == QFont::SmallCaps;
+        return false;
+    }
+    int pixelSize() const
+    {
+        Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+        if (m_data)
+            return m_data->font.pixelSize();
+        return 0;
+    }
+    unsigned hash() const;
 
 #ifndef NDEBUG
     String description() const;
 #endif
-
-    float m_size;
-    bool m_bold;
-    bool m_oblique;
-    QFont m_font;
+private:
+    FontPlatformDataPrivate* m_data;
 };
 
 } // namespace WebCore
index 7709be6b4eb466236bdcb75248216c1bb677ceeb..a0e2a1d680db4c121e8155985bbf741d543fe9ab 100644 (file)
 
 namespace WebCore {
 
+static inline bool isEmtpyValue(const float size, const bool bold, const bool oblique)
+{
+     // this is the empty value by definition of the trait FontDataCacheKeyTraits
+    return !bold && !oblique && size == 0.f;
+}
+
+FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
+{
+    if (isEmtpyValue(size, bold, oblique))
+        m_data = 0;
+    else
+        m_data = new FontPlatformDataPrivate(size, bold, oblique);
+}
+
+FontPlatformData::FontPlatformData(const FontPlatformData &other) : m_data(other.m_data)
+{
+    if (m_data && m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1))
+        ++m_data->refCount;
+}
+
 FontPlatformData::FontPlatformData(const FontDescription& description, int wordSpacing, int letterSpacing)
-    : m_size(0.0f)
-    , m_bold(false)
-    , m_oblique(false)
+    : m_data(new FontPlatformDataPrivate())
 {
     QString familyName;
     const FontFamily* family = &description.family();
@@ -39,43 +57,70 @@ FontPlatformData::FontPlatformData(const FontDescription& description, int wordS
         if (family)
             familyName += QLatin1Char(',');
     }
+    QFont& font = m_data->font;
+    font.setFamily(familyName);
+    font.setPixelSize(qRound(description.computedSize()));
+    font.setItalic(description.italic());
+    font.setWeight(toQFontWeight(description.weight()));
+    font.setWordSpacing(wordSpacing);
+    font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
+    const bool smallCaps = description.smallCaps();
+    font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
+
+    m_data->bold = font.bold();
+    m_data->size = font.pointSizeF();
+}
 
-    m_font.setFamily(familyName);
-    m_font.setPixelSize(qRound(description.computedSize()));
-    m_font.setItalic(description.italic());
-
-    m_font.setWeight(toQFontWeight(description.weight()));
-    m_bold = m_font.bold();
-
-    bool smallCaps = description.smallCaps();
-    m_font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
-    m_font.setWordSpacing(wordSpacing);
-    m_font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
-    m_size = m_font.pointSize();
+FontPlatformData::~FontPlatformData()
+{
+    if (!m_data || m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1))
+        return;
+    --m_data->refCount;
+    if (!m_data->refCount)
+        delete m_data;
 }
 
-FontPlatformData::FontPlatformData(const QFont& font, bool bold)
-    : m_size(font.pointSize())
-    , m_bold(bold)
-    , m_oblique(false)
-    , m_font(font)
+FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other)
 {
+    if (m_data == other.m_data)
+        return *this;
+    if (m_data && m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1)) {
+        --m_data->refCount;
+        if (!m_data->refCount)
+            delete m_data;
+    }
+    m_data = other.m_data;
+    if (m_data && m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1))
+        ++m_data->refCount;
+    return *this;
 }
 
-#if ENABLE(SVG_FONTS)
-FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
-    : m_size(size)
-    , m_bold(bold)
-    , m_oblique(oblique)
+bool FontPlatformData::operator==(const FontPlatformData& other) const
 {
+    if (m_data == other.m_data)
+        return true;
+
+    if (!m_data || !other.m_data
+        || m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1) || other.m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1))
+        return  false;
+
+    const bool equals = (m_data->size == other.m_data->size
+                         && m_data->bold == other.m_data->bold
+                         && m_data->oblique == other.m_data->oblique
+                         && m_data->font == other.m_data->font);
+    return equals;
 }
-#endif
 
-FontPlatformData::FontPlatformData()
-    : m_size(0.0f)
-    , m_bold(false)
-    , m_oblique(false)
+unsigned FontPlatformData::hash() const
 {
+    if (!m_data)
+        return 0;
+    if (m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1))
+        return 1;
+    return qHash(m_data->font.toString())
+           ^ qHash(*reinterpret_cast<quint32*>(&m_data->size))
+           ^ qHash(m_data->bold)
+           ^ qHash(m_data->oblique);
 }
 
 #ifndef NDEBUG