diff options
author | Kristian Monsen <kristianm@google.com> | 2010-09-30 15:42:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2010-10-07 10:59:29 +0100 |
commit | bec39347bb3bb5bf1187ccaf471d26247f28b585 (patch) | |
tree | 56bdc4c2978fbfd3d79d0d36d5d6c640ecc09cc8 /WebCore/platform/graphics | |
parent | 90b7966e7815b262cd19ac25f03aaad9b21fdc06 (diff) | |
download | external_webkit-bec39347bb3bb5bf1187ccaf471d26247f28b585.zip external_webkit-bec39347bb3bb5bf1187ccaf471d26247f28b585.tar.gz external_webkit-bec39347bb3bb5bf1187ccaf471d26247f28b585.tar.bz2 |
Merge WebKit at r68651 : Initial merge by git.
Change-Id: I3d6bff59f17eedd6722723354f386fec9be8ad12
Diffstat (limited to 'WebCore/platform/graphics')
135 files changed, 6227 insertions, 1515 deletions
diff --git a/WebCore/platform/graphics/Color.cpp b/WebCore/platform/graphics/Color.cpp index 80c8286..f28d51c 100644 --- a/WebCore/platform/graphics/Color.cpp +++ b/WebCore/platform/graphics/Color.cpp @@ -26,13 +26,12 @@ #include "config.h" #include "Color.h" +#include "HashTools.h" #include "PlatformString.h" #include <math.h> #include <wtf/Assertions.h> #include <wtf/MathExtras.h> -#include "ColorData.cpp" - using namespace std; using namespace WTF; diff --git a/WebCore/platform/graphics/qt/ContextShadow.cpp b/WebCore/platform/graphics/ContextShadow.cpp index 4609923..1007962 100644 --- a/WebCore/platform/graphics/qt/ContextShadow.cpp +++ b/WebCore/platform/graphics/ContextShadow.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Sencha, Inc. + * Copyright (C) 2010 Igalia S.L. * * All rights reserved. * @@ -28,115 +29,50 @@ #include "config.h" #include "ContextShadow.h" -#include <QTimerEvent> +#include <wtf/MathExtras.h> #include <wtf/Noncopyable.h> -namespace WebCore { - -// ContextShadow needs a scratch image as the buffer for the blur filter. -// Instead of creating and destroying the buffer for every operation, -// we create a buffer which will be automatically purged via a timer. - -class ShadowBuffer: public QObject { -public: - ShadowBuffer(QObject* parent = 0); - - QImage* scratchImage(const QSize& size); - - void schedulePurge(); - -protected: - void timerEvent(QTimerEvent* event); - -private: - QImage image; - int timerId; -}; - -ShadowBuffer::ShadowBuffer(QObject* parent) - : QObject(parent) - , timerId(0) -{ -} - -QImage* ShadowBuffer::scratchImage(const QSize& size) -{ - int width = size.width(); - int height = size.height(); - - // We do not need to recreate the buffer if the buffer is reasonably - // larger than the requested size. However, if the requested size is - // much smaller than our buffer, reduce our buffer so that we will not - // keep too many allocated pixels for too long. - if (!image.isNull() && (image.width() > width) && (image.height() > height)) - if (((2 * width) > image.width()) && ((2 * height) > image.height())) { - image.fill(Qt::transparent); - return ℑ - } - - // Round to the nearest 32 pixels so we do not grow the buffer everytime - // there is larger request by 1 pixel. - width = (1 + (width >> 5)) << 5; - height = (1 + (height >> 5)) << 5; - - image = QImage(width, height, QImage::Format_ARGB32_Premultiplied); - image.fill(Qt::transparent); - return ℑ -} - -void ShadowBuffer::schedulePurge() -{ - static const double BufferPurgeDelay = 2; // seconds - killTimer(timerId); - timerId = startTimer(BufferPurgeDelay * 1000); -} - -void ShadowBuffer::timerEvent(QTimerEvent* event) -{ - if (event->timerId() == timerId) { - killTimer(timerId); - image = QImage(); - } - QObject::timerEvent(event); -} +using WTF::min; +using WTF::max; -Q_GLOBAL_STATIC(ShadowBuffer, scratchShadowBuffer) +namespace WebCore { ContextShadow::ContextShadow() - : type(NoShadow) - , blurRadius(0) + : m_type(NoShadow) + , m_blurRadius(0) { } -ContextShadow::ContextShadow(const QColor& c, float r, qreal dx, qreal dy) - : color(c) - , blurRadius(qRound(r)) - , offset(dx, dy) +ContextShadow::ContextShadow(const Color& color, float radius, const FloatSize& offset) + : m_color(color) + , m_blurRadius(round(radius)) + , m_offset(offset) { + // See comments in http://webkit.org/b/40793, it seems sensible + // to follow Skia's limit of 128 pixels of blur radius + m_blurRadius = min(m_blurRadius, 128); + // The type of shadow is decided by the blur radius, shadow offset, and shadow color. - if (!color.isValid() || !color.alpha()) { + if (!m_color.isValid() || !color.alpha()) { // Can't paint the shadow with invalid or invisible color. - type = NoShadow; - } else if (r > 0) { + m_type = NoShadow; + } else if (radius > 0) { // Shadow is always blurred, even the offset is zero. - type = BlurShadow; - } else if (offset.isNull()) { + m_type = BlurShadow; + } else if (!m_offset.width() && !m_offset.height()) { // Without blur and zero offset means the shadow is fully hidden. - type = NoShadow; + m_type = NoShadow; } else { - if (color.alpha() > 0) - type = AlphaSolidShadow; - else - type = OpaqueSolidShadow; + m_type = SolidShadow; } } void ContextShadow::clear() { - type = NoShadow; - color = QColor(); - blurRadius = 0; - offset = QPointF(0, 0); + m_type = NoShadow; + m_color = Color(); + m_blurRadius = 0; + m_offset = FloatSize(); } // Instead of integer division, we use 17.15 for fixed-point division. @@ -146,27 +82,22 @@ static const int BlurSumShift = 15; // As noted in the SVG filter specification, running box blur 3x // approximates a real gaussian blur nicely. -void shadowBlur(QImage& image, int radius, const QColor& shadowColor) +void ContextShadow::blurLayerImage(unsigned char* imageData, const IntSize& size, int rowStride) { - // See comments in http://webkit.org/b/40793, it seems sensible - // to follow Skia's limit of 128 pixels for the blur radius. - if (radius > 128) - radius = 128; - int channels[4] = { 3, 0, 1, 3 }; - int dmax = radius >> 1; - int dmin = dmax - 1 + (radius & 1); + int dmax = m_blurRadius >> 1; + int dmin = dmax - 1 + (m_blurRadius & 1); if (dmin < 0) dmin = 0; // Two stages: horizontal and vertical for (int k = 0; k < 2; ++k) { - unsigned char* pixels = image.bits(); - int stride = (!k) ? 4 : image.bytesPerLine(); - int delta = (!k) ? image.bytesPerLine() : 4; - int jfinal = (!k) ? image.height() : image.width(); - int dim = (!k) ? image.width() : image.height(); + unsigned char* pixels = imageData; + int stride = (!k) ? 4 : rowStride; + int delta = (!k) ? rowStride : 4; + int jfinal = (!k) ? size.height() : size.width(); + int dim = (!k) ? size.width() : size.height(); for (int j = 0; j < jfinal; ++j, pixels += delta) { @@ -213,74 +144,31 @@ void shadowBlur(QImage& image, int radius, const QColor& shadowColor) } } } - - // "Colorize" with the right shadow color. - QPainter p(&image); - p.setCompositionMode(QPainter::CompositionMode_SourceIn); - p.fillRect(image.rect(), shadowColor.rgb()); - p.end(); } -QPainter* ContextShadow::beginShadowLayer(QPainter* p, const QRectF &rect) +void ContextShadow::calculateLayerBoundingRect(const FloatRect& layerArea, const IntRect& clipRect) { - // We expand the area by the blur radius * 2 to give extra space - // for the blur transition. - int extra = (type == BlurShadow) ? blurRadius * 2 : 0; - - QRectF shadowRect = rect.translated(offset); - QRectF bufferRect = shadowRect.adjusted(-extra, -extra, extra, extra); - m_layerRect = bufferRect.toAlignedRect(); + // Calculate the destination of the blurred layer. + FloatRect destinationRect(layerArea); + destinationRect.move(m_offset); + m_layerRect = enclosingIntRect(destinationRect); - QRect clipRect; - if (p->hasClipping()) -#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0) - clipRect = p->clipBoundingRect(); -#else - clipRect = p->clipRegion().boundingRect(); -#endif - else - clipRect = p->transform().inverted().mapRect(p->window()); + // We expand the area by the blur radius * 2 to give extra space for the blur transition. + m_layerRect.inflate((m_type == BlurShadow) ? ceil(m_blurRadius * 2) : 0); if (!clipRect.contains(m_layerRect)) { - // No need to have the buffer larger than the clip. - m_layerRect = m_layerRect.intersected(clipRect); + m_layerRect.intersect(clipRect); + + // If we are totally outside the clip region, we aren't painting at all. if (m_layerRect.isEmpty()) - return 0; + return; // We adjust again because the pixels at the borders are still // potentially affected by the pixels outside the buffer. - if (type == BlurShadow) - m_layerRect.adjust(-extra, -extra, extra, extra); + if (m_type == BlurShadow) + m_layerRect.inflate((m_type == BlurShadow) ? ceil(m_blurRadius * 2) : 0); } - - ShadowBuffer* shadowBuffer = scratchShadowBuffer(); - QImage* shadowImage = shadowBuffer->scratchImage(m_layerRect.size()); - m_layerImage = QImage(*shadowImage); - - m_layerPainter = new QPainter; - m_layerPainter->begin(&m_layerImage); - m_layerPainter->setFont(p->font()); - m_layerPainter->translate(offset); - - // The origin is now the top left corner of the scratch image. - m_layerPainter->translate(-m_layerRect.topLeft()); - - return m_layerPainter; } -void ContextShadow::endShadowLayer(QPainter* p) -{ - m_layerPainter->end(); - delete m_layerPainter; - m_layerPainter = 0; - - if (type == BlurShadow) - shadowBlur(m_layerImage, blurRadius, color); - - p->drawImage(m_layerRect.topLeft(), m_layerImage); - - scratchShadowBuffer()->schedulePurge(); -} - -} +} // namespace WebCore diff --git a/WebCore/platform/graphics/qt/ContextShadow.h b/WebCore/platform/graphics/ContextShadow.h index 7140340..ede9336 100644 --- a/WebCore/platform/graphics/qt/ContextShadow.h +++ b/WebCore/platform/graphics/ContextShadow.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Sencha, Inc. + * Copyright (C) 2010 Igalia S.L. * * All rights reserved. * @@ -28,7 +29,22 @@ #ifndef ContextShadow_h #define ContextShadow_h -#include <QPainter> +#include "Color.h" +#include "FloatRect.h" +#include "IntRect.h" +#include "RefCounted.h" + +#if PLATFORM(CAIRO) +typedef struct _cairo cairo_t; +typedef struct _cairo_surface cairo_surface_t; +typedef cairo_surface_t* PlatformImage; +typedef cairo_t* PlatformContext; +#elif PLATFORM(QT) +#include <QImage> +class QPainter; +typedef QImage PlatformImage; +typedef QPainter* PlatformContext; +#endif namespace WebCore { @@ -44,49 +60,57 @@ class ContextShadow { public: enum { NoShadow, - OpaqueSolidShadow, - AlphaSolidShadow, + SolidShadow, BlurShadow - } type; + } m_type; - QColor color; - int blurRadius; - QPointF offset; + Color m_color; + int m_blurRadius; + FloatSize m_offset; ContextShadow(); - ContextShadow(const QColor& c, float r, qreal dx, qreal dy); + ContextShadow(const Color&, float radius, const FloatSize& offset); void clear(); // The pair beginShadowLayer and endShadowLayer creates a temporary image - // where the caller can draw onto, using the returned QPainter. This - // QPainter instance must be used only to draw between the call to - // beginShadowLayer and endShadowLayer. + // where the caller can draw onto, using the returned context. This context + // must be used only to draw between the call to beginShadowLayer and + // endShadowLayer. // - // Note: multiple/nested shadow layer is NOT allowed. + // Note: multiple/nested shadow layers are NOT allowed. // // The current clip region will be used to optimize the size of the - // temporary image. Thus, the original painter should not change any - // clipping until endShadowLayer. - // If the shadow will be completely outside the clipping region, - // beginShadowLayer will return 0. + // temporary image. Thus, the original context should not change any + // clipping until endShadowLayer. If the shadow will be completely outside + // the clipping region, beginShadowLayer will return 0. // - // The returned QPainter will have the transformation matrix and clipping - // properly initialized to start doing the painting (no need to account - // for the shadow offset), however it will not have the same render hints, - // pen, brush, etc as the passed QPainter. This is intentional, usually - // shadow has different properties than the shape which casts the shadow. + // The returned context will have the transformation matrix and clipping + // properly initialized to start doing the painting (no need to account for + // the shadow offset), however it will not have the same render hints, pen, + // brush, etc as the passed context. This is intentional, usually shadows + // have different properties than the shapes which cast them. // - // Once endShadowLayer is called, the temporary image will be drawn - // with the original painter. If blur radius is specified, the shadow - // will be filtered first. - QPainter* beginShadowLayer(QPainter* p, const QRectF& rect); - void endShadowLayer(QPainter* p); + // Once endShadowLayer is called, the temporary image will be drawn with the + // original context. If blur radius is specified, the shadow will be + // filtered first. + + PlatformContext beginShadowLayer(PlatformContext, const FloatRect& layerArea); + void endShadowLayer(PlatformContext); + static void purgeScratchBuffer(); + +#if PLATFORM(QT) + QPointF offset() { return QPointF(m_offset.width(), m_offset.height()); } +#endif + private: - QRect m_layerRect; - QImage m_layerImage; - QPainter* m_layerPainter; + IntRect m_layerRect; + PlatformImage m_layerImage; + PlatformContext m_layerContext; + + void blurLayerImage(unsigned char*, const IntSize& imageSize, int stride); + void calculateLayerBoundingRect(const FloatRect& layerArea, const IntRect& clipRect); }; } // namespace WebCore diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h index d6cf140..1a321bd 100644 --- a/WebCore/platform/graphics/Font.h +++ b/WebCore/platform/graphics/Font.h @@ -191,8 +191,8 @@ public: } FontSelector* fontSelector() const; - static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == 0x00A0; } - static bool treatAsZeroWidthSpace(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || (c >= 0x200c && c <= 0x200f) || (c >= 0x202a && c <= 0x202e) || c == 0xFFFC; } + static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == noBreakSpace; } + static bool treatAsZeroWidthSpace(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == softHyphen || (c >= 0x200c && c <= 0x200f) || (c >= 0x202a && c <= 0x202e) || c == objectReplacementCharacter; } static inline UChar normalizeSpaces(UChar character) { diff --git a/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/WebCore/platform/graphics/GlyphPageTreeNode.cpp index dac26b3..3df14b9 100644 --- a/WebCore/platform/graphics/GlyphPageTreeNode.cpp +++ b/WebCore/platform/graphics/GlyphPageTreeNode.cpp @@ -171,6 +171,7 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu buffer[i] = zeroWidthSpace; for (i = 0x7F; i < 0xA0; i++) buffer[i] = zeroWidthSpace; + buffer[softHyphen] = zeroWidthSpace; // \n, \t, and nonbreaking space must render as a space. buffer[(int)'\n'] = ' '; diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h index 7863b95..fd3bf2c 100644 --- a/WebCore/platform/graphics/GraphicsContext.h +++ b/WebCore/platform/graphics/GraphicsContext.h @@ -108,12 +108,6 @@ typedef unsigned char UInt8; #endif #endif -#if PLATFORM(CHROMIUM) -#define CanvasInterpolationQuality InterpolationMedium -#else -#define CanvasInterpolationQuality InterpolationDefault -#endif - #if PLATFORM(QT) && defined(Q_WS_WIN) #include <windows.h> #endif diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp index 2da5862..86e9569 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.cpp +++ b/WebCore/platform/graphics/GraphicsContext3D.cpp @@ -255,6 +255,14 @@ void unpackRGB8ToRGBA8(const uint8_t* source, uint8_t* destination) destination[3] = 0xFF; } +void unpackARGB8ToRGBA8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[1]; + destination[1] = source[2]; + destination[2] = source[3]; + destination[3] = source[0]; +} + void unpackBGRA8ToRGBA8(const uint8_t* source, uint8_t* destination) { destination[0] = source[2]; @@ -316,6 +324,14 @@ void unpackRA8ToRGBA8(const uint8_t* source, uint8_t* destination) destination[3] = source[1]; } +void unpackAR8ToRGBA8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[1]; + destination[1] = source[1]; + destination[2] = source[1]; + destination[3] = source[0]; +} + void unpackA8ToRGBA8(const uint8_t* source, uint8_t* destination) { destination[0] = 0x0; @@ -634,6 +650,12 @@ static void doPacking(const void* sourceData, doUnpackingAndPacking<uint8_t, DestType, unpackRGB8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } + case GraphicsContext3D::kSourceFormatARGB8: { + unsigned int sourceElementsPerPixel, sourceElementsPerRow; + computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); + doUnpackingAndPacking<uint8_t, DestType, unpackARGB8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); + break; + } case GraphicsContext3D::kSourceFormatBGRA8: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); @@ -670,6 +692,12 @@ static void doPacking(const void* sourceData, doUnpackingAndPacking<uint8_t, DestType, unpackRA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } + case GraphicsContext3D::kSourceFormatAR8: { + unsigned int sourceElementsPerPixel, sourceElementsPerRow; + computeIncrementParameters<uint8_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); + doUnpackingAndPacking<uint8_t, DestType, unpackAR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); + break; + } case GraphicsContext3D::kSourceFormatA8: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint8_t>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index bcb7997..a12b1c4 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -537,11 +537,13 @@ public: kSourceFormatRGBA8, kSourceFormatRGB8, kSourceFormatBGRA8, + kSourceFormatARGB8, kSourceFormatRGBA5551, kSourceFormatRGBA4444, kSourceFormatRGB565, kSourceFormatR8, kSourceFormatRA8, + kSourceFormatAR8, kSourceFormatA8 }; @@ -834,14 +836,14 @@ public: int m_currentWidth, m_currentHeight; - typedef struct { - String source; - String log; +#if PLATFORM(MAC) + typedef struct { + String source; + String log; bool isValid; } ShaderSourceEntry; HashMap<Platform3DObject, ShaderSourceEntry> m_shaderSourceMap; -#if PLATFORM(MAC) ANGLEWebKitBridge m_compiler; Attributes m_attrs; diff --git a/WebCore/platform/graphics/GraphicsLayer.cpp b/WebCore/platform/graphics/GraphicsLayer.cpp index b0f529b..412f06d 100644 --- a/WebCore/platform/graphics/GraphicsLayer.cpp +++ b/WebCore/platform/graphics/GraphicsLayer.cpp @@ -246,6 +246,12 @@ void GraphicsLayer::paintGraphicsLayerContents(GraphicsContext& context, const I m_client->paintContents(this, context, m_paintingPhase, clip); } +String GraphicsLayer::animationNameForTransition(AnimatedPropertyID property) +{ + // | is not a valid identifier character in CSS, so this can never conflict with a keyframe identifier. + return String::format("-|transition%c-", property); +} + void GraphicsLayer::suspendAnimations(double) { } diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h index 04899f2..ad4d056 100644 --- a/WebCore/platform/graphics/GraphicsLayer.h +++ b/WebCore/platform/graphics/GraphicsLayer.h @@ -284,13 +284,16 @@ public: IntRect contentsRect() const { return m_contentsRect; } virtual void setContentsRect(const IntRect& r) { m_contentsRect = r; } + // Transitions are identified by a special animation name that cannot clash with a keyframe identifier. + static String animationNameForTransition(AnimatedPropertyID); + // Return true if the animation is handled by the compositing system. If this returns // false, the animation will be run by AnimationController. - virtual bool addAnimation(const KeyframeValueList&, const IntSize& /*boxSize*/, const Animation*, const String& /*keyframesName*/, double /*timeOffset*/) { return false; } - virtual void removeAnimationsForProperty(AnimatedPropertyID) { } - virtual void removeAnimationsForKeyframes(const String& /* keyframesName */) { } - virtual void pauseAnimation(const String& /* keyframesName */, double /*timeOffset*/) { } - + // These methods handle both transitions and keyframe animations. + virtual bool addAnimation(const KeyframeValueList&, const IntSize& /*boxSize*/, const Animation*, const String& /*animationName*/, double /*timeOffset*/) { return false; } + virtual void pauseAnimation(const String& /*animationName*/, double /*timeOffset*/) { } + virtual void removeAnimation(const String& /*animationName*/) { } + virtual void suspendAnimations(double time); virtual void resumeAnimations(); diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp index b4a669c..79c33e0 100644 --- a/WebCore/platform/graphics/MediaPlayer.cpp +++ b/WebCore/platform/graphics/MediaPlayer.cpp @@ -173,6 +173,12 @@ static Vector<MediaPlayerFactory*>& installedMediaEngines() #if PLATFORM(WIN) MediaPlayerPrivateQuickTimeVisualContext::registerMediaEngine(addMediaEngine); +#elif PLATFORM(QT) +#if USE(QT_MULTIMEDIA) + MediaPlayerPrivateQt::registerMediaEngine(addMediaEngine); +#else + MediaPlayerPrivatePhonon::registerMediaEngine(addMediaEngine); +#endif #elif !PLATFORM(GTK) && !PLATFORM(EFL) // FIXME: currently all the MediaEngines are named // MediaPlayerPrivate. This code will need an update when bug diff --git a/WebCore/platform/graphics/WidthIterator.cpp b/WebCore/platform/graphics/WidthIterator.cpp index ef047e8..ae58918 100644 --- a/WebCore/platform/graphics/WidthIterator.cpp +++ b/WebCore/platform/graphics/WidthIterator.cpp @@ -212,20 +212,29 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) // Force characters that are used to determine word boundaries for the rounding hack // to be integer width, so following words will start on an integer boundary. - if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(c)) + if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(c)) { width = ceilf(width); - // Check to see if the next character is a "rounding hack character", if so, adjust - // width so that the total run width will be on an integer boundary. - if ((m_run.applyWordRounding() && currentCharacter < m_run.length() && Font::isRoundingHackCharacter(*cp)) - || (m_run.applyRunRounding() && currentCharacter >= m_end)) { - float totalWidth = widthSinceLastRounding + width; - widthSinceLastRounding = ceilf(totalWidth); - width += widthSinceLastRounding - totalWidth; - m_runWidthSoFar += widthSinceLastRounding; - widthSinceLastRounding = 0; - } else - widthSinceLastRounding += width; + // Since widthSinceLastRounding can lose precision if we include measurements for + // preceding whitespace, we bypass it here. + m_runWidthSoFar += width; + + // Since this is a rounding hack character, we should have reset this sum on the previous + // iteration. + ASSERT(!widthSinceLastRounding); + } else { + // Check to see if the next character is a "rounding hack character", if so, adjust + // width so that the total run width will be on an integer boundary. + if ((m_run.applyWordRounding() && currentCharacter < m_run.length() && Font::isRoundingHackCharacter(*cp)) + || (m_run.applyRunRounding() && currentCharacter >= m_end)) { + float totalWidth = widthSinceLastRounding + width; + widthSinceLastRounding = ceilf(totalWidth); + width += widthSinceLastRounding - totalWidth; + m_runWidthSoFar += widthSinceLastRounding; + widthSinceLastRounding = 0; + } else + widthSinceLastRounding += width; + } if (glyphBuffer) glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width)); diff --git a/WebCore/platform/graphics/brew/ImageBrew.cpp b/WebCore/platform/graphics/brew/ImageBrew.cpp new file mode 100644 index 0000000..f5c855d --- /dev/null +++ b/WebCore/platform/graphics/brew/ImageBrew.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2010, Company 100, 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER OR 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 "Image.h" + +#include "BitmapImage.h" +#include "FileSystem.h" +#include "SharedBuffer.h" + +#include <wtf/text/CString.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +PassRefPtr<Image> Image::loadPlatformResource(const char *name) +{ + String resourcePath = homeDirectoryPath() + String::format("res/%s.png", name); + + RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(resourcePath.utf8().data()); + if (!buffer) + return Image::nullImage(); + + RefPtr<Image> image = BitmapImage::create(); + image->setData(buffer, true); + return image.release(); +} + +} // namespace WebCore diff --git a/WebCore/platform/graphics/cairo/CairoUtilities.cpp b/WebCore/platform/graphics/cairo/CairoUtilities.cpp new file mode 100644 index 0000000..8c2049f --- /dev/null +++ b/WebCore/platform/graphics/cairo/CairoUtilities.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010 Igalia S.L. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "CairoUtilities.h" + +#include "Color.h" +#include <cairo.h> +#include <wtf/Vector.h> + +namespace WebCore { + +void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr) +{ + cairo_set_antialias(dstCr, cairo_get_antialias(srcCr)); + + size_t dashCount = cairo_get_dash_count(srcCr); + Vector<double> dashes(dashCount); + + double offset; + cairo_get_dash(srcCr, dashes.data(), &offset); + cairo_set_dash(dstCr, dashes.data(), dashCount, offset); + cairo_set_line_cap(dstCr, cairo_get_line_cap(srcCr)); + cairo_set_line_join(dstCr, cairo_get_line_join(srcCr)); + cairo_set_line_width(dstCr, cairo_get_line_width(srcCr)); + cairo_set_miter_limit(dstCr, cairo_get_miter_limit(srcCr)); + cairo_set_fill_rule(dstCr, cairo_get_fill_rule(srcCr)); +} + +void setSourceRGBAFromColor(cairo_t* context, const Color& color) +{ + float red, green, blue, alpha; + color.getRGBA(red, green, blue, alpha); + cairo_set_source_rgba(context, red, green, blue, alpha); +} + +} // namespace WebCore diff --git a/WebCore/platform/graphics/cairo/CairoUtilities.h b/WebCore/platform/graphics/cairo/CairoUtilities.h new file mode 100644 index 0000000..0675b90 --- /dev/null +++ b/WebCore/platform/graphics/cairo/CairoUtilities.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2010 Igalia S.L. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +#ifndef CairoUtilities_h +#define CairoUtilities_h + +typedef struct _cairo cairo_t; + +namespace WebCore { +class Color; + +void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr); +void setSourceRGBAFromColor(cairo_t*, const Color&); + +} // namespace WebCore + +#endif // CairoUtilities_h diff --git a/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp b/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp new file mode 100644 index 0000000..4b94cb3 --- /dev/null +++ b/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2010 Sencha, Inc. + * Copyright (C) 2010 Igalia S.L. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ContextShadow.h" + +#include "CairoUtilities.h" +#include "Timer.h" +#include <cairo.h> + +namespace WebCore { + +static cairo_surface_t* scratchBuffer = 0; +static void purgeScratchBuffer() +{ + cairo_surface_destroy(scratchBuffer); + scratchBuffer = 0; +} + +// ContextShadow needs a scratch image as the buffer for the blur filter. +// Instead of creating and destroying the buffer for every operation, +// we create a buffer which will be automatically purged via a timer. +class PurgeScratchBufferTimer : public TimerBase { +private: + virtual void fired() { purgeScratchBuffer(); } +}; +static PurgeScratchBufferTimer purgeScratchBufferTimer; +static void scheduleScratchBufferPurge() +{ + if (purgeScratchBufferTimer.isActive()) + purgeScratchBufferTimer.stop(); + purgeScratchBufferTimer.startOneShot(2); +} + +static cairo_surface_t* getScratchBuffer(const IntSize& size) +{ + int width = size.width(); + int height = size.height(); + int scratchWidth = scratchBuffer ? cairo_image_surface_get_width(scratchBuffer) : 0; + int scratchHeight = scratchBuffer ? cairo_image_surface_get_height(scratchBuffer) : 0; + + // We do not need to recreate the buffer if the current buffer is large enough. + if (scratchBuffer && scratchWidth >= width && scratchHeight >= height) + return scratchBuffer; + + purgeScratchBuffer(); + + // Round to the nearest 32 pixels so we do not grow the buffer for similar sized requests. + width = (1 + (width >> 5)) << 5; + height = (1 + (height >> 5)) << 5; + scratchBuffer = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + return scratchBuffer; +} + +PlatformContext ContextShadow::beginShadowLayer(PlatformContext context, const FloatRect& layerArea) +{ + double x1, x2, y1, y2; + cairo_clip_extents(context, &x1, &y1, &x2, &y2); + calculateLayerBoundingRect(layerArea, IntRect(x1, y1, x2 - x1, y2 - y1)); + + // Don't paint if we are totally outside the clip region. + if (m_layerRect.isEmpty()) + return 0; + + m_layerImage = getScratchBuffer(m_layerRect.size()); + m_layerContext = cairo_create(m_layerImage); + + // Always clear the surface first. + cairo_set_operator(m_layerContext, CAIRO_OPERATOR_CLEAR); + cairo_paint(m_layerContext); + cairo_set_operator(m_layerContext, CAIRO_OPERATOR_OVER); + + cairo_translate(m_layerContext, m_offset.width(), m_offset.height()); + cairo_translate(m_layerContext, -m_layerRect.x(), -m_layerRect.y()); + return m_layerContext; +} + +void ContextShadow::endShadowLayer(cairo_t* cr) +{ + cairo_destroy(m_layerContext); + m_layerContext = 0; + + if (m_type == BlurShadow) + blurLayerImage(cairo_image_surface_get_data(m_layerImage), + IntSize(cairo_image_surface_get_width(m_layerImage), cairo_image_surface_get_height(m_layerImage)), + cairo_image_surface_get_stride(m_layerImage)); + + cairo_save(cr); + setSourceRGBAFromColor(cr, m_color); + cairo_mask_surface(cr, m_layerImage, m_layerRect.x(), m_layerRect.y()); + cairo_restore(cr); + + // Schedule a purge of the scratch buffer. We do not need to destroy the surface. + scheduleScratchBufferPurge(); +} + +} diff --git a/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp b/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp index c09dd49..febad12 100644 --- a/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp +++ b/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Alp Toker <alp@atoker.com> + * Copyright (C) 2010 Igalia S.L. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,13 +27,17 @@ #include "OwnPtrCairo.h" #include "PlatformRefPtrCairo.h" #include "SimpleFontData.h" +#include <cairo-ft.h> +#include <cairo.h> +#include <fontconfig/fcfreetype.h> #include <wtf/Assertions.h> namespace WebCore { void FontCache::platformInit() { - if (!FontPlatformData::init()) + // It's fine to call FcInit multiple times per the documentation. + if (!FcInit()) ASSERT_NOT_REACHED(); } @@ -72,9 +77,9 @@ SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) { - // FIXME: Would be even better to somehow get the user's default font here. - // For now we'll pick the default that the user would get without changing any prefs. - static AtomicString timesStr("Times New Roman"); + // We want to return a fallback font here, otherwise the logic preventing FontConfig + // matches for non-fallback fonts might return 0. See isFallbackFontAllowed. + static AtomicString timesStr("serif"); return getCachedFontData(fontDescription, timesStr); } @@ -82,54 +87,106 @@ void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigne { } -static bool isWellKnownFontName(const AtomicString family) +static CString getFamilyNameStringFromFontDescriptionAndFamily(const FontDescription& fontDescription, const AtomicString& family) { - // Fonts that are used by layout tests included. The fact that - // they are used in Layout Tests indicate web compatibility issues - // if we do not handle them correctly. - if (equalIgnoringCase(family, "sans-serif") || equalIgnoringCase(family, "sans") - || equalIgnoringCase(family, "serif") || equalIgnoringCase(family, "mono") - || equalIgnoringCase(family, "monospace") || equalIgnoringCase(family, "cursive") - || equalIgnoringCase(family, "fantasy") || equalIgnoringCase(family, "Times") - || equalIgnoringCase(family, "Courier") || equalIgnoringCase(family, "Helvetica") - || equalIgnoringCase(family, "Arial") || equalIgnoringCase(family, "Lucida Grande") - || equalIgnoringCase(family, "Ahem") || equalIgnoringCase(family, "Georgia") - || equalIgnoringCase(family, "Times New Roman")) - return true; - - return false; + // If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into + // the fallback name (like "monospace") that fontconfig understands. + if (family.length() && !family.startsWith("-webkit-")) + return family.string().utf8(); + + switch (fontDescription.genericFamily()) { + case FontDescription::StandardFamily: + case FontDescription::SerifFamily: + return "serif"; + case FontDescription::SansSerifFamily: + return "sans-serif"; + case FontDescription::MonospaceFamily: + return "monospace"; + case FontDescription::CursiveFamily: + return "cursive"; + case FontDescription::FantasyFamily: + return "fantasy"; + case FontDescription::NoFamily: + default: + return ""; + } } -FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) -{ - // Handle generic family types specially, because fontconfig does not know them, but we have - // code to fallback correctly in our platform data implementation. - if (!family.length() || family.startsWith("-webkit-") - || (fontDescription.genericFamily() != FontDescription::NoFamily) - || isWellKnownFontName(family)) - return new FontPlatformData(fontDescription, family); - // First check the font exists. - CString familyNameString = family.string().utf8(); - const char* fcfamily = familyNameString.data(); +static bool isFallbackFontAllowed(const CString& familyName) +{ + return !strcasecmp(familyName.data(), "sans") + || !strcasecmp(familyName.data(), "sans-serif") + || !strcasecmp(familyName.data(), "serif") + || !strcasecmp(familyName.data(), "monospace"); +} +FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) +{ + // The CSS font matching algorithm (http://www.w3.org/TR/css3-fonts/#font-matching-algorithm) + // says that we must find an exact match for font family, slant (italic or oblique can be used) + // and font weight (we only match bold/non-bold here). PlatformRefPtr<FcPattern> pattern = adoptPlatformRef(FcPatternCreate()); - if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily))) + CString familyNameString = getFamilyNameStringFromFontDescriptionAndFamily(fontDescription, family); + if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(familyNameString.data()))) return 0; - OwnPtr<FcObjectSet> objectSet(FcObjectSetCreate()); - if (!FcObjectSetAdd(objectSet.get(), FC_FAMILY)) + bool italic = fontDescription.italic(); + if (!FcPatternAddInteger(pattern.get(), FC_SLANT, italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN)) + return 0; + bool bold = fontDescription.weight() >= FontWeightBold; + if (!FcPatternAddInteger(pattern.get(), FC_WEIGHT, bold ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL)) + return 0; + if (!FcPatternAddDouble(pattern.get(), FC_PIXEL_SIZE, fontDescription.computedPixelSize())) return 0; - OwnPtr<FcFontSet> fontSet(FcFontList(0, pattern.get(), objectSet.get())); - - if (!fontSet) + // The following comment and strategy are originally from Skia (src/ports/SkFontHost_fontconfig.cpp): + // Font matching: + // CSS often specifies a fallback list of families: + // font-family: a, b, c, serif; + // However, fontconfig will always do its best to find *a* font when asked + // for something so we need a way to tell if the match which it has found is + // "good enough" for us. Otherwise, we can return null which gets piped up + // and lets WebKit know to try the next CSS family name. However, fontconfig + // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we + // wish to support that. + // + // Thus, if a specific family is requested we set @family_requested. Then we + // record two strings: the family name after config processing and the + // family name after resolving. If the two are equal, it's a good match. + // + // So consider the case where a user has mapped Arial to Helvetica in their + // config. + // requested family: "Arial" + // post_config_family: "Helvetica" + // post_match_family: "Helvetica" + // -> good match + // + // and for a missing font: + // requested family: "Monaco" + // post_config_family: "Monaco" + // post_match_family: "Times New Roman" + // -> BAD match + // + FcConfigSubstitute(0, pattern.get(), FcMatchPattern); + FcDefaultSubstitute(pattern.get()); + + FcChar8* familyNameAfterConfiguration; + FcPatternGetString(pattern.get(), FC_FAMILY, 0, &familyNameAfterConfiguration); + + FcResult fontConfigResult; + PlatformRefPtr<FcPattern> resultPattern = adoptPlatformRef(FcFontMatch(0, pattern.get(), &fontConfigResult)); + if (!resultPattern) // No match. return 0; - if (!fontSet->fonts) + // Properly handle the situation where Fontconfig gives us a font that has a different family than we requested. + FcChar8* familyNameAfterMatching; + FcPatternGetString(resultPattern.get(), FC_FAMILY, 0, &familyNameAfterMatching); + if (strcasecmp(reinterpret_cast<char*>(familyNameAfterConfiguration), + reinterpret_cast<char*>(familyNameAfterMatching)) && !isFallbackFontAllowed(familyNameString)) return 0; - return new FontPlatformData(fontDescription, family); + return new FontPlatformData(resultPattern.get(), fontDescription); } } diff --git a/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp b/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp index 6b76c2a..0d195cb 100644 --- a/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp +++ b/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Alp Toker <alp@atoker.com> + * Copyright (C) 2010 Igalia S.L. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,11 +24,37 @@ #include "FontPlatformData.h" #include "SharedBuffer.h" +#include <cairo-ft.h> +#include <cairo.h> namespace WebCore { +static void releaseCustomFontData(void* data) +{ + static_cast<SharedBuffer*>(data)->deref(); +} + +FontCustomPlatformData::FontCustomPlatformData(FT_Face freeTypeFace, SharedBuffer* buffer) + : m_freeTypeFace(freeTypeFace) + , m_fontFace(cairo_ft_font_face_create_for_ft_face(freeTypeFace, 0)) +{ + // FIXME Should we be setting some hinting options here? + + buffer->ref(); // This is balanced by the buffer->deref() in releaseCustomFontData. + static cairo_user_data_key_t bufferKey; + cairo_font_face_set_user_data(m_fontFace, &bufferKey, buffer, + static_cast<cairo_destroy_func_t>(releaseCustomFontData)); + + // Cairo doesn't do FreeType reference counting, so we need to ensure that when + // this cairo_font_face_t is destroyed, it cleans up the FreeType face as well. + static cairo_user_data_key_t freeTypeFaceKey; + cairo_font_face_set_user_data(m_fontFace, &freeTypeFaceKey, freeTypeFace, + reinterpret_cast<cairo_destroy_func_t>(FT_Done_Face)); +} + FontCustomPlatformData::~FontCustomPlatformData() { + // m_freeTypeFace will be destroyed along with m_fontFace. See the constructor. cairo_font_face_destroy(m_fontFace); } @@ -36,38 +63,20 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b return FontPlatformData(m_fontFace, size, bold, italic); } -static void releaseData(void* data) -{ - static_cast<SharedBuffer*>(data)->deref(); -} - FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) { ASSERT_ARG(buffer, buffer); - int error; - static FT_Library library = 0; - if (!library) { - error = FT_Init_FreeType(&library); - if (error) { - library = 0; - return 0; - } + if (!library && FT_Init_FreeType(&library)) { + library = 0; + return 0; } - FT_Face face; - error = FT_New_Memory_Face(library, reinterpret_cast<const FT_Byte*>(buffer->data()), buffer->size(), 0, &face); - if (error) + FT_Face freeTypeFace; + if (FT_New_Memory_Face(library, reinterpret_cast<const FT_Byte*>(buffer->data()), buffer->size(), 0, &freeTypeFace)) return 0; - - buffer->ref(); - cairo_font_face_t* fontFace = cairo_ft_font_face_create_for_ft_face(face, 0); - - static cairo_user_data_key_t bufferKey; - cairo_font_face_set_user_data(fontFace, &bufferKey, buffer, releaseData); - - return new FontCustomPlatformData(fontFace); + return new FontCustomPlatformData(freeTypeFace, buffer); } bool FontCustomPlatformData::supportsFormat(const String& format) diff --git a/WebCore/platform/graphics/cairo/FontCustomPlatformData.h b/WebCore/platform/graphics/cairo/FontCustomPlatformData.h index a72a6a4..c48d110 100644 --- a/WebCore/platform/graphics/cairo/FontCustomPlatformData.h +++ b/WebCore/platform/graphics/cairo/FontCustomPlatformData.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Alp Toker <alp@atoker.com> + * Copyright (C) 2010 Igalia S.L. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -25,6 +26,7 @@ #include <wtf/Forward.h> #include <wtf/Noncopyable.h> +typedef struct FT_FaceRec_* FT_Face; typedef struct _cairo_font_face cairo_font_face_t; namespace WebCore { @@ -33,16 +35,14 @@ class FontPlatformData; class SharedBuffer; struct FontCustomPlatformData : Noncopyable { - FontCustomPlatformData(cairo_font_face_t* fontFace) - : m_fontFace(fontFace) - {} - +public: + FontCustomPlatformData(FT_Face, SharedBuffer*); ~FontCustomPlatformData(); - FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontRenderingMode = NormalRenderingMode); - static bool supportsFormat(const String&); +private: + FT_Face m_freeTypeFace; cairo_font_face_t* m_fontFace; }; diff --git a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp index 7968966..0617e6c 100644 --- a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp +++ b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp @@ -3,7 +3,7 @@ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com * Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com> * Copyright (C) 2007 Holger Hans Peter Freyther - * Copyright (C) 2009 Igalia S.L. + * Copyright (C) 2009, 2010 Igalia S.L. * All rights reserved. * * This library is free software; you can redistribute it and/or @@ -27,100 +27,88 @@ #include "PlatformString.h" #include "FontDescription.h" -#include <wtf/text/CString.h> - #include <cairo-ft.h> #include <cairo.h> #include <fontconfig/fcfreetype.h> + #if !PLATFORM(EFL) || ENABLE(GLIB_SUPPORT) #include <gdk/gdk.h> #endif namespace WebCore { -FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName) - : m_fallbacks(0) +cairo_subpixel_order_t convertFontConfigSubpixelOrder(int fontConfigOrder) +{ + switch (fontConfigOrder) { + case FC_RGBA_RGB: + return CAIRO_SUBPIXEL_ORDER_RGB; + case FC_RGBA_BGR: + return CAIRO_SUBPIXEL_ORDER_BGR; + case FC_RGBA_VRGB: + return CAIRO_SUBPIXEL_ORDER_VRGB; + case FC_RGBA_VBGR: + return CAIRO_SUBPIXEL_ORDER_VBGR; + case FC_RGBA_NONE: + case FC_RGBA_UNKNOWN: + return CAIRO_SUBPIXEL_ORDER_DEFAULT; + } + return CAIRO_SUBPIXEL_ORDER_DEFAULT; +} + +cairo_hint_style_t convertFontConfigHintStyle(int fontConfigStyle) +{ + switch (fontConfigStyle) { + case FC_HINT_NONE: + return CAIRO_HINT_STYLE_NONE; + case FC_HINT_SLIGHT: + return CAIRO_HINT_STYLE_SLIGHT; + case FC_HINT_MEDIUM: + return CAIRO_HINT_STYLE_MEDIUM; + case FC_HINT_FULL: + return CAIRO_HINT_STYLE_FULL; + } + return CAIRO_HINT_STYLE_NONE; +} + +void setCairoFontOptionsFromFontConfigPattern(cairo_font_options_t* options, FcPattern* pattern) +{ + FcBool booleanResult; + int integerResult; + + // We will determine if subpixel anti-aliasing is enabled via the FC_RGBA setting. + if (FcPatternGetBool(pattern, FC_ANTIALIAS, 0, &booleanResult) == FcResultMatch && booleanResult) + cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_GRAY); + + if (FcPatternGetInteger(pattern, FC_RGBA, 0, &integerResult) == FcResultMatch) { + if (integerResult != FC_RGBA_NONE) + cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL); + cairo_font_options_set_subpixel_order(options, convertFontConfigSubpixelOrder(integerResult)); + } + + if (FcPatternGetInteger(pattern, FC_HINT_STYLE, 0, &integerResult) == FcResultMatch) + cairo_font_options_set_hint_style(options, convertFontConfigHintStyle(integerResult)); + + if (FcPatternGetBool(pattern, FC_HINTING, 0, &booleanResult) == FcResultMatch && !booleanResult) + cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE); +} + +FontPlatformData::FontPlatformData(FcPattern* pattern, const FontDescription& fontDescription) + : m_pattern(pattern) + , m_fallbacks(0) , m_size(fontDescription.computedPixelSize()) , m_syntheticBold(false) , m_syntheticOblique(false) { - FontPlatformData::init(); - - CString familyNameString = familyName.string().utf8(); - const char* fcfamily = familyNameString.data(); - int fcslant = FC_SLANT_ROMAN; - // FIXME: Map all FontWeight values to fontconfig weights. - int fcweight = FC_WEIGHT_NORMAL; - double fcsize = fontDescription.computedPixelSize(); - if (fontDescription.italic()) - fcslant = FC_SLANT_ITALIC; - if (fontDescription.weight() >= FontWeight600) - fcweight = FC_WEIGHT_BOLD; - - int type = fontDescription.genericFamily(); - - PlatformRefPtr<FcPattern> pattern = adoptPlatformRef(FcPatternCreate()); - cairo_font_face_t* fontFace; - static const cairo_font_options_t* defaultOptions = cairo_font_options_create(); - const cairo_font_options_t* options = NULL; - cairo_matrix_t fontMatrix; - - if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily))) - return; - - switch (type) { - case FontDescription::SerifFamily: - fcfamily = "serif"; - break; - case FontDescription::SansSerifFamily: - fcfamily = "sans-serif"; - break; - case FontDescription::MonospaceFamily: - fcfamily = "monospace"; - break; - case FontDescription::StandardFamily: - fcfamily = "sans-serif"; - break; - case FontDescription::NoFamily: - default: - fcfamily = NULL; - break; - } + cairo_font_options_t* options = cairo_font_options_create(); + setCairoFontOptionsFromFontConfigPattern(options, pattern); - if (fcfamily && !FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily))) - return; - if (!FcPatternAddInteger(pattern.get(), FC_WEIGHT, fcweight)) - return; - if (!FcPatternAddInteger(pattern.get(), FC_SLANT, fcslant)) - return; - if (!FcPatternAddDouble(pattern.get(), FC_PIXEL_SIZE, fcsize)) - return; - - FcConfigSubstitute(0, pattern.get(), FcMatchPattern); - FcDefaultSubstitute(pattern.get()); - - FcResult fcresult; - m_pattern = adoptPlatformRef(FcFontMatch(0, pattern.get(), &fcresult)); - // FIXME: should we set some default font? - if (!m_pattern) - return; - fontFace = cairo_ft_font_face_create_for_pattern(m_pattern.get()); + cairo_matrix_t fontMatrix; + cairo_matrix_init_scale(&fontMatrix, m_size, m_size); cairo_matrix_t ctm; - cairo_matrix_init_scale(&fontMatrix, fontDescription.computedPixelSize(), fontDescription.computedPixelSize()); cairo_matrix_init_identity(&ctm); -#if !PLATFORM(EFL) || ENABLE(GLIB_SUPPORT) - if (GdkScreen* screen = gdk_screen_get_default()) -gdk_screen_get_font_options(screen); -#endif - - // gdk_screen_get_font_options() returns NULL if no default options are - // set, so we always have to check. - if (!options) - options = defaultOptions; - - m_scaledFont = adoptPlatformRef(cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options)); - cairo_font_face_destroy(fontFace); + PlatformRefPtr<cairo_font_face_t> fontFace = adoptPlatformRef(cairo_ft_font_face_create_for_pattern(m_pattern.get())); + m_scaledFont = adoptPlatformRef(cairo_scaled_font_create(fontFace.get(), &fontMatrix, &ctm, options)); } FontPlatformData::FontPlatformData(float size, bool bold, bool italic) @@ -184,19 +172,6 @@ FontPlatformData::FontPlatformData(const FontPlatformData& other) *this = other; } -bool FontPlatformData::init() -{ - static bool initialized = false; - if (initialized) - return true; - if (!FcInit()) { - fprintf(stderr, "Can't init font config library\n"); - return false; - } - initialized = true; - return true; -} - FontPlatformData::~FontPlatformData() { if (m_fallbacks) { diff --git a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h index 987a684..f3488ef 100644 --- a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h +++ b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h @@ -3,6 +3,7 @@ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com * Copyright (C) 2007 Holger Hans Peter Freyther * Copyright (C) 2007 Pioneer Research Center USA, Inc. + * Copyright (C) 2010 Igalia S.L. * All rights reserved. * * This library is free software; you can redistribute it and/or @@ -29,11 +30,10 @@ #include "GlyphBuffer.h" #include "HashFunctions.h" #include "PlatformRefPtrCairo.h" -#include <cairo-ft.h> -#include <cairo.h> -#include <fontconfig/fcfreetype.h> #include <wtf/Forward.h> +typedef struct _FcFontSet FcFontSet; + namespace WebCore { class FontPlatformData { @@ -53,14 +53,13 @@ public: , m_syntheticOblique(false) { } - FontPlatformData(const FontDescription&, const AtomicString& family); + FontPlatformData(FcPattern*, const FontDescription&); FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic); FontPlatformData(float size, bool bold, bool italic); FontPlatformData(const FontPlatformData&); ~FontPlatformData(); - static bool init(); bool isFixedPitch(); float size() const { return m_size; } void setSize(float size) { m_size = size; } diff --git a/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp b/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp index 26da68d..66e9c16 100644 --- a/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp +++ b/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp @@ -32,6 +32,9 @@ #include "GlyphPageTreeNode.h" #include "SimpleFontData.h" +#include <cairo-ft.h> +#include <cairo.h> +#include <fontconfig/fcfreetype.h> namespace WebCore { diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index 5de7e1f..05096a9 100644 --- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -35,6 +35,7 @@ #include "AffineTransform.h" #include "CairoPath.h" +#include "CairoUtilities.h" #include "FEGaussianBlur.h" #include "FloatRect.h" #include "Font.h" @@ -131,28 +132,10 @@ static inline void fillRectSourceOver(cairo_t* cr, const FloatRect& rect, const cairo_fill(cr); } -static inline void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr) -{ - cairo_set_antialias(dstCr, cairo_get_antialias(srcCr)); - - size_t dashCount = cairo_get_dash_count(srcCr); - Vector<double> dashes(dashCount); - - double offset; - cairo_get_dash(srcCr, dashes.data(), &offset); - cairo_set_dash(dstCr, dashes.data(), dashCount, offset); - cairo_set_line_cap(dstCr, cairo_get_line_cap(srcCr)); - cairo_set_line_join(dstCr, cairo_get_line_join(srcCr)); - cairo_set_line_width(dstCr, cairo_get_line_width(srcCr)); - cairo_set_miter_limit(dstCr, cairo_get_miter_limit(srcCr)); - cairo_set_fill_rule(dstCr, cairo_get_fill_rule(srcCr)); -} - static void appendPathToCairoContext(cairo_t* to, cairo_t* from) { - cairo_path_t* cairoPath = cairo_copy_path(from); - cairo_append_path(to, cairoPath); - cairo_path_destroy(cairoPath); + OwnPtr<cairo_path_t> cairoPath(cairo_copy_path(from)); + cairo_append_path(to, cairoPath.get()); } // We apply the pending path built via addPath to the Cairo context @@ -1182,9 +1165,8 @@ void GraphicsContext::clip(const Path& path) return; cairo_t* cr = m_data->cr; - cairo_path_t* p = cairo_copy_path(path.platformPath()->context()); - cairo_append_path(cr, p); - cairo_path_destroy(p); + OwnPtr<cairo_path_t> p(cairo_copy_path(path.platformPath()->context())); + cairo_append_path(cr, p.get()); cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr); cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING); cairo_clip(cr); @@ -1341,9 +1323,8 @@ void GraphicsContext::drawTiledShadow(const IntRect& rect, const FloatSize& topL copyContextProperties(cr, shadowContext); cairo_translate(shadowContext, -rect.x() + blurRadius, -rect.y() + blurRadius); cairo_new_path(shadowContext); - cairo_path_t* path = cairo_copy_path(cr); - cairo_append_path(shadowContext, path); - cairo_path_destroy(path); + OwnPtr<cairo_path_t> path(cairo_copy_path(cr)); + cairo_append_path(shadowContext, path.get()); setPlatformFill(this, shadowContext, m_common); diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp index 05c6952..776bceb 100644 --- a/WebCore/platform/graphics/cairo/PathCairo.cpp +++ b/WebCore/platform/graphics/cairo/PathCairo.cpp @@ -29,9 +29,9 @@ #include "CairoPath.h" #include "FloatRect.h" #include "GraphicsContext.h" +#include "OwnPtrCairo.h" #include "PlatformString.h" #include "StrokeStyleApplier.h" - #include <cairo.h> #include <math.h> #include <wtf/MathExtras.h> @@ -52,9 +52,8 @@ Path::Path(const Path& other) : m_path(new CairoPath()) { cairo_t* cr = platformPath()->context(); - cairo_path_t* p = cairo_copy_path(other.platformPath()->context()); - cairo_append_path(cr, p); - cairo_path_destroy(p); + OwnPtr<cairo_path_t> p(cairo_copy_path(other.platformPath()->context())); + cairo_append_path(cr, p.get()); } Path& Path::operator=(const Path& other) @@ -64,9 +63,8 @@ Path& Path::operator=(const Path& other) clear(); cairo_t* cr = platformPath()->context(); - cairo_path_t* p = cairo_copy_path(other.platformPath()->context()); - cairo_append_path(cr, p); - cairo_path_destroy(p); + OwnPtr<cairo_path_t> p(cairo_copy_path(other.platformPath()->context())); + cairo_append_path(cr, p.get()); return *this; } @@ -297,7 +295,7 @@ bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) void Path::apply(void* info, PathApplierFunction function) const { cairo_t* cr = platformPath()->context(); - cairo_path_t* path = cairo_copy_path(cr); + OwnPtr<cairo_path_t> path(cairo_copy_path(cr)); cairo_path_data_t* data; PathElement pelement; FloatPoint points[3]; @@ -329,7 +327,6 @@ void Path::apply(void* info, PathApplierFunction function) const break; } } - cairo_path_destroy(path); } void Path::transform(const AffineTransform& trans) @@ -346,7 +343,7 @@ String Path::debugString() const return String(); String pathString; - cairo_path_t* path = cairo_copy_path(platformPath()->context()); + OwnPtr<cairo_path_t> path(cairo_copy_path(platformPath()->context())); cairo_path_data_t* data; for (int i = 0; i < path->num_data; i += path->data[i].header.length) { @@ -373,7 +370,6 @@ String Path::debugString() const } } - cairo_path_destroy(path); return pathString.simplifyWhiteSpace(); } diff --git a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp index aa466f9..d289585 100644 --- a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp +++ b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp @@ -54,6 +54,19 @@ template <> void derefPlatformPtr(cairo_surface_t* ptr) cairo_surface_destroy(ptr); } +template <> cairo_font_face_t* refPlatformPtr(cairo_font_face_t* ptr) +{ + if (ptr) + cairo_font_face_reference(ptr); + return ptr; +} + +template <> void derefPlatformPtr(cairo_font_face_t* ptr) +{ + if (ptr) + cairo_font_face_destroy(ptr); +} + template <> cairo_scaled_font_t* refPlatformPtr(cairo_scaled_font_t* ptr) { if (ptr) diff --git a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h index 4b45c1b..3b720c6 100644 --- a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h +++ b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h @@ -24,6 +24,7 @@ typedef struct _cairo cairo_t; typedef struct _cairo_surface cairo_surface_t; +typedef struct _cairo_font_face cairo_font_face_t; typedef struct _cairo_scaled_font cairo_scaled_font_t; #if defined(USE_FREETYPE) @@ -38,6 +39,9 @@ template <> void derefPlatformPtr(cairo_t* ptr); template <> cairo_surface_t* refPlatformPtr(cairo_surface_t* ptr); template <> void derefPlatformPtr(cairo_surface_t* ptr); +template <> cairo_font_face_t* refPlatformPtr(cairo_font_face_t*); +template <> void derefPlatformPtr(cairo_font_face_t*); + template <> cairo_scaled_font_t* refPlatformPtr(cairo_scaled_font_t*); template <> void derefPlatformPtr(cairo_scaled_font_t*); diff --git a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp index fd85d6f..3d7c34b 100644 --- a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp +++ b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp @@ -38,7 +38,9 @@ #include "FontCache.h" #include "FontDescription.h" #include "GlyphBuffer.h" +#include <cairo-ft.h> #include <cairo.h> +#include <fontconfig/fcfreetype.h> #include <wtf/MathExtras.h> namespace WebCore { @@ -81,12 +83,12 @@ void SimpleFontData::platformDestroy() SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { - if (!m_smallCapsFontData) { - FontDescription desc = FontDescription(fontDescription); - desc.setComputedSize(0.70f * fontDescription.computedSize()); - FontPlatformData platformData(desc, desc.family().family()); - m_smallCapsFontData = new SimpleFontData(platformData); - } + // FIXME: I think we want to ask FontConfig for the right font again. + if (!m_smallCapsFontData) + m_smallCapsFontData = new SimpleFontData( + FontPlatformData(cairo_scaled_font_get_font_face(m_platformData.scaledFont()), + 0.70f * fontDescription.computedSize(), m_platformData.syntheticBold(), m_platformData.syntheticOblique())); + return m_smallCapsFontData; } diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp index fadc385..2a81fd2 100644 --- a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp @@ -71,9 +71,54 @@ bool GraphicsContext3D::getImageData(Image* image, AlphaOp neededAlphaOp = kAlphaDoNothing; switch (CGImageGetAlphaInfo(cgImage)) { case kCGImageAlphaPremultipliedFirst: + // This path is only accessible for MacOS earlier than 10.6.4. + // This is a special case for texImage2D with HTMLCanvasElement input, + // in which case image->data() should be null. + ASSERT(!image->data()); + if (!premultiplyAlpha) + neededAlphaOp = kAlphaDoUnmultiply; + switch (componentsPerPixel) { + case 2: + srcDataFormat = kSourceFormatAR8; + break; + case 4: + srcDataFormat = kSourceFormatARGB8; + break; + default: + return false; + } + break; case kCGImageAlphaFirst: + // This path is only accessible for MacOS earlier than 10.6.4. + if (premultiplyAlpha) + neededAlphaOp = kAlphaDoPremultiply; + switch (componentsPerPixel) { + case 1: + srcDataFormat = kSourceFormatA8; + break; + case 2: + srcDataFormat = kSourceFormatAR8; + break; + case 4: + srcDataFormat = kSourceFormatARGB8; + break; + default: + return false; + } + break; case kCGImageAlphaNoneSkipFirst: - return false; + // This path is only accessible for MacOS earlier than 10.6.4. + switch (componentsPerPixel) { + case 2: + srcDataFormat = kSourceFormatAR8; + break; + case 4: + srcDataFormat = kSourceFormatARGB8; + break; + default: + return false; + } + break; case kCGImageAlphaPremultipliedLast: // This is a special case for texImage2D with HTMLCanvasElement input, // in which case image->data() should be null. diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp index 86be8da..8dda4d6 100644 --- a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp @@ -126,10 +126,28 @@ ContentLayerChromium::ContentLayerChromium(GraphicsLayerChromium* owner) ContentLayerChromium::~ContentLayerChromium() { - if (m_contentsTexture) - GLC(layerRendererContext(), layerRendererContext()->deleteTexture(m_contentsTexture)); + cleanupResources(); } +void ContentLayerChromium::setLayerRenderer(LayerRendererChromium* renderer) +{ + // If we're changing layer renderers then we need to free up any resources + // allocated by the old renderer. + if (layerRenderer() && layerRenderer() != renderer) + cleanupResources(); + + LayerChromium::setLayerRenderer(renderer); +} + +void ContentLayerChromium::cleanupResources() +{ + if (layerRenderer()) { + if (m_contentsTexture) { + layerRenderer()->deleteLayerTexture(m_contentsTexture); + m_contentsTexture = 0; + } + } +} void ContentLayerChromium::updateContents() { diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/WebCore/platform/graphics/chromium/ContentLayerChromium.h index 42a77c7..412ba06 100644 --- a/WebCore/platform/graphics/chromium/ContentLayerChromium.h +++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.h @@ -49,6 +49,7 @@ public: virtual void updateContents(); virtual void draw(); virtual bool drawsContent() { return m_owner && m_owner->drawsContent(); } + virtual void setLayerRenderer(LayerRendererChromium*); // Stores values that are shared between instances of this class that are // associated with the same LayerRendererChromium (and hence the same GL @@ -79,6 +80,8 @@ protected: void updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize, const IntRect& updateRect, unsigned textureId); + void cleanupResources(); + unsigned m_contentsTexture; IntSize m_allocatedTextureSize; bool m_skipsDraw; diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp index 696cd9c..a242523 100644 --- a/WebCore/platform/graphics/chromium/FontLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontLinux.cpp @@ -130,7 +130,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, if (textMode & cTextFill) { // If we also filled, we don't want to draw shadows twice. // See comment in FontChromiumWin.cpp::paintSkiaText() for more details. - paint.setLooper(0)->safeUnref(); + SkSafeUnref(paint.setLooper(0)); } canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint); @@ -313,7 +313,7 @@ public: // So we allow that to run first, then do a second pass over the range it // found and take the largest subregion that stays within a single font. const FontData* glyphData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData; - int endOfRun; + unsigned endOfRun; for (endOfRun = 1; endOfRun < m_item.item.length; ++endOfRun) { const FontData* nextGlyphData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos + endOfRun], false, false).fontData; if (nextGlyphData != glyphData) @@ -406,7 +406,7 @@ private: // Harfbuzz will do the same thing for us using the GSUB table. // 2) Convert spacing characters into plain spaces, as some fonts will provide glyphs // for characters like '\n' otherwise. - for (unsigned i = 0; i < originalRun.length(); ++i) { + for (int i = 0; i < originalRun.length(); ++i) { UChar ch = originalRun[i]; UBlockCode block = ::ublock_getCode(ch); if (block == UBLOCK_COMBINING_DIACRITICAL_MARKS || (Font::treatAsSpace(ch) && ch != ' ')) { @@ -428,7 +428,7 @@ private: normalizedString.extract(m_normalizedBuffer.get(), normalizedString.length() + 1, error); ASSERT(U_SUCCESS(error)); - for (unsigned i = 0; i < normalizedString.length(); ++i) { + for (int i = 0; i < normalizedString.length(); ++i) { if (Font::treatAsSpace(m_normalizedBuffer[i])) m_normalizedBuffer[i] = ' '; } @@ -517,7 +517,7 @@ private: // glyph. unsigned logClustersIndex = isRTL ? m_item.num_glyphs - 1 : 0; - for (int iter = 0; iter < m_item.num_glyphs; ++iter) { + for (unsigned iter = 0; iter < m_item.num_glyphs; ++iter) { // Glyphs are stored in logical order, but for layout purposes we // always go left to right. int i = isRTL ? m_item.num_glyphs - iter - 1 : iter; @@ -683,7 +683,7 @@ static int glyphIndexForXPositionInScriptRun(const TextRunWalker& walker, int x) x -= truncateFixedPointToInteger(advances[glyphIndex]); } } else { - for (glyphIndex = 0; glyphIndex < walker.length(); ++glyphIndex) { + for (glyphIndex = 0; static_cast<unsigned>(glyphIndex) < walker.length(); ++glyphIndex) { if (x < truncateFixedPointToInteger(advances[glyphIndex])) break; x -= truncateFixedPointToInteger(advances[glyphIndex]); @@ -741,7 +741,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, if (walker.rtl()) basePosition -= walker.numCodePoints(); - if (x >= 0 && x < walker.width()) { + if (x >= 0 && static_cast<unsigned>(x) < walker.width()) { // The x value in question is within this script run. We consider // each glyph in presentation order and stop when we find the one // covering this position. @@ -803,7 +803,7 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, if (walker.rtl()) base -= walker.width(); - if (fromX == -1 && from < walker.numCodePoints()) { + if (fromX == -1 && from >= 0 && static_cast<unsigned>(from) < walker.numCodePoints()) { // |from| is within this script run. So we index the clusters log to // find which glyph this code-point contributed to and find its x // position. @@ -813,7 +813,7 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, } else from -= walker.numCodePoints(); - if (toX == -1 && to < walker.numCodePoints()) { + if (toX == -1 && to >= 0 && static_cast<unsigned>(to) < walker.numCodePoints()) { int glyph = walker.logClusters()[to]; toX = base + walker.xPositions()[glyph]; toAdvance = walker.advances()[glyph]; diff --git a/WebCore/platform/graphics/chromium/FontPlatformData.h b/WebCore/platform/graphics/chromium/FontPlatformData.h index 871fec8..d8ce3e2 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformData.h +++ b/WebCore/platform/graphics/chromium/FontPlatformData.h @@ -33,7 +33,7 @@ #if OS(WINDOWS) #include "FontPlatformDataChromiumWin.h" -#elif OS(LINUX) +#elif OS(LINUX) || OS(FREEBSD) #include "FontPlatformDataLinux.h" #endif diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp index b51eb8c..0da873b 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp @@ -76,7 +76,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src) , m_style(src.m_style) , m_harfbuzzFace(src.m_harfbuzzFace) { - m_typeface->safeRef(); + SkSafeRef(m_typeface); } FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic) @@ -86,7 +86,7 @@ FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float tex , m_fakeBold(fakeBold) , m_fakeItalic(fakeItalic) { - m_typeface->safeRef(); + SkSafeRef(m_typeface); querySystemForRenderStyle(); } @@ -98,13 +98,13 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) , m_fakeItalic(src.m_fakeItalic) , m_harfbuzzFace(src.m_harfbuzzFace) { - m_typeface->safeRef(); + SkSafeRef(m_typeface); querySystemForRenderStyle(); } FontPlatformData::~FontPlatformData() { - m_typeface->safeUnref(); + SkSafeUnref(m_typeface); } FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) diff --git a/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp b/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp index 59e8122..056d8eb 100644 --- a/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp +++ b/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp @@ -150,7 +150,7 @@ static HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags, hb_ui SkPath path; paint.getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path); int numPoints = path.getPoints(0, 0); - if (point >= numPoints) + if (point >= static_cast<unsigned>(numPoints)) return HB_Err_Invalid_SubTable; SkPoint* points = reinterpret_cast<SkPoint*>(fastMalloc(sizeof(SkPoint) * (point + 1))); if (!points) diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp index e36c69d..5dba58d 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -174,9 +174,6 @@ LayerChromium::~LayerChromium() void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer) { - // It's not expected that layers will ever switch renderers. - ASSERT(!renderer || !m_layerRenderer || renderer == m_layerRenderer); - m_layerRenderer = renderer; } @@ -224,9 +221,10 @@ unsigned LayerChromium::createShaderProgram(GraphicsContext3D* context, const ch void LayerChromium::setNeedsCommit() { - // Call notifySyncRequired(), which in this implementation plumbs through to + // Call notifySyncRequired(), which for non-root layers plumbs through to // call setRootLayerNeedsDisplay() on the WebView, which will cause LayerRendererChromium // to render a frame. + // This function has no effect on root layers. if (m_owner) m_owner->notifySyncRequired(); } @@ -352,8 +350,9 @@ LayerChromium* LayerChromium::superlayer() const void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect) { - // Simply mark the contents as dirty. The actual redraw will - // happen when it's time to do the compositing. + // Simply mark the contents as dirty. For non-root layers, the call to + // setNeedsCommit will schedule a fresh compositing pass. + // For the root layer, setNeedsCommit has no effect. m_contentsDirty = true; m_dirtyRect.unite(dirtyRect); diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h index 30d35d1..0a66318 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/WebCore/platform/graphics/chromium/LayerChromium.h @@ -147,7 +147,9 @@ public: bool preserves3D() { return m_owner && m_owner->preserves3D(); } - void setLayerRenderer(LayerRendererChromium*); + // Derived types must override this method if they need to react to a change + // in the LayerRendererChromium. + virtual void setLayerRenderer(LayerRendererChromium*); void setOwner(GraphicsLayerChromium* owner) { m_owner = owner; } @@ -200,7 +202,7 @@ protected: GraphicsLayerChromium* m_owner; LayerChromium(GraphicsLayerChromium* owner); - LayerRendererChromium* layerRenderer() const { return m_layerRenderer; } + LayerRendererChromium* layerRenderer() const { return m_layerRenderer.get(); } GraphicsContext3D* layerRendererContext() const; static void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix, @@ -260,7 +262,7 @@ private: bool m_needsDisplayOnBoundsChange; // Points to the layer renderer that updates and draws this layer. - LayerRendererChromium* m_layerRenderer; + RefPtr<LayerRendererChromium> m_layerRenderer; FloatRect m_frame; TransformationMatrix m_transform; diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index 116a15d..c4031e5 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -73,12 +73,12 @@ static inline bool compareLayerZ(const LayerChromium* a, const LayerChromium* b) return transformA.m43() < transformB.m43(); } -PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(PassOwnPtr<GraphicsContext3D> context) +PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassOwnPtr<GraphicsContext3D> context) { if (!context) return 0; - OwnPtr<LayerRendererChromium> layerRenderer(new LayerRendererChromium(context)); + RefPtr<LayerRendererChromium> layerRenderer(adoptRef(new LayerRendererChromium(context))); if (!layerRenderer->hardwareCompositing()) return 0; @@ -91,7 +91,6 @@ LayerRendererChromium::LayerRendererChromium(PassOwnPtr<GraphicsContext3D> conte , m_rootLayerTextureHeight(0) , m_scrollShaderProgram(0) , m_rootLayer(0) - , m_needsDisplay(false) , m_scrollPosition(IntPoint(-1, -1)) , m_currentShader(0) , m_context(context) @@ -159,8 +158,10 @@ void LayerRendererChromium::useShader(unsigned programId) } } -// Updates the contents of the root layer texture that fall inside the updateRect -// and re-composits all sublayers. +// This method must be called before any other updates are made to the +// root layer texture. It resizes the root layer texture and scrolls its +// contents as needed. It also sets up common GL state used by the rest +// of the layer drawing code. void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition) { @@ -172,6 +173,8 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons makeContextCurrent(); GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId)); + + bool skipScroll = false; // If the size of the visible area has changed then allocate a new texture // to store the contents of the root layer and adjust the projection matrix @@ -184,6 +187,10 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons m_projectionMatrix = orthoMatrix(0, visibleRectWidth, visibleRectHeight, 0, -1000, 1000); GLC(m_context, m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_rootLayerTextureWidth, m_rootLayerTextureHeight, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0)); + + // The root layer texture was just resized so its contents are not + // useful for scrolling. + skipScroll = true; } // The GL viewport covers the entire visible area, including the scrollbars. @@ -198,12 +205,20 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons GLC(m_context, m_context->depthFunc(GraphicsContext3D::LEQUAL)); GLC(m_context, m_context->clearStencil(0)); - if (m_scrollPosition == IntPoint(-1, -1)) + if (m_scrollPosition == IntPoint(-1, -1)) { m_scrollPosition = scrollPosition; + skipScroll = true; + } IntPoint scrollDelta = toPoint(scrollPosition - m_scrollPosition); + + // Scrolling larger than the contentRect size does not preserve any of the pixels, so there is + // no need to copy framebuffer pixels back into the texture. + if (abs(scrollDelta.y()) > contentRect.height() || abs(scrollDelta.x()) > contentRect.width()) + skipScroll = true; + // Scroll the backbuffer - if (scrollDelta.x() || scrollDelta.y()) { + if (!skipScroll && (scrollDelta.x() || scrollDelta.y())) { // Scrolling works as follows: We render a quad with the current root layer contents // translated by the amount the page has scrolled since the last update and then read the // pixels of the content area (visible area excluding the scroll bars) back into the @@ -221,23 +236,9 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons m_scrollShaderMatrixLocation, -1); GLC(m_context, m_context->copyTexSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, 0, 0, contentRect.width(), contentRect.height())); - m_scrollPosition = scrollPosition; - } else if (abs(scrollDelta.y()) > contentRect.height() || abs(scrollDelta.x()) > contentRect.width()) { - // Scrolling larger than the contentRect size does not preserve any of the pixels, so there is - // no need to copy framebuffer pixels back into the texture. - m_scrollPosition = scrollPosition; } - // Translate all the composited layers by the scroll position. - TransformationMatrix matrix; - matrix.translate3d(-m_scrollPosition.x(), -m_scrollPosition.y(), 0); - - // Traverse the layer tree and update the layer transforms. - float opacity = 1; - const Vector<RefPtr<LayerChromium> >& sublayers = m_rootLayer->getSublayers(); - size_t i; - for (i = 0; i < sublayers.size(); i++) - updateLayersRecursive(sublayers[i].get(), matrix, opacity); + m_scrollPosition = scrollPosition; } void LayerRendererChromium::updateRootLayerTextureRect(const IntRect& updateRect) @@ -256,9 +257,7 @@ void LayerRendererChromium::updateRootLayerTextureRect(const IntRect& updateRect #if PLATFORM(SKIA) // Get the contents of the updated rect. const SkBitmap bitmap = m_rootLayerCanvas->getDevice()->accessBitmap(false); - int bitmapWidth = bitmap.width(); - int bitmapHeight = bitmap.height(); - ASSERT(bitmapWidth == updateRect.width() && bitmapHeight == updateRect.height()); + ASSERT(bitmap.width() == updateRect.width() && bitmap.height() == updateRect.height()); void* pixels = bitmap.getPixels(); #elif PLATFORM(CG) // Get the contents of the updated rect. @@ -306,16 +305,13 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect // Set the rootVisibleRect --- used by subsequent drawLayers calls m_rootVisibleRect = visibleRect; - // Translate all the composited layers by the scroll position. - TransformationMatrix matrix; - matrix.translate3d(-m_scrollPosition.x(), -m_scrollPosition.y(), 0); - // Traverse the layer tree and update the layer transforms. float opacity = 1; const Vector<RefPtr<LayerChromium> >& sublayers = m_rootLayer->getSublayers(); size_t i; + TransformationMatrix identityMatrix; for (i = 0; i < sublayers.size(); i++) - updateLayersRecursive(sublayers[i].get(), matrix, opacity); + updateLayersRecursive(sublayers[i].get(), identityMatrix, opacity); // Enable scissoring to avoid rendering composited layers over the scrollbars. GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST)); @@ -349,7 +345,6 @@ void LayerRendererChromium::present() // Note that currently this has the same effect as swapBuffers; we should // consider exposing a different entry point on GraphicsContext3D. m_context->prepareTexture(); - m_needsDisplay = false; } void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect) @@ -381,6 +376,14 @@ unsigned LayerRendererChromium::createLayerTexture() return textureId; } +void LayerRendererChromium::deleteLayerTexture(unsigned textureId) +{ + if (!textureId) + return; + + GLC(m_context, m_context->deleteTexture(textureId)); +} + // Returns true if any part of the layer falls within the visibleRect bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const TransformationMatrix& matrix, const IntRect& visibleRect) { @@ -717,7 +720,8 @@ bool LayerRendererChromium::initializeSharedObjects() m_layerSharedValues = adoptPtr(new LayerChromium::SharedValues(m_context.get())); m_contentLayerSharedValues = adoptPtr(new ContentLayerChromium::SharedValues(m_context.get())); m_canvasLayerSharedValues = adoptPtr(new CanvasLayerChromium::SharedValues(m_context.get())); - if (!m_layerSharedValues->initialized() || !m_contentLayerSharedValues->initialized() || !m_canvasLayerSharedValues->initialized()) { + m_videoLayerSharedValues = adoptPtr(new VideoLayerChromium::SharedValues(m_context.get())); + if (!m_layerSharedValues->initialized() || !m_contentLayerSharedValues->initialized() || !m_canvasLayerSharedValues->initialized() || !m_videoLayerSharedValues->initialized()) { cleanupSharedObjects(); return false; } @@ -732,6 +736,7 @@ void LayerRendererChromium::cleanupSharedObjects() m_layerSharedValues.clear(); m_contentLayerSharedValues.clear(); m_canvasLayerSharedValues.clear(); + m_videoLayerSharedValues.clear(); if (m_scrollShaderProgram) { GLC(m_context, m_context->deleteProgram(m_scrollShaderProgram)); @@ -739,7 +744,7 @@ void LayerRendererChromium::cleanupSharedObjects() } if (m_rootLayerTextureId) { - GLC(m_context, m_context->deleteTexture(m_rootLayerTextureId)); + deleteLayerTexture(m_rootLayerTextureId); m_rootLayerTextureId = 0; } } diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h index c733228..b714584 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -39,9 +39,12 @@ #include "IntRect.h" #include "LayerChromium.h" #include "SkBitmap.h" +#include "VideoLayerChromium.h" #include <wtf/HashMap.h> #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> #include <wtf/Vector.h> #if PLATFORM(CG) @@ -54,9 +57,9 @@ namespace WebCore { class GraphicsContext3D; // Class that handles drawing of composited render layers using GL. -class LayerRendererChromium : public Noncopyable { +class LayerRendererChromium : public RefCounted<LayerRendererChromium> { public: - static PassOwnPtr<LayerRendererChromium> create(PassOwnPtr<GraphicsContext3D> graphicsContext3D); + static PassRefPtr<LayerRendererChromium> create(PassOwnPtr<GraphicsContext3D> graphicsContext3D); LayerRendererChromium(PassOwnPtr<GraphicsContext3D> graphicsContext3D); ~LayerRendererChromium(); @@ -81,8 +84,6 @@ public: void setRootLayer(PassRefPtr<LayerChromium> layer) { m_rootLayer = layer; } LayerChromium* rootLayer() { return m_rootLayer.get(); } - void setNeedsDisplay() { m_needsDisplay = true; } - bool hardwareCompositing() const { return m_hardwareCompositing; } void setRootLayerCanvasSize(const IntSize&); @@ -90,6 +91,7 @@ public: GraphicsContext* rootLayerGraphicsContext() const { return m_rootLayerGraphicsContext.get(); } unsigned createLayerTexture(); + void deleteLayerTexture(unsigned); static void debugGLCall(GraphicsContext3D*, const char* command, const char* file, int line); @@ -102,6 +104,7 @@ public: const LayerChromium::SharedValues* layerSharedValues() const { return m_layerSharedValues.get(); } const ContentLayerChromium::SharedValues* contentLayerSharedValues() const { return m_contentLayerSharedValues.get(); } const CanvasLayerChromium::SharedValues* canvasLayerSharedValues() const { return m_canvasLayerSharedValues.get(); } + const VideoLayerChromium::SharedValues* videoLayerSharedValues() const { return m_videoLayerSharedValues.get(); } void resizeOnscreenContent(const IntSize&); @@ -139,7 +142,6 @@ private: RefPtr<LayerChromium> m_rootLayer; - bool m_needsDisplay; IntPoint m_scrollPosition; bool m_hardwareCompositing; @@ -170,6 +172,7 @@ private: OwnPtr<LayerChromium::SharedValues> m_layerSharedValues; OwnPtr<ContentLayerChromium::SharedValues> m_contentLayerSharedValues; OwnPtr<CanvasLayerChromium::SharedValues> m_canvasLayerSharedValues; + OwnPtr<VideoLayerChromium::SharedValues> m_videoLayerSharedValues; OwnPtr<GraphicsContext3D> m_context; }; diff --git a/WebCore/platform/graphics/chromium/VDMXParser.cpp b/WebCore/platform/graphics/chromium/VDMXParser.cpp index 3347226..bd30a97 100644 --- a/WebCore/platform/graphics/chromium/VDMXParser.cpp +++ b/WebCore/platform/graphics/chromium/VDMXParser.cpp @@ -31,7 +31,6 @@ #include <stdint.h> #include <stdlib.h> #include <string.h> -#include <sys/types.h> // For htons/ntohs #include <arpa/inet.h> diff --git a/WebCore/platform/graphics/chromium/VideoFrameChromium.cpp b/WebCore/platform/graphics/chromium/VideoFrameChromium.cpp new file mode 100644 index 0000000..43b40e2 --- /dev/null +++ b/WebCore/platform/graphics/chromium/VideoFrameChromium.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER OR 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 "VideoFrameChromium.h" + +namespace WebCore { + +const unsigned VideoFrameChromium::maxPlanes = 3; +const unsigned VideoFrameChromium::numRGBPlanes = 1; +const unsigned VideoFrameChromium::rgbPlane = 0; +const unsigned VideoFrameChromium::numYUVPlanes = 3; +const unsigned VideoFrameChromium::yPlane = 0; +const unsigned VideoFrameChromium::uPlane = 1; +const unsigned VideoFrameChromium::vPlane = 2; + +} // namespace WebCore + + diff --git a/WebCore/platform/graphics/chromium/VideoFrameChromium.h b/WebCore/platform/graphics/chromium/VideoFrameChromium.h index bbd677e..34e922b 100644 --- a/WebCore/platform/graphics/chromium/VideoFrameChromium.h +++ b/WebCore/platform/graphics/chromium/VideoFrameChromium.h @@ -31,18 +31,20 @@ #ifndef VideoFrameChromium_h #define VideoFrameChromium_h +#include "IntSize.h" + namespace WebCore { // A class that represents a video frame in chromium. class VideoFrameChromium { public: - static const unsigned cMaxPlanes; - static const unsigned cNumRGBPlanes; - static const unsigned cRGBPlane; - static const unsigned cNumYUVPlanes; - static const unsigned cYPlane; - static const unsigned cUPlane; - static const unsigned cVPlane; + static const unsigned maxPlanes; + static const unsigned numRGBPlanes; + static const unsigned rgbPlane; + static const unsigned numYUVPlanes; + static const unsigned yPlane; + static const unsigned uPlane; + static const unsigned vPlane; // These enums must be kept in sync with WebKit::WebVideoFrame. enum Format { @@ -74,6 +76,7 @@ public: virtual unsigned planes() const = 0; virtual int stride(unsigned plane) const = 0; virtual const void* data(unsigned plane) const = 0; + virtual const IntSize requiredTextureSize(unsigned plane) const = 0; }; } // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp index 0fb1bb4..26641a9 100644 --- a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp @@ -36,15 +36,134 @@ #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" #include "RenderLayerBacking.h" -#include "skia/ext/platform_canvas.h" - -#if PLATFORM(SKIA) -#include "NativeImageSkia.h" -#include "PlatformContextSkia.h" -#endif +#include "VideoFrameChromium.h" +#include "VideoFrameProvider.h" namespace WebCore { +// These values are magic numbers that are used in the transformation +// from YUV to RGB color values. +const float VideoLayerChromium::yuv2RGB[9] = { + 1.f, 1.f, 1.f, + 0.f, -.344f, 1.772f, + 1.403f, -.714f, 0.f, +}; + +VideoLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context) + : m_context(context) + , m_yuvShaderProgram(0) + , m_rgbaShaderProgram(0) + , m_yuvShaderMatrixLocation(0) + , m_yuvWidthScaleFactorLocation(0) + , m_rgbaShaderMatrixLocation(0) + , m_rgbaWidthScaleFactorLocation(0) + , m_ccMatrixLocation(0) + , m_yTextureLocation(0) + , m_uTextureLocation(0) + , m_vTextureLocation(0) + , m_rgbaTextureLocation(0) + , m_yuvAlphaLocation(0) + , m_rgbaAlphaLocation(0) + , m_initialized(false) +{ + // Frame textures are allocated based on stride width, not visible frame + // width, such that there is a guarantee that the frame rows line up + // properly and are not shifted by (stride - width) pixels. To hide the + // "padding" pixels between the edge of the visible frame width and the end + // of the stride, we give the shader a widthScaleFactor (<=1.0) of how much + // of the width of the texture should be shown when drawing the texture onto + // the vertices. + char vertexShaderString[] = + "precision mediump float; \n" + "attribute vec4 a_position; \n" + "attribute vec2 a_texCoord; \n" + "uniform mat4 matrix; \n" + "varying vec2 v_texCoord; \n" + "uniform float widthScaleFactor; \n" + "void main() \n" + "{ \n" + " gl_Position = matrix * a_position; \n" + " v_texCoord = vec2(widthScaleFactor * a_texCoord.x, a_texCoord.y); \n" + "} \n"; + + char yuvFragmentShaderString[] = + "precision mediump float; \n" + "precision mediump int; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D y_texture; \n" + "uniform sampler2D u_texture; \n" + "uniform sampler2D v_texture; \n" + "uniform float alpha; \n" + "uniform mat3 cc_matrix; \n" + "void main() \n" + "{ \n" + " float y = texture2D(y_texture, v_texCoord).x; \n" + " float u = texture2D(u_texture, v_texCoord).r - .5; \n" + " float v = texture2D(v_texture, v_texCoord).r - .5; \n" + " vec3 rgb = cc_matrix * vec3(y, u, v); \n" + " gl_FragColor = vec4(rgb.x, rgb.y, rgb.z, 1.0) * alpha; \n" + "} \n"; + + char rgbaFragmentShaderString[] = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D rgba_texture; \n" + "uniform float alpha; \n" + "void main() \n" + "{ \n" + " vec4 texColor = texture2D(rgba_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); \n" + " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n" + "} \n"; + + m_rgbaShaderProgram = createShaderProgram(m_context, vertexShaderString, rgbaFragmentShaderString); + if (!m_rgbaShaderProgram) { + LOG_ERROR("VideoLayerChromium: Failed to create rgba shader program"); + return; + } + + m_yuvShaderProgram = createShaderProgram(m_context, vertexShaderString, yuvFragmentShaderString); + if (!m_yuvShaderProgram) { + LOG_ERROR("VideoLayerChromium: Failed to create yuv shader program"); + return; + } + + m_yuvShaderMatrixLocation = m_context->getUniformLocation(m_yuvShaderProgram, "matrix"); + m_yuvWidthScaleFactorLocation = m_context->getUniformLocation(m_yuvShaderProgram, "widthScaleFactor"); + m_yTextureLocation = m_context->getUniformLocation(m_yuvShaderProgram, "y_texture"); + m_uTextureLocation = m_context->getUniformLocation(m_yuvShaderProgram, "u_texture"); + m_vTextureLocation = m_context->getUniformLocation(m_yuvShaderProgram, "v_texture"); + m_ccMatrixLocation = m_context->getUniformLocation(m_yuvShaderProgram, "cc_matrix"); + m_yuvAlphaLocation = m_context->getUniformLocation(m_yuvShaderProgram, "alpha"); + + ASSERT(m_yuvShaderMatrixLocation != -1); + ASSERT(m_yuvWidthScaleFactorLocation != -1); + ASSERT(m_yTextureLocation != -1); + ASSERT(m_uTextureLocation != -1); + ASSERT(m_vTextureLocation != -1); + ASSERT(m_ccMatrixLocation != -1); + ASSERT(m_yuvAlphaLocation != -1); + + m_rgbaShaderMatrixLocation = m_context->getUniformLocation(m_rgbaShaderProgram, "matrix"); + m_rgbaTextureLocation = m_context->getUniformLocation(m_rgbaShaderProgram, "rgba_texture"); + m_rgbaWidthScaleFactorLocation = m_context->getUniformLocation(m_rgbaShaderProgram, "widthScaleFactor"); + m_rgbaAlphaLocation = m_context->getUniformLocation(m_rgbaShaderProgram, "alpha"); + + ASSERT(m_rgbaShaderMatrixLocation != -1); + ASSERT(m_rgbaTextureLocation != -1); + ASSERT(m_rgbaWidthScaleFactorLocation != -1); + ASSERT(m_rgbaAlphaLocation != -1); + + m_initialized = true; +} + +VideoLayerChromium::SharedValues::~SharedValues() +{ + if (m_yuvShaderProgram) + GLC(m_context, m_context->deleteProgram(m_yuvShaderProgram)); + if (m_rgbaShaderProgram) + GLC(m_context, m_context->deleteProgram(m_rgbaShaderProgram)); +} + PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(GraphicsLayerChromium* owner, VideoFrameProvider* provider) { @@ -52,14 +171,25 @@ PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(GraphicsLayerChromium* } VideoLayerChromium::VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameProvider* provider) - : ContentLayerChromium(owner) -#if PLATFORM(SKIA) - , m_canvas(0) - , m_skiaContext(0) -#endif - , m_graphicsContext(0) + : LayerChromium(owner) + , m_skipsDraw(true) + , m_frameFormat(VideoFrameChromium::Invalid) , m_provider(provider) { + for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) { + m_textures[plane] = 0; + m_textureSizes[plane] = IntSize(); + m_frameSizes[plane] = IntSize(); + } +} + +VideoLayerChromium::~VideoLayerChromium() +{ + GraphicsContext3D* context = layerRendererContext(); + for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) { + if (m_textures[plane]) + GLC(context, context->deleteTexture(m_textures[plane])); + } } void VideoLayerChromium::updateContents() @@ -70,129 +200,176 @@ void VideoLayerChromium::updateContents() ASSERT(drawsContent()); - IntRect dirtyRect(m_dirtyRect); - IntSize requiredTextureSize; - -#if PLATFORM(SKIA) - requiredTextureSize = m_bounds; - IntRect boundsRect(IntPoint(0, 0), m_bounds); - - // If the texture needs to be reallocated, then we must redraw the entire - // contents of the layer. - if (requiredTextureSize != m_allocatedTextureSize) - dirtyRect = boundsRect; - else { - // Clip the dirtyRect to the size of the layer to avoid drawing outside - // the bounds of the backing texture. - dirtyRect.intersect(boundsRect); + m_skipsDraw = false; + VideoFrameChromium* frame = m_provider->getCurrentFrame(); + if (!frame) { + m_skipsDraw = true; + m_provider->putCurrentFrame(frame); + return; } - if (!m_canvas.get() - || dirtyRect.width() != m_canvas->getDevice()->width() - || dirtyRect.height() != m_canvas->getDevice()->height()) { - m_canvas = new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), true); - m_skiaContext = new PlatformContextSkia(m_canvas.get()); - - // This is needed to get text to show up correctly. - // FIXME: Does this take us down a very slow text rendering path? - m_skiaContext->setDrawingToImageBuffer(true); - m_graphicsContext = new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(m_skiaContext.get())); + m_frameFormat = frame->format(); + unsigned textureFormat = determineTextureFormat(frame); + if (textureFormat == GraphicsContext3D::INVALID_VALUE) { + // FIXME: Implement other paths. + notImplemented(); + m_skipsDraw = true; + m_provider->putCurrentFrame(frame); + return; } - // Bring the canvas into the coordinate system of the paint rect. - m_canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y())); - - // FIXME: Remove this test when tiled layers are implemented. - m_skipsDraw = false; - if (!layerRenderer()->checkTextureSize(requiredTextureSize)) { + // Allocate textures for planes if they are not allocated already, or + // reallocate textures that are the wrong size for the frame. + GraphicsContext3D* context = layerRendererContext(); + bool texturesAllocated = allocateTexturesIfNeeded(context, frame, textureFormat); + if (!texturesAllocated) { m_skipsDraw = true; + m_provider->putCurrentFrame(frame); return; } - unsigned textureId = m_contentsTexture; - if (!textureId) - textureId = layerRenderer()->createLayerTexture(); - - // If the texture id or size changed since last time, then we need to tell GL - // to re-allocate a texture. - if (m_contentsTexture != textureId || requiredTextureSize != m_allocatedTextureSize) - createTextureRect(requiredTextureSize, dirtyRect, textureId); - else - updateTextureRect(dirtyRect, textureId); -#else - // FIXME: Implement non-skia path - notImplemented(); -#endif + // Update texture planes. + for (unsigned plane = 0; plane < frame->planes(); plane++) { + ASSERT(frame->requiredTextureSize(plane) == m_textureSizes[plane]); + updateTexture(context, m_textures[plane], frame->requiredTextureSize(plane), textureFormat, frame->data(plane)); + } + + m_dirtyRect.setSize(FloatSize()); + m_contentsDirty = false; + m_provider->putCurrentFrame(frame); } -void VideoLayerChromium::createTextureRect(const IntSize& requiredTextureSize, const IntRect& updateRect, unsigned textureId) +unsigned VideoLayerChromium::determineTextureFormat(VideoFrameChromium* frame) { - // Paint into graphics context and get bitmap. - m_owner->paintGraphicsLayerContents(*m_graphicsContext, updateRect); - void* pixels = 0; - IntSize bitmapSize = IntSize(); -#if PLATFORM(SKIA) - const SkBitmap& bitmap = m_canvas->getDevice()->accessBitmap(false); - const SkBitmap* skiaBitmap = &bitmap; - ASSERT(skiaBitmap); - - SkAutoLockPixels lock(*skiaBitmap); - SkBitmap::Config skiaConfig = skiaBitmap->config(); - // FIXME: Do we need to support more image configurations? - if (skiaConfig == SkBitmap::kARGB_8888_Config) { - pixels = skiaBitmap->getPixels(); - bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); + switch (frame->format()) { + case VideoFrameChromium::YV12: + return GraphicsContext3D::LUMINANCE; + case VideoFrameChromium::RGBA: + return GraphicsContext3D::RGBA; + default: + break; } -#else - // FIXME: Implement non-skia path - notImplemented(); -#endif - if (!pixels) - return; + return GraphicsContext3D::INVALID_VALUE; +} - GraphicsContext3D* context = layerRendererContext(); - context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId); - ASSERT(bitmapSize == requiredTextureSize); - context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels); +bool VideoLayerChromium::allocateTexturesIfNeeded(GraphicsContext3D* context, VideoFrameChromium* frame, unsigned textureFormat) +{ + ASSERT(context); + ASSERT(frame); + + for (unsigned plane = 0; plane < frame->planes(); plane++) { + IntSize planeTextureSize = frame->requiredTextureSize(plane); - m_contentsTexture = textureId; - m_allocatedTextureSize = requiredTextureSize; + // If the renderer cannot handle this large of a texture, return false. + // FIXME: Remove this test when tiled layers are implemented. + if (!layerRenderer()->checkTextureSize(planeTextureSize)) + return false; - updateCompleted(); + if (!m_textures[plane]) + m_textures[plane] = layerRenderer()->createLayerTexture(); + + if (!planeTextureSize.isZero() && planeTextureSize != m_textureSizes[plane]) { + allocateTexture(context, m_textures[plane], planeTextureSize, textureFormat); + m_textureSizes[plane] = planeTextureSize; + m_frameSizes[plane] = IntSize(frame->width(), frame->height()); + } + } + return true; +} + +void VideoLayerChromium::allocateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned textureFormat) +{ + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); + GLC(context, context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, textureFormat, dimensions.width(), dimensions.height(), 0, textureFormat, GraphicsContext3D::UNSIGNED_BYTE, 0)); } -void VideoLayerChromium::updateTextureRect(const IntRect& updateRect, unsigned textureId) +void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned format, const void* data) { -#if PLATFORM(SKIA) - const SkBitmap& bitmap = m_canvas->getDevice()->accessBitmap(true); - SkBitmap* skiaBitmap = const_cast<SkBitmap*>(&bitmap); - ASSERT(skiaBitmap); - - SkAutoLockPixels lock(*skiaBitmap); - SkBitmap::Config skiaConfig = skiaBitmap->config(); - - if (skiaConfig == SkBitmap::kARGB_8888_Config) { - GraphicsContext3D* context = layerRendererContext(); - context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId); - ASSERT(context->supportsMapSubCHROMIUM()); - void* mem = context->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, GraphicsContext3D::WRITE_ONLY); - skiaBitmap->setPixels(mem); - m_owner->paintGraphicsLayerContents(*m_graphicsContext, updateRect); - context->unmapTexSubImage2DCHROMIUM(mem); + ASSERT(context); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); + void* mem = context->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, GraphicsContext3D::WRITE_ONLY); + if (mem) { + memcpy(mem, data, dimensions.width() * dimensions.height()); + GLC(context, context->unmapTexSubImage2DCHROMIUM(mem)); + } else { + // FIXME: We should have some sort of code to handle the case when + // mapTexSubImage2D fails. + m_skipsDraw = true; } +} + +void VideoLayerChromium::draw() +{ + if (m_skipsDraw) + return; + + ASSERT(layerRenderer()); + const VideoLayerChromium::SharedValues* sv = layerRenderer()->videoLayerSharedValues(); + ASSERT(sv && sv->initialized()); - updateCompleted(); -#else - // FIXME: Implement non-skia path - notImplemented(); -#endif + switch (m_frameFormat) { + case VideoFrameChromium::YV12: + drawYUV(sv); + break; + case VideoFrameChromium::RGBA: + drawRGBA(sv); + break; + default: + // FIXME: Implement other paths. + notImplemented(); + break; + } } -void VideoLayerChromium::updateCompleted() +void VideoLayerChromium::drawYUV(const SharedValues* sv) { - m_dirtyRect.setSize(FloatSize()); - m_contentsDirty = false; + GraphicsContext3D* context = layerRendererContext(); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::yPlane])); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::uPlane])); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::vPlane])); + + layerRenderer()->useShader(sv->yuvShaderProgram()); + unsigned frameWidth = m_frameSizes[VideoFrameChromium::yPlane].width(); + unsigned textureWidth = m_textureSizes[VideoFrameChromium::yPlane].width(); + float widthScaleFactor = static_cast<float>(frameWidth) / textureWidth; + GLC(context, context->uniform1f(sv->yuvWidthScaleFactorLocation(), widthScaleFactor)); + + GLC(context, context->uniform1i(sv->yTextureLocation(), 1)); + GLC(context, context->uniform1i(sv->uTextureLocation(), 2)); + GLC(context, context->uniform1i(sv->vTextureLocation(), 3)); + + GLC(context, context->uniformMatrix3fv(sv->ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1)); + + drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + sv->yuvShaderMatrixLocation(), sv->yuvAlphaLocation()); + + // Reset active texture back to texture 0. + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); } +void VideoLayerChromium::drawRGBA(const SharedValues* sv) +{ + GraphicsContext3D* context = layerRendererContext(); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::rgbPlane])); + + layerRenderer()->useShader(sv->rgbaShaderProgram()); + unsigned frameWidth = m_frameSizes[VideoFrameChromium::rgbPlane].width(); + unsigned textureWidth = m_textureSizes[VideoFrameChromium::rgbPlane].width(); + float widthScaleFactor = static_cast<float>(frameWidth) / textureWidth; + GLC(context, context->uniform1f(sv->rgbaWidthScaleFactorLocation(), widthScaleFactor)); + + GLC(context, context->uniform1i(sv->rgbaTextureLocation(), 0)); + + drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + sv->rgbaShaderMatrixLocation(), sv->rgbaAlphaLocation()); } + +} // namespace WebCore + #endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/WebCore/platform/graphics/chromium/VideoLayerChromium.h index 3507cb2..620d1a7 100644 --- a/WebCore/platform/graphics/chromium/VideoLayerChromium.h +++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.h @@ -34,31 +34,76 @@ #if USE(ACCELERATED_COMPOSITING) -#include "ContentLayerChromium.h" +#include "LayerChromium.h" #include "VideoFrameProvider.h" namespace WebCore { // A Layer that contains a Video element. -class VideoLayerChromium : public ContentLayerChromium { +class VideoLayerChromium : public LayerChromium { public: static PassRefPtr<VideoLayerChromium> create(GraphicsLayerChromium* owner = 0, VideoFrameProvider* = 0); - virtual bool drawsContent() { return true; } + virtual ~VideoLayerChromium(); virtual void updateContents(); + virtual bool drawsContent() { return true; } + virtual void draw(); + + class SharedValues { + public: + explicit SharedValues(GraphicsContext3D*); + ~SharedValues(); + unsigned yuvShaderProgram() const { return m_yuvShaderProgram; } + unsigned rgbaShaderProgram() const { return m_rgbaShaderProgram; } + int yuvShaderMatrixLocation() const { return m_yuvShaderMatrixLocation; } + int rgbaShaderMatrixLocation() const { return m_rgbaShaderMatrixLocation; } + int yuvWidthScaleFactorLocation() const { return m_yuvWidthScaleFactorLocation; } + int rgbaWidthScaleFactorLocation() const { return m_rgbaWidthScaleFactorLocation; } + int yTextureLocation() const { return m_yTextureLocation; } + int uTextureLocation() const { return m_uTextureLocation; } + int vTextureLocation() const { return m_vTextureLocation; } + int yuvAlphaLocation() const { return m_yuvAlphaLocation; } + int rgbaAlphaLocation() const { return m_rgbaAlphaLocation; } + int rgbaTextureLocation() const { return m_rgbaTextureLocation; } + int ccMatrixLocation() const { return m_ccMatrixLocation; } + bool initialized() const { return m_initialized; }; + private: + GraphicsContext3D* m_context; + unsigned m_yuvShaderProgram; + unsigned m_rgbaShaderProgram; + int m_yuvShaderMatrixLocation; + int m_yuvWidthScaleFactorLocation; + int m_rgbaShaderMatrixLocation; + int m_rgbaWidthScaleFactorLocation; + int m_ccMatrixLocation; + int m_yTextureLocation; + int m_uTextureLocation; + int m_vTextureLocation; + int m_rgbaTextureLocation; + int m_yuvAlphaLocation; + int m_rgbaAlphaLocation; + bool m_initialized; + }; private: VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameProvider*); - void createTextureRect(const IntSize& requiredTextureSize, const IntRect& updateRect, unsigned textureId); - void updateTextureRect(const IntRect& updateRect, unsigned textureId); - void updateCompleted(); + static unsigned determineTextureFormat(VideoFrameChromium*); + bool allocateTexturesIfNeeded(GraphicsContext3D*, VideoFrameChromium*, unsigned textureFormat); + void updateYUVContents(GraphicsContext3D*, const VideoFrameChromium*); + void updateRGBAContents(GraphicsContext3D*, const VideoFrameChromium*); + void allocateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat); + void updateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat, const void* data); + void drawYUV(const SharedValues*); + void drawRGBA(const SharedValues*); -#if PLATFORM(SKIA) - OwnPtr<skia::PlatformCanvas> m_canvas; - OwnPtr<PlatformContextSkia> m_skiaContext; -#endif - OwnPtr<GraphicsContext> m_graphicsContext; + static const float yuv2RGB[9]; + + bool m_skipsDraw; + VideoFrameChromium::Format m_frameFormat; OwnPtr<VideoFrameProvider> m_provider; + unsigned m_textures[3]; + IntSize m_textureSizes[3]; + IntSize m_frameSizes[3]; }; } diff --git a/WebCore/platform/graphics/filters/DistantLightSource.h b/WebCore/platform/graphics/filters/DistantLightSource.h new file mode 100644 index 0000000..d5d474f --- /dev/null +++ b/WebCore/platform/graphics/filters/DistantLightSource.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef DistantLightSource_h +#define DistantLightSource_h + +#if ENABLE(FILTERS) +#include "LightSource.h" + +namespace WebCore { + +class DistantLightSource : public LightSource { +public: + static PassRefPtr<DistantLightSource> create(float azimuth, float elevation) + { + return adoptRef(new DistantLightSource(azimuth, elevation)); + } + + float azimuth() const { return m_azimuth; } + float elevation() const { return m_elevation; } + + virtual void initPaintingData(PaintingData&); + virtual void updatePaintingData(PaintingData&, int x, int y, float z); + + virtual TextStream& externalRepresentation(TextStream&) const; + +private: + DistantLightSource(float azimuth, float elevation) + : LightSource(LS_DISTANT) + , m_azimuth(azimuth) + , m_elevation(elevation) + { + } + + float m_azimuth; + float m_elevation; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // DistantLightSource_h diff --git a/WebCore/platform/graphics/filters/FEBlend.cpp b/WebCore/platform/graphics/filters/FEBlend.cpp index acd6545..4185f61 100644 --- a/WebCore/platform/graphics/filters/FEBlend.cpp +++ b/WebCore/platform/graphics/filters/FEBlend.cpp @@ -1,24 +1,24 @@ /* - Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> - 2004, 2005 Rob Buis <buis@kde.org> - 2005 Eric Seidel <eric@webkit.org> - 2009 Dirk Schulze <krit@webkit.org> - - 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 - aint 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. -*/ + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * 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. + */ #include "config.h" @@ -98,13 +98,13 @@ void FEBlend::apply(Filter* filter) if (m_mode == FEBLEND_MODE_UNKNOWN) return; - if (!getEffectContext()) + if (!effectContext()) return; - IntRect effectADrawingRect = calculateDrawingIntRect(in->repaintRectInLocalCoordinates()); + IntRect effectADrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates()); RefPtr<CanvasPixelArray> srcPixelArrayA(in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data()); - IntRect effectBDrawingRect = calculateDrawingIntRect(in2->repaintRectInLocalCoordinates()); + IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->repaintRectInLocalCoordinates()); RefPtr<CanvasPixelArray> srcPixelArrayB(in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)->data()); IntRect imageRect(IntPoint(), resultImage()->size()); diff --git a/WebCore/platform/graphics/filters/FEBlend.h b/WebCore/platform/graphics/filters/FEBlend.h index 2e67588..a6569e2 100644 --- a/WebCore/platform/graphics/filters/FEBlend.h +++ b/WebCore/platform/graphics/filters/FEBlend.h @@ -1,23 +1,23 @@ /* - Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> - 2004, 2005 Rob Buis <buis@kde.org> - 2005 Eric Seidel <eric@webkit.org> - - 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 - aint 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. -*/ + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ #ifndef FEBlend_h #define FEBlend_h @@ -29,31 +29,32 @@ namespace WebCore { - enum BlendModeType { - FEBLEND_MODE_UNKNOWN = 0, - FEBLEND_MODE_NORMAL = 1, - FEBLEND_MODE_MULTIPLY = 2, - FEBLEND_MODE_SCREEN = 3, - FEBLEND_MODE_DARKEN = 4, - FEBLEND_MODE_LIGHTEN = 5 - }; +enum BlendModeType { + FEBLEND_MODE_UNKNOWN = 0, + FEBLEND_MODE_NORMAL = 1, + FEBLEND_MODE_MULTIPLY = 2, + FEBLEND_MODE_SCREEN = 3, + FEBLEND_MODE_DARKEN = 4, + FEBLEND_MODE_LIGHTEN = 5 +}; - class FEBlend : public FilterEffect { - public: - static PassRefPtr<FEBlend> create(BlendModeType); +class FEBlend : public FilterEffect { +public: + static PassRefPtr<FEBlend> create(BlendModeType); - BlendModeType blendMode() const; - void setBlendMode(BlendModeType); + BlendModeType blendMode() const; + void setBlendMode(BlendModeType); - void apply(Filter*); - void dump(); - TextStream& externalRepresentation(TextStream&, int indent) const; + virtual void apply(Filter*); + virtual void dump(); - private: - FEBlend(BlendModeType); + virtual TextStream& externalRepresentation(TextStream&, int indention) const; - BlendModeType m_mode; - }; +private: + FEBlend(BlendModeType); + + BlendModeType m_mode; +}; } // namespace WebCore diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/WebCore/platform/graphics/filters/FEColorMatrix.cpp index 1d9c66b..86c37c2 100644 --- a/WebCore/platform/graphics/filters/FEColorMatrix.cpp +++ b/WebCore/platform/graphics/filters/FEColorMatrix.cpp @@ -1,24 +1,24 @@ /* - Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> - 2004, 2005 Rob Buis <buis@kde.org> - 2005 Eric Seidel <eric@webkit.org> - 2009 Dirk Schulze <krit@webkit.org> - - 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 - aint 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. -*/ + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * 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. + */ #include "config.h" @@ -160,11 +160,11 @@ void FEColorMatrix::apply(Filter* filter) if (!in->resultImage()) return; - GraphicsContext* filterContext = getEffectContext(); + GraphicsContext* filterContext = effectContext(); if (!filterContext) return; - filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, calculateDrawingRect(in->repaintRectInLocalCoordinates())); + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates())); IntRect imageRect(IntPoint(), resultImage()->size()); PassRefPtr<ImageData> imageData(resultImage()->getUnmultipliedImageData(imageRect)); diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.h b/WebCore/platform/graphics/filters/FEColorMatrix.h index 9b9084c..b898b17 100644 --- a/WebCore/platform/graphics/filters/FEColorMatrix.h +++ b/WebCore/platform/graphics/filters/FEColorMatrix.h @@ -1,23 +1,23 @@ /* - Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> - 2004, 2005 Rob Buis <buis@kde.org> - 2005 Eric Seidel <eric@webkit.org> - - 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 - aint 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. -*/ + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ #ifndef FEColorMatrix_h #define FEColorMatrix_h @@ -30,34 +30,35 @@ namespace WebCore { - enum ColorMatrixType { - FECOLORMATRIX_TYPE_UNKNOWN = 0, - FECOLORMATRIX_TYPE_MATRIX = 1, - FECOLORMATRIX_TYPE_SATURATE = 2, - FECOLORMATRIX_TYPE_HUEROTATE = 3, - FECOLORMATRIX_TYPE_LUMINANCETOALPHA = 4 - }; +enum ColorMatrixType { + FECOLORMATRIX_TYPE_UNKNOWN = 0, + FECOLORMATRIX_TYPE_MATRIX = 1, + FECOLORMATRIX_TYPE_SATURATE = 2, + FECOLORMATRIX_TYPE_HUEROTATE = 3, + FECOLORMATRIX_TYPE_LUMINANCETOALPHA = 4 +}; + +class FEColorMatrix : public FilterEffect { +public: + static PassRefPtr<FEColorMatrix> create(ColorMatrixType, const Vector<float>&); - class FEColorMatrix : public FilterEffect { - public: - static PassRefPtr<FEColorMatrix> create(ColorMatrixType, const Vector<float>&); + ColorMatrixType type() const; + void setType(ColorMatrixType); - ColorMatrixType type() const; - void setType(ColorMatrixType); + const Vector<float>& values() const; + void setValues(const Vector<float>&); - const Vector<float>& values() const; - void setValues(const Vector<float>&); + virtual void apply(Filter*); + virtual void dump(); - void apply(Filter*); - void dump(); - TextStream& externalRepresentation(TextStream&, int indent) const; + virtual TextStream& externalRepresentation(TextStream&, int indention) const; - private: - FEColorMatrix(ColorMatrixType, const Vector<float>&); +private: + FEColorMatrix(ColorMatrixType, const Vector<float>&); - ColorMatrixType m_type; - Vector<float> m_values; - }; + ColorMatrixType m_type; + Vector<float> m_values; +}; } // namespace WebCore diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp index 471fec8..6fe38e4 100644 --- a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp +++ b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp @@ -1,25 +1,25 @@ /* - Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> - 2004, 2005 Rob Buis <buis@kde.org> - 2005 Eric Seidel <eric@webkit.org> - 2009 Dirk Schulze <krit@webkit.org> - Copyright (C) Research In Motion Limited 2010. All rights reserved. - - 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 - aint 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. -*/ + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * 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. + */ #include "config.h" @@ -36,8 +36,8 @@ namespace WebCore { typedef void (*TransferType)(unsigned char*, const ComponentTransferFunction&); -FEComponentTransfer::FEComponentTransfer(const ComponentTransferFunction& redFunc, - const ComponentTransferFunction& greenFunc, const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc) +FEComponentTransfer::FEComponentTransfer(const ComponentTransferFunction& redFunc, const ComponentTransferFunction& greenFunc, + const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc) : FilterEffect() , m_redFunc(redFunc) , m_greenFunc(greenFunc) @@ -154,7 +154,7 @@ void FEComponentTransfer::apply(Filter* filter) if (!in->resultImage()) return; - if (!getEffectContext()) + if (!effectContext()) return; unsigned char rValues[256], gValues[256], bValues[256], aValues[256]; @@ -167,7 +167,7 @@ void FEComponentTransfer::apply(Filter* filter) for (unsigned channel = 0; channel < 4; channel++) (*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]); - IntRect drawingRect = calculateDrawingIntRect(in->repaintRectInLocalCoordinates()); + IntRect drawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates()); RefPtr<ImageData> imageData(in->resultImage()->getUnmultipliedImageData(drawingRect)); CanvasPixelArray* srcPixelArray(imageData->data()); diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.h b/WebCore/platform/graphics/filters/FEComponentTransfer.h index 55724db..d3145d4 100644 --- a/WebCore/platform/graphics/filters/FEComponentTransfer.h +++ b/WebCore/platform/graphics/filters/FEComponentTransfer.h @@ -1,23 +1,23 @@ /* - Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> - 2004, 2005 Rob Buis <buis@kde.org> - 2005 Eric Seidel <eric@webkit.org> - - 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 - aint 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. -*/ + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ #ifndef FEComponentTransfer_h #define FEComponentTransfer_h @@ -30,67 +30,68 @@ namespace WebCore { - enum ComponentTransferType { - FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0, - FECOMPONENTTRANSFER_TYPE_IDENTITY = 1, - FECOMPONENTTRANSFER_TYPE_TABLE = 2, - FECOMPONENTTRANSFER_TYPE_DISCRETE = 3, - FECOMPONENTTRANSFER_TYPE_LINEAR = 4, - FECOMPONENTTRANSFER_TYPE_GAMMA = 5 - }; - - struct ComponentTransferFunction { - ComponentTransferFunction() - : type(FECOMPONENTTRANSFER_TYPE_UNKNOWN) - , slope(0.0f) - , intercept(0.0f) - , amplitude(0.0f) - , exponent(0.0f) - , offset(0.0f) - { - } - - ComponentTransferType type; - - float slope; - float intercept; - float amplitude; - float exponent; - float offset; - - Vector<float> tableValues; - }; - - class FEComponentTransfer : public FilterEffect { - public: - static PassRefPtr<FEComponentTransfer> create(const ComponentTransferFunction&, - const ComponentTransferFunction&, const ComponentTransferFunction&, const ComponentTransferFunction&); - - ComponentTransferFunction redFunction() const; - void setRedFunction(const ComponentTransferFunction&); - - ComponentTransferFunction greenFunction() const; - void setGreenFunction(const ComponentTransferFunction&); - - ComponentTransferFunction blueFunction() const; - void setBlueFunction(const ComponentTransferFunction&); - - ComponentTransferFunction alphaFunction() const; - void setAlphaFunction(const ComponentTransferFunction&); - - void apply(Filter*); - void dump(); - TextStream& externalRepresentation(TextStream&, int indent) const; - - private: - FEComponentTransfer(const ComponentTransferFunction&, const ComponentTransferFunction&, - const ComponentTransferFunction&, const ComponentTransferFunction&); - - ComponentTransferFunction m_redFunc; - ComponentTransferFunction m_greenFunc; - ComponentTransferFunction m_blueFunc; - ComponentTransferFunction m_alphaFunc; - }; +enum ComponentTransferType { + FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0, + FECOMPONENTTRANSFER_TYPE_IDENTITY = 1, + FECOMPONENTTRANSFER_TYPE_TABLE = 2, + FECOMPONENTTRANSFER_TYPE_DISCRETE = 3, + FECOMPONENTTRANSFER_TYPE_LINEAR = 4, + FECOMPONENTTRANSFER_TYPE_GAMMA = 5 +}; + +struct ComponentTransferFunction { + ComponentTransferFunction() + : type(FECOMPONENTTRANSFER_TYPE_UNKNOWN) + , slope(0) + , intercept(0) + , amplitude(0) + , exponent(0) + , offset(0) + { + } + + ComponentTransferType type; + + float slope; + float intercept; + float amplitude; + float exponent; + float offset; + + Vector<float> tableValues; +}; + +class FEComponentTransfer : public FilterEffect { +public: + static PassRefPtr<FEComponentTransfer> create(const ComponentTransferFunction& redFunc, const ComponentTransferFunction& greenFunc, + const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc); + + ComponentTransferFunction redFunction() const; + void setRedFunction(const ComponentTransferFunction&); + + ComponentTransferFunction greenFunction() const; + void setGreenFunction(const ComponentTransferFunction&); + + ComponentTransferFunction blueFunction() const; + void setBlueFunction(const ComponentTransferFunction&); + + ComponentTransferFunction alphaFunction() const; + void setAlphaFunction(const ComponentTransferFunction&); + + virtual void apply(Filter*); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEComponentTransfer(const ComponentTransferFunction& redFunc, const ComponentTransferFunction& greenFunc, + const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc); + + ComponentTransferFunction m_redFunc; + ComponentTransferFunction m_greenFunc; + ComponentTransferFunction m_blueFunc; + ComponentTransferFunction m_alphaFunc; +}; } // namespace WebCore diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp index c10a0f2..94e2524 100644 --- a/WebCore/platform/graphics/filters/FEComposite.cpp +++ b/WebCore/platform/graphics/filters/FEComposite.cpp @@ -1,24 +1,24 @@ /* - Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> - 2004, 2005 Rob Buis <buis@kde.org> - 2005 Eric Seidel <eric@webkit.org> - 2009 Dirk Schulze <krit@webkit.org> - - 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 - aint 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. -*/ + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * 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. + */ #include "config.h" @@ -122,39 +122,39 @@ void FEComposite::apply(Filter* filter) if (!in->resultImage() || !in2->resultImage()) return; - GraphicsContext* filterContext = getEffectContext(); + GraphicsContext* filterContext = effectContext(); if (!filterContext) return; - FloatRect srcRect = FloatRect(0.f, 0.f, -1.f, -1.f); + FloatRect srcRect = FloatRect(0, 0, -1, -1); switch (m_type) { case FECOMPOSITE_OPERATOR_OVER: - filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, calculateDrawingRect(in2->repaintRectInLocalCoordinates())); - filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, calculateDrawingRect(in->repaintRectInLocalCoordinates())); + filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates())); + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates())); break; case FECOMPOSITE_OPERATOR_IN: filterContext->save(); - filterContext->clipToImageBuffer(in2->resultImage(), calculateDrawingRect(in2->repaintRectInLocalCoordinates())); - filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, calculateDrawingRect(in->repaintRectInLocalCoordinates())); + filterContext->clipToImageBuffer(in2->resultImage(), drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates())); + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates())); filterContext->restore(); break; case FECOMPOSITE_OPERATOR_OUT: - filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, calculateDrawingRect(in->repaintRectInLocalCoordinates())); - filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, calculateDrawingRect(in2->repaintRectInLocalCoordinates()), srcRect, CompositeDestinationOut); + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates())); + filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates()), srcRect, CompositeDestinationOut); break; case FECOMPOSITE_OPERATOR_ATOP: - filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, calculateDrawingRect(in2->repaintRectInLocalCoordinates())); - filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, calculateDrawingRect(in->repaintRectInLocalCoordinates()), srcRect, CompositeSourceAtop); + filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates())); + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()), srcRect, CompositeSourceAtop); break; case FECOMPOSITE_OPERATOR_XOR: - filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, calculateDrawingRect(in2->repaintRectInLocalCoordinates())); - filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, calculateDrawingRect(in->repaintRectInLocalCoordinates()), srcRect, CompositeXOR); + filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates())); + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()), srcRect, CompositeXOR); break; case FECOMPOSITE_OPERATOR_ARITHMETIC: { - IntRect effectADrawingRect = calculateDrawingIntRect(in->repaintRectInLocalCoordinates()); + IntRect effectADrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates()); RefPtr<CanvasPixelArray> srcPixelArrayA(in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data()); - IntRect effectBDrawingRect = calculateDrawingIntRect(in2->repaintRectInLocalCoordinates()); + IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->repaintRectInLocalCoordinates()); RefPtr<ImageData> imageData(in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)); CanvasPixelArray* srcPixelArrayB(imageData->data()); diff --git a/WebCore/platform/graphics/filters/FEComposite.h b/WebCore/platform/graphics/filters/FEComposite.h index 448d036..82a3b06 100644 --- a/WebCore/platform/graphics/filters/FEComposite.h +++ b/WebCore/platform/graphics/filters/FEComposite.h @@ -1,23 +1,23 @@ /* - Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> - 2004, 2005 Rob Buis <buis@kde.org> - 2005 Eric Seidel <eric@webkit.org> - - 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 - aint 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. -*/ + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ #ifndef FEComposite_h #define FEComposite_h @@ -59,9 +59,10 @@ public: float k4() const; void setK4(float); - void apply(Filter*); - void dump(); - TextStream& externalRepresentation(TextStream&, int indent) const; + virtual void apply(Filter*); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; private: FEComposite(const CompositeOperationType&, float, float, float, float); diff --git a/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp b/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp new file mode 100644 index 0000000..dd66c6a --- /dev/null +++ b/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp @@ -0,0 +1,471 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org> + * + * 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. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEConvolveMatrix.h" + +#include "CanvasPixelArray.h" +#include "Filter.h" +#include "ImageData.h" + +namespace WebCore { + +FEConvolveMatrix::FEConvolveMatrix(const IntSize& kernelSize, + float divisor, float bias, const IntPoint& targetOffset, EdgeModeType edgeMode, + const FloatPoint& kernelUnitLength, bool preserveAlpha, const Vector<float>& kernelMatrix) + : FilterEffect() + , m_kernelSize(kernelSize) + , m_divisor(divisor) + , m_bias(bias) + , m_targetOffset(targetOffset) + , m_edgeMode(edgeMode) + , m_kernelUnitLength(kernelUnitLength) + , m_preserveAlpha(preserveAlpha) + , m_kernelMatrix(kernelMatrix) +{ +} + +PassRefPtr<FEConvolveMatrix> FEConvolveMatrix::create(const IntSize& kernelSize, + float divisor, float bias, const IntPoint& targetOffset, EdgeModeType edgeMode, + const FloatPoint& kernelUnitLength, bool preserveAlpha, const Vector<float>& kernelMatrix) +{ + return adoptRef(new FEConvolveMatrix(kernelSize, divisor, bias, targetOffset, edgeMode, kernelUnitLength, + preserveAlpha, kernelMatrix)); +} + + +IntSize FEConvolveMatrix::kernelSize() const +{ + return m_kernelSize; +} + +void FEConvolveMatrix::setKernelSize(IntSize kernelSize) +{ + m_kernelSize = kernelSize; +} + +const Vector<float>& FEConvolveMatrix::kernel() const +{ + return m_kernelMatrix; +} + +void FEConvolveMatrix::setKernel(const Vector<float>& kernel) +{ + m_kernelMatrix = kernel; +} + +float FEConvolveMatrix::divisor() const +{ + return m_divisor; +} + +void FEConvolveMatrix::setDivisor(float divisor) +{ + m_divisor = divisor; +} + +float FEConvolveMatrix::bias() const +{ + return m_bias; +} + +void FEConvolveMatrix::setBias(float bias) +{ + m_bias = bias; +} + +IntPoint FEConvolveMatrix::targetOffset() const +{ + return m_targetOffset; +} + +void FEConvolveMatrix::setTargetOffset(IntPoint targetOffset) +{ + m_targetOffset = targetOffset; +} + +EdgeModeType FEConvolveMatrix::edgeMode() const +{ + return m_edgeMode; +} + +void FEConvolveMatrix::setEdgeMode(EdgeModeType edgeMode) +{ + m_edgeMode = edgeMode; +} + +FloatPoint FEConvolveMatrix::kernelUnitLength() const +{ + return m_kernelUnitLength; +} + +void FEConvolveMatrix::setKernelUnitLength(FloatPoint kernelUnitLength) +{ + m_kernelUnitLength = kernelUnitLength; +} + +bool FEConvolveMatrix::preserveAlpha() const +{ + return m_preserveAlpha; +} + +void FEConvolveMatrix::setPreserveAlpha(bool preserveAlpha) +{ + m_preserveAlpha = preserveAlpha; +} + +/* + ----------------------------------- + ConvolveMatrix implementation + ----------------------------------- + + The image rectangle is split in the following way: + + +---------------------+ + | A | + +---------------------+ + | | | | + | B | C | D | + | | | | + +---------------------+ + | E | + +---------------------+ + + Where region C contains those pixels, whose values + can be calculated without crossing the edge of the rectangle. + + Example: + Image size: width: 10, height: 10 + + Order (kernel matrix size): width: 3, height 4 + Target: x:1, y:3 + + The following figure shows the target inside the kernel matrix: + + ... + ... + ... + .X. + + The regions in this case are the following: + Note: (x1, y1) top-left and (x2, y2) is the bottom-right corner + Note: row x2 and column y2 is not part of the region + only those (x, y) pixels, where x1 <= x < x2 and y1 <= y < y2 + + Region A: x1: 0, y1: 0, x2: 10, y2: 3 + Region B: x1: 0, y1: 3, x2: 1, y2: 10 + Region C: x1: 1, y1: 3, x2: 9, y2: 10 + Region D: x1: 9, y1: 3, x2: 10, y2: 10 + Region E: x1: 0, y1: 10, x2: 10, y2: 10 (empty region) + + Since region C (often) contains most of the pixels, we implemented + a fast algoritm to calculate these values, called fastSetInteriorPixels. + For other regions, fastSetOuterPixels is used, which calls getPixelValue, + to handle pixels outside of the image. In a rare situations, when + kernel matrix is bigger than the image, all pixels are calculated by this + function. + + Although these two functions have lot in common, I decided not to make + common a template for them, since there are key differences as well, + and would make it really hard to understand. +*/ + +static ALWAYS_INLINE unsigned char clampRGBAValue(float channel, unsigned char max = 255) +{ + if (channel <= 0) + return 0; + if (channel >= max) + return max; + return channel; +} + +template<bool preserveAlphaValues> +ALWAYS_INLINE void setDestinationPixels(CanvasPixelArray* image, int& pixel, float* totals, float divisor, float bias, CanvasPixelArray* src) +{ + unsigned char maxAlpha = preserveAlphaValues ? 255 : clampRGBAValue(totals[3] / divisor + bias); + for (int i = 0; i < 3; ++i) + image->set(pixel++, clampRGBAValue(totals[i] / divisor + bias, maxAlpha)); + + if (preserveAlphaValues) { + image->set(pixel, src->get(pixel)); + ++pixel; + } else + image->set(pixel++, maxAlpha); +} + +// Only for region C +template<bool preserveAlphaValues> +ALWAYS_INLINE void FEConvolveMatrix::fastSetInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom) +{ + // edge mode does not affect these pixels + int pixel = (m_targetOffset.y() * paintingData.width + m_targetOffset.x()) * 4; + int startKernelPixel = 0; + int kernelIncrease = clipRight * 4; + int xIncrease = (m_kernelSize.width() - 1) * 4; + // Contains the sum of rgb(a) components + float totals[3 + (preserveAlphaValues ? 0 : 1)]; + + // m_divisor cannot be 0, SVGFEConvolveMatrixElement ensures this + ASSERT(m_divisor); + + for (int y = clipBottom + 1; y > 0; --y) { + for (int x = clipRight + 1; x > 0; --x) { + int kernelValue = m_kernelMatrix.size() - 1; + int kernelPixel = startKernelPixel; + int width = m_kernelSize.width(); + + totals[0] = 0; + totals[1] = 0; + totals[2] = 0; + if (!preserveAlphaValues) + totals[3] = 0; + + while (kernelValue >= 0) { + totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel++)); + totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel++)); + totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel++)); + if (!preserveAlphaValues) + totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel)); + ++kernelPixel; + --kernelValue; + if (!--width) { + kernelPixel += kernelIncrease; + width = m_kernelSize.width(); + } + } + + setDestinationPixels<preserveAlphaValues>(paintingData.dstPixelArray, pixel, totals, m_divisor, paintingData.bias, paintingData.srcPixelArray); + startKernelPixel += 4; + } + pixel += xIncrease; + startKernelPixel += xIncrease; + } +} + +ALWAYS_INLINE int FEConvolveMatrix::getPixelValue(PaintingData& paintingData, int x, int y) +{ + if (x >= 0 && x < paintingData.width && x >= 0 && y < paintingData.height) + return (y * paintingData.width + x) << 2; + + switch (m_edgeMode) { + default: // EDGEMODE_NONE + return -1; + case EDGEMODE_DUPLICATE: + if (x < 0) + x = 0; + else if (x >= paintingData.width) + x = paintingData.width - 1; + if (y < 0) + y = 0; + else if (y >= paintingData.height) + y = paintingData.height - 1; + return (y * paintingData.width + x) << 2; + case EDGEMODE_WRAP: + while (x < 0) + x += paintingData.width; + x %= paintingData.width; + while (y < 0) + y += paintingData.height; + y %= paintingData.height; + return (y * paintingData.width + x) << 2; + } +} + +// For other regions than C +template<bool preserveAlphaValues> +void FEConvolveMatrix::fastSetOuterPixels(PaintingData& paintingData, int x1, int y1, int x2, int y2) +{ + int pixel = (y1 * paintingData.width + x1) * 4; + int height = y2 - y1; + int width = x2 - x1; + int beginKernelPixelX = x1 - m_targetOffset.x(); + int startKernelPixelX = beginKernelPixelX; + int startKernelPixelY = y1 - m_targetOffset.y(); + int xIncrease = (paintingData.width - width) * 4; + // Contains the sum of rgb(a) components + float totals[3 + (preserveAlphaValues ? 0 : 1)]; + + // m_divisor cannot be 0, SVGFEConvolveMatrixElement ensures this + ASSERT(m_divisor); + + for (int y = height; y > 0; --y) { + for (int x = width; x > 0; --x) { + int kernelValue = m_kernelMatrix.size() - 1; + int kernelPixelX = startKernelPixelX; + int kernelPixelY = startKernelPixelY; + int width = m_kernelSize.width(); + + totals[0] = 0; + totals[1] = 0; + totals[2] = 0; + if (!preserveAlphaValues) + totals[3] = 0; + + while (kernelValue >= 0) { + int pixelIndex = getPixelValue(paintingData, kernelPixelX, kernelPixelY); + if (pixelIndex >= 0) { + totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex)); + totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex + 1)); + totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex + 2)); + } + if (!preserveAlphaValues && pixelIndex >= 0) + totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex + 3)); + ++kernelPixelX; + --kernelValue; + if (!--width) { + kernelPixelX = startKernelPixelX; + ++kernelPixelY; + width = m_kernelSize.width(); + } + } + + setDestinationPixels<preserveAlphaValues>(paintingData.dstPixelArray, pixel, totals, m_divisor, paintingData.bias, paintingData.srcPixelArray); + ++startKernelPixelX; + } + pixel += xIncrease; + startKernelPixelX = beginKernelPixelX; + ++startKernelPixelY; + } +} + +ALWAYS_INLINE void FEConvolveMatrix::setInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom) +{ + // Must be implemented here, since it refers another ALWAYS_INLINE + // function, which defined in this C++ source file as well + if (m_preserveAlpha) + fastSetInteriorPixels<true>(paintingData, clipRight, clipBottom); + else + fastSetInteriorPixels<false>(paintingData, clipRight, clipBottom); +} + +ALWAYS_INLINE void FEConvolveMatrix::setOuterPixels(PaintingData& paintingData, int x1, int y1, int x2, int y2) +{ + // Although this function can be moved to the header, it is implemented here + // because setInteriorPixels is also implemented here + if (m_preserveAlpha) + fastSetOuterPixels<true>(paintingData, x1, y1, x2, y2); + else + fastSetOuterPixels<false>(paintingData, x1, y1, x2, y2); +} + +void FEConvolveMatrix::apply(Filter* filter) +{ + FilterEffect* in = inputEffect(0); + in->apply(filter); + if (!in->resultImage()) + return; + + if (!effectContext()) + return; + + IntRect imageRect(IntPoint(), resultImage()->size()); + IntRect effectDrawingRect = requestedRegionOfInputImageData(in->filterPrimitiveSubregion()); + + RefPtr<CanvasPixelArray> srcPixelArray; + if (m_preserveAlpha) + srcPixelArray = in->resultImage()->getUnmultipliedImageData(effectDrawingRect)->data(); + else + srcPixelArray = in->resultImage()->getPremultipliedImageData(effectDrawingRect)->data(); + + RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height()); + + PaintingData paintingData; + paintingData.srcPixelArray = srcPixelArray.get(); + paintingData.dstPixelArray = imageData->data(); + paintingData.width = imageRect.width(); + paintingData.height = imageRect.height(); + paintingData.bias = m_bias * 255; + + // Drawing fully covered pixels + int clipRight = imageRect.width() - m_kernelSize.width(); + int clipBottom = imageRect.height() - m_kernelSize.height(); + + if (clipRight >= 0 && clipBottom >= 0) { + setInteriorPixels(paintingData, clipRight, clipBottom); + + clipRight += m_targetOffset.x() + 1; + clipBottom += m_targetOffset.y() + 1; + if (m_targetOffset.y() > 0) + setOuterPixels(paintingData, 0, 0, imageRect.width(), m_targetOffset.y()); + if (clipBottom < imageRect.height()) + setOuterPixels(paintingData, 0, clipBottom, imageRect.width(), imageRect.height()); + if (m_targetOffset.x() > 0) + setOuterPixels(paintingData, 0, m_targetOffset.y(), m_targetOffset.x(), clipBottom); + if (clipRight < imageRect.width()) + setOuterPixels(paintingData, clipRight, m_targetOffset.y(), imageRect.width(), clipBottom); + } else { + // Rare situation, not optimizied for speed + setOuterPixels(paintingData, 0, 0, imageRect.width(), imageRect.height()); + } + + if (m_preserveAlpha) + resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint()); + else + resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint()); +} + +void FEConvolveMatrix::dump() +{ +} + +static TextStream& operator<<(TextStream& ts, const EdgeModeType& type) +{ + switch (type) { + case EDGEMODE_UNKNOWN: + ts << "UNKNOWN"; + break; + case EDGEMODE_DUPLICATE: + ts << "DUPLICATE"; + break; + case EDGEMODE_WRAP: + ts << "WRAP"; + break; + case EDGEMODE_NONE: + ts << "NONE"; + break; + } + return ts; +} + +TextStream& FEConvolveMatrix::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feConvolveMatrix"; + FilterEffect::externalRepresentation(ts); + ts << " order=\"" << m_kernelSize << "\" " + << "kernelMatrix=\"" << m_kernelMatrix << "\" " + << "divisor=\"" << m_divisor << "\" " + << "bias=\"" << m_bias << "\" " + << "target=\"" << m_targetOffset << "\" " + << "edgeMode=\"" << m_edgeMode << "\" " + << "kernelUnitLength=\"" << m_kernelUnitLength << "\" " + << "preserveAlpha=\"" << m_preserveAlpha << "\"]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + return ts; +} + +}; // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/WebCore/platform/graphics/filters/FEConvolveMatrix.h b/WebCore/platform/graphics/filters/FEConvolveMatrix.h new file mode 100644 index 0000000..2fe634f --- /dev/null +++ b/WebCore/platform/graphics/filters/FEConvolveMatrix.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org> + * + * 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. + */ + +#ifndef FEConvolveMatrix_h +#define FEConvolveMatrix_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" +#include "FloatPoint.h" +#include "FloatSize.h" +#include "Filter.h" +#include <wtf/AlwaysInline.h> +#include <wtf/Vector.h> + +namespace WebCore { + +enum EdgeModeType { + EDGEMODE_UNKNOWN = 0, + EDGEMODE_DUPLICATE = 1, + EDGEMODE_WRAP = 2, + EDGEMODE_NONE = 3 +}; + +class CanvasPixelArray; + +class FEConvolveMatrix : public FilterEffect { +public: + static PassRefPtr<FEConvolveMatrix> create(const IntSize&, + float, float, const IntPoint&, EdgeModeType, const FloatPoint&, + bool, const Vector<float>&); + + IntSize kernelSize() const; + void setKernelSize(IntSize); + + const Vector<float>& kernel() const; + void setKernel(const Vector<float>&); + + float divisor() const; + void setDivisor(float); + + float bias() const; + void setBias(float); + + IntPoint targetOffset() const; + void setTargetOffset(IntPoint); + + EdgeModeType edgeMode() const; + void setEdgeMode(EdgeModeType); + + FloatPoint kernelUnitLength() const; + void setKernelUnitLength(FloatPoint); + + bool preserveAlpha() const; + void setPreserveAlpha(bool); + + virtual void apply(Filter*); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEConvolveMatrix(const IntSize&, float, float, + const IntPoint&, EdgeModeType, const FloatPoint&, bool, const Vector<float>&); + + struct PaintingData { + CanvasPixelArray* srcPixelArray; + CanvasPixelArray* dstPixelArray; + int width; + int height; + float bias; + }; + + template<bool preserveAlphaValues> + ALWAYS_INLINE void fastSetInteriorPixels(PaintingData&, int clipRight, int clipBottom); + + ALWAYS_INLINE int getPixelValue(PaintingData&, int x, int y); + + template<bool preserveAlphaValues> + void fastSetOuterPixels(PaintingData&, int x1, int y1, int x2, int y2); + + // Wrapper functions + ALWAYS_INLINE void setInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom); + ALWAYS_INLINE void setOuterPixels(PaintingData& paintingData, int x1, int y1, int x2, int y2); + + IntSize m_kernelSize; + float m_divisor; + float m_bias; + IntPoint m_targetOffset; + EdgeModeType m_edgeMode; + FloatPoint m_kernelUnitLength; + bool m_preserveAlpha; + Vector<float> m_kernelMatrix; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEConvolveMatrix_h diff --git a/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp b/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp new file mode 100644 index 0000000..98b5adf --- /dev/null +++ b/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEDiffuseLighting.h" + +#include "LightSource.h" + +namespace WebCore { + +FEDiffuseLighting::FEDiffuseLighting(const Color& lightingColor, float surfaceScale, + float diffuseConstant, float kernelUnitLengthX, float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) + : FELighting(DiffuseLighting, lightingColor, surfaceScale, diffuseConstant, 0, 0, kernelUnitLengthX, kernelUnitLengthY, lightSource) +{ +} + +PassRefPtr<FEDiffuseLighting> FEDiffuseLighting::create(const Color& lightingColor, + float surfaceScale, float diffuseConstant, float kernelUnitLengthX, + float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) +{ + return adoptRef(new FEDiffuseLighting(lightingColor, surfaceScale, diffuseConstant, kernelUnitLengthX, kernelUnitLengthY, lightSource)); +} + +FEDiffuseLighting::~FEDiffuseLighting() +{ +} + +Color FEDiffuseLighting::lightingColor() const +{ + return m_lightingColor; +} + +void FEDiffuseLighting::setLightingColor(const Color& lightingColor) +{ + m_lightingColor = lightingColor; +} + +float FEDiffuseLighting::surfaceScale() const +{ + return m_surfaceScale; +} + +void FEDiffuseLighting::setSurfaceScale(float surfaceScale) +{ + m_surfaceScale = surfaceScale; +} + +float FEDiffuseLighting::diffuseConstant() const +{ + return m_diffuseConstant; +} + +void FEDiffuseLighting::setDiffuseConstant(float diffuseConstant) +{ + m_diffuseConstant = diffuseConstant; +} + +float FEDiffuseLighting::kernelUnitLengthX() const +{ + return m_kernelUnitLengthX; +} + +void FEDiffuseLighting::setKernelUnitLengthX(float kernelUnitLengthX) +{ + m_kernelUnitLengthX = kernelUnitLengthX; +} + +float FEDiffuseLighting::kernelUnitLengthY() const +{ + return m_kernelUnitLengthY; +} + +void FEDiffuseLighting::setKernelUnitLengthY(float kernelUnitLengthY) +{ + m_kernelUnitLengthY = kernelUnitLengthY; +} + +const LightSource* FEDiffuseLighting::lightSource() const +{ + return m_lightSource.get(); +} + +void FEDiffuseLighting::setLightSource(PassRefPtr<LightSource> lightSource) +{ + m_lightSource = lightSource; +} + +void FEDiffuseLighting::dump() +{ +} + +TextStream& FEDiffuseLighting::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feDiffuseLighting"; + FilterEffect::externalRepresentation(ts); + ts << " surfaceScale=\"" << m_surfaceScale << "\" " + << "diffuseConstant=\"" << m_diffuseConstant << "\" " + << "kernelUnitLength=\"" << m_kernelUnitLengthX << ", " << m_kernelUnitLengthY << "\"]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/WebCore/platform/graphics/filters/FEDiffuseLighting.h b/WebCore/platform/graphics/filters/FEDiffuseLighting.h new file mode 100644 index 0000000..5273144 --- /dev/null +++ b/WebCore/platform/graphics/filters/FEDiffuseLighting.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef FEDiffuseLighting_h +#define FEDiffuseLighting_h + +#if ENABLE(FILTERS) +#include "FELighting.h" + +namespace WebCore { + +class LightSource; + +class FEDiffuseLighting : public FELighting { +public: + static PassRefPtr<FEDiffuseLighting> create(const Color&, float, float, + float, float, PassRefPtr<LightSource>); + virtual ~FEDiffuseLighting(); + + Color lightingColor() const; + void setLightingColor(const Color&); + + float surfaceScale() const; + void setSurfaceScale(float); + + float diffuseConstant() const; + void setDiffuseConstant(float); + + float kernelUnitLengthX() const; + void setKernelUnitLengthX(float); + + float kernelUnitLengthY() const; + void setKernelUnitLengthY(float); + + const LightSource* lightSource() const; + void setLightSource(PassRefPtr<LightSource>); + + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEDiffuseLighting(const Color&, float, float, float, float, PassRefPtr<LightSource>); +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEDiffuseLighting_h diff --git a/WebCore/platform/graphics/filters/FEDisplacementMap.cpp b/WebCore/platform/graphics/filters/FEDisplacementMap.cpp new file mode 100644 index 0000000..6b5dbaa --- /dev/null +++ b/WebCore/platform/graphics/filters/FEDisplacementMap.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * 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. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEDisplacementMap.h" + +#include "CanvasPixelArray.h" +#include "Filter.h" +#include "GraphicsContext.h" +#include "ImageData.h" + +namespace WebCore { + +FEDisplacementMap::FEDisplacementMap(ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float scale) + : FilterEffect() + , m_xChannelSelector(xChannelSelector) + , m_yChannelSelector(yChannelSelector) + , m_scale(scale) +{ +} + +PassRefPtr<FEDisplacementMap> FEDisplacementMap::create(ChannelSelectorType xChannelSelector, + ChannelSelectorType yChannelSelector, float scale) +{ + return adoptRef(new FEDisplacementMap(xChannelSelector, yChannelSelector, scale)); +} + +ChannelSelectorType FEDisplacementMap::xChannelSelector() const +{ + return m_xChannelSelector; +} + +void FEDisplacementMap::setXChannelSelector(const ChannelSelectorType xChannelSelector) +{ + m_xChannelSelector = xChannelSelector; +} + +ChannelSelectorType FEDisplacementMap::yChannelSelector() const +{ + return m_yChannelSelector; +} + +void FEDisplacementMap::setYChannelSelector(const ChannelSelectorType yChannelSelector) +{ + m_yChannelSelector = yChannelSelector; +} + +float FEDisplacementMap::scale() const +{ + return m_scale; +} + +void FEDisplacementMap::setScale(float scale) +{ + m_scale = scale; +} + +void FEDisplacementMap::apply(Filter* filter) +{ + FilterEffect* in = inputEffect(0); + FilterEffect* in2 = inputEffect(1); + in->apply(filter); + in2->apply(filter); + if (!in->resultImage() || !in2->resultImage()) + return; + + if (m_xChannelSelector == CHANNEL_UNKNOWN || m_yChannelSelector == CHANNEL_UNKNOWN) + return; + + if (!effectContext()) + return; + + IntRect effectADrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates()); + RefPtr<CanvasPixelArray> srcPixelArrayA(in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data()); + + IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->repaintRectInLocalCoordinates()); + RefPtr<CanvasPixelArray> srcPixelArrayB(in2->resultImage()->getUnmultipliedImageData(effectBDrawingRect)->data()); + + IntRect imageRect(IntPoint(), resultImage()->size()); + RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height()); + + ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length()); + + float scaleX = m_scale / 255.f * filter->filterResolution().width(); + float scaleY = m_scale / 255.f * filter->filterResolution().height(); + float scaleAdjustmentX = (0.5f - 0.5f * m_scale) * filter->filterResolution().width(); + float scaleAdjustmentY = (0.5f - 0.5f * m_scale) * filter->filterResolution().height(); + int stride = imageRect.width() * 4; + for (int y = 0; y < imageRect.height(); ++y) { + int line = y * stride; + for (int x = 0; x < imageRect.width(); ++x) { + int dstIndex = line + x * 4; + int srcX = x + static_cast<int>(scaleX * srcPixelArrayB->get(dstIndex + m_xChannelSelector - 1) + scaleAdjustmentX); + int srcY = y + static_cast<int>(scaleY * srcPixelArrayB->get(dstIndex + m_yChannelSelector - 1) + scaleAdjustmentY); + for (unsigned channel = 0; channel < 4; ++channel) { + if (srcX < 0 || srcX >= imageRect.width() || srcY < 0 || srcY >= imageRect.height()) + imageData->data()->set(dstIndex + channel, static_cast<unsigned char>(0)); + else { + unsigned char pixelValue = srcPixelArrayA->get(srcY * stride + srcX * 4 + channel); + imageData->data()->set(dstIndex + channel, pixelValue); + } + } + + } + } + resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint()); +} + +void FEDisplacementMap::dump() +{ +} + +static TextStream& operator<<(TextStream& ts, const ChannelSelectorType& type) +{ + switch (type) { + case CHANNEL_UNKNOWN: + ts << "UNKNOWN"; + break; + case CHANNEL_R: + ts << "RED"; + break; + case CHANNEL_G: + ts << "GREEN"; + break; + case CHANNEL_B: + ts << "BLUE"; + break; + case CHANNEL_A: + ts << "ALPHA"; + break; + } + return ts; +} + +TextStream& FEDisplacementMap::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feDisplacementMap"; + FilterEffect::externalRepresentation(ts); + ts << " scale=\"" << m_scale << "\" " + << "xChannelSelector=\"" << m_xChannelSelector << "\" " + << "yChannelSelector=\"" << m_yChannelSelector << "\"]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + inputEffect(1)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/WebCore/platform/graphics/filters/FEDisplacementMap.h b/WebCore/platform/graphics/filters/FEDisplacementMap.h new file mode 100644 index 0000000..dc87b90 --- /dev/null +++ b/WebCore/platform/graphics/filters/FEDisplacementMap.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef FEDisplacementMap_h +#define FEDisplacementMap_h + +#if ENABLE(FILTERS) +#include "PlatformString.h" +#include "FilterEffect.h" +#include "Filter.h" + +namespace WebCore { + +enum ChannelSelectorType { + CHANNEL_UNKNOWN = 0, + CHANNEL_R = 1, + CHANNEL_G = 2, + CHANNEL_B = 3, + CHANNEL_A = 4 +}; + +class FEDisplacementMap : public FilterEffect { +public: + static PassRefPtr<FEDisplacementMap> create(ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float); + + ChannelSelectorType xChannelSelector() const; + void setXChannelSelector(const ChannelSelectorType); + + ChannelSelectorType yChannelSelector() const; + void setYChannelSelector(const ChannelSelectorType); + + float scale() const; + void setScale(float scale); + + virtual void apply(Filter*); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEDisplacementMap(ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float); + + ChannelSelectorType m_xChannelSelector; + ChannelSelectorType m_yChannelSelector; + float m_scale; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEDisplacementMap_h diff --git a/WebCore/platform/graphics/filters/FEFlood.cpp b/WebCore/platform/graphics/filters/FEFlood.cpp new file mode 100644 index 0000000..7804d89 --- /dev/null +++ b/WebCore/platform/graphics/filters/FEFlood.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * 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. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEFlood.h" + +#include "Filter.h" +#include "GraphicsContext.h" + +namespace WebCore { + +FEFlood::FEFlood(const Color& floodColor, float floodOpacity) + : FilterEffect() + , m_floodColor(floodColor) + , m_floodOpacity(floodOpacity) +{ +} + +PassRefPtr<FEFlood> FEFlood::create(const Color& floodColor, float floodOpacity) +{ + return adoptRef(new FEFlood(floodColor, floodOpacity)); +} + +Color FEFlood::floodColor() const +{ + return m_floodColor; +} + +void FEFlood::setFloodColor(const Color& color) +{ + m_floodColor = color; +} + +float FEFlood::floodOpacity() const +{ + return m_floodOpacity; +} + +void FEFlood::setFloodOpacity(float floodOpacity) +{ + m_floodOpacity = floodOpacity; +} + +void FEFlood::apply(Filter*) +{ + GraphicsContext* filterContext = effectContext(); + if (!filterContext) + return; + + Color color = colorWithOverrideAlpha(floodColor().rgb(), floodOpacity()); + filterContext->fillRect(FloatRect(FloatPoint(), repaintRectInLocalCoordinates().size()), color, DeviceColorSpace); +} + +void FEFlood::dump() +{ +} + +TextStream& FEFlood::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feFlood"; + FilterEffect::externalRepresentation(ts); + ts << " flood-color=\"" << floodColor().name() << "\" " + << "flood-opacity=\"" << floodOpacity() << "\"]\n"; + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/WebCore/platform/graphics/filters/FEFlood.h b/WebCore/platform/graphics/filters/FEFlood.h new file mode 100644 index 0000000..b615531 --- /dev/null +++ b/WebCore/platform/graphics/filters/FEFlood.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef FEFlood_h +#define FEFlood_h + +#if ENABLE(FILTERS) +#include "Color.h" +#include "Filter.h" +#include "FilterEffect.h" + +namespace WebCore { + +class FEFlood : public FilterEffect { +public: + static PassRefPtr<FEFlood> create(const Color&, float); + + Color floodColor() const; + void setFloodColor(const Color &); + + float floodOpacity() const; + void setFloodOpacity(float); + + virtual void apply(Filter*); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEFlood(const Color&, float); + + Color m_floodColor; + float m_floodOpacity; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEFlood_h diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp index 72a5a04..fd9a3d8 100644 --- a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp +++ b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp @@ -1,25 +1,25 @@ /* - Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> - 2004, 2005 Rob Buis <buis@kde.org> - 2005 Eric Seidel <eric@webkit.org> - 2009 Dirk Schulze <krit@webkit.org> - 2010 Igalia, S.L. - - 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 - aint 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. -*/ + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2010 Igalia, S.L. + * + * 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. + */ #include "config.h" @@ -132,12 +132,12 @@ void FEGaussianBlur::apply(Filter* filter) if (!in->resultImage()) return; - if (!getEffectContext()) + if (!effectContext()) return; setIsAlphaImage(in->isAlphaImage()); - IntRect effectDrawingRect = calculateDrawingIntRect(in->repaintRectInLocalCoordinates()); + IntRect effectDrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates()); RefPtr<ImageData> srcImageData(in->resultImage()->getPremultipliedImageData(effectDrawingRect)); IntRect imageRect(IntPoint(), resultImage()->size()); diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.h b/WebCore/platform/graphics/filters/FEGaussianBlur.h index 63d763e..745bcc8 100644 --- a/WebCore/platform/graphics/filters/FEGaussianBlur.h +++ b/WebCore/platform/graphics/filters/FEGaussianBlur.h @@ -1,23 +1,23 @@ /* - Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> - 2004, 2005 Rob Buis <buis@kde.org> - 2005 Eric Seidel <eric@webkit.org> - - 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 - aint 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. -*/ + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ #ifndef FEGaussianBlur_h #define FEGaussianBlur_h @@ -38,12 +38,13 @@ public: float stdDeviationY() const; void setStdDeviationY(float); - void apply(Filter*); - void dump(); - TextStream& externalRepresentation(TextStream&, int indent) const; - static float calculateStdDeviation(float); + virtual void apply(Filter*); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + private: FEGaussianBlur(float, float); static void kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight); diff --git a/WebCore/platform/graphics/filters/FELighting.cpp b/WebCore/platform/graphics/filters/FELighting.cpp new file mode 100644 index 0000000..f49b67d --- /dev/null +++ b/WebCore/platform/graphics/filters/FELighting.cpp @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2010 University of Szeged + * Copyright (C) 2010 Zoltan Herczeg + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED OR + * 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" + +#if ENABLE(FILTERS) +#include "FELighting.h" + +#include "CanvasPixelArray.h" +#include "ImageData.h" +#include "LightSource.h" + +namespace WebCore { + +FELighting::FELighting(LightingType lightingType, const Color& lightingColor, float surfaceScale, + float diffuseConstant, float specularConstant, float specularExponent, + float kernelUnitLengthX, float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) + : FilterEffect() + , m_lightingType(lightingType) + , m_lightSource(lightSource) + , m_lightingColor(lightingColor) + , m_surfaceScale(surfaceScale) + , m_diffuseConstant(diffuseConstant) + , m_specularConstant(specularConstant) + , m_specularExponent(specularExponent) + , m_kernelUnitLengthX(kernelUnitLengthX) + , m_kernelUnitLengthY(kernelUnitLengthY) +{ +} + +const static int cPixelSize = 4; +const static int cAlphaChannelOffset = 3; +const static unsigned char cOpaqueAlpha = static_cast<unsigned char>(0xff); + +ALWAYS_INLINE int FELighting::LightingData::upLeftPixelValue() +{ + return static_cast<int>(pixels->get(offset - widthMultipliedByPixelSize - cPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::upPixelValue() +{ + return static_cast<int>(pixels->get(offset - widthMultipliedByPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::upRightPixelValue() +{ + return static_cast<int>(pixels->get(offset - widthMultipliedByPixelSize + cPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::leftPixelValue() +{ + return static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::centerPixelValue() +{ + return static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::rightPixelValue() +{ + return static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::downLeftPixelValue() +{ + return static_cast<int>(pixels->get(offset + widthMultipliedByPixelSize - cPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::downPixelValue() +{ + return static_cast<int>(pixels->get(offset + widthMultipliedByPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::downRightPixelValue() +{ + return static_cast<int>(pixels->get(offset + widthMultipliedByPixelSize + cPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE void FELighting::setPixel(LightingData& data, LightSource::PaintingData& paintingData, + int lightX, int lightY, float factorX, int normalX, float factorY, int normalY) +{ + m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->get(data.offset + 3)) * data.surfaceScale); + + data.normalVector.setX(factorX * static_cast<float>(normalX) * data.surfaceScale); + data.normalVector.setY(factorY * static_cast<float>(normalY) * data.surfaceScale); + data.normalVector.setZ(1.0f); + data.normalVector.normalize(); + + if (m_lightingType == FELighting::DiffuseLighting) + data.lightStrength = m_diffuseConstant * (data.normalVector * paintingData.lightVector); + else { + FloatPoint3D halfwayVector = paintingData.lightVector; + halfwayVector.setZ(halfwayVector.z() + 1.0f); + halfwayVector.normalize(); + if (m_specularExponent == 1.0f) + data.lightStrength = m_specularConstant * (data.normalVector * halfwayVector); + else + data.lightStrength = m_specularConstant * powf(data.normalVector * halfwayVector, m_specularExponent); + } + + if (data.lightStrength > 1.0f) + data.lightStrength = 1.0f; + if (data.lightStrength < 0.0f) + data.lightStrength = 0.0f; + + data.pixels->set(data.offset, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.x())); + data.pixels->set(data.offset + 1, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.y())); + data.pixels->set(data.offset + 2, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.z())); +} + +bool FELighting::drawLighting(CanvasPixelArray* pixels, int width, int height) +{ + LightSource::PaintingData paintingData; + LightingData data; + + if (!m_lightSource) + return false; + + // FIXME: do something if width or height (or both) is 1 pixel. + // The W3 spec does not define this case. Now the filter just returns. + if (width <= 2 || height <= 2) + return false; + + data.pixels = pixels; + data.surfaceScale = m_surfaceScale / 255.0f; + data.widthMultipliedByPixelSize = width * cPixelSize; + data.widthDecreasedByOne = width - 1; + data.heightDecreasedByOne = height - 1; + paintingData.colorVector = FloatPoint3D(m_lightingColor.red(), m_lightingColor.green(), m_lightingColor.blue()); + m_lightSource->initPaintingData(paintingData); + + // Top/Left corner + data.offset = 0; + setPixel(data, paintingData, 0, 0, + -2.0f / 3.0f, -2 * data.centerPixelValue() + 2 * data.rightPixelValue() - data.downPixelValue() + data.downRightPixelValue(), + -2.0f / 3.0f, -2 * data.centerPixelValue() - data.rightPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue()); + + // Top/Right pixel + data.offset = data.widthMultipliedByPixelSize - cPixelSize; + setPixel(data, paintingData, data.widthDecreasedByOne, 0, + -2.0f / 3.0f, -2 * data.leftPixelValue() + 2 * data.centerPixelValue() - data.downLeftPixelValue() + data.downPixelValue(), + -2.0f / 3.0f, -data.leftPixelValue() - 2 * data.centerPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue()); + + // Bottom/Left pixel + data.offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize; + setPixel(data, paintingData, 0, data.heightDecreasedByOne, + -2.0f / 3.0f, -data.upPixelValue() + data.upRightPixelValue() - 2 * data.centerPixelValue() + 2 * data.rightPixelValue(), + -2.0f / 3.0f, -2 * data.upPixelValue() - data.upRightPixelValue() + 2 * data.centerPixelValue() + data.rightPixelValue()); + + // Bottom/Right pixel + data.offset = height * data.widthMultipliedByPixelSize - cPixelSize; + setPixel(data, paintingData, data.widthDecreasedByOne, data.heightDecreasedByOne, + -2.0f / 3.0f, -data.upLeftPixelValue() + data.upPixelValue() - 2 * data.leftPixelValue() + 2 * data.centerPixelValue(), + -2.0f / 3.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() + data.leftPixelValue() + 2 * data.centerPixelValue()); + + if (width >= 3) { + // Top line + data.offset = cPixelSize; + for (int x = 1; x < data.widthDecreasedByOne; ++x, data.offset += cPixelSize) { + setPixel(data, paintingData, x, 0, + -1.0f / 3.0f, -2 * data.leftPixelValue() + 2 * data.rightPixelValue() - data.downLeftPixelValue() + data.downRightPixelValue(), + -1.0f / 2.0f, -data.leftPixelValue() - 2 * data.centerPixelValue() - data.rightPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue()); + } + // Bottom line + data.offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize + cPixelSize; + for (int x = 1; x < data.widthDecreasedByOne; ++x, data.offset += cPixelSize) { + setPixel(data, paintingData, x, data.heightDecreasedByOne, + -1.0f / 3.0f, -data.upLeftPixelValue() + data.upRightPixelValue() - 2 * data.leftPixelValue() + 2 * data.rightPixelValue(), + -1.0f / 2.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() - data.upRightPixelValue() + data.leftPixelValue() + 2 * data.centerPixelValue() + data.rightPixelValue()); + } + } + + if (height >= 3) { + // Left line + data.offset = data.widthMultipliedByPixelSize; + for (int y = 1; y < data.heightDecreasedByOne; ++y, data.offset += data.widthMultipliedByPixelSize) { + setPixel(data, paintingData, 0, y, + -1.0f / 2.0f, -data.upPixelValue() + data.upRightPixelValue() - 2 * data.centerPixelValue() + 2 * data.rightPixelValue() - data.downPixelValue() + data.downRightPixelValue(), + -1.0f / 3.0f, -2 * data.upPixelValue() - data.upRightPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue()); + } + // Right line + data.offset = data.widthMultipliedByPixelSize + data.widthMultipliedByPixelSize - cPixelSize; + for (int y = 1; y < data.heightDecreasedByOne; ++y, data.offset += data.widthMultipliedByPixelSize) { + setPixel(data, paintingData, data.widthDecreasedByOne, y, + -1.0f / 2.0f, -data.upLeftPixelValue() + data.upPixelValue() -2 * data.leftPixelValue() + 2 * data.centerPixelValue() - data.downLeftPixelValue() + data.downPixelValue(), + -1.0f / 3.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue()); + } + } + + if (width >= 3 && height >= 3) { + // Interior pixels + for (int y = 1; y < data.heightDecreasedByOne; ++y) { + data.offset = y * data.widthMultipliedByPixelSize + cPixelSize; + for (int x = 1; x < data.widthDecreasedByOne; ++x, data.offset += cPixelSize) { + setPixel(data, paintingData, x, y, + -1.0f / 4.0f, -data.upLeftPixelValue() + data.upRightPixelValue() - 2 * data.leftPixelValue() + 2 * data.rightPixelValue() - data.downLeftPixelValue() + data.downRightPixelValue(), + -1.0f / 4.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() - data.upRightPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue()); + } + } + } + + int totalSize = data.widthMultipliedByPixelSize * height; + if (m_lightingType == DiffuseLighting) { + for (int i = 3; i < totalSize; i += 4) + data.pixels->set(i, cOpaqueAlpha); + } else { + for (int i = 0; i < totalSize; i += 4) { + unsigned char a1 = data.pixels->get(i); + unsigned char a2 = data.pixels->get(i + 1); + unsigned char a3 = data.pixels->get(i + 2); + // alpha set to set to max(a1, a2, a3) + data.pixels->set(i + 3, a1 >= a2 ? (a1 >= a3 ? a1 : a3) : (a2 >= a3 ? a2 : a3)); + } + } + + return true; +} + +void FELighting::apply(Filter* filter) +{ + FilterEffect* in = inputEffect(0); + in->apply(filter); + if (!in->resultImage()) + return; + + if (!effectContext()) + return; + + setIsAlphaImage(false); + + IntRect effectDrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates()); + RefPtr<ImageData> srcImageData(in->resultImage()->getUnmultipliedImageData(effectDrawingRect)); + CanvasPixelArray* srcPixelArray(srcImageData->data()); + + // FIXME: support kernelUnitLengths other than (1,1). The issue here is that the W3 + // standard has no test case for them, and other browsers (like Firefox) has strange + // output for various kernelUnitLengths, and I am not sure they are reliable. + // Anyway, feConvolveMatrix should also use the implementation + + if (drawLighting(srcPixelArray, effectDrawingRect.width(), effectDrawingRect.height())) + resultImage()->putUnmultipliedImageData(srcImageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint()); +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/WebCore/platform/graphics/filters/FELighting.h b/WebCore/platform/graphics/filters/FELighting.h new file mode 100644 index 0000000..28c00c4 --- /dev/null +++ b/WebCore/platform/graphics/filters/FELighting.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2010 University of Szeged + * Copyright (C) 2010 Zoltan Herczeg + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED OR + * 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. + */ + +#ifndef FELighting_h +#define FELighting_h + +#if ENABLE(FILTERS) +#include "Color.h" +#include "Filter.h" +#include "FilterEffect.h" +#include "LightSource.h" +#include <wtf/AlwaysInline.h> + +// Common base class for FEDiffuseLighting and FESpecularLighting + +namespace WebCore { + +class CanvasPixelArray; + +class FELighting : public FilterEffect { +public: + virtual void apply(Filter*); + +protected: + enum LightingType { + DiffuseLighting, + SpecularLighting + }; + + struct LightingData { + FloatPoint3D normalVector; + CanvasPixelArray* pixels; + float lightStrength; + float surfaceScale; + int offset; + int widthMultipliedByPixelSize; + int widthDecreasedByOne; + int heightDecreasedByOne; + + ALWAYS_INLINE int upLeftPixelValue(); + ALWAYS_INLINE int upPixelValue(); + ALWAYS_INLINE int upRightPixelValue(); + ALWAYS_INLINE int leftPixelValue(); + ALWAYS_INLINE int centerPixelValue(); + ALWAYS_INLINE int rightPixelValue(); + ALWAYS_INLINE int downLeftPixelValue(); + ALWAYS_INLINE int downPixelValue(); + ALWAYS_INLINE int downRightPixelValue(); + }; + + FELighting(LightingType, const Color&, float, float, float, float, float, float, PassRefPtr<LightSource>); + + bool drawLighting(CanvasPixelArray*, int, int); + ALWAYS_INLINE void setPixel(LightingData&, LightSource::PaintingData&, + int lightX, int lightY, float factorX, int normalX, float factorY, int normalY); + + LightingType m_lightingType; + RefPtr<LightSource> m_lightSource; + + Color m_lightingColor; + float m_surfaceScale; + float m_diffuseConstant; + float m_specularConstant; + float m_specularExponent; + float m_kernelUnitLengthX; + float m_kernelUnitLengthY; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FELighting_h diff --git a/WebCore/platform/graphics/filters/FEMerge.cpp b/WebCore/platform/graphics/filters/FEMerge.cpp new file mode 100644 index 0000000..19c832a --- /dev/null +++ b/WebCore/platform/graphics/filters/FEMerge.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEMerge.h" + +#include "Filter.h" +#include "GraphicsContext.h" + +namespace WebCore { + +FEMerge::FEMerge() + : FilterEffect() +{ +} + +PassRefPtr<FEMerge> FEMerge::create() +{ + return adoptRef(new FEMerge); +} + +void FEMerge::apply(Filter* filter) +{ + unsigned size = numberOfEffectInputs(); + ASSERT(size > 0); + for (unsigned i = 0; i < size; ++i) { + FilterEffect* in = inputEffect(i); + in->apply(filter); + if (!in->resultImage()) + return; + } + + GraphicsContext* filterContext = effectContext(); + if (!filterContext) + return; + + for (unsigned i = 0; i < size; ++i) { + FilterEffect* in = inputEffect(i); + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates())); + } +} + +void FEMerge::dump() +{ +} + +TextStream& FEMerge::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feMerge"; + FilterEffect::externalRepresentation(ts); + unsigned size = numberOfEffectInputs(); + ASSERT(size > 0); + ts << " mergeNodes=\"" << size << "\"]\n"; + for (unsigned i = 0; i < size; ++i) + inputEffect(i)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/WebCore/platform/graphics/filters/FEMerge.h b/WebCore/platform/graphics/filters/FEMerge.h new file mode 100644 index 0000000..46b882f --- /dev/null +++ b/WebCore/platform/graphics/filters/FEMerge.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef FEMerge_h +#define EMerge_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" +#include "Filter.h" +#include <wtf/Vector.h> + +namespace WebCore { + +class FEMerge : public FilterEffect { +public: + static PassRefPtr<FEMerge> create(); + + virtual void apply(Filter*); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEMerge(); +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEMerge_h diff --git a/WebCore/platform/graphics/filters/FEMorphology.cpp b/WebCore/platform/graphics/filters/FEMorphology.cpp new file mode 100644 index 0000000..7329e1e --- /dev/null +++ b/WebCore/platform/graphics/filters/FEMorphology.cpp @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * 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. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEMorphology.h" + +#include "CanvasPixelArray.h" +#include "Filter.h" +#include "ImageData.h" + +#include <wtf/Vector.h> + +using std::min; +using std::max; + +namespace WebCore { + +FEMorphology::FEMorphology(MorphologyOperatorType type, float radiusX, float radiusY) + : FilterEffect() + , m_type(type) + , m_radiusX(radiusX) + , m_radiusY(radiusY) +{ +} + +PassRefPtr<FEMorphology> FEMorphology::create(MorphologyOperatorType type, float radiusX, float radiusY) +{ + return adoptRef(new FEMorphology(type, radiusX, radiusY)); +} + +MorphologyOperatorType FEMorphology::morphologyOperator() const +{ + return m_type; +} + +void FEMorphology::setMorphologyOperator(MorphologyOperatorType type) +{ + m_type = type; +} + +float FEMorphology::radiusX() const +{ + return m_radiusX; +} + +void FEMorphology::setRadiusX(float radiusX) +{ + m_radiusX = radiusX; +} + +float FEMorphology::radiusY() const +{ + return m_radiusY; +} + +void FEMorphology::setRadiusY(float radiusY) +{ + m_radiusY = radiusY; +} + +void FEMorphology::apply(Filter* filter) +{ + FilterEffect* in = inputEffect(0); + in->apply(filter); + if (!in->resultImage()) + return; + + if (!effectContext()) + return; + + setIsAlphaImage(in->isAlphaImage()); + + int radiusX = static_cast<int>(m_radiusX * filter->filterResolution().width()); + int radiusY = static_cast<int>(m_radiusY * filter->filterResolution().height()); + if (radiusX <= 0 || radiusY <= 0) + return; + + IntRect imageRect(IntPoint(), resultImage()->size()); + IntRect effectDrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates()); + RefPtr<CanvasPixelArray> srcPixelArray(in->resultImage()->getPremultipliedImageData(effectDrawingRect)->data()); + RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height()); + + int effectWidth = effectDrawingRect.width() * 4; + + // Limit the radius size to effect dimensions + radiusX = min(effectDrawingRect.width() - 1, radiusX); + radiusY = min(effectDrawingRect.height() - 1, radiusY); + + Vector<unsigned char> extrema; + for (int y = 0; y < effectDrawingRect.height(); ++y) { + int startY = max(0, y - radiusY); + int endY = min(effectDrawingRect.height() - 1, y + radiusY); + for (unsigned channel = 0; channel < 4; ++channel) { + // Fill the kernel + extrema.clear(); + for (int j = 0; j <= radiusX; ++j) { + unsigned char columnExtrema = srcPixelArray->get(startY * effectWidth + 4 * j + channel); + for (int i = startY; i <= endY; ++i) { + unsigned char pixel = srcPixelArray->get(i * effectWidth + 4 * j + channel); + if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema) || + (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema)) + columnExtrema = pixel; + } + extrema.append(columnExtrema); + } + + // Kernel is filled, get extrema of next column + for (int x = 0; x < effectDrawingRect.width(); ++x) { + unsigned endX = min(x + radiusX, effectDrawingRect.width() - 1); + unsigned char columnExtrema = srcPixelArray->get(startY * effectWidth + endX * 4 + channel); + for (int i = startY; i <= endY; ++i) { + unsigned char pixel = srcPixelArray->get(i * effectWidth + endX * 4 + channel); + if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema) || + (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema)) + columnExtrema = pixel; + } + if (x - radiusX >= 0) + extrema.remove(0); + if (x + radiusX <= effectDrawingRect.width()) + extrema.append(columnExtrema); + unsigned char entireExtrema = extrema[0]; + for (unsigned kernelIndex = 0; kernelIndex < extrema.size(); ++kernelIndex) { + if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && extrema[kernelIndex] <= entireExtrema) || + (m_type == FEMORPHOLOGY_OPERATOR_DILATE && extrema[kernelIndex] >= entireExtrema)) + entireExtrema = extrema[kernelIndex]; + } + imageData->data()->set(y * effectWidth + 4 * x + channel, entireExtrema); + } + } + } + resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint()); +} + +void FEMorphology::dump() +{ +} + +static TextStream& operator<<(TextStream& ts, const MorphologyOperatorType& type) +{ + switch (type) { + case FEMORPHOLOGY_OPERATOR_UNKNOWN: + ts << "UNKNOWN"; + break; + case FEMORPHOLOGY_OPERATOR_ERODE: + ts << "ERODE"; + break; + case FEMORPHOLOGY_OPERATOR_DILATE: + ts << "DILATE"; + break; + } + return ts; +} + +TextStream& FEMorphology::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feMorphology"; + FilterEffect::externalRepresentation(ts); + ts << " operator=\"" << morphologyOperator() << "\" " + << "radius=\"" << radiusX() << ", " << radiusY() << "\"]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/WebCore/platform/graphics/filters/FEMorphology.h b/WebCore/platform/graphics/filters/FEMorphology.h new file mode 100644 index 0000000..c8ce058 --- /dev/null +++ b/WebCore/platform/graphics/filters/FEMorphology.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef FEMorphology_h +#define FEMorphology_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" +#include "Filter.h" + +namespace WebCore { + +enum MorphologyOperatorType { + FEMORPHOLOGY_OPERATOR_UNKNOWN = 0, + FEMORPHOLOGY_OPERATOR_ERODE = 1, + FEMORPHOLOGY_OPERATOR_DILATE = 2 +}; + +class FEMorphology : public FilterEffect { +public: + static PassRefPtr<FEMorphology> create(MorphologyOperatorType, float radiusX, float radiusY); + MorphologyOperatorType morphologyOperator() const; + void setMorphologyOperator(MorphologyOperatorType); + + float radiusX() const; + void setRadiusX(float); + + float radiusY() const; + void setRadiusY(float); + + virtual void apply(Filter*); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEMorphology(MorphologyOperatorType, float radiusX, float radiusY); + + MorphologyOperatorType m_type; + float m_radiusX; + float m_radiusY; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEMorphology_h diff --git a/WebCore/platform/graphics/filters/FEOffset.cpp b/WebCore/platform/graphics/filters/FEOffset.cpp new file mode 100644 index 0000000..ea84cf0 --- /dev/null +++ b/WebCore/platform/graphics/filters/FEOffset.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * 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. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEOffset.h" + +#include "Filter.h" +#include "GraphicsContext.h" + +namespace WebCore { + +FEOffset::FEOffset(float dx, float dy) + : FilterEffect() + , m_dx(dx) + , m_dy(dy) +{ +} + +PassRefPtr<FEOffset> FEOffset::create(float dx, float dy) +{ + return adoptRef(new FEOffset(dx, dy)); +} + +float FEOffset::dx() const +{ + return m_dx; +} + +void FEOffset::setDx(float dx) +{ + m_dx = dx; +} + +float FEOffset::dy() const +{ + return m_dy; +} + +void FEOffset::setDy(float dy) +{ + m_dy = dy; +} + +void FEOffset::apply(Filter* filter) +{ + FilterEffect* in = inputEffect(0); + in->apply(filter); + if (!in->resultImage()) + return; + + GraphicsContext* filterContext = effectContext(); + if (!filterContext) + return; + + setIsAlphaImage(in->isAlphaImage()); + + FloatRect sourceImageRect = filter->sourceImageRect(); + sourceImageRect.scale(filter->filterResolution().width(), filter->filterResolution().height()); + + if (filter->effectBoundingBoxMode()) { + m_dx *= sourceImageRect.width(); + m_dy *= sourceImageRect.height(); + } + m_dx *= filter->filterResolution().width(); + m_dy *= filter->filterResolution().height(); + + FloatRect dstRect = FloatRect(m_dx + in->repaintRectInLocalCoordinates().x() - repaintRectInLocalCoordinates().x(), + m_dy + in->repaintRectInLocalCoordinates().y() - repaintRectInLocalCoordinates().y(), + in->repaintRectInLocalCoordinates().width(), + in->repaintRectInLocalCoordinates().height()); + + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, dstRect); +} + +void FEOffset::dump() +{ +} + +TextStream& FEOffset::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feOffset"; + FilterEffect::externalRepresentation(ts); + ts << " dx=\"" << dx() << "\" dy=\"" << dy() << "\"]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/WebCore/platform/graphics/filters/FEOffset.h b/WebCore/platform/graphics/filters/FEOffset.h new file mode 100644 index 0000000..052ba74 --- /dev/null +++ b/WebCore/platform/graphics/filters/FEOffset.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef FEOffset_h +#define FEOffset_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" +#include "Filter.h" + +namespace WebCore { + +class FEOffset : public FilterEffect { +public: + static PassRefPtr<FEOffset> create(float dx, float dy); + + float dx() const; + void setDx(float); + + float dy() const; + void setDy(float); + + virtual void apply(Filter*); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEOffset(float dx, float dy); + + float m_dx; + float m_dy; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEOffset_h diff --git a/WebCore/platform/graphics/filters/FESpecularLighting.cpp b/WebCore/platform/graphics/filters/FESpecularLighting.cpp new file mode 100644 index 0000000..2606600 --- /dev/null +++ b/WebCore/platform/graphics/filters/FESpecularLighting.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FESpecularLighting.h" + +#include "LightSource.h" + +namespace WebCore { + +FESpecularLighting::FESpecularLighting(const Color& lightingColor, float surfaceScale, + float specularConstant, float specularExponent, float kernelUnitLengthX, + float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) + : FELighting(SpecularLighting, lightingColor, surfaceScale, 0, specularConstant, specularExponent, kernelUnitLengthX, kernelUnitLengthY, lightSource) +{ +} + +PassRefPtr<FESpecularLighting> FESpecularLighting::create(const Color& lightingColor, + float surfaceScale, float specularConstant, float specularExponent, + float kernelUnitLengthX, float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) +{ + return adoptRef(new FESpecularLighting(lightingColor, surfaceScale, specularConstant, specularExponent, + kernelUnitLengthX, kernelUnitLengthY, lightSource)); +} + +FESpecularLighting::~FESpecularLighting() +{ +} + +Color FESpecularLighting::lightingColor() const +{ + return m_lightingColor; +} + +void FESpecularLighting::setLightingColor(const Color& lightingColor) +{ + m_lightingColor = lightingColor; +} + +float FESpecularLighting::surfaceScale() const +{ + return m_surfaceScale; +} + +void FESpecularLighting::setSurfaceScale(float surfaceScale) +{ + m_surfaceScale = surfaceScale; +} + +float FESpecularLighting::specularConstant() const +{ + return m_specularConstant; +} + +void FESpecularLighting::setSpecularConstant(float specularConstant) +{ + m_specularConstant = specularConstant; +} + +float FESpecularLighting::specularExponent() const +{ + return m_specularExponent; +} + +void FESpecularLighting::setSpecularExponent(float specularExponent) +{ + m_specularExponent = specularExponent; +} + +float FESpecularLighting::kernelUnitLengthX() const +{ + return m_kernelUnitLengthX; +} + +void FESpecularLighting::setKernelUnitLengthX(float kernelUnitLengthX) +{ + m_kernelUnitLengthX = kernelUnitLengthX; +} + +float FESpecularLighting::kernelUnitLengthY() const +{ + return m_kernelUnitLengthY; +} + +void FESpecularLighting::setKernelUnitLengthY(float kernelUnitLengthY) +{ + m_kernelUnitLengthY = kernelUnitLengthY; +} + +const LightSource* FESpecularLighting::lightSource() const +{ + return m_lightSource.get(); +} + +void FESpecularLighting::setLightSource(PassRefPtr<LightSource> lightSource) +{ + m_lightSource = lightSource; +} + +void FESpecularLighting::dump() +{ +} + +TextStream& FESpecularLighting::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feSpecularLighting"; + FilterEffect::externalRepresentation(ts); + ts << " surfaceScale=\"" << m_surfaceScale << "\" " + << "specualConstant=\"" << m_specularConstant << "\" " + << "specularExponent=\"" << m_specularExponent << "\"]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/WebCore/platform/graphics/filters/FESpecularLighting.h b/WebCore/platform/graphics/filters/FESpecularLighting.h new file mode 100644 index 0000000..f6e7b66 --- /dev/null +++ b/WebCore/platform/graphics/filters/FESpecularLighting.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef FESpecularLighting_h +#define FESpecularLighting_h + +#if ENABLE(FILTERS) +#include "FELighting.h" + +namespace WebCore { + +class FESpecularLighting : public FELighting { +public: + static PassRefPtr<FESpecularLighting> create(const Color&, float, float, + float, float, float, PassRefPtr<LightSource>); + virtual ~FESpecularLighting(); + + Color lightingColor() const; + void setLightingColor(const Color&); + + float surfaceScale() const; + void setSurfaceScale(float); + + float specularConstant() const; + void setSpecularConstant(float); + + float specularExponent() const; + void setSpecularExponent(float); + + float kernelUnitLengthX() const; + void setKernelUnitLengthX(float); + + float kernelUnitLengthY() const; + void setKernelUnitLengthY(float); + + const LightSource* lightSource() const; + void setLightSource(PassRefPtr<LightSource>); + + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FESpecularLighting(const Color&, float, float, float, float, float, PassRefPtr<LightSource>); +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FESpecularLighting_h diff --git a/WebCore/platform/graphics/filters/FETile.cpp b/WebCore/platform/graphics/filters/FETile.cpp new file mode 100644 index 0000000..41abd34 --- /dev/null +++ b/WebCore/platform/graphics/filters/FETile.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * 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. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FETile.h" + +#include "AffineTransform.h" +#include "Filter.h" +#include "GraphicsContext.h" +#include "Pattern.h" + +namespace WebCore { + +FETile::FETile() + : FilterEffect() +{ +} + +PassRefPtr<FETile> FETile::create() +{ + return adoptRef(new FETile); +} + +FloatRect FETile::determineFilterPrimitiveSubregion(Filter* filter) +{ + inputEffect(0)->determineFilterPrimitiveSubregion(filter); + + filter->determineFilterPrimitiveSubregion(this, filter->filterRegion()); + return filterPrimitiveSubregion(); +} + +void FETile::apply(Filter* filter) +{ + FilterEffect* in = inputEffect(0); + in->apply(filter); + if (!in->resultImage()) + return; + + GraphicsContext* filterContext = effectContext(); + if (!filterContext) + return; + + setIsAlphaImage(in->isAlphaImage()); + + IntRect tileRect = enclosingIntRect(in->repaintRectInLocalCoordinates()); + + // Source input needs more attention. It has the size of the filterRegion but gives the + // size of the cutted sourceImage back. This is part of the specification and optimization. + if (in->isSourceInput()) { + FloatRect filterRegion = filter->filterRegion(); + filterRegion.scale(filter->filterResolution().width(), filter->filterResolution().height()); + tileRect = enclosingIntRect(filterRegion); + } + + OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(tileRect.size()); + GraphicsContext* tileImageContext = tileImage->context(); + tileImageContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, IntPoint()); + RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(), true, true); + + AffineTransform matrix; + matrix.translate(in->repaintRectInLocalCoordinates().x() - repaintRectInLocalCoordinates().x(), + in->repaintRectInLocalCoordinates().y() - repaintRectInLocalCoordinates().y()); + pattern.get()->setPatternSpaceTransform(matrix); + + filterContext->setFillPattern(pattern); + filterContext->fillRect(FloatRect(FloatPoint(), repaintRectInLocalCoordinates().size())); +} + +void FETile::dump() +{ +} + +TextStream& FETile::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feTile"; + FilterEffect::externalRepresentation(ts); + ts << "]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + diff --git a/WebCore/platform/graphics/filters/FETile.h b/WebCore/platform/graphics/filters/FETile.h new file mode 100644 index 0000000..20efbcd --- /dev/null +++ b/WebCore/platform/graphics/filters/FETile.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef FETile_h +#define FETile_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" +#include "Filter.h" + +namespace WebCore { + +class FETile : public FilterEffect { +public: + static PassRefPtr<FETile> create(); + + virtual void apply(Filter*); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + + virtual FloatRect determineFilterPrimitiveSubregion(Filter*); + +private: + FETile(); +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FETile_h diff --git a/WebCore/platform/graphics/filters/FETurbulence.cpp b/WebCore/platform/graphics/filters/FETurbulence.cpp new file mode 100644 index 0000000..bb24362 --- /dev/null +++ b/WebCore/platform/graphics/filters/FETurbulence.cpp @@ -0,0 +1,386 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2010 Renata Hodovan <reni@inf.u-szeged.hu> + * + * 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. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FETurbulence.h" + +#include "CanvasPixelArray.h" +#include "Filter.h" +#include "ImageData.h" + +#include <wtf/MathExtras.h> + +namespace WebCore { + +/* + Produces results in the range [1, 2**31 - 2]. Algorithm is: + r = (a * r) mod m where a = randAmplitude = 16807 and + m = randMaximum = 2**31 - 1 = 2147483647, r = seed. + See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988 + To test: the algorithm should produce the result 1043618065 + as the 10,000th generated number if the original seed is 1. +*/ +static const int s_perlinNoise = 4096; +static const long s_randMaximum = 2147483647; // 2**31 - 1 +static const int s_randAmplitude = 16807; // 7**5; primitive root of m +static const int s_randQ = 127773; // m / a +static const int s_randR = 2836; // m % a + +FETurbulence::FETurbulence(TurbulanceType type, float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, bool stitchTiles) + : FilterEffect() + , m_type(type) + , m_baseFrequencyX(baseFrequencyX) + , m_baseFrequencyY(baseFrequencyY) + , m_numOctaves(numOctaves) + , m_seed(seed) + , m_stitchTiles(stitchTiles) +{ +} + +PassRefPtr<FETurbulence> FETurbulence::create(TurbulanceType type, float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, bool stitchTiles) +{ + return adoptRef(new FETurbulence(type, baseFrequencyX, baseFrequencyY, numOctaves, seed, stitchTiles)); +} + +TurbulanceType FETurbulence::type() const +{ + return m_type; +} + +void FETurbulence::setType(TurbulanceType type) +{ + m_type = type; +} + +float FETurbulence::baseFrequencyY() const +{ + return m_baseFrequencyY; +} + +void FETurbulence::setBaseFrequencyY(float baseFrequencyY) +{ + m_baseFrequencyY = baseFrequencyY; +} + +float FETurbulence::baseFrequencyX() const +{ + return m_baseFrequencyX; +} + +void FETurbulence::setBaseFrequencyX(float baseFrequencyX) +{ + m_baseFrequencyX = baseFrequencyX; +} + +float FETurbulence::seed() const +{ + return m_seed; +} + +void FETurbulence::setSeed(float seed) +{ + m_seed = seed; +} + +int FETurbulence::numOctaves() const +{ + return m_numOctaves; +} + +void FETurbulence::setNumOctaves(bool numOctaves) +{ + m_numOctaves = numOctaves; +} + +bool FETurbulence::stitchTiles() const +{ + return m_stitchTiles; +} + +void FETurbulence::setStitchTiles(bool stitch) +{ + m_stitchTiles = stitch; +} + +// The turbulence calculation code is an adapted version of what appears in the SVG 1.1 specification: +// http://www.w3.org/TR/SVG11/filters.html#feTurbulence + +FETurbulence::PaintingData::PaintingData(long paintingSeed, const IntSize& paintingSize) + : seed(paintingSeed) + , width(0) + , height(0) + , wrapX(0) + , wrapY(0) + , channel(0) + , filterSize(paintingSize) +{ +} + +// Compute pseudo random number. +inline long FETurbulence::PaintingData::random() +{ + long result = s_randAmplitude * (seed % s_randQ) - s_randR * (seed / s_randQ); + if (result <= 0) + result += s_randMaximum; + seed = result; + return result; +} + +inline float smoothCurve(float t) +{ + return t * t * (3 - 2 * t); +} + +inline float linearInterpolation(float t, float a, float b) +{ + return a + t * (b - a); +} + +inline void FETurbulence::initPaint(PaintingData& paintingData) +{ + float normalizationFactor; + + // The seed value clamp to the range [1, s_randMaximum - 1]. + if (paintingData.seed <= 0) + paintingData.seed = -(paintingData.seed % (s_randMaximum - 1)) + 1; + if (paintingData.seed > s_randMaximum - 1) + paintingData.seed = s_randMaximum - 1; + + float* gradient; + for (int channel = 0; channel < 4; ++channel) { + for (int i = 0; i < s_blockSize; ++i) { + paintingData.latticeSelector[i] = i; + gradient = paintingData.gradient[channel][i]; + gradient[0] = static_cast<float>((paintingData.random() % (2 * s_blockSize)) - s_blockSize) / s_blockSize; + gradient[1] = static_cast<float>((paintingData.random() % (2 * s_blockSize)) - s_blockSize) / s_blockSize; + normalizationFactor = sqrtf(gradient[0] * gradient[0] + gradient[1] * gradient[1]); + gradient[0] /= normalizationFactor; + gradient[1] /= normalizationFactor; + } + } + for (int i = s_blockSize - 1; i > 0; --i) { + int k = paintingData.latticeSelector[i]; + int j = paintingData.random() % s_blockSize; + ASSERT(j >= 0); + ASSERT(j < 2 * s_blockSize + 2); + paintingData.latticeSelector[i] = paintingData.latticeSelector[j]; + paintingData.latticeSelector[j] = k; + } + for (int i = 0; i < s_blockSize + 2; ++i) { + paintingData.latticeSelector[s_blockSize + i] = paintingData.latticeSelector[i]; + for (int channel = 0; channel < 4; ++channel) { + paintingData.gradient[channel][s_blockSize + i][0] = paintingData.gradient[channel][i][0]; + paintingData.gradient[channel][s_blockSize + i][1] = paintingData.gradient[channel][i][1]; + } + } +} + +inline void checkNoise(int& noiseValue, int limitValue, int newValue) +{ + if (noiseValue >= limitValue) + noiseValue -= newValue; + if (noiseValue >= limitValue - 1) + noiseValue -= newValue - 1; +} + +float FETurbulence::noise2D(PaintingData& paintingData, const FloatPoint& noiseVector) +{ + struct Noise { + int noisePositionIntegerValue; + float noisePositionFractionValue; + + Noise(float component) + { + float position = component + s_perlinNoise; + noisePositionIntegerValue = static_cast<int>(position); + noisePositionFractionValue = position - noisePositionIntegerValue; + } + }; + + Noise noiseX(noiseVector.x()); + Noise noiseY(noiseVector.y()); + float* q; + float sx, sy, a, b, u, v; + + // If stitching, adjust lattice points accordingly. + if (m_stitchTiles) { + checkNoise(noiseX.noisePositionIntegerValue, paintingData.wrapX, paintingData.width); + checkNoise(noiseY.noisePositionIntegerValue, paintingData.wrapY, paintingData.height); + } + + noiseX.noisePositionIntegerValue &= s_blockMask; + noiseY.noisePositionIntegerValue &= s_blockMask; + int latticeIndex = paintingData.latticeSelector[noiseX.noisePositionIntegerValue]; + int nextLatticeIndex = paintingData.latticeSelector[(noiseX.noisePositionIntegerValue + 1) & s_blockMask]; + + sx = smoothCurve(noiseX.noisePositionFractionValue); + sy = smoothCurve(noiseY.noisePositionFractionValue); + + // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement. + int temp = paintingData.latticeSelector[latticeIndex + noiseY.noisePositionIntegerValue]; + q = paintingData.gradient[paintingData.channel][temp]; + u = noiseX.noisePositionFractionValue * q[0] + noiseY.noisePositionFractionValue * q[1]; + temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue]; + q = paintingData.gradient[paintingData.channel][temp]; + v = (noiseX.noisePositionFractionValue - 1) * q[0] + noiseY.noisePositionFractionValue * q[1]; + a = linearInterpolation(sx, u, v); + temp = paintingData.latticeSelector[latticeIndex + noiseY.noisePositionIntegerValue + 1]; + q = paintingData.gradient[paintingData.channel][temp]; + u = noiseX.noisePositionFractionValue * q[0] + (noiseY.noisePositionFractionValue - 1) * q[1]; + temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue + 1]; + q = paintingData.gradient[paintingData.channel][temp]; + v = (noiseX.noisePositionFractionValue - 1) * q[0] + (noiseY.noisePositionFractionValue - 1) * q[1]; + b = linearInterpolation(sx, u, v); + return linearInterpolation(sy, a, b); +} + +unsigned char FETurbulence::calculateTurbulenceValueForPoint(PaintingData& paintingData, const FloatPoint& point) +{ + float tileWidth = paintingData.filterSize.width(); + ASSERT(tileWidth > 0); + float tileHeight = paintingData.filterSize.height(); + ASSERT(tileHeight > 0); + // Adjust the base frequencies if necessary for stitching. + if (m_stitchTiles) { + // When stitching tiled turbulence, the frequencies must be adjusted + // so that the tile borders will be continuous. + if (m_baseFrequencyX) { + float lowFrequency = floorf(tileWidth * m_baseFrequencyX) / tileWidth; + float highFrequency = ceilf(tileWidth * m_baseFrequencyX) / tileWidth; + // BaseFrequency should be non-negative according to the standard. + if (m_baseFrequencyX / lowFrequency < highFrequency / m_baseFrequencyX) + m_baseFrequencyX = lowFrequency; + else + m_baseFrequencyX = highFrequency; + } + if (m_baseFrequencyY) { + float lowFrequency = floorf(tileHeight * m_baseFrequencyY) / tileHeight; + float highFrequency = ceilf(tileHeight * m_baseFrequencyY) / tileHeight; + if (m_baseFrequencyY / lowFrequency < highFrequency / m_baseFrequencyY) + m_baseFrequencyY = lowFrequency; + else + m_baseFrequencyY = highFrequency; + } + // Set up TurbulenceInitial stitch values. + paintingData.width = roundf(tileWidth * m_baseFrequencyX); + paintingData.wrapX = s_perlinNoise + paintingData.width; + paintingData.height = roundf(tileHeight * m_baseFrequencyY); + paintingData.wrapY = s_perlinNoise + paintingData.height; + } + float turbulenceFunctionResult = 0; + FloatPoint noiseVector(point.x() * m_baseFrequencyX, point.y() * m_baseFrequencyY); + float ratio = 1; + for (int octave = 0; octave < m_numOctaves; ++octave) { + if (m_type == FETURBULENCE_TYPE_FRACTALNOISE) + turbulenceFunctionResult += noise2D(paintingData, noiseVector) / ratio; + else + turbulenceFunctionResult += fabsf(noise2D(paintingData, noiseVector)) / ratio; + noiseVector.setX(noiseVector.x() * 2); + noiseVector.setY(noiseVector.y() * 2); + ratio *= 2; + if (m_stitchTiles) { + // Update stitch values. Subtracting s_perlinNoiseoise before the multiplication and + // adding it afterward simplifies to subtracting it once. + paintingData.width *= 2; + paintingData.wrapX = 2 * paintingData.wrapX - s_perlinNoise; + paintingData.height *= 2; + paintingData.wrapY = 2 * paintingData.wrapY - s_perlinNoise; + } + } + + // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult * 255) + 255) / 2 by fractalNoise + // and (turbulenceFunctionResult * 255) by turbulence. + if (m_type == FETURBULENCE_TYPE_FRACTALNOISE) + turbulenceFunctionResult = turbulenceFunctionResult * 0.5f + 0.5f; + // Clamp result + turbulenceFunctionResult = std::max(std::min(turbulenceFunctionResult, 1.f), 0.f); + return static_cast<unsigned char>(turbulenceFunctionResult * 255); +} + +void FETurbulence::apply(Filter* filter) +{ + if (!effectContext()) + return; + + IntRect imageRect(IntPoint(), resultImage()->size()); + if (!imageRect.size().width() || !imageRect.size().height()) + return; + + RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height()); + PaintingData paintingData(m_seed, imageRect.size()); + initPaint(paintingData); + + FloatRect filterRegion = filter->filterRegion(); + FloatPoint point; + point.setY(filterRegion.y()); + int indexOfPixelChannel = 0; + for (int y = 0; y < imageRect.height(); ++y) { + point.setY(point.y() + 1); + point.setX(filterRegion.x()); + for (int x = 0; x < imageRect.width(); ++x) { + point.setX(point.x() + 1); + for (paintingData.channel = 0; paintingData.channel < 4; ++paintingData.channel, ++indexOfPixelChannel) + imageData->data()->set(indexOfPixelChannel, calculateTurbulenceValueForPoint(paintingData, point)); + } + } + resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint()); +} + +void FETurbulence::dump() +{ +} + +static TextStream& operator<<(TextStream& ts, const TurbulanceType& type) +{ + switch (type) { + case FETURBULENCE_TYPE_UNKNOWN: + ts << "UNKNOWN"; + break; + case FETURBULENCE_TYPE_TURBULENCE: + ts << "TURBULANCE"; + break; + case FETURBULENCE_TYPE_FRACTALNOISE: + ts << "NOISE"; + break; + } + return ts; +} + +TextStream& FETurbulence::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feTurbulence"; + FilterEffect::externalRepresentation(ts); + ts << " type=\"" << type() << "\" " + << "baseFrequency=\"" << baseFrequencyX() << ", " << baseFrequencyY() << "\" " + << "seed=\"" << seed() << "\" " + << "numOctaves=\"" << numOctaves() << "\" " + << "stitchTiles=\"" << stitchTiles() << "\"]\n"; + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/WebCore/platform/graphics/filters/FETurbulence.h b/WebCore/platform/graphics/filters/FETurbulence.h new file mode 100644 index 0000000..1a5a28a --- /dev/null +++ b/WebCore/platform/graphics/filters/FETurbulence.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2010 Renata Hodovan <reni@inf.u-szeged.hu> + * + * 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. + */ + +#ifndef FETurbulence_h +#define FETurbulence_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" +#include "Filter.h" + +namespace WebCore { + +enum TurbulanceType { + FETURBULENCE_TYPE_UNKNOWN = 0, + FETURBULENCE_TYPE_FRACTALNOISE = 1, + FETURBULENCE_TYPE_TURBULENCE = 2 +}; + +class FETurbulence : public FilterEffect { +public: + static PassRefPtr<FETurbulence> create(TurbulanceType, float, float, int, float, bool); + + TurbulanceType type() const; + void setType(TurbulanceType); + + float baseFrequencyY() const; + void setBaseFrequencyY(float); + + float baseFrequencyX() const; + void setBaseFrequencyX(float); + + float seed() const; + void setSeed(float); + + int numOctaves() const; + void setNumOctaves(bool); + + bool stitchTiles() const; + void setStitchTiles(bool); + + virtual void apply(Filter*); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + static const int s_blockSize = 256; + static const int s_blockMask = s_blockSize - 1; + + struct PaintingData { + long seed; + int latticeSelector[2 * s_blockSize + 2]; + float gradient[4][2 * s_blockSize + 2][2]; + int width; // How much to subtract to wrap for stitching. + int height; + int wrapX; // Minimum value to wrap. + int wrapY; + int channel; + IntSize filterSize; + + PaintingData(long paintingSeed, const IntSize& paintingSize); + inline long random(); + }; + + FETurbulence(TurbulanceType, float, float, int, float, bool); + + inline void initPaint(PaintingData&); + float noise2D(PaintingData&, const FloatPoint&); + unsigned char calculateTurbulenceValueForPoint(PaintingData&, const FloatPoint&); + + TurbulanceType m_type; + float m_baseFrequencyX; + float m_baseFrequencyY; + int m_numOctaves; + float m_seed; + bool m_stitchTiles; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FETurbulence_h diff --git a/WebCore/platform/graphics/filters/Filter.h b/WebCore/platform/graphics/filters/Filter.h index 7ad25aa..bce4be3 100644 --- a/WebCore/platform/graphics/filters/Filter.h +++ b/WebCore/platform/graphics/filters/Filter.h @@ -1,20 +1,20 @@ /* - * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> * - * 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 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. + * 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 - * aint 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. + * 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. */ #ifndef Filter_h diff --git a/WebCore/platform/graphics/filters/FilterEffect.cpp b/WebCore/platform/graphics/filters/FilterEffect.cpp index b6278b2..461b22a 100644 --- a/WebCore/platform/graphics/filters/FilterEffect.cpp +++ b/WebCore/platform/graphics/filters/FilterEffect.cpp @@ -56,7 +56,7 @@ FloatRect FilterEffect::determineFilterPrimitiveSubregion(Filter* filter) return m_filterPrimitiveSubregion; } -IntRect FilterEffect::calculateDrawingIntRect(const FloatRect& effectRect) const +IntRect FilterEffect::requestedRegionOfInputImageData(const FloatRect& effectRect) const { ASSERT(m_effectBuffer); FloatPoint location = m_repaintRectInLocalCoordinates.location(); @@ -64,7 +64,7 @@ IntRect FilterEffect::calculateDrawingIntRect(const FloatRect& effectRect) const return IntRect(roundedIntPoint(location), m_effectBuffer->size()); } -FloatRect FilterEffect::calculateDrawingRect(const FloatRect& srcRect) const +FloatRect FilterEffect::drawingRegionOfInputImage(const FloatRect& srcRect) const { return FloatRect(FloatPoint(srcRect.x() - m_repaintRectInLocalCoordinates.x(), srcRect.y() - m_repaintRectInLocalCoordinates.y()), srcRect.size()); @@ -76,7 +76,7 @@ FilterEffect* FilterEffect::inputEffect(unsigned number) const return m_inputEffects.at(number).get(); } -GraphicsContext* FilterEffect::getEffectContext() +GraphicsContext* FilterEffect::effectContext() { IntRect bufferRect = enclosingIntRect(m_repaintRectInLocalCoordinates); m_effectBuffer = ImageBuffer::create(bufferRect.size(), LinearRGB); diff --git a/WebCore/platform/graphics/filters/FilterEffect.h b/WebCore/platform/graphics/filters/FilterEffect.h index 91c52f3..ebe1880 100644 --- a/WebCore/platform/graphics/filters/FilterEffect.h +++ b/WebCore/platform/graphics/filters/FilterEffect.h @@ -49,14 +49,14 @@ public: // Creates the ImageBuffer for the current filter primitive result in the size of the // repaintRect. Gives back the GraphicsContext of the own ImageBuffer. - GraphicsContext* getEffectContext(); + GraphicsContext* effectContext(); FilterEffectVector& inputEffects() { return m_inputEffects; } FilterEffect* inputEffect(unsigned) const; unsigned numberOfEffectInputs() const { return m_inputEffects.size(); } - FloatRect calculateDrawingRect(const FloatRect&) const; - IntRect calculateDrawingIntRect(const FloatRect&) const; + FloatRect drawingRegionOfInputImage(const FloatRect&) const; + IntRect requestedRegionOfInputImageData(const FloatRect&) const; // Solid black image with different alpha values. bool isAlphaImage() const { return m_alphaImage; } diff --git a/WebCore/platform/graphics/filters/ImageBufferFilter.cpp b/WebCore/platform/graphics/filters/ImageBufferFilter.cpp index 33953d6..12407f8 100644 --- a/WebCore/platform/graphics/filters/ImageBufferFilter.cpp +++ b/WebCore/platform/graphics/filters/ImageBufferFilter.cpp @@ -1,21 +1,21 @@ /* - * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> - * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org> * - * 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 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. + * 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 - * aint 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. + * 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. */ #include "config.h" diff --git a/WebCore/platform/graphics/filters/ImageBufferFilter.h b/WebCore/platform/graphics/filters/ImageBufferFilter.h index a2775ea..cd4bc2f 100644 --- a/WebCore/platform/graphics/filters/ImageBufferFilter.h +++ b/WebCore/platform/graphics/filters/ImageBufferFilter.h @@ -1,21 +1,21 @@ /* - * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> - * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org> * - * 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 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. + * 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 - * aint 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. + * 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. */ #ifndef ImageBufferFilter_h diff --git a/WebCore/platform/graphics/filters/LightSource.cpp b/WebCore/platform/graphics/filters/LightSource.cpp new file mode 100644 index 0000000..a80b14b --- /dev/null +++ b/WebCore/platform/graphics/filters/LightSource.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org> + * + * 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. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "LightSource.h" + +#include "DistantLightSource.h" +#include "PointLightSource.h" +#include "RenderTreeAsText.h" +#include "SpotLightSource.h" +#include <wtf/MathExtras.h> + +namespace WebCore { + +void PointLightSource::initPaintingData(PaintingData&) +{ +} + +void PointLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z) +{ + paintingData.lightVector.setX(m_position.x() - x); + paintingData.lightVector.setY(m_position.y() - y); + paintingData.lightVector.setZ(m_position.z() - z); + paintingData.lightVector.normalize(); +} + +// spot-light edge darkening depends on an absolute treshold +// according to the SVG 1.1 SE light regression tests +static const float antiAliasTreshold = 0.016f; + +void SpotLightSource::initPaintingData(PaintingData& paintingData) +{ + paintingData.privateColorVector = paintingData.colorVector; + paintingData.directionVector.setX(m_direction.x() - m_position.x()); + paintingData.directionVector.setY(m_direction.y() - m_position.y()); + paintingData.directionVector.setZ(m_direction.z() - m_position.z()); + paintingData.directionVector.normalize(); + + if (!m_limitingConeAngle) { + paintingData.coneCutOffLimit = 0.0f; + paintingData.coneFullLight = -antiAliasTreshold; + } else { + float limitingConeAngle = m_limitingConeAngle; + if (limitingConeAngle < 0.0f) + limitingConeAngle = -limitingConeAngle; + if (limitingConeAngle > 90.0f) + limitingConeAngle = 90.0f; + paintingData.coneCutOffLimit = cosf(deg2rad(180.0f - limitingConeAngle)); + paintingData.coneFullLight = paintingData.coneCutOffLimit - antiAliasTreshold; + } + + // Optimization for common specularExponent values + if (!m_specularExponent) + paintingData.specularExponent = 0; + else if (m_specularExponent == 1.0f) + paintingData.specularExponent = 1; + else // It is neither 0.0f nor 1.0f + paintingData.specularExponent = 2; +} + +void SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z) +{ + paintingData.lightVector.setX(m_position.x() - x); + paintingData.lightVector.setY(m_position.y() - y); + paintingData.lightVector.setZ(m_position.z() - z); + paintingData.lightVector.normalize(); + + float cosineOfAngle = paintingData.lightVector * paintingData.directionVector; + if (cosineOfAngle > paintingData.coneCutOffLimit) { + // No light is produced, scanlines are not updated + paintingData.colorVector.setX(0.0f); + paintingData.colorVector.setY(0.0f); + paintingData.colorVector.setZ(0.0f); + return; + } + + // Set the color of the pixel + float lightStrength; + switch (paintingData.specularExponent) { + case 0: + lightStrength = 1.0f; // -cosineOfAngle ^ 0 == 1 + break; + case 1: + lightStrength = -cosineOfAngle; // -cosineOfAngle ^ 1 == -cosineOfAngle + break; + default: + lightStrength = powf(-cosineOfAngle, m_specularExponent); + break; + } + + if (cosineOfAngle > paintingData.coneFullLight) + lightStrength *= (paintingData.coneCutOffLimit - cosineOfAngle) / (paintingData.coneCutOffLimit - paintingData.coneFullLight); + + if (lightStrength > 1.0f) + lightStrength = 1.0f; + + paintingData.colorVector.setX(paintingData.privateColorVector.x() * lightStrength); + paintingData.colorVector.setY(paintingData.privateColorVector.y() * lightStrength); + paintingData.colorVector.setZ(paintingData.privateColorVector.z() * lightStrength); +} + +void DistantLightSource::initPaintingData(PaintingData& paintingData) +{ + float azimuth = deg2rad(m_azimuth); + float elevation = deg2rad(m_elevation); + paintingData.lightVector.setX(cosf(azimuth) * cosf(elevation)); + paintingData.lightVector.setY(sinf(azimuth) * cosf(elevation)); + paintingData.lightVector.setZ(sinf(elevation)); +} + +void DistantLightSource::updatePaintingData(PaintingData&, int, int, float) +{ +} + +static TextStream& operator<<(TextStream& ts, const FloatPoint3D& p) +{ + ts << "x=" << p.x() << " y=" << p.y() << " z=" << p.z(); + return ts; +} + +TextStream& PointLightSource::externalRepresentation(TextStream& ts) const +{ + ts << "[type=POINT-LIGHT] "; + ts << "[position=\"" << position() << "\"]"; + return ts; +} + +TextStream& SpotLightSource::externalRepresentation(TextStream& ts) const +{ + ts << "[type=SPOT-LIGHT] "; + ts << "[position=\"" << position() << "\"]"; + ts << "[direction=\"" << direction() << "\"]"; + ts << "[specularExponent=\"" << specularExponent() << "\"]"; + ts << "[limitingConeAngle=\"" << limitingConeAngle() << "\"]"; + return ts; +} + +TextStream& DistantLightSource::externalRepresentation(TextStream& ts) const +{ + ts << "[type=DISTANT-LIGHT] "; + ts << "[azimuth=\"" << azimuth() << "\"]"; + ts << "[elevation=\"" << elevation() << "\"]"; + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/WebCore/platform/graphics/filters/LightSource.h b/WebCore/platform/graphics/filters/LightSource.h new file mode 100644 index 0000000..2e4c579 --- /dev/null +++ b/WebCore/platform/graphics/filters/LightSource.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org> + * + * 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. + */ + +#ifndef LightSource_h +#define LightSource_h + +#if ENABLE(FILTERS) +#include "FloatPoint3D.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +namespace WebCore { + +enum LightType { + LS_DISTANT, + LS_POINT, + LS_SPOT +}; + +class TextStream; + +class LightSource : public RefCounted<LightSource> { +public: + + // Light vectors must be calculated for every pixel during + // painting. It is expensive to pass all these arguments to + // a frequently called function, especially because not all + // light sources require all of them. Instead, we just pass + // a reference to the following structure + struct PaintingData { + // SVGFELighting also use them + FloatPoint3D lightVector; + FloatPoint3D colorVector; + // Private members + FloatPoint3D directionVector; + FloatPoint3D privateColorVector; + float coneCutOffLimit; + float coneFullLight; + int specularExponent; + }; + + LightSource(LightType type) + : m_type(type) + { } + + virtual ~LightSource() { } + + LightType type() const { return m_type; } + virtual TextStream& externalRepresentation(TextStream&) const = 0; + + virtual void initPaintingData(PaintingData&) = 0; + // z is a float number, since it is the alpha value scaled by a user + // specified "surfaceScale" constant, which type is <number> in the SVG standard + virtual void updatePaintingData(PaintingData&, int x, int y, float z) = 0; + +private: + LightType m_type; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // LightSource_h diff --git a/WebCore/platform/graphics/filters/PointLightSource.h b/WebCore/platform/graphics/filters/PointLightSource.h new file mode 100644 index 0000000..163c829 --- /dev/null +++ b/WebCore/platform/graphics/filters/PointLightSource.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef PointLightSource_h +#define PointLightSource_h + +#if ENABLE(FILTERS) +#include "LightSource.h" + +namespace WebCore { + +class PointLightSource : public LightSource { +public: + static PassRefPtr<PointLightSource> create(const FloatPoint3D& position) + { + return adoptRef(new PointLightSource(position)); + } + + const FloatPoint3D& position() const { return m_position; } + + virtual void initPaintingData(PaintingData&); + virtual void updatePaintingData(PaintingData&, int x, int y, float z); + + virtual TextStream& externalRepresentation(TextStream&) const; + +private: + PointLightSource(const FloatPoint3D& position) + : LightSource(LS_POINT) + , m_position(position) + { + } + + FloatPoint3D m_position; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // PointLightSource_h diff --git a/WebCore/platform/graphics/filters/SourceAlpha.cpp b/WebCore/platform/graphics/filters/SourceAlpha.cpp index 9c6a953..beaf2e7 100644 --- a/WebCore/platform/graphics/filters/SourceAlpha.cpp +++ b/WebCore/platform/graphics/filters/SourceAlpha.cpp @@ -1,20 +1,20 @@ /* - * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> * - * 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 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. + * 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 - * aint 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. + * 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. */ #include "config.h" @@ -57,7 +57,7 @@ FloatRect SourceAlpha::determineFilterPrimitiveSubregion(Filter* filter) void SourceAlpha::apply(Filter* filter) { - GraphicsContext* filterContext = getEffectContext(); + GraphicsContext* filterContext = effectContext(); if (!filterContext) return; diff --git a/WebCore/platform/graphics/filters/SourceAlpha.h b/WebCore/platform/graphics/filters/SourceAlpha.h index 25a17b2..f0fa319 100644 --- a/WebCore/platform/graphics/filters/SourceAlpha.h +++ b/WebCore/platform/graphics/filters/SourceAlpha.h @@ -1,21 +1,21 @@ /* - Copyright (C) 2009 Dirk Schulze <krit@webkit.org> - - 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 - aint 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. -*/ + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * 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. + */ #ifndef SourceAlpha_h #define SourceAlpha_h @@ -28,22 +28,25 @@ namespace WebCore { - class SourceAlpha : public FilterEffect { - public: - static PassRefPtr<SourceAlpha> create(); +class SourceAlpha : public FilterEffect { +public: + static PassRefPtr<SourceAlpha> create(); + + static const AtomicString& effectName(); + + virtual FloatRect determineFilterPrimitiveSubregion(Filter*); + + virtual void apply(Filter*); + virtual void dump(); + + virtual bool isSourceInput() const { return true; } - static const AtomicString& effectName(); + virtual TextStream& externalRepresentation(TextStream&, int indention) const; - void apply(Filter*); - void dump(); - TextStream& externalRepresentation(TextStream&, int indent) const; +private: + SourceAlpha() { } +}; - virtual bool isSourceInput() const { return true; } - virtual FloatRect determineFilterPrimitiveSubregion(Filter*); - - private: - SourceAlpha() { } - }; } //namespace WebCore #endif // ENABLE(FILTERS) diff --git a/WebCore/platform/graphics/filters/SourceGraphic.cpp b/WebCore/platform/graphics/filters/SourceGraphic.cpp index 6a32e36..c014e68 100644 --- a/WebCore/platform/graphics/filters/SourceGraphic.cpp +++ b/WebCore/platform/graphics/filters/SourceGraphic.cpp @@ -1,20 +1,20 @@ /* - * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> * - * 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 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. + * 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 - * aint 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. + * 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. */ #include "config.h" @@ -56,7 +56,7 @@ FloatRect SourceGraphic::determineFilterPrimitiveSubregion(Filter* filter) void SourceGraphic::apply(Filter* filter) { - GraphicsContext* filterContext = getEffectContext(); + GraphicsContext* filterContext = effectContext(); if (!filterContext) return; diff --git a/WebCore/platform/graphics/filters/SourceGraphic.h b/WebCore/platform/graphics/filters/SourceGraphic.h index 911648c..2378798 100644 --- a/WebCore/platform/graphics/filters/SourceGraphic.h +++ b/WebCore/platform/graphics/filters/SourceGraphic.h @@ -1,22 +1,22 @@ /* - Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> - 2009 Dirk Schulze <krit@webkit.org> - - 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 - aint 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. -*/ + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * 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. + */ #ifndef SourceGraphic_h #define SourceGrahpic_h @@ -29,22 +29,25 @@ namespace WebCore { - class SourceGraphic : public FilterEffect { - public: - static PassRefPtr<SourceGraphic> create(); +class SourceGraphic : public FilterEffect { +public: + static PassRefPtr<SourceGraphic> create(); + + static const AtomicString& effectName(); + + virtual FloatRect determineFilterPrimitiveSubregion(Filter*); + + virtual void apply(Filter*); + virtual void dump(); - static const AtomicString& effectName(); + virtual bool isSourceInput() const { return true; } - void apply(Filter*); - void dump(); - TextStream& externalRepresentation(TextStream&, int indent) const; + virtual TextStream& externalRepresentation(TextStream&, int indention) const; - virtual bool isSourceInput() const { return true; } - virtual FloatRect determineFilterPrimitiveSubregion(Filter*); +private: + SourceGraphic() { } +}; - private: - SourceGraphic() { } - }; } //namespace WebCore #endif // ENABLE(FILTERS) diff --git a/WebCore/platform/graphics/filters/SpotLightSource.h b/WebCore/platform/graphics/filters/SpotLightSource.h new file mode 100644 index 0000000..cd6a614 --- /dev/null +++ b/WebCore/platform/graphics/filters/SpotLightSource.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef SpotLightSource_h +#define SpotLightSource_h + +#if ENABLE(FILTERS) +#include "LightSource.h" + +namespace WebCore { + +class SpotLightSource : public LightSource { +public: + static PassRefPtr<SpotLightSource> create(const FloatPoint3D& position, + const FloatPoint3D& direction, float specularExponent, float limitingConeAngle) + { + return adoptRef(new SpotLightSource(position, direction, specularExponent, limitingConeAngle)); + } + + const FloatPoint3D& position() const { return m_position; } + const FloatPoint3D& direction() const { return m_direction; } + + float specularExponent() const { return m_specularExponent; } + float limitingConeAngle() const { return m_limitingConeAngle; } + + virtual void initPaintingData(PaintingData&); + virtual void updatePaintingData(PaintingData&, int x, int y, float z); + + virtual TextStream& externalRepresentation(TextStream&) const; + +private: + SpotLightSource(const FloatPoint3D& position, const FloatPoint3D& direction, + float specularExponent, float limitingConeAngle) + : LightSource(LS_SPOT) + , m_position(position) + , m_direction(direction) + , m_specularExponent(specularExponent) + , m_limitingConeAngle(limitingConeAngle) + { + } + + FloatPoint3D m_position; + FloatPoint3D m_direction; + + float m_specularExponent; + float m_limitingConeAngle; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // SpotLightSource_h diff --git a/WebCore/platform/graphics/gpu/LoopBlinnLocalTriangulator.cpp b/WebCore/platform/graphics/gpu/LoopBlinnLocalTriangulator.cpp new file mode 100644 index 0000000..3b73ff6 --- /dev/null +++ b/WebCore/platform/graphics/gpu/LoopBlinnLocalTriangulator.cpp @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2010 Google 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. + * + * 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 "LoopBlinnLocalTriangulator.h" + +#include "LoopBlinnMathUtils.h" +#include <algorithm> + +namespace WebCore { + +using LoopBlinnMathUtils::approxEqual; +using LoopBlinnMathUtils::linesIntersect; +using LoopBlinnMathUtils::pointInTriangle; + +bool LoopBlinnLocalTriangulator::Triangle::contains(LoopBlinnLocalTriangulator::Vertex* v) +{ + return indexForVertex(v) >= 0; +} + +LoopBlinnLocalTriangulator::Vertex* LoopBlinnLocalTriangulator::Triangle::nextVertex(LoopBlinnLocalTriangulator::Vertex* current, bool traverseCounterClockwise) +{ + int index = indexForVertex(current); + ASSERT(index >= 0); + if (traverseCounterClockwise) + ++index; + else + --index; + if (index < 0) + index += 3; + else + index = index % 3; + return m_vertices[index]; +} + +int LoopBlinnLocalTriangulator::Triangle::indexForVertex(LoopBlinnLocalTriangulator::Vertex* vertex) +{ + for (int i = 0; i < 3; ++i) + if (m_vertices[i] == vertex) + return i; + return -1; +} + +void LoopBlinnLocalTriangulator::Triangle::makeCounterClockwise() +{ + // Possibly swaps two vertices so that the triangle's vertices are + // always specified in counterclockwise order. This orders the + // vertices canonically when walking the interior edges from the + // start to the end vertex. + FloatPoint3D point0(m_vertices[0]->xyCoordinates()); + FloatPoint3D point1(m_vertices[1]->xyCoordinates()); + FloatPoint3D point2(m_vertices[2]->xyCoordinates()); + FloatPoint3D crossProduct = (point1 - point0).cross(point2 - point0); + if (crossProduct.z() < 0) + std::swap(m_vertices[1], m_vertices[2]); +} + +LoopBlinnLocalTriangulator::LoopBlinnLocalTriangulator() +{ + reset(); +} + +void LoopBlinnLocalTriangulator::reset() +{ + m_numberOfTriangles = 0; + m_numberOfInteriorVertices = 0; + for (int i = 0; i < 4; ++i) { + m_interiorVertices[i] = 0; + m_vertices[i].resetFlags(); + } +} + +void LoopBlinnLocalTriangulator::triangulate(InsideEdgeComputation computeInsideEdges, LoopBlinnConstants::FillSide sideToFill) +{ + triangulateHelper(sideToFill); + + if (computeInsideEdges == ComputeInsideEdges) { + // We need to compute which vertices describe the path along the + // interior portion of the shape, to feed these vertices to the + // more general tessellation algorithm. It is possible that we + // could determine this directly while producing triangles above. + // Here we try to do it generally just by examining the triangles + // that have already been produced. We walk around them in a + // specific direction determined by which side of the curve is + // being filled. We ignore the interior vertex unless it is also + // the ending vertex, and skip the edges shared between two + // triangles. + Vertex* v = &m_vertices[0]; + addInteriorVertex(v); + int numSteps = 0; + while (!v->end() && numSteps < 4) { + // Find the next vertex according to the above rules + bool gotNext = false; + for (int i = 0; i < numberOfTriangles() && !gotNext; ++i) { + Triangle* tri = getTriangle(i); + if (tri->contains(v)) { + Vertex* next = tri->nextVertex(v, sideToFill == LoopBlinnConstants::RightSide); + if (!next->marked() && !isSharedEdge(v, next) && (!next->interior() || next->end())) { + addInteriorVertex(next); + v = next; + // Break out of for loop + gotNext = true; + } + } + } + ++numSteps; + } + if (!v->end()) { + // Something went wrong with the above algorithm; add the last + // vertex to the interior vertices anyway. (FIXME: should we + // add an assert here and do more extensive testing?) + addInteriorVertex(&m_vertices[3]); + } + } +} + +void LoopBlinnLocalTriangulator::triangulateHelper(LoopBlinnConstants::FillSide sideToFill) +{ + reset(); + + m_vertices[3].setEnd(true); + + // First test for degenerate cases. + for (int i = 0; i < 4; ++i) { + for (int j = i + 1; j < 4; ++j) { + if (approxEqual(m_vertices[i].xyCoordinates(), m_vertices[j].xyCoordinates())) { + // Two of the vertices are coincident, so we can eliminate at + // least one triangle. We might be able to eliminate the other + // as well, but this seems sufficient to avoid degenerate + // triangulations. + int indices[3] = { 0 }; + int index = 0; + for (int k = 0; k < 4; ++k) + if (k != j) + indices[index++] = k; + addTriangle(&m_vertices[indices[0]], + &m_vertices[indices[1]], + &m_vertices[indices[2]]); + return; + } + } + } + + // See whether any of the points are fully contained in the + // triangle defined by the other three. + for (int i = 0; i < 4; ++i) { + int indices[3] = { 0 }; + int index = 0; + for (int j = 0; j < 4; ++j) + if (i != j) + indices[index++] = j; + if (pointInTriangle(m_vertices[i].xyCoordinates(), + m_vertices[indices[0]].xyCoordinates(), + m_vertices[indices[1]].xyCoordinates(), + m_vertices[indices[2]].xyCoordinates())) { + // Produce three triangles surrounding this interior vertex. + for (int j = 0; j < 3; ++j) + addTriangle(&m_vertices[indices[j % 3]], + &m_vertices[indices[(j + 1) % 3]], + &m_vertices[i]); + // Mark the interior vertex so we ignore it if trying to trace + // the interior edge. + m_vertices[i].setInterior(true); + return; + } + } + + // There are only a few permutations of the vertices, ignoring + // rotations, which are irrelevant: + // + // 0--3 0--2 0--3 0--1 0--2 0--1 + // | | | | | | | | | | | | + // | | | | | | | | | | | | + // 1--2 1--3 2--1 2--3 3--1 3--2 + // + // Note that three of these are reflections of each other. + // Therefore there are only three possible triangulations: + // + // 0--3 0--2 0--3 + // |\ | |\ | |\ | + // | \| | \| | \| + // 1--2 1--3 2--1 + // + // From which we can choose by seeing which of the potential + // diagonals intersect. Note that we choose the shortest diagonal + // to split the quad. + if (linesIntersect(m_vertices[0].xyCoordinates(), + m_vertices[2].xyCoordinates(), + m_vertices[1].xyCoordinates(), + m_vertices[3].xyCoordinates())) { + if ((m_vertices[2].xyCoordinates() - m_vertices[0].xyCoordinates()).diagonalLengthSquared() < + (m_vertices[3].xyCoordinates() - m_vertices[1].xyCoordinates()).diagonalLengthSquared()) { + addTriangle(&m_vertices[0], &m_vertices[1], &m_vertices[2]); + addTriangle(&m_vertices[0], &m_vertices[2], &m_vertices[3]); + } else { + addTriangle(&m_vertices[0], &m_vertices[1], &m_vertices[3]); + addTriangle(&m_vertices[1], &m_vertices[2], &m_vertices[3]); + } + } else if (linesIntersect(m_vertices[0].xyCoordinates(), + m_vertices[3].xyCoordinates(), + m_vertices[1].xyCoordinates(), + m_vertices[2].xyCoordinates())) { + if ((m_vertices[3].xyCoordinates() - m_vertices[0].xyCoordinates()).diagonalLengthSquared() < + (m_vertices[2].xyCoordinates() - m_vertices[1].xyCoordinates()).diagonalLengthSquared()) { + addTriangle(&m_vertices[0], &m_vertices[1], &m_vertices[3]); + addTriangle(&m_vertices[0], &m_vertices[3], &m_vertices[2]); + } else { + addTriangle(&m_vertices[0], &m_vertices[1], &m_vertices[2]); + addTriangle(&m_vertices[2], &m_vertices[1], &m_vertices[3]); + } + } else { + // Lines (0->1), (2->3) intersect -- or should, modulo numerical + // precision issues + if ((m_vertices[1].xyCoordinates() - m_vertices[0].xyCoordinates()).diagonalLengthSquared() < + (m_vertices[3].xyCoordinates() - m_vertices[2].xyCoordinates()).diagonalLengthSquared()) { + addTriangle(&m_vertices[0], &m_vertices[2], &m_vertices[1]); + addTriangle(&m_vertices[0], &m_vertices[1], &m_vertices[3]); + } else { + addTriangle(&m_vertices[0], &m_vertices[2], &m_vertices[3]); + addTriangle(&m_vertices[3], &m_vertices[2], &m_vertices[1]); + } + } +} + +void LoopBlinnLocalTriangulator::addTriangle(Vertex* v0, Vertex* v1, Vertex* v2) +{ + ASSERT(m_numberOfTriangles < 3); + m_triangles[m_numberOfTriangles++].setVertices(v0, v1, v2); +} + +void LoopBlinnLocalTriangulator::addInteriorVertex(Vertex* v) +{ + ASSERT(m_numberOfInteriorVertices < 4); + m_interiorVertices[m_numberOfInteriorVertices++] = v; + v->setMarked(true); +} + +bool LoopBlinnLocalTriangulator::isSharedEdge(Vertex* v0, Vertex* v1) +{ + bool haveEdge01 = false; + bool haveEdge10 = false; + for (int i = 0; i < numberOfTriangles(); ++i) { + Triangle* tri = getTriangle(i); + if (tri->contains(v0) && tri->nextVertex(v0, true) == v1) + haveEdge01 = true; + if (tri->contains(v1) && tri->nextVertex(v1, true) == v0) + haveEdge10 = true; + } + return haveEdge01 && haveEdge10; +} + +} // namespace WebCore diff --git a/WebCore/platform/graphics/gpu/LoopBlinnLocalTriangulator.h b/WebCore/platform/graphics/gpu/LoopBlinnLocalTriangulator.h new file mode 100644 index 0000000..ea3d7e3 --- /dev/null +++ b/WebCore/platform/graphics/gpu/LoopBlinnLocalTriangulator.h @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2010 Google 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. + * + * 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. + */ + +#ifndef LoopBlinnLocalTriangulator_h +#define LoopBlinnLocalTriangulator_h + +#include "FloatPoint.h" +#include "FloatPoint3D.h" +#include "LoopBlinnConstants.h" +#include <wtf/Assertions.h> +#include <wtf/Noncopyable.h> + +namespace WebCore { + +// Performs a localized triangulation of the triangle mesh +// corresponding to the four control point vertices of a cubic curve +// segment. +class LoopBlinnLocalTriangulator : public Noncopyable { +public: + // The vertices that the triangulator operates upon, containing both + // the position information as well as the cubic texture + // coordinates. + class Vertex : public Noncopyable { + public: + Vertex() + { + resetFlags(); + } + + const FloatPoint& xyCoordinates() const + { + return m_xyCoordinates; + } + + const FloatPoint3D& klmCoordinates() const + { + return m_klmCoordinates; + } + + // Sets the position and texture coordinates of the vertex. + void set(float x, float y, + float k, float l, float m) + { + m_xyCoordinates.set(x, y); + m_klmCoordinates.set(k, l, m); + } + + // Flags for walking from the start vertex to the end vertex. + bool end() + { + return m_end; + } + + void setEnd(bool end) + { + m_end = end; + } + + bool marked() + { + return m_marked; + } + + void setMarked(bool marked) + { + m_marked = marked; + } + + bool interior() + { + return m_interior; + } + + void setInterior(bool interior) + { + m_interior = interior; + } + + void resetFlags() + { + m_end = false; + m_marked = false; + m_interior = false; + } + + private: + // 2D coordinates of the vertex in the plane. + FloatPoint m_xyCoordinates; + // Cubic texture coordinates for rendering the curve. + FloatPoint3D m_klmCoordinates; + + // Flags for walking from the start vertex to the end vertex. + bool m_end; + bool m_marked; + bool m_interior; + }; + + // The triangles the Triangulator produces. + class Triangle { + public: + Triangle() + { + m_vertices[0] = 0; + m_vertices[1] = 0; + m_vertices[2] = 0; + } + + // Gets the vertex at the given index, 0 <= index < 3. + Vertex* getVertex(int index) + { + ASSERT(index >= 0 && index < 3); + return m_vertices[index]; + } + + // Returns true if this triangle contains the given vertex (by + // identity, not geometrically). + bool contains(Vertex* v); + + // Returns the vertex following the current one in the specified + // direction, counterclockwise or clockwise. + Vertex* nextVertex(Vertex* current, bool traverseCounterClockwise); + + // Sets the vertices of this triangle, potentially reordering them + // to produce a canonical orientation. + void setVertices(Vertex* v0, + Vertex* v1, + Vertex* v2) + { + m_vertices[0] = v0; + m_vertices[1] = v1; + m_vertices[2] = v2; + makeCounterClockwise(); + } + + private: + // Returns the index [0..2] associated with the given vertex, or + // -1 if not found. + int indexForVertex(Vertex* vertex); + + // Reorders the vertices in this triangle to make them + // counterclockwise when viewed in the 2D plane, in order to + // achieve a canonical ordering. + void makeCounterClockwise(); + + // Note: these are raw pointers because they point to the + // m_vertices contained in the surrounding triangulator. + Vertex* m_vertices[3]; + }; + + LoopBlinnLocalTriangulator(); + + // Resets the triangulator's state. After each triangulation and + // before the next, call this to re-initialize the internal + // vertices' state. + void reset(); + + // Returns a mutable vertex stored in the triangulator. Use this to + // set up the vertices before a triangulation. + Vertex* getVertex(int index) + { + ASSERT(index >= 0 && index < 4); + return &m_vertices[index]; + } + + enum InsideEdgeComputation { + ComputeInsideEdges, + DontComputeInsideEdges + }; + + // Once the vertices' contents have been set up, call triangulate() + // to recompute the triangles. + // + // If computeInsideEdges is ComputeInsideEdges, then sideToFill + // will be used to determine which side of the cubic curve defined + // by the four control points is to be filled. + // + // The triangulation obeys the following guarantees: + // - If the convex hull is a quadrilateral, then the shortest edge + // will be chosen for the cut into two triangles. + // - If one of the vertices is contained in the triangle spanned + // by the other three, three triangles will be produced. + void triangulate(InsideEdgeComputation computeInsideEdges, + LoopBlinnConstants::FillSide sideToFill); + + // Number of triangles computed by triangulate(). + int numberOfTriangles() const + { + return m_numberOfTriangles; + } + + // Returns the computed triangle at index, 0 <= index < numberOfTriangles(). + Triangle* getTriangle(int index) + { + ASSERT(index >= 0 && index < m_numberOfTriangles); + return &m_triangles[index]; + } + + // Number of vertices facing the inside of the shape, if + // ComputeInsideEdges was passed when triangulate() was called. + int numberOfInteriorVertices() const + { + return m_numberOfInteriorVertices; + } + + // Fetches the given interior vertex, 0 <= index < numberOfInteriorVertices(). + Vertex* getInteriorVertex(int index) + { + ASSERT(index >= 0 && index < m_numberOfInteriorVertices); + return m_interiorVertices[index]; + } + +private: + void triangulateHelper(LoopBlinnConstants::FillSide sideToFill); + + // Adds a triangle to the triangulation. + void addTriangle(Vertex* v0, Vertex* v1, Vertex* v2); + + // Adds a vertex to the list of interior vertices. + void addInteriorVertex(Vertex* v); + + // Indicates whether the edge between vertex v0 and v1 is shared + // between two or more triangles. + bool isSharedEdge(Vertex* v0, Vertex* v1); + + // The vertices being triangulated. + Vertex m_vertices[4]; + + // The vertices corresponding to the edges facing the inside of the + // shape, in order from the start vertex to the end vertex. The more + // general triangulation algorithm tessellates this interior region. + Vertex* m_interiorVertices[4]; + // The number of interior vertices that are valid for the current + // triangulation. + int m_numberOfInteriorVertices; + + // There can be at most three triangles computed by this local + // algorithm, which occurs when one of the vertices is contained in + // the triangle spanned by the other three. Most of the time the + // algorithm computes two triangles. + Triangle m_triangles[3]; + int m_numberOfTriangles; +}; + +} // namespace WebCore + +#endif // LoopBlinnLocalTriangulator_h diff --git a/WebCore/platform/graphics/gpu/Texture.cpp b/WebCore/platform/graphics/gpu/Texture.cpp index 95436ba..6023fe9 100644 --- a/WebCore/platform/graphics/gpu/Texture.cpp +++ b/WebCore/platform/graphics/gpu/Texture.cpp @@ -129,7 +129,7 @@ static uint32_t* copySubRect(uint32_t* src, int srcX, int srcY, uint32_t* dst, i for (int y = 0; y < height; ++y) { for (int x = 0; x < width ; ++x) { uint32_t pixel = srcOffset[x + y * srcStride]; - *dstPixel = pixel & 0xFF00FF00 | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16); + *dstPixel = (pixel & 0xFF00FF00) | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16); dstPixel++; } } diff --git a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp index 63555bf..5a94fd4 100644 --- a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp @@ -18,7 +18,7 @@ #include "config.h" #include "DataSourceGStreamer.h" -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include <gio/gio.h> #include <glib.h> @@ -243,4 +243,4 @@ static void webkit_data_src_uri_handler_init(gpointer g_iface, gpointer iface_da iface->set_uri = webkit_data_src_uri_set_uri; } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) diff --git a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h index 453685a..d462ccc4 100644 --- a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h @@ -19,7 +19,7 @@ #ifndef DataSourceGStreamer_h #define DataSourceGStreamer_h -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include <glib-object.h> #include <gst/base/gstbasesrc.h> @@ -53,5 +53,5 @@ GType webkit_data_src_get_type(void); G_END_DECLS -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) #endif diff --git a/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp index 6333437..06eec14 100644 --- a/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp @@ -20,7 +20,7 @@ #include "config.h" #include "GOwnPtrGStreamer.h" -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include <gst/gstelement.h> namespace WTF { @@ -32,4 +32,4 @@ template <> void freeOwnedGPtr<GstElement>(GstElement* ptr) } } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) diff --git a/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h index 84a3e30..672a23d 100644 --- a/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h @@ -19,7 +19,7 @@ #ifndef GOwnPtrGStreamer_h #define GOwnPtrGStreamer_h -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include "GOwnPtr.h" @@ -31,5 +31,5 @@ template<> void freeOwnedGPtr<GstElement>(GstElement* ptr); } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) #endif diff --git a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp index efccff0..539d92a 100644 --- a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp +++ b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp @@ -19,7 +19,7 @@ #include "config.h" #include "GStreamerGWorld.h" -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include "GOwnPtrGStreamer.h" #include <gst/gst.h> @@ -203,4 +203,4 @@ void GStreamerGWorld::setWindowOverlay(GstMessage* message) } } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) diff --git a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h index 282f13c..f519911 100644 --- a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h +++ b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h @@ -20,7 +20,7 @@ #ifndef GStreamerGWorld_h #define GStreamerGWorld_h -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include "PlatformVideoWindow.h" #include "RefCounted.h" @@ -62,5 +62,5 @@ private: }; } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) #endif diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamer.h b/WebCore/platform/graphics/gstreamer/ImageGStreamer.h index 4a4ff2b..cf2b9d6 100644 --- a/WebCore/platform/graphics/gstreamer/ImageGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/ImageGStreamer.h @@ -20,7 +20,7 @@ #ifndef ImageGStreamer_h #define ImageGStreamer_h -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include "BitmapImage.h" #include <gst/gst.h> @@ -59,5 +59,5 @@ class ImageGStreamer : public RefCounted<ImageGStreamer> { }; } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) #endif diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamerCG.mm b/WebCore/platform/graphics/gstreamer/ImageGStreamerCG.mm index 076df4a..c73adc0 100644 --- a/WebCore/platform/graphics/gstreamer/ImageGStreamerCG.mm +++ b/WebCore/platform/graphics/gstreamer/ImageGStreamerCG.mm @@ -19,7 +19,7 @@ #include "config.h" #include "ImageGStreamer.h" -#if ENABLE(VIDEO) +#if USE(GSTREAMER) using namespace WebCore; @@ -57,4 +57,4 @@ ImageGStreamer::~ImageGStreamer() m_image = 0; } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp b/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp index 2fed892..6a9d068 100644 --- a/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp +++ b/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp @@ -20,7 +20,7 @@ #include "config.h" #include "ImageGStreamer.h" -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include "GOwnPtr.h" @@ -65,4 +65,4 @@ ImageGStreamer::~ImageGStreamer() m_image = 0; } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp index 0071d67..da9255b 100644 --- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp @@ -24,7 +24,7 @@ #include "config.h" #include "MediaPlayerPrivateGStreamer.h" -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include "ColorSpace.h" #include "DataSourceGStreamer.h" @@ -1459,4 +1459,4 @@ void MediaPlayerPrivateGStreamer::createGSTPlayBin() } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h index 6d1392d..800ca6d 100644 --- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h @@ -22,7 +22,7 @@ #ifndef MediaPlayerPrivateGStreamer_h #define MediaPlayerPrivateGStreamer_h -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include <wtf/Forward.h> #include "MediaPlayerPrivate.h" @@ -179,5 +179,5 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface { }; } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) #endif diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h b/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h index 3c4904b..f3df207 100644 --- a/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h +++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h @@ -19,7 +19,7 @@ #ifndef PlatformVideoWindow_h #define PlatformVideoWindow_h -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include "Widget.h" #include <wtf/PassRefPtr.h> @@ -44,5 +44,5 @@ class PlatformVideoWindow : public RefCounted<PlatformVideoWindow> { }; } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) #endif diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp index 68ab7ac..c55b9cc 100644 --- a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp +++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp @@ -19,7 +19,7 @@ #include "config.h" #include "PlatformVideoWindow.h" -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include "NotImplemented.h" @@ -35,4 +35,4 @@ PlatformVideoWindow::~PlatformVideoWindow() notImplemented(); } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp index 88b6552..77343ae 100644 --- a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp +++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp @@ -19,7 +19,7 @@ #include "config.h" #include "PlatformVideoWindow.h" -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include <gtk/gtk.h> @@ -61,4 +61,4 @@ PlatformVideoWindow::~PlatformVideoWindow() m_videoWindowId = 0; } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) diff --git a/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp index 00fef4b..4319f6c 100644 --- a/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp @@ -28,7 +28,7 @@ #include "config.h" #include "VideoSinkGStreamer.h" -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include <glib.h> #include <gst/gst.h> @@ -371,4 +371,4 @@ webkit_video_sink_new(void) return (GstElement*)g_object_new(WEBKIT_TYPE_VIDEO_SINK, 0); } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) diff --git a/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h index 767e83f..6cd86c2 100644 --- a/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h @@ -20,7 +20,7 @@ #ifndef VideoSinkGStreamer_h #define VideoSinkGStreamer_h -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include <glib-object.h> #include <gst/video/gstvideosink.h> @@ -77,5 +77,5 @@ GstElement *webkit_video_sink_new(void); G_END_DECLS -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) #endif diff --git a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp index 4e57193..635feff 100644 --- a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp @@ -18,7 +18,7 @@ #include "config.h" #include "WebKitWebSourceGStreamer.h" -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include "Document.h" #include "GOwnPtr.h" @@ -795,5 +795,5 @@ void StreamingClient::cannotShowURL(ResourceHandle*) GST_ELEMENT_ERROR(m_src, RESOURCE, OPEN_READ, ("Can't show \"%s\"", m_src->priv->uri), (0)); } -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) diff --git a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h index 1594062..bdb0833 100644 --- a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h @@ -18,7 +18,7 @@ #ifndef WebKitWebSourceGStreamer_h #define WebKitWebSourceGStreamer_h -#if ENABLE(VIDEO) +#if USE(GSTREAMER) #include "Frame.h" #include <gst/gst.h> @@ -50,5 +50,5 @@ void webKitWebSrcSetFrame(WebKitWebSrc* src, WebCore::Frame* frame); G_END_DECLS -#endif // ENABLE(VIDEO) +#endif // USE(GSTREAMER) #endif diff --git a/WebCore/platform/graphics/gtk/CairoUtilities.cpp b/WebCore/platform/graphics/gtk/GdkCairoUtilities.cpp index 81e00f0..d768ce2 100644 --- a/WebCore/platform/graphics/gtk/CairoUtilities.cpp +++ b/WebCore/platform/graphics/gtk/GdkCairoUtilities.cpp @@ -24,7 +24,7 @@ */ #include "config.h" -#include "CairoUtilities.h" +#include "GdkCairoUtilities.h" #include <cairo.h> #include <gtk/gtk.h> diff --git a/WebCore/platform/graphics/gtk/CairoUtilities.h b/WebCore/platform/graphics/gtk/GdkCairoUtilities.h index 594abc0..ff5b3ed 100644 --- a/WebCore/platform/graphics/gtk/CairoUtilities.h +++ b/WebCore/platform/graphics/gtk/GdkCairoUtilities.h @@ -23,9 +23,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CairoUtilities_h -#define CairoUtilities_h +#ifndef GdkCairoUtilities_h +#define GdkCairoUtilities_h GdkPixbuf* cairoImageSurfaceToGdkPixbuf(cairo_surface_t* surface); -#endif // CairoUtilities_h +#endif // GdkCairoUtilities_h diff --git a/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp b/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp index 821cc12..edb26f0 100644 --- a/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp +++ b/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp @@ -21,7 +21,7 @@ #include "ImageBuffer.h" #include "Base64.h" -#include "CairoUtilities.h" +#include "GdkCairoUtilities.h" #include "GOwnPtr.h" #include "GRefPtrGtk.h" #include "MIMETypeRegistry.h" diff --git a/WebCore/platform/graphics/gtk/ImageGtk.cpp b/WebCore/platform/graphics/gtk/ImageGtk.cpp index 5272243..623ace6 100644 --- a/WebCore/platform/graphics/gtk/ImageGtk.cpp +++ b/WebCore/platform/graphics/gtk/ImageGtk.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "BitmapImage.h" -#include "CairoUtilities.h" +#include "GdkCairoUtilities.h" #include "GOwnPtrGtk.h" #include "SharedBuffer.h" #include <wtf/text/CString.h> diff --git a/WebCore/platform/graphics/mac/ComplexTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp index da381f2..a2733f8 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -185,25 +185,14 @@ void ComplexTextController::collectComplexTextRuns() // We break up glyph run generation for the string by FontData and (if needed) the use of small caps. const UChar* cp = m_run.characters(); - bool hasTrailingSoftHyphen = m_run[m_end - 1] == softHyphen; - if (m_font.isSmallCaps() || hasTrailingSoftHyphen) + if (m_font.isSmallCaps()) m_smallCapsBuffer.resize(m_end); unsigned indexOfFontTransition = m_run.rtl() ? m_end - 1 : 0; const UChar* curr = m_run.rtl() ? cp + m_end - 1 : cp; const UChar* end = m_run.rtl() ? cp - 1 : cp + m_end; - // FIXME: Using HYPHEN-MINUS rather than HYPHEN because Times has a HYPHEN-MINUS glyph that looks like its - // SOFT-HYPHEN glyph, and has no HYPHEN glyph. - static const UChar hyphen = '-'; - - if (hasTrailingSoftHyphen && m_run.rtl()) { - collectComplexTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData); - indexOfFontTransition--; - curr--; - } - GlyphData glyphData; GlyphData nextGlyphData; @@ -267,14 +256,11 @@ void ComplexTextController::collectComplexTextRuns() } } - int itemLength = m_run.rtl() ? indexOfFontTransition + 1 : m_end - indexOfFontTransition - (hasTrailingSoftHyphen ? 1 : 0); + int itemLength = m_run.rtl() ? indexOfFontTransition + 1 : m_end - indexOfFontTransition; if (itemLength) { int itemStart = m_run.rtl() ? 0 : indexOfFontTransition; collectComplexTextRunsForCharacters((nextIsSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, nextGlyphData.glyph ? nextGlyphData.fontData : 0); } - - if (hasTrailingSoftHyphen && m_run.ltr()) - collectComplexTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData); } #if USE(CORE_TEXT) && USE(ATSUI) @@ -382,9 +368,9 @@ void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer) unsigned glyphEndOffset; if (complexTextRun.isMonotonic()) { if (ltr) - glyphEndOffset = max<unsigned>(glyphStartOffset, g + 1 < glyphCount ? complexTextRun.indexAt(g + 1) : complexTextRun.stringLength()); + glyphEndOffset = max<unsigned>(glyphStartOffset, g + 1 < glyphCount ? static_cast<unsigned>(complexTextRun.indexAt(g + 1)) : complexTextRun.stringLength()); else - glyphEndOffset = max<unsigned>(glyphStartOffset, g > 0 ? complexTextRun.indexAt(g - 1) : complexTextRun.stringLength()); + glyphEndOffset = max<unsigned>(glyphStartOffset, g > 0 ? static_cast<unsigned>(complexTextRun.indexAt(g - 1)) : complexTextRun.stringLength()); } else glyphEndOffset = complexTextRun.endOffsetAt(g); diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h index 6ff3ff0..17a67ac 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h @@ -96,11 +96,10 @@ public: virtual void suspendAnimations(double time); virtual void resumeAnimations(); - virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, const String& keyframesName, double timeOffset); - virtual void removeAnimationsForProperty(AnimatedPropertyID); - virtual void removeAnimationsForKeyframes(const String& keyframesName); - virtual void pauseAnimation(const String& keyframesName, double timeOffset); - + virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, const String& animationName, double timeOffset); + virtual void pauseAnimation(const String& animationName, double timeOffset); + virtual void removeAnimation(const String& animationName); + virtual void setContentsToImage(Image*); virtual void setContentsToMedia(PlatformLayer*); virtual void setContentsToCanvas(PlatformLayer*); @@ -119,6 +118,9 @@ public: virtual void syncCompositingState(); virtual void syncCompositingStateForThisLayerOnly(); + // Should only be called by animationDidStart: callback + void animationDidStart(CAAnimation*); + protected: virtual void setOpacityInternal(float); @@ -128,17 +130,17 @@ private: CALayer* primaryLayer() const { return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); } CALayer* hostLayerForSublayers() const; CALayer* layerForSuperlayer() const; - CALayer* animatedLayer(AnimatedPropertyID property) const; + CALayer* animatedLayer(AnimatedPropertyID) const; typedef String CloneID; // Identifier for a given clone, based on original/replica branching down the tree. static bool isReplicatedRootClone(const CloneID& cloneID) { return cloneID[0U] & 1; } typedef HashMap<CloneID, RetainPtr<CALayer> > LayerMap; LayerMap* primaryLayerClones() const { return m_structuralLayer.get() ? m_structuralLayerClones.get() : m_layerClones.get(); } - LayerMap* animatedLayerClones(AnimatedPropertyID property) const; + LayerMap* animatedLayerClones(AnimatedPropertyID) const; - bool createAnimationFromKeyframes(const KeyframeValueList&, const Animation*, const String& keyframesName, double timeOffset); - bool createTransformAnimationsFromKeyframes(const KeyframeValueList&, const Animation*, const String& keyframesName, double timeOffset, const IntSize& boxSize); + bool createAnimationFromKeyframes(const KeyframeValueList&, const Animation*, const String& animationName, double timeOffset); + bool createTransformAnimationsFromKeyframes(const KeyframeValueList&, const Animation*, const String& animationName, double timeOffset, const IntSize& boxSize); // Return autoreleased animation (use RetainPtr?) CABasicAnimation* createBasicAnimation(const Animation*, AnimatedPropertyID, bool additive); @@ -153,9 +155,9 @@ private: bool setTransformAnimationEndpoints(const KeyframeValueList&, const Animation*, CABasicAnimation*, int functionIndex, TransformOperation::OperationType, bool isMatrixAnimation, const IntSize& boxSize); bool setTransformAnimationKeyframes(const KeyframeValueList&, const Animation*, CAKeyframeAnimation*, int functionIndex, TransformOperation::OperationType, bool isMatrixAnimation, const IntSize& boxSize); - bool animationIsRunning(const String& keyframesName) const + bool animationIsRunning(const String& animationName) const { - return m_runningKeyframeAnimations.find(keyframesName) != m_runningKeyframeAnimations.end(); + return m_runningAnimations.find(animationName) != m_runningAnimations.end(); } void commitLayerChangesBeforeSublayers(); @@ -271,13 +273,13 @@ private: void ensureStructuralLayer(StructuralLayerPurpose); StructuralLayerPurpose structuralLayerPurpose() const; - void setAnimationOnLayer(CAPropertyAnimation*, AnimatedPropertyID, const String& keyframesName, int index, double timeOffset); - bool removeAnimationFromLayer(AnimatedPropertyID, const String& keyframesName, int index); - void pauseAnimationOnLayer(AnimatedPropertyID, const String& keyframesName, int index, double timeOffset); + void setCAAnimationOnLayer(CAPropertyAnimation*, AnimatedPropertyID, const String& animationName, int index, double timeOffset); + bool removeCAAnimationFromLayer(AnimatedPropertyID, const String& animationName, int index); + void pauseCAAnimationOnLayer(AnimatedPropertyID, const String& animationName, int index, double timeOffset); enum MoveOrCopy { Move, Copy }; - void moveOrCopyAnimationsForProperty(MoveOrCopy, AnimatedPropertyID property, CALayer * fromLayer, CALayer * toLayer); - static void moveOrCopyAllAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, const String& keyframesName, CALayer * fromLayer, CALayer * toLayer); + static void moveOrCopyLayerAnimation(MoveOrCopy, const String& animationIdentifier, CALayer *fromLayer, CALayer *toLayer); + void moveOrCopyAnimationsForProperty(MoveOrCopy, AnimatedPropertyID, CALayer * fromLayer, CALayer * toLayer); enum LayerChange { NoChange = 0, @@ -335,29 +337,26 @@ private: RetainPtr<CGImageRef> m_uncorrectedContentsImage; RetainPtr<CGImageRef> m_pendingContentsImage; - struct LayerAnimation { - LayerAnimation(CAPropertyAnimation* caAnim, const String& keyframesName, AnimatedPropertyID property, int index, double timeOffset) - : m_animation(caAnim) - , m_keyframesName(keyframesName) + // This represents the animation of a single property. There may be multiple transform animations for + // a single transition or keyframe animation, so index is used to distinguish these. + struct LayerPropertyAnimation { + LayerPropertyAnimation(CAPropertyAnimation* caAnimation, const String& animationName, AnimatedPropertyID property, int index, double timeOffset) + : m_animation(caAnimation) + , m_name(animationName) , m_property(property) , m_index(index) , m_timeOffset(timeOffset) { } RetainPtr<CAPropertyAnimation*> m_animation; - String m_keyframesName; + String m_name; AnimatedPropertyID m_property; int m_index; double m_timeOffset; }; - Vector<LayerAnimation> m_uncomittedAnimations; - - // Animations on the layer are identified by property + index. - typedef int AnimatedProperty; // std containers choke on the AnimatedPropertyID enum - typedef pair<AnimatedProperty, int> AnimationPair; - - HashSet<AnimatedProperty> m_transitionPropertiesToRemove; + // Uncommitted transitions and animations. + Vector<LayerPropertyAnimation> m_uncomittedAnimations; enum Action { Remove, Pause }; struct AnimationProcessingAction { @@ -367,15 +366,15 @@ private: { } Action action; - double timeOffset; // only used for pause + double timeOffset; // only used for pause }; typedef HashMap<String, AnimationProcessingAction> AnimationsToProcessMap; - AnimationsToProcessMap m_keyframeAnimationsToProcess; + AnimationsToProcessMap m_animationsToProcess; + + // Map of animation names to their associated lists of property animations, so we can remove/pause them. + typedef HashMap<String, Vector<LayerPropertyAnimation> > AnimationsMap; + AnimationsMap m_runningAnimations; - // Map of keyframe names to their associated lists of animations for running animations, so we can remove/pause them. - typedef HashMap<String, Vector<AnimationPair> > KeyframeAnimationsMap; - KeyframeAnimationsMap m_runningKeyframeAnimations; - Vector<FloatRect> m_dirtyRects; LayerChangeFlags m_uncommittedChanges; diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm index 395a691..d4cd851 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm @@ -55,6 +55,8 @@ using namespace std; namespace WebCore { +static NSString * const WebKitAnimationBeginTimeSetKey = @"WebKitAnimationBeginTimeSet"; + // The threshold width or height above which a tiled layer will be used. This should be // large enough to avoid tiled layers for most GraphicsLayers, but less than the OpenGL // texture size limit on all supported hardware. @@ -101,11 +103,8 @@ static double mediaTimeToCurrentTime(CFTimeInterval t) - (void)animationDidStart:(CAAnimation *)animation { - if (!m_graphicsLayer) - return; - - double startTime = WebCore::mediaTimeToCurrentTime([animation beginTime]); - m_graphicsLayer->client()->notifyAnimationStarted(m_graphicsLayer, startTime); + if (m_graphicsLayer) + m_graphicsLayer->animationDidStart(animation); } - (WebCore::GraphicsLayerCA*)graphicsLayer @@ -197,7 +196,7 @@ static NSValue* getTransformFunctionValue(const TransformOperation* transformOp, } #if HAVE_MODERN_QUARTZCORE -static NSString* getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType) +static NSString *getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType) { // Use literal strings to avoid link-time dependency on those symbols. switch (transformType) { @@ -247,20 +246,9 @@ static String propertyIdToString(AnimatedPropertyID property) return ""; } -static String animationIdentifier(AnimatedPropertyID property, const String& keyframesName, int index) +static String animationIdentifier(const String& animationName, AnimatedPropertyID property, int index) { - StringBuilder builder; - - builder.append(propertyIdToString(property)); - builder.append("_"); - - if (!keyframesName.isEmpty()) { - builder.append(keyframesName); - builder.append("_"); - } - builder.append("_"); - builder.append(String::number(index)); - return builder.toString(); + return animationName + String::format("_%d_%d", property, index); } static CAMediaTimingFunction* getCAMediaTimingFunction(const TimingFunction* timingFunction) @@ -550,39 +538,40 @@ void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t) noteLayerPropertyChanged(ChildrenTransformChanged); } -void GraphicsLayerCA::moveOrCopyAllAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, const String& keyframesName, CALayer *fromLayer, CALayer *toLayer) +void GraphicsLayerCA::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, CALayer *fromLayer, CALayer *toLayer) { - for (int index = 0; ; ++index) { - String animName = animationIdentifier(property, keyframesName, index); + NSString *animationID = animationIdentifier; + CAAnimation *anim = [fromLayer animationForKey:animationID]; + if (!anim) + return; - CAAnimation* anim = [fromLayer animationForKey:animName]; - if (!anim) + switch (operation) { + case Move: + [anim retain]; + [fromLayer removeAnimationForKey:animationID]; + [toLayer addAnimation:anim forKey:animationID]; + [anim release]; break; - switch (operation) { - case Move: - [anim retain]; - [fromLayer removeAnimationForKey:animName]; - [toLayer addAnimation:anim forKey:animName]; - [anim release]; - break; - - case Copy: - [toLayer addAnimation:anim forKey:animName]; - break; - } + case Copy: + [toLayer addAnimation:anim forKey:animationID]; + break; } } void GraphicsLayerCA::moveOrCopyAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, CALayer *fromLayer, CALayer *toLayer) { - // Move transitions for this property. - moveOrCopyAllAnimationsForProperty(operation, property, "", fromLayer, toLayer); - // Look for running animations affecting this property. - KeyframeAnimationsMap::const_iterator end = m_runningKeyframeAnimations.end(); - for (KeyframeAnimationsMap::const_iterator it = m_runningKeyframeAnimations.begin(); it != end; ++it) - moveOrCopyAllAnimationsForProperty(operation, property, it->first, fromLayer, toLayer); + AnimationsMap::const_iterator end = m_runningAnimations.end(); + for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) { + const Vector<LayerPropertyAnimation>& propertyAnimations = it->second; + size_t numAnimations = propertyAnimations.size(); + for (size_t i = 0; i < numAnimations; ++i) { + const LayerPropertyAnimation& currAnimation = propertyAnimations[i]; + if (currAnimation.m_property == property) + moveOrCopyLayerAnimation(operation, animationIdentifier(currAnimation.m_name, currAnimation.m_property, currAnimation.m_index), fromLayer, toLayer); + } + } } void GraphicsLayerCA::setPreserves3D(bool preserves3D) @@ -704,8 +693,10 @@ void GraphicsLayerCA::setContentsRect(const IntRect& rect) noteLayerPropertyChanged(ContentsRectChanged); } -bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset) +bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& animationName, double timeOffset) { + ASSERT(!animationName.isEmpty()); + if (forceSoftwareAnimation() || !anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2) return false; @@ -723,9 +714,9 @@ bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const Int bool createdAnimations = false; if (valueList.property() == AnimatedPropertyWebkitTransform) - createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, keyframesName, timeOffset, boxSize); + createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, timeOffset, boxSize); else - createdAnimations = createAnimationFromKeyframes(valueList, anim, keyframesName, timeOffset); + createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, timeOffset); if (createdAnimations) noteLayerPropertyChanged(AnimationChanged); @@ -733,39 +724,46 @@ bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const Int return createdAnimations; } -void GraphicsLayerCA::removeAnimationsForProperty(AnimatedPropertyID property) +void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOffset) { - if (m_transitionPropertiesToRemove.find(property) != m_transitionPropertiesToRemove.end()) + if (!animationIsRunning(animationName)) return; - m_transitionPropertiesToRemove.add(property); + AnimationsToProcessMap::iterator it = m_animationsToProcess.find(animationName); + if (it != m_animationsToProcess.end()) { + AnimationProcessingAction& processingInfo = it->second; + // If an animation is scheduled to be removed, don't change the remove to a pause. + if (processingInfo.action != Remove) + processingInfo.action = Pause; + } else + m_animationsToProcess.add(animationName, AnimationProcessingAction(Pause, timeOffset)); + noteLayerPropertyChanged(AnimationChanged); } -void GraphicsLayerCA::removeAnimationsForKeyframes(const String& animationName) +void GraphicsLayerCA::removeAnimation(const String& animationName) { if (!animationIsRunning(animationName)) return; - m_keyframeAnimationsToProcess.add(animationName, AnimationProcessingAction(Remove)); + m_animationsToProcess.add(animationName, AnimationProcessingAction(Remove)); noteLayerPropertyChanged(AnimationChanged); } -void GraphicsLayerCA::pauseAnimation(const String& keyframesName, double timeOffset) +void GraphicsLayerCA::animationDidStart(CAAnimation* caAnimation) { - if (!animationIsRunning(keyframesName)) - return; + bool hadNonZeroBeginTime = [[caAnimation valueForKey:WebKitAnimationBeginTimeSetKey] boolValue]; - AnimationsToProcessMap::iterator it = m_keyframeAnimationsToProcess.find(keyframesName); - if (it != m_keyframeAnimationsToProcess.end()) { - AnimationProcessingAction& processingInfo = it->second; - // If an animation is scheduled to be removed, don't change the remove to a pause. - if (processingInfo.action != Remove) - processingInfo.action = Pause; + double startTime; + if (hadNonZeroBeginTime) { + // We don't know what time CA used to commit the animation, so just use the current time + // (even though this will be slightly off). + startTime = WebCore::mediaTimeToCurrentTime(CACurrentMediaTime()); } else - m_keyframeAnimationsToProcess.add(keyframesName, AnimationProcessingAction(Pause, timeOffset)); + startTime = WebCore::mediaTimeToCurrentTime([caAnimation beginTime]); - noteLayerPropertyChanged(AnimationChanged); + if (m_client) + m_client->notifyAnimationStarted(this, startTime); } void GraphicsLayerCA::setContentsToImage(Image* image) @@ -1496,68 +1494,49 @@ CALayer *GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState) void GraphicsLayerCA::updateLayerAnimations() { - if (m_transitionPropertiesToRemove.size()) { - HashSet<int>::const_iterator end = m_transitionPropertiesToRemove.end(); - for (HashSet<AnimatedProperty>::const_iterator it = m_transitionPropertiesToRemove.begin(); it != end; ++it) { - AnimatedPropertyID currProperty = static_cast<AnimatedPropertyID>(*it); - // Remove all animations with this property in the key. - for (int index = 0; ; ++index) { - if (!removeAnimationFromLayer(currProperty, "", index)) - break; - } - } - - m_transitionPropertiesToRemove.clear(); - } - - if (m_keyframeAnimationsToProcess.size()) { - AnimationsToProcessMap::const_iterator end = m_keyframeAnimationsToProcess.end(); - for (AnimationsToProcessMap::const_iterator it = m_keyframeAnimationsToProcess.begin(); it != end; ++it) { - const String& currKeyframeName = it->first; - KeyframeAnimationsMap::iterator animationIt = m_runningKeyframeAnimations.find(currKeyframeName); - if (animationIt == m_runningKeyframeAnimations.end()) + if (m_animationsToProcess.size()) { + AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end(); + for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) { + const String& currAnimationName = it->first; + AnimationsMap::iterator animationIt = m_runningAnimations.find(currAnimationName); + if (animationIt == m_runningAnimations.end()) continue; const AnimationProcessingAction& processingInfo = it->second; - const Vector<AnimationPair>& animations = animationIt->second; + const Vector<LayerPropertyAnimation>& animations = animationIt->second; for (size_t i = 0; i < animations.size(); ++i) { - const AnimationPair& currPair = animations[i]; + const LayerPropertyAnimation& currAnimation = animations[i]; switch (processingInfo.action) { case Remove: - removeAnimationFromLayer(static_cast<AnimatedPropertyID>(currPair.first), currKeyframeName, currPair.second); + removeCAAnimationFromLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index); break; case Pause: - pauseAnimationOnLayer(static_cast<AnimatedPropertyID>(currPair.first), currKeyframeName, currPair.second, processingInfo.timeOffset); + pauseCAAnimationOnLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, processingInfo.timeOffset); break; } } if (processingInfo.action == Remove) - m_runningKeyframeAnimations.remove(currKeyframeName); + m_runningAnimations.remove(currAnimationName); } - m_keyframeAnimationsToProcess.clear(); + m_animationsToProcess.clear(); } size_t numAnimations; if ((numAnimations = m_uncomittedAnimations.size())) { for (size_t i = 0; i < numAnimations; ++i) { - const LayerAnimation& pendingAnimation = m_uncomittedAnimations[i]; - setAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_keyframesName, pendingAnimation.m_index, pendingAnimation.m_timeOffset); + const LayerPropertyAnimation& pendingAnimation = m_uncomittedAnimations[i]; + setCAAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_name, pendingAnimation.m_index, pendingAnimation.m_timeOffset); - if (!pendingAnimation.m_keyframesName.isEmpty()) { - // If this is a keyframe anim, we have to remember the association of keyframes name to property/index pairs, - // so we can remove the animations later if needed. - // For transitions, we can just generate animation names with property and index. - KeyframeAnimationsMap::iterator it = m_runningKeyframeAnimations.find(pendingAnimation.m_keyframesName); - if (it == m_runningKeyframeAnimations.end()) { - Vector<AnimationPair> firstPair; - firstPair.append(AnimationPair(pendingAnimation.m_property, pendingAnimation.m_index)); - m_runningKeyframeAnimations.add(pendingAnimation.m_keyframesName, firstPair); - } else { - Vector<AnimationPair>& animPairs = it->second; - animPairs.append(AnimationPair(pendingAnimation.m_property, pendingAnimation.m_index)); - } + AnimationsMap::iterator it = m_runningAnimations.find(pendingAnimation.m_name); + if (it == m_runningAnimations.end()) { + Vector<LayerPropertyAnimation> animations; + animations.append(pendingAnimation); + m_runningAnimations.add(pendingAnimation.m_name, animations); + } else { + Vector<LayerPropertyAnimation>& animations = it->second; + animations.append(pendingAnimation); } } @@ -1565,16 +1544,19 @@ void GraphicsLayerCA::updateLayerAnimations() } } -void GraphicsLayerCA::setAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedPropertyID property, const String& keyframesName, int index, double timeOffset) +void GraphicsLayerCA::setCAAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedPropertyID property, const String& animationName, int index, double timeOffset) { PlatformLayer* layer = animatedLayer(property); - [caAnim setTimeOffset:timeOffset]; - - String animationName = animationIdentifier(property, keyframesName, index); - - [layer removeAnimationForKey:animationName]; - [layer addAnimation:caAnim forKey:animationName]; + if (timeOffset) { + [caAnim setBeginTime:CACurrentMediaTime() - timeOffset]; + [caAnim setValue:[NSNumber numberWithBool:YES] forKey:WebKitAnimationBeginTimeSetKey]; + } + + NSString *animationID = animationIdentifier(animationName, property, index); + + [layer removeAnimationForKey:animationID]; + [layer addAnimation:caAnim forKey:animationID]; if (LayerMap* layerCloneMap = animatedLayerClones(property)) { LayerMap::const_iterator end = layerCloneMap->end(); @@ -1583,8 +1565,8 @@ void GraphicsLayerCA::setAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedP if (m_replicaLayer && isReplicatedRootClone(it->first)) continue; CALayer *currLayer = it->second.get(); - [currLayer removeAnimationForKey:animationName]; - [currLayer addAnimation:caAnim forKey:animationName]; + [currLayer removeAnimationForKey:animationID]; + [currLayer addAnimation:caAnim forKey:animationID]; } } } @@ -1604,16 +1586,16 @@ static void bug7311367Workaround(CALayer* transformLayer, const TransformationMa [transformLayer setTransform:caTransform]; } -bool GraphicsLayerCA::removeAnimationFromLayer(AnimatedPropertyID property, const String& keyframesName, int index) +bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index) { PlatformLayer* layer = animatedLayer(property); - String animationName = animationIdentifier(property, keyframesName, index); + NSString *animationID = animationIdentifier(animationName, property, index); - if (![layer animationForKey:animationName]) + if (![layer animationForKey:animationID]) return false; - [layer removeAnimationForKey:animationName]; + [layer removeAnimationForKey:animationID]; bug7311367Workaround(m_structuralLayer.get(), m_transform); if (LayerMap* layerCloneMap = animatedLayerClones(property)) { @@ -1624,7 +1606,7 @@ bool GraphicsLayerCA::removeAnimationFromLayer(AnimatedPropertyID property, cons continue; CALayer *currLayer = it->second.get(); - [currLayer removeAnimationForKey:animationName]; + [currLayer removeAnimationForKey:animationID]; } } return true; @@ -1644,15 +1626,18 @@ static void copyAnimationProperties(CAPropertyAnimation* from, CAPropertyAnimati #if HAVE_MODERN_QUARTZCORE [to setValueFunction:[from valueFunction]]; #endif + + if (id object = [from valueForKey:WebKitAnimationBeginTimeSetKey]) + [to setValue:object forKey:WebKitAnimationBeginTimeSetKey]; } -void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, const String& keyframesName, int index, double timeOffset) +void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, double timeOffset) { PlatformLayer* layer = animatedLayer(property); - String animationName = animationIdentifier(property, keyframesName, index); + NSString *animationID = animationIdentifier(animationName, property, index); - CAAnimation* caAnim = [layer animationForKey:animationName]; + CAAnimation *caAnim = [layer animationForKey:animationID]; if (!caAnim) return; @@ -1679,7 +1664,7 @@ void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, const S [pausedAnim setSpeed:0]; [pausedAnim setTimeOffset:timeOffset]; - [layer addAnimation:pausedAnim forKey:animationName]; // This will replace the running animation. + [layer addAnimation:pausedAnim forKey:animationID]; // This will replace the running animation. // Pause the animations on the clones too. if (LayerMap* layerCloneMap = animatedLayerClones(property)) { @@ -1689,7 +1674,7 @@ void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, const S if (m_replicaLayer && isReplicatedRootClone(it->first)) continue; CALayer *currLayer = it->second.get(); - [currLayer addAnimation:pausedAnim forKey:animationName]; + [currLayer addAnimation:pausedAnim forKey:animationID]; } } } @@ -1726,7 +1711,7 @@ void GraphicsLayerCA::updateContentsNeedsDisplay() [m_contentsLayer.get() setNeedsDisplay]; } -bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& keyframesName, double timeOffset) +bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset) { ASSERT(valueList.property() != AnimatedPropertyWebkitTransform); @@ -1752,14 +1737,14 @@ bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valu if (!valuesOK) return false; - m_uncomittedAnimations.append(LayerAnimation(caAnimation, keyframesName, valueList.property(), animationIndex, timeOffset)); + m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset)); END_BLOCK_OBJC_EXCEPTIONS; return true; } -bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& keyframesName, double timeOffset, const IntSize& boxSize) +bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const IntSize& boxSize) { ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); @@ -1810,7 +1795,7 @@ bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValue if (!validMatrices) break; - m_uncomittedAnimations.append(LayerAnimation(caAnimation, keyframesName, valueList.property(), animationIndex, timeOffset)); + m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset)); } END_BLOCK_OBJC_EXCEPTIONS; @@ -1844,7 +1829,7 @@ void GraphicsLayerCA::setupAnimation(CAPropertyAnimation* propertyAnim, const An else if (anim->direction() == Animation::AnimationDirectionAlternate) repeatCount /= 2; - NSString* fillMode = 0; + NSString *fillMode = 0; switch (anim->fillMode()) { case AnimationFillModeNone: fillMode = kCAFillModeForwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash. @@ -1983,7 +1968,7 @@ bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& va [basicAnim setToValue:toValue]; #if HAVE_MODERN_QUARTZCORE - if (NSString* valueFunctionName = getValueFunctionNameForTransformOperation(transformOp)) + if (NSString *valueFunctionName = getValueFunctionNameForTransformOperation(transformOp)) [basicAnim setValueFunction:[CAValueFunction functionWithName:valueFunctionName]]; #endif @@ -2028,7 +2013,7 @@ bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& va [keyframeAnim setTimingFunctions:timingFunctions.get()]; #if HAVE_MODERN_QUARTZCORE - if (NSString* valueFunctionName = getValueFunctionNameForTransformOperation(transformOpType)) + if (NSString *valueFunctionName = getValueFunctionNameForTransformOperation(transformOpType)) [keyframeAnim setValueFunction:[CAValueFunction functionWithName:valueFunctionName]]; #endif return true; @@ -2045,7 +2030,7 @@ void GraphicsLayerCA::suspendAnimations(double time) LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { CALayer *currLayer = it->second.get(); - [currLayer setSpeed:0 ]; + [currLayer setSpeed:0]; [currLayer setTimeOffset:t]; } } diff --git a/WebCore/platform/graphics/mac/ImageMac.mm b/WebCore/platform/graphics/mac/ImageMac.mm index 96b93be..6ad3080 100644 --- a/WebCore/platform/graphics/mac/ImageMac.mm +++ b/WebCore/platform/graphics/mac/ImageMac.mm @@ -27,7 +27,6 @@ #import "BitmapImage.h" #import "FloatRect.h" -#import "FoundationExtras.h" #import "GraphicsContext.h" #import "PlatformString.h" #import "SharedBuffer.h" diff --git a/WebCore/platform/graphics/qt/ContextShadowQt.cpp b/WebCore/platform/graphics/qt/ContextShadowQt.cpp new file mode 100644 index 0000000..342e027 --- /dev/null +++ b/WebCore/platform/graphics/qt/ContextShadowQt.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2010 Sencha, 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ContextShadow.h" + +#include <QPainter> +#include <QTimerEvent> + +namespace WebCore { + +// ContextShadow needs a scratch image as the buffer for the blur filter. +// Instead of creating and destroying the buffer for every operation, +// we create a buffer which will be automatically purged via a timer. + +class ShadowBuffer: public QObject { +public: + ShadowBuffer(QObject* parent = 0); + + QImage* scratchImage(const QSize& size); + + void schedulePurge(); + +protected: + void timerEvent(QTimerEvent* event); + +private: + QImage image; + int timerId; +}; + +ShadowBuffer::ShadowBuffer(QObject* parent) + : QObject(parent) + , timerId(0) +{ +} + +QImage* ShadowBuffer::scratchImage(const QSize& size) +{ + int width = size.width(); + int height = size.height(); + + // We do not need to recreate the buffer if the buffer is reasonably + // larger than the requested size. However, if the requested size is + // much smaller than our buffer, reduce our buffer so that we will not + // keep too many allocated pixels for too long. + if (!image.isNull() && (image.width() > width) && (image.height() > height)) + if (((2 * width) > image.width()) && ((2 * height) > image.height())) { + image.fill(Qt::transparent); + return ℑ + } + + // Round to the nearest 32 pixels so we do not grow the buffer everytime + // there is larger request by 1 pixel. + width = (1 + (width >> 5)) << 5; + height = (1 + (height >> 5)) << 5; + + image = QImage(width, height, QImage::Format_ARGB32_Premultiplied); + image.fill(Qt::transparent); + return ℑ +} + +void ShadowBuffer::schedulePurge() +{ + static const double BufferPurgeDelay = 2; // seconds + killTimer(timerId); + timerId = startTimer(BufferPurgeDelay * 1000); +} + +void ShadowBuffer::timerEvent(QTimerEvent* event) +{ + if (event->timerId() == timerId) { + killTimer(timerId); + image = QImage(); + } + QObject::timerEvent(event); +} + +Q_GLOBAL_STATIC(ShadowBuffer, scratchShadowBuffer) + +PlatformContext ContextShadow::beginShadowLayer(PlatformContext p, const FloatRect& layerArea) +{ + QRect clipRect; + if (p->hasClipping()) +#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0) + clipRect = p->clipBoundingRect().toAlignedRect(); +#else + clipRect = p->clipRegion().boundingRect(); +#endif + else + clipRect = p->transform().inverted().mapRect(p->window()); + + calculateLayerBoundingRect(layerArea, IntRect(clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height())); + + // Don't paint if we are totally outside the clip region. + if (m_layerRect.isEmpty()) + return 0; + + ShadowBuffer* shadowBuffer = scratchShadowBuffer(); + QImage* shadowImage = shadowBuffer->scratchImage(m_layerRect.size()); + m_layerImage = QImage(*shadowImage); + + m_layerContext = new QPainter; + m_layerContext->begin(&m_layerImage); + m_layerContext->setFont(p->font()); + m_layerContext->translate(m_offset.width(), m_offset.height()); + + // The origin is now the top left corner of the scratch image. + m_layerContext->translate(-m_layerRect.x(), -m_layerRect.y()); + + return m_layerContext; +} + +void ContextShadow::endShadowLayer(PlatformContext p) +{ + m_layerContext->end(); + delete m_layerContext; + m_layerContext = 0; + + if (m_type == BlurShadow) { + blurLayerImage(m_layerImage.bits(), IntSize(m_layerImage.width(), m_layerImage.height()), + m_layerImage.bytesPerLine()); + + // "Colorize" with the right shadow color. + QPainter p(&m_layerImage); + p.setCompositionMode(QPainter::CompositionMode_SourceIn); + p.fillRect(m_layerImage.rect(), m_color.rgb()); + p.end(); + } + + p->drawImage(m_layerRect.topLeft(), m_layerImage); + scratchShadowBuffer()->schedulePurge(); +} + +} diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp index 2b246de..e7566eb 100644 --- a/WebCore/platform/graphics/qt/FontQt.cpp +++ b/WebCore/platform/graphics/qt/FontQt.cpp @@ -125,37 +125,38 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float ContextShadow* ctxShadow = ctx->contextShadow(); - if (ctxShadow->type != ContextShadow::NoShadow) { + if (ctxShadow->m_type != ContextShadow::NoShadow) { qreal dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0; - if (ctxShadow->offset.x() > 0) - dx2 = ctxShadow->offset.x(); + if (ctxShadow->offset().x() > 0) + dx2 = ctxShadow->offset().x(); else - dx1 = -ctxShadow->offset.x(); - if (ctxShadow->offset.y() > 0) - dy2 = ctxShadow->offset.y(); + dx1 = -ctxShadow->offset().x(); + if (ctxShadow->offset().y() > 0) + dy2 = ctxShadow->offset().y(); else - dy1 = -ctxShadow->offset.y(); + dy1 = -ctxShadow->offset().y(); // expand the clip rect to include the text shadow as well clip.adjust(dx1, dx2, dy1, dy2); - clip.adjust(-ctxShadow->blurRadius, -ctxShadow->blurRadius, ctxShadow->blurRadius, ctxShadow->blurRadius); + clip.adjust(-ctxShadow->m_blurRadius, -ctxShadow->m_blurRadius, ctxShadow->m_blurRadius, ctxShadow->m_blurRadius); } p->save(); p->setClipRect(clip.toRect(), Qt::IntersectClip); pt.setY(pt.y() - ascent); - if (ctxShadow->type != ContextShadow::NoShadow) { + if (ctxShadow->m_type != ContextShadow::NoShadow) { ContextShadow* ctxShadow = ctx->contextShadow(); - if (ctxShadow->type != ContextShadow::BlurShadow) { + if (ctxShadow->m_type != ContextShadow::BlurShadow) { p->save(); - p->setPen(ctxShadow->color); - p->translate(ctxShadow->offset); + p->setPen(ctxShadow->m_color); + p->translate(ctxShadow->offset()); line.draw(p, pt); p->restore(); } else { QPainter* shadowPainter = ctxShadow->beginShadowLayer(p, boundingRect); if (shadowPainter) { // Since it will be blurred anyway, we don't care about render hints. - shadowPainter->setPen(ctxShadow->color); + shadowPainter->setFont(p->font()); + shadowPainter->setPen(ctxShadow->m_color); line.draw(shadowPainter, pt); ctxShadow->endShadowLayer(p); } @@ -181,12 +182,12 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float if (!isComplexText && !(ctx->textDrawingMode() & cTextStroke)) flags |= Qt::TextBypassShaping; #endif - if (ctx->contextShadow()->type != ContextShadow::NoShadow) { + if (ctx->contextShadow()->m_type != ContextShadow::NoShadow) { ContextShadow* ctxShadow = ctx->contextShadow(); - if (ctxShadow->type != ContextShadow::BlurShadow) { + if (ctxShadow->m_type != ContextShadow::BlurShadow) { p->save(); - p->setPen(ctxShadow->color); - p->translate(ctxShadow->offset); + p->setPen(ctxShadow->m_color); + p->translate(ctxShadow->offset()); p->drawText(pt, string, flags, run.padding()); p->restore(); } else { @@ -196,7 +197,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float if (shadowPainter) { // Since it will be blurred anyway, we don't care about render hints. shadowPainter->setFont(p->font()); - shadowPainter->setPen(ctxShadow->color); + shadowPainter->setPen(ctxShadow->m_color); shadowPainter->drawText(pt, string, flags, run.padding()); ctxShadow->endShadowLayer(p); } @@ -205,12 +206,13 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float if (ctx->textDrawingMode() & cTextStroke) { QPainterPath path; path.addText(pt, font, string); - p->setPen(textStrokePen); - p->strokePath(path, p->pen()); + p->strokePath(path, textStrokePen); } if (ctx->textDrawingMode() & cTextFill) { + QPen previousPen = p->pen(); p->setPen(textFillPen); p->drawText(pt, string, flags, run.padding()); + p->setPen(previousPen); } } diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 5a29ad4..7e4af40 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -201,7 +201,7 @@ public: bool hasShadow() const { - return shadow.type != ContextShadow::NoShadow; + return shadow.m_type != ContextShadow::NoShadow; } QRectF clipBoundingRect() const @@ -440,9 +440,9 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp if (m_data->hasShadow()) { p->save(); - p->translate(m_data->shadow.offset); + p->translate(m_data->shadow.offset()); QPen pen(p->pen()); - pen.setColor(m_data->shadow.color); + pen.setColor(m_data->shadow.m_color); p->setPen(pen); p->drawArc(rect, startAngle, angleSpan); p->restore(); @@ -470,12 +470,12 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points p->setRenderHint(QPainter::Antialiasing, shouldAntialias); if (m_data->hasShadow()) { p->save(); - p->translate(m_data->shadow.offset); + p->translate(m_data->shadow.offset()); if (p->brush().style() != Qt::NoBrush) - p->setBrush(QBrush(m_data->shadow.color)); + p->setBrush(QBrush(m_data->shadow.m_color)); QPen pen(p->pen()); if (pen.style() != Qt::NoPen) { - pen.setColor(m_data->shadow.color); + pen.setColor(m_data->shadow.m_color); p->setPen(pen); } p->drawConvexPolygon(polygon); @@ -519,9 +519,9 @@ void GraphicsContext::fillPath() path.setFillRule(toQtFillRule(fillRule())); if (m_data->hasShadow()) { - p->translate(m_data->shadow.offset); - p->fillPath(path, m_data->shadow.color); - p->translate(-m_data->shadow.offset); + p->translate(m_data->shadow.offset()); + p->fillPath(path, QColor(m_data->shadow.m_color)); + p->translate(-m_data->shadow.offset()); } if (m_common->state.fillPattern) { AffineTransform affine; @@ -547,11 +547,11 @@ void GraphicsContext::strokePath() path.setFillRule(toQtFillRule(fillRule())); if (m_data->hasShadow()) { - p->translate(m_data->shadow.offset); + p->translate(m_data->shadow.offset()); QPen shadowPen(pen); - shadowPen.setColor(m_data->shadow.color); + shadowPen.setColor(m_data->shadow.m_color); p->strokePath(path, shadowPen); - p->translate(-m_data->shadow.offset); + p->translate(-m_data->shadow.offset()); } if (m_common->state.strokePattern) { AffineTransform affine; @@ -653,7 +653,7 @@ void GraphicsContext::fillRect(const FloatRect& rect) if (shadowPainter) { drawRepeatPattern(shadowPainter, image, normalizedRect, m_common->state.fillPattern->repeatX(), m_common->state.fillPattern->repeatY()); shadowPainter->setCompositionMode(QPainter::CompositionMode_SourceIn); - shadowPainter->fillRect(normalizedRect, shadow->color); + shadowPainter->fillRect(normalizedRect, shadow->m_color); shadow->endShadowLayer(p); } drawRepeatPattern(p, image, normalizedRect, m_common->state.fillPattern->repeatX(), m_common->state.fillPattern->repeatY()); @@ -664,13 +664,13 @@ void GraphicsContext::fillRect(const FloatRect& rect) if (shadowPainter) { shadowPainter->fillRect(normalizedRect, brush); shadowPainter->setCompositionMode(QPainter::CompositionMode_SourceIn); - shadowPainter->fillRect(normalizedRect, shadow->color); + shadowPainter->fillRect(normalizedRect, shadow->m_color); shadow->endShadowLayer(p); } p->fillRect(normalizedRect, brush); } else { if (m_data->hasShadow()) { - if (shadow->type == ContextShadow::BlurShadow) { + if (shadow->m_type == ContextShadow::BlurShadow) { QPainter* shadowPainter = shadow->beginShadowLayer(p, normalizedRect); if (shadowPainter) { shadowPainter->fillRect(normalizedRect, p->brush()); @@ -679,9 +679,9 @@ void GraphicsContext::fillRect(const FloatRect& rect) } else { // Solid rectangle fill with no blur shadow can be done faster // without using the shadow layer at all. - QColor shadowColor = shadow->color; + QColor shadowColor = shadow->m_color; shadowColor.setAlphaF(shadowColor.alphaF() * p->brush().color().alphaF()); - p->fillRect(normalizedRect.translated(shadow->offset), shadowColor); + p->fillRect(normalizedRect.translated(shadow->offset()), shadowColor); } } p->fillRect(normalizedRect, p->brush()); @@ -701,14 +701,14 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS if (m_data->hasShadow()) { ContextShadow* shadow = contextShadow(); - if (shadow->type != ContextShadow::BlurShadow) { + if (shadow->m_type != ContextShadow::BlurShadow) { // We do not need any layer for simple shadow. - p->fillRect(normalizedRect.translated(shadow->offset), shadow->color); + p->fillRect(normalizedRect.translated(shadow->offset()), shadow->m_color); } else { QPainter* shadowPainter = shadow->beginShadowLayer(p, normalizedRect); if (shadowPainter) { shadowPainter->setCompositionMode(QPainter::CompositionMode_Source); - shadowPainter->fillRect(normalizedRect, shadow->color); + shadowPainter->fillRect(normalizedRect, shadow->m_color); shadow->endShadowLayer(p); } } @@ -725,9 +725,9 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef Path path = Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight); QPainter* p = m_data->p(); if (m_data->hasShadow()) { - p->translate(m_data->shadow.offset); - p->fillPath(path.platformPath(), m_data->shadow.color); - p->translate(-m_data->shadow.offset); + p->translate(m_data->shadow.offset()); + p->fillPath(path.platformPath(), QColor(m_data->shadow.m_color)); + p->translate(-m_data->shadow.offset()); } p->fillPath(path.platformPath(), QColor(color)); } @@ -884,9 +884,9 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const // Meaning that this graphics context is associated with a CanvasRenderingContext // We flip the height since CG and HTML5 Canvas have opposite Y axis m_common->state.shadowOffset = FloatSize(size.width(), -size.height()); - m_data->shadow = ContextShadow(color, blur, size.width(), -size.height()); + m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), -size.height())); } else { - m_data->shadow = ContextShadow(color, blur, size.width(), size.height()); + m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height())); } } @@ -1002,7 +1002,7 @@ void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) pattern.append(dashes[i % dashLength] / penWidth); pen.setDashPattern(pattern); - pen.setDashOffset(dashOffset); + pen.setDashOffset(dashOffset / penWidth); } else pen.setStyle(Qt::SolidLine); p->setPen(pen); diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp index 08eb816..b881036 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp @@ -51,7 +51,7 @@ using namespace Phonon; #define LOG_MEDIAOBJECT() (LOG(Media, "%s", debugMediaObject(this, *m_mediaObject).constData())) #if !LOG_DISABLED -static QByteArray debugMediaObject(WebCore::MediaPlayerPrivate* mediaPlayer, const MediaObject& mediaObject) +static QByteArray debugMediaObject(WebCore::MediaPlayerPrivatePhonon* mediaPlayer, const MediaObject& mediaObject) { QByteArray byteArray; QTextStream stream(&byteArray); @@ -84,7 +84,7 @@ using namespace WTF; namespace WebCore { -MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) +MediaPlayerPrivatePhonon::MediaPlayerPrivatePhonon(MediaPlayer* player) : m_player(player) , m_networkState(MediaPlayer::Empty) , m_readyState(MediaPlayer::HaveNothing) @@ -118,19 +118,19 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) connect(m_mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64))); } -MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) +MediaPlayerPrivateInterface* MediaPlayerPrivatePhonon::create(MediaPlayer* player) { - return new MediaPlayerPrivate(player); + return new MediaPlayerPrivatePhonon(player); } -void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar) +void MediaPlayerPrivatePhonon::registerMediaEngine(MediaEngineRegistrar registrar) { if (isAvailable()) registrar(create, getSupportedTypes, supportsType); } -MediaPlayerPrivate::~MediaPlayerPrivate() +MediaPlayerPrivatePhonon::~MediaPlayerPrivatePhonon() { LOG(Media, "MediaPlayerPrivatePhonon::dtor deleting videowidget"); m_videoWidget->close(); @@ -146,7 +146,7 @@ MediaPlayerPrivate::~MediaPlayerPrivate() m_mediaObject = 0; } -HashSet<String>& MediaPlayerPrivate::supportedTypesCache() +HashSet<String>& MediaPlayerPrivatePhonon::supportedTypesCache() { static HashSet<String> supportedTypes; if (!supportedTypes.isEmpty()) @@ -190,12 +190,12 @@ HashSet<String>& MediaPlayerPrivate::supportedTypesCache() return supportedTypes; } -void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types) +void MediaPlayerPrivatePhonon::getSupportedTypes(HashSet<String>& types) { types = supportedTypesCache(); } -MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs) +MediaPlayer::SupportsType MediaPlayerPrivatePhonon::supportsType(const String& type, const String& codecs) { if (type.isEmpty()) return MediaPlayer::IsNotSupported; @@ -205,14 +205,14 @@ MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, c return MediaPlayer::IsNotSupported; } -bool MediaPlayerPrivate::hasVideo() const +bool MediaPlayerPrivatePhonon::hasVideo() const { bool hasVideo = m_mediaObject->hasVideo(); LOG(Media, "MediaPlayerPrivatePhonon::hasVideo() -> %s", hasVideo ? "true" : "false"); return hasVideo; } -bool MediaPlayerPrivate::hasAudio() const +bool MediaPlayerPrivatePhonon::hasAudio() const { // FIXME: Phonon::MediaObject does not have such a hasAudio() function bool hasAudio = true; @@ -220,7 +220,7 @@ bool MediaPlayerPrivate::hasAudio() const return hasAudio; } -void MediaPlayerPrivate::load(const String& url) +void MediaPlayerPrivatePhonon::load(const String& url) { LOG(Media, "MediaPlayerPrivatePhonon::load(\"%s\")", url.utf8().data()); @@ -241,33 +241,33 @@ void MediaPlayerPrivate::load(const String& url) setVisible(m_player->visible()); } -void MediaPlayerPrivate::cancelLoad() +void MediaPlayerPrivatePhonon::cancelLoad() { notImplemented(); } -void MediaPlayerPrivate::play() +void MediaPlayerPrivatePhonon::play() { LOG(Media, "MediaPlayerPrivatePhonon::play()"); m_mediaObject->play(); } -void MediaPlayerPrivate::pause() +void MediaPlayerPrivatePhonon::pause() { LOG(Media, "MediaPlayerPrivatePhonon::pause()"); m_mediaObject->pause(); } -bool MediaPlayerPrivate::paused() const +bool MediaPlayerPrivatePhonon::paused() const { bool paused = m_mediaObject->state() == Phonon::PausedState; LOG(Media, "MediaPlayerPrivatePhonon::paused() --> %s", paused ? "true" : "false"); return paused; } -void MediaPlayerPrivate::seek(float position) +void MediaPlayerPrivatePhonon::seek(float position) { LOG(Media, "MediaPlayerPrivatePhonon::seek(%f)", position); @@ -280,12 +280,12 @@ void MediaPlayerPrivate::seek(float position) m_mediaObject->seek(position * 1000.0f); } -bool MediaPlayerPrivate::seeking() const +bool MediaPlayerPrivatePhonon::seeking() const { return false; } -float MediaPlayerPrivate::duration() const +float MediaPlayerPrivatePhonon::duration() const { if (m_readyState < MediaPlayer::HaveMetadata) return 0.0f; @@ -299,7 +299,7 @@ float MediaPlayerPrivate::duration() const return duration; } -float MediaPlayerPrivate::currentTime() const +float MediaPlayerPrivatePhonon::currentTime() const { float currentTime = m_mediaObject->currentTime() / 1000.0f; @@ -307,48 +307,48 @@ float MediaPlayerPrivate::currentTime() const return currentTime; } -PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const +PassRefPtr<TimeRanges> MediaPlayerPrivatePhonon::buffered() const { notImplemented(); return TimeRanges::create(); } -float MediaPlayerPrivate::maxTimeSeekable() const +float MediaPlayerPrivatePhonon::maxTimeSeekable() const { notImplemented(); return 0.0f; } -unsigned MediaPlayerPrivate::bytesLoaded() const +unsigned MediaPlayerPrivatePhonon::bytesLoaded() const { notImplemented(); return 0; } -unsigned MediaPlayerPrivate::totalBytes() const +unsigned MediaPlayerPrivatePhonon::totalBytes() const { //notImplemented(); return 0; } -void MediaPlayerPrivate::setRate(float) +void MediaPlayerPrivatePhonon::setRate(float) { notImplemented(); } -void MediaPlayerPrivate::setVolume(float volume) +void MediaPlayerPrivatePhonon::setVolume(float volume) { LOG(Media, "MediaPlayerPrivatePhonon::setVolume()"); m_audioOutput->setVolume(volume); } -void MediaPlayerPrivate::setMuted(bool muted) +void MediaPlayerPrivatePhonon::setMuted(bool muted) { LOG(Media, "MediaPlayerPrivatePhonon::setMuted()"); m_audioOutput->setMuted(muted); } -MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const +MediaPlayer::NetworkState MediaPlayerPrivatePhonon::networkState() const { const QMetaObject* metaObj = this->metaObject(); QMetaEnum networkStates = metaObj->enumerator(metaObj->indexOfEnumerator("NetworkState")); @@ -356,7 +356,7 @@ MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const return m_networkState; } -MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const +MediaPlayer::ReadyState MediaPlayerPrivatePhonon::readyState() const { const QMetaObject* metaObj = this->metaObject(); QMetaEnum readyStates = metaObj->enumerator(metaObj->indexOfEnumerator("ReadyState")); @@ -364,7 +364,7 @@ MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const return m_readyState; } -void MediaPlayerPrivate::updateStates() +void MediaPlayerPrivatePhonon::updateStates() { MediaPlayer::NetworkState oldNetworkState = m_networkState; MediaPlayer::ReadyState oldReadyState = m_readyState; @@ -412,7 +412,7 @@ void MediaPlayerPrivate::updateStates() } } -void MediaPlayerPrivate::setVisible(bool visible) +void MediaPlayerPrivatePhonon::setVisible(bool visible) { m_isVisible = visible; LOG(Media, "MediaPlayerPrivatePhonon::setVisible(%s)", visible ? "true" : "false"); @@ -420,7 +420,7 @@ void MediaPlayerPrivate::setVisible(bool visible) m_videoWidget->setVisible(m_isVisible); } -void MediaPlayerPrivate::setSize(const IntSize& newSize) +void MediaPlayerPrivatePhonon::setSize(const IntSize& newSize) { if (!m_videoWidget) return; @@ -434,7 +434,7 @@ void MediaPlayerPrivate::setSize(const IntSize& newSize) m_videoWidget->resize(newSize.width(), newSize.height()); } -IntSize MediaPlayerPrivate::naturalSize() const +IntSize MediaPlayerPrivatePhonon::naturalSize() const { if (!hasVideo()) { LOG(Media, "MediaPlayerPrivatePhonon::naturalSize() -> %dx%d", @@ -455,7 +455,7 @@ IntSize MediaPlayerPrivate::naturalSize() const return naturalSize; } -bool MediaPlayerPrivate::eventFilter(QObject* obj, QEvent* event) +bool MediaPlayerPrivatePhonon::eventFilter(QObject* obj, QEvent* event) { if (event->type() == QEvent::UpdateRequest) m_player->repaint(); @@ -463,7 +463,7 @@ bool MediaPlayerPrivate::eventFilter(QObject* obj, QEvent* event) return QObject::eventFilter(obj, event); } -void MediaPlayerPrivate::paint(GraphicsContext* graphicsContect, const IntRect& rect) +void MediaPlayerPrivatePhonon::paint(GraphicsContext* graphicsContect, const IntRect& rect) { if (graphicsContect->paintingDisabled()) return; @@ -481,7 +481,7 @@ void MediaPlayerPrivate::paint(GraphicsContext* graphicsContect, const IntRect& // ====================== Phonon::MediaObject signals ====================== -void MediaPlayerPrivate::stateChanged(Phonon::State newState, Phonon::State oldState) +void MediaPlayerPrivatePhonon::stateChanged(Phonon::State newState, Phonon::State oldState) { const QMetaObject* metaObj = this->metaObject(); QMetaEnum phononStates = metaObj->enumerator(metaObj->indexOfEnumerator("PhononState")); @@ -491,48 +491,48 @@ void MediaPlayerPrivate::stateChanged(Phonon::State newState, Phonon::State oldS updateStates(); } -void MediaPlayerPrivate::metaDataChanged() +void MediaPlayerPrivatePhonon::metaDataChanged() { LOG(Media, "MediaPlayerPrivatePhonon::metaDataChanged()"); LOG_MEDIAOBJECT(); } -void MediaPlayerPrivate::seekableChanged(bool) +void MediaPlayerPrivatePhonon::seekableChanged(bool) { notImplemented(); LOG_MEDIAOBJECT(); } -void MediaPlayerPrivate::hasVideoChanged(bool hasVideo) +void MediaPlayerPrivatePhonon::hasVideoChanged(bool hasVideo) { LOG(Media, "MediaPlayerPrivatePhonon::hasVideoChanged(%s)", hasVideo ? "true" : "false"); } -void MediaPlayerPrivate::bufferStatus(int) +void MediaPlayerPrivatePhonon::bufferStatus(int) { notImplemented(); LOG_MEDIAOBJECT(); } -void MediaPlayerPrivate::finished() +void MediaPlayerPrivatePhonon::finished() { notImplemented(); LOG_MEDIAOBJECT(); } -void MediaPlayerPrivate::currentSourceChanged(const Phonon::MediaSource&) +void MediaPlayerPrivatePhonon::currentSourceChanged(const Phonon::MediaSource&) { notImplemented(); LOG_MEDIAOBJECT(); } -void MediaPlayerPrivate::aboutToFinish() +void MediaPlayerPrivatePhonon::aboutToFinish() { notImplemented(); LOG_MEDIAOBJECT(); } -void MediaPlayerPrivate::totalTimeChanged(qint64 totalTime) +void MediaPlayerPrivatePhonon::totalTimeChanged(qint64 totalTime) { #if OS(WINDOWS) LOG(Media, "MediaPlayerPrivatePhonon::totalTimeChanged(%I64d)", totalTime); diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h index ff6a01c..d793675 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h @@ -40,13 +40,13 @@ QT_END_NAMESPACE namespace WebCore { - class MediaPlayerPrivate : public QObject, public MediaPlayerPrivateInterface { + class MediaPlayerPrivatePhonon : public QObject, public MediaPlayerPrivateInterface { Q_OBJECT public: static void registerMediaEngine(MediaEngineRegistrar); - ~MediaPlayerPrivate(); + ~MediaPlayerPrivatePhonon(); // These enums are used for debugging Q_ENUMS(ReadyState NetworkState PhononState) @@ -127,7 +127,7 @@ namespace WebCore { void totalTimeChanged(qint64); private: - MediaPlayerPrivate(MediaPlayer*); + MediaPlayerPrivatePhonon(MediaPlayer*); static MediaPlayerPrivateInterface* create(MediaPlayer* player); static void getSupportedTypes(HashSet<String>&); diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp index 1bf1a3d..1a31d1e 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -53,17 +53,17 @@ using namespace WTF; namespace WebCore { -MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) +MediaPlayerPrivateInterface* MediaPlayerPrivateQt::create(MediaPlayer* player) { - return new MediaPlayerPrivate(player); + return new MediaPlayerPrivateQt(player); } -void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar) +void MediaPlayerPrivateQt::registerMediaEngine(MediaEngineRegistrar registrar) { registrar(create, getSupportedTypes, supportsType); } -void MediaPlayerPrivate::getSupportedTypes(HashSet<String> &supported) +void MediaPlayerPrivateQt::getSupportedTypes(HashSet<String> &supported) { QStringList types = QMediaPlayer::supportedMimeTypes(); @@ -74,7 +74,7 @@ void MediaPlayerPrivate::getSupportedTypes(HashSet<String> &supported) } } -MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& mime, const String& codec) +MediaPlayer::SupportsType MediaPlayerPrivateQt::supportsType(const String& mime, const String& codec) { if (!mime.startsWith("audio/") && !mime.startsWith("video/")) return MediaPlayer::IsNotSupported; @@ -85,8 +85,8 @@ MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& mime, c return MediaPlayer::MayBeSupported; } -MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) - : m_player(player) +MediaPlayerPrivateQt::MediaPlayerPrivateQt(MediaPlayer* player) + : m_webCorePlayer(player) , m_mediaPlayer(new QMediaPlayer) , m_mediaPlayerControl(0) , m_videoItem(new QGraphicsVideoItem) @@ -132,23 +132,23 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) } } -MediaPlayerPrivate::~MediaPlayerPrivate() +MediaPlayerPrivateQt::~MediaPlayerPrivateQt() { delete m_mediaPlayer; delete m_videoScene; } -bool MediaPlayerPrivate::hasVideo() const +bool MediaPlayerPrivateQt::hasVideo() const { return m_mediaPlayer->isVideoAvailable(); } -bool MediaPlayerPrivate::hasAudio() const +bool MediaPlayerPrivateQt::hasAudio() const { return true; } -void MediaPlayerPrivate::load(const String& url) +void MediaPlayerPrivateQt::load(const String& url) { m_mediaUrl = url; @@ -162,25 +162,25 @@ void MediaPlayerPrivate::load(const String& url) commitLoad(url); } -void MediaPlayerPrivate::commitLoad(const String& url) +void MediaPlayerPrivateQt::commitLoad(const String& url) { // We are now loading if (m_networkState != MediaPlayer::Loading) { m_networkState = MediaPlayer::Loading; - m_player->networkStateChanged(); + m_webCorePlayer->networkStateChanged(); } // And we don't have any data yet if (m_readyState != MediaPlayer::HaveNothing) { m_readyState = MediaPlayer::HaveNothing; - m_player->readyStateChanged(); + m_webCorePlayer->readyStateChanged(); } const QUrl rUrl = QUrl(QString(url)); const QString scheme = rUrl.scheme().toLower(); // Grab the client media element - HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_player->mediaPlayerClient()); + HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient()); // Construct the media content with a network request if the resource is http[s] if (scheme == "http" || scheme == "https") { @@ -236,7 +236,7 @@ void MediaPlayerPrivate::commitLoad(const String& url) m_mediaPlayer->play(); } -void MediaPlayerPrivate::resumeLoad() +void MediaPlayerPrivateQt::resumeLoad() { m_delayingLoad = false; @@ -244,36 +244,36 @@ void MediaPlayerPrivate::resumeLoad() commitLoad(m_mediaUrl); } -void MediaPlayerPrivate::cancelLoad() +void MediaPlayerPrivateQt::cancelLoad() { m_mediaPlayer->setMedia(QMediaContent()); updateStates(); } -void MediaPlayerPrivate::prepareToPlay() +void MediaPlayerPrivateQt::prepareToPlay() { if (m_mediaPlayer->media().isNull() || m_delayingLoad) resumeLoad(); } -void MediaPlayerPrivate::play() +void MediaPlayerPrivateQt::play() { if (m_mediaPlayer->state() != QMediaPlayer::PlayingState) m_mediaPlayer->play(); } -void MediaPlayerPrivate::pause() +void MediaPlayerPrivateQt::pause() { if (m_mediaPlayer->state() == QMediaPlayer::PlayingState) m_mediaPlayer->pause(); } -bool MediaPlayerPrivate::paused() const +bool MediaPlayerPrivateQt::paused() const { return (m_mediaPlayer->state() != QMediaPlayer::PlayingState); } -void MediaPlayerPrivate::seek(float position) +void MediaPlayerPrivateQt::seek(float position) { if (!m_mediaPlayer->isSeekable()) return; @@ -309,12 +309,12 @@ void MediaPlayerPrivate::seek(float position) } } -bool MediaPlayerPrivate::seeking() const +bool MediaPlayerPrivateQt::seeking() const { return m_isSeeking; } -float MediaPlayerPrivate::duration() const +float MediaPlayerPrivateQt::duration() const { if (m_readyState < MediaPlayer::HaveMetadata) return 0.0f; @@ -328,13 +328,13 @@ float MediaPlayerPrivate::duration() const return duration; } -float MediaPlayerPrivate::currentTime() const +float MediaPlayerPrivateQt::currentTime() const { float currentTime = m_mediaPlayer->position() / 1000.0f; return currentTime; } -PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const +PassRefPtr<TimeRanges> MediaPlayerPrivateQt::buffered() const { RefPtr<TimeRanges> buffered = TimeRanges::create(); @@ -352,7 +352,7 @@ PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const return buffered.release(); } -float MediaPlayerPrivate::maxTimeSeekable() const +float MediaPlayerPrivateQt::maxTimeSeekable() const { if (!m_mediaPlayerControl) return 0; @@ -360,7 +360,7 @@ float MediaPlayerPrivate::maxTimeSeekable() const return static_cast<float>(m_mediaPlayerControl->availablePlaybackRanges().latestTime()) / 1000.0f; } -unsigned MediaPlayerPrivate::bytesLoaded() const +unsigned MediaPlayerPrivateQt::bytesLoaded() const { QLatin1String bytesLoadedKey("bytes-loaded"); if (m_mediaPlayer->availableExtendedMetaData().contains(bytesLoadedKey)) @@ -369,7 +369,7 @@ unsigned MediaPlayerPrivate::bytesLoaded() const return m_mediaPlayer->bufferStatus(); } -unsigned MediaPlayerPrivate::totalBytes() const +unsigned MediaPlayerPrivateQt::totalBytes() const { if (m_mediaPlayer->availableMetaData().contains(QtMultimediaKit::Size)) return m_mediaPlayer->metaData(QtMultimediaKit::Size).toInt(); @@ -377,59 +377,59 @@ unsigned MediaPlayerPrivate::totalBytes() const return 100; } -void MediaPlayerPrivate::setPreload(MediaPlayer::Preload preload) +void MediaPlayerPrivateQt::setPreload(MediaPlayer::Preload preload) { m_preload = preload; if (m_delayingLoad && m_preload != MediaPlayer::None) resumeLoad(); } -void MediaPlayerPrivate::setRate(float rate) +void MediaPlayerPrivateQt::setRate(float rate) { m_mediaPlayer->setPlaybackRate(rate); } -void MediaPlayerPrivate::setVolume(float volume) +void MediaPlayerPrivateQt::setVolume(float volume) { m_mediaPlayer->setVolume(static_cast<int>(volume * 100.0)); } -bool MediaPlayerPrivate::supportsMuting() const +bool MediaPlayerPrivateQt::supportsMuting() const { return true; } -void MediaPlayerPrivate::setMuted(bool muted) +void MediaPlayerPrivateQt::setMuted(bool muted) { m_mediaPlayer->setMuted(muted); } -MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const +MediaPlayer::NetworkState MediaPlayerPrivateQt::networkState() const { return m_networkState; } -MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const +MediaPlayer::ReadyState MediaPlayerPrivateQt::readyState() const { return m_readyState; } -void MediaPlayerPrivate::setVisible(bool visible) +void MediaPlayerPrivateQt::setVisible(bool visible) { m_isVisible = visible; } -void MediaPlayerPrivate::mediaStatusChanged(QMediaPlayer::MediaStatus) +void MediaPlayerPrivateQt::mediaStatusChanged(QMediaPlayer::MediaStatus) { updateStates(); } -void MediaPlayerPrivate::handleError(QMediaPlayer::Error) +void MediaPlayerPrivateQt::handleError(QMediaPlayer::Error) { updateStates(); } -void MediaPlayerPrivate::stateChanged(QMediaPlayer::State state) +void MediaPlayerPrivateQt::stateChanged(QMediaPlayer::State state) { if (state != QMediaPlayer::PlayingState && m_isSeeking && m_queuedSeek >= 0) { m_mediaPlayer->setPosition(m_queuedSeek); @@ -437,12 +437,12 @@ void MediaPlayerPrivate::stateChanged(QMediaPlayer::State state) } } -void MediaPlayerPrivate::nativeSizeChanged(const QSizeF&) +void MediaPlayerPrivateQt::nativeSizeChanged(const QSizeF&) { - m_player->sizeChanged(); + m_webCorePlayer->sizeChanged(); } -void MediaPlayerPrivate::queuedSeekTimeout() +void MediaPlayerPrivateQt::queuedSeekTimeout() { // If we haven't heard anything, assume the player is now paused // and we can attempt the seek @@ -455,45 +455,45 @@ void MediaPlayerPrivate::queuedSeekTimeout() } } -void MediaPlayerPrivate::seekTimeout() +void MediaPlayerPrivateQt::seekTimeout() { // If we haven't heard anything, assume the seek succeeded if (m_isSeeking) { - m_player->timeChanged(); + m_webCorePlayer->timeChanged(); m_isSeeking = false; } } -void MediaPlayerPrivate::positionChanged(qint64) +void MediaPlayerPrivateQt::positionChanged(qint64) { // Only propogate this event if we are seeking if (m_isSeeking && m_queuedSeek == -1) { - m_player->timeChanged(); + m_webCorePlayer->timeChanged(); m_isSeeking = false; } } -void MediaPlayerPrivate::bufferStatusChanged(int) +void MediaPlayerPrivateQt::bufferStatusChanged(int) { notImplemented(); } -void MediaPlayerPrivate::durationChanged(qint64) +void MediaPlayerPrivateQt::durationChanged(qint64) { - m_player->durationChanged(); + m_webCorePlayer->durationChanged(); } -void MediaPlayerPrivate::volumeChanged(int volume) +void MediaPlayerPrivateQt::volumeChanged(int volume) { - m_player->volumeChanged(static_cast<float>(volume) / 100.0); + m_webCorePlayer->volumeChanged(static_cast<float>(volume) / 100.0); } -void MediaPlayerPrivate::mutedChanged(bool muted) +void MediaPlayerPrivateQt::mutedChanged(bool muted) { - m_player->muteChanged(muted); + m_webCorePlayer->muteChanged(muted); } -void MediaPlayerPrivate::updateStates() +void MediaPlayerPrivateQt::updateStates() { // Store the old states so that we can detect a change and raise change events MediaPlayer::NetworkState oldNetworkState = m_networkState; @@ -538,13 +538,13 @@ void MediaPlayerPrivate::updateStates() // Breaking this invariant will cause the resource selection algorithm for multiple // sources to fail. if (m_readyState != oldReadyState) - m_player->readyStateChanged(); + m_webCorePlayer->readyStateChanged(); if (m_networkState != oldNetworkState) - m_player->networkStateChanged(); + m_webCorePlayer->networkStateChanged(); } -void MediaPlayerPrivate::setSize(const IntSize& size) +void MediaPlayerPrivateQt::setSize(const IntSize& size) { if (size == m_currentSize) return; @@ -553,7 +553,7 @@ void MediaPlayerPrivate::setSize(const IntSize& size) m_videoItem->setSize(QSizeF(QSize(size))); } -IntSize MediaPlayerPrivate::naturalSize() const +IntSize MediaPlayerPrivateQt::naturalSize() const { if (!hasVideo() || m_readyState < MediaPlayer::HaveMetadata) return IntSize(); @@ -561,7 +561,7 @@ IntSize MediaPlayerPrivate::naturalSize() const return IntSize(m_videoItem->nativeSize().toSize()); } -void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect) +void MediaPlayerPrivateQt::paint(GraphicsContext* context, const IntRect& rect) { #if USE(ACCELERATED_COMPOSITING) if (m_composited) @@ -580,15 +580,16 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect) m_videoScene->render(painter, QRectF(QRect(rect)), m_videoItem->sceneBoundingRect()); } -void MediaPlayerPrivate::repaint() +void MediaPlayerPrivateQt::repaint() { - m_player->repaint(); + m_webCorePlayer->repaint(); } #if USE(ACCELERATED_COMPOSITING) -void MediaPlayerPrivate::acceleratedRenderingStateChanged() +void MediaPlayerPrivateQt::acceleratedRenderingStateChanged() { - bool composited = m_player->mediaPlayerClient()->mediaPlayerRenderingCanBeAccelerated(m_player); + MediaPlayerClient* client = m_webCorePlayer->mediaPlayerClient(); + bool composited = client->mediaPlayerRenderingCanBeAccelerated(m_webCorePlayer); if (composited == m_composited) return; @@ -599,17 +600,17 @@ void MediaPlayerPrivate::acceleratedRenderingStateChanged() m_videoScene->addItem(m_videoItem); } -PlatformLayer* MediaPlayerPrivate::platformLayer() const +PlatformLayer* MediaPlayerPrivateQt::platformLayer() const { return m_composited ? m_videoItem : 0; } #endif -PlatformMedia MediaPlayerPrivate::platformMedia() const +PlatformMedia MediaPlayerPrivateQt::platformMedia() const { PlatformMedia pm; pm.type = PlatformMedia::QtMediaPlayerType; - pm.media.qtMediaPlayer = const_cast<MediaPlayerPrivate*>(this); + pm.media.qtMediaPlayer = const_cast<MediaPlayerPrivateQt*>(this); return pm; } diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h index 117187d..179bf2a 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h @@ -33,13 +33,13 @@ QT_END_NAMESPACE namespace WebCore { -class MediaPlayerPrivate : public QObject, public MediaPlayerPrivateInterface { +class MediaPlayerPrivateQt : public QObject, public MediaPlayerPrivateInterface { Q_OBJECT public: static MediaPlayerPrivateInterface* create(MediaPlayer* player); - ~MediaPlayerPrivate(); + ~MediaPlayerPrivateQt(); static void registerMediaEngine(MediaEngineRegistrar); static void getSupportedTypes(HashSet<String>&); @@ -118,9 +118,9 @@ private: void updateStates(); private: - MediaPlayerPrivate(MediaPlayer*); + MediaPlayerPrivateQt(MediaPlayer*); - MediaPlayer* m_player; + MediaPlayer* m_webCorePlayer; QMediaPlayer* m_mediaPlayer; QMediaPlayerControl* m_mediaPlayerControl; QGraphicsVideoItem* m_videoItem; diff --git a/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp b/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp index b6d6e65..8301871 100644 --- a/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp +++ b/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp @@ -36,7 +36,7 @@ #include "Base64.h" #include "ChromiumBridge.h" #include "OpenTypeUtilities.h" -#elif OS(LINUX) +#elif OS(LINUX) || OS(FREEBSD) #include "SkStream.h" #endif @@ -47,7 +47,7 @@ #if OS(WINDOWS) #include <objbase.h> -#elif OS(LINUX) +#elif OS(LINUX) || OS(FREEBSD) #include <cstring> #endif @@ -58,7 +58,7 @@ FontCustomPlatformData::~FontCustomPlatformData() #if OS(WINDOWS) if (m_fontReference) RemoveFontMemResourceEx(m_fontReference); -#elif OS(LINUX) +#elif OS(LINUX) || OS(FREEBSD) if (m_fontReference) m_fontReference->unref(); #endif @@ -99,7 +99,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b HFONT hfont = CreateFontIndirect(&logFont); return FontPlatformData(hfont, size); -#elif OS(LINUX) +#elif OS(LINUX) || OS(FREEBSD) ASSERT(m_fontReference); return FontPlatformData(m_fontReference, "", size, bold && !m_fontReference->isBold(), italic && !m_fontReference->isItalic()); #else @@ -123,7 +123,7 @@ static String createUniqueFontName() } #endif -#if OS(LINUX) +#if OS(LINUX) || OS(FREEBSD) class RemoteFontStream : public SkStream { public: explicit RemoteFontStream(PassRefPtr<SharedBuffer> buffer) @@ -189,7 +189,7 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) if (!fontReference) return 0; return new FontCustomPlatformData(fontReference, fontName); -#elif OS(LINUX) +#elif OS(LINUX) || OS(FREEBSD) RemoteFontStream* stream = new RemoteFontStream(buffer); SkTypeface* typeface = SkTypeface::CreateFromStream(stream); if (!typeface) diff --git a/WebCore/platform/graphics/skia/FontCustomPlatformData.h b/WebCore/platform/graphics/skia/FontCustomPlatformData.h index d451c9c..94d7ec3 100644 --- a/WebCore/platform/graphics/skia/FontCustomPlatformData.h +++ b/WebCore/platform/graphics/skia/FontCustomPlatformData.h @@ -39,7 +39,7 @@ #if OS(WINDOWS) #include "PlatformString.h" #include <windows.h> -#elif OS(LINUX) +#elif OS(LINUX) || OS(FREEBSD) #include "SkTypeface.h" #endif @@ -54,7 +54,7 @@ struct FontCustomPlatformData : Noncopyable { : m_fontReference(fontReference) , m_name(name) {} -#elif OS(LINUX) +#elif OS(LINUX) || OS(FREEBSD) explicit FontCustomPlatformData(SkTypeface* typeface) : m_fontReference(typeface) {} @@ -70,7 +70,7 @@ struct FontCustomPlatformData : Noncopyable { #if OS(WINDOWS) HANDLE m_fontReference; String m_name; -#elif OS(LINUX) +#elif OS(LINUX) || OS(FREEBSD) SkTypeface* m_fontReference; #endif }; diff --git a/WebCore/platform/graphics/skia/GradientSkia.cpp b/WebCore/platform/graphics/skia/GradientSkia.cpp index 66a8976..a636d10 100644 --- a/WebCore/platform/graphics/skia/GradientSkia.cpp +++ b/WebCore/platform/graphics/skia/GradientSkia.cpp @@ -42,7 +42,7 @@ namespace WebCore { void Gradient::platformDestroy() { if (m_gradient) - m_gradient->safeUnref(); + SkSafeUnref(m_gradient); m_gradient = 0; } diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index d618c19..4bc98fb 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -338,13 +338,15 @@ void GraphicsContext::clearRect(const FloatRect& rect) if (paintingDisabled()) return; - if (platformContext()->useGPU()) { + if (platformContext()->useGPU() && !platformContext()->canvasClipApplied()) { platformContext()->prepareForHardwareDraw(); platformContext()->gpuCanvas()->clearRect(rect); return; } - platformContext()->prepareForSoftwareDraw(); + // Force a readback here (if we're using the GPU), since clearRect() is + // incompatible with mixed-mode rendering. + platformContext()->syncSoftwareCanvas(); SkRect r = rect; if (!isRectSkiaSafe(getCTM(), r)) diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp index 0b96d80..e123256 100644 --- a/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -36,7 +36,6 @@ #include "FloatConversion.h" #include "FloatRect.h" #include "GLES2Canvas.h" -#include "GLES2Context.h" #include "GraphicsContext.h" #include "Logging.h" #include "NativeImageSkia.h" @@ -144,7 +143,9 @@ static ResamplingMode computeResamplingMode(PlatformContextSkia* platformContext // Everything else gets resampled. // If the platform context permits high quality interpolation, use it. - if (platformContext->interpolationQuality() == InterpolationHigh) + // High quality interpolation only enabled for scaling and translation. + if (platformContext->interpolationQuality() == InterpolationHigh + && !(platformContext->canvas()->getTotalMatrix().getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask))) return RESAMPLE_AWESOME; return RESAMPLE_LINEAR; @@ -174,8 +175,12 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm && srcIRect.height() == bitmap.height(); // We will always draw in integer sizes, so round the destination rect. + // First we need to apply canvas transformation matrix to get desired size of + // resampled image. + SkRect destRectTransformed; + canvas.getTotalMatrix().mapRect(&destRectTransformed, destRect); SkIRect destRectRounded; - destRect.round(&destRectRounded); + destRectTransformed.round(&destRectRounded); SkIRect resizedImageRect = // Represents the size of the resized image. { 0, 0, destRectRounded.width(), destRectRounded.height() }; @@ -189,7 +194,10 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm // Compute the visible portion of our rect. SkRect destBitmapSubsetSk; ClipRectToCanvas(canvas, destRect, &destBitmapSubsetSk); - destBitmapSubsetSk.offset(-destRect.fLeft, -destRect.fTop); + // Determine size of resampled image based on clipped destination rect. + SkRect destBitmapSubsetSkTransformed; + canvas.getTotalMatrix().mapRect(&destBitmapSubsetSkTransformed, destBitmapSubsetSk); + destBitmapSubsetSkTransformed.offset(-destBitmapSubsetSkTransformed.fLeft, -destBitmapSubsetSkTransformed.fTop); // The matrix inverting, etc. could have introduced rounding error which // causes the bounds to be outside of the resized bitmap. We round outward @@ -197,7 +205,7 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm // need, and then clamp to the bitmap bounds so we don't get any invalid // data. SkIRect destBitmapSubsetSkI; - destBitmapSubsetSk.roundOut(&destBitmapSubsetSkI); + destBitmapSubsetSkTransformed.roundOut(&destBitmapSubsetSkI); if (!destBitmapSubsetSkI.intersect(resizedImageRect)) return; // Resized image does not intersect. diff --git a/WebCore/platform/graphics/skia/PatternSkia.cpp b/WebCore/platform/graphics/skia/PatternSkia.cpp index bd27b6a..72fac77 100644 --- a/WebCore/platform/graphics/skia/PatternSkia.cpp +++ b/WebCore/platform/graphics/skia/PatternSkia.cpp @@ -42,7 +42,7 @@ namespace WebCore { void Pattern::platformDestroy() { - m_pattern->safeUnref(); + SkSafeUnref(m_pattern); m_pattern = 0; } diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index 88fbcdd..b469312 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -162,19 +162,19 @@ PlatformContextSkia::State::State(const State& other) , m_interpolationQuality(other.m_interpolationQuality) , m_canvasClipApplied(other.m_canvasClipApplied) { - // Up the ref count of these. saveRef does nothing if 'this' is NULL. - m_looper->safeRef(); - m_dash->safeRef(); - m_fillShader->safeRef(); - m_strokeShader->safeRef(); + // Up the ref count of these. SkSafeRef does nothing if its argument is 0. + SkSafeRef(m_looper); + SkSafeRef(m_dash); + SkSafeRef(m_fillShader); + SkSafeRef(m_strokeShader); } PlatformContextSkia::State::~State() { - m_looper->safeUnref(); - m_dash->safeUnref(); - m_fillShader->safeUnref(); - m_strokeShader->safeUnref(); + SkSafeUnref(m_looper); + SkSafeUnref(m_dash); + SkSafeUnref(m_fillShader); + SkSafeUnref(m_strokeShader); } // Returns a new State with all of this object's inherited properties copied. @@ -327,7 +327,7 @@ void PlatformContextSkia::drawRect(SkRect rect) // setFillColor() will set the shader to NULL, so save a ref to it now. SkShader* oldFillShader = m_state->m_fillShader; - oldFillShader->safeRef(); + SkSafeRef(oldFillShader); setFillColor(m_state->m_strokeColor); paint.reset(); setupPaintForFilling(&paint); @@ -341,7 +341,7 @@ void PlatformContextSkia::drawRect(SkRect rect) canvas()->drawRect(rightBorder, paint); setFillColor(oldFillColor); setFillShader(oldFillShader); - oldFillShader->safeUnref(); + SkSafeUnref(oldFillShader); } } @@ -487,9 +487,9 @@ void PlatformContextSkia::setStrokeThickness(float thickness) void PlatformContextSkia::setStrokeShader(SkShader* strokeShader) { if (strokeShader != m_state->m_strokeShader) { - m_state->m_strokeShader->safeUnref(); + SkSafeUnref(m_state->m_strokeShader); m_state->m_strokeShader = strokeShader; - m_state->m_strokeShader->safeRef(); + SkSafeRef(m_state->m_strokeShader); } } @@ -561,9 +561,9 @@ void PlatformContextSkia::setFillRule(SkPath::FillType fr) void PlatformContextSkia::setFillShader(SkShader* fillShader) { if (fillShader != m_state->m_fillShader) { - m_state->m_fillShader->safeUnref(); + SkSafeUnref(m_state->m_fillShader); m_state->m_fillShader = fillShader; - m_state->m_fillShader->safeRef(); + SkSafeRef(m_state->m_fillShader); } } @@ -580,7 +580,7 @@ void PlatformContextSkia::setInterpolationQuality(InterpolationQuality interpola void PlatformContextSkia::setDashPathEffect(SkDashPathEffect* dash) { if (dash != m_state->m_dash) { - m_state->m_dash->safeUnref(); + SkSafeUnref(m_state->m_dash); m_state->m_dash = dash; } } @@ -677,6 +677,11 @@ bool PlatformContextSkia::canAccelerate() const && !m_state->m_canvasClipApplied; // Can't accelerate with a clip to path applied. } +bool PlatformContextSkia::canvasClipApplied() const +{ + return m_state->m_canvasClipApplied; +} + class WillPublishCallbackImpl : public DrawingBuffer::WillPublishCallback { public: static PassOwnPtr<WillPublishCallback> create(PlatformContextSkia* pcs) @@ -840,7 +845,7 @@ void PlatformContextSkia::readbackHardwareToSoftware() const for (int i = 0; i < width; ++i) { uint32_t pixel = pixels[i]; // Swizzles from RGBA -> BGRA. - pixels[i] = pixel & 0xFF00FF00 | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16); + pixels[i] = (pixel & 0xFF00FF00) | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16); } } } diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h index 4ba85d1..eb03224 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.h +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h @@ -180,6 +180,7 @@ public: bool hasImageResamplingHint() const; bool canAccelerate() const; + bool canvasClipApplied() const; bool useGPU() { return m_useGPU; } void setSharedGraphicsContext3D(SharedGraphicsContext3D*, DrawingBuffer*, const IntSize&); GLES2Canvas* gpuCanvas() const { return m_gpuCanvas.get(); } diff --git a/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/WebCore/platform/graphics/skia/SkiaFontWin.cpp index 9edb775..6acfd35 100644 --- a/WebCore/platform/graphics/skia/SkiaFontWin.cpp +++ b/WebCore/platform/graphics/skia/SkiaFontWin.cpp @@ -340,7 +340,7 @@ bool paintSkiaText(GraphicsContext* context, // thing would be to draw to a new layer and then draw that layer // with a shadow. But this is a lot of extra work for something // that isn't normally an issue. - paint.setLooper(0)->safeUnref(); + SkSafeUnref(paint.setLooper(0)); } if (!skiaDrawText(hfont, dc, platformContext->canvas(), *origin, &paint, diff --git a/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp b/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp index 4072a18..80e01a9 100644 --- a/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp +++ b/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp @@ -234,7 +234,6 @@ static void addArcPoints(PathPolygon& poly, const PlatformPathElement::ArcTo& da static void drawPolygons(HDC dc, const Vector<PathPolygon>& polygons, bool fill, const AffineTransform* transformation) { - MemoryAllocationCanFail canFail; for (Vector<PathPolygon>::const_iterator i = polygons.begin(); i != polygons.end(); ++i) { int npoints = i->size(); if (!npoints) |