diff options
author | Iain Merrick <husky@google.com> | 2010-08-19 17:55:56 +0100 |
---|---|---|
committer | Iain Merrick <husky@google.com> | 2010-08-23 11:05:40 +0100 |
commit | f486d19d62f1bc33246748b14b14a9dfa617b57f (patch) | |
tree | 195485454c93125455a30e553a73981c3816144d /WebCore/platform/graphics | |
parent | 6ba0b43722d16bc295606bec39f396f596e4fef1 (diff) | |
download | external_webkit-f486d19d62f1bc33246748b14b14a9dfa617b57f.zip external_webkit-f486d19d62f1bc33246748b14b14a9dfa617b57f.tar.gz external_webkit-f486d19d62f1bc33246748b14b14a9dfa617b57f.tar.bz2 |
Merge WebKit at r65615 : Initial merge by git.
Change-Id: Ifbf384f4531e3b58475a662e38195c2d9152ae79
Diffstat (limited to 'WebCore/platform/graphics')
87 files changed, 2093 insertions, 571 deletions
diff --git a/WebCore/platform/graphics/ANGLEWebKitBridge.cpp b/WebCore/platform/graphics/ANGLEWebKitBridge.cpp new file mode 100644 index 0000000..9a14820 --- /dev/null +++ b/WebCore/platform/graphics/ANGLEWebKitBridge.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2010 Apple 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" + +#if ENABLE(3D_CANVAS) + +#include "ANGLEWebKitBridge.h" + +namespace WebCore { + + +ANGLEWebKitBridge::ANGLEWebKitBridge() : + builtCompilers(false) +{ + ShInitialize(); +} + +ANGLEWebKitBridge::~ANGLEWebKitBridge() +{ + if (builtCompilers) { + ShDestruct(m_fragmentCompiler); + ShDestruct(m_vertexCompiler); + } + + ShFinalize(); +} + +bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog) +{ + if (!builtCompilers) { + m_fragmentCompiler = ShConstructCompiler(EShLangFragment, EShSpecWebGL, &m_resources); + m_vertexCompiler = ShConstructCompiler(EShLangVertex, EShSpecWebGL, &m_resources); + + builtCompilers = true; + } + + ShHandle compiler; + + if (shaderType == SHADER_TYPE_VERTEX) + compiler = m_vertexCompiler; + else + compiler = m_fragmentCompiler; + + const char* const shaderSourceStrings[] = { shaderSource }; + + bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, EShOptNone, EDebugOpIntermediate); + + translatedShaderSource = ShGetObjectCode(compiler); + shaderValidationLog = ShGetInfoLog(compiler); + + return validateSuccess; +} + +} + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/platform/graphics/ANGLEWebKitBridge.h b/WebCore/platform/graphics/ANGLEWebKitBridge.h new file mode 100644 index 0000000..d01de8f --- /dev/null +++ b/WebCore/platform/graphics/ANGLEWebKitBridge.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010 Apple 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. + */ + +#ifndef ANGLEWebKitBridge_h +#define ANGLEWebKitBridge_h + +#include "ANGLE/ShaderLang.h" +#include "PlatformString.h" + +#include <wtf/text/CString.h> + +namespace WebCore { + +enum ANGLEShaderType { + SHADER_TYPE_VERTEX = EShLangVertex, + SHADER_TYPE_FRAGMENT = EShLangFragment +}; + +class ANGLEWebKitBridge { +public: + + ANGLEWebKitBridge(); + ~ANGLEWebKitBridge(); + + void setResources(TBuiltInResource resources) { m_resources = resources; } + + bool validateShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog); + +private: + + ShHandle m_fragmentCompiler; + ShHandle m_vertexCompiler; + + bool builtCompilers; + + TBuiltInResource m_resources; +}; + +} // namespace WebCore + +#endif diff --git a/WebCore/platform/graphics/FontCache.cpp b/WebCore/platform/graphics/FontCache.cpp index cb54cdd..ff865c2 100644 --- a/WebCore/platform/graphics/FontCache.cpp +++ b/WebCore/platform/graphics/FontCache.cpp @@ -34,10 +34,10 @@ #include "FontFallbackList.h" #include "FontPlatformData.h" #include "FontSelector.h" -#include "StringHash.h" #include <wtf/HashMap.h> #include <wtf/ListHashSet.h> #include <wtf/StdLibExtras.h> +#include <wtf/text/StringHash.h> using namespace WTF; diff --git a/WebCore/platform/graphics/FontDescription.h b/WebCore/platform/graphics/FontDescription.h index 86a4349..48fcaad 100644 --- a/WebCore/platform/graphics/FontDescription.h +++ b/WebCore/platform/graphics/FontDescription.h @@ -103,7 +103,11 @@ public: void setIsAbsoluteSize(bool s) { m_isAbsoluteSize = s; } void setWeight(FontWeight w) { m_weight = w; } void setGenericFamily(GenericFamilyType genericFamily) { m_genericFamily = genericFamily; } +#if PLATFORM(CHROMIUM) && OS(DARWIN) + void setUsePrinterFont(bool) { } +#else void setUsePrinterFont(bool p) { m_usePrinterFont = p; } +#endif void setRenderingMode(FontRenderingMode mode) { m_renderingMode = mode; } void setKeywordSize(unsigned s) { m_keywordSize = s; } void setFontSmoothing(FontSmoothingMode smoothing) { m_fontSmoothing = smoothing; } diff --git a/WebCore/platform/graphics/FontFamily.h b/WebCore/platform/graphics/FontFamily.h index 126bd83..21a6b64 100644 --- a/WebCore/platform/graphics/FontFamily.h +++ b/WebCore/platform/graphics/FontFamily.h @@ -26,9 +26,9 @@ #ifndef FontFamily_h #define FontFamily_h -#include "AtomicString.h" #include <wtf/RefCounted.h> #include <wtf/ListRefPtr.h> +#include <wtf/text/AtomicString.h> namespace WebCore { diff --git a/WebCore/platform/graphics/GeneratedImage.cpp b/WebCore/platform/graphics/GeneratedImage.cpp index cd0748e..5df2608 100644 --- a/WebCore/platform/graphics/GeneratedImage.cpp +++ b/WebCore/platform/graphics/GeneratedImage.cpp @@ -63,11 +63,8 @@ void GeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcR GraphicsContext* graphicsContext = imageBuffer->context(); graphicsContext->fillRect(FloatRect(FloatPoint(), adjustedSize), *m_generator.get()); - // Grab the final image from the image buffer. - Image* bitmap = imageBuffer->image(); - - // Now just call drawTiled on that image. - bitmap->drawPattern(context, adjustedSrcRect, patternTransform, phase, styleColorSpace, compositeOp, destRect); + // Tile the image buffer into the context. + imageBuffer->drawPattern(context, adjustedSrcRect, patternTransform, phase, styleColorSpace, compositeOp, destRect); } } diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp index bee3ef6..bb4f858 100644 --- a/WebCore/platform/graphics/GraphicsContext.cpp +++ b/WebCore/platform/graphics/GraphicsContext.cpp @@ -30,6 +30,7 @@ #include "Font.h" #include "Generator.h" #include "GraphicsContextPrivate.h" +#include "ImageBuffer.h" using namespace std; @@ -442,6 +443,57 @@ void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, c restore(); } +void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op) +{ + drawImageBuffer(image, styleColorSpace, p, IntRect(0, 0, -1, -1), op); +} + +void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, bool useLowQualityScale) +{ + drawImageBuffer(image, styleColorSpace, r, IntRect(0, 0, -1, -1), op, useLowQualityScale); +} + +void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op) +{ + drawImageBuffer(image, styleColorSpace, IntRect(dest, srcRect.size()), srcRect, op); +} + +void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale) +{ + drawImageBuffer(image, styleColorSpace, FloatRect(dest), srcRect, op, useLowQualityScale); +} + +void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale) +{ + if (paintingDisabled() || !image) + return; + + float tsw = src.width(); + float tsh = src.height(); + float tw = dest.width(); + float th = dest.height(); + + if (tsw == -1) + tsw = image->width(); + if (tsh == -1) + tsh = image->height(); + + if (tw == -1) + tw = image->width(); + if (th == -1) + th = image->height(); + + if (useLowQualityScale) { + save(); + setImageInterpolationQuality(InterpolationNone); + } + + image->draw(this, styleColorSpace, dest, src, op, useLowQualityScale); + + if (useLowQualityScale) + restore(); +} + void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight) { @@ -460,6 +512,13 @@ void GraphicsContext::clipOutRoundedRect(const IntRect& rect, const IntSize& top clipOut(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight)); } +void GraphicsContext::clipToImageBuffer(ImageBuffer* buffer, const FloatRect& rect) +{ + if (paintingDisabled()) + return; + buffer->clip(this, rect); +} + int GraphicsContext::textDrawingMode() { return m_common->state.textDrawingMode; @@ -541,4 +600,14 @@ void GraphicsContext::adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2 } } +#if !PLATFORM(SKIA) +void GraphicsContext::setGraphicsContext3D(GraphicsContext3D*, const IntSize&) +{ +} + +void GraphicsContext::syncSoftwareCanvas() +{ +} +#endif + } diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h index 9cae2f1..c48f91a 100644 --- a/WebCore/platform/graphics/GraphicsContext.h +++ b/WebCore/platform/graphics/GraphicsContext.h @@ -104,6 +104,12 @@ 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 @@ -267,6 +273,13 @@ namespace WebCore { Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false); + void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntPoint&, CompositeOperator = CompositeSourceOver); + void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntRect&, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false); + void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntPoint& destPoint, const IntRect& srcRect, CompositeOperator = CompositeSourceOver); + void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false); + void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1), + CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false); + void setImageInterpolationQuality(InterpolationQuality); InterpolationQuality imageInterpolationQuality() const; @@ -277,8 +290,8 @@ namespace WebCore { void clipOutEllipseInRect(const IntRect&); void clipOutRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight); void clipPath(WindRule); - void clipToImageBuffer(const FloatRect&, const ImageBuffer*); void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias = true); + void clipToImageBuffer(ImageBuffer*, const FloatRect&); int textDrawingMode(); void setTextDrawingMode(int); @@ -415,6 +428,7 @@ namespace WebCore { #if PLATFORM(QT) bool inTransparencyLayer() const; PlatformPath* currentPath(); + void pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask); QPen pen(); static QPainter::CompositionMode toQtCompositionMode(CompositeOperator op); #endif @@ -429,10 +443,8 @@ namespace WebCore { pattern getHaikuStrokeStyle(); #endif -#if PLATFORM(SKIA) void setGraphicsContext3D(GraphicsContext3D*, const IntSize&); void syncSoftwareCanvas(); -#endif private: void savePlatformState(); diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp index 79f6ecf..51c4cd5 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.cpp +++ b/WebCore/platform/graphics/GraphicsContext3D.cpp @@ -816,6 +816,21 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, return true; } +#if !PLATFORM(CHROMIUM) +bool GraphicsContext3D::supportsBGRA() +{ + // For OpenGL ES2.0, this requires checking for + // GL_EXT_texture_format_BGRA8888 and GL_EXT_read_format_bgra. + // For desktop GL, BGRA has been supported since OpenGL 1.2. + + // However, note that the GL ES2 extension requires the internalFormat to + // glTexImage2D() be GL_BGRA, while desktop GL will not accept GL_BGRA + // (must be GL_RGBA), so this must be checked on each platform. + // Returning false for now to be safe. + return false; +} +#endif + } // namespace WebCore #endif // ENABLE(3D_CANVAS) diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index d702096..25d1d06 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -26,9 +26,13 @@ #ifndef GraphicsContext3D_h #define GraphicsContext3D_h +#if PLATFORM(MAC) +#include "ANGLEWebKitBridge.h" +#endif #include "GraphicsLayer.h" #include "PlatformString.h" +#include <wtf/HashMap.h> #include <wtf/ListHashSet.h> #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> @@ -403,7 +407,9 @@ public: // WebGL-specific enums UNPACK_FLIP_Y_WEBGL = 0x9240, - UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241 + UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241, + + BGRA_EXT = 0x80E1 }; // Context creation attributes. @@ -716,11 +722,13 @@ public: void paintRenderingResultsToCanvas(CanvasRenderingContext* context); - // Helpers for notification about paint events - void beginPaint(CanvasRenderingContext* context); - void endPaint(); #if PLATFORM(QT) void paint(QPainter* painter, const QRect& rect) const; + bool paintsIntoCanvasBuffer() const { return true; } +#elif PLATFORM(CHROMIUM) + bool paintsIntoCanvasBuffer() const; +#else + bool paintsIntoCanvasBuffer() const { return false; } #endif // Support for buffer creation and deletion @@ -748,6 +756,8 @@ public: // getError in the order they were added. void synthesizeGLError(unsigned long error); + bool supportsBGRA(); + private: GraphicsContext3D(Attributes attrs, HostWindow* hostWindow); @@ -807,7 +817,16 @@ public: int m_currentWidth, m_currentHeight; + typedef struct { + String source; + String log; + bool isValid; + } ShaderSourceEntry; + HashMap<Platform3DObject, ShaderSourceEntry> m_shaderSourceMap; + #if PLATFORM(MAC) + ANGLEWebKitBridge m_compiler; + Attributes m_attrs; Vector<Vector<float> > m_vertexArray; diff --git a/WebCore/platform/graphics/Image.h b/WebCore/platform/graphics/Image.h index 7c00b71..3c5e7fd 100644 --- a/WebCore/platform/graphics/Image.h +++ b/WebCore/platform/graphics/Image.h @@ -154,6 +154,9 @@ public: static PassRefPtr<Image> loadPlatformThemeIcon(const char* name, int size); #endif + virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect); + protected: Image(ImageObserver* = 0); @@ -171,9 +174,6 @@ protected: virtual bool mayFillWithSolidColor() { return false; } virtual Color solidColor() const { return Color(); } - virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, - const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect); - private: RefPtr<SharedBuffer> m_data; // The encoded raw data for the image. ImageObserver* m_imageObserver; diff --git a/WebCore/platform/graphics/ImageBuffer.h b/WebCore/platform/graphics/ImageBuffer.h index a54c721..3c0508e 100644 --- a/WebCore/platform/graphics/ImageBuffer.h +++ b/WebCore/platform/graphics/ImageBuffer.h @@ -29,6 +29,7 @@ #define ImageBuffer_h #include "AffineTransform.h" +#include "FloatRect.h" #include "Image.h" #include "IntSize.h" #include "ImageBufferData.h" @@ -71,16 +72,13 @@ namespace WebCore { ~ImageBuffer(); const IntSize& size() const { return m_size; } + int width() const { return m_size.width(); } + int height() const { return m_size.height(); } + GraphicsContext* context() const; - Image* image() const; -#if PLATFORM(QT) - Image* imageForRendering() const; -#else - Image* imageForRendering() const { return image(); } -#endif - - void clearImage() { m_image.clear(); } + bool drawsUsingCopy() const; // If the image buffer has to render using a copied image, it will return true. + PassRefPtr<Image> copyImage() const; // Return a new image that is a copy of the buffer. PassRefPtr<ImageData> getUnmultipliedImageData(const IntRect&) const; PassRefPtr<ImageData> getPremultipliedImageData(const IntRect&) const; @@ -96,12 +94,23 @@ namespace WebCore { #else AffineTransform baseTransform() const { return AffineTransform(1, 0, 0, -1, 0, m_size.height()); } #endif + + private: + void clip(GraphicsContext*, const FloatRect&) const; + + // The draw method draws the contents of the buffer without copying it. + void draw(GraphicsContext*, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1), + CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false); + void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect); + friend class GraphicsContext; + friend class GeneratedImage; + private: ImageBufferData m_data; IntSize m_size; OwnPtr<GraphicsContext> m_context; - mutable RefPtr<Image> m_image; #if !PLATFORM(CG) Vector<int> m_linearRgbLUT; diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp index b8b742d..e72987a 100644 --- a/WebCore/platform/graphics/MediaPlayer.cpp +++ b/WebCore/platform/graphics/MediaPlayer.cpp @@ -173,7 +173,7 @@ static Vector<MediaPlayerFactory*>& installedMediaEngines() #if PLATFORM(WIN) MediaPlayerPrivateQuickTimeVisualContext::registerMediaEngine(addMediaEngine); -#elif !PLATFORM(GTK) +#elif !PLATFORM(GTK) && !PLATFORM(EFL) // FIXME: currently all the MediaEngines are named // MediaPlayerPrivate. This code will need an update when bug // 36663 is adressed. @@ -257,8 +257,8 @@ void MediaPlayer::load(const String& url, const ContentType& contentType) // if we don't know the MIME type, see if the extension can help if (type.isEmpty() || type == "application/octet-stream" || type == "text/plain") { - int pos = url.reverseFind('.'); - if (pos >= 0) { + size_t pos = url.reverseFind('.'); + if (pos != notFound) { String extension = url.substring(pos + 1); String mediaType = MIMETypeRegistry::getMediaMIMETypeForExtension(extension); if (!mediaType.isEmpty()) diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h index 4da697a..643f17f 100644 --- a/WebCore/platform/graphics/MediaPlayer.h +++ b/WebCore/platform/graphics/MediaPlayer.h @@ -34,12 +34,12 @@ #include "Document.h" #include "IntRect.h" -#include "StringHash.h" #include <wtf/Forward.h> #include <wtf/HashSet.h> #include <wtf/OwnPtr.h> #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> +#include <wtf/text/StringHash.h> #if USE(ACCELERATED_COMPOSITING) #include "GraphicsLayer.h" diff --git a/WebCore/platform/graphics/Path.cpp b/WebCore/platform/graphics/Path.cpp index af94be7..333afcb 100644 --- a/WebCore/platform/graphics/Path.cpp +++ b/WebCore/platform/graphics/Path.cpp @@ -266,8 +266,6 @@ Path Path::createCircle(const FloatPoint& center, float r) Path Path::createLine(const FloatPoint& start, const FloatPoint& end) { Path path; - if (start.x() == end.x() && start.y() == end.y()) - return path; path.moveTo(start); path.addLineTo(end); diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h index 43ba889..61ea328 100644 --- a/WebCore/platform/graphics/Path.h +++ b/WebCore/platform/graphics/Path.h @@ -156,6 +156,10 @@ namespace WebCore { private: PlatformPathPtr m_path; + +#if PLATFORM(QT) + int m_lastMoveToIndex; +#endif }; } diff --git a/WebCore/platform/graphics/Pattern.cpp b/WebCore/platform/graphics/Pattern.cpp index bb07307..82d0a24 100644 --- a/WebCore/platform/graphics/Pattern.cpp +++ b/WebCore/platform/graphics/Pattern.cpp @@ -31,7 +31,7 @@ namespace WebCore { -Pattern::Pattern(Image* image, bool repeatX, bool repeatY) +Pattern::Pattern(PassRefPtr<Image> image, bool repeatX, bool repeatY) : m_tileImage(image) , m_repeatX(repeatX) , m_repeatY(repeatY) @@ -39,7 +39,7 @@ Pattern::Pattern(Image* image, bool repeatX, bool repeatY) , m_pattern(0) #endif { - ASSERT(image); + ASSERT(m_tileImage); } Pattern::~Pattern() diff --git a/WebCore/platform/graphics/Pattern.h b/WebCore/platform/graphics/Pattern.h index 48e8d8b..e215f3d 100644 --- a/WebCore/platform/graphics/Pattern.h +++ b/WebCore/platform/graphics/Pattern.h @@ -29,6 +29,7 @@ #define Pattern_h #include "AffineTransform.h" +#include "Image.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -64,11 +65,10 @@ typedef void* PlatformPatternPtr; namespace WebCore { class AffineTransform; -class Image; class Pattern : public RefCounted<Pattern> { public: - static PassRefPtr<Pattern> create(Image* tileImage, bool repeatX, bool repeatY) + static PassRefPtr<Pattern> create(PassRefPtr<Image> tileImage, bool repeatX, bool repeatY) { return adoptRef(new Pattern(tileImage, repeatX, repeatY)); } @@ -91,7 +91,7 @@ public: bool repeatY() const { return m_repeatY; } private: - Pattern(Image*, bool repeatX, bool repeatY); + Pattern(PassRefPtr<Image>, bool repeatX, bool repeatY); RefPtr<Image> m_tileImage; bool m_repeatX; diff --git a/WebCore/platform/graphics/WOFFFileFormat.cpp b/WebCore/platform/graphics/WOFFFileFormat.cpp index 908e288..25b3b00 100644 --- a/WebCore/platform/graphics/WOFFFileFormat.cpp +++ b/WebCore/platform/graphics/WOFFFileFormat.cpp @@ -31,6 +31,9 @@ #include "SharedBuffer.h" #if !PLATFORM(WIN) +#if OS(UNIX) +#include <netinet/in.h> +#endif #include <zlib.h> #if PLATFORM(BREWMP) #include <AEEStdLib.h> diff --git a/WebCore/platform/graphics/cairo/GRefPtrCairo.cpp b/WebCore/platform/graphics/cairo/GRefPtrCairo.cpp new file mode 100644 index 0000000..d244954 --- /dev/null +++ b/WebCore/platform/graphics/cairo/GRefPtrCairo.cpp @@ -0,0 +1,52 @@ +/* + * 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 Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "GRefPtrCairo.h" + +#include <cairo.h> + +namespace WTF { + +template <> cairo_t* refGPtr(cairo_t* ptr) +{ + if (ptr) + cairo_reference(ptr); + return ptr; +} + +template <> void derefGPtr(cairo_t* ptr) +{ + if (ptr) + cairo_destroy(ptr); +} + +template <> cairo_surface_t* refGPtr(cairo_surface_t* ptr) +{ + if (ptr) + cairo_surface_reference(ptr); + return ptr; +} + +template <> void derefGPtr(cairo_surface_t* ptr) +{ + if (ptr) + cairo_surface_destroy(ptr); +} + +} diff --git a/WebCore/platform/graphics/cairo/GRefPtrCairo.h b/WebCore/platform/graphics/cairo/GRefPtrCairo.h new file mode 100644 index 0000000..aef51fe --- /dev/null +++ b/WebCore/platform/graphics/cairo/GRefPtrCairo.h @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#ifndef GRefPtrCairo_h +#define GRefPtrCairo_h + +#include "GRefPtr.h" + +typedef struct _cairo cairo_t; +typedef struct _cairo_surface cairo_surface_t; + +namespace WTF { + +template <> cairo_t* refGPtr(cairo_t* ptr); +template <> void derefGPtr(cairo_t* ptr); + +template <> cairo_surface_t* refGPtr(cairo_surface_t* ptr); +template <> void derefGPtr(cairo_surface_t* ptr); + +} + +#endif diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index f3fc943..9b3096e 100644 --- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -908,14 +908,6 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness cairo_set_fill_rule(cr, savedFillRule); } -void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer) -{ - if (paintingDisabled()) - return; - - notImplemented(); -} - void GraphicsContext::setPlatformShadow(FloatSize const& size, float, Color const&, ColorSpace) { // Cairo doesn't support shadows natively, they are drawn manually in the draw* @@ -936,7 +928,7 @@ void GraphicsContext::createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const // draw the shadow without blurring, if kernelSize is zero if (!kernelSize) { setColor(cr, shadowColor); - cairo_mask_surface(cr, buffer->image()->nativeImageForCurrentFrame(), shadowRect.x(), shadowRect.y()); + cairo_mask_surface(cr, buffer->m_data.m_surface, shadowRect.x(), shadowRect.y()); return; } @@ -956,7 +948,7 @@ void GraphicsContext::createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const // Mask the filter with the shadow color and draw it to the context. // Masking makes it possible to just blur the alpha channel. setColor(cr, shadowColor); - cairo_mask_surface(cr, blur->resultImage()->image()->nativeImageForCurrentFrame(), shadowRect.x(), shadowRect.y()); + cairo_mask_surface(cr, blur->resultImage()->m_data.m_surface, shadowRect.x(), shadowRect.y()); #endif } diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp index 1a43e54..db66276 100644 --- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp +++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp @@ -35,6 +35,7 @@ #include "GraphicsContext.h" #include "ImageData.h" #include "MIMETypeRegistry.h" +#include "NotImplemented.h" #include "Pattern.h" #include "PlatformString.h" @@ -97,26 +98,34 @@ GraphicsContext* ImageBuffer::context() const return m_context.get(); } -Image* ImageBuffer::image() const +bool ImageBuffer::drawsUsingCopy() const { - if (!m_image) { - // It's assumed that if image() is called, the actual rendering to the - // GraphicsContext must be done. - ASSERT(context()); - - // This creates a COPY of the image and will cache that copy. This means - // that if subsequent operations take place on the context, neither the - // currently-returned image, nor the results of future image() calls, - // will contain that operation. - // - // This seems silly, but is the way the CG port works: image() is - // intended to be used only when rendering is "complete." - cairo_surface_t* newsurface = copySurface(m_data.m_surface); - - // BitmapImage will release the passed in surface on destruction - m_image = BitmapImage::create(newsurface); - } - return m_image.get(); + return true; +} + +PassRefPtr<Image> ImageBuffer::copyImage() const +{ + // BitmapImage will release the passed in surface on destruction + return BitmapImage::create(copySurface(m_data.m_surface)); +} + +void ImageBuffer::clip(GraphicsContext*, const FloatRect&) const +{ + notImplemented(); +} + +void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, + CompositeOperator op , bool useLowQualityScale) +{ + RefPtr<Image> imageCopy = copyImage(); + context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale); +} + +void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect) +{ + RefPtr<Image> imageCopy = copyImage(); + imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect); } void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp index 64fbedf..1582671 100644 --- a/WebCore/platform/graphics/cairo/ImageCairo.cpp +++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp @@ -33,6 +33,7 @@ #include "AffineTransform.h" #include "Color.h" #include "FloatRect.h" +#include "GRefPtrCairo.h" #include "GraphicsContext.h" #include "ImageBuffer.h" #include "ImageObserver.h" @@ -184,17 +185,14 @@ void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, con cairo_t* cr = context->platformContext(); context->save(); - IntRect imageSize = enclosingIntRect(tileRect); - OwnPtr<ImageBuffer> imageSurface = ImageBuffer::create(imageSize.size()); - - if (!imageSurface) - return; - + GRefPtr<cairo_surface_t> clippedImageSurface = 0; if (tileRect.size() != size()) { - cairo_t* clippedImageContext = imageSurface->context()->platformContext(); - cairo_set_source_surface(clippedImageContext, image, -tileRect.x(), -tileRect.y()); - cairo_paint(clippedImageContext); - image = imageSurface->image()->nativeImageForCurrentFrame(); + IntRect imageSize = enclosingIntRect(tileRect); + clippedImageSurface = adoptGRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, imageSize.width(), imageSize.height())); + GRefPtr<cairo_t> clippedImageContext(cairo_create(clippedImageSurface.get())); + cairo_set_source_surface(clippedImageContext.get(), image, -tileRect.x(), -tileRect.y()); + cairo_paint(clippedImageContext.get()); + image = clippedImageSurface.get(); } cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image); diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp index 2de4d14..e5079dc 100644 --- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp @@ -753,18 +753,6 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness CGContextEOClip(context); } -void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer) -{ - if (paintingDisabled()) - return; - - CGContextTranslateCTM(platformContext(), rect.x(), rect.y() + rect.height()); - CGContextScaleCTM(platformContext(), 1, -1); - CGContextClipToMask(platformContext(), FloatRect(FloatPoint(), rect.size()), imageBuffer->image()->getCGImageRef()); - CGContextScaleCTM(platformContext(), 1, -1); - CGContextTranslateCTM(platformContext(), -rect.x(), -rect.y() - rect.height()); -} - void GraphicsContext::beginTransparencyLayer(float opacity) { if (paintingDisabled()) @@ -950,9 +938,17 @@ void GraphicsContext::clip(const Path& path) if (paintingDisabled()) return; CGContextRef context = platformContext(); - CGContextBeginPath(context); - CGContextAddPath(context, path.platformPath()); - CGContextClip(context); + + // CGContextClip does nothing if the path is empty, so in this case, we + // instead clip against a zero rect to reduce the clipping region to + // nothing - which is the intended behavior of clip() if the path is empty. + if (path.isEmpty()) + CGContextClipToRect(context, CGRectZero); + else { + CGContextBeginPath(context); + CGContextAddPath(context, path.platformPath()); + CGContextClip(context); + } m_data->clip(path); } diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp index feb8cec..ecbcf60 100644 --- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp +++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp @@ -46,6 +46,11 @@ using namespace std; namespace WebCore { +static void releaseImageData(void*, const void* data, size_t) +{ + fastFree(const_cast<void*>(data)); +} + ImageBufferData::ImageBufferData(const IntSize&) : m_data(0) { @@ -56,42 +61,46 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b , m_size(size) { success = false; // Make early return mean failure. - unsigned bytesPerRow; if (size.width() < 0 || size.height() < 0) return; - bytesPerRow = size.width(); + + unsigned bytesPerRow = size.width(); if (imageColorSpace != GrayScale) { // Protect against overflow if (bytesPerRow > 0x3FFFFFFF) return; bytesPerRow *= 4; } + m_data.m_bytesPerRow = bytesPerRow; + size_t dataSize = size.height() * bytesPerRow; if (!tryFastCalloc(size.height(), bytesPerRow).getValue(m_data.m_data)) return; ASSERT((reinterpret_cast<size_t>(m_data.m_data) & 2) == 0); - RetainPtr<CGColorSpaceRef> colorSpace; switch(imageColorSpace) { case DeviceRGB: - colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB()); + m_data.m_colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB()); break; case GrayScale: - colorSpace.adoptCF(CGColorSpaceCreateDeviceGray()); + m_data.m_colorSpace.adoptCF(CGColorSpaceCreateDeviceGray()); break; #if ((PLATFORM(MAC) || PLATFORM(CHROMIUM)) && !defined(BUILDING_ON_TIGER)) case LinearRGB: - colorSpace.adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear)); + m_data.m_colorSpace.adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear)); break; + #endif default: - colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB()); + m_data.m_colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB()); break; } + m_data.m_grayScale = imageColorSpace == GrayScale; + m_data.m_bitmapInfo = m_data.m_grayScale ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast; RetainPtr<CGContextRef> cgContext(AdoptCF, CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow, - colorSpace.get(), (imageColorSpace == GrayScale) ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast)); + m_data.m_colorSpace.get(), m_data.m_bitmapInfo)); if (!cgContext) return; @@ -99,11 +108,13 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b m_context->scale(FloatSize(1, -1)); m_context->translate(0, -size.height()); success = true; + + // Create a live image that wraps the data. + m_data.m_dataProvider.adoptCF(CGDataProviderCreateWithData(0, m_data.m_data, dataSize, releaseImageData)); } ImageBuffer::~ImageBuffer() { - fastFree(m_data.m_data); } GraphicsContext* ImageBuffer::context() const @@ -111,17 +122,59 @@ GraphicsContext* ImageBuffer::context() const return m_context.get(); } -Image* ImageBuffer::image() const +bool ImageBuffer::drawsUsingCopy() const +{ + return false; +} + +PassRefPtr<Image> ImageBuffer::copyImage() const +{ + // BitmapImage will release the passed in CGImage on destruction + return BitmapImage::create(CGBitmapContextCreateImage(context()->platformContext())); +} + +static CGImageRef cgImage(const IntSize& size, const ImageBufferData& data) { - if (!m_image) { - // It's assumed that if image() is called, the actual rendering to the - // GraphicsContext must be done. - ASSERT(context()); - CGImageRef cgImage = CGBitmapContextCreateImage(context()->platformContext()); - // BitmapImage will release the passed in CGImage on destruction - m_image = BitmapImage::create(cgImage); + return CGImageCreate(size.width(), size.height(), 8, data.m_grayScale ? 8 : 32, data.m_bytesPerRow, + data.m_colorSpace.get(), data.m_bitmapInfo, data.m_dataProvider.get(), 0, true, kCGRenderingIntentDefault); +} + +void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, + CompositeOperator op, bool useLowQualityScale) +{ + if (destContext == context()) { + // We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first. + RefPtr<Image> copy = copyImage(); + destContext->drawImage(copy.get(), DeviceColorSpace, destRect, srcRect, op, useLowQualityScale); + } else { + RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data)); + destContext->drawImage(imageForRendering.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale); + } +} + +void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect) +{ + if (destContext == context()) { + // We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first. + RefPtr<Image> copy = copyImage(); + copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect); + } else { + RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data)); + imageForRendering->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect); } - return m_image.get(); +} + +void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const +{ + RetainPtr<CGImageRef> image(AdoptCF, cgImage(m_size, m_data)); + + CGContextRef platformContext = context->platformContext(); + CGContextTranslateCTM(platformContext, rect.x(), rect.y() + rect.height()); + CGContextScaleCTM(platformContext, 1, -1); + CGContextClipToMask(platformContext, FloatRect(FloatPoint(), rect.size()), image.get()); + CGContextScaleCTM(platformContext, 1, -1); + CGContextTranslateCTM(platformContext, -rect.x(), -rect.y() - rect.height()); } template <Multiply multiplied> diff --git a/WebCore/platform/graphics/cg/ImageBufferData.h b/WebCore/platform/graphics/cg/ImageBufferData.h index 5e6fc4c..2f9d854 100644 --- a/WebCore/platform/graphics/cg/ImageBufferData.h +++ b/WebCore/platform/graphics/cg/ImageBufferData.h @@ -26,6 +26,14 @@ #ifndef ImageBufferData_h #define ImageBufferData_h +#include "Image.h" +#include <wtf/RefPtr.h> +#include <wtf/RetainPtr.h> + +typedef struct CGColorSpace *CGColorSpaceRef; +typedef struct CGDataProvider *CGDataProviderRef; +typedef uint32_t CGBitmapInfo; + namespace WebCore { class IntSize; @@ -35,6 +43,12 @@ public: ImageBufferData(const IntSize&); void* m_data; + + RetainPtr<CGDataProviderRef> m_dataProvider; + CGBitmapInfo m_bitmapInfo; + bool m_grayScale; + unsigned m_bytesPerRow; + RetainPtr<CGColorSpaceRef> m_colorSpace; }; } // namespace WebCore diff --git a/WebCore/platform/graphics/cg/ImageSourceCGWin.cpp b/WebCore/platform/graphics/cg/ImageSourceCGWin.cpp index c7d9a0b..ef69e5e 100644 --- a/WebCore/platform/graphics/cg/ImageSourceCGWin.cpp +++ b/WebCore/platform/graphics/cg/ImageSourceCGWin.cpp @@ -27,8 +27,8 @@ #include "ImageSourceCG.h" #include "StdLibExtras.h" -#include "StringHash.h" #include <wtf/HashMap.h> +#include <wtf/text/StringHash.h> namespace WebCore { diff --git a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp index 8ba37c6..7c3e450 100644 --- a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp @@ -38,8 +38,8 @@ #include "HashMap.h" #include "HashSet.h" #include "SimpleFontData.h" -#include "StringHash.h" #include <unicode/uniset.h> +#include <wtf/text/StringHash.h> #include <windows.h> #include <objidl.h> diff --git a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp index 53f4a52..2fda22d 100644 --- a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "FontCache.h" -#include "AtomicString.h" #include "ChromiumBridge.h" #include "Font.h" #include "FontDescription.h" @@ -46,6 +45,7 @@ #include <unicode/utf16.h> #include <wtf/Assertions.h> +#include <wtf/text/AtomicString.h> #include <wtf/text/CString.h> namespace WebCore { diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp index 1953dd8..ec79b82 100644 --- a/WebCore/platform/graphics/chromium/FontLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontLinux.cpp @@ -166,6 +166,9 @@ public: , m_offsetX(m_startingX) , m_run(getTextRun(run)) , m_iterateBackwards(m_run.rtl()) + , m_wordSpacingAdjustment(0) + , m_padding(0) + , m_padError(0) { // Do not use |run| inside this constructor. Use |m_run| instead. @@ -207,6 +210,56 @@ public: delete[] m_item.string; } + // setWordSpacingAdjustment sets a delta (in pixels) which is applied at + // each word break in the TextRun. + void setWordSpacingAdjustment(int wordSpacingAdjustment) + { + m_wordSpacingAdjustment = wordSpacingAdjustment; + } + + // setLetterSpacingAdjustment sets an additional number of pixels that is + // added to the advance after each output cluster. This matches the behaviour + // of WidthIterator::advance. + // + // (NOTE: currently does nothing because I don't know how to get the + // cluster information from Harfbuzz.) + void setLetterSpacingAdjustment(int letterSpacingAdjustment) + { + m_letterSpacing = letterSpacingAdjustment; + } + + bool isWordBreak(unsigned i, bool isRTL) + { + if (!isRTL) + return i && isCodepointSpace(m_item.string[i]) && !isCodepointSpace(m_item.string[i - 1]); + return i != m_item.stringLength - 1 && isCodepointSpace(m_item.string[i]) && !isCodepointSpace(m_item.string[i + 1]); + } + + // setPadding sets a number of pixels to be distributed across the TextRun. + // WebKit uses this to justify text. + void setPadding(int padding) + { + m_padding = padding; + if (!m_padding) + return; + + // If we have padding to distribute, then we try to give an equal + // amount to each space. The last space gets the smaller amount, if + // any. + unsigned numWordBreaks = 0; + bool isRTL = m_iterateBackwards; + + for (unsigned i = 0; i < m_item.stringLength; i++) { + if (isWordBreak(i, isRTL)) + numWordBreaks++; + } + + if (numWordBreaks) + m_padPerWordBreak = m_padding / numWordBreaks; + else + m_padPerWordBreak = 0; + } + void reset() { if (m_iterateBackwards) @@ -453,8 +506,15 @@ private: void setGlyphXPositions(bool isRTL) { double position = 0; + // logClustersIndex indexes logClusters for the first (or last when + // RTL) codepoint of the current glyph. Each time we advance a glyph, + // we skip over all the codepoints that contributed to the current + // glyph. + unsigned logClustersIndex = isRTL ? m_item.num_glyphs - 1 : 0; + for (int iter = 0; iter < m_item.num_glyphs; ++iter) { - // Glyphs are stored in logical order, but for layout purposes we always go left to right. + // 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; m_glyphs16[i] = m_item.glyphs[i]; @@ -462,12 +522,48 @@ private: m_xPositions[i] = m_offsetX + position + offsetX; double advance = truncateFixedPointToInteger(m_item.advances[i]); + unsigned glyphIndex = m_item.item.pos + logClustersIndex; + if (isWordBreak(glyphIndex, isRTL)) { + advance += m_wordSpacingAdjustment; + + if (m_padding > 0) { + unsigned toPad = roundf(m_padPerWordBreak + m_padError); + m_padError += m_padPerWordBreak - toPad; + + if (m_padding < toPad) + toPad = m_padding; + m_padding -= toPad; + advance += toPad; + } + } + + // We would like to add m_letterSpacing after each cluster, but I + // don't know where the cluster information is. This is typically + // fine for Roman languages, but breaks more complex languages + // terribly. + // advance += m_letterSpacing; + + if (isRTL) { + while (logClustersIndex > 0 && logClusters()[logClustersIndex] == i) + logClustersIndex--; + } else { + while (logClustersIndex < m_item.num_glyphs && logClusters()[logClustersIndex] == i) + logClustersIndex++; + } + position += advance; } + m_pixelWidth = position; m_offsetX += m_pixelWidth; } + static bool isCodepointSpace(HB_UChar16 c) + { + // This matches the logic in RenderBlock::findNextLineBreak + return c == ' ' || c == '\t'; + } + void mirrorCharacters(UChar* destination, const UChar* source, int length) const { int position = 0; @@ -498,6 +594,14 @@ private: OwnArrayPtr<UChar> m_normalizedBuffer; // A buffer for normalized run. const TextRun& m_run; bool m_iterateBackwards; + int m_wordSpacingAdjustment; // delta adjustment (pixels) for each word break. + float m_padding; // pixels to be distributed over the line at word breaks. + float m_padPerWordBreak; // pixels to be added to each word break. + float m_padError; // |m_padPerWordBreak| might have a fractional component. + // Since we only add a whole number of padding pixels at + // each word break we accumulate error. This is the + // number of pixels that we are behind so far. + unsigned m_letterSpacing; // pixels to be added after each glyph. }; static void setupForTextPainting(SkPaint* paint, SkColor color) @@ -534,6 +638,9 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run, TextRunWalker walker(run, point.x(), this); bool haveMultipleLayers = isCanvasMultiLayered(canvas); + walker.setWordSpacingAdjustment(wordSpacing()); + walker.setLetterSpacingAdjustment(letterSpacing()); + walker.setPadding(run.padding()); while (walker.nextScriptRun()) { if (fill) { @@ -553,6 +660,8 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run, float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const { TextRunWalker walker(run, 0, this); + walker.setWordSpacingAdjustment(wordSpacing()); + walker.setLetterSpacingAdjustment(letterSpacing()); return walker.widthOfFullRun(); } @@ -588,6 +697,8 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, // (Mac code ignores includePartialGlyphs, and they don't know what it's // supposed to do, so we just ignore it as well.) TextRunWalker walker(run, 0, this); + walker.setWordSpacingAdjustment(wordSpacing()); + walker.setLetterSpacingAdjustment(letterSpacing()); // If this is RTL text, the first glyph from the left is actually the last // code point. So we need to know how many code points there are total in @@ -664,6 +775,8 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, { int fromX = -1, toX = -1, fromAdvance = -1, toAdvance = -1; TextRunWalker walker(run, 0, this); + walker.setWordSpacingAdjustment(wordSpacing()); + walker.setLetterSpacingAdjustment(letterSpacing()); // Base will point to the x offset for the current script run. Note that, in // the LTR case, width will be 0. diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h index 1d6cc8e..beac0bf 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h +++ b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h @@ -34,10 +34,10 @@ #include "config.h" -#include "StringImpl.h" #include <wtf/Forward.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> +#include <wtf/text/StringImpl.h> #include <usp10.h> diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp index 9b54732..b51eb8c 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp @@ -35,11 +35,12 @@ #include "HarfbuzzSkia.h" #include "NotImplemented.h" #include "PlatformString.h" -#include "StringImpl.h" #include "SkPaint.h" #include "SkTypeface.h" +#include <wtf/text/StringImpl.h> + namespace WebCore { static SkPaint::Hinting skiaHinting = SkPaint::kNormal_Hinting; diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h index de12832..363e55f 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h +++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h @@ -32,10 +32,10 @@ #define FontPlatformDataLinux_h #include "FontRenderStyle.h" -#include "StringImpl.h" #include <wtf/Forward.h> #include <wtf/RefPtr.h> #include <wtf/text/CString.h> +#include <wtf/text/StringImpl.h> #include <SkPaint.h> class SkTypeface; diff --git a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp index 78170a9..e725c50 100644 --- a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp @@ -34,11 +34,11 @@ #include <limits> #include "PlatformString.h" -#include "StringHash.h" #include "UniscribeHelper.h" #include <unicode/locid.h> #include <unicode/uchar.h> #include <wtf/HashMap.h> +#include <wtf/text/StringHash.h> namespace WebCore { diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp index 8a9bde1..534de7b 100644 --- a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp +++ b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp @@ -38,14 +38,15 @@ #include "FloatRect.h" #include "GLES2Texture.h" #include "GraphicsContext3D.h" +#include "IntRect.h" #include "PlatformString.h" #include "Uint16Array.h" #define _USE_MATH_DEFINES #include <math.h> -#include <wtf/text/CString.h> #include <wtf/OwnArrayPtr.h> +#include <wtf/text/CString.h> namespace WebCore { @@ -221,7 +222,6 @@ void GLES2Canvas::drawTexturedRect(GLES2Texture* texture, const FloatRect& srcRe checkGLError("glUseProgram"); m_context->activeTexture(GraphicsContext3D::TEXTURE0); - texture->bind(); m_context->uniform1i(m_texSamplerLocation, 0); checkGLError("glUniform1i"); @@ -229,28 +229,52 @@ void GLES2Canvas::drawTexturedRect(GLES2Texture* texture, const FloatRect& srcRe m_context->uniform1f(m_texAlphaLocation, alpha); checkGLError("glUniform1f for alpha"); + m_context->vertexAttribPointer(m_texPositionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); + + m_context->enableVertexAttribArray(m_texPositionLocation); + + const TilingData& tiles = texture->tiles(); + IntRect tileIdxRect = tiles.overlappedTileIndices(srcRect); + + for (int y = tileIdxRect.y(); y <= tileIdxRect.bottom(); y++) { + for (int x = tileIdxRect.x(); x <= tileIdxRect.right(); x++) + drawTexturedRectTile(texture, tiles.tileIndex(x, y), srcRect, dstRect, transform); + } +} + +void GLES2Canvas::drawTexturedRectTile(GLES2Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform) +{ + if (dstRect.isEmpty()) + return; + + const TilingData& tiles = texture->tiles(); + + texture->bindTile(tile); + + FloatRect srcRectClippedInTileSpace; + FloatRect dstRectIntersected; + tiles.intersectDrawQuad(srcRect, dstRect, tile, &srcRectClippedInTileSpace, &dstRectIntersected); + + IntRect tileBoundsWithBorder = tiles.tileBoundsWithBorder(tile); + AffineTransform matrix(m_flipMatrix); matrix.multLeft(transform); - matrix.translate(dstRect.x(), dstRect.y()); - matrix.scale(dstRect.width(), dstRect.height()); + matrix.translate(dstRectIntersected.x(), dstRectIntersected.y()); + matrix.scale(dstRectIntersected.width(), dstRectIntersected.height()); float mat[9]; affineTo3x3(matrix, mat); m_context->uniformMatrix3fv(m_texMatrixLocation, false /*transpose*/, mat, 1 /*count*/); checkGLError("glUniformMatrix3fv"); AffineTransform texMatrix; - texMatrix.scale(1.0f / texture->width(), 1.0f / texture->height()); - texMatrix.translate(srcRect.x(), srcRect.y()); - texMatrix.scale(srcRect.width(), srcRect.height()); + texMatrix.scale(1.0f / tileBoundsWithBorder.width(), 1.0f / tileBoundsWithBorder.height()); + texMatrix.translate(srcRectClippedInTileSpace.x(), srcRectClippedInTileSpace.y()); + texMatrix.scale(srcRectClippedInTileSpace.width(), srcRectClippedInTileSpace.height()); float texMat[9]; affineTo3x3(texMatrix, texMat); m_context->uniformMatrix3fv(m_texTexMatrixLocation, false /*transpose*/, texMat, 1 /*count*/); checkGLError("glUniformMatrix3fv"); - m_context->vertexAttribPointer(m_texPositionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); - - m_context->enableVertexAttribArray(m_texPositionLocation); - m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0); checkGLError("glDrawElements"); } diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.h b/WebCore/platform/graphics/chromium/GLES2Canvas.h index cea90ae..0ad07fc 100644 --- a/WebCore/platform/graphics/chromium/GLES2Canvas.h +++ b/WebCore/platform/graphics/chromium/GLES2Canvas.h @@ -81,6 +81,7 @@ public: GLES2Texture* getTexture(NativeImagePtr); private: + void drawTexturedRectTile(GLES2Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&); void applyCompositeOperator(CompositeOperator); void checkGLError(const char* header); unsigned getQuadVertices(); diff --git a/WebCore/platform/graphics/chromium/GLES2Texture.cpp b/WebCore/platform/graphics/chromium/GLES2Texture.cpp index 5e8a141..ae230db 100644 --- a/WebCore/platform/graphics/chromium/GLES2Texture.cpp +++ b/WebCore/platform/graphics/chromium/GLES2Texture.cpp @@ -35,45 +35,27 @@ #include "GLES2Texture.h" #include "GraphicsContext3D.h" - +#include "IntRect.h" #include <wtf/OwnArrayPtr.h> namespace WebCore { -GLES2Texture::GLES2Texture(GraphicsContext3D* context, unsigned textureId, Format format, int width, int height) + +GLES2Texture::GLES2Texture(GraphicsContext3D* context, PassOwnPtr<Vector<unsigned int> > tileTextureIds, Format format, int width, int height, int maxTextureSize) : m_context(context) - , m_textureId(textureId) , m_format(format) - , m_width(width) - , m_height(height) + , m_tiles(maxTextureSize, width, height, true) + , m_tileTextureIds(tileTextureIds) { } GLES2Texture::~GLES2Texture() { - m_context->deleteTexture(m_textureId); -} - -PassRefPtr<GLES2Texture> GLES2Texture::create(GraphicsContext3D* context, Format format, int width, int height) -{ - int max; - context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &max); - if (width > max || height > max) { - ASSERT(!"texture too big"); - return 0; - } - - unsigned textureId = context->createTexture(); - if (!textureId) - return 0; - - context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId); - context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, width, height, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0); - - return adoptRef(new GLES2Texture(context, textureId, format, width, height)); + for (unsigned int i = 0; i < m_tileTextureIds->size(); i++) + m_context->deleteTexture(m_tileTextureIds->at(i)); } -static void convertFormat(GLES2Texture::Format format, unsigned int* glFormat, unsigned int* glType, bool* swizzle) +static void convertFormat(GraphicsContext3D* context, GLES2Texture::Format format, unsigned int* glFormat, unsigned int* glType, bool* swizzle) { *swizzle = false; switch (format) { @@ -82,43 +64,113 @@ static void convertFormat(GLES2Texture::Format format, unsigned int* glFormat, u *glType = GraphicsContext3D::UNSIGNED_BYTE; break; case GLES2Texture::BGRA8: -// FIXME: Once we have support for extensions, we should check for EXT_texture_format_BGRA8888, -// and use that if present. - *glFormat = GraphicsContext3D::RGBA; - *glType = GraphicsContext3D::UNSIGNED_BYTE; - *swizzle = true; + if (context->supportsBGRA()) { + *glFormat = GraphicsContext3D::BGRA_EXT; + *glType = GraphicsContext3D::UNSIGNED_BYTE; + } else { + *glFormat = GraphicsContext3D::RGBA; + *glType = GraphicsContext3D::UNSIGNED_BYTE; + *swizzle = true; + } break; default: - ASSERT(!"bad format"); + ASSERT_NOT_REACHED(); break; } } +PassRefPtr<GLES2Texture> GLES2Texture::create(GraphicsContext3D* context, Format format, int width, int height) +{ + int maxTextureSize = 0; + context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize); + + TilingData tiling(maxTextureSize, width, height, true); + int numTiles = tiling.numTiles(); + + OwnPtr<Vector<unsigned int> > textureIds(new Vector<unsigned int>(numTiles)); + textureIds->fill(0, numTiles); + + for (int i = 0; i < numTiles; i++) { + int textureId = context->createTexture(); + if (!textureId) { + for (int i = 0; i < numTiles; i++) + context->deleteTexture(textureIds->at(i)); + return 0; + } + textureIds->at(i) = textureId; + + IntRect tileBoundsWithBorder = tiling.tileBoundsWithBorder(i); + + unsigned int glFormat, glType; + bool swizzle; + convertFormat(context, format, &glFormat, &glType, &swizzle); + context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId); + context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, glFormat, + tileBoundsWithBorder.width(), + tileBoundsWithBorder.height(), + 0, glFormat, glType, 0); + } + return adoptRef(new GLES2Texture(context, textureIds.leakPtr(), format, width, height, maxTextureSize)); +} + +template <bool swizzle> +static uint32_t* copySubRect(uint32_t* src, int srcX, int srcY, uint32_t* dst, int width, int height, int srcStride) +{ + uint32_t* srcOffset = src + srcX + srcY * srcStride; + + if (!swizzle && width == srcStride) + return srcOffset; + + uint32_t* dstPixel = dst; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width ; x++) { + uint32_t pixel = srcOffset[x + y * srcStride]; + if (swizzle) + *dstPixel = pixel & 0xFF00FF00 | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16); + else + *dstPixel = pixel; + dstPixel++; + } + } + return dst; +} + void GLES2Texture::load(void* pixels) { + uint32_t* pixels32 = static_cast<uint32_t*>(pixels); unsigned int glFormat, glType; bool swizzle; - convertFormat(m_format, &glFormat, &glType, &swizzle); - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId); + convertFormat(m_context, m_format, &glFormat, &glType, &swizzle); if (swizzle) { ASSERT(glFormat == GraphicsContext3D::RGBA && glType == GraphicsContext3D::UNSIGNED_BYTE); // FIXME: This could use PBO's to save doing an extra copy here. - int size = m_width * m_height; - unsigned* pixels32 = static_cast<unsigned*>(pixels); - OwnArrayPtr<unsigned> buf(new unsigned[size]); - unsigned* bufptr = buf.get(); - for (int i = 0; i < size; ++i) { - unsigned pixel = pixels32[i]; - bufptr[i] = pixel & 0xFF00FF00 | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16); + } + OwnArrayPtr<uint32_t> tempBuff(new uint32_t[m_tiles.maxTextureSize() * m_tiles.maxTextureSize()]); + + for (int i = 0; i < m_tiles.numTiles(); i++) { + IntRect tileBoundsWithBorder = m_tiles.tileBoundsWithBorder(i); + + uint32_t* uploadBuff = 0; + if (swizzle) { + uploadBuff = copySubRect<true>( + pixels32, tileBoundsWithBorder.x(), tileBoundsWithBorder.y(), + tempBuff.get(), tileBoundsWithBorder.width(), tileBoundsWithBorder.height(), m_tiles.totalSizeX()); + } else { + uploadBuff = copySubRect<false>( + pixels32, tileBoundsWithBorder.x(), tileBoundsWithBorder.y(), + tempBuff.get(), tileBoundsWithBorder.width(), tileBoundsWithBorder.height(), m_tiles.totalSizeX()); } - m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, m_width, m_height, glFormat, glType, buf.get()); - } else - m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, m_width, m_height, glFormat, glType, pixels); + + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_tileTextureIds->at(i)); + m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, + tileBoundsWithBorder.width(), + tileBoundsWithBorder.height(), glFormat, glType, uploadBuff); + } } -void GLES2Texture::bind() +void GLES2Texture::bindTile(int tile) { - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId); + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_tileTextureIds->at(tile)); m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); diff --git a/WebCore/platform/graphics/chromium/GLES2Texture.h b/WebCore/platform/graphics/chromium/GLES2Texture.h index 4d351cd..43a4955 100644 --- a/WebCore/platform/graphics/chromium/GLES2Texture.h +++ b/WebCore/platform/graphics/chromium/GLES2Texture.h @@ -35,6 +35,10 @@ #include "RefCounted.h" #include "RefPtr.h" +#include "TilingData.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/Vector.h> namespace WebCore { class GraphicsContext3D; @@ -44,18 +48,16 @@ public: ~GLES2Texture(); enum Format { RGBA8, BGRA8 }; static PassRefPtr<GLES2Texture> create(GraphicsContext3D*, Format, int width, int height); - void bind(); + void bindTile(int tile); void load(void* pixels); Format format() const { return m_format; } - int width() const { return m_width; } - int height() const { return m_height; } + const TilingData& tiles() const { return m_tiles; } private: - GLES2Texture(GraphicsContext3D*, unsigned textureId, Format, int width, int height); + GLES2Texture(GraphicsContext3D*, PassOwnPtr<Vector<unsigned int> > tileTextureIds, Format format, int width, int height, int maxTextureSize); GraphicsContext3D* m_context; - unsigned m_textureId; Format m_format; - int m_width; - int m_height; + TilingData m_tiles; + OwnPtr<Vector<unsigned int> > m_tileTextureIds; }; } diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp index 9f6ee17..3cc7cad 100644 --- a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp @@ -114,7 +114,7 @@ void ImageLayerChromium::updateTextureContents(unsigned textureId) case kCGColorSpaceModelDeviceN: break; default: - colorSpace.adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear)); + colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB()); break; } RetainPtr<CGContextRef> tempContext(AdoptCF, CGBitmapContextCreate(tempVector.data(), diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp index bba65f4..21d8d12 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -180,8 +180,7 @@ void LayerChromium::updateTextureContents(unsigned textureId) int rowBytes = 4 * dirtyRect.width(); tempVector.resize(rowBytes * dirtyRect.height()); memset(tempVector.data(), 0, tempVector.size()); - // FIXME: unsure whether this is the best color space choice. - RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear)); + RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); RetainPtr<CGContextRef> contextCG(AdoptCF, CGBitmapContextCreate(tempVector.data(), dirtyRect.width(), dirtyRect.height(), 8, rowBytes, colorSpace.get(), diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h index ebb4504..9fba415 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/WebCore/platform/graphics/chromium/LayerChromium.h @@ -38,12 +38,12 @@ #include "GraphicsContext.h" #include "GraphicsLayerChromium.h" #include "PlatformString.h" -#include "StringHash.h" #include "TransformationMatrix.h" #include <wtf/OwnPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/Vector.h> +#include <wtf/text/StringHash.h> namespace skia { diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index 15acfa5..2f70efa 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -255,8 +255,7 @@ void LayerRendererChromium::setRootLayerCanvasSize(const IntSize& size) int rowBytes = 4 * size.width(); m_rootLayerBackingStore.resize(rowBytes * size.height()); memset(m_rootLayerBackingStore.data(), 0, m_rootLayerBackingStore.size()); - // FIXME: unsure whether this is the best color space choice. - RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear)); + RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); m_rootLayerCGContext.adoptCF(CGBitmapContextCreate(m_rootLayerBackingStore.data(), size.width(), size.height(), 8, rowBytes, colorSpace.get(), diff --git a/WebCore/platform/graphics/chromium/TilingData.cpp b/WebCore/platform/graphics/chromium/TilingData.cpp new file mode 100755 index 0000000..c52288d --- /dev/null +++ b/WebCore/platform/graphics/chromium/TilingData.cpp @@ -0,0 +1,218 @@ +/* + * 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 "TilingData.h" + +#include "FloatRect.h" +#include "IntRect.h" +#include <algorithm> + +using namespace std; + +namespace WebCore { + +static int computeNumTiles(int maxTextureSize, int totalSize, int borderTexels) +{ + return max(1, 1 + (totalSize - 1 - 2 * borderTexels) / (maxTextureSize - 2 * borderTexels)); +} + +TilingData::TilingData(int maxTextureSize, int totalSizeX, int totalSizeY, bool hasBorderTexels) + : m_maxTextureSize(maxTextureSize) + , m_totalSizeX(totalSizeX) + , m_totalSizeY(totalSizeY) + , m_borderTexels(hasBorderTexels ? 1 : 0) +{ + m_numTilesX = computeNumTiles(maxTextureSize, m_totalSizeX, m_borderTexels); + m_numTilesY = computeNumTiles(maxTextureSize, m_totalSizeY, m_borderTexels); +} + +int TilingData::tileXIndexFromSrcCoord(int srcPos) const +{ + int x = (srcPos - m_borderTexels) / (m_maxTextureSize - 2 * m_borderTexels); + return min(max(x, 0), numTilesX() - 1); +} + +int TilingData::tileYIndexFromSrcCoord(int srcPos) const +{ + int y = (srcPos - m_borderTexels) / (m_maxTextureSize - 2 * m_borderTexels); + return min(max(y, 0), numTilesY() - 1); +} + +IntRect TilingData::tileBounds(int tile) const +{ + assertTile(tile); + int ix = tileXIndex(tile); + int iy = tileYIndex(tile); + int x = tilePositionX(ix); + int y = tilePositionY(iy); + int width = tileSizeX(ix); + int height = tileSizeY(iy); + ASSERT(x >= 0 && y >= 0 && width >= 0 && height >= 0); + ASSERT(x <= totalSizeX() && y <= totalSizeY()); + return IntRect(x, y, width, height); +} + +IntRect TilingData::tileBoundsWithBorder(int tile) const +{ + IntRect bounds = tileBounds(tile); + + if (m_borderTexels) { + int x1 = bounds.x(); + int x2 = bounds.right(); + int y1 = bounds.y(); + int y2 = bounds.bottom(); + + if (tileXIndex(tile) > 0) + x1--; + if (tileXIndex(tile) < (numTilesX() - 1)) + x2++; + if (tileYIndex(tile) > 0) + y1--; + if (tileYIndex(tile) < (numTilesY() - 1)) + y2++; + + bounds = IntRect(x1, y1, x2 - x1, y2 - y1); + } + + return bounds; +} + +FloatRect TilingData::tileBoundsNormalized(int tile) const +{ + assertTile(tile); + FloatRect bounds(tileBounds(tile)); + bounds.scale(1.0f / m_totalSizeX, 1.0f / m_totalSizeY); + return bounds; +} + +int TilingData::tilePositionX(int xIndex) const +{ + ASSERT(xIndex >= 0 && xIndex < numTilesX()); + + if (!xIndex) + return 0; + return tilePositionX(xIndex - 1) + tileSizeX(xIndex - 1); +} + +int TilingData::tilePositionY(int yIndex) const +{ + ASSERT(yIndex >= 0 && yIndex < numTilesY()); + + if (!yIndex) + return 0; + return tilePositionX(yIndex - 1) + tileSizeY(yIndex - 1); +} + +int TilingData::tileSizeX(int xIndex) const +{ + ASSERT(xIndex >= 0 && xIndex < numTilesX()); + + int size = maxTextureSize(); + size = min(size, totalSizeX()); + + if (!xIndex && m_numTilesX == 1) + return m_totalSizeX; + if (!xIndex && m_numTilesX > 1) + return m_maxTextureSize - m_borderTexels; + if (xIndex < numTilesX() - 1) + return m_maxTextureSize - 2 * m_borderTexels; + if (xIndex == numTilesX() - 1) + return m_totalSizeX - tilePositionX(xIndex); + + ASSERT_NOT_REACHED(); + return 0; +} + +int TilingData::tileSizeY(int yIndex) const +{ + ASSERT(yIndex >= 0 && yIndex < numTilesY()); + + int size = maxTextureSize(); + size = min(size, totalSizeY()); + + if (!yIndex && m_numTilesY == 1) + return m_totalSizeY; + if (!yIndex && m_numTilesY > 1) + return m_maxTextureSize - m_borderTexels; + if (yIndex < numTilesY() - 1) + return m_maxTextureSize - 2 * m_borderTexels; + if (yIndex == numTilesY() - 1) + return m_totalSizeY - tilePositionY(yIndex); + + ASSERT_NOT_REACHED(); + return 0; +} + +IntRect TilingData::overlappedTileIndices(const WebCore::IntRect &srcRect) const +{ + int x = tileXIndexFromSrcCoord(srcRect.x()); + int y = tileYIndexFromSrcCoord(srcRect.y()); + int r = tileXIndexFromSrcCoord(srcRect.right()); + int b = tileYIndexFromSrcCoord(srcRect.bottom()); + return IntRect(x, y, r - x, b - y); +} + +IntRect TilingData::overlappedTileIndices(const WebCore::FloatRect &srcRect) const +{ + return overlappedTileIndices(enclosingIntRect(srcRect)); +} + +void TilingData::intersectDrawQuad(const FloatRect& srcRect, const FloatRect& dstRect, int tile, + FloatRect* newSrc, FloatRect* newDst) const +{ + // Intersect with tile + FloatRect tileBounds = this->tileBounds(tile); + FloatRect srcRectIntersected = srcRect; + srcRectIntersected.intersect(tileBounds); + + if (srcRectIntersected.isEmpty()) { + *newSrc = *newDst = FloatRect(0, 0, 0, 0); + return; + } + + float srcRectIntersectedNormX = (srcRectIntersected.x() - srcRect.x()) / srcRect.width(); + float srcRectIntersectedNormY = (srcRectIntersected.y() - srcRect.y()) / srcRect.height(); + float srcRectIntersectedNormW = srcRectIntersected.width() / srcRect.width(); + float srcRectIntersectedNormH = srcRectIntersected.height() / srcRect.height(); + + *newSrc = srcRectIntersected; + newSrc->move( + -tileBounds.x() + ((tileXIndex(tile) > 0) ? m_borderTexels : 0), + -tileBounds.y() + ((tileYIndex(tile) > 0) ? m_borderTexels : 0)); + + *newDst = FloatRect( + srcRectIntersectedNormX * dstRect.width() + dstRect.x(), + srcRectIntersectedNormY * dstRect.height() + dstRect.y(), + srcRectIntersectedNormW * dstRect.width(), + srcRectIntersectedNormH * dstRect.height()); +} + +} diff --git a/WebCore/platform/graphics/chromium/TilingData.h b/WebCore/platform/graphics/chromium/TilingData.h new file mode 100755 index 0000000..f12e66e --- /dev/null +++ b/WebCore/platform/graphics/chromium/TilingData.h @@ -0,0 +1,87 @@ +/* + * 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. + */ + +#ifndef TilingData_h +#define TilingData_h + +#include <wtf/Noncopyable.h> + +namespace WebCore { + +class FloatRect; +class IntRect; + +class TilingData : public Noncopyable { +public: + TilingData(int maxTextureSize, int totalSizeX, int totalSizeY, bool hasBorderTexels); + int maxTextureSize() const { return m_maxTextureSize; } + int totalSizeX() const { return m_totalSizeX; } + int totalSizeY() const { return m_totalSizeY; } + + int numTiles() const { return numTilesX() * numTilesY(); } + int numTilesX() const { return m_numTilesX; } + int numTilesY() const { return m_numTilesY; } + int tileIndex(int x, int y) const { return x + y * numTilesX(); } + int tileXIndex(int tile) const { assertTile(tile); return tile % numTilesX(); } + int tileYIndex(int tile) const { assertTile(tile); return tile / numTilesX(); } + int tileXIndexFromSrcCoord(int) const; + int tileYIndexFromSrcCoord(int) const; + + IntRect tileBounds(int tile) const; + IntRect tileBoundsWithBorder(int tile) const; + FloatRect tileBoundsNormalized(int tile) const; + int tilePositionX(int xIndex) const; + int tilePositionY(int yIndex) const; + int tileSizeX(int xIndex) const; + int tileSizeY(int yIndex) const; + IntRect overlappedTileIndices(const IntRect& srcRect) const; + IntRect overlappedTileIndices(const FloatRect& srcRect) const; + + // Given a set of source and destination coordinates for a drawing quad + // in texel units, returns adjusted data to render just the one tile. + void intersectDrawQuad(const FloatRect& srcRect, const FloatRect& dstRect, int tile, FloatRect* newSrc, FloatRect* newDst) const; + +private: + TilingData() : m_maxTextureSize(0), m_totalSizeX(0), m_totalSizeY(0) {} + void assertTile(int tile) const { ASSERT(tile >= 0 && tile < numTiles()); } + + int m_maxTextureSize; + int m_totalSizeX; + int m_totalSizeY; + int m_borderTexels; // 0 or 1 + + // computed values: + int m_numTilesX; + int m_numTilesY; +}; + +} + +#endif // TilingData_h diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/WebCore/platform/graphics/filters/FEColorMatrix.cpp index c5ae3b9..7718066 100644 --- a/WebCore/platform/graphics/filters/FEColorMatrix.cpp +++ b/WebCore/platform/graphics/filters/FEColorMatrix.cpp @@ -164,7 +164,7 @@ void FEColorMatrix::apply(Filter* filter) if (!filterContext) return; - filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); + filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); IntRect imageRect(IntPoint(), resultImage()->size()); PassRefPtr<ImageData> imageData(resultImage()->getUnmultipliedImageData(imageRect)); diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp index 18df3b2..0bafc48 100644 --- a/WebCore/platform/graphics/filters/FEComposite.cpp +++ b/WebCore/platform/graphics/filters/FEComposite.cpp @@ -131,26 +131,26 @@ void FEComposite::apply(Filter* filter) FloatRect srcRect = FloatRect(0.f, 0.f, -1.f, -1.f); switch (m_type) { case FECOMPOSITE_OPERATOR_OVER: - filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); - filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); + filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); + filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); break; case FECOMPOSITE_OPERATOR_IN: filterContext->save(); - filterContext->clipToImageBuffer(calculateDrawingRect(m_in2->scaledSubRegion()), m_in2->resultImage()); - filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); + filterContext->clipToImageBuffer(m_in->resultImage(), calculateDrawingRect(m_in2->scaledSubRegion())); + filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); filterContext->restore(); break; case FECOMPOSITE_OPERATOR_OUT: - filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); - filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()), srcRect, CompositeDestinationOut); + filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); + filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()), srcRect, CompositeDestinationOut); break; case FECOMPOSITE_OPERATOR_ATOP: - filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); - filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeSourceAtop); + filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); + filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeSourceAtop); break; case FECOMPOSITE_OPERATOR_XOR: - filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); - filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeXOR); + filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); + filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeXOR); break; case FECOMPOSITE_OPERATOR_ARITHMETIC: { IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion()); diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp index 61aea90..70465a0 100644 --- a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp +++ b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp @@ -3,6 +3,7 @@ 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 @@ -29,18 +30,19 @@ #include "Filter.h" #include "GraphicsContext.h" #include "ImageData.h" -#include <math.h> #include <wtf/MathExtras.h> using std::max; +static const float gGaussianKernelFactor = (3 * sqrtf(2 * piFloat) / 4.f); + namespace WebCore { FEGaussianBlur::FEGaussianBlur(FilterEffect* in, const float& x, const float& y) : FilterEffect() , m_in(in) - , m_x(x) - , m_y(y) + , m_stdX(x) + , m_stdY(y) { } @@ -51,30 +53,27 @@ PassRefPtr<FEGaussianBlur> FEGaussianBlur::create(FilterEffect* in, const float& float FEGaussianBlur::stdDeviationX() const { - return m_x; + return m_stdX; } void FEGaussianBlur::setStdDeviationX(float x) { - m_x = x; + m_stdX = x; } float FEGaussianBlur::stdDeviationY() const { - return m_y; + return m_stdY; } void FEGaussianBlur::setStdDeviationY(float y) { - m_y = y; + m_stdY = y; } static void boxBlur(CanvasPixelArray*& srcPixelArray, CanvasPixelArray*& dstPixelArray, - unsigned dx, int stride, int strideLine, int effectWidth, int effectHeight, bool alphaImage) + unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight, bool alphaImage) { - int dxLeft = dx / 2; - int dxRight = dx - dxLeft; - for (int y = 0; y < effectHeight; ++y) { int line = y * strideLine; for (int channel = 3; channel >= 0; --channel) { @@ -99,6 +98,34 @@ static void boxBlur(CanvasPixelArray*& srcPixelArray, CanvasPixelArray*& dstPixe } } +void FEGaussianBlur::kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight) +{ + // check http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement for details + switch (boxBlur) { + case 0: + if (!(std % 2)) { + dLeft = std / 2 - 1; + dRight = std - dLeft; + } else { + dLeft = std / 2; + dRight = std - dLeft; + } + break; + case 1: + if (!(std % 2)) { + dLeft++; + dRight--; + } + break; + case 2: + if (!(std % 2)) { + dRight++; + std++; + } + break; + } +} + void FEGaussianBlur::apply(Filter* filter) { m_in->apply(filter); @@ -110,26 +137,50 @@ void FEGaussianBlur::apply(Filter* filter) setIsAlphaImage(m_in->isAlphaImage()); - if (m_x == 0 || m_y == 0) + IntRect effectDrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion()); + RefPtr<ImageData> srcImageData(m_in->resultImage()->getPremultipliedImageData(effectDrawingRect)); + IntRect imageRect(IntPoint(), resultImage()->size()); + + if (!m_stdX && !m_stdY) { + resultImage()->putPremultipliedImageData(srcImageData.get(), imageRect, IntPoint()); return; + } - unsigned sdx = static_cast<unsigned>(floor(m_x * filter->filterResolution().width() * 3 * sqrt(2 * piDouble) / 4.f + 0.5f)); - unsigned sdy = static_cast<unsigned>(floor(m_y * filter->filterResolution().height() * 3 * sqrt(2 * piDouble) / 4.f + 0.5f)); - sdx = max(sdx, static_cast<unsigned>(1)); - sdy = max(sdy, static_cast<unsigned>(1)); + unsigned kernelSizeX = 0; + if (m_stdX) + kernelSizeX = max(2U, static_cast<unsigned>(floor(m_stdX * filter->filterResolution().width() * gGaussianKernelFactor + 0.5f))); - IntRect effectDrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion()); - RefPtr<ImageData> srcImageData(m_in->resultImage()->getPremultipliedImageData(effectDrawingRect)); - CanvasPixelArray* srcPixelArray(srcImageData->data()); + unsigned kernelSizeY = 0; + if (m_stdY) + kernelSizeY = max(2U, static_cast<unsigned>(floor(m_stdY * filter->filterResolution().height() * gGaussianKernelFactor + 0.5f))); - IntRect imageRect(IntPoint(), resultImage()->size()); + CanvasPixelArray* srcPixelArray(srcImageData->data()); RefPtr<ImageData> tmpImageData = ImageData::create(imageRect.width(), imageRect.height()); CanvasPixelArray* tmpPixelArray(tmpImageData->data()); int stride = 4 * imageRect.width(); + int dxLeft = 0; + int dxRight = 0; + int dyLeft = 0; + int dyRight = 0; for (int i = 0; i < 3; ++i) { - boxBlur(srcPixelArray, tmpPixelArray, sdx, 4, stride, imageRect.width(), imageRect.height(), isAlphaImage()); - boxBlur(tmpPixelArray, srcPixelArray, sdy, stride, 4, imageRect.height(), imageRect.width(), isAlphaImage()); + if (kernelSizeX) { + kernelPosition(i, kernelSizeX, dxLeft, dxRight); + boxBlur(srcPixelArray, tmpPixelArray, kernelSizeX, dxLeft, dxRight, 4, stride, imageRect.width(), imageRect.height(), isAlphaImage()); + } else { + CanvasPixelArray* auxPixelArray = tmpPixelArray; + tmpPixelArray = srcPixelArray; + srcPixelArray = auxPixelArray; + } + + if (kernelSizeY) { + kernelPosition(i, kernelSizeY, dyLeft, dyRight); + boxBlur(tmpPixelArray, srcPixelArray, kernelSizeY, dyLeft, dyRight, stride, 4, imageRect.height(), imageRect.width(), isAlphaImage()); + } else { + CanvasPixelArray* auxPixelArray = tmpPixelArray; + tmpPixelArray = srcPixelArray; + srcPixelArray = auxPixelArray; + } } resultImage()->putPremultipliedImageData(srcImageData.get(), imageRect, IntPoint()); @@ -144,7 +195,7 @@ TextStream& FEGaussianBlur::externalRepresentation(TextStream& ts, int indent) c writeIndent(ts, indent); ts << "[feGaussianBlur"; FilterEffect::externalRepresentation(ts); - ts << " stdDeviation=\"" << m_x << ", " << m_y << "\"]\n"; + ts << " stdDeviation=\"" << m_stdX << ", " << m_stdY << "\"]\n"; m_in->externalRepresentation(ts, indent + 1); return ts; } diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.h b/WebCore/platform/graphics/filters/FEGaussianBlur.h index bcc030e..4c7c43c 100644 --- a/WebCore/platform/graphics/filters/FEGaussianBlur.h +++ b/WebCore/platform/graphics/filters/FEGaussianBlur.h @@ -45,10 +45,11 @@ public: private: FEGaussianBlur(FilterEffect*, const float&, const float&); + static void kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight); RefPtr<FilterEffect> m_in; - float m_x; - float m_y; + float m_stdX; + float m_stdY; }; } // namespace WebCore diff --git a/WebCore/platform/graphics/filters/Filter.h b/WebCore/platform/graphics/filters/Filter.h index 8924b94..16d499f 100644 --- a/WebCore/platform/graphics/filters/Filter.h +++ b/WebCore/platform/graphics/filters/Filter.h @@ -24,11 +24,11 @@ #include "FloatRect.h" #include "FloatSize.h" #include "ImageBuffer.h" -#include "StringHash.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> +#include <wtf/text/StringHash.h> namespace WebCore { diff --git a/WebCore/platform/graphics/filters/SourceAlpha.cpp b/WebCore/platform/graphics/filters/SourceAlpha.cpp index eb23814..37b0023 100644 --- a/WebCore/platform/graphics/filters/SourceAlpha.cpp +++ b/WebCore/platform/graphics/filters/SourceAlpha.cpp @@ -63,9 +63,9 @@ void SourceAlpha::apply(Filter* filter) setIsAlphaImage(true); - FloatRect imageRect(FloatPoint(), filter->sourceImage()->image()->size()); + FloatRect imageRect(FloatPoint(), filter->sourceImage()->size()); filterContext->save(); - filterContext->clipToImageBuffer(imageRect, filter->sourceImage()); + filterContext->clipToImageBuffer(filter->sourceImage(), imageRect); filterContext->fillRect(imageRect, Color::black, DeviceColorSpace); filterContext->restore(); } diff --git a/WebCore/platform/graphics/filters/SourceGraphic.cpp b/WebCore/platform/graphics/filters/SourceGraphic.cpp index a1864d6..5730d34 100644 --- a/WebCore/platform/graphics/filters/SourceGraphic.cpp +++ b/WebCore/platform/graphics/filters/SourceGraphic.cpp @@ -60,7 +60,7 @@ void SourceGraphic::apply(Filter* filter) if (!filterContext) return; - filterContext->drawImage(filter->sourceImage()->image(), DeviceColorSpace, IntPoint()); + filterContext->drawImageBuffer(filter->sourceImage(), DeviceColorSpace, IntPoint()); } void SourceGraphic::dump() diff --git a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp index d3b5f1b..1059b59 100644 --- a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp @@ -780,9 +780,13 @@ void StreamingClient::didFail(ResourceHandle*, const ResourceError& error) void StreamingClient::wasBlocked(ResourceHandle*) { + GST_ERROR_OBJECT(m_src, "Request was blocked"); + GST_ELEMENT_ERROR(m_src, RESOURCE, OPEN_READ, ("Access to \"%s\" was blocked", m_src->priv->uri), (0)); } void StreamingClient::cannotShowURL(ResourceHandle*) { + GST_ERROR_OBJECT(m_src, "Cannot show URL"); + GST_ELEMENT_ERROR(m_src, RESOURCE, OPEN_READ, ("Can't show \"%s\"", m_src->priv->uri), (0)); } diff --git a/WebCore/platform/graphics/gtk/ImageGtk.cpp b/WebCore/platform/graphics/gtk/ImageGtk.cpp index 30db6d7..5272243 100644 --- a/WebCore/platform/graphics/gtk/ImageGtk.cpp +++ b/WebCore/platform/graphics/gtk/ImageGtk.cpp @@ -27,81 +27,60 @@ #include "BitmapImage.h" #include "CairoUtilities.h" -#include "GOwnPtr.h" +#include "GOwnPtrGtk.h" #include "SharedBuffer.h" #include <wtf/text/CString.h> #include <cairo.h> #include <gtk/gtk.h> -#ifdef _WIN32 -# include <mbstring.h> -# include <shlobj.h> -/* search for data relative to where we are installed */ +#if PLATFORM(WIN) +#include <mbstring.h> +#include <shlobj.h> static HMODULE hmodule; -#ifdef __cplusplus extern "C" { -#endif -BOOL WINAPI -DllMain(HINSTANCE hinstDLL, - DWORD fdwReason, - LPVOID lpvReserved) +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - switch (fdwReason) { - case DLL_PROCESS_ATTACH: + if (fdwReason == DLL_PROCESS_ATTACH) hmodule = hinstDLL; - break; - } - return TRUE; } -#ifdef __cplusplus } -#endif -static char * -get_webkit_datadir(void) +static const char* getWebKitDataDirectory() { - static char retval[1000]; - static int beenhere = 0; - - unsigned char *p; - - if (beenhere) - return retval; + static char* dataDirectory = 0; + if (dataDirectory) + return dataDirectory; - if (!GetModuleFileName (hmodule, (CHAR *) retval, sizeof(retval) - 10)) + dataDirectory = new char[PATH_MAX]; + if (!GetModuleFileName(hmodule, static_cast<CHAR*>(dataDirectory), sizeof(dataDirectory) - 10)) return DATA_DIR; - p = _mbsrchr((const unsigned char *) retval, '\\'); + // FIXME: This is pretty ugly. Ideally we should be using Windows API + // functions or GLib methods to calculate paths. + unsigned char *p; + p = _mbsrchr(static_cast<const unsigned char *>(dataDirectory), '\\'); *p = '\0'; - p = _mbsrchr((const unsigned char *) retval, '\\'); + p = _mbsrchr(static_cast<const unsigned char *>(dataDirectory), '\\'); if (p) { if (!stricmp((const char *) (p+1), "bin")) *p = '\0'; } - strcat(retval, "\\share"); - - beenhere = 1; + strcat(dataDirectory, "\\share"); - return retval; + return dataDirectory; } -#undef DATA_DIR -#define DATA_DIR get_webkit_datadir () -#endif - +#else -namespace WTF { - -template <> void freeOwnedGPtr<GtkIconInfo>(GtkIconInfo* info) +static const char* getWebKitDataDirectory() { - if (info) - gtk_icon_info_free(info); + return DATA_DIR; } -} +#endif namespace WebCore { @@ -158,11 +137,9 @@ PassRefPtr<Image> Image::loadPlatformResource(const char* name) if (!strcmp("missingImage", name)) fileName = getThemeIconFileName(GTK_STOCK_MISSING_IMAGE, 16); if (fileName.isNull()) { - gchar* imagename = g_strdup_printf("%s.png", name); - gchar* glibFileName = g_build_filename(DATA_DIR, "webkit-1.0", "images", imagename, NULL); - fileName = glibFileName; - g_free(imagename); - g_free(glibFileName); + GOwnPtr<gchar> imageName(g_strdup_printf("%s.png", name)); + GOwnPtr<gchar> glibFileName(g_build_filename(getWebKitDataDirectory(), "webkitgtk-"WEBKITGTK_API_VERSION_STRING, "images", imageName.get(), NULL)); + fileName = glibFileName.get(); } return loadImageFromFile(fileName); diff --git a/WebCore/platform/graphics/mac/FontPlatformData.h b/WebCore/platform/graphics/mac/FontPlatformData.h index 07ae4f8..dc876a8 100644 --- a/WebCore/platform/graphics/mac/FontPlatformData.h +++ b/WebCore/platform/graphics/mac/FontPlatformData.h @@ -24,7 +24,7 @@ #ifndef FontPlatformData_h #define FontPlatformData_h -#include "StringImpl.h" +#include <wtf/text/StringImpl.h> #ifdef __OBJC__ @class NSFont; diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm index fd503fc..be1d278 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm @@ -31,6 +31,7 @@ #import "BlockExceptions.h" +#include "ANGLE/ResourceLimits.h" #include "ArrayBuffer.h" #include "ArrayBufferView.h" #include "WebGLObject.h" @@ -181,6 +182,30 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWi ::glGenRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer); } + // ANGLE initialization. + + TBuiltInResource ANGLEResources; + + ANGLEResources.maxVertexAttribs = 0; + getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &ANGLEResources.maxVertexAttribs); + ANGLEResources.maxVertexUniformVectors = 0; + getIntegerv(GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.maxVertexUniformVectors); + ANGLEResources.maxVaryingVectors = 0; + getIntegerv(GraphicsContext3D::MAX_VARYING_VECTORS, &ANGLEResources.maxVaryingVectors); + ANGLEResources.maxVertexTextureImageUnits = 0; + getIntegerv(GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.maxVertexTextureImageUnits); + ANGLEResources.maxCombinedTextureImageUnits = 0; + getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.maxCombinedTextureImageUnits); + ANGLEResources.maxTextureImageUnits = 0; + getIntegerv(GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.maxTextureImageUnits); + ANGLEResources.maxFragmentUniformVectors = 0; + getIntegerv(GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.maxFragmentUniformVectors); + + // Always set to 1 for OpenGL ES. + ANGLEResources.maxDrawBuffers = 1; + + m_compiler.setResources(ANGLEResources); + ::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); ::glClearColor(0, 0, 0, 0); } @@ -282,15 +307,6 @@ void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* co canvas->width(), canvas->height(), imageBuffer->context()->platformContext()); } -void GraphicsContext3D::beginPaint(CanvasRenderingContext* context) -{ - UNUSED_PARAM(context); -} - -void GraphicsContext3D::endPaint() -{ -} - bool GraphicsContext3D::isGLES2Compliant() const { return false; @@ -617,7 +633,52 @@ void GraphicsContext3D::compileShader(Platform3DObject shader) { ASSERT(shader); ensureContext(m_contextObj); + + int GLshaderType; + ANGLEShaderType shaderType; + + glGetShaderiv(shader, SHADER_TYPE, &GLshaderType); + + if (GLshaderType == VERTEX_SHADER) + shaderType = SHADER_TYPE_VERTEX; + else if (GLshaderType == FRAGMENT_SHADER) + shaderType = SHADER_TYPE_FRAGMENT; + else + return; // Invalid shader type. + + HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + + if (result == m_shaderSourceMap.end()) + return; + + ShaderSourceEntry& entry = result->second; + + String translatedShaderSource; + String shaderInfoLog; + + bool isValid = m_compiler.validateShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog); + + entry.log = shaderInfoLog; + entry.isValid = isValid; + + if (!isValid) + return; // Shader didn't validate, don't move forward with compiling translated source + + int translatedShaderLength = translatedShaderSource.length(); + + const CString& translatedShaderCString = translatedShaderSource.utf8(); + const char* translatedShaderPtr = translatedShaderCString.data(); + + ::glShaderSource((GLuint) shader, 1, &translatedShaderPtr, &translatedShaderLength); + ::glCompileShader((GLuint) shader); + + int GLCompileSuccess; + + ::glGetShaderiv((GLuint) shader, COMPILE_STATUS, &GLCompileSuccess); + + // ASSERT that ANGLE generated GLSL will be accepted by OpenGL + ASSERT(GLCompileSuccess == GL_TRUE); } void GraphicsContext3D::copyTexImage2D(unsigned long target, long level, unsigned long internalformat, long x, long y, unsigned long width, unsigned long height, long border) @@ -998,11 +1059,12 @@ void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& stri ASSERT(shader); ensureContext(m_contextObj); - const CString& cs = string.utf8(); - const char* s = cs.data(); - - int length = string.length(); - ::glShaderSource((GLuint) shader, 1, &s, &length); + + ShaderSourceEntry entry; + + entry.source = string; + + m_shaderSourceMap.set(shader, entry); } void GraphicsContext3D::stencilFunc(unsigned long func, long ref, unsigned long mask) @@ -1346,26 +1408,77 @@ void GraphicsContext3D::getShaderiv(Platform3DObject shader, unsigned long pname ASSERT(shader); ensureContext(m_contextObj); - ::glGetShaderiv((GLuint) shader, pname, value); + + HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + + switch (pname) { + case DELETE_STATUS: + case SHADER_TYPE: + // Let OpenGL handle these. + + ::glGetShaderiv((GLuint) shader, pname, value); + break; + + case COMPILE_STATUS: + if (result == m_shaderSourceMap.end()) { + (*value) = static_cast<int>(false); + return; + } + + (*value) = static_cast<int>(result->second.isValid); + break; + + case INFO_LOG_LENGTH: + if (result == m_shaderSourceMap.end()) { + (*value) = 0; + return; + } + + (*value) = getShaderInfoLog(shader).length(); + break; + + case SHADER_SOURCE_LENGTH: + (*value) = getShaderSource(shader).length(); + break; + + default: + synthesizeGLError(INVALID_ENUM); + } } String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader) { ASSERT(shader); - + ensureContext(m_contextObj); GLint length; ::glGetShaderiv((GLuint) shader, GL_INFO_LOG_LENGTH, &length); - - GLsizei size; - GLchar* info = (GLchar*) fastMalloc(length); - if (!info) - return ""; - - ::glGetShaderInfoLog((GLuint) shader, length, &size, info); - String s(info); - fastFree(info); - return s; + + HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + + if (result == m_shaderSourceMap.end()) + return ""; + + ShaderSourceEntry entry = result->second; + + if (entry.isValid) { + GLint length; + ::glGetShaderiv((GLuint) shader, GL_INFO_LOG_LENGTH, &length); + + GLsizei size; + GLchar* info = (GLchar*) fastMalloc(length); + if (!info) + return ""; + + ::glGetShaderInfoLog((GLuint) shader, length, &size, info); + + String s(info); + fastFree(info); + return s; + } + else { + return entry.log; + } } String GraphicsContext3D::getShaderSource(Platform3DObject shader) @@ -1373,18 +1486,13 @@ String GraphicsContext3D::getShaderSource(Platform3DObject shader) ASSERT(shader); ensureContext(m_contextObj); - GLint length; - ::glGetShaderiv((GLuint) shader, GL_SHADER_SOURCE_LENGTH, &length); - - GLsizei size; - GLchar* info = (GLchar*) fastMalloc(length); - if (!info) + + HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + + if (result == m_shaderSourceMap.end()) return ""; - - ::glGetShaderSource((GLuint) shader, length, &size, info); - String s(info); - fastFree(info); - return s; + + return result->second.source; } diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h index ee70338..a9f747a 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h @@ -29,11 +29,11 @@ #if USE(ACCELERATED_COMPOSITING) #include "GraphicsLayer.h" -#include "StringHash.h" #include "WebLayer.h" #include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/RetainPtr.h> +#include <wtf/text/StringHash.h> @class CABasicAnimation; @class CAKeyframeAnimation; diff --git a/WebCore/platform/graphics/qt/ContextShadow.cpp b/WebCore/platform/graphics/qt/ContextShadow.cpp new file mode 100644 index 0000000..0511218 --- /dev/null +++ b/WebCore/platform/graphics/qt/ContextShadow.cpp @@ -0,0 +1,256 @@ +/* + * 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" + +namespace WebCore { + +ContextShadow::ContextShadow() + : type(NoShadow) + , blurRadius(0) +{ +} + +ContextShadow::ContextShadow(const QColor& c, float r, qreal dx, qreal dy) + : color(c) + , blurRadius(qRound(r)) + , offset(dx, dy) +{ + // The type of shadow is decided by the blur radius, shadow offset, and shadow color. + if (!color.isValid() || !color.alpha()) { + // Can't paint the shadow with invalid or invisible color. + type = NoShadow; + } else if (r > 0) { + // Shadow is always blurred, even the offset is zero. + type = BlurShadow; + } else if (offset.isNull()) { + // Without blur and zero offset means the shadow is fully hidden. + type = NoShadow; + } else { + if (color.alpha() > 0) + type = AlphaSolidShadow; + else + type = OpaqueSolidShadow; + } +} + +void ContextShadow::clear() +{ + type = NoShadow; + color = QColor(); + blurRadius = 0; + offset = QPointF(0, 0); +} + +// Instead of integer division, we use 18.14 for fixed-point division. +static const int BlurSumShift = 14; + +// Note: image must be RGB32 format +static void blurHorizontal(QImage& image, int radius, bool swap = false) +{ + Q_ASSERT(image.format() == QImage::Format_ARGB32_Premultiplied); + + // See comments in http://webkit.org/b/40793, it seems sensible + // to follow Skia's limit of 128 pixels of blur radius + radius = qMin(128, radius); + + int imgWidth = image.width(); + int imgHeight = image.height(); + + // Check http://www.w3.org/TR/SVG/filters.html#feGaussianBlur + // for the approaches when the box-blur radius is even vs odd. + int dmax = radius >> 1; + int dmin = qMax(0, dmax - 1 + (radius & 1)); + + for (int y = 0; y < imgHeight; ++y) { + + unsigned char* pixels = image.scanLine(y); + + int left; + int right; + int pixelCount; + int prev; + int next; + int firstAlpha; + int lastAlpha; + int totalAlpha; + unsigned char* target; + unsigned char* prevPtr; + unsigned char* nextPtr; + + int invCount; + + static const int alphaChannel = 3; + static const int blueChannel = 0; + static const int greenChannel = 1; + + // For each step, we use sliding window algorithm. This is much more + // efficient than computing the sum of each pixels covered by the box + // kernel size for each x. + + // As noted in the SVG filter specification, running box blur 3x + // approximates a real gaussian blur nicely. + + // Step 1: blur alpha channel and store the result in the blue channel. + left = swap ? dmax : dmin; + right = swap ? dmin : dmax; + pixelCount = left + 1 + right; + invCount = (1 << BlurSumShift) / pixelCount; + prev = -left; + next = 1 + right; + firstAlpha = pixels[alphaChannel]; + lastAlpha = pixels[(imgWidth - 1) * 4 + alphaChannel]; + totalAlpha = 0; + for (int i = 0; i < pixelCount; ++i) + totalAlpha += pixels[qBound(0, i - left, imgWidth - 1) * 4 + alphaChannel]; + target = pixels + blueChannel; + prevPtr = pixels + prev * 4 + alphaChannel; + nextPtr = pixels + next * 4 + alphaChannel; + for (int x = 0; x < imgWidth; ++x, ++prev, ++next, target += 4, prevPtr += 4, nextPtr += 4) { + *target = (totalAlpha * invCount) >> BlurSumShift; + int delta = ((next < imgWidth) ? *nextPtr : lastAlpha) - + ((prev > 0) ? *prevPtr : firstAlpha); + totalAlpha += delta; + } + + // Step 2: blur blue channel and store the result in the green channel. + left = swap ? dmin : dmax; + right = swap ? dmax : dmin; + pixelCount = left + 1 + right; + invCount = (1 << BlurSumShift) / pixelCount; + prev = -left; + next = 1 + right; + firstAlpha = pixels[blueChannel]; + lastAlpha = pixels[(imgWidth - 1) * 4 + blueChannel]; + totalAlpha = 0; + for (int i = 0; i < pixelCount; ++i) + totalAlpha += pixels[qBound(0, i - left, imgWidth - 1) * 4 + blueChannel]; + target = pixels + greenChannel; + prevPtr = pixels + prev * 4 + blueChannel; + nextPtr = pixels + next * 4 + blueChannel; + for (int x = 0; x < imgWidth; ++x, ++prev, ++next, target += 4, prevPtr += 4, nextPtr += 4) { + *target = (totalAlpha * invCount) >> BlurSumShift; + int delta = ((next < imgWidth) ? *nextPtr : lastAlpha) - + ((prev > 0) ? *prevPtr : firstAlpha); + totalAlpha += delta; + } + + // Step 3: blur green channel and store the result in the alpha channel. + left = dmax; + right = dmax; + pixelCount = left + 1 + right; + invCount = (1 << BlurSumShift) / pixelCount; + prev = -left; + next = 1 + right; + firstAlpha = pixels[greenChannel]; + lastAlpha = pixels[(imgWidth - 1) * 4 + greenChannel]; + totalAlpha = 0; + for (int i = 0; i < pixelCount; ++i) + totalAlpha += pixels[qBound(0, i - left, imgWidth - 1) * 4 + greenChannel]; + target = pixels + alphaChannel; + prevPtr = pixels + prev * 4 + greenChannel; + nextPtr = pixels + next * 4 + greenChannel; + for (int x = 0; x < imgWidth; ++x, ++prev, ++next, target += 4, prevPtr += 4, nextPtr += 4) { + *target = (totalAlpha * invCount) >> BlurSumShift; + int delta = ((next < imgWidth) ? *nextPtr : lastAlpha) - + ((prev > 0) ? *prevPtr : firstAlpha); + totalAlpha += delta; + } + } +} + +static void shadowBlur(QImage& image, int radius, const QColor& shadowColor) +{ + blurHorizontal(image, radius); + + QTransform transform; + transform.rotate(90); + image = image.transformed(transform); + blurHorizontal(image, radius, true); + transform.reset(); + transform.rotate(270); + image = image.transformed(transform); + + // "Colorize" with the right shadow color. + QPainter p(&image); + p.setCompositionMode(QPainter::CompositionMode_SourceIn); + p.fillRect(image.rect(), shadowColor.rgb()); + p.end(); +} + +void ContextShadow::drawShadowRect(QPainter* p, const QRectF& rect) +{ + if (type == NoShadow) + return; + + if (type == BlurShadow) { + QRectF shadowRect = rect.translated(offset); + + // We expand the area by the blur radius * 2 to give extra space + // for the blur transition. + int extra = blurRadius * 2; + QRectF bufferRect = shadowRect.adjusted(-extra, -extra, extra, extra); + QRect alignedBufferRect = bufferRect.toAlignedRect(); + + QRect clipRect; + if (p->hasClipping()) + clipRect = p->clipRegion().boundingRect(); + else + clipRect = p->transform().inverted().mapRect(p->window()); + + if (!clipRect.contains(alignedBufferRect)) { + + // No need to have the buffer larger that the clip. + alignedBufferRect = alignedBufferRect.intersected(clipRect); + if (alignedBufferRect.isEmpty()) + return; + + // We adjust again because the pixels at the borders are still + // potentially affected by the pixels outside the buffer. + alignedBufferRect.adjust(-extra, -extra, extra, extra); + } + + QImage shadowImage(alignedBufferRect.size(), QImage::Format_ARGB32_Premultiplied); + shadowImage.fill(Qt::transparent); + QPainter shadowPainter(&shadowImage); + + shadowPainter.fillRect(shadowRect.translated(-alignedBufferRect.topLeft()), color); + shadowPainter.end(); + + shadowBlur(shadowImage, blurRadius, color); + + p->drawImage(alignedBufferRect.topLeft(), shadowImage); + + return; + } + + p->fillRect(rect.translated(offset), color); +} + + +} diff --git a/WebCore/platform/graphics/qt/ContextShadow.h b/WebCore/platform/graphics/qt/ContextShadow.h new file mode 100644 index 0000000..e114ebc --- /dev/null +++ b/WebCore/platform/graphics/qt/ContextShadow.h @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#ifndef ContextShadow_h +#define ContextShadow_h + +#include <QPainter> + +namespace WebCore { + +// This is to track and keep the shadow state. We use this rather than +// using GraphicsContextState to allow possible optimizations (right now +// only to determine the shadow type, but in future it might covers things +// like cached scratch image, persistent shader, etc). + +// This class should be copyable since GraphicsContextQt keeps a stack of +// the shadow state for savePlatformState and restorePlatformState. + +class ContextShadow { +public: + enum { + NoShadow, + OpaqueSolidShadow, + AlphaSolidShadow, + BlurShadow + } type; + + QColor color; + int blurRadius; + QPointF offset; + + ContextShadow(); + ContextShadow(const QColor& c, float r, qreal dx, qreal dy); + + void clear(); + + // Draws the shadow for colored rectangle (can't be filled with pattern + // or gradient) according to the shadow parameters. + // Note: 'rect' specifies the rectangle which casts the shadow, + // NOT the bounding box of the shadow. + void drawShadowRect(QPainter* p, const QRectF& rect); + +}; + +} // namespace WebCore + +#endif // ContextShadow_h diff --git a/WebCore/platform/graphics/qt/FontCacheQt.cpp b/WebCore/platform/graphics/qt/FontCacheQt.cpp index bfcc5c3..c59c523 100644 --- a/WebCore/platform/graphics/qt/FontCacheQt.cpp +++ b/WebCore/platform/graphics/qt/FontCacheQt.cpp @@ -29,10 +29,10 @@ #include "FontPlatformData.h" #include "Font.h" #include "PlatformString.h" -#include "StringHash.h" #include <utility> #include <wtf/ListHashSet.h> #include <wtf/StdLibExtras.h> +#include <wtf/text/StringHash.h> #include <QFont> diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index 273e2dd..d5e7b3f 100644 --- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -512,15 +512,6 @@ void GraphicsContext3D::makeContextCurrent() m_internal->m_glWidget->makeCurrent(); } -void GraphicsContext3D::beginPaint(CanvasRenderingContext* context) -{ - paintRenderingResultsToCanvas(); -} - -void GraphicsContext3D::endPaint() -{ -} - void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context) { m_internal->m_glWidget->makeCurrent(); diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index d4a145f..1632804 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -8,6 +8,7 @@ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2008 Dirk Schulze <vbs85@gmx.de> + * Copyright (C) 2010 Sencha, Inc. * * All rights reserved. * @@ -42,6 +43,7 @@ #include "AffineTransform.h" #include "Color.h" +#include "ContextShadow.h" #include "FloatConversion.h" #include "Font.h" #include "GraphicsContextPrivate.h" @@ -50,6 +52,7 @@ #include "Path.h" #include "Pattern.h" #include "Pen.h" +#include "TransparencyLayer.h" #include <QBrush> #include <QDebug> @@ -166,48 +169,6 @@ static inline Qt::FillRule toQtFillRule(WindRule rule) return Qt::OddEvenFill; } -struct TransparencyLayer : FastAllocBase { - TransparencyLayer(const QPainter* p, const QRect &rect, qreal opacity, QPixmap& alphaMask) - : pixmap(rect.width(), rect.height()) - , opacity(opacity) - , alphaMask(alphaMask) - , saveCounter(1) // see the comment for saveCounter - { - offset = rect.topLeft(); - pixmap.fill(Qt::transparent); - painter.begin(&pixmap); - painter.setRenderHint(QPainter::Antialiasing, p->testRenderHint(QPainter::Antialiasing)); - painter.translate(-offset); - painter.setPen(p->pen()); - painter.setBrush(p->brush()); - painter.setTransform(p->transform(), true); - painter.setOpacity(p->opacity()); - painter.setFont(p->font()); - if (painter.paintEngine()->hasFeature(QPaintEngine::PorterDuff)) - painter.setCompositionMode(p->compositionMode()); - // if the path is an empty region, this assignment disables all painting - if (!p->clipPath().isEmpty()) - painter.setClipPath(p->clipPath()); - } - - TransparencyLayer() - { - } - - QPixmap pixmap; - QPoint offset; - QPainter painter; - qreal opacity; - // for clipToImageBuffer - QPixmap alphaMask; - // saveCounter is only used in combination with alphaMask - // otherwise, its value is unspecified - int saveCounter; -private: - TransparencyLayer(const TransparencyLayer &) {} - TransparencyLayer & operator=(const TransparencyLayer &) { return *this; } -}; - class GraphicsContextPlatformPrivate : public Noncopyable { public: GraphicsContextPlatformPrivate(QPainter* painter); @@ -240,6 +201,14 @@ public: // Only used by SVG for now. QPainterPath currentPath; + ContextShadow shadow; + QStack<ContextShadow> shadowStack; + + bool hasShadow() const + { + return shadow.type != ContextShadow::NoShadow; + } + private: QPainter* painter; }; @@ -307,6 +276,7 @@ void GraphicsContext::savePlatformState() if (!m_data->layers.isEmpty() && !m_data->layers.top()->alphaMask.isNull()) ++m_data->layers.top()->saveCounter; m_data->p()->save(); + m_data->shadowStack.push(m_data->shadow); } void GraphicsContext::restorePlatformState() @@ -321,9 +291,16 @@ void GraphicsContext::restorePlatformState() QTransform matrix = m_common->state.pathTransform; m_data->currentPath = m_data->currentPath * matrix; } + + if (m_data->shadowStack.isEmpty()) + m_data->shadow = ContextShadow(); + else + m_data->shadow = m_data->shadowStack.pop(); } // Draws a filled rectangle with a stroked border. +// This is only used to draw borders (real fill is done via fillRect), and +// thus it must not cast any shadow. void GraphicsContext::drawRect(const IntRect& rect) { if (paintingDisabled()) @@ -333,24 +310,13 @@ void GraphicsContext::drawRect(const IntRect& rect) const bool antiAlias = p->testRenderHint(QPainter::Antialiasing); p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines); - if (m_common->state.shadowColor.isValid()) { - FloatSize shadowSize; - float shadowBlur; - Color shadowColor; - if (getShadow(shadowSize, shadowBlur, shadowColor)) { - IntRect shadowRect = rect; - shadowRect.move(shadowSize.width(), shadowSize.height()); - shadowRect.inflate(static_cast<int>(p->pen().widthF())); - p->fillRect(shadowRect, QColor(shadowColor)); - } - } - p->drawRect(rect); p->setRenderHint(QPainter::Antialiasing, antiAlias); } // This is only used to draw borders. +// Must not cast any shadow. void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) { if (paintingDisabled()) @@ -372,17 +338,6 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines); adjustLineToPixelBoundaries(p1, p2, width, style); - FloatSize shadowSize; - float shadowBlur; - Color shadowColor; - if (textDrawingMode() == cTextFill && getShadow(shadowSize, shadowBlur, shadowColor)) { - p->save(); - p->translate(shadowSize.width(), shadowSize.height()); - p->setPen(shadowColor); - p->drawLine(p1, p2); - p->restore(); - } - int patWidth = 0; switch (style) { case NoStroke: @@ -474,16 +429,14 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp const bool antiAlias = p->testRenderHint(QPainter::Antialiasing); p->setRenderHint(QPainter::Antialiasing, true); - FloatSize shadowSize; - float shadowBlur; - Color shadowColor; startAngle *= 16; angleSpan *= 16; - if (getShadow(shadowSize, shadowBlur, shadowColor)) { + + if (m_data->hasShadow()) { p->save(); - p->translate(shadowSize.width(), shadowSize.height()); + p->translate(m_data->shadow.offset); QPen pen(p->pen()); - pen.setColor(shadowColor); + pen.setColor(m_data->shadow.color); p->setPen(pen); p->drawArc(rect, startAngle, angleSpan); p->restore(); @@ -509,17 +462,14 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points QPainter* p = m_data->p(); p->save(); p->setRenderHint(QPainter::Antialiasing, shouldAntialias); - FloatSize shadowSize; - float shadowBlur; - Color shadowColor; - if (getShadow(shadowSize, shadowBlur, shadowColor)) { + if (m_data->hasShadow()) { p->save(); - p->translate(shadowSize.width(), shadowSize.height()); + p->translate(m_data->shadow.offset); if (p->brush().style() != Qt::NoBrush) - p->setBrush(QBrush(shadowColor)); + p->setBrush(QBrush(m_data->shadow.color)); QPen pen(p->pen()); if (pen.style() != Qt::NoPen) { - pen.setColor(shadowColor); + pen.setColor(m_data->shadow.color); p->setPen(pen); } p->drawConvexPolygon(polygon); @@ -553,18 +503,6 @@ QPen GraphicsContext::pen() return p->pen(); } -static void inline drawFilledShadowPath(GraphicsContext* context, QPainter* p, const QPainterPath& path) -{ - FloatSize shadowSize; - float shadowBlur; - Color shadowColor; - if (context->getShadow(shadowSize, shadowBlur, shadowColor)) { - p->translate(shadowSize.width(), shadowSize.height()); - p->fillPath(path, QBrush(shadowColor)); - p->translate(-shadowSize.width(), -shadowSize.height()); - } -} - void GraphicsContext::fillPath() { if (paintingDisabled()) @@ -574,7 +512,11 @@ void GraphicsContext::fillPath() QPainterPath& path = m_data->currentPath; // Avoid detaching the QPainterPath path.setFillRule(toQtFillRule(fillRule())); - drawFilledShadowPath(this, p, path); + if (m_data->hasShadow()) { + p->translate(m_data->shadow.offset); + p->fillPath(path, m_data->shadow.color); + p->translate(-m_data->shadow.offset); + } if (m_common->state.fillPattern) { AffineTransform affine; p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine))); @@ -598,16 +540,12 @@ void GraphicsContext::strokePath() QPainterPath& path = m_data->currentPath; // Avoid detaching the QPainterPath path.setFillRule(toQtFillRule(fillRule())); - FloatSize shadowSize; - float shadowBlur; - Color shadowColor; - if (getShadow(shadowSize, shadowBlur, shadowColor)) { - QTransform t(p->worldTransform()); - p->translate(shadowSize.width(), shadowSize.height()); + if (m_data->hasShadow()) { + p->translate(m_data->shadow.offset); QPen shadowPen(pen); - shadowPen.setColor(shadowColor); + shadowPen.setColor(m_data->shadow.color); p->strokePath(path, shadowPen); - p->setWorldTransform(t); + p->translate(-m_data->shadow.offset); } if (m_common->state.strokePattern) { AffineTransform affine; @@ -625,18 +563,6 @@ void GraphicsContext::strokePath() m_data->currentPath = QPainterPath(); } -static inline void drawBorderlessRectShadow(GraphicsContext* context, QPainter* p, const FloatRect& rect) -{ - FloatSize shadowSize; - float shadowBlur; - Color shadowColor; - if (context->getShadow(shadowSize, shadowBlur, shadowColor)) { - FloatRect shadowRect(rect); - shadowRect.move(shadowSize.width(), shadowSize.height()); - p->fillRect(shadowRect, QColor(shadowColor)); - } -} - static inline void drawRepeatPattern(QPainter* p, QPixmap* image, const FloatRect& rect, const bool repeatX, const bool repeatY) { // Patterns must be painted so that the top left of the first image is anchored at @@ -712,22 +638,18 @@ void GraphicsContext::fillRect(const FloatRect& rect) QPainter* p = m_data->p(); FloatRect normalizedRect = rect.normalized(); - FloatSize shadowSize; - float shadowBlur; - Color shadowColor; - bool hasShadow = getShadow(shadowSize, shadowBlur, shadowColor); - FloatRect shadowDestRect; + QRectF shadowDestRect; QImage* shadowImage = 0; QPainter* pShadow = 0; - if (hasShadow) { + if (m_data->hasShadow()) { shadowImage = new QImage(roundedIntSize(normalizedRect.size()), QImage::Format_ARGB32_Premultiplied); pShadow = new QPainter(shadowImage); shadowDestRect = normalizedRect; - shadowDestRect.move(shadowSize.width(), shadowSize.height()); + shadowDestRect.translate(m_data->shadow.offset); pShadow->setCompositionMode(QPainter::CompositionMode_Source); - pShadow->fillRect(shadowImage->rect(), shadowColor); + pShadow->fillRect(shadowImage->rect(), m_data->shadow.color); pShadow->setCompositionMode(QPainter::CompositionMode_DestinationIn); } @@ -737,7 +659,7 @@ void GraphicsContext::fillRect(const FloatRect& rect) QBrush brush(m_common->state.fillPattern->createPlatformPattern(affine)); QPixmap* image = m_common->state.fillPattern->tileImage()->nativeImageForCurrentFrame(); - if (hasShadow) { + if (m_data->hasShadow()) { drawRepeatPattern(pShadow, image, FloatRect(static_cast<QRectF>(shadowImage->rect())), m_common->state.fillPattern->repeatX(), m_common->state.fillPattern->repeatY()); pShadow->end(); p->drawImage(shadowDestRect, *shadowImage, shadowImage->rect()); @@ -747,14 +669,14 @@ void GraphicsContext::fillRect(const FloatRect& rect) QBrush brush(*m_common->state.fillGradient->platformGradient()); brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform()); - if (hasShadow) { + if (m_data->hasShadow()) { pShadow->fillRect(shadowImage->rect(), brush); pShadow->end(); p->drawImage(shadowDestRect, *shadowImage, shadowImage->rect()); } p->fillRect(normalizedRect, brush); } else { - if (hasShadow) { + if (m_data->hasShadow()) { pShadow->fillRect(shadowImage->rect(), p->brush()); pShadow->end(); p->drawImage(shadowDestRect, *shadowImage, shadowImage->rect()); @@ -774,8 +696,10 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS m_data->solidColor.setColor(color); QPainter* p = m_data->p(); - if (m_common->state.shadowColor.isValid()) - drawBorderlessRectShadow(this, p, rect); + + if (m_data->hasShadow()) + m_data->shadow.drawShadowRect(p, rect); + p->fillRect(rect, m_data->solidColor); } @@ -786,7 +710,11 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef Path path = Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight); QPainter* p = m_data->p(); - drawFilledShadowPath(this, p, path.platformPath()); + 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->fillPath(path.platformPath(), QColor(color)); } @@ -928,7 +856,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect) return FloatRect(roundedOrigin, roundedLowerRight - roundedOrigin); } -void GraphicsContext::setPlatformShadow(const FloatSize& size, float, const Color&, ColorSpace) +void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const Color& color, ColorSpace) { // Qt doesn't support shadows natively, they are drawn manually in the draw* // functions @@ -937,13 +865,20 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size, float, const Colo // 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.shadowSize = FloatSize(size.width(), -size.height()); + m_data->shadow = ContextShadow(color, blur, size.width(), -size.height()); + } else { + m_data->shadow = ContextShadow(color, blur, size.width(), size.height()); } } void GraphicsContext::clearPlatformShadow() { - // Qt doesn't support shadows natively, they are drawn manually in the draw* - // functions + m_data->shadow.clear(); +} + +void GraphicsContext::pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask) +{ + m_data->layers.push(new TransparencyLayer(m_data->p(), m_data->p()->transform().mapRect(rect), 1.0, alphaMask)); } void GraphicsContext::beginTransparencyLayer(float opacity) @@ -1226,23 +1161,6 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect) } } -void GraphicsContext::clipToImageBuffer(const FloatRect& floatRect, const ImageBuffer* image) -{ - if (paintingDisabled()) - return; - - QPixmap* nativeImage = image->image()->nativeImageForCurrentFrame(); - if (!nativeImage) - return; - - IntRect rect(floatRect); - QPixmap alphaMask = *nativeImage; - if (alphaMask.width() != rect.width() || alphaMask.height() != rect.height()) - alphaMask = alphaMask.scaled(rect.width(), rect.height()); - - m_data->layers.push(new TransparencyLayer(m_data->p(), m_data->p()->transform().mapRect(rect), 1.0, alphaMask)); -} - void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) { diff --git a/WebCore/platform/graphics/qt/ImageBufferData.h b/WebCore/platform/graphics/qt/ImageBufferData.h index 222dabe..aa32253 100644 --- a/WebCore/platform/graphics/qt/ImageBufferData.h +++ b/WebCore/platform/graphics/qt/ImageBufferData.h @@ -26,6 +26,9 @@ #ifndef ImageBufferData_h #define ImageBufferData_h +#include "Image.h" +#include <wtf/RefPtr.h> + #include <QPainter> #include <QPixmap> @@ -41,6 +44,7 @@ public: QPixmap m_pixmap; OwnPtr<QPainter> m_painter; + RefPtr<Image> m_image; }; } // namespace WebCore diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp index 761a4fe..11ca377 100644 --- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -33,6 +33,7 @@ #include "ImageData.h" #include "MIMETypeRegistry.h" #include "StillImageQt.h" +#include "TransparencyLayer.h" #include <wtf/text/CString.h> #include <QBuffer> @@ -74,6 +75,8 @@ ImageBufferData::ImageBufferData(const IntSize& size) brush.setColor(Qt::black); painter->setBrush(brush); painter->setCompositionMode(QPainter::CompositionMode_SourceOver); + + m_image = StillImage::createForRendering(&m_pixmap); } ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace, bool& success) @@ -98,24 +101,50 @@ GraphicsContext* ImageBuffer::context() const return m_context.get(); } -Image* ImageBuffer::imageForRendering() const +bool ImageBuffer::drawsUsingCopy() const { - if (!m_image) - m_image = StillImage::createForRendering(&m_data.m_pixmap); + return false; +} - return m_image.get(); +PassRefPtr<Image> ImageBuffer::copyImage() const +{ + return StillImage::create(m_data.m_pixmap); } -Image* ImageBuffer::image() const +void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, + CompositeOperator op, bool useLowQualityScale) { - if (!m_image) { - // It's assumed that if image() is called, the actual rendering to the - // GraphicsContext must be done. - ASSERT(context()); - m_image = StillImage::create(m_data.m_pixmap); - } + if (destContext == context()) { + // We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first. + RefPtr<Image> copy = copyImage(); + destContext->drawImage(copy.get(), DeviceColorSpace, destRect, srcRect, op, useLowQualityScale); + } else + destContext->drawImage(m_data.m_image.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale); +} + +void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect) +{ + if (destContext == context()) { + // We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first. + RefPtr<Image> copy = copyImage(); + copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect); + } else + m_data.m_image->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect); +} + +void ImageBuffer::clip(GraphicsContext* context, const FloatRect& floatRect) const +{ + QPixmap* nativeImage = m_data.m_image->nativeImageForCurrentFrame(); + if (!nativeImage) + return; + + IntRect rect(floatRect); + QPixmap alphaMask = *nativeImage; + if (alphaMask.width() != rect.width() || alphaMask.height() != rect.height()) + alphaMask = alphaMask.scaled(rect.width(), rect.height()); - return m_image.get(); + context->pushTransparencyLayerInternal(rect, 1.0, alphaMask); } void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp index fb3d621..858cc44 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp @@ -78,6 +78,9 @@ void ImageDecoderQt::setData(SharedBuffer* data, bool allDataReceived) m_buffer->open(QIODevice::ReadOnly | QIODevice::Unbuffered); m_reader.set(new QImageReader(m_buffer.get(), m_format)); + // This will force the JPEG decoder to use JDCT_IFAST + m_reader->setQuality(49); + // QImageReader only allows retrieving the format before reading the image m_format = m_reader->format(); } @@ -186,20 +189,16 @@ void ImageDecoderQt::internalReadImage(size_t frameIndex) bool ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex) { QPixmap pixmap; - bool pixmapLoaded; - const int imageCount = m_reader->imageCount(); - if (imageCount == 0 || imageCount == 1) - pixmapLoaded = pixmap.loadFromData((const uchar*)(m_data->data()), m_data->size(), m_format); - else { - QImage img; - const bool imageLoaded = m_reader->read(&img); - if (imageLoaded) { - pixmap = QPixmap::fromImage(img); - pixmapLoaded = true; - } - } - if (!pixmapLoaded) { +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + pixmap = QPixmap::fromImageReader(m_reader.get()); +#else + QImage img; + if (m_reader->read(&img)) + pixmap = QPixmap::fromImage(img); +#endif + + if (pixmap.isNull()) { frameCount(); repetitionCount(); clearPointers(); diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp index 3c6c5aa..08eb816 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp @@ -534,7 +534,11 @@ void MediaPlayerPrivate::aboutToFinish() void MediaPlayerPrivate::totalTimeChanged(qint64 totalTime) { +#if OS(WINDOWS) + LOG(Media, "MediaPlayerPrivatePhonon::totalTimeChanged(%I64d)", totalTime); +#else LOG(Media, "MediaPlayerPrivatePhonon::totalTimeChanged(%lld)", totalTime); +#endif LOG_MEDIAOBJECT(); } diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp index 525aaf4..4ad5571 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -25,6 +25,7 @@ #include "GraphicsContext.h" #include "HTMLMediaElement.h" #include "HTMLVideoElement.h" +#include "NotImplemented.h" #include "TimeRanges.h" #include "Widget.h" #include "qwebframe.h" @@ -95,6 +96,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) , m_isSeeking(false) , m_composited(false) , m_queuedSeek(-1) + , m_preload(MediaPlayer::Auto) { m_mediaPlayer->bind(m_videoItem); m_videoScene->addItem(m_videoItem); @@ -106,6 +108,8 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) this, SLOT(stateChanged(QMediaPlayer::State))); connect(m_mediaPlayer, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(handleError(QMediaPlayer::Error))); + connect(m_mediaPlayer, SIGNAL(bufferStatusChanged(int)), + this, SLOT(bufferStatusChanged(int))); connect(m_mediaPlayer, SIGNAL(durationChanged(qint64)), this, SLOT(durationChanged(qint64))); connect(m_mediaPlayer, SIGNAL(positionChanged(qint64)), @@ -145,6 +149,20 @@ bool MediaPlayerPrivate::hasAudio() const void MediaPlayerPrivate::load(const String& url) { + m_mediaUrl = url; + + // QtMultimedia does not have an API to throttle loading + // so we handle this ourselves by delaying the load + if (m_preload == MediaPlayer::None) { + m_delayingLoad = true; + return; + } + + commitLoad(url); +} + +void MediaPlayerPrivate::commitLoad(const String& url) +{ // We are now loading if (m_networkState != MediaPlayer::Loading) { m_networkState = MediaPlayer::Loading; @@ -208,6 +226,21 @@ void MediaPlayerPrivate::load(const String& url) // engine which does. m_mediaPlayer->setMuted(element->muted()); m_mediaPlayer->setVolume(static_cast<int>(element->volume() * 100.0)); + + // Setting a media source will start loading the media, but we need + // to pre-roll as well to get video size-hints and buffer-status + if (element->paused()) + m_mediaPlayer->pause(); + else + m_mediaPlayer->play(); +} + +void MediaPlayerPrivate::resumeLoad() +{ + m_delayingLoad = false; + + if (!m_mediaUrl.isNull()) + commitLoad(m_mediaUrl); } void MediaPlayerPrivate::cancelLoad() @@ -216,6 +249,12 @@ void MediaPlayerPrivate::cancelLoad() updateStates(); } +void MediaPlayerPrivate::prepareToPlay() +{ + if (m_mediaPlayer->media().isNull() || m_delayingLoad) + resumeLoad(); +} + void MediaPlayerPrivate::play() { if (m_mediaPlayer->state() != QMediaPlayer::PlayingState) @@ -322,24 +361,11 @@ float MediaPlayerPrivate::maxTimeSeekable() const unsigned MediaPlayerPrivate::bytesLoaded() const { - unsigned percentage = m_mediaPlayer->bufferStatus(); - - if (percentage == 100) { - if (m_networkState != MediaPlayer::Idle) { - m_networkState = MediaPlayer::Idle; - m_player->networkStateChanged(); - } - if (m_readyState != MediaPlayer::HaveEnoughData) { - m_readyState = MediaPlayer::HaveEnoughData; - m_player->readyStateChanged(); - } - } - QLatin1String bytesLoadedKey("bytes-loaded"); if (m_mediaPlayer->availableExtendedMetaData().contains(bytesLoadedKey)) return m_mediaPlayer->extendedMetaData(bytesLoadedKey).toInt(); - return percentage; + return m_mediaPlayer->bufferStatus(); } unsigned MediaPlayerPrivate::totalBytes() const @@ -350,6 +376,13 @@ unsigned MediaPlayerPrivate::totalBytes() const return 100; } +void MediaPlayerPrivate::setPreload(MediaPlayer::Preload preload) +{ + m_preload = preload; + if (m_delayingLoad && m_preload != MediaPlayer::None) + resumeLoad(); +} + void MediaPlayerPrivate::setRate(float rate) { m_mediaPlayer->setPlaybackRate(rate); @@ -439,6 +472,11 @@ void MediaPlayerPrivate::positionChanged(qint64) } } +void MediaPlayerPrivate::bufferStatusChanged(int) +{ + notImplemented(); +} + void MediaPlayerPrivate::durationChanged(qint64) { m_player->durationChanged(); diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h index d72404c..165efde 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h @@ -50,10 +50,13 @@ public: bool hasAudio() const; void load(const String &url); + void commitLoad(const String& url); + void resumeLoad(); void cancelLoad(); void play(); void pause(); + void prepareToPlay(); bool paused() const; bool seeking() const; @@ -68,6 +71,8 @@ public: bool supportsMuting() const; void setMuted(bool); + void setPreload(MediaPlayer::Preload); + MediaPlayer::NetworkState networkState() const; MediaPlayer::ReadyState readyState() const; @@ -103,6 +108,7 @@ private slots: void seekTimeout(); void positionChanged(qint64); void durationChanged(qint64); + void bufferStatusChanged(int); void volumeChanged(int); void mutedChanged(bool); void repaint(); @@ -127,6 +133,10 @@ private: bool m_isSeeking; bool m_composited; qint64 m_queuedSeek; + MediaPlayer::Preload m_preload; + bool m_delayingLoad; + String m_mediaUrl; + }; } diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index de9de07..ce5da2e 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -51,6 +51,7 @@ namespace WebCore { Path::Path() + : m_lastMoveToIndex(0) { } @@ -60,12 +61,14 @@ Path::~Path() Path::Path(const Path& other) : m_path(other.m_path) + , m_lastMoveToIndex(other.m_lastMoveToIndex) { } Path& Path::operator=(const Path& other) { m_path = other.m_path; + m_lastMoveToIndex = other.m_lastMoveToIndex; return *this; } @@ -180,6 +183,7 @@ FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) void Path::moveTo(const FloatPoint& point) { + m_lastMoveToIndex = m_path.elementCount(); m_path.moveTo(point); } @@ -260,7 +264,26 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) void Path::closeSubpath() { - m_path.closeSubpath(); + const int elementCount = m_path.elementCount(); + + if (!elementCount) + return; + + QPointF lastMoveToPoint = m_path.elementAt(m_lastMoveToIndex); + int elementsInLastSubpath = 0; + + for (int i = m_lastMoveToIndex; i < elementCount; ++i) { + QPainterPath::Element element = m_path.elementAt(i); + if (element.isLineTo() || element.isCurveTo()) { + // All we need to know is if there are 1 or more elements in the last subpath. + if (++elementsInLastSubpath == 2) { + m_path.lineTo(lastMoveToPoint); + return; + } + } + } + + moveTo(lastMoveToPoint); } #define DEGREES(t) ((t) * 180.0 / M_PI) @@ -440,7 +463,7 @@ void Path::transform(const AffineTransform& transform) // QTransform.map doesn't handle the MoveTo element because of the isEmpty issue if (m_path.isEmpty() && m_path.elementCount()) { QPointF point = qTransform.map(m_path.currentPosition()); - m_path.moveTo(point); + moveTo(point); } else #endif m_path = qTransform.map(m_path); diff --git a/WebCore/platform/graphics/qt/TransparencyLayer.h b/WebCore/platform/graphics/qt/TransparencyLayer.h new file mode 100644 index 0000000..0d9c121 --- /dev/null +++ b/WebCore/platform/graphics/qt/TransparencyLayer.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2006 Dirk Mueller <mueller@kde.org> + * Copyright (C) 2006 Zack Rusin <zack@kde.org> + * Copyright (C) 2006 George Staikos <staikos@kde.org> + * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org> + * Copyright (C) 2006 Allan Sandfeld Jensen <sandfeld@kde.org> + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (C) 2008 Dirk Schulze <vbs85@gmx.de> + * + * 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. + */ + +#ifndef TransparencyLayer_h +#define TransparencyLayer_h + +#include <QPaintEngine> +#include <QPainter> +#include <QPixmap> + +namespace WebCore { + +struct TransparencyLayer : FastAllocBase { + TransparencyLayer(const QPainter* p, const QRect &rect, qreal opacity, QPixmap& alphaMask) + : pixmap(rect.width(), rect.height()) + , opacity(opacity) + , alphaMask(alphaMask) + , saveCounter(1) // see the comment for saveCounter + { + offset = rect.topLeft(); + pixmap.fill(Qt::transparent); + painter.begin(&pixmap); + painter.setRenderHint(QPainter::Antialiasing, p->testRenderHint(QPainter::Antialiasing)); + painter.translate(-offset); + painter.setPen(p->pen()); + painter.setBrush(p->brush()); + painter.setTransform(p->transform(), true); + painter.setOpacity(p->opacity()); + painter.setFont(p->font()); + if (painter.paintEngine()->hasFeature(QPaintEngine::PorterDuff)) + painter.setCompositionMode(p->compositionMode()); + // if the path is an empty region, this assignment disables all painting + if (!p->clipPath().isEmpty()) + painter.setClipPath(p->clipPath()); + } + + TransparencyLayer() + { + } + + QPixmap pixmap; + QPoint offset; + QPainter painter; + qreal opacity; + // for clipToImageBuffer + QPixmap alphaMask; + // saveCounter is only used in combination with alphaMask + // otherwise, its value is unspecified + int saveCounter; +private: + TransparencyLayer(const TransparencyLayer &) {} + TransparencyLayer & operator=(const TransparencyLayer &) { return *this; } +}; + +} // namespace WebCore + +#endif // TransparencyLayer_h diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index 7bcd84b..fe7f6ce 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -53,6 +53,7 @@ #include <math.h> #include <wtf/Assertions.h> #include <wtf/MathExtras.h> +#include <wtf/UnusedParam.h> #if USE(GLES2_RENDERING) #include "GLES2Canvas.h" @@ -455,17 +456,6 @@ void GraphicsContext::clipPath(WindRule clipRule) platformContext()->clipPathAntiAliased(path); } -void GraphicsContext::clipToImageBuffer(const FloatRect& rect, - const ImageBuffer* imageBuffer) -{ - if (paintingDisabled()) - return; - -#if OS(LINUX) || OS(WINDOWS) - platformContext()->beginLayerClippedToImage(rect, imageBuffer); -#endif -} - void GraphicsContext::concatCTM(const AffineTransform& affine) { if (paintingDisabled()) diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp index eaa91ec..a63eec5 100644 --- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp @@ -87,20 +87,35 @@ GraphicsContext* ImageBuffer::context() const return m_context.get(); } -Image* ImageBuffer::image() const +bool ImageBuffer::drawsUsingCopy() const { - if (!m_image) { - // This creates a COPY of the image and will cache that copy. This means - // that if subsequent operations take place on the context, neither the - // currently-returned image, nor the results of future image() calls, - // will contain that operation. - // - // This seems silly, but is the way the CG port works: image() is - // intended to be used only when rendering is "complete." - m_image = BitmapImageSingleFrameSkia::create( - *m_data.m_platformContext.bitmap()); - } - return m_image.get(); + return true; +} + +PassRefPtr<Image> ImageBuffer::copyImage() const +{ + return BitmapImageSingleFrameSkia::create(*m_data.m_platformContext.bitmap()); +} + +void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const +{ +#if OS(LINUX) || OS(WINDOWS) + context->platformContext()->beginLayerClippedToImage(rect, this); +#endif +} + +void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, + CompositeOperator op, bool useLowQualityScale) +{ + RefPtr<Image> imageCopy = copyImage(); + context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale); +} + +void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect) +{ + RefPtr<Image> imageCopy = copyImage(); + imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect); } void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp index 024bf50..b514b1a 100644 --- a/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -465,18 +465,18 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, if (!bm) return; // It's too early and we don't have an image yet. -#if USE(GLES2_RENDERING) - if (ctxt->platformContext()->useGPU()) { - drawBitmapGLES2(ctxt, bm, srcRect, dstRect, colorSpace, compositeOp); - return; - } -#endif FloatRect normDstRect = normalizeRect(dstRect); FloatRect normSrcRect = normalizeRect(srcRect); if (normSrcRect.isEmpty() || normDstRect.isEmpty()) return; // Nothing to draw. +#if USE(GLES2_RENDERING) + if (ctxt->platformContext()->useGPU()) { + drawBitmapGLES2(ctxt, bm, normSrcRect, normDstRect, colorSpace, compositeOp); + return; + } +#endif ctxt->platformContext()->prepareForSoftwareDraw(); paintSkBitmap(ctxt->platformContext(), diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index abf04f9..1161224 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -39,6 +39,7 @@ #include "NativeImageSkia.h" #include "PlatformContextSkia.h" #include "SkiaUtils.h" +#include "TilingData.h" #include "skia/ext/image_operations.h" #include "skia/ext/platform_canvas.h" @@ -706,6 +707,7 @@ void PlatformContextSkia::setGraphicsContext3D(GraphicsContext3D* context, const { m_useGPU = true; m_gpuCanvas = new GLES2Canvas(context, size); + m_uploadTexture.clear(); #if USE(ACCELERATED_COMPOSITING) CanvasLayerChromium* layer = static_cast<CanvasLayerChromium*>(context->platformLayer()); layer->setPrepareTextureCallback(PrepareTextureCallbackImpl::create(this)); @@ -791,13 +793,13 @@ void PlatformContextSkia::uploadSoftwareToHardware(CompositeOperator op) const { const SkBitmap& bitmap = m_canvas->getDevice()->accessBitmap(false); SkAutoLockPixels lock(bitmap); - // FIXME: Keep a texture around for this rather than constantly creating/destroying one. GraphicsContext3D* context = m_gpuCanvas->context(); - RefPtr<GLES2Texture> texture = GLES2Texture::create(context, GLES2Texture::BGRA8, bitmap.width(), bitmap.height()); - texture->load(bitmap.getPixels()); + if (!m_uploadTexture || m_uploadTexture->tiles().totalSizeX() < bitmap.width() || m_uploadTexture->tiles().totalSizeY() < bitmap.height()) + m_uploadTexture = GLES2Texture::create(context, GLES2Texture::BGRA8, bitmap.width(), bitmap.height()); + m_uploadTexture->load(bitmap.getPixels()); IntRect rect(0, 0, bitmap.width(), bitmap.height()); AffineTransform identity; - gpuCanvas()->drawTexturedRect(texture.get(), rect, rect, identity, 1.0, DeviceColorSpace, op); + gpuCanvas()->drawTexturedRect(m_uploadTexture.get(), rect, rect, identity, 1.0, DeviceColorSpace, op); } void PlatformContextSkia::readbackHardwareToSoftware() const @@ -810,11 +812,15 @@ void PlatformContextSkia::readbackHardwareToSoftware() const // Flips the image vertically. for (int y = 0; y < height; ++y) { uint32_t* pixels = bitmap.getAddr32(0, y); - context->readPixels(0, height - 1 - y, width, 1, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels); - 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); + if (context->supportsBGRA()) + context->readPixels(0, height - 1 - y, width, 1, GraphicsContext3D::BGRA_EXT, GraphicsContext3D::UNSIGNED_BYTE, pixels); + else { + context->readPixels(0, height - 1 - y, width, 1, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels); + 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); + } } } } diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h index ff80d1b..6c84797 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.h +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h @@ -48,6 +48,7 @@ namespace WebCore { #if USE(GLES2_RENDERING) enum CompositeOperator; class GLES2Canvas; +class GLES2Texture; class GraphicsContext3D; #endif @@ -240,6 +241,7 @@ private: bool m_useGPU; OwnPtr<GLES2Canvas> m_gpuCanvas; mutable enum { None, Software, Mixed, Hardware } m_backingStoreState; + mutable RefPtr<GLES2Texture> m_uploadTexture; #endif }; diff --git a/WebCore/platform/graphics/win/FontCacheWin.cpp b/WebCore/platform/graphics/win/FontCacheWin.cpp index d050243..2240f80 100644 --- a/WebCore/platform/graphics/win/FontCacheWin.cpp +++ b/WebCore/platform/graphics/win/FontCacheWin.cpp @@ -31,11 +31,11 @@ #include "FontCache.h" #include "Font.h" #include "SimpleFontData.h" -#include "StringHash.h" #include "UnicodeRange.h" #include <mlang.h> #include <windows.h> #include <wtf/StdLibExtras.h> +#include <wtf/text/StringHash.h> #if PLATFORM(CG) #include <ApplicationServices/ApplicationServices.h> #include <WebKitSystemInterface/WebKitSystemInterface.h> diff --git a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp index a804432..9234229 100644 --- a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp +++ b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp @@ -25,12 +25,12 @@ #include "FontPlatformData.h" #include "PlatformString.h" -#include "StringHash.h" #include <ApplicationServices/ApplicationServices.h> #include <WebKitSystemInterface/WebKitSystemInterface.h> #include <wtf/HashMap.h> #include <wtf/RetainPtr.h> #include <wtf/Vector.h> +#include <wtf/text/StringHash.h> using std::min; diff --git a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp index 9b916bd..0f5c365 100644 --- a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp +++ b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp @@ -27,10 +27,10 @@ #include "FontPlatformData.h" #include "PlatformString.h" -#include "StringHash.h" #include <wtf/HashMap.h> #include <wtf/RetainPtr.h> #include <wtf/Vector.h> +#include <wtf/text/StringHash.h> #include <cairo-win32.h> diff --git a/WebCore/platform/graphics/win/FontPlatformDataWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataWin.cpp index 99f364c..09ed4a6 100644 --- a/WebCore/platform/graphics/win/FontPlatformDataWin.cpp +++ b/WebCore/platform/graphics/win/FontPlatformDataWin.cpp @@ -26,10 +26,10 @@ #include "FontPlatformData.h" #include "PlatformString.h" -#include "StringHash.h" #include <wtf/HashMap.h> #include <wtf/RetainPtr.h> #include <wtf/Vector.h> +#include <wtf/text/StringHash.h> using std::min; diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp index e0ecf78..9bc68d1 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp @@ -43,7 +43,6 @@ #include "Settings.h" #include "SoftLinking.h" #include "StringBuilder.h" -#include "StringHash.h" #include "TimeRanges.h" #include "Timer.h" #include <AssertMacros.h> @@ -54,6 +53,7 @@ #include <wtf/MainThread.h> #include <wtf/MathExtras.h> #include <wtf/StdLibExtras.h> +#include <wtf/text/StringHash.h> #if USE(ACCELERATED_COMPOSITING) #include "GraphicsLayerCACF.h" diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp index 69aaeaf..34f1135 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp @@ -39,7 +39,6 @@ #include "ScrollView.h" #include "SoftLinking.h" #include "StringBuilder.h" -#include "StringHash.h" #include "TimeRanges.h" #include "Timer.h" #include <Wininet.h> @@ -47,6 +46,7 @@ #include <wtf/HashSet.h> #include <wtf/MathExtras.h> #include <wtf/StdLibExtras.h> +#include <wtf/text/StringHash.h> #if USE(ACCELERATED_COMPOSITING) #include "GraphicsLayerCACF.h" diff --git a/WebCore/platform/graphics/win/WKCACFLayer.h b/WebCore/platform/graphics/win/WKCACFLayer.h index ed39297..abc04c8 100644 --- a/WebCore/platform/graphics/win/WKCACFLayer.h +++ b/WebCore/platform/graphics/win/WKCACFLayer.h @@ -28,8 +28,6 @@ #if USE(ACCELERATED_COMPOSITING) -#include "StringHash.h" - #include <wtf/RefCounted.h> #include <QuartzCore/CACFLayer.h> @@ -37,6 +35,7 @@ #include <wtf/PassRefPtr.h> #include <wtf/RetainPtr.h> #include <wtf/Vector.h> +#include <wtf/text/StringHash.h> #include "GraphicsContext.h" #include "PlatformString.h" diff --git a/WebCore/platform/graphics/wince/FontPlatformData.cpp b/WebCore/platform/graphics/wince/FontPlatformData.cpp index 74cadc2..d84a7cc 100644 --- a/WebCore/platform/graphics/wince/FontPlatformData.cpp +++ b/WebCore/platform/graphics/wince/FontPlatformData.cpp @@ -26,10 +26,10 @@ #include "FontData.h" #include "PlatformString.h" #include "SimpleFontData.h" -#include "StringHash.h" #include "UnicodeRange.h" #include "wtf/OwnPtr.h" #include <wtf/StdLibExtras.h> +#include <wtf/text/StringHash.h> #include <windows.h> #include <mlang.h> diff --git a/WebCore/platform/graphics/wince/PathWince.cpp b/WebCore/platform/graphics/wince/PathWince.cpp index 747e650..6aa2864 100644 --- a/WebCore/platform/graphics/wince/PathWince.cpp +++ b/WebCore/platform/graphics/wince/PathWince.cpp @@ -160,11 +160,9 @@ bool Path::hasCurrentPoint() const return !isEmpty(); } -FloatPoint Path::currentPoint() const +FloatPoint Path::currentPoint() const { - // FIXME: return current point of subpath. - float quietNaN = std::numeric_limits<float>::quiet_NaN(); - return FloatPoint(quietNaN, quietNaN); + return m_path->lastPoint(); } -} +} // namespace WebCore diff --git a/WebCore/platform/graphics/wx/FontPlatformData.h b/WebCore/platform/graphics/wx/FontPlatformData.h index 4f8d740..b328545 100644 --- a/WebCore/platform/graphics/wx/FontPlatformData.h +++ b/WebCore/platform/graphics/wx/FontPlatformData.h @@ -30,10 +30,10 @@ #define FontPlatformData_h #include "FontDescription.h" -#include "AtomicString.h" #include "StringImpl.h" #include <wtf/Forward.h> #include <wtf/RefPtr.h> +#include <wtf/text/AtomicString.h> #include <wtf/text/CString.h> #include <wx/defs.h> diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp index 4d5afd7..2428e7e 100644 --- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp +++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp @@ -378,11 +378,6 @@ void GraphicsContext::canvasClip(const Path& path) clip(path); } -void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*) -{ - notImplemented(); -} - AffineTransform GraphicsContext::getCTM() const { #if USE(WXGC) diff --git a/WebCore/platform/graphics/wx/ImageBufferWx.cpp b/WebCore/platform/graphics/wx/ImageBufferWx.cpp index 775e018..2522cbd 100644 --- a/WebCore/platform/graphics/wx/ImageBufferWx.cpp +++ b/WebCore/platform/graphics/wx/ImageBufferWx.cpp @@ -82,12 +82,36 @@ String ImageBuffer::toDataURL(const String&, const double*) const return String(); } -Image* ImageBuffer::image() const +bool ImageBuffer::drawsUsingCopy() const +{ + return true; +} + +PassRefPtr<Image> ImageBuffer::copyImage() const { notImplemented(); return 0; } +void ImageBuffer::clip(GraphicsContext*, const FloatRect&) const +{ + notImplemented(); +} + +void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, + CompositeOperator op, bool useLowQualityScale) +{ + RefPtr<Image> imageCopy = copyImage(); + context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale); +} + +void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect) +{ + RefPtr<Image> imageCopy = copyImage(); + imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect); +} + void ImageBuffer::platformTransformColorSpace(const Vector<int>&) { notImplemented(); |