Skip to content
Permalink
Browse files
WebCore: [Qt] Handle fonts like the other ports
Patch by Benjamin Poulain <benjamin.poulain@nokia.com> on 2009-11-02
Reviewed by Simon Hausmann.

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.

https://bugs.webkit.org/show_bug.cgi?id=29856

Test: svg/text/text-font-invalid.html

* 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/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::FontPlatformData::FontPlatformData):
Added a boolean to identify deleted value in the hash table.
(WebCore::FontPlatformData::isHashTableDeletedValue):
(WebCore::FontPlatformData::hash):
(WebCore::FontPlatformData::operator==):
* platform/graphics/qt/FontPlatformDataQt.cpp:
(WebCore::FontPlatformData::FontPlatformData):

LayoutTests: Add a new test to reproduce 29856. The bug only happen
when the SVG file is used as an image.
https://bugs.webkit.org/show_bug.cgi?id=29856

Patch by Benjamin Poulain <benjamin.poulain@nokia.com> on 2009-11-02
Reviewed by Simon Hausmann.

* svg/text/text-font-invalid-expected.txt: Added.
* svg/text/resources/text-font-invalid.svg: Added.
* svg/text/text-font-invalid.html: Added.

Canonical link: https://commits.webkit.org/41926@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@50496 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Benjamin Poulain authored and tronical committed Nov 4, 2009
1 parent d3e9fa0 commit e0e7dd9b95dd52d3b6770b0ce805ea77afe95e9b
Showing 10 changed files with 138 additions and 378 deletions.
@@ -1,3 +1,15 @@
2009-11-02 Benjamin Poulain <benjamin.poulain@nokia.com>

Reviewed by Simon Hausmann.

Add a new test to reproduce 29856. The bug only happen
when the SVG file is used as an image.
https://bugs.webkit.org/show_bug.cgi?id=29856

* svg/text/text-font-invalid-expected.txt: Added.
* svg/text/resources/text-font-invalid.svg: Added.
* svg/text/text-font-invalid.html: Added.

2009-11-04 Roland Steiner <rolandsteiner@chromium.org>

Reviewed by Dave Hyatt.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,3 @@
This test is to ensure that we do not crash when loading a SVG image without a valid font-family
PASS: Did not crash when rendering the SVG image.

@@ -0,0 +1,12 @@
<html>
<body>
This test is to ensure that we do not crash when loading a SVG image without a valid font-family
<div id="log"><span style='color: red;'>FAIL:</span> Did not complete test</div>
<img src="resources/text-font-invalid.svg" />
<script>
if (window.layoutTestController)
layoutTestController.dumpAsText();
document.getElementById("log").innerHTML = "<span style='color: green;'>PASS:</span> Did not crash when rendering the SVG image.";
</script>
</body>
</html>
@@ -1,3 +1,49 @@
2009-11-02 Benjamin Poulain <benjamin.poulain@nokia.com>

Reviewed by Simon Hausmann.

[Qt] Handle fonts like the other ports

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.

https://bugs.webkit.org/show_bug.cgi?id=29856

Test: svg/text/text-font-invalid.html

* 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/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::FontPlatformData::FontPlatformData):
Added a boolean to identify deleted value in the hash table.
(WebCore::FontPlatformData::isHashTableDeletedValue):
(WebCore::FontPlatformData::hash):
(WebCore::FontPlatformData::operator==):
* platform/graphics/qt/FontPlatformDataQt.cpp:
(WebCore::FontPlatformData::FontPlatformData):

2009-11-03 Dan Bernstein <mitz@apple.com>

Leopard build fix
@@ -1187,6 +1187,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 \
@@ -1197,6 +1198,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 \
@@ -2382,7 +2384,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 \
@@ -38,256 +38,32 @@ 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)
FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
{
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)
{
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&)
{
return new FontPlatformData();
}

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();
return new FontPlatformData(fontDescription);
}

} // namespace WebCore

0 comments on commit e0e7dd9

Please sign in to comment.