diff options
Diffstat (limited to 'WebCore/platform/graphics/qt')
-rw-r--r-- | WebCore/platform/graphics/qt/FontCacheQt.cpp | 230 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/FontFallbackListQt.cpp | 44 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/FontPlatformData.h | 34 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/FontPlatformDataQt.cpp | 18 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/FontQt.cpp | 18 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/FontQt43.cpp | 16 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/GradientQt.cpp | 2 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/GraphicsContextQt.cpp | 30 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/IconQt.cpp | 5 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/ImageBufferQt.cpp | 29 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/ImageDecoderQt.cpp | 24 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/ImageDecoderQt.h | 4 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/ImageQt.cpp | 11 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/ImageSourceQt.cpp | 17 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp | 19 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/PathQt.cpp | 19 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/TransformationMatrixQt.cpp | 2 |
17 files changed, 402 insertions, 120 deletions
diff --git a/WebCore/platform/graphics/qt/FontCacheQt.cpp b/WebCore/platform/graphics/qt/FontCacheQt.cpp index 668912e..5d29389 100644 --- a/WebCore/platform/graphics/qt/FontCacheQt.cpp +++ b/WebCore/platform/graphics/qt/FontCacheQt.cpp @@ -1,6 +1,8 @@ /* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) Copyright (C) 2008 Holger Hans Peter Freyther + Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -26,10 +28,13 @@ #include "FontDescription.h" #include "FontPlatformData.h" #include "Font.h" +#include "PlatformString.h" #include "StringHash.h" +#include <utility> +#include <wtf/ListHashSet.h> #include <wtf/StdLibExtras.h> -#include <QHash> +using namespace WTF; namespace WebCore { @@ -47,36 +52,173 @@ void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigne { } -typedef QHash<FontDescription, FontPlatformData*> FontPlatformDataCache; +// 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_bold(false) + , m_size(description.computedPixelSize()) + , 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; -// using Q_GLOBAL_STATIC leads to crash. TODO investigate the way to fix this. -static FontPlatformDataCache* gFontPlatformDataCache; + const FontFamily* family = &description.family(); + while (family) { + m_familyName.append(family->family()); + family = family->next(); + if (family) + m_familyName.append(','); + } -uint qHash(const FontDescription& key) -{ - uint value = CaseFoldingHash::hash(key.family().family()); - value ^= key.computedPixelSize(); - value ^= static_cast<int>(key.weight()); - return value; -} + 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& family, bool checkingAlternateName) { if (!gFontPlatformDataCache) gFontPlatformDataCache = new FontPlatformDataCache; - FontPlatformData* fontData = gFontPlatformDataCache->value(description, 0); - if (!fontData) { - fontData = new FontPlatformData(description); - gFontPlatformDataCache->insert(description, fontData); + FontPlatformDataCacheKey key(description); + FontPlatformData* platformData = gFontPlatformDataCache->get(key); + if (!platformData) { + platformData = new FontPlatformData(description); + gFontPlatformDataCache->add(key, platformData); } - - return fontData; + return platformData; } -SimpleFontData* FontCache::getCachedFontData(const FontPlatformData*) +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) { - return 0; + 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&) @@ -84,8 +226,52 @@ FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription&) return 0; } -void FontCache::releaseFontData(const WebCore::SimpleFontData*) +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) +{ + 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; } void FontCache::addClient(FontSelector*) @@ -98,10 +284,10 @@ void FontCache::removeClient(FontSelector*) void FontCache::invalidate() { - if (!gFontPlatformDataCache) + if (!gFontPlatformDataCache || !gFontDataCache) return; - gFontPlatformDataCache->clear(); + purgeInactiveFontData(); } } // namespace WebCore diff --git a/WebCore/platform/graphics/qt/FontFallbackListQt.cpp b/WebCore/platform/graphics/qt/FontFallbackListQt.cpp index 50627b7..c29fd56 100644 --- a/WebCore/platform/graphics/qt/FontFallbackListQt.cpp +++ b/WebCore/platform/graphics/qt/FontFallbackListQt.cpp @@ -25,6 +25,7 @@ #include "FontFallbackList.h" #include "Font.h" +#include "FontCache.h" #include "SegmentedFontData.h" #include <QDebug> @@ -32,16 +33,23 @@ namespace WebCore { FontFallbackList::FontFallbackList() - : m_familyIndex(0) + : m_pageZero(0) + , m_cachedPrimarySimpleFontData(0) + , m_fontSelector(0) + , m_familyIndex(0) , m_pitch(UnknownPitch) , m_loadingCustomFonts(false) - , m_fontSelector(0) , 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; @@ -51,14 +59,20 @@ void FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector> fontSel void FontFallbackList::releaseFontData() { - if (m_fontList.size()) - delete m_fontList[0].first; - m_fontList.clear(); + 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 = primaryFont(font); + const FontData* fontData = primaryFontData(font); if (!fontData->isSegmented()) m_pitch = static_cast<const SimpleFontData*>(fontData)->pitch(); else { @@ -76,6 +90,14 @@ const FontData* FontFallbackList::fontDataAt(const WebCore::Font* _font, unsigne 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(); @@ -85,6 +107,10 @@ const FontData* FontFallbackList::fontDataAt(const WebCore::Font* _font, unsigne 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; } } @@ -94,14 +120,14 @@ const FontData* FontFallbackList::fontDataAt(const WebCore::Font* _font, unsigne if (m_fontList.size()) return m_fontList[0].first; - const FontData* result = new SimpleFontData(FontPlatformData(description), _font->wordSpacing(), _font->letterSpacing()); - m_fontList.append(pair<const FontData*, bool>(result, result->isCustomFont())); + 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 primaryFont(font); + return primaryFontData(font); } void FontFallbackList::setPlatformFont(const WebCore::FontPlatformData& platformData) diff --git a/WebCore/platform/graphics/qt/FontPlatformData.h b/WebCore/platform/graphics/qt/FontPlatformData.h index 5e97678..92219fd 100644 --- a/WebCore/platform/graphics/qt/FontPlatformData.h +++ b/WebCore/platform/graphics/qt/FontPlatformData.h @@ -1,6 +1,7 @@ /* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) Copyright (C) 2008 Holger Hans Peter Freyther + Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -24,11 +25,12 @@ #define FontPlatformData_h #include "FontDescription.h" - #include <QFont> namespace WebCore { +class String; + class FontPlatformData { public: @@ -39,8 +41,38 @@ public: FontPlatformData(const FontDescription&, int wordSpacing = 0, int letterSpacing = 0); FontPlatformData(const QFont&, bool bold); + static inline QFont::Weight toQFontWeight(FontWeight fontWeight) + { + switch (fontWeight) { + case FontWeight100: + case FontWeight200: + return QFont::Light; // QFont::Light == Weight of 25 + case FontWeight600: + return QFont::DemiBold; // QFont::DemiBold == Weight of 63 + case FontWeight700: + case FontWeight800: + return QFont::Bold; // QFont::Bold == Weight of 75 + case FontWeight900: + return QFont::Black; // QFont::Black == Weight of 87 + case FontWeight300: + case FontWeight400: + case FontWeight500: + default: + return QFont::Normal; // QFont::Normal == Weight of 50 + } + } + 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(); } + +#ifndef NDEBUG + String description() const; +#endif float m_size; bool m_bold; diff --git a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp index f0dd3ea..7709be6 100644 --- a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp +++ b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp @@ -1,5 +1,6 @@ /* Copyright (C) 2008 Holger Hans Peter Freyther + Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -21,6 +22,8 @@ #include "config.h" #include "FontPlatformData.h" +#include "PlatformString.h" + namespace WebCore { FontPlatformData::FontPlatformData(const FontDescription& description, int wordSpacing, int letterSpacing) @@ -40,11 +43,9 @@ FontPlatformData::FontPlatformData(const FontDescription& description, int wordS m_font.setFamily(familyName); m_font.setPixelSize(qRound(description.computedSize())); m_font.setItalic(description.italic()); - // FIXME: Map all FontWeight values to QFont weights. - if (description.weight() >= FontWeight600) - m_font.setWeight(QFont::Bold); - else - m_font.setWeight(QFont::Normal); + + m_font.setWeight(toQFontWeight(description.weight())); + m_bold = m_font.bold(); bool smallCaps = description.smallCaps(); m_font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase); @@ -77,4 +78,11 @@ FontPlatformData::FontPlatformData() { } +#ifndef NDEBUG +String FontPlatformData::description() const +{ + return String(); +} +#endif + } diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp index 5a4b7b2..e8eb923 100644 --- a/WebCore/platform/graphics/qt/FontQt.cpp +++ b/WebCore/platform/graphics/qt/FontQt.cpp @@ -47,8 +47,8 @@ namespace WebCore { static const QString qstring(const TextRun& run) { - //We don't detach - return QString::fromRawData((const QChar *)run.characters(), run.length()); + // We don't detach + return QString::fromRawData(reinterpret_cast<const QChar*>(run.characters()), run.length()); } static const QString fixSpacing(const QString &string) @@ -57,11 +57,10 @@ static const QString fixSpacing(const QString &string) QString possiblyDetached = string; for (int i = 0; i < string.length(); ++i) { const QChar c = string.at(i); - if (c.unicode() != 0x20 && Font::treatAsSpace(c.unicode())) { - possiblyDetached[i] = 0x20; //detach - } else if (c.unicode() != 0x200c && Font::treatAsZeroWidthSpace(c.unicode())) { - possiblyDetached[i] = 0x200c; //detach - } + if (c.unicode() != 0x20 && Font::treatAsSpace(c.unicode())) + possiblyDetached[i] = 0x20; // detach + else if (c.unicode() != 0x200c && Font::treatAsZeroWidthSpace(c.unicode())) + possiblyDetached[i] = 0x200c; // detach } return possiblyDetached; } @@ -222,7 +221,10 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& QFont Font::font() const { - return primaryFont()->getQtFont(); + QFont f = primaryFont()->getQtFont(); + f.setLetterSpacing(QFont::AbsoluteSpacing, m_letterSpacing); + f.setWordSpacing(m_wordSpacing); + return f; } } diff --git a/WebCore/platform/graphics/qt/FontQt43.cpp b/WebCore/platform/graphics/qt/FontQt43.cpp index 137b7c9..45bf05d 100644 --- a/WebCore/platform/graphics/qt/FontQt43.cpp +++ b/WebCore/platform/graphics/qt/FontQt43.cpp @@ -105,9 +105,9 @@ static int generateComponents(Vector<TextRunComponent, 1024>* components, const offset += add + letterSpacing + components->last().width; start = 1; // qDebug() << "space at 0" << offset; - } else if (smallCaps) { + } else if (smallCaps) f = (QChar::category(run[0]) == QChar::Letter_Lowercase ? &font.scFont() : &font.font()); - } + for (int i = 1; i < run.length(); ++i) { uint ch = run[i]; if (QChar(ch).isHighSurrogate() && QChar(run[i-1]).isLowSurrogate()) @@ -263,7 +263,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool if (!l.isValid()) return offset; - l.setLineWidth(INT_MAX/256); + l.setLineWidth(INT_MAX / 256); layout.endLayout(); if (position - xs >= l.width()) @@ -272,9 +272,8 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool if (cursor > 1) --cursor; return offset + cursor; - } else { + } else offset += components.at(i).string.length() - 1; - } } } else { for (int i = 0; i < components.size(); ++i) { @@ -287,7 +286,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool if (!l.isValid()) return offset; - l.setLineWidth(INT_MAX/256); + l.setLineWidth(INT_MAX / 256); layout.endLayout(); if (position - xs >= l.width()) @@ -296,9 +295,8 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool if (cursor > 1) --cursor; return offset + cursor; - } else { + } else offset += components.at(i).string.length() - 1; - } } } return run.length(); @@ -321,7 +319,7 @@ static float cursorToX(const Vector<TextRunComponent, 1024>& components, int wid if (!l.isValid()) return 0; - l.setLineWidth(INT_MAX/256); + l.setLineWidth(INT_MAX / 256); layout.endLayout(); return xs + l.cursorToX(cursor - start + 1); diff --git a/WebCore/platform/graphics/qt/GradientQt.cpp b/WebCore/platform/graphics/qt/GradientQt.cpp index 1e71f58..9b9acc2 100644 --- a/WebCore/platform/graphics/qt/GradientQt.cpp +++ b/WebCore/platform/graphics/qt/GradientQt.cpp @@ -67,7 +67,7 @@ QGradient* Gradient::platformGradient() ++stopIterator; } - switch(m_spreadMethod) { + switch (m_spreadMethod) { case SpreadMethodPad: m_gradient->setSpread(QGradient::PadSpread); break; diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index ed7ac47..e259a4e 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -95,7 +95,8 @@ static inline QPainter::CompositionMode toQtCompositionMode(CompositeOperator op case CompositeXOR: return QPainter::CompositionMode_Xor; case CompositePlusDarker: - return QPainter::CompositionMode_SourceOver; + // there is no exact match, but this is the closest + return QPainter::CompositionMode_Darken; case CompositeHighlight: return QPainter::CompositionMode_SourceOver; case CompositePlusLighter: @@ -155,7 +156,7 @@ static Qt::PenStyle toQPenStyle(StrokeStyle style) static inline Qt::FillRule toQtFillRule(WindRule rule) { - switch(rule) { + switch (rule) { case RULE_EVENODD: return Qt::OddEvenFill; case RULE_NONZERO: @@ -165,8 +166,7 @@ static inline Qt::FillRule toQtFillRule(WindRule rule) return Qt::OddEvenFill; } -struct TransparencyLayer -{ +struct TransparencyLayer { TransparencyLayer(const QPainter* p, const QRect &rect) : pixmap(rect.width(), rect.height()) { @@ -198,8 +198,7 @@ private: TransparencyLayer & operator=(const TransparencyLayer &) { return *this; } }; -class GraphicsContextPlatformPrivate -{ +class GraphicsContextPlatformPrivate { public: GraphicsContextPlatformPrivate(QPainter* painter); ~GraphicsContextPlatformPrivate(); @@ -217,7 +216,7 @@ public: bool antiAliasingForRectsAndLines; - QStack<TransparencyLayer *> layers; + QStack<TransparencyLayer*> layers; QPainter* redirect; QBrush solidColor; @@ -242,9 +241,8 @@ GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p) antiAliasingForRectsAndLines = painter->testRenderHint(QPainter::Antialiasing); // FIXME: Maybe only enable in SVG mode? painter->setRenderHint(QPainter::Antialiasing, true); - } else { + } else antiAliasingForRectsAndLines = false; - } } GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate() @@ -265,7 +263,7 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext* context) GraphicsContext::~GraphicsContext() { - while(!m_data->layers.isEmpty()) + while (!m_data->layers.isEmpty()) endTransparencyLayer(); destroyGraphicsContextPrivate(m_common); @@ -280,7 +278,7 @@ PlatformGraphicsContext* GraphicsContext::platformContext() const TransformationMatrix GraphicsContext::getCTM() const { QTransform matrix(platformContext()->combinedTransform()); - return TransformationMatrix(matrix.m11(), matrix.m12(), 0, matrix.m13(), + return TransformationMatrix(matrix.m11(), matrix.m12(), 0, matrix.m13(), matrix.m21(), matrix.m22(), 0, matrix.m23(), 0, 0, 1, 0, matrix.m31(), matrix.m32(), 0, matrix.m33()); @@ -763,7 +761,6 @@ void GraphicsContext::clipPath(WindRule clipRule) * RenderTheme handles drawing focus on widgets which * need it. */ -Color focusRingColor() { return Color(0, 0, 0); } void GraphicsContext::drawFocusRing(const Color& color) { if (paintingDisabled()) @@ -1127,8 +1124,9 @@ void GraphicsContext::concatCTM(const TransformationMatrix& transform) m_data->p()->setWorldTransform(transform, true); - // Transformations to the context shouldn't transform the currentPath. - // We have to undo every change made to the context from the currentPath to avoid wrong drawings. + // Transformations to the context shouldn't transform the currentPath. + // We have to undo every change made to the context from the currentPath + // to avoid wrong drawings. if (!m_data->currentPath.isEmpty() && transform.isInvertible()) { QTransform matrix = transform.inverse(); m_data->currentPath = m_data->currentPath * matrix; @@ -1211,7 +1209,7 @@ HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlpha bitmapInfo.bmiHeader.biClrImportant = 0; void* pixels = 0; - HBITMAP bitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0); + HBITMAP bitmap = ::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0); if (!bitmap) return 0; @@ -1229,7 +1227,7 @@ HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlpha memset(bmpInfo.bmBits, 0, bufferSize); } -#if !PLATFORM(WIN_CE) +#if !PLATFORM(WINCE) // Make sure we can do world transforms. SetGraphicsMode(bitmapDC, GM_ADVANCED); diff --git a/WebCore/platform/graphics/qt/IconQt.cpp b/WebCore/platform/graphics/qt/IconQt.cpp index c9f3ced..34c3c47 100644 --- a/WebCore/platform/graphics/qt/IconQt.cpp +++ b/WebCore/platform/graphics/qt/IconQt.cpp @@ -39,7 +39,7 @@ Icon::Icon() Icon::~Icon() { } - + PassRefPtr<Icon> Icon::createIconForFile(const String& filename) { RefPtr<Icon> i = adoptRef(new Icon); @@ -57,9 +57,8 @@ void Icon::paint(GraphicsContext* ctx, const IntRect& rect) { QPixmap px = m_icon.pixmap(rect.size()); QPainter *p = static_cast<QPainter*>(ctx->platformContext()); - if (p && !px.isNull()) { + if (p && !px.isNull()) p->drawPixmap(rect.x(), rect.y(), px); - } } } diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp index 506a8ea..22a5a43 100644 --- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -40,6 +40,7 @@ #include <QImageWriter> #include <QPainter> #include <QPixmap> +#include <math.h> namespace WebCore { @@ -67,7 +68,7 @@ ImageBufferData::ImageBufferData(const IntSize& size) painter->setCompositionMode(QPainter::CompositionMode_SourceOver); } -ImageBuffer::ImageBuffer(const IntSize& size, bool grayScale, bool& success) +ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, bool& success) : m_data(size) , m_size(size) { @@ -98,6 +99,32 @@ Image* ImageBuffer::image() const return m_image.get(); } +void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) +{ + bool isPainting = m_data.m_painter->isActive(); + if (isPainting) + m_data.m_painter->end(); + + QImage image = m_data.m_pixmap.toImage().convertToFormat(QImage::Format_ARGB32); + ASSERT(!image.isNull()); + + for (int y = 0; y < m_size.height(); ++y) { + for (int x = 0; x < m_size.width(); x++) { + QRgb value = image.pixel(x, y); + value = qRgba(lookUpTable[qRed(value)], + lookUpTable[qGreen(value)], + lookUpTable[qBlue(value)], + lookUpTable[qAlpha(value)]); + image.setPixel(x, y, value); + } + } + + m_data.m_pixmap = QPixmap::fromImage(image); + + if (isPainting) + m_data.m_painter->begin(&m_data.m_pixmap); +} + PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const { PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height()); diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp index cd32428..7bbdcc0 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp @@ -118,7 +118,7 @@ ImageDecoderQt::ReadContext::ReadResult // Attempt to construct an empty image of the matching size and format // for efficient reading QImage newImage = m_dataFormat != QImage::Format_Invalid ? - QImage(m_size,m_dataFormat) : QImage(); + QImage(m_size, m_dataFormat) : QImage(); m_target.push_back(ImageData(newImage)); } @@ -137,8 +137,8 @@ ImageDecoderQt::ReadContext::ReadResult const bool supportsAnimation = m_reader.supportsAnimation(); if (debugImageDecoderQt) - qDebug() << "readImage(): #" << m_target.size() << " complete, " << m_size << " format " << m_dataFormat - << " supportsAnimation=" << supportsAnimation ; + qDebug() << "readImage(): #" << m_target.size() << " complete, " << m_size + << " format " << m_dataFormat << " supportsAnimation=" << supportsAnimation; // No point in readinfg further if (!supportsAnimation) return ReadComplete; @@ -158,7 +158,7 @@ ImageDecoderQt::ReadContext::IncrementalReadResult // set state to reflect complete header, etc. // For now, we read the whole image. - const qint64 startPos = m_buffer.pos (); + const qint64 startPos = m_buffer.pos(); // Oops, failed. Rewind. if (!m_reader.read(&imageData.m_image)) { m_buffer.seek(startPos); @@ -217,9 +217,7 @@ void ImageDecoderQt::reset() m_failed = false; m_imageList.clear(); m_pixmapCache.clear(); - m_sizeAvailable = false; m_loopCount = cAnimationNone; - m_size = IntSize(-1, -1); } void ImageDecoderQt::setData(const IncomingData &data, bool allDataReceived) @@ -238,7 +236,7 @@ void ImageDecoderQt::setData(const IncomingData &data, bool allDataReceived) if (debugImageDecoderQt) qDebug() << " read returns " << readResult; - switch ( readResult) { + switch (readResult) { case ReadContext::ReadFailed: m_failed = true; break; @@ -247,8 +245,8 @@ void ImageDecoderQt::setData(const IncomingData &data, bool allDataReceived) case ReadContext::ReadComplete: // Did we read anything - try to set the size. if (hasFirstImageHeader()) { - m_sizeAvailable = true; - m_size = m_imageList[0].m_image.size(); + QSize imgSize = m_imageList[0].m_image.size(); + setSize(imgSize.width(), imgSize.height()); if (readContext.reader()->supportsAnimation()) { if (readContext.reader()->loopCount() != -1) @@ -262,14 +260,14 @@ void ImageDecoderQt::setData(const IncomingData &data, bool allDataReceived) } -bool ImageDecoderQt::isSizeAvailable() const +bool ImageDecoderQt::isSizeAvailable() { if (debugImageDecoderQt) - qDebug() << " ImageDecoderQt::isSizeAvailable() returns" << m_sizeAvailable; - return m_sizeAvailable; + qDebug() << " ImageDecoderQt::isSizeAvailable() returns" << ImageDecoder::isSizeAvailable(); + return ImageDecoder::isSizeAvailable(); } -int ImageDecoderQt::frameCount() const +size_t ImageDecoderQt::frameCount() const { if (debugImageDecoderQt) qDebug() << " ImageDecoderQt::frameCount() returns" << m_imageList.size(); diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h index b8c3edd..fc52479 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.h +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h @@ -45,8 +45,8 @@ public: typedef Vector<char> IncomingData; virtual void setData(const IncomingData& data, bool allDataReceived); - virtual bool isSizeAvailable() const; - virtual int frameCount() const; + virtual bool isSizeAvailable(); + virtual size_t frameCount() const; virtual int repetitionCount() const; virtual RGBA32Buffer* frameBufferAtIndex(size_t index); diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp index a2e96f3..5d40e26 100644 --- a/WebCore/platform/graphics/qt/ImageQt.cpp +++ b/WebCore/platform/graphics/qt/ImageQt.cpp @@ -83,7 +83,6 @@ bool FrameData::clear(bool clearMetadata) } - // ================================================ // Image Class // ================================================ @@ -93,7 +92,6 @@ PassRefPtr<Image> Image::loadPlatformResource(const char* name) return StillImage::create(loadResourcePixmap(name)); } - void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect) { @@ -103,9 +101,8 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const QPixmap pixmap = *framePixmap; QRect tr = QRectF(tileRect).toRect(); - if (tr.x() || tr.y() || tr.width() != pixmap.width() || tr.height() != pixmap.height()) { + if (tr.x() || tr.y() || tr.width() != pixmap.width() || tr.height() != pixmap.height()) pixmap = pixmap.copy(tr); - } QBrush b(pixmap); b.setTransform(patternTransform); @@ -129,7 +126,7 @@ void BitmapImage::initPlatformData() void BitmapImage::invalidatePlatformData() { } - + // Drawing Routines void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, CompositeOperator op) @@ -139,7 +136,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, QPixmap* image = nativeImageForCurrentFrame(); if (!image) return; - + if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, dst, solidColor(), op); return; @@ -158,7 +155,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, painter->setCompositionMode(QPainter::CompositionMode_Source); // Test using example site at - // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html + // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html painter->drawPixmap(dst, *image, src); ctxt->restore(); diff --git a/WebCore/platform/graphics/qt/ImageSourceQt.cpp b/WebCore/platform/graphics/qt/ImageSourceQt.cpp index 621728e..8ae449c 100644 --- a/WebCore/platform/graphics/qt/ImageSourceQt.cpp +++ b/WebCore/platform/graphics/qt/ImageSourceQt.cpp @@ -91,9 +91,12 @@ IntSize ImageSource::size() const return m_decoder->size(); } -IntSize ImageSource::frameSizeAtIndex(size_t) const +IntSize ImageSource::frameSizeAtIndex(size_t index) const { - return size(); + if (!m_decoder) + return IntSize(); + + return m_decoder->frameSizeAtIndex(index); } int ImageSource::repetitionCount() @@ -124,7 +127,7 @@ float ImageSource::frameDurationAtIndex(size_t index) { if (!m_decoder) return 0; - + // Many annoying ads specify a 0 duration to make an image flash as quickly // as possible. We follow WinIE's behavior and use a duration of 100 ms // for any frames that specify a duration of <= 50 ms. See @@ -138,17 +141,17 @@ bool ImageSource::frameHasAlphaAtIndex(size_t index) { if (!m_decoder || !m_decoder->supportsAlpha()) return false; - - const QPixmap* source = m_decoder->imageAtIndex( index); + + const QPixmap* source = m_decoder->imageAtIndex(index); if (!source) return false; - + return source->hasAlphaChannel(); } bool ImageSource::frameIsCompleteAtIndex(size_t index) { - return (m_decoder && m_decoder->imageAtIndex(index) != 0); + return (m_decoder && m_decoder->imageAtIndex(index)); } void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived) diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp index c80d73b..76b1494 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp @@ -36,11 +36,14 @@ #include <QMetaEnum> #include <QUrl> #include <QEvent> -#include <phonon> + +#include <Phonon/AudioOutput> +#include <Phonon/MediaObject> +#include <Phonon/VideoWidget> using namespace Phonon; -#define LOG_MEDIAOBJECT() (LOG(Media,"%s", debugMediaObject(this, *m_mediaObject).constData())) +#define LOG_MEDIAOBJECT() (LOG(Media, "%s", debugMediaObject(this, *m_mediaObject).constData())) static QByteArray debugMediaObject(WebCore::MediaPlayerPrivate* mediaPlayer, const MediaObject& mediaObject) { @@ -94,9 +97,8 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) // Make sure we get updates for each frame m_videoWidget->installEventFilter(this); - foreach(QWidget* widget, qFindChildren<QWidget*>(m_videoWidget)) { + foreach (QWidget* widget, qFindChildren<QWidget*>(m_videoWidget)) widget->installEventFilter(this); - } connect(m_mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged(Phonon::State, Phonon::State))); @@ -111,8 +113,8 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) connect(m_mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64))); } -MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) -{ +MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) +{ return new MediaPlayerPrivate(player); } @@ -263,7 +265,7 @@ float MediaPlayerPrivate::maxTimeSeekable() const } unsigned MediaPlayerPrivate::bytesLoaded() const -{ +{ notImplemented(); return 0; } @@ -343,9 +345,8 @@ void MediaPlayerPrivate::updateStates() m_networkState = MediaPlayer::NetworkError; m_readyState = MediaPlayer::HaveNothing; cancelLoad(); - } else { + } else m_mediaObject->pause(); - } } if (seeking()) diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index 7569031..e5cecc8 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -92,7 +92,7 @@ bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) // FIXME: We should try to use a 'shared Context' instead of creating a new ImageBuffer // on each call. - OwnPtr<ImageBuffer> scratchImage = ImageBuffer::create(IntSize(1, 1), false); + OwnPtr<ImageBuffer> scratchImage = ImageBuffer::create(IntSize(1, 1)); GraphicsContext* gc = scratchImage->context(); QPainterPathStroker stroke; applier->strokeStyle(gc); @@ -124,7 +124,7 @@ FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) { // FIXME: We should try to use a 'shared Context' instead of creating a new ImageBuffer // on each call. - OwnPtr<ImageBuffer> scratchImage = ImageBuffer::create(IntSize(1, 1), false); + OwnPtr<ImageBuffer> scratchImage = ImageBuffer::create(IntSize(1, 1)); GraphicsContext* gc = scratchImage->context(); QPainterPathStroker stroke; if (applier) { @@ -170,8 +170,8 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) return; } - FloatPoint p1p0((p0.x() - p1.x()),(p0.y() - p1.y())); - FloatPoint p1p2((p2.x() - p1.x()),(p2.y() - p1.y())); + FloatPoint p1p0((p0.x() - p1.x()), (p0.y() - p1.y())); + FloatPoint p1p2((p2.x() - p1.x()), (p2.y() - p1.y())); float p1p0_length = sqrtf(p1p0.x() * p1p0.x() + p1p0.y() * p1p0.y()); float p1p2_length = sqrtf(p1p2.x() * p1p2.x() + p1p2.y() * p1p2.y()); @@ -216,7 +216,7 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) float factor_p1p2 = tangent / p1p2_length; FloatPoint t_p1p2((p1.x() + factor_p1p2 * p1p2.x()), (p1.y() + factor_p1p2 * p1p2.y())); - FloatPoint orth_p1p2((t_p1p2.x() - p.x()),(t_p1p2.y() - p.y())); + FloatPoint orth_p1p2((t_p1p2.x() - p.x()), (t_p1p2.y() - p.y())); float orth_p1p2_length = sqrtf(orth_p1p2.x() * orth_p1p2.x() + orth_p1p2.y() * orth_p1p2.y()); float ea = acos(orth_p1p2.x() / orth_p1p2_length); if (orth_p1p2.y() < 0) @@ -298,7 +298,14 @@ void Path::clear() bool Path::isEmpty() const { - return m_path->isEmpty(); + // Don't use QPainterPath::isEmpty(), as that also returns true if there's only + // one initial MoveTo element in the path. + return !m_path->elementCount(); +} + +bool Path::hasCurrentPoint() const +{ + return !isEmpty(); } String Path::debugString() const diff --git a/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp b/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp index 15f0cc5..37b86f3 100644 --- a/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp +++ b/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp @@ -32,7 +32,7 @@ namespace WebCore { TransformationMatrix::operator QTransform() const -{ +{ return QTransform(m11(), m12(), m14(), m21(), m22(), m24(), m41(), m42(), m44()); } |