summaryrefslogtreecommitdiffstats
path: root/WebCore/platform
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform')
-rw-r--r--WebCore/platform/AsyncFileStream.h74
-rw-r--r--WebCore/platform/ContextMenu.cpp4
-rw-r--r--WebCore/platform/Cursor.h9
-rw-r--r--WebCore/platform/FileStream.cpp150
-rw-r--r--WebCore/platform/FileStream.h100
-rw-r--r--WebCore/platform/FileStreamClient.h (renamed from WebCore/platform/graphics/chromium/TransformLayerChromium.h)42
-rw-r--r--WebCore/platform/PlatformTouchPoint.h1
-rw-r--r--WebCore/platform/chromium/ChromiumBridge.h4
-rw-r--r--WebCore/platform/chromium/ClipboardChromium.cpp7
-rw-r--r--WebCore/platform/efl/PopupMenuEfl.cpp3
-rw-r--r--WebCore/platform/efl/RenderThemeEfl.cpp23
-rw-r--r--WebCore/platform/efl/RenderThemeEfl.h6
-rw-r--r--WebCore/platform/graphics/GraphicsContext.h8
-rw-r--r--WebCore/platform/graphics/GraphicsContext3D.cpp5
-rw-r--r--WebCore/platform/graphics/GraphicsContext3D.h15
-rw-r--r--WebCore/platform/graphics/ImageSource.cpp5
-rw-r--r--WebCore/platform/graphics/ImageSource.h3
-rw-r--r--WebCore/platform/graphics/MediaPlayer.cpp67
-rw-r--r--WebCore/platform/graphics/cairo/FontCairo.cpp8
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp43
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h1
-rw-r--r--WebCore/platform/graphics/cairo/ImageBufferCairo.cpp15
-rw-r--r--WebCore/platform/graphics/cairo/ImageCairo.cpp14
-rw-r--r--WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp (renamed from WebCore/platform/graphics/cairo/GRefPtrCairo.cpp)10
-rw-r--r--WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h (renamed from WebCore/platform/graphics/cairo/GRefPtrCairo.h)14
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.cpp4
-rw-r--r--WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp76
-rw-r--r--WebCore/platform/graphics/chromium/CanvasLayerChromium.h27
-rw-r--r--WebCore/platform/graphics/chromium/ContentLayerChromium.cpp301
-rw-r--r--WebCore/platform/graphics/chromium/ContentLayerChromium.h90
-rw-r--r--WebCore/platform/graphics/chromium/GLES2Canvas.cpp66
-rw-r--r--WebCore/platform/graphics/chromium/GLES2Canvas.h2
-rw-r--r--WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp6
-rw-r--r--WebCore/platform/graphics/chromium/ImageLayerChromium.cpp19
-rw-r--r--WebCore/platform/graphics/chromium/ImageLayerChromium.h8
-rw-r--r--WebCore/platform/graphics/chromium/LayerChromium.cpp331
-rw-r--r--WebCore/platform/graphics/chromium/LayerChromium.h125
-rw-r--r--WebCore/platform/graphics/chromium/LayerRendererChromium.cpp664
-rw-r--r--WebCore/platform/graphics/chromium/LayerRendererChromium.h91
-rwxr-xr-xWebCore/platform/graphics/chromium/TilingData.cpp16
-rw-r--r--WebCore/platform/graphics/chromium/VideoFrameChromium.h81
-rw-r--r--WebCore/platform/graphics/chromium/VideoFrameProvider.h (renamed from WebCore/platform/graphics/chromium/TransformLayerChromium.cpp)33
-rw-r--r--WebCore/platform/graphics/chromium/VideoLayerChromium.cpp28
-rw-r--r--WebCore/platform/graphics/chromium/VideoLayerChromium.h15
-rw-r--r--WebCore/platform/graphics/filters/FEComposite.cpp2
-rw-r--r--WebCore/platform/graphics/filters/FEGaussianBlur.cpp6
-rw-r--r--WebCore/platform/graphics/filters/FEGaussianBlur.h2
-rw-r--r--WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp164
-rw-r--r--WebCore/platform/graphics/gstreamer/GStreamerGWorld.h24
-rw-r--r--WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp3
-rw-r--r--WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h54
-rw-r--r--WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp60
-rw-r--r--WebCore/platform/graphics/gtk/ImageBufferGtk.cpp2
-rw-r--r--WebCore/platform/graphics/mac/FontCustomPlatformData.cpp2
-rw-r--r--WebCore/platform/graphics/mac/FontPlatformDataMac.mm18
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContext3DMac.mm42
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.mm15
-rw-r--r--WebCore/platform/graphics/qt/ContextShadow.cpp162
-rw-r--r--WebCore/platform/graphics/qt/ContextShadow.h33
-rw-r--r--WebCore/platform/graphics/qt/FontQt.cpp82
-rw-r--r--WebCore/platform/graphics/qt/GradientQt.cpp25
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp110
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp105
-rw-r--r--WebCore/platform/graphics/qt/GraphicsLayerQt.h3
-rw-r--r--WebCore/platform/graphics/qt/ImageBufferQt.cpp12
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.cpp20
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.h2
-rw-r--r--WebCore/platform/graphics/qt/TransparencyLayer.h2
-rw-r--r--WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h11
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp32
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContextSkia.cpp4
-rw-r--r--WebCore/platform/graphics/skia/ImageBufferSkia.cpp13
-rw-r--r--WebCore/platform/graphics/skia/ImageSkia.cpp21
-rw-r--r--WebCore/platform/graphics/skia/NativeImageSkia.cpp8
-rw-r--r--WebCore/platform/graphics/skia/NativeImageSkia.h5
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.cpp8
-rw-r--r--WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp8
-rw-r--r--WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h9
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayer.cpp30
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayer.h23
-rwxr-xr-xWebCore/platform/graphics/win/WebTiledLayer.cpp20
-rw-r--r--WebCore/platform/graphics/win/WebTiledLayer.h4
-rw-r--r--WebCore/platform/gtk/ClipboardGtk.cpp2
-rw-r--r--WebCore/platform/gtk/CursorGtk.cpp70
-rw-r--r--WebCore/platform/gtk/CursorGtk.h50
-rw-r--r--WebCore/platform/gtk/DataObjectGtk.h4
-rw-r--r--WebCore/platform/gtk/GRefPtrGtk.cpp8
-rw-r--r--WebCore/platform/gtk/GRefPtrGtk.h8
-rw-r--r--WebCore/platform/gtk/GtkVersioning.h2
-rw-r--r--WebCore/platform/gtk/PasteboardGtk.cpp2
-rw-r--r--WebCore/platform/gtk/PasteboardHelper.cpp2
-rw-r--r--WebCore/platform/gtk/PopupMenuGtk.h2
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.cpp6
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.h2
-rw-r--r--WebCore/platform/gtk/ScrollViewGtk.cpp18
-rw-r--r--WebCore/platform/gtk/ScrollbarGtk.cpp18
-rw-r--r--WebCore/platform/gtk/gtk2drawing.c54
-rw-r--r--WebCore/platform/gtk/gtkdrawing.h3
-rw-r--r--WebCore/platform/image-decoders/ImageDecoder.cpp16
-rw-r--r--WebCore/platform/image-decoders/ImageDecoder.h18
-rw-r--r--WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp9
-rw-r--r--WebCore/platform/image-decoders/bmp/BMPImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp7
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp12
-rw-r--r--WebCore/platform/image-decoders/ico/ICOImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp7
-rw-r--r--WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/png/PNGImageDecoder.cpp9
-rw-r--r--WebCore/platform/image-decoders/png/PNGImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp2
-rw-r--r--WebCore/platform/mock/SpeechInputClientMock.cpp2
-rw-r--r--WebCore/platform/mock/SpeechInputClientMock.h2
-rw-r--r--WebCore/platform/network/BlobData.cpp5
-rw-r--r--WebCore/platform/network/BlobData.h28
-rw-r--r--WebCore/platform/network/BlobRegistry.h11
-rw-r--r--WebCore/platform/network/BlobRegistryImpl.cpp62
-rw-r--r--WebCore/platform/network/BlobRegistryImpl.h4
-rw-r--r--WebCore/platform/network/BlobResourceHandle.cpp589
-rw-r--r--WebCore/platform/network/BlobResourceHandle.h116
-rw-r--r--WebCore/platform/network/BlobStorageData.h69
-rw-r--r--WebCore/platform/network/CredentialStorage.cpp1
-rw-r--r--WebCore/platform/network/FormData.cpp10
-rw-r--r--WebCore/platform/network/FormData.h24
-rw-r--r--WebCore/platform/network/HTTPParsers.cpp57
-rw-r--r--WebCore/platform/network/HTTPParsers.h3
-rw-r--r--WebCore/platform/network/ResourceHandle.cpp9
-rw-r--r--WebCore/platform/network/ResourceHandle.h3
-rw-r--r--WebCore/platform/network/ResourceHandleClient.h5
-rw-r--r--WebCore/platform/network/ResourceHandleInternal.h2
-rw-r--r--WebCore/platform/network/mac/ResourceHandleMac.mm7
-rw-r--r--WebCore/platform/network/win/ResourceHandleWin.cpp168
-rw-r--r--WebCore/platform/qt/CursorQt.cpp444
-rw-r--r--WebCore/platform/qt/PasteboardQt.cpp5
-rw-r--r--WebCore/platform/qt/WidgetQt.cpp8
-rw-r--r--WebCore/platform/sql/SQLiteStatement.cpp20
-rw-r--r--WebCore/platform/sql/SQLiteStatement.h2
-rw-r--r--WebCore/platform/text/TextCodecLatin1.cpp2
-rw-r--r--WebCore/platform/text/qt/TextCodecQt.cpp2
-rw-r--r--WebCore/platform/win/BitmapInfo.cpp13
-rw-r--r--WebCore/platform/win/BitmapInfo.h21
-rw-r--r--WebCore/platform/win/PopupMenuWin.cpp2
142 files changed, 4029 insertions, 1768 deletions
diff --git a/WebCore/platform/AsyncFileStream.h b/WebCore/platform/AsyncFileStream.h
new file mode 100644
index 0000000..3abda01
--- /dev/null
+++ b/WebCore/platform/AsyncFileStream.h
@@ -0,0 +1,74 @@
+/*
+ * 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 AsyncFileStream_h
+#define AsyncFileStream_h
+
+#if ENABLE(BLOB) || ENABLE(FILE_WRITER)
+
+#include "FileStreamClient.h"
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class KURL;
+
+class AsyncFileStream : public RefCounted<AsyncFileStream> {
+public:
+ virtual ~AsyncFileStream() { }
+
+ virtual void getSize(const String& path, double expectedModificationTime) = 0;
+ virtual void openForRead(const String& path, long long offset, long long length) = 0;
+ virtual void openForWrite(const String& path) = 0;
+ virtual void close() = 0;
+ virtual void read(char* buffer, int length) = 0;
+ virtual void write(const KURL& blobURL, long long position, int length) = 0;
+ virtual void truncate(long long position) = 0;
+ virtual void stop() = 0;
+
+ FileStreamClient* client() const { return m_client; }
+ void setClient(FileStreamClient* client) { m_client = client; }
+
+protected:
+ AsyncFileStream(FileStreamClient* client)
+ : m_client(client)
+ {
+ }
+
+private:
+ FileStreamClient* m_client;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(BLOB) || ENABLE(FILE_WRITER)
+
+#endif // AsyncFileStream_h
diff --git a/WebCore/platform/ContextMenu.cpp b/WebCore/platform/ContextMenu.cpp
index 84a2ffc..37d4c2b 100644
--- a/WebCore/platform/ContextMenu.cpp
+++ b/WebCore/platform/ContextMenu.cpp
@@ -584,6 +584,10 @@ void ContextMenu::checkOrEnableIfNeeded(ContextMenuItem& item) const
if (!frame)
return;
+ // Custom items already have proper checked and enabled values.
+ if (ContextMenuItemBaseCustomTag <= item.action() && item.action() <= ContextMenuItemLastCustomTag)
+ return;
+
bool shouldEnable = true;
bool shouldCheck = false;
diff --git a/WebCore/platform/Cursor.h b/WebCore/platform/Cursor.h
index 5e547ef..92d3596 100644
--- a/WebCore/platform/Cursor.h
+++ b/WebCore/platform/Cursor.h
@@ -62,7 +62,7 @@ typedef struct HICON__ *HICON;
typedef HICON HCURSOR;
#endif
-#if PLATFORM(WIN) || PLATFORM(MAC) || PLATFORM(GTK)
+#if PLATFORM(WIN) || PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(QT)
#define WTF_USE_LAZY_NATIVE_CURSOR 1
#endif
@@ -84,11 +84,12 @@ namespace WebCore {
#elif PLATFORM(MAC)
typedef NSCursor* PlatformCursor;
#elif PLATFORM(GTK)
- typedef GRefPtr<GdkCursor> PlatformCursor;
+ typedef PlatformRefPtr<GdkCursor> PlatformCursor;
#elif PLATFORM(EFL)
typedef const char* PlatformCursor;
#elif PLATFORM(QT) && !defined(QT_NO_CURSOR)
- typedef QCursor PlatformCursor;
+ // Do not need to be shared but need to be created dynamically via ensurePlatformCursor.
+ typedef QCursor* PlatformCursor;
#elif PLATFORM(WX)
typedef wxCursor* PlatformCursor;
#elif PLATFORM(CHROMIUM)
@@ -151,7 +152,7 @@ namespace WebCore {
static const Cursor& fromType(Cursor::Type);
Cursor()
-#if !PLATFORM(QT) && !PLATFORM(EFL)
+#if !PLATFORM(EFL)
: m_platformCursor(0)
#endif
{
diff --git a/WebCore/platform/FileStream.cpp b/WebCore/platform/FileStream.cpp
new file mode 100644
index 0000000..45f435e
--- /dev/null
+++ b/WebCore/platform/FileStream.cpp
@@ -0,0 +1,150 @@
+/*
+ * 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"
+
+#if ENABLE(BLOB) || ENABLE(FILE_WRITER)
+
+#include "FileStream.h"
+
+#include "PlatformString.h"
+
+namespace WebCore {
+
+FileStream::FileStream()
+ : m_handle(invalidPlatformFileHandle)
+ , m_bytesProcessed(0)
+ , m_totalBytesToRead(0)
+{
+}
+
+FileStream::~FileStream()
+{
+ ASSERT(!isHandleValid(m_handle));
+}
+
+// FIXME: To be removed when we switch to using BlobData.
+void FileStream::start()
+{
+}
+
+void FileStream::stop()
+{
+ close();
+}
+
+long long FileStream::getSize(const String& path, double expectedModificationTime)
+{
+ // Check the modification time for the possible file change.
+ time_t modificationTime;
+ if (!getFileModificationTime(path, modificationTime))
+ return -1;
+ if (expectedModificationTime) {
+ if (static_cast<time_t>(expectedModificationTime) != modificationTime)
+ return -1;
+ }
+
+ // Now get the file size.
+ long long length;
+ if (!getFileSize(path, length))
+ return -1;
+
+ return length;
+}
+
+bool FileStream::openForRead(const String& path, long long offset, long long length)
+{
+ if (isHandleValid(m_handle))
+ return true;
+
+ // Open the file.
+ m_handle = openFile(path, OpenForRead);
+ if (!isHandleValid(m_handle))
+ return false;
+
+ // Jump to the beginning position if the file has been sliced.
+ if (offset > 0) {
+ if (seekFile(m_handle, offset, SeekFromBeginning) < 0)
+ return false;
+ }
+
+ m_totalBytesToRead = length;
+ m_bytesProcessed = 0;
+
+ return true;
+}
+
+bool FileStream::openForWrite(const String&)
+{
+ // FIXME: to be implemented.
+ return false;
+}
+
+void FileStream::close()
+{
+ if (isHandleValid(m_handle)) {
+ closeFile(m_handle);
+ m_handle = invalidPlatformFileHandle;
+ }
+}
+
+int FileStream::read(char* buffer, int bufferSize)
+{
+ if (!isHandleValid(m_handle))
+ return -1;
+
+ long long remaining = m_totalBytesToRead - m_bytesProcessed;
+ int bytesToRead = (remaining < bufferSize) ? static_cast<int>(remaining) : bufferSize;
+ int bytesRead = 0;
+ if (bytesToRead > 0)
+ bytesRead = readFromFile(m_handle, buffer, bytesToRead);
+ if (bytesRead < 0)
+ return -1;
+ if (bytesRead > 0)
+ m_bytesProcessed += bytesRead;
+
+ return bytesRead;
+}
+
+int FileStream::write(const KURL&, long long, int)
+{
+ // FIXME: to be implemented.
+ return -1;
+}
+
+bool FileStream::truncate(long long)
+{
+ // FIXME: to be implemented.
+ return false;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(BLOB) || ENABLE(FILE_WRITER)
diff --git a/WebCore/platform/FileStream.h b/WebCore/platform/FileStream.h
new file mode 100644
index 0000000..6c3a221
--- /dev/null
+++ b/WebCore/platform/FileStream.h
@@ -0,0 +1,100 @@
+/*
+ * 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 FileStream_h
+#define FileStream_h
+
+#if ENABLE(BLOB) || ENABLE(FILE_WRITER)
+
+#include "FileSystem.h"
+#include <wtf/Forward.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class KURL;
+
+// All methods are synchronous.
+class FileStream : public RefCounted<FileStream> {
+public:
+ static PassRefPtr<FileStream> create()
+ {
+ return adoptRef(new FileStream());
+ }
+ ~FileStream();
+
+ // FIXME: To be removed when we switch to using BlobData.
+ void start();
+
+ // Aborts the operation.
+ void stop();
+
+ // Gets the size of a file. Also validates if the file has been changed or not if the expected modification time is provided, i.e. non-zero.
+ // Returns total number of bytes if successful. -1 otherwise.
+ long long getSize(const String& path, double expectedModificationTime);
+
+ // Opens a file for reading. The reading starts at the specified offset and lasts till the specified length.
+ // Returns true on success. False otherwise.
+ bool openForRead(const String& path, long long offset, long long length);
+
+ // Opens a file for writing.
+ // Returns true on success. False otherwise.
+ bool openForWrite(const String& path);
+
+ // Closes the file.
+ void close();
+
+ // Reads a file into the provided data buffer.
+ // Returns number of bytes being read on success. -1 otherwise.
+ // If 0 is returned, it means that the reading is completed.
+ int read(char* buffer, int length);
+
+ // Writes a blob to the file.
+ // Returns number of bytes being written on success. -1 otherwise.
+ int write(const KURL& blobURL, long long position, int length);
+
+ // Truncates the file to the specified position.
+ // Returns true on success. False otherwise.
+ bool truncate(long long position);
+
+private:
+ FileStream();
+
+ PlatformFileHandle m_handle;
+ long long m_bytesProcessed;
+ long long m_totalBytesToRead;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(BLOB) || ENABLE(FILE_WRITER)
+
+#endif // FileStream_h
diff --git a/WebCore/platform/graphics/chromium/TransformLayerChromium.h b/WebCore/platform/FileStreamClient.h
index 3d5ce94..b3d1fff 100644
--- a/WebCore/platform/graphics/chromium/TransformLayerChromium.h
+++ b/WebCore/platform/FileStreamClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
+ * 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
@@ -28,28 +28,36 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef FileStreamClient_h
+#define FileStreamClient_h
-#ifndef TransformLayerChromium_h
-#define TransformLayerChromium_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "LayerChromium.h"
+#if ENABLE(BLOB) || ENABLE(FILE_WRITER)
namespace WebCore {
-// A Layer that doesn't draw any content but simply exists to group and
-// transform its descendants.
-class TransformLayerChromium : public LayerChromium {
+class FileStreamClient {
public:
- static PassRefPtr<TransformLayerChromium> create(GraphicsLayerChromium* owner = 0);
- virtual bool drawsContent() { return false; }
+ // For reading.
+ virtual void didRead(int) { }
+
+ // For writing.
+ virtual void didWrite(int) { }
+ virtual void didTruncate(bool) { }
-private:
- TransformLayerChromium(GraphicsLayerChromium* owner);
+ // FIXME: To be removed when we switch to using BlobData.
+ virtual void didStart() { }
+
+ // For both reading and writing.
+ virtual void didOpen(bool) { }
+ virtual void didStop() { }
+ virtual void didGetSize(long long) { }
+
+protected:
+ virtual ~FileStreamClient() { }
};
-}
-#endif // USE(ACCELERATED_COMPOSITING)
+} // namespace WebCore
+
+#endif // ENABLE(BLOB) || ENABLE(FILE_WRITER)
-#endif
+#endif // FileStreamClient_h
diff --git a/WebCore/platform/PlatformTouchPoint.h b/WebCore/platform/PlatformTouchPoint.h
index 4a667a0..3a25736 100644
--- a/WebCore/platform/PlatformTouchPoint.h
+++ b/WebCore/platform/PlatformTouchPoint.h
@@ -45,6 +45,7 @@ public:
#if PLATFORM(QT)
PlatformTouchPoint(const QTouchEvent::TouchPoint&);
+ PlatformTouchPoint() {};
#elif PLATFORM(ANDROID)
PlatformTouchPoint(const IntPoint& windowPos, State);
#endif
diff --git a/WebCore/platform/chromium/ChromiumBridge.h b/WebCore/platform/chromium/ChromiumBridge.h
index fc1345e..35ace89 100644
--- a/WebCore/platform/chromium/ChromiumBridge.h
+++ b/WebCore/platform/chromium/ChromiumBridge.h
@@ -72,8 +72,10 @@ namespace WebCore {
class GraphicsContext;
class Image;
class IDBFactoryBackendInterface;
+ class IDBKey;
class IntRect;
class KURL;
+ class SerializedScriptValue;
class Widget;
struct Cookie;
@@ -167,6 +169,8 @@ namespace WebCore {
// IndexedDB ----------------------------------------------------------
static PassRefPtr<IDBFactoryBackendInterface> idbFactory();
+ // Extracts keyPath from values and returns the corresponding keys.
+ static void createIDBKeysFromSerializedValuesAndKeyPath(const Vector<RefPtr<SerializedScriptValue> >& values, const String& keyPath, Vector<RefPtr<IDBKey> >& keys);
// JavaScript ---------------------------------------------------------
static void notifyJSOutOfMemory(Frame*);
diff --git a/WebCore/platform/chromium/ClipboardChromium.cpp b/WebCore/platform/chromium/ClipboardChromium.cpp
index 06244a2..23508a6 100644
--- a/WebCore/platform/chromium/ClipboardChromium.cpp
+++ b/WebCore/platform/chromium/ClipboardChromium.cpp
@@ -400,7 +400,12 @@ void ClipboardChromium::setDragImageElement(Node* node, const IntPoint& loc)
DragImageRef ClipboardChromium::createDragImage(IntPoint& loc) const
{
DragImageRef result = 0;
- if (m_dragImage) {
+ if (m_dragImageElement) {
+ if (m_frame) {
+ result = m_frame->nodeImage(m_dragImageElement.get());
+ loc = m_dragLoc;
+ }
+ } else if (m_dragImage) {
result = createDragImageFromImage(m_dragImage->image());
loc = m_dragLoc;
}
diff --git a/WebCore/platform/efl/PopupMenuEfl.cpp b/WebCore/platform/efl/PopupMenuEfl.cpp
index 401f24f..a6f7a53 100644
--- a/WebCore/platform/efl/PopupMenuEfl.cpp
+++ b/WebCore/platform/efl/PopupMenuEfl.cpp
@@ -43,7 +43,8 @@ PopupMenuEfl::~PopupMenuEfl()
{
// Tell client to destroy data related to this popup since this object is
// going away.
- hide();
+ if (m_view)
+ hide();
}
void PopupMenuEfl::show(const IntRect& rect, FrameView* view, int index)
diff --git a/WebCore/platform/efl/RenderThemeEfl.cpp b/WebCore/platform/efl/RenderThemeEfl.cpp
index 36600a9..102f754 100644
--- a/WebCore/platform/efl/RenderThemeEfl.cpp
+++ b/WebCore/platform/efl/RenderThemeEfl.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "RenderThemeEfl.h"
+#include "CSSValueKeywords.h"
#include "FileSystem.h"
#include "Frame.h"
#include "FrameView.h"
@@ -631,6 +632,8 @@ void RenderThemeEfl::themeChanged()
applyPartDescriptions();
}
+float RenderThemeEfl::defaultFontSize = 16.0f;
+
RenderThemeEfl::RenderThemeEfl(Page* page)
: RenderTheme()
, m_page(page)
@@ -985,10 +988,24 @@ bool RenderThemeEfl::paintSearchField(RenderObject* o, const PaintInfo& i, const
return paintThemePart(o, SearchField, i, rect);
}
-void RenderThemeEfl::systemFont(int, FontDescription&) const
+void RenderThemeEfl::setDefaultFontSize(int size)
{
- // If you remove this notImplemented(), replace it with an comment that explains why.
- notImplemented();
+ defaultFontSize = size;
+}
+
+void RenderThemeEfl::systemFont(int propId, FontDescription& fontDescription) const
+{
+ // It was called by RenderEmbeddedObject::paintReplaced to render alternative string.
+ // To avoid cairo_error while rendering, fontDescription should be passed.
+ DEFINE_STATIC_LOCAL(String, fontFace, ("Sans"));
+ float fontSize = defaultFontSize;
+
+ fontDescription.firstFamily().setFamily(fontFace);
+ fontDescription.setSpecifiedSize(fontSize);
+ fontDescription.setIsAbsoluteSize(true);
+ fontDescription.setGenericFamily(FontDescription::NoFamily);
+ fontDescription.setWeight(FontWeightNormal);
+ fontDescription.setItalic(false);
}
}
diff --git a/WebCore/platform/efl/RenderThemeEfl.h b/WebCore/platform/efl/RenderThemeEfl.h
index 8e5650d..478dfc5 100644
--- a/WebCore/platform/efl/RenderThemeEfl.h
+++ b/WebCore/platform/efl/RenderThemeEfl.h
@@ -142,6 +142,12 @@ public:
virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+
+ static void setDefaultFontSize(int size);
+
+protected:
+ static float defaultFontSize;
+
private:
void createCanvas();
void createEdje();
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index c48f91a..1056d81 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -48,6 +48,9 @@ class SurfaceOpenVG;
typedef class WebCore::SurfaceOpenVG PlatformGraphicsContext;
#elif PLATFORM(QT)
#include <QPainter>
+namespace WebCore {
+class ContextShadow;
+}
typedef QPainter PlatformGraphicsContext;
#elif PLATFORM(WX)
class wxGCDC;
@@ -329,8 +332,8 @@ namespace WebCore {
void setAlpha(float);
#if PLATFORM(CAIRO)
float getAlpha();
- void createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float kernelSize);
- static void calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const FloatSize& shadowSize, float shadowBlur);
+ void createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float radius);
+ static void calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& radius, const FloatRect& sourceRect, const FloatSize& shadowSize, float shadowBlur);
#endif
void setCompositeOperation(CompositeOperator);
@@ -431,6 +434,7 @@ namespace WebCore {
void pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask);
QPen pen();
static QPainter::CompositionMode toQtCompositionMode(CompositeOperator op);
+ ContextShadow* contextShadow();
#endif
#if PLATFORM(GTK)
diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp
index 51c4cd5..170bb84 100644
--- a/WebCore/platform/graphics/GraphicsContext3D.cpp
+++ b/WebCore/platform/graphics/GraphicsContext3D.cpp
@@ -144,7 +144,7 @@ bool GraphicsContext3D::extractTextureData(unsigned int width, unsigned int heig
unsigned int format, unsigned int type,
unsigned int unpackAlignment,
bool flipY, bool premultiplyAlpha,
- ArrayBufferView* pixels,
+ const void* pixels,
Vector<uint8_t>& data)
{
// Assumes format, type, etc. have already been validated.
@@ -193,7 +193,7 @@ bool GraphicsContext3D::extractTextureData(unsigned int width, unsigned int heig
unsigned long bytesPerPixel = componentsPerPixel * bytesPerComponent;
data.resize(width * height * bytesPerPixel);
- if (!packPixels(static_cast<uint8_t*>(pixels->baseAddress()),
+ if (!packPixels(static_cast<const uint8_t*>(pixels),
sourceDataFormat,
width, height, unpackAlignment,
format, type,
@@ -424,6 +424,7 @@ void packRGBA8ToRGBA8Premultiply(const uint8_t* source, uint8_t* destination)
destination[0] = sourceR;
destination[1] = sourceG;
destination[2] = sourceB;
+ destination[3] = source[3];
}
// FIXME: this routine is lossy and must be removed.
diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h
index 25d1d06..b583813 100644
--- a/WebCore/platform/graphics/GraphicsContext3D.h
+++ b/WebCore/platform/graphics/GraphicsContext3D.h
@@ -77,15 +77,10 @@ const Platform3DObject NullPlatform3DObject = 0;
#endif
namespace WebCore {
-class ArrayBuffer;
-class ArrayBufferView;
class CanvasRenderingContext;
-class Float32Array;
class HostWindow;
class Image;
class ImageData;
-class Int32Array;
-class Uint8Array;
class WebGLActiveInfo;
struct ActiveInfo {
@@ -468,6 +463,8 @@ public:
int sizeInBytes(int type);
bool isGLES2Compliant() const;
+ bool isGLES2NPOTStrict() const;
+ bool isErrorGeneratedOnOutOfBoundsAccesses() const;
//----------------------------------------------------------------------
// Helpers for texture uploading and pixel readback.
@@ -512,7 +509,7 @@ public:
unsigned int format, unsigned int type,
unsigned int unpackAlignment,
bool flipY, bool premultiplyAlpha,
- ArrayBufferView* pixels,
+ const void* pixels,
Vector<uint8_t>& data);
// Flips the given image data vertically, in-place.
@@ -556,10 +553,8 @@ public:
void blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha);
void bufferData(unsigned long target, int size, unsigned long usage);
- void bufferData(unsigned long target, ArrayBuffer* data, unsigned long usage);
- void bufferData(unsigned long target, ArrayBufferView* data, unsigned long usage);
- void bufferSubData(unsigned long target, long offset, ArrayBuffer* data);
- void bufferSubData(unsigned long target, long offset, ArrayBufferView* data);
+ void bufferData(unsigned long target, int size, const void* data, unsigned long usage);
+ void bufferSubData(unsigned long target, long offset, int size, const void* data);
unsigned long checkFramebufferStatus(unsigned long target);
void clear(unsigned long mask);
diff --git a/WebCore/platform/graphics/ImageSource.cpp b/WebCore/platform/graphics/ImageSource.cpp
index 7f6d323..c6d97fe 100644
--- a/WebCore/platform/graphics/ImageSource.cpp
+++ b/WebCore/platform/graphics/ImageSource.cpp
@@ -41,8 +41,9 @@ namespace WebCore {
unsigned ImageSource::s_maxPixelsPerDecodedImage = 1024 * 1024;
#endif
-ImageSource::ImageSource()
+ImageSource::ImageSource(bool premultiplyAlpha)
: m_decoder(0)
+ , m_premultiplyAlpha(premultiplyAlpha)
{
}
@@ -77,7 +78,7 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
// If insufficient bytes are available to determine the image type, no decoder plugin will be
// made.
if (!m_decoder) {
- m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data));
+ m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data, m_premultiplyAlpha));
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
if (m_decoder && s_maxPixelsPerDecodedImage)
m_decoder->setMaxNumPixels(s_maxPixelsPerDecodedImage);
diff --git a/WebCore/platform/graphics/ImageSource.h b/WebCore/platform/graphics/ImageSource.h
index 014c136..189f0f5 100644
--- a/WebCore/platform/graphics/ImageSource.h
+++ b/WebCore/platform/graphics/ImageSource.h
@@ -133,7 +133,7 @@ const int cAnimationNone = -2;
class ImageSource : public Noncopyable {
public:
- ImageSource();
+ ImageSource(bool premultiplyAlpha = true);
~ImageSource();
// Tells the ImageSource that the Image no longer cares about decoded frame
@@ -201,6 +201,7 @@ private:
protected:
#endif
NativeImageSourcePtr m_decoder;
+ bool m_premultiplyAlpha;
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
static unsigned s_maxPixelsPerDecodedImage;
#endif
diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp
index e72987a..87060a4 100644
--- a/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/WebCore/platform/graphics/MediaPlayer.cpp
@@ -194,6 +194,24 @@ static void addMediaEngine(CreateMediaEnginePlayer constructor, MediaEngineSuppo
installedMediaEngines().append(new MediaPlayerFactory(constructor, getSupportedTypes, supportsType));
}
+static const AtomicString& applicationOctetStream()
+{
+ DEFINE_STATIC_LOCAL(const AtomicString, applicationOctetStream, ("application/octet-stream"));
+ return applicationOctetStream;
+}
+
+static const AtomicString& textPlain()
+{
+ DEFINE_STATIC_LOCAL(const AtomicString, textPlain, ("text/plain"));
+ return textPlain;
+}
+
+static const AtomicString& codecs()
+{
+ DEFINE_STATIC_LOCAL(const AtomicString, codecs, ("codecs"));
+ return codecs;
+}
+
static MediaPlayerFactory* chooseBestEngineForTypeAndCodecs(const String& type, const String& codecs)
{
Vector<MediaPlayerFactory*>& engines = installedMediaEngines();
@@ -201,6 +219,14 @@ static MediaPlayerFactory* chooseBestEngineForTypeAndCodecs(const String& type,
if (engines.isEmpty())
return 0;
+ // 4.8.10.3 MIME types - In the absence of a specification to the contrary, the MIME type "application/octet-stream"
+ // when used with parameters, e.g. "application/octet-stream;codecs=theora", is a type that the user agent knows
+ // it cannot render.
+ if (type == applicationOctetStream()) {
+ if (!codecs.isEmpty())
+ return 0;
+ }
+
MediaPlayerFactory* engine = 0;
MediaPlayer::SupportsType supported = MediaPlayer::IsNotSupported;
@@ -252,11 +278,11 @@ MediaPlayer::~MediaPlayer()
void MediaPlayer::load(const String& url, const ContentType& contentType)
{
- String type = contentType.type();
- String codecs = contentType.parameter("codecs");
+ String type = contentType.type().lower();
+ String typeCodecs = contentType.parameter(codecs());
- // if we don't know the MIME type, see if the extension can help
- if (type.isEmpty() || type == "application/octet-stream" || type == "text/plain") {
+ // If the MIME type is unhelpful, see if the type registry has a match for the file extension.
+ if (type.isEmpty() || type == applicationOctetStream() || type == textPlain()) {
size_t pos = url.reverseFind('.');
if (pos != notFound) {
String extension = url.substring(pos + 1);
@@ -268,14 +294,17 @@ void MediaPlayer::load(const String& url, const ContentType& contentType)
MediaPlayerFactory* engine = 0;
if (!type.isEmpty())
- engine = chooseBestEngineForTypeAndCodecs(type, codecs);
+ engine = chooseBestEngineForTypeAndCodecs(type, typeCodecs);
- // if we didn't find an engine that claims the MIME type, just use the first engine
- if (!engine && !installedMediaEngines().isEmpty())
+ // If we didn't find an engine and no MIME type is specified, just use the first engine.
+ if (!engine && type.isEmpty() && !installedMediaEngines().isEmpty())
engine = installedMediaEngines()[0];
- // don't delete and recreate the player unless it comes from a different engine
- if (engine && m_currentMediaEngine != engine) {
+ // Don't delete and recreate the player unless it comes from a different engine
+ if (!engine) {
+ m_currentMediaEngine = engine;
+ m_private.clear();
+ } else if (m_currentMediaEngine != engine) {
m_currentMediaEngine = engine;
m_private.clear();
m_private.set(engine->constructor(this));
@@ -532,14 +561,26 @@ void MediaPlayer::paintCurrentFrameInContext(GraphicsContext* p, const IntRect&
MediaPlayer::SupportsType MediaPlayer::supportsType(ContentType contentType)
{
- String type = contentType.type();
- String codecs = contentType.parameter("codecs");
- MediaPlayerFactory* engine = chooseBestEngineForTypeAndCodecs(type, codecs);
+ String type = contentType.type().lower();
+ String typeCodecs = contentType.parameter(codecs());
+
+ // 4.8.10.3 MIME types - In the absence of a specification to the contrary, the MIME type "application/octet-stream"
+ // when used with parameters, e.g. "application/octet-stream;codecs=theora", is a type that the user agent knows
+ // it cannot render.
+ if (type == applicationOctetStream()) {
+ if (!typeCodecs.isEmpty())
+ return IsNotSupported;
+
+ // The MIME type "application/octet-stream" with no parameters is never a type that the user agent knows it
+ // cannot render.
+ return MayBeSupported;
+ }
+ MediaPlayerFactory* engine = chooseBestEngineForTypeAndCodecs(type, typeCodecs);
if (!engine)
return IsNotSupported;
- return engine->supportsTypeAndCodecs(type, codecs);
+ return engine->supportsTypeAndCodecs(type, typeCodecs);
}
void MediaPlayer::getSupportedTypes(HashSet<String>& types)
diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp
index 9217a81..f6d8f3d 100644
--- a/WebCore/platform/graphics/cairo/FontCairo.cpp
+++ b/WebCore/platform/graphics/cairo/FontCairo.cpp
@@ -94,15 +94,15 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
FloatRect rect(FloatPoint(), FloatSize(extents.width, extents.height));
IntSize shadowBufferSize;
FloatRect shadowRect;
- float kernelSize = 0.f;
- GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, rect, shadowSize, shadowBlur);
+ float radius = 0;
+ context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowSize, shadowBlur);
// Draw shadow into a new ImageBuffer
OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
GraphicsContext* shadowContext = shadowBuffer->context();
cairo_t* shadowCr = shadowContext->platformContext();
- cairo_translate(shadowCr, kernelSize, extents.height + kernelSize);
+ cairo_translate(shadowCr, radius, extents.height + radius);
cairo_set_scaled_font(shadowCr, font->platformData().scaledFont());
cairo_show_glyphs(shadowCr, glyphs, numGlyphs);
@@ -113,7 +113,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
cairo_restore(shadowCr);
}
cairo_translate(cr, 0.0, -extents.height);
- context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize);
+ context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
#else
cairo_translate(cr, shadowSize.width(), shadowSize.height());
cairo_show_glyphs(cr, glyphs, numGlyphs);
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 9b3096e..3a667ac 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -61,6 +61,8 @@
#include "GraphicsContextPlatformPrivateCairo.h"
#include "GraphicsContextPrivate.h"
+using namespace std;
+
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
@@ -173,18 +175,17 @@ static void addConvexPolygonToContext(cairo_t* context, size_t numPoints, const
cairo_close_path(context);
}
-void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const FloatSize& shadowSize, float shadowBlur)
+void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& radius, const FloatRect& sourceRect, const FloatSize& shadowSize, float shadowBlur)
{
#if ENABLE(FILTERS)
- // calculate the kernel size according to the HTML5 canvas shadow specification
- kernelSize = (shadowBlur < 8 ? shadowBlur / 2.f : sqrt(shadowBlur * 2.f));
- int blurRadius = ceil(kernelSize);
+ // limit radius to 128
+ radius = min(128.f, max(shadowBlur, 0.f));
- shadowBufferSize = IntSize(sourceRect.width() + blurRadius * 2, sourceRect.height() + blurRadius * 2);
+ shadowBufferSize = IntSize(sourceRect.width() + radius * 2, sourceRect.height() + radius * 2);
// determine dimensions of shadow rect
shadowRect = FloatRect(sourceRect.location(), shadowBufferSize);
- shadowRect.move(shadowSize.width() - kernelSize, shadowSize.height() - kernelSize);
+ shadowRect.move(shadowSize.width() - radius, shadowSize.height() - radius);
#endif
}
@@ -209,8 +210,8 @@ static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPriva
IntSize shadowBufferSize;
FloatRect shadowRect;
- float kernelSize = 0;
- GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, rect, shadowSize, shadowBlur);
+ float radius = 0;
+ GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowSize, shadowBlur);
// Create suitably-sized ImageBuffer to hold the shadow.
OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
@@ -218,7 +219,7 @@ static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPriva
// Draw shadow into a new ImageBuffer.
cairo_t* shadowContext = shadowBuffer->context()->platformContext();
copyContextProperties(cr, shadowContext);
- cairo_translate(shadowContext, -rect.x() + kernelSize, -rect.y() + kernelSize);
+ cairo_translate(shadowContext, -rect.x() + radius, -rect.y() + radius);
cairo_new_path(shadowContext);
cairo_append_path(shadowContext, path);
@@ -227,7 +228,7 @@ static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPriva
if (strokeShadow)
setPlatformStroke(context, shadowContext, gcp);
- context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize);
+ context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
#endif
}
@@ -631,15 +632,15 @@ static void drawBorderlessRectShadow(GraphicsContext* context, const FloatRect&
IntSize shadowBufferSize;
FloatRect shadowRect;
- float kernelSize = 0;
- GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, rect, shadowSize, shadowBlur);
+ float radius = 0;
+ GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowSize, shadowBlur);
// Draw shadow into a new ImageBuffer
OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
GraphicsContext* shadowContext = shadowBuffer->context();
- shadowContext->fillRect(FloatRect(FloatPoint(kernelSize, kernelSize), rect.size()), rectColor, DeviceColorSpace);
+ shadowContext->fillRect(FloatRect(FloatPoint(radius, radius), rect.size()), rectColor, DeviceColorSpace);
- context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize);
+ context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
#endif
}
@@ -920,28 +921,28 @@ void GraphicsContext::setPlatformShadow(FloatSize const& size, float, Color cons
}
}
-void GraphicsContext::createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float kernelSize)
+void GraphicsContext::createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float radius)
{
#if ENABLE(FILTERS)
cairo_t* cr = m_data->cr;
- // draw the shadow without blurring, if kernelSize is zero
- if (!kernelSize) {
+ // calculate the standard deviation
+ float sd = FEGaussianBlur::calculateStdDeviation(radius);
+
+ // draw the shadow without blurring, if radius is zero
+ if (!radius || !sd) {
setColor(cr, shadowColor);
cairo_mask_surface(cr, buffer->m_data.m_surface, shadowRect.x(), shadowRect.y());
return;
}
- // limit kernel size to 1000, this is what CG is doing.
- kernelSize = std::min(1000.f, kernelSize);
-
// create filter
RefPtr<Filter> filter = ImageBufferFilter::create();
filter->setSourceImage(buffer);
RefPtr<FilterEffect> source = SourceGraphic::create();
source->setScaledSubRegion(FloatRect(FloatPoint(), shadowRect.size()));
source->setIsAlphaImage(true);
- RefPtr<FilterEffect> blur = FEGaussianBlur::create(source.get(), kernelSize, kernelSize);
+ RefPtr<FilterEffect> blur = FEGaussianBlur::create(source.get(), sd, sd);
blur->setScaledSubRegion(FloatRect(FloatPoint(), shadowRect.size()));
blur->apply(filter.get());
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
index 97e7e07..81987ef 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
+++ b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
@@ -27,6 +27,7 @@
#include "GraphicsContext.h"
+#include "CairoPath.h"
#include <cairo.h>
#include <math.h>
#include <stdio.h>
diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index db66276..976dcb4 100644
--- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -38,10 +38,8 @@
#include "NotImplemented.h"
#include "Pattern.h"
#include "PlatformString.h"
-
#include <cairo.h>
#include <wtf/Vector.h>
-#include <math.h>
using namespace std;
@@ -100,7 +98,7 @@ GraphicsContext* ImageBuffer::context() const
bool ImageBuffer::drawsUsingCopy() const
{
- return true;
+ return false;
}
PassRefPtr<Image> ImageBuffer::copyImage() const
@@ -112,20 +110,23 @@ PassRefPtr<Image> ImageBuffer::copyImage() const
void ImageBuffer::clip(GraphicsContext*, const FloatRect&) const
{
notImplemented();
+ // See https://bugs.webkit.org/show_bug.cgi?id=23526 for why this is unimplemented.
}
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);
+ // BitmapImage will release the passed in surface on destruction
+ RefPtr<Image> image = BitmapImage::create(cairo_surface_reference(m_data.m_surface));
+ context->drawImage(image.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);
+ // BitmapImage will release the passed in surface on destruction
+ RefPtr<Image> image = BitmapImage::create(cairo_surface_reference(m_data.m_surface));
+ image->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 1582671..d9eb5e6 100644
--- a/WebCore/platform/graphics/cairo/ImageCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp
@@ -33,7 +33,7 @@
#include "AffineTransform.h"
#include "Color.h"
#include "FloatRect.h"
-#include "GRefPtrCairo.h"
+#include "PlatformRefPtrCairo.h"
#include "GraphicsContext.h"
#include "ImageBuffer.h"
#include "ImageObserver.h"
@@ -141,8 +141,8 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
if (context->getShadow(shadowSize, shadowBlur, shadowColor)) {
IntSize shadowBufferSize;
FloatRect shadowRect;
- float kernelSize (0.0);
- GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, dstRect, shadowSize, shadowBlur);
+ float radius = 0;
+ context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, dstRect, shadowSize, shadowBlur);
shadowColor = colorWithOverrideAlpha(shadowColor.rgb(), (shadowColor.alpha() * context->getAlpha()) / 255.f);
//draw shadow into a new ImageBuffer
@@ -153,7 +153,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
cairo_rectangle(shadowContext, 0, 0, dstRect.width(), dstRect.height());
cairo_fill(shadowContext);
- context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize);
+ context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
}
#endif
@@ -185,11 +185,11 @@ void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, con
cairo_t* cr = context->platformContext();
context->save();
- GRefPtr<cairo_surface_t> clippedImageSurface = 0;
+ PlatformRefPtr<cairo_surface_t> clippedImageSurface = 0;
if (tileRect.size() != size()) {
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()));
+ clippedImageSurface = adoptPlatformRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, imageSize.width(), imageSize.height()));
+ PlatformRefPtr<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();
diff --git a/WebCore/platform/graphics/cairo/GRefPtrCairo.cpp b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp
index d244954..6870560 100644
--- a/WebCore/platform/graphics/cairo/GRefPtrCairo.cpp
+++ b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp
@@ -17,33 +17,33 @@
*/
#include "config.h"
-#include "GRefPtrCairo.h"
+#include "PlatformRefPtrCairo.h"
#include <cairo.h>
namespace WTF {
-template <> cairo_t* refGPtr(cairo_t* ptr)
+template <> cairo_t* refPlatformPtr(cairo_t* ptr)
{
if (ptr)
cairo_reference(ptr);
return ptr;
}
-template <> void derefGPtr(cairo_t* ptr)
+template <> void derefPlatformPtr(cairo_t* ptr)
{
if (ptr)
cairo_destroy(ptr);
}
-template <> cairo_surface_t* refGPtr(cairo_surface_t* ptr)
+template <> cairo_surface_t* refPlatformPtr(cairo_surface_t* ptr)
{
if (ptr)
cairo_surface_reference(ptr);
return ptr;
}
-template <> void derefGPtr(cairo_surface_t* ptr)
+template <> void derefPlatformPtr(cairo_surface_t* ptr)
{
if (ptr)
cairo_surface_destroy(ptr);
diff --git a/WebCore/platform/graphics/cairo/GRefPtrCairo.h b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h
index aef51fe..51d8fa9 100644
--- a/WebCore/platform/graphics/cairo/GRefPtrCairo.h
+++ b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h
@@ -17,21 +17,21 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef GRefPtrCairo_h
-#define GRefPtrCairo_h
+#ifndef PlatformRefPtrCairo_h
+#define PlatformRefPtrCairo_h
-#include "GRefPtr.h"
+#include "PlatformRefPtr.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_t* refPlatformPtr(cairo_t* ptr);
+template <> void derefPlatformPtr(cairo_t* ptr);
-template <> cairo_surface_t* refGPtr(cairo_surface_t* ptr);
-template <> void derefGPtr(cairo_surface_t* ptr);
+template <> cairo_surface_t* refPlatformPtr(cairo_surface_t* ptr);
+template <> void derefPlatformPtr(cairo_surface_t* ptr);
}
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
index 4a7aecc..5fa4896 100644
--- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -63,8 +63,10 @@ void sharedBufferRelease(void* info)
}
#endif
-ImageSource::ImageSource()
+ImageSource::ImageSource(bool premultiplyAlpha)
: m_decoder(0)
+ // FIXME: m_premultiplyAlpha is ignored in cg at the moment.
+ , m_premultiplyAlpha(premultiplyAlpha)
{
}
diff --git a/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp b/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
index 7e732d1..bbf091c 100644
--- a/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
@@ -35,11 +35,63 @@
#include "CanvasLayerChromium.h"
#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
#include <GLES2/gl2.h>
namespace WebCore {
-unsigned CanvasLayerChromium::m_shaderProgramId = 0;
+CanvasLayerChromium::SharedValues::SharedValues()
+ : m_canvasShaderProgram(0)
+ , m_shaderSamplerLocation(-1)
+ , m_shaderMatrixLocation(-1)
+ , m_shaderAlphaLocation(-1)
+ , m_initialized(false)
+{
+ char vertexShaderString[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "uniform mat4 matrix; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = matrix * a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ // Canvas layers need to be flipped vertically and their colors shouldn't be
+ // swizzled.
+ char fragmentShaderString[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "uniform float alpha; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); \n"
+ " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
+ "} \n";
+
+ m_canvasShaderProgram = createShaderProgram(vertexShaderString, fragmentShaderString);
+ if (!m_canvasShaderProgram) {
+ LOG_ERROR("CanvasLayerChromium: Failed to create shader program");
+ return;
+ }
+
+ m_shaderSamplerLocation = glGetUniformLocation(m_canvasShaderProgram, "s_texture");
+ m_shaderMatrixLocation = glGetUniformLocation(m_canvasShaderProgram, "matrix");
+ m_shaderAlphaLocation = glGetUniformLocation(m_canvasShaderProgram, "alpha");
+ ASSERT(m_shaderSamplerLocation != -1);
+ ASSERT(m_shaderMatrixLocation != -1);
+ ASSERT(m_shaderAlphaLocation != -1);
+
+ m_initialized = true;
+}
+
+CanvasLayerChromium::SharedValues::~SharedValues()
+{
+ if (m_canvasShaderProgram)
+ GLC(glDeleteProgram(m_canvasShaderProgram));
+}
PassRefPtr<CanvasLayerChromium> CanvasLayerChromium::create(GraphicsLayerChromium* owner)
{
@@ -54,14 +106,8 @@ CanvasLayerChromium::CanvasLayerChromium(GraphicsLayerChromium* owner)
{
}
-unsigned CanvasLayerChromium::textureId()
-{
- return m_textureId;
-}
-
-void CanvasLayerChromium::updateTextureContents(unsigned textureId)
+void CanvasLayerChromium::updateContents()
{
- ASSERT(textureId == m_textureId);
ASSERT(m_context);
if (m_textureChanged) {
glBindTexture(GL_TEXTURE_2D, m_textureId);
@@ -92,5 +138,19 @@ void CanvasLayerChromium::setContext(const GraphicsContext3D* context)
m_textureId = textureId;
}
+void CanvasLayerChromium::draw()
+{
+ ASSERT(layerRenderer());
+ const CanvasLayerChromium::SharedValues* sv = layerRenderer()->canvasLayerSharedValues();
+ ASSERT(sv && sv->initialized());
+ GLC(glActiveTexture(GL_TEXTURE0));
+ GLC(glBindTexture(GL_TEXTURE_2D, m_textureId));
+ layerRenderer()->useShader(sv->canvasShaderProgram());
+ GLC(glUniform1i(sv->shaderSamplerLocation(), 0));
+ drawTexturedQuad(layerRenderer()->projectionMatrix(), drawTransform(),
+ bounds().width(), bounds().height(), drawOpacity(),
+ sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
+}
+
}
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/chromium/CanvasLayerChromium.h b/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
index 98be270..053efff 100644
--- a/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
@@ -45,14 +45,29 @@ class CanvasLayerChromium : public LayerChromium {
public:
static PassRefPtr<CanvasLayerChromium> create(GraphicsLayerChromium* owner = 0);
virtual bool drawsContent() { return m_context; }
- virtual bool ownsTexture() { return true; }
- virtual void updateTextureContents(unsigned);
- virtual unsigned textureId();
- virtual unsigned shaderProgramId() { return m_shaderProgramId; }
+ virtual void updateContents();
+ virtual void draw();
void setContext(const GraphicsContext3D* context);
- static void setShaderProgramId(unsigned shaderProgramId) { m_shaderProgramId = shaderProgramId; }
+ class SharedValues {
+ public:
+ SharedValues();
+ ~SharedValues();
+
+ unsigned canvasShaderProgram() const { return m_canvasShaderProgram; }
+ int shaderSamplerLocation() const { return m_shaderSamplerLocation; }
+ int shaderMatrixLocation() const { return m_shaderMatrixLocation; }
+ int shaderAlphaLocation() const { return m_shaderAlphaLocation; }
+ bool initialized() const { return m_initialized; }
+
+ private:
+ unsigned m_canvasShaderProgram;
+ int m_shaderSamplerLocation;
+ int m_shaderMatrixLocation;
+ int m_shaderAlphaLocation;
+ bool m_initialized;
+ };
class PrepareTextureCallback : public Noncopyable {
public:
@@ -66,8 +81,6 @@ private:
unsigned m_textureId;
bool m_textureChanged;
OwnPtr<PrepareTextureCallback> m_prepareTextureCallback;
-
- static unsigned m_shaderProgramId;
};
}
diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
new file mode 100644
index 0000000..974933d
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
@@ -0,0 +1,301 @@
+/*
+ * 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"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "ContentLayerChromium.h"
+
+#include "LayerRendererChromium.h"
+#include "RenderLayerBacking.h"
+
+#if PLATFORM(SKIA)
+#include "NativeImageSkia.h"
+#include "PlatformContextSkia.h"
+#include "skia/ext/platform_canvas.h"
+#elif PLATFORM(CG)
+#include <CoreGraphics/CGBitmapContext.h>
+#endif
+
+#include <GLES2/gl2.h>
+
+namespace WebCore {
+
+ContentLayerChromium::SharedValues::SharedValues()
+ : m_contentShaderProgram(0)
+ , m_shaderSamplerLocation(-1)
+ , m_shaderMatrixLocation(-1)
+ , m_shaderAlphaLocation(-1)
+ , m_initialized(false)
+{
+ // Shaders for drawing the layer contents.
+ char vertexShaderString[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "uniform mat4 matrix; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = matrix * a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ // Note differences between Skia and Core Graphics versions:
+ // - Skia uses BGRA and origin is upper left
+ // - Core Graphics uses RGBA and origin is lower left
+ char fragmentShaderString[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "uniform float alpha; \n"
+ "void main() \n"
+ "{ \n"
+#if PLATFORM(SKIA)
+ " vec4 texColor = texture2D(s_texture, v_texCoord); \n"
+ " gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha; \n"
+#elif PLATFORM(CG)
+ " vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); \n"
+ " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
+#else
+#error "Need to implement for your platform."
+#endif
+ "} \n";
+
+ m_contentShaderProgram = createShaderProgram(vertexShaderString, fragmentShaderString);
+ if (!m_contentShaderProgram) {
+ LOG_ERROR("ContentLayerChromium: Failed to create shader program");
+ return;
+ }
+
+ m_shaderSamplerLocation = glGetUniformLocation(m_contentShaderProgram, "s_texture");
+ m_shaderMatrixLocation = glGetUniformLocation(m_contentShaderProgram, "matrix");
+ m_shaderAlphaLocation = glGetUniformLocation(m_contentShaderProgram, "alpha");
+ ASSERT(m_shaderSamplerLocation != -1);
+ ASSERT(m_shaderMatrixLocation != -1);
+ ASSERT(m_shaderAlphaLocation != -1);
+
+ m_initialized = true;
+}
+
+ContentLayerChromium::SharedValues::~SharedValues()
+{
+ if (m_contentShaderProgram)
+ GLC(glDeleteProgram(m_contentShaderProgram));
+}
+
+
+PassRefPtr<ContentLayerChromium> ContentLayerChromium::create(GraphicsLayerChromium* owner)
+{
+ return adoptRef(new ContentLayerChromium(owner));
+}
+
+ContentLayerChromium::ContentLayerChromium(GraphicsLayerChromium* owner)
+ : LayerChromium(owner)
+ , m_contentsTexture(0)
+{
+}
+
+ContentLayerChromium::~ContentLayerChromium()
+{
+ if (m_contentsTexture)
+ GLC(glDeleteTextures(1, &m_contentsTexture));
+}
+
+
+void ContentLayerChromium::updateContents()
+{
+ RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
+ if (!backing || backing->paintingGoesToWindow())
+ return;
+
+ ASSERT(drawsContent());
+
+ ASSERT(layerRenderer());
+
+ // FIXME: Remove this test when tiled layers are implemented.
+ m_skipsDraw = false;
+ if (!layerRenderer()->checkTextureSize(m_bounds)) {
+ m_skipsDraw = true;
+ return;
+ }
+
+ void* pixels = 0;
+ IntRect dirtyRect(m_dirtyRect);
+ IntSize requiredTextureSize;
+ IntSize bitmapSize;
+
+#if PLATFORM(SKIA)
+ const SkBitmap* skiaBitmap = 0;
+ OwnPtr<skia::PlatformCanvas> canvas;
+ OwnPtr<PlatformContextSkia> skiaContext;
+ OwnPtr<GraphicsContext> graphicsContext;
+
+ requiredTextureSize = m_bounds;
+ IntRect boundsRect(IntPoint(0, 0), m_bounds);
+
+ // If the texture needs to be reallocated then we must redraw the entire
+ // contents of the layer.
+ if (requiredTextureSize != m_allocatedTextureSize)
+ dirtyRect = boundsRect;
+ else {
+ // Clip the dirtyRect to the size of the layer to avoid drawing outside
+ // the bounds of the backing texture.
+ dirtyRect.intersect(boundsRect);
+ }
+
+ canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false));
+ skiaContext.set(new PlatformContextSkia(canvas.get()));
+
+#if OS(WINDOWS)
+ // This is needed to get text to show up correctly. Without it,
+ // GDI renders with zero alpha and the text becomes invisible.
+ // Unfortunately, setting this to true disables cleartype.
+ // FIXME: Does this take us down a very slow text rendering path?
+ // FIXME: why is this is a windows-only call ?
+ skiaContext->setDrawingToImageBuffer(true);
+#endif
+
+ graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get())));
+
+ // Bring the canvas into the coordinate system of the paint rect.
+ canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y()));
+
+ m_owner->paintGraphicsLayerContents(*graphicsContext, dirtyRect);
+ const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
+ skiaBitmap = &bitmap;
+ ASSERT(skiaBitmap);
+
+ SkAutoLockPixels lock(*skiaBitmap);
+ SkBitmap::Config skiaConfig = skiaBitmap->config();
+ // FIXME: do we need to support more image configurations?
+ if (skiaConfig == SkBitmap::kARGB_8888_Config) {
+ pixels = skiaBitmap->getPixels();
+ bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
+ }
+#elif PLATFORM(CG)
+ requiredTextureSize = m_bounds;
+ IntRect boundsRect(IntPoint(0, 0), m_bounds);
+
+ // If the texture needs to be reallocated then we must redraw the entire
+ // contents of the layer.
+ if (requiredTextureSize != m_allocatedTextureSize)
+ dirtyRect = boundsRect;
+ else {
+ // Clip the dirtyRect to the size of the layer to avoid drawing outside
+ // the bounds of the backing texture.
+ dirtyRect.intersect(boundsRect);
+ }
+
+ Vector<uint8_t> tempVector;
+ int rowBytes = 4 * dirtyRect.width();
+ tempVector.resize(rowBytes * dirtyRect.height());
+ memset(tempVector.data(), 0, tempVector.size());
+ RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+ RetainPtr<CGContextRef> contextCG(AdoptCF, CGBitmapContextCreate(tempVector.data(),
+ dirtyRect.width(), dirtyRect.height(), 8, rowBytes,
+ colorSpace.get(),
+ kCGImageAlphaPremultipliedLast));
+
+ GraphicsContext graphicsContext(contextCG.get());
+
+ // Translate the graphics contxt into the coordinate system of the dirty rect.
+ graphicsContext.translate(-dirtyRect.x(), -dirtyRect.y());
+
+ m_owner->paintGraphicsLayerContents(graphicsContext, dirtyRect);
+
+ pixels = tempVector.data();
+ bitmapSize = dirtyRect.size();
+#else
+#error "Need to implement for your platform."
+#endif
+
+ unsigned textureId = m_contentsTexture;
+ if (!textureId)
+ textureId = layerRenderer()->createLayerTexture();
+
+ if (pixels)
+ updateTextureRect(pixels, bitmapSize, requiredTextureSize, dirtyRect, textureId);
+}
+
+void ContentLayerChromium::updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize, const IntRect& updateRect, unsigned textureId)
+{
+ if (!pixels)
+ return;
+
+ glBindTexture(GL_TEXTURE_2D, textureId);
+
+ // If the texture id or size changed since last time then we need to tell GL
+ // to re-allocate a texture.
+ if (m_contentsTexture != textureId || requiredTextureSize != m_allocatedTextureSize) {
+ ASSERT(bitmapSize == requiredTextureSize);
+ GLC(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
+
+ m_contentsTexture = textureId;
+ m_allocatedTextureSize = requiredTextureSize;
+ } else {
+ ASSERT(updateRect.width() <= m_allocatedTextureSize.width() && updateRect.height() <= m_allocatedTextureSize.height());
+ ASSERT(updateRect.width() == bitmapSize.width() && updateRect.height() == bitmapSize.height());
+#if PLATFORM(CG)
+ // The origin is at the lower left in Core Graphics' coordinate system. We need to correct for this here.
+ GLC(glTexSubImage2D(GL_TEXTURE_2D, 0,
+ updateRect.x(), m_allocatedTextureSize.height() - updateRect.height() - updateRect.y(),
+ updateRect.width(), updateRect.height(),
+ GL_RGBA, GL_UNSIGNED_BYTE, pixels));
+#elif PLATFORM(SKIA)
+ GLC(glTexSubImage2D(GL_TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels));
+#else
+#error "Need to implement for your platform."
+#endif
+ }
+
+ m_dirtyRect.setSize(FloatSize());
+ m_contentsDirty = false;
+}
+
+void ContentLayerChromium::draw()
+{
+ if (m_skipsDraw)
+ return;
+
+ ASSERT(layerRenderer());
+ const ContentLayerChromium::SharedValues* sv = layerRenderer()->contentLayerSharedValues();
+ ASSERT(sv && sv->initialized());
+ GLC(glActiveTexture(GL_TEXTURE0));
+ GLC(glBindTexture(GL_TEXTURE_2D, m_contentsTexture));
+ layerRenderer()->useShader(sv->contentShaderProgram());
+ GLC(glUniform1i(sv->shaderSamplerLocation(), 0));
+ drawTexturedQuad(layerRenderer()->projectionMatrix(), drawTransform(),
+ bounds().width(), bounds().height(), drawOpacity(),
+ sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/WebCore/platform/graphics/chromium/ContentLayerChromium.h
new file mode 100644
index 0000000..3e15372
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.h
@@ -0,0 +1,90 @@
+/*
+ * 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 ContentLayerChromium_h
+#define ContentLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerChromium.h"
+
+namespace WebCore {
+
+// A Layer that requires a GraphicsContext to render its contents.
+class ContentLayerChromium : public LayerChromium {
+ friend class LayerRendererChromium;
+public:
+ static PassRefPtr<ContentLayerChromium> create(GraphicsLayerChromium* owner = 0);
+
+ ~ContentLayerChromium();
+
+ virtual void updateContents();
+ virtual void draw();
+ virtual bool drawsContent() { return m_owner && m_owner->drawsContent(); }
+
+ // Stores values that are shared between instances of this class that are
+ // associated with the same LayerRendererChromium (and hence the same GL
+ // context).
+ class SharedValues {
+ public:
+ SharedValues();
+ ~SharedValues();
+
+ unsigned contentShaderProgram() const { return m_contentShaderProgram; }
+ int shaderSamplerLocation() const { return m_shaderSamplerLocation; }
+ int shaderMatrixLocation() const { return m_shaderMatrixLocation; }
+ int shaderAlphaLocation() const { return m_shaderAlphaLocation; }
+ int initialized() const { return m_initialized; }
+
+ private:
+ unsigned m_contentShaderProgram;
+ int m_shaderSamplerLocation;
+ int m_shaderMatrixLocation;
+ int m_shaderAlphaLocation;
+ int m_initialized;
+ };
+
+protected:
+ ContentLayerChromium(GraphicsLayerChromium* owner);
+
+ void updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize,
+ const IntRect& updateRect, unsigned textureId);
+
+ unsigned m_contentsTexture;
+ IntSize m_allocatedTextureSize;
+ bool m_skipsDraw;
+
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
index 534de7b..c0cb87c 100644
--- a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
+++ b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
@@ -34,13 +34,11 @@
#include "GLES2Canvas.h"
-#include "Float32Array.h"
#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>
@@ -79,7 +77,6 @@ struct GLES2Canvas::State {
GLES2Canvas::GLES2Canvas(GraphicsContext3D* context, const IntSize& size)
: m_context(context)
, m_quadVertices(0)
- , m_quadIndices(0)
, m_simpleProgram(0)
, m_texProgram(0)
, m_simpleMatrixLocation(-1)
@@ -111,40 +108,33 @@ GLES2Canvas::~GLES2Canvas()
m_context->deleteProgram(m_simpleProgram);
m_context->deleteProgram(m_texProgram);
m_context->deleteBuffer(m_quadVertices);
- m_context->deleteBuffer(m_quadIndices);
}
void GLES2Canvas::clearRect(const FloatRect& rect)
{
- m_context->scissor(rect.x(), rect.y(), rect.width(), rect.height());
- m_context->enable(GraphicsContext3D::SCISSOR_TEST);
- m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
- m_context->disable(GraphicsContext3D::SCISSOR_TEST);
+ if (m_state->m_ctm.isIdentity()) {
+ m_context->scissor(rect.x(), rect.y(), rect.width(), rect.height());
+ m_context->enable(GraphicsContext3D::SCISSOR_TEST);
+ m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
+ m_context->disable(GraphicsContext3D::SCISSOR_TEST);
+ } else {
+ save();
+ setCompositeOperation(CompositeClear);
+ fillRect(rect, Color(RGBA32(0)), DeviceColorSpace);
+ restore();
+ }
}
void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
- m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, getQuadVertices());
- m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, getQuadIndices());
-
- float rgba[4];
- color.getRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
- m_context->uniform4f(m_simpleColorLocation, rgba[0] * rgba[3], rgba[1] * rgba[3], rgba[2] * rgba[3], rgba[3]);
-
- m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0);
-}
-
-void GLES2Canvas::fillRect(const FloatRect& rect)
-{
applyCompositeOperator(m_state->m_compositeOp);
m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, getQuadVertices());
- m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, getQuadIndices());
m_context->useProgram(getSimpleProgram());
float rgba[4];
- m_state->m_fillColor.getRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
+ color.getRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
m_context->uniform4f(m_simpleColorLocation, rgba[0] * rgba[3], rgba[1] * rgba[3], rgba[2] * rgba[3], rgba[3]);
AffineTransform matrix(m_flipMatrix);
@@ -159,7 +149,12 @@ void GLES2Canvas::fillRect(const FloatRect& rect)
m_context->enableVertexAttribArray(m_simplePositionLocation);
- m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0);
+ m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4);
+}
+
+void GLES2Canvas::fillRect(const FloatRect& rect)
+{
+ fillRect(rect, m_state->m_fillColor, DeviceColorSpace);
}
void GLES2Canvas::setFillColor(const Color& color, ColorSpace colorSpace)
@@ -215,7 +210,6 @@ void GLES2Canvas::drawTexturedRect(GLES2Texture* texture, const FloatRect& srcRe
applyCompositeOperator(compositeOp);
m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, getQuadVertices());
- m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, getQuadIndices());
checkGLError("glBindBuffer");
m_context->useProgram(getTexProgram());
@@ -275,8 +269,8 @@ void GLES2Canvas::drawTexturedRectTile(GLES2Texture* texture, int tile, const Fl
m_context->uniformMatrix3fv(m_texTexMatrixLocation, false /*transpose*/, texMat, 1 /*count*/);
checkGLError("glUniformMatrix3fv");
- m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0);
- checkGLError("glDrawElements");
+ m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4);
+ checkGLError("glDrawArrays");
}
void GLES2Canvas::setCompositeOperation(CompositeOperator op)
@@ -351,30 +345,16 @@ unsigned GLES2Canvas::getQuadVertices()
if (!m_quadVertices) {
float vertices[] = { 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f,
- 1.0f, 1.0f, 1.0f,
- 0.0f, 1.0f, 1.0f };
+ 0.0f, 1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f };
m_quadVertices = m_context->createBuffer();
- RefPtr<Float32Array> vertexArray = Float32Array::create(vertices, sizeof(vertices) / sizeof(float));
m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_quadVertices);
- m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, vertexArray.get(), GraphicsContext3D::STATIC_DRAW);
+ m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, sizeof(vertices), vertices, GraphicsContext3D::STATIC_DRAW);
}
return m_quadVertices;
}
-unsigned GLES2Canvas::getQuadIndices()
-{
- if (!m_quadIndices) {
- unsigned short indices[] = { 0, 1, 2, 0, 2, 3};
-
- m_quadIndices = m_context->createBuffer();
- RefPtr<Uint16Array> indexArray = Uint16Array::create(indices, sizeof(indices) / sizeof(unsigned short));
- m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_quadIndices);
- m_context->bufferData(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, indexArray.get(), GraphicsContext3D::STATIC_DRAW);
- }
- return m_quadIndices;
-}
-
static unsigned loadShader(GraphicsContext3D* context, unsigned type, const char* shaderSource)
{
unsigned shader = context->createShader(type);
diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.h b/WebCore/platform/graphics/chromium/GLES2Canvas.h
index 0ad07fc..d00510a 100644
--- a/WebCore/platform/graphics/chromium/GLES2Canvas.h
+++ b/WebCore/platform/graphics/chromium/GLES2Canvas.h
@@ -85,7 +85,6 @@ private:
void applyCompositeOperator(CompositeOperator);
void checkGLError(const char* header);
unsigned getQuadVertices();
- unsigned getQuadIndices();
unsigned getSimpleProgram();
unsigned getTexProgram();
@@ -94,7 +93,6 @@ private:
WTF::Vector<State> m_stateStack;
State* m_state;
unsigned m_quadVertices;
- unsigned m_quadIndices;
unsigned m_simpleProgram;
unsigned m_texProgram;
int m_simpleMatrixLocation;
diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
index 1d67857..648e35f 100644
--- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
@@ -45,6 +45,7 @@
#include "GraphicsLayerChromium.h"
+#include "ContentLayerChromium.h"
#include "FloatConversion.h"
#include "FloatRect.h"
#include "Image.h"
@@ -52,7 +53,6 @@
#include "LayerChromium.h"
#include "PlatformString.h"
#include "SystemTime.h"
-#include "TransformLayerChromium.h"
#include <wtf/CurrentTime.h>
#include <wtf/StringExtras.h>
@@ -97,7 +97,7 @@ GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
, m_contentsLayerPurpose(NoContentsLayer)
, m_contentsLayerHasBackgroundColor(false)
{
- m_layer = LayerChromium::create(this);
+ m_layer = ContentLayerChromium::create(this);
updateDebugIndicators();
}
@@ -538,7 +538,7 @@ void GraphicsLayerChromium::updateLayerPreserves3D()
{
if (m_preserves3D && !m_transformLayer) {
// Create the transform layer.
- m_transformLayer = TransformLayerChromium::create(this);
+ m_transformLayer = LayerChromium::create(this);
// Copy the position from this layer.
updateLayerPosition();
diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
index 3cc7cad..09b388d 100644
--- a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
@@ -34,6 +34,8 @@
#include "ImageLayerChromium.h"
+#include "LayerRendererChromium.h"
+
#if PLATFORM(SKIA)
#include "NativeImageSkia.h"
#include "PlatformContextSkia.h"
@@ -54,7 +56,7 @@ PassRefPtr<ImageLayerChromium> ImageLayerChromium::create(GraphicsLayerChromium*
}
ImageLayerChromium::ImageLayerChromium(GraphicsLayerChromium* owner)
- : LayerChromium(owner)
+ : ContentLayerChromium(owner)
, m_contents(0)
{
}
@@ -68,8 +70,10 @@ void ImageLayerChromium::setContents(NativeImagePtr contents)
setNeedsDisplay();
}
-void ImageLayerChromium::updateTextureContents(unsigned textureId)
+void ImageLayerChromium::updateContents()
{
+ ASSERT(layerRenderer());
+
void* pixels = 0;
IntRect dirtyRect(m_dirtyRect);
IntSize requiredTextureSize;
@@ -129,6 +133,17 @@ void ImageLayerChromium::updateTextureContents(unsigned textureId)
#else
#error "Need to implement for your platform."
#endif
+ // FIXME: Remove this test when tiled layers are implemented.
+ m_skipsDraw = false;
+ if (!layerRenderer()->checkTextureSize(requiredTextureSize)) {
+ m_skipsDraw = true;
+ return;
+ }
+
+ unsigned textureId = m_contentsTexture;
+ if (!textureId)
+ textureId = layerRenderer()->createLayerTexture();
+
if (pixels)
updateTextureRect(pixels, bitmapSize, requiredTextureSize, dirtyRect, textureId);
}
diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/WebCore/platform/graphics/chromium/ImageLayerChromium.h
index 9355b2d..e95284c 100644
--- a/WebCore/platform/graphics/chromium/ImageLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.h
@@ -34,16 +34,18 @@
#if USE(ACCELERATED_COMPOSITING)
-#include "LayerChromium.h"
+#include "ContentLayerChromium.h"
namespace WebCore {
// A Layer that contains only an Image element.
-class ImageLayerChromium : public LayerChromium {
+class ImageLayerChromium : public ContentLayerChromium {
public:
static PassRefPtr<ImageLayerChromium> create(GraphicsLayerChromium* owner = 0);
+
+ virtual void updateContents();
virtual bool drawsContent() { return m_contents; }
- virtual void updateTextureContents(unsigned textureId);
+
void setContents(NativeImagePtr);
private:
diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp
index 21d8d12..3553878 100644
--- a/WebCore/platform/graphics/chromium/LayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp
@@ -48,7 +48,93 @@ namespace WebCore {
using namespace std;
-unsigned LayerChromium::m_shaderProgramId = 0;
+const unsigned LayerChromium::s_positionAttribLocation = 0;
+const unsigned LayerChromium::s_texCoordAttribLocation = 1;
+
+static GLuint loadShader(GLenum type, const char* shaderSource)
+{
+ GLuint shader = glCreateShader(type);
+ if (!shader)
+ return 0;
+ GLC(glShaderSource(shader, 1, &shaderSource, 0));
+ GLC(glCompileShader(shader));
+ GLint compiled;
+ GLC(glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled));
+ if (!compiled) {
+ GLC(glDeleteShader(shader));
+ return 0;
+ }
+ return shader;
+}
+
+LayerChromium::SharedValues::SharedValues()
+ : m_quadVerticesVbo(0)
+ , m_quadElementsVbo(0)
+ , m_maxTextureSize(0)
+ , m_borderShaderProgram(0)
+ , m_borderShaderMatrixLocation(-1)
+ , m_borderShaderColorLocation(-1)
+ , m_initialized(false)
+{
+ // Vertex positions and texture coordinates for the 4 corners of a 1x1 quad.
+ GLfloat vertices[] = { -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
+ -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
+ 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
+ 0.5f, 0.5f, 0.0f, 1.0f, 1.0f };
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3, // The two triangles that make up the layer quad.
+ 0, 1, 2, 3}; // A line path for drawing the layer border.
+
+ GLuint vboIds[2];
+ GLC(glGenBuffers(2, vboIds));
+ m_quadVerticesVbo = vboIds[0];
+ m_quadElementsVbo = vboIds[1];
+ GLC(glBindBuffer(GL_ARRAY_BUFFER, m_quadVerticesVbo));
+ GLC(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW));
+ GLC(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_quadElementsVbo));
+ GLC(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW));
+
+ // Get the max texture size supported by the system.
+ GLC(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize));
+
+ // Shaders for drawing the debug borders around the layers.
+ char borderVertexShaderString[] =
+ "attribute vec4 a_position; \n"
+ "uniform mat4 matrix; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = matrix * a_position; \n"
+ "} \n";
+ char borderFragmentShaderString[] =
+ "precision mediump float; \n"
+ "uniform vec4 color; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = color; \n"
+ "} \n";
+
+ m_borderShaderProgram = createShaderProgram(borderVertexShaderString, borderFragmentShaderString);
+ if (!m_borderShaderProgram) {
+ LOG_ERROR("ContentLayerChromium: Failed to create shader program");
+ return;
+ }
+
+ m_borderShaderMatrixLocation = glGetUniformLocation(m_borderShaderProgram, "matrix");
+ m_borderShaderColorLocation = glGetUniformLocation(m_borderShaderProgram, "color");
+ ASSERT(m_borderShaderMatrixLocation != -1);
+ ASSERT(m_borderShaderColorLocation != -1);
+
+ m_initialized = true;
+}
+
+LayerChromium::SharedValues::~SharedValues()
+{
+ GLuint vboIds[2] = { m_quadVerticesVbo, m_quadElementsVbo };
+ GLC(glDeleteBuffers(2, vboIds));
+
+ if (m_borderShaderProgram)
+ GLC(glDeleteProgram(m_borderShaderProgram));
+}
+
PassRefPtr<LayerChromium> LayerChromium::create(GraphicsLayerChromium* owner)
{
@@ -62,13 +148,10 @@ LayerChromium::LayerChromium(GraphicsLayerChromium* owner)
, m_anchorPoint(0.5, 0.5)
, m_backgroundColor(0, 0, 0, 0)
, m_borderColor(0, 0, 0, 0)
- , m_layerRenderer(0)
- , m_edgeAntialiasingMask(0)
, m_opacity(1.0)
, m_zPosition(0.0)
, m_anchorPointZ(0)
, m_borderWidth(0)
- , m_allocatedTextureId(0)
, m_clearsContext(false)
, m_doubleSided(true)
, m_hidden(false)
@@ -76,6 +159,7 @@ LayerChromium::LayerChromium(GraphicsLayerChromium* owner)
, m_opaque(true)
, m_geometryFlipped(false)
, m_needsDisplayOnBoundsChange(false)
+ , m_layerRenderer(0)
{
}
@@ -87,10 +171,6 @@ LayerChromium::~LayerChromium()
// Remove the superlayer reference from all sublayers.
removeAllSublayers();
-
- // Notify the renderer to clean up the texture associated with the layer.
- if (m_layerRenderer)
- m_layerRenderer->freeLayerTexture(this);
}
void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer)
@@ -101,140 +181,46 @@ void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer)
m_layerRenderer = renderer;
}
-void LayerChromium::updateTextureContents(unsigned textureId)
+unsigned LayerChromium::createShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource)
{
- RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
- if (!backing || backing->paintingGoesToWindow())
- return;
-
- ASSERT(drawsContent());
-
- void* pixels = 0;
- IntRect dirtyRect(m_dirtyRect);
- IntSize requiredTextureSize;
- IntSize bitmapSize;
-
-#if PLATFORM(SKIA)
- const SkBitmap* skiaBitmap = 0;
- OwnPtr<skia::PlatformCanvas> canvas;
- OwnPtr<PlatformContextSkia> skiaContext;
- OwnPtr<GraphicsContext> graphicsContext;
-
- requiredTextureSize = m_bounds;
- IntRect boundsRect(IntPoint(0, 0), m_bounds);
-
- // If the texture needs to be reallocated then we must redraw the entire
- // contents of the layer.
- if (requiredTextureSize != m_allocatedTextureSize)
- dirtyRect = boundsRect;
- else {
- // Clip the dirtyRect to the size of the layer to avoid drawing outside
- // the bounds of the backing texture.
- dirtyRect.intersect(boundsRect);
+ GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexShaderSource);
+ if (!vertexShader) {
+ LOG_ERROR("Failed to create vertex shader");
+ return 0;
}
- canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false));
- skiaContext.set(new PlatformContextSkia(canvas.get()));
-
-#if OS(WINDOWS)
- // This is needed to get text to show up correctly. Without it,
- // GDI renders with zero alpha and the text becomes invisible.
- // Unfortunately, setting this to true disables cleartype.
- // FIXME: Does this take us down a very slow text rendering path?
- // FIXME: why is this is a windows-only call ?
- skiaContext->setDrawingToImageBuffer(true);
-#endif
-
- graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get())));
-
- // Bring the canvas into the coordinate system of the paint rect.
- canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y()));
-
- m_owner->paintGraphicsLayerContents(*graphicsContext, dirtyRect);
- const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
- skiaBitmap = &bitmap;
- ASSERT(skiaBitmap);
-
- SkAutoLockPixels lock(*skiaBitmap);
- SkBitmap::Config skiaConfig = skiaBitmap->config();
- // FIXME: do we need to support more image configurations?
- if (skiaConfig == SkBitmap::kARGB_8888_Config) {
- pixels = skiaBitmap->getPixels();
- bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
- }
-#elif PLATFORM(CG)
- requiredTextureSize = m_bounds;
- IntRect boundsRect(IntPoint(0, 0), m_bounds);
-
- // If the texture needs to be reallocated then we must redraw the entire
- // contents of the layer.
- if (requiredTextureSize != m_allocatedTextureSize)
- dirtyRect = boundsRect;
- else {
- // Clip the dirtyRect to the size of the layer to avoid drawing outside
- // the bounds of the backing texture.
- dirtyRect.intersect(boundsRect);
+ GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
+ if (!fragmentShader) {
+ GLC(glDeleteShader(vertexShader));
+ LOG_ERROR("Failed to create fragment shader");
+ return 0;
}
- Vector<uint8_t> tempVector;
- int rowBytes = 4 * dirtyRect.width();
- tempVector.resize(rowBytes * dirtyRect.height());
- memset(tempVector.data(), 0, tempVector.size());
- RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
- RetainPtr<CGContextRef> contextCG(AdoptCF, CGBitmapContextCreate(tempVector.data(),
- dirtyRect.width(), dirtyRect.height(), 8, rowBytes,
- colorSpace.get(),
- kCGImageAlphaPremultipliedLast));
-
- GraphicsContext graphicsContext(contextCG.get());
-
- // Translate the graphics contxt into the coordinate system of the dirty rect.
- graphicsContext.translate(-dirtyRect.x(), -dirtyRect.y());
-
- m_owner->paintGraphicsLayerContents(graphicsContext, dirtyRect);
-
- pixels = tempVector.data();
- bitmapSize = dirtyRect.size();
-#else
-#error "Need to implement for your platform."
-#endif
+ GLuint programObject = glCreateProgram();
+ if (!programObject) {
+ LOG_ERROR("Failed to create shader program");
+ return 0;
+ }
- if (pixels)
- updateTextureRect(pixels, bitmapSize, requiredTextureSize, dirtyRect, textureId);
-}
+ GLC(glAttachShader(programObject, vertexShader));
+ GLC(glAttachShader(programObject, fragmentShader));
-void LayerChromium::updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize, const IntRect& updateRect, unsigned textureId)
-{
- if (!pixels)
- return;
+ // Bind the common attrib locations.
+ GLC(glBindAttribLocation(programObject, s_positionAttribLocation, "a_position"));
+ GLC(glBindAttribLocation(programObject, s_texCoordAttribLocation, "a_texCoord"));
- glBindTexture(GL_TEXTURE_2D, textureId);
- // If the texture id or size changed since last time then we need to tell GL
- // to re-allocate a texture.
- if (m_allocatedTextureId != textureId || requiredTextureSize != m_allocatedTextureSize) {
- ASSERT(bitmapSize == requiredTextureSize);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-
- m_allocatedTextureId = textureId;
- m_allocatedTextureSize = requiredTextureSize;
- } else {
- ASSERT(updateRect.width() <= m_allocatedTextureSize.width() && updateRect.height() <= m_allocatedTextureSize.height());
- ASSERT(updateRect.width() == bitmapSize.width() && updateRect.height() == bitmapSize.height());
-#if PLATFORM(CG)
- // The origin is at the lower left in Core Graphics' coordinate system. We need to correct for this here.
- glTexSubImage2D(GL_TEXTURE_2D, 0,
- updateRect.x(), m_allocatedTextureSize.height() - updateRect.height() - updateRect.y(),
- updateRect.width(), updateRect.height(),
- GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-#elif PLATFORM(SKIA)
- glTexSubImage2D(GL_TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-#else
-#error "Need to implement for your platform."
-#endif
+ GLC(glLinkProgram(programObject));
+ GLint linked;
+ GLC(glGetProgramiv(programObject, GL_LINK_STATUS, &linked));
+ if (!linked) {
+ LOG_ERROR("Failed to link shader program");
+ GLC(glDeleteProgram(programObject));
+ return 0;
}
- m_dirtyRect.setSize(FloatSize());
- m_contentsDirty = false;
+ GLC(glDeleteShader(vertexShader));
+ GLC(glDeleteShader(fragmentShader));
+ return programObject;
}
void LayerChromium::setNeedsCommit()
@@ -377,5 +363,86 @@ void LayerChromium::setNeedsDisplay()
m_contentsDirty = true;
}
+void LayerChromium::toGLMatrix(float* flattened, const TransformationMatrix& m)
+{
+ flattened[0] = m.m11();
+ flattened[1] = m.m12();
+ flattened[2] = m.m13();
+ flattened[3] = m.m14();
+ flattened[4] = m.m21();
+ flattened[5] = m.m22();
+ flattened[6] = m.m23();
+ flattened[7] = m.m24();
+ flattened[8] = m.m31();
+ flattened[9] = m.m32();
+ flattened[10] = m.m33();
+ flattened[11] = m.m34();
+ flattened[12] = m.m41();
+ flattened[13] = m.m42();
+ flattened[14] = m.m43();
+ flattened[15] = m.m44();
+}
+
+void LayerChromium::drawTexturedQuad(const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix,
+ float width, float height, float opacity,
+ int matrixLocation, int alphaLocation)
+{
+ static GLfloat glMatrix[16];
+
+ TransformationMatrix renderMatrix = drawMatrix;
+
+ // Apply a scaling factor to size the quad from 1x1 to its intended size.
+ renderMatrix.scale3d(width, height, 1);
+
+ // Apply the projection matrix before sending the transform over to the shader.
+ renderMatrix.multiply(projectionMatrix);
+
+ toGLMatrix(&glMatrix[0], renderMatrix);
+
+ GLC(glUniformMatrix4fv(matrixLocation, 1, false, &glMatrix[0]));
+
+ if (alphaLocation != -1)
+ GLC(glUniform1f(alphaLocation, opacity));
+
+ GLC(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0));
+}
+
+void LayerChromium::drawDebugBorder()
+{
+ static GLfloat glMatrix[16];
+ if (!borderColor().alpha())
+ return;
+
+ ASSERT(layerRenderer());
+ const SharedValues* sv = layerRenderer()->layerSharedValues();
+ ASSERT(sv && sv->initialized());
+ layerRenderer()->useShader(sv->borderShaderProgram());
+ TransformationMatrix renderMatrix = drawTransform();
+ renderMatrix.scale3d(bounds().width(), bounds().height(), 1);
+ renderMatrix.multiply(layerRenderer()->projectionMatrix());
+ toGLMatrix(&glMatrix[0], renderMatrix);
+ GLC(glUniformMatrix4fv(sv->borderShaderMatrixLocation(), 1, false, &glMatrix[0]));
+
+ GLC(glUniform4f(sv->borderShaderColorLocation(), borderColor().red() / 255.0, borderColor().green() / 255.0, borderColor().blue() / 255.0, 1));
+
+ GLC(glLineWidth(borderWidth()));
+
+ // The indices for the line are stored in the same array as the triangle indices.
+ GLC(glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, (void*)(6 * sizeof(unsigned short))));
+}
+
+// static
+void LayerChromium::prepareForDraw(const SharedValues* sv)
+{
+ GLC(glBindBuffer(GL_ARRAY_BUFFER, sv->quadVerticesVbo()));
+ GLC(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sv->quadElementsVbo()));
+ GLuint offset = 0;
+ GLC(glVertexAttribPointer(s_positionAttribLocation, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)offset));
+ offset += 3 * sizeof(GLfloat);
+ GLC(glVertexAttribPointer(s_texCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)offset));
+ GLC(glEnableVertexAttribArray(s_positionAttribLocation));
+ GLC(glEnableVertexAttribArray(s_texCoordAttribLocation));
+}
+
}
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h
index 9fba415..0d0d362 100644
--- a/WebCore/platform/graphics/chromium/LayerChromium.h
+++ b/WebCore/platform/graphics/chromium/LayerChromium.h
@@ -55,19 +55,24 @@ namespace WebCore {
class GraphicsContext3D;
class LayerRendererChromium;
-// Base class for composited layers. The implementation covers layers that require
-// a GraphicsContext to render their contents. Special layer types are derived from
+// Base class for composited layers. Special layer types are derived from
// this class.
class LayerChromium : public RefCounted<LayerChromium> {
+ friend class LayerRendererChromium;
public:
static PassRefPtr<LayerChromium> create(GraphicsLayerChromium* owner = 0);
~LayerChromium();
+ const LayerChromium* rootLayer() const;
+ LayerChromium* superlayer() const;
void addSublayer(PassRefPtr<LayerChromium>);
void insertSublayer(PassRefPtr<LayerChromium>, size_t index);
void replaceSublayer(LayerChromium* reference, PassRefPtr<LayerChromium> newLayer);
void removeFromSuperlayer();
+ void removeAllSublayers();
+ void setSublayers(const Vector<RefPtr<LayerChromium> >&);
+ const Vector<RefPtr<LayerChromium> >& getSublayers() const { return m_sublayers; }
void setAnchorPoint(const FloatPoint& anchorPoint) { m_anchorPoint = anchorPoint; setNeedsCommit(); }
FloatPoint anchorPoint() const { return m_anchorPoint; }
@@ -93,9 +98,6 @@ public:
void setDoubleSided(bool doubleSided) { m_doubleSided = doubleSided; setNeedsCommit(); }
bool doubleSided() const { return m_doubleSided; }
- void setEdgeAntialiasingMask(uint32_t mask) { m_edgeAntialiasingMask = mask; setNeedsCommit(); }
- uint32_t edgeAntialiasingMask() const { return m_edgeAntialiasingMask; }
-
void setFrame(const FloatRect&);
FloatRect frame() const { return m_frame; }
@@ -120,76 +122,99 @@ public:
bool opaque() const { return m_opaque; }
void setPosition(const FloatPoint& position) { m_position = position; setNeedsCommit(); }
-
FloatPoint position() const { return m_position; }
void setZPosition(float zPosition) { m_zPosition = zPosition; setNeedsCommit(); }
float zPosition() const { return m_zPosition; }
- const LayerChromium* rootLayer() const;
-
- void removeAllSublayers();
-
- void setSublayers(const Vector<RefPtr<LayerChromium> >&);
-
- const Vector<RefPtr<LayerChromium> >& getSublayers() const { return m_sublayers; }
-
void setSublayerTransform(const TransformationMatrix& transform) { m_sublayerTransform = transform; setNeedsCommit(); }
const TransformationMatrix& sublayerTransform() const { return m_sublayerTransform; }
- LayerChromium* superlayer() const;
-
-
void setTransform(const TransformationMatrix& transform) { m_transform = transform; setNeedsCommit(); }
const TransformationMatrix& transform() const { return m_transform; }
+ // FIXME: This setting is currently ignored.
void setGeometryFlipped(bool flipped) { m_geometryFlipped = flipped; setNeedsCommit(); }
bool geometryFlipped() const { return m_geometryFlipped; }
- virtual void updateTextureContents(unsigned textureId);
- bool contentsDirty() { return m_contentsDirty; }
-
void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = transform; }
const TransformationMatrix& drawTransform() const { return m_drawTransform; }
void setDrawOpacity(float opacity) { m_drawOpacity = opacity; }
float drawOpacity() const { return m_drawOpacity; }
- virtual bool drawsContent() { return m_owner && m_owner->drawsContent(); }
-
- // Return true if the layer has its own GL texture and false if the texture
- // needs to be allocated by the compositor.
- virtual bool ownsTexture() { return false; }
-
- // Returns the id of the GL texture that stores the contents of this layer.
- // Derived layer classes that own their own textures should overwrite this method.
- virtual unsigned textureId() { return m_allocatedTextureId; }
-
bool preserves3D() { return m_owner && m_owner->preserves3D(); }
void setLayerRenderer(LayerRendererChromium*);
- static void setShaderProgramId(unsigned shaderProgramId) { m_shaderProgramId = shaderProgramId; }
- virtual unsigned shaderProgramId() { return m_shaderProgramId; }
-
void setOwner(GraphicsLayerChromium* owner) { m_owner = owner; }
+ bool contentsDirty() { return m_contentsDirty; }
+
+ // These methods typically need to be overwritten by derived classes.
+ virtual bool drawsContent() { return false; }
+ virtual void updateContents() { };
+ virtual void draw() { };
+
+ void drawDebugBorder();
+
+ // Stores values that are shared between instances of this class that are
+ // associated with the same LayerRendererChromium (and hence the same GL
+ // context).
+ class SharedValues {
+ public:
+ SharedValues();
+ ~SharedValues();
+
+ unsigned quadVerticesVbo() const { return m_quadVerticesVbo; }
+ unsigned quadElementsVbo() const { return m_quadElementsVbo; }
+ int maxTextureSize() const { return m_maxTextureSize; }
+ unsigned borderShaderProgram() const { return m_borderShaderProgram; }
+ int borderShaderMatrixLocation() const { return m_borderShaderMatrixLocation; }
+ int borderShaderColorLocation() const { return m_borderShaderColorLocation; }
+ bool initialized() const { return m_initialized; }
+
+ private:
+ unsigned m_quadVerticesVbo;
+ unsigned m_quadElementsVbo;
+ int m_maxTextureSize;
+ unsigned m_borderShaderProgram;
+ int m_borderShaderMatrixLocation;
+ int m_borderShaderColorLocation;
+ bool m_initialized;
+ };
+
+ static void prepareForDraw(const SharedValues*);
+
protected:
GraphicsLayerChromium* m_owner;
LayerChromium(GraphicsLayerChromium* owner);
- void updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize, const IntRect& dirtyRect, unsigned textureId);
+
+ LayerRendererChromium* layerRenderer() const { return m_layerRenderer; }
+
+ static void drawTexturedQuad(const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix,
+ float width, float height, float opacity,
+ int matrixLocation, int alphaLocation);
+
+ static void toGLMatrix(float*, const TransformationMatrix&);
+
+ static unsigned createShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource);
IntSize m_bounds;
FloatRect m_dirtyRect;
bool m_contentsDirty;
+ // All layer shaders share the same attribute locations for the vertex positions
+ // and texture coordinates. This allows switching shaders without rebinding attribute
+ // arrays.
+ static const unsigned s_positionAttribLocation;
+ static const unsigned s_texCoordAttribLocation;
+
private:
void setNeedsCommit();
void setSuperlayer(LayerChromium* superlayer) { m_superlayer = superlayer; }
- void paintMe();
-
size_t numSublayers() const
{
return m_sublayers.size();
@@ -204,35 +229,17 @@ private:
Vector<RefPtr<LayerChromium> > m_sublayers;
LayerChromium* m_superlayer;
+ // Layer properties.
IntSize m_backingStoreSize;
FloatPoint m_position;
FloatPoint m_anchorPoint;
Color m_backgroundColor;
Color m_borderColor;
-
- LayerRendererChromium* m_layerRenderer;
-
- FloatRect m_frame;
- TransformationMatrix m_transform;
- TransformationMatrix m_sublayerTransform;
-
- TransformationMatrix m_drawTransform;
-
- uint32_t m_edgeAntialiasingMask;
float m_opacity;
float m_zPosition;
float m_anchorPointZ;
float m_borderWidth;
-
float m_drawOpacity;
-
- unsigned m_allocatedTextureId;
- IntSize m_allocatedTextureSize;
-
- // The shader program used by all layers of this type is the same.
- // This static can be shadowed by derived classes to use a special shader.
- static unsigned m_shaderProgramId;
-
bool m_clearsContext;
bool m_doubleSided;
bool m_hidden;
@@ -241,6 +248,14 @@ private:
bool m_geometryFlipped;
bool m_needsDisplayOnBoundsChange;
+ // Points to the layer renderer that updates and draws this layer.
+ LayerRendererChromium* m_layerRenderer;
+
+ FloatRect m_frame;
+ TransformationMatrix m_transform;
+ TransformationMatrix m_sublayerTransform;
+ TransformationMatrix m_drawTransform;
+
String m_name;
};
diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
index 2f70efa..cf23871 100644
--- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
+++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -35,10 +35,10 @@
#include "LayerRendererChromium.h"
#include "CanvasLayerChromium.h"
+#include "ContentLayerChromium.h"
#include "GLES2Context.h"
#include "LayerChromium.h"
#include "NotImplemented.h"
-#include "TransformLayerChromium.h"
#if PLATFORM(SKIA)
#include "NativeImageSkia.h"
#include "PlatformContextSkia.h"
@@ -50,101 +50,6 @@
namespace WebCore {
-#ifndef NDEBUG
-static WTFLogChannel LogLayerRenderer = { 0x00000000, "LayerRenderer", WTFLogChannelOn };
-#endif
-
-static void checkGLError()
-{
-#ifndef NDEBUG
- GLenum error = glGetError();
- if (error)
- LOG_ERROR("GL Error: %d " , error);
-#endif
-}
-
-static GLuint loadShader(GLenum type, const char* shaderSource)
-{
- GLuint shader = glCreateShader(type);
- if (!shader)
- return 0;
- glShaderSource(shader, 1, &shaderSource, 0);
- glCompileShader(shader);
- GLint compiled;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
- if (!compiled) {
- glDeleteShader(shader);
- return 0;
- }
- return shader;
-}
-
-static GLuint loadShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource)
-{
- GLuint vertexShader;
- GLuint fragmentShader;
- GLuint programObject;
- GLint linked;
- vertexShader = loadShader(GL_VERTEX_SHADER, vertexShaderSource);
- if (!vertexShader)
- return 0;
- fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
- if (!fragmentShader) {
- glDeleteShader(vertexShader);
- return 0;
- }
- programObject = glCreateProgram();
- if (!programObject)
- return 0;
- glAttachShader(programObject, vertexShader);
- glAttachShader(programObject, fragmentShader);
- glLinkProgram(programObject);
- glGetProgramiv(programObject, GL_LINK_STATUS, &linked);
- if (!linked) {
- glDeleteProgram(programObject);
- return 0;
- }
- glDeleteShader(vertexShader);
- glDeleteShader(fragmentShader);
- return programObject;
-}
-
-bool LayerRendererChromium::createLayerShader(ShaderProgramType type, const char* vertexShaderSource, const char* fragmentShaderSource)
-{
- unsigned programId = loadShaderProgram(vertexShaderSource, fragmentShaderSource);
- ASSERT(programId);
-
- ShaderProgram* program = &m_shaderPrograms[type];
-
- program->m_shaderProgramId = programId;
- program->m_samplerLocation = glGetUniformLocation(programId, "s_texture");
- program->m_matrixLocation = glGetUniformLocation(programId, "matrix");
- program->m_alphaLocation = glGetUniformLocation(programId, "alpha");
-
- return programId;
-}
-
-
-static void toGLMatrix(float* flattened, const TransformationMatrix& m)
-{
- flattened[0] = m.m11();
- flattened[1] = m.m12();
- flattened[2] = m.m13();
- flattened[3] = m.m14();
- flattened[4] = m.m21();
- flattened[5] = m.m22();
- flattened[6] = m.m23();
- flattened[7] = m.m24();
- flattened[8] = m.m31();
- flattened[9] = m.m32();
- flattened[10] = m.m33();
- flattened[11] = m.m34();
- flattened[12] = m.m41();
- flattened[13] = m.m42();
- flattened[14] = m.m43();
- flattened[15] = m.m44();
-}
-
static TransformationMatrix orthoMatrix(float left, float right, float bottom, float top, float nearZ, float farZ)
{
float deltaX = right - left;
@@ -162,21 +67,6 @@ static TransformationMatrix orthoMatrix(float left, float right, float bottom, f
return ortho;
}
-// Creates a GL texture object to be used for transfering the layer's bitmap into.
-static GLuint createLayerTexture()
-{
- GLuint textureId = 0;
- glGenTextures(1, &textureId);
- glBindTexture(GL_TEXTURE_2D, textureId);
- // Do basic linear filtering on resize.
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- // NPOT textures in GL ES only work when the wrap mode is set to GL_CLAMP_TO_EDGE.
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- return textureId;
-}
-
static inline bool compareLayerZ(const LayerChromium* a, const LayerChromium* b)
{
const TransformationMatrix& transformA = a->drawTransform();
@@ -185,51 +75,35 @@ static inline bool compareLayerZ(const LayerChromium* a, const LayerChromium* b)
return transformA.m43() < transformB.m43();
}
-ShaderProgram::ShaderProgram()
- : m_shaderProgramId(0)
- , m_samplerLocation(-1)
- , m_matrixLocation(-1)
- , m_alphaLocation(-1)
-{
-}
-
PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(PassOwnPtr<GLES2Context> gles2Context)
{
return new LayerRendererChromium(gles2Context);
}
LayerRendererChromium::LayerRendererChromium(PassOwnPtr<GLES2Context> gles2Context)
- : m_rootLayerTextureWidth(0)
+ : m_rootLayerTextureId(0)
+ , m_rootLayerTextureWidth(0)
, m_rootLayerTextureHeight(0)
- , m_positionLocation(0)
- , m_texCoordLocation(1)
+ , m_scrollShaderProgram(0)
, m_rootLayer(0)
, m_needsDisplay(false)
, m_scrollPosition(IntPoint(-1, -1))
- , m_currentShaderProgramType(NumShaderProgramTypes)
+ , m_currentShader(0)
, m_gles2Context(gles2Context)
{
- m_quadVboIds[Vertices] = m_quadVboIds[LayerElements] = 0;
- m_hardwareCompositing = (m_gles2Context && initializeSharedGLObjects());
+ m_hardwareCompositing = (m_gles2Context && initializeSharedObjects());
}
LayerRendererChromium::~LayerRendererChromium()
{
- if (m_hardwareCompositing) {
- makeContextCurrent();
- glDeleteBuffers(3, m_quadVboIds);
-
- for (int i = 0; i < NumShaderProgramTypes; i++) {
- if (m_shaderPrograms[i].m_shaderProgramId)
- glDeleteProgram(m_shaderPrograms[i].m_shaderProgramId);
- }
- }
+ cleanupSharedObjects();
+}
- // Free up all GL textures.
- for (TextureIdMap::iterator iter = m_textureIdMap.begin(); iter != m_textureIdMap.end(); ++iter) {
- glDeleteTextures(1, &(iter->second));
- iter->first->setLayerRenderer(0);
- }
+void LayerRendererChromium::debugGLCall(const char* command, const char* file, int line)
+{
+ GLenum error = glGetError();
+ if (error != GL_NO_ERROR)
+ LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error %x\n", file, line, command, error);
}
// Creates a canvas and an associated graphics context that the root layer will
@@ -268,43 +142,14 @@ void LayerRendererChromium::setRootLayerCanvasSize(const IntSize& size)
m_rootLayerCanvasSize = size;
}
-void LayerRendererChromium::useShaderProgram(ShaderProgramType programType)
+void LayerRendererChromium::useShader(unsigned programId)
{
- if (programType != m_currentShaderProgramType) {
- ShaderProgram* program = &m_shaderPrograms[programType];
- glUseProgram(program->m_shaderProgramId);
- m_currentShaderProgramType = programType;
-
- // Set the uniform locations matching the program.
- m_samplerLocation = program->m_samplerLocation;
- m_matrixLocation = program->m_matrixLocation;
- m_alphaLocation = program->m_alphaLocation;
+ if (programId != m_currentShader) {
+ GLC(glUseProgram(programId));
+ m_currentShader = programId;
}
}
-void LayerRendererChromium::drawTexturedQuad(const TransformationMatrix& matrix, float width, float height, float opacity)
-{
- static GLfloat glMatrix[16];
-
- TransformationMatrix renderMatrix = matrix;
-
- // Apply a scaling factor to size the quad from 1x1 to its intended size.
- renderMatrix.scale3d(width, height, 1);
-
- // Apply the projection matrix before sending the transform over to the shader.
- renderMatrix.multiply(m_projectionMatrix);
-
- toGLMatrix(&glMatrix[0], renderMatrix);
-
- glUniformMatrix4fv(m_matrixLocation, 1, false, &glMatrix[0]);
-
- if (m_alphaLocation != -1)
- glUniform1f(m_alphaLocation, opacity);
-
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
-}
-
-
// Updates the contents of the root layer texture that fall inside the updateRect
// and re-composits all sublayers.
void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& visibleRect,
@@ -315,17 +160,13 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect&
if (!m_rootLayer)
return;
- // If the size of the visible area has changed then allocate a new texture
- // to store the contents of the root layer and adjust the projection matrix
- // and viewport.
makeContextCurrent();
- checkGLError();
-
- glBindTexture(GL_TEXTURE_2D, m_rootLayerTextureId);
-
- checkGLError();
+ GLC(glBindTexture(GL_TEXTURE_2D, m_rootLayerTextureId));
+ // If the size of the visible area has changed then allocate a new texture
+ // to store the contents of the root layer and adjust the projection matrix
+ // and viewport.
int visibleRectWidth = visibleRect.width();
int visibleRectHeight = visibleRect.height();
if (visibleRectWidth != m_rootLayerTextureWidth || visibleRectHeight != m_rootLayerTextureHeight) {
@@ -333,38 +174,18 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect&
m_rootLayerTextureHeight = visibleRect.height();
m_projectionMatrix = orthoMatrix(0, visibleRectWidth, visibleRectHeight, 0, -1000, 1000);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_rootLayerTextureWidth, m_rootLayerTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-
- checkGLError();
+ GLC(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_rootLayerTextureWidth, m_rootLayerTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
}
// The GL viewport covers the entire visible area, including the scrollbars.
- glViewport(0, 0, visibleRectWidth, visibleRectHeight);
-
- checkGLError();
-
- // The layer, scroll and debug border shaders all use the same vertex attributes
- // so we can bind them only once.
- glBindBuffer(GL_ARRAY_BUFFER, m_quadVboIds[Vertices]);
- checkGLError();
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_quadVboIds[LayerElements]);
- checkGLError();
- GLuint offset = 0;
- glVertexAttribPointer(m_positionLocation, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(offset));
- checkGLError();
- offset += 3 * sizeof(GLfloat);
- glVertexAttribPointer(m_texCoordLocation, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(offset));
- checkGLError();
- glEnableVertexAttribArray(m_positionLocation);
- checkGLError();
- glEnableVertexAttribArray(m_texCoordLocation);
- checkGLError();
- glActiveTexture(GL_TEXTURE0);
- checkGLError();
- glDisable(GL_DEPTH_TEST);
- checkGLError();
- glDisable(GL_CULL_FACE);
- checkGLError();
+ GLC(glViewport(0, 0, visibleRectWidth, visibleRectHeight));
+
+ // Bind the common vertex attributes used for drawing all the layers.
+ LayerChromium::prepareForDraw(layerSharedValues());
+
+ GLC(glDisable(GL_DEPTH_TEST));
+ GLC(glDisable(GL_CULL_FACE));
+ GLC(glDepthFunc(GL_LEQUAL));
if (m_scrollPosition == IntPoint(-1, -1))
m_scrollPosition = scrollPosition;
@@ -390,21 +211,21 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect&
#error "Need to implement for your platform."
#endif
- scrolledLayerMatrix.translate3d((int)floorf(0.5 * visibleRect.width()) - scrollDelta.x(),
- (int)floorf(0.5 * visibleRect.height()) + scaleFactor * scrollDelta.y(), 0);
+ scrolledLayerMatrix.translate3d(0.5 * visibleRect.width() - scrollDelta.x(),
+ 0.5 * visibleRect.height() + scaleFactor * scrollDelta.y(), 0);
scrolledLayerMatrix.scale3d(1, -1, 1);
- // Switch shaders to avoid RGB swizzling.
- useShaderProgram(ScrollLayerProgram);
- glUniform1i(m_shaderPrograms[ScrollLayerProgram].m_samplerLocation, 0);
- checkGLError();
-
- drawTexturedQuad(scrolledLayerMatrix, visibleRect.width(), visibleRect.height(), 1);
- checkGLError();
+ useShader(m_scrollShaderProgram);
+ GLC(glUniform1i(m_scrollShaderSamplerLocation, 0));
+ LayerChromium::drawTexturedQuad(m_projectionMatrix, scrolledLayerMatrix,
+ visibleRect.width(), visibleRect.height(), 1,
+ m_scrollShaderMatrixLocation, -1);
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, contentRect.width(), contentRect.height());
-
- checkGLError();
+ GLC(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, contentRect.width(), contentRect.height()));
+ m_scrollPosition = scrollPosition;
+ } else if (abs(scrollDelta.y()) > contentRect.height() || abs(scrollDelta.x()) > contentRect.width()) {
+ // Scrolling larger than the contentRect size does not preserve any of the pixels, so there is
+ // no need to copy framebuffer pixels back into the texture.
m_scrollPosition = scrollPosition;
}
@@ -423,154 +244,92 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect&
ASSERT(rootLayerWidth == updateRect.width() && rootLayerHeight == updateRect.height());
void* pixels = bitmap.getPixels();
- checkGLError();
// Copy the contents of the updated rect to the root layer texture.
- glTexSubImage2D(GL_TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels);
- checkGLError();
+ GLC(glTexSubImage2D(GL_TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels));
#elif PLATFORM(CG)
// Get the contents of the updated rect.
ASSERT(static_cast<int>(CGBitmapContextGetWidth(m_rootLayerCGContext.get())) == updateRect.width() && static_cast<int>(CGBitmapContextGetHeight(m_rootLayerCGContext.get())) == updateRect.height());
void* pixels = m_rootLayerBackingStore.data();
- checkGLError();
// Copy the contents of the updated rect to the root layer texture.
// The origin is at the lower left in Core Graphics' coordinate system. We need to correct for this here.
- glTexSubImage2D(GL_TEXTURE_2D, 0,
- updateRect.x(), m_rootLayerTextureHeight - updateRect.y() - updateRect.height(),
- updateRect.width(), updateRect.height(),
- GL_RGBA, GL_UNSIGNED_BYTE, pixels);
- checkGLError();
+ GLC(glTexSubImage2D(GL_TEXTURE_2D, 0,
+ updateRect.x(), m_rootLayerTextureHeight - updateRect.y() - updateRect.height(),
+ updateRect.width(), updateRect.height(),
+ GL_RGBA, GL_UNSIGNED_BYTE, pixels));
#else
#error "Need to implement for your platform."
#endif
}
glClearColor(0, 0, 1, 1);
- checkGLError();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- checkGLError();
// Render the root layer using a quad that takes up the entire visible area of the window.
- useShaderProgram(ContentLayerProgram);
- checkGLError();
- glUniform1i(m_samplerLocation, 0);
- checkGLError();
+ // We reuse the shader program used by ContentLayerChromium.
+ const ContentLayerChromium::SharedValues* contentLayerValues = contentLayerSharedValues();
+ useShader(contentLayerValues->contentShaderProgram());
+ GLC(glUniform1i(contentLayerValues->shaderSamplerLocation(), 0));
TransformationMatrix layerMatrix;
layerMatrix.translate3d(visibleRect.width() * 0.5f, visibleRect.height() * 0.5f, 0);
- drawTexturedQuad(layerMatrix, visibleRect.width(), visibleRect.height(), 1);
- checkGLError();
+ LayerChromium::drawTexturedQuad(m_projectionMatrix, layerMatrix,
+ visibleRect.width(), visibleRect.height(), 1,
+ contentLayerValues->shaderMatrixLocation(), contentLayerValues->shaderAlphaLocation());
// If culling is enabled then we will cull the backface.
- glCullFace(GL_BACK);
- checkGLError();
+ GLC(glCullFace(GL_BACK));
// The orthographic projection is setup such that Y starts at zero and
// increases going down the page so we need to adjust the winding order of
// front facing triangles.
- glFrontFace(GL_CW);
- checkGLError();
+ GLC(glFrontFace(GL_CW));
// The shader used to render layers returns pre-multiplied alpha colors
// so we need to send the blending mode appropriately.
- glEnable(GL_BLEND);
- checkGLError();
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-
- checkGLError();
+ GLC(glEnable(GL_BLEND));
+ GLC(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
// Translate all the composited layers by the scroll position.
TransformationMatrix matrix;
matrix.translate3d(-m_scrollPosition.x(), -m_scrollPosition.y(), 0);
+ // Traverse the layer tree and update the layer transforms.
float opacity = 1;
- m_layerList.shrink(0);
const Vector<RefPtr<LayerChromium> >& sublayers = m_rootLayer->getSublayers();
- for (size_t i = 0; i < sublayers.size(); i++)
- updateLayersRecursive(sublayers[i].get(), matrix, opacity, visibleRect);
-
- // Sort layers by the z coordinate of their center so that layers further
- // away get drawn first.
- std::stable_sort(m_layerList.begin(), m_layerList.end(), compareLayerZ);
+ size_t i;
+ for (i = 0; i < sublayers.size(); i++)
+ updateLayersRecursive(sublayers[i].get(), matrix, opacity);
// Enable scissoring to avoid rendering composited layers over the scrollbars.
- glEnable(GL_SCISSOR_TEST);
- glScissor(0, visibleRect.height() - contentRect.height(), contentRect.width(), contentRect.height());
+ GLC(glEnable(GL_SCISSOR_TEST));
+ GLC(glScissor(0, visibleRect.height() - contentRect.height(), contentRect.width(), contentRect.height()));
- for (size_t j = 0; j < m_layerList.size(); j++)
- drawLayer(m_layerList[j]);
+ // Traverse the layer tree one more time to draw the layers.
+ m_visibleRect = visibleRect;
+ for (i = 0; i < sublayers.size(); i++)
+ drawLayersRecursive(sublayers[i].get());
- glDisable(GL_SCISSOR_TEST);
+ GLC(glDisable(GL_SCISSOR_TEST));
- glFlush();
m_gles2Context->swapBuffers();
m_needsDisplay = false;
}
-// Returns the id of the texture currently associated with the layer or
-// -1 if the id hasn't been registered yet.
-int LayerRendererChromium::getTextureId(LayerChromium* layer)
+// FIXME: This method should eventually be replaced by a proper texture manager.
+unsigned LayerRendererChromium::createLayerTexture()
{
- TextureIdMap::iterator textureId = m_textureIdMap.find(layer);
- if (textureId != m_textureIdMap.end())
- return textureId->second;
-
- return -1;
-}
-
-// Allocates a new texture for the layer and registers it in the textureId map.
-// FIXME: We will need to come up with a more sophisticated allocation strategy here.
-int LayerRendererChromium::assignTextureForLayer(LayerChromium* layer)
-{
- GLuint textureId = createLayerTexture();
-
- // FIXME: Check that textureId is valid
- m_textureIdMap.set(layer, textureId);
-
- layer->setLayerRenderer(this);
-
+ GLuint textureId = 0;
+ GLC(glGenTextures(1, &textureId));
+ GLC(glBindTexture(GL_TEXTURE_2D, textureId));
+ // Do basic linear filtering on resize.
+ GLC(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GLC(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+ // NPOT textures in GL ES only work when the wrap mode is set to GL_CLAMP_TO_EDGE.
+ GLC(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GLC(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
return textureId;
}
-bool LayerRendererChromium::freeLayerTexture(LayerChromium* layer)
-{
- TextureIdMap::iterator textureId = m_textureIdMap.find(layer);
- if (textureId == m_textureIdMap.end())
- return false;
- // Free up the texture.
- glDeleteTextures(1, &(textureId->second));
- m_textureIdMap.remove(textureId);
- return true;
-}
-
-// Draws a debug border around the layer's bounds.
-void LayerRendererChromium::drawDebugBorder(LayerChromium* layer, const TransformationMatrix& matrix)
-{
- static GLfloat glMatrix[16];
- Color borderColor = layer->borderColor();
- if (!borderColor.alpha())
- return;
-
- useShaderProgram(DebugBorderProgram);
- TransformationMatrix renderMatrix = matrix;
- IntSize bounds = layer->bounds();
- renderMatrix.scale3d(bounds.width(), bounds.height(), 1);
- renderMatrix.multiply(m_projectionMatrix);
- toGLMatrix(&glMatrix[0], renderMatrix);
- unsigned borderMatrixLocation = m_shaderPrograms[DebugBorderProgram].m_matrixLocation;
- glUniformMatrix4fv(borderMatrixLocation, 1, false, &glMatrix[0]);
-
- glUniform4f(m_borderColorLocation, borderColor.red() / 255.0,
- borderColor.green() / 255.0,
- borderColor.blue() / 255.0,
- 1);
-
- glLineWidth(layer->borderWidth());
-
- // The indices for the line are stored in the same array as the triangle indices.
- glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, (void*)(6 * sizeof(unsigned short)));
- checkGLError();
-}
-
// Returns true if any part of the layer falls within the visibleRect
bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const TransformationMatrix& matrix, const IntRect& visibleRect)
{
@@ -588,9 +347,9 @@ bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const Transform
return mappedRect.intersects(FloatRect(-1, -1, 2, 2));
}
-// Updates and caches the layer transforms and opacity values that will be used
-// when rendering them.
-void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity, const IntRect& visibleRect)
+// Recursively walks the layer tree starting at the given node and updates the
+// transform and opacity values.
+void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity)
{
// Compute the new matrix transformation that will be applied to this layer and
// all its sublayers. It's important to remember that the layer's position
@@ -627,23 +386,11 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
// M = M[p] * Tr[l] * M[l] * Tr[c]
localMatrix.translate3d(centerOffsetX, centerOffsetY, -layer->anchorPointZ());
- // Check if the layer falls within the visible bounds of the page.
- bool layerVisible = isLayerVisible(layer, localMatrix, visibleRect);
-
- bool skipLayer = false;
- if (bounds.width() > 2048 || bounds.height() > 2048) {
- if (layer->drawsContent())
- LOG(LayerRenderer, "Skipping layer with size %d %d", bounds.width(), bounds.height());
- skipLayer = true;
- }
-
// Calculate the layer's opacity.
opacity *= layer->opacity();
layer->setDrawTransform(localMatrix);
layer->setDrawOpacity(opacity);
- if (layerVisible && !skipLayer)
- m_layerList.append(layer);
// Flatten to 2D if the layer doesn't preserve 3D.
if (!layer->preserves3D()) {
@@ -667,29 +414,71 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers();
for (size_t i = 0; i < sublayers.size(); i++)
- updateLayersRecursive(sublayers[i].get(), localMatrix, opacity, visibleRect);
+ updateLayersRecursive(sublayers[i].get(), localMatrix, opacity);
+
+ layer->setLayerRenderer(this);
+}
+
+// Recursively walk the layer tree and draw the layers.
+void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer)
+{
+ static bool depthTestEnabledForSubtree = false;
+
+ // Check if the layer falls within the visible bounds of the page.
+ bool layerVisible = isLayerVisible(layer, layer->drawTransform(), m_visibleRect);
+
+ // Enable depth testing for this layer and all its descendants if preserves3D is set.
+ bool mustClearDepth = false;
+ if (layer->preserves3D()) {
+ if (!depthTestEnabledForSubtree) {
+ GLC(glEnable(GL_DEPTH_TEST));
+ depthTestEnabledForSubtree = true;
+
+ // Need to clear the depth buffer when we're done rendering this subtree.
+ mustClearDepth = true;
+ }
+ }
+
+ if (layerVisible)
+ drawLayer(layer);
+
+ // If we're using depth testing then we need to sort the children in Z to
+ // get the transparency to work properly.
+ if (depthTestEnabledForSubtree) {
+ const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers();
+ Vector<LayerChromium*> sublayerList;
+ size_t i;
+ for (i = 0; i < sublayers.size(); i++)
+ sublayerList.append(sublayers[i].get());
+
+ // Sort by the z coordinate of the layer center so that layers further away
+ // are drawn first.
+ std::stable_sort(sublayerList.begin(), sublayerList.end(), compareLayerZ);
+
+ for (i = 0; i < sublayerList.size(); i++)
+ drawLayersRecursive(sublayerList[i]);
+ } else {
+ const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers();
+ for (size_t i = 0; i < sublayers.size(); i++)
+ drawLayersRecursive(sublayers[i].get());
+ }
+
+ if (mustClearDepth) {
+ GLC(glDisable(GL_DEPTH_TEST));
+ GLC(glClear(GL_DEPTH_BUFFER_BIT));
+ depthTestEnabledForSubtree = false;
+ }
}
void LayerRendererChromium::drawLayer(LayerChromium* layer)
{
- const TransformationMatrix& localMatrix = layer->drawTransform();
IntSize bounds = layer->bounds();
if (layer->drawsContent()) {
- int textureId;
- if (layer->ownsTexture())
- textureId = layer->textureId();
- else {
- textureId = getTextureId(layer);
- // If no texture has been created for the layer yet then create one now.
- if (textureId == -1)
- textureId = assignTextureForLayer(layer);
- }
-
- // Redraw the contents of the layer if necessary.
+ // Update the contents of the layer if necessary.
if (layer->contentsDirty()) {
// Update the backing texture contents for any dirty portion of the layer.
- layer->updateTextureContents(textureId);
+ layer->updateContents();
m_gles2Context->makeCurrent();
}
@@ -698,13 +487,11 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer)
else
glEnable(GL_CULL_FACE);
- glBindTexture(GL_TEXTURE_2D, textureId);
- useShaderProgram(static_cast<ShaderProgramType>(layer->shaderProgramId()));
- drawTexturedQuad(localMatrix, bounds.width(), bounds.height(), layer->drawOpacity());
+ layer->draw();
}
// Draw the debug border if there is one.
- drawDebugBorder(layer, localMatrix);
+ layer->drawDebugBorder();
}
bool LayerRendererChromium::makeContextCurrent()
@@ -712,21 +499,22 @@ bool LayerRendererChromium::makeContextCurrent()
return m_gles2Context->makeCurrent();
}
-void LayerRendererChromium::bindCommonAttribLocations(ShaderProgramType program)
+// Checks whether a given size is within the maximum allowed texture size range.
+bool LayerRendererChromium::checkTextureSize(const IntSize& textureSize)
{
- unsigned programId = m_shaderPrograms[program].m_shaderProgramId;
- glBindAttribLocation(programId, m_positionLocation, "a_position");
- glBindAttribLocation(programId, m_texCoordLocation, "a_texCoord");
-
- // Re-link the program for the new attribute locations to take effect.
- glLinkProgram(programId);
- checkGLError();
+ if (textureSize.width() > m_maxTextureSize || textureSize.height() > m_maxTextureSize)
+ return false;
+ return true;
}
-bool LayerRendererChromium::initializeSharedGLObjects()
+bool LayerRendererChromium::initializeSharedObjects()
{
- // Shaders for drawing the layer contents.
- char vertexShaderString[] =
+ makeContextCurrent();
+
+ // Vertex and fragment shaders for rendering the scrolled root layer quad.
+ // They differ from a regular content layer shader in that they don't swizzle
+ // the colors or take an alpha value.
+ char scrollVertexShaderString[] =
"attribute vec4 a_position; \n"
"attribute vec2 a_texCoord; \n"
"uniform mat4 matrix; \n"
@@ -736,30 +524,6 @@ bool LayerRendererChromium::initializeSharedGLObjects()
" gl_Position = matrix * a_position; \n"
" v_texCoord = a_texCoord; \n"
"} \n";
- // Note differences between Skia and Core Graphics versions:
- // - Skia uses BGRA and origin is upper left
- // - Core Graphics uses RGBA and origin is lower left
- char fragmentShaderString[] =
- "precision mediump float; \n"
- "varying vec2 v_texCoord; \n"
- "uniform sampler2D s_texture; \n"
- "uniform float alpha; \n"
- "void main() \n"
- "{ \n"
-#if PLATFORM(SKIA)
- " vec4 texColor = texture2D(s_texture, v_texCoord); \n"
- " gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha; \n"
-#elif PLATFORM(CG)
- " vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); \n"
- " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
-#else
-#error "Need to implement for your platform."
-#endif
- "} \n";
-
- // Fragment shader used for rendering the scrolled root layer quad. It differs
- // from fragmentShaderString in that it doesn't swizzle the colors and doesn't
- // take an alpha value.
char scrollFragmentShaderString[] =
"precision mediump float; \n"
"varying vec2 v_texCoord; \n"
@@ -770,101 +534,67 @@ bool LayerRendererChromium::initializeSharedGLObjects()
" gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w); \n"
"} \n";
- // Canvas layers need to be flipped vertically and their colors shouldn't be
- // swizzled.
- char canvasFragmentShaderString[] =
- "precision mediump float; \n"
- "varying vec2 v_texCoord; \n"
- "uniform sampler2D s_texture; \n"
- "uniform float alpha; \n"
- "void main() \n"
- "{ \n"
- " vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); \n"
- " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
- "} \n";
-
- // Shaders for drawing the debug borders around the layers.
- char borderVertexShaderString[] =
- "attribute vec4 a_position; \n"
- "uniform mat4 matrix; \n"
- "void main() \n"
- "{ \n"
- " gl_Position = matrix * a_position; \n"
- "} \n";
- char borderFragmentShaderString[] =
- "precision mediump float; \n"
- "uniform vec4 color; \n"
- "void main() \n"
- "{ \n"
- " gl_FragColor = color; \n"
- "} \n";
-
- GLfloat vertices[] = { -0.5f, 0.5f, 0.0f, // Position 0
- 0.0f, 1.0f, // TexCoord 0
- -0.5f, -0.5f, 0.0f, // Position 1
- 0.0f, 0.0f, // TexCoord 1
- 0.5f, -0.5f, 0.0f, // Position 2
- 1.0f, 0.0f, // TexCoord 2
- 0.5f, 0.5f, 0.0f, // Position 3
- 1.0f, 1.0f // TexCoord 3
- };
- GLushort indices[] = { 0, 1, 2, 0, 2, 3, // The two triangles that make up the layer quad.
- 0, 1, 2, 3}; // A line path for drawing the layer border.
-
- makeContextCurrent();
-
- if (!createLayerShader(ContentLayerProgram, vertexShaderString, fragmentShaderString)) {
- LOG_ERROR("Failed to create shader program for content layers");
- return false;
- }
- LayerChromium::setShaderProgramId(ContentLayerProgram);
-
- if (!createLayerShader(CanvasLayerProgram, vertexShaderString, canvasFragmentShaderString)) {
- LOG_ERROR("Failed to create shader program for Canvas layers");
+ m_scrollShaderProgram = LayerChromium::createShaderProgram(scrollVertexShaderString, scrollFragmentShaderString);
+ if (!m_scrollShaderProgram) {
+ LOG_ERROR("LayerRendererChromium: Failed to create scroll shader program");
+ cleanupSharedObjects();
return false;
}
- CanvasLayerChromium::setShaderProgramId(CanvasLayerProgram);
- if (!createLayerShader(ScrollLayerProgram, vertexShaderString, scrollFragmentShaderString)) {
- LOG_ERROR("Failed to create shader program for scrolling layer");
+ GLC(m_scrollShaderSamplerLocation = glGetUniformLocation(m_scrollShaderProgram, "s_texture"));
+ GLC(m_scrollShaderMatrixLocation = glGetUniformLocation(m_scrollShaderProgram, "matrix"));
+ if (m_scrollShaderSamplerLocation == -1 || m_scrollShaderMatrixLocation == -1) {
+ LOG_ERROR("Failed to initialize scroll shader.");
+ cleanupSharedObjects();
return false;
}
- if (!createLayerShader(DebugBorderProgram, borderVertexShaderString, borderFragmentShaderString)) {
- LOG_ERROR("Failed to create shader program for debug borders");
- return false;
- }
-
- // Specify the attrib location for the position and texCoord and make it the same for all programs to
- // avoid binding re-binding the vertex attributes.
- bindCommonAttribLocations(ContentLayerProgram);
- bindCommonAttribLocations(CanvasLayerProgram);
- bindCommonAttribLocations(DebugBorderProgram);
- bindCommonAttribLocations(ScrollLayerProgram);
-
- // Get the location of the color uniform for the debug border shader program.
- m_borderColorLocation = glGetUniformLocation(m_shaderPrograms[DebugBorderProgram].m_shaderProgramId, "color");
-
- glGenBuffers(3, m_quadVboIds);
- glBindBuffer(GL_ARRAY_BUFFER, m_quadVboIds[Vertices]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_quadVboIds[LayerElements]);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
-
// Create a texture object to hold the contents of the root layer.
m_rootLayerTextureId = createLayerTexture();
if (!m_rootLayerTextureId) {
LOG_ERROR("Failed to create texture for root layer");
+ cleanupSharedObjects();
return false;
}
// Turn off filtering for the root layer to avoid blurring from the repeated
// writes and reads to the framebuffer that happen while scrolling.
- glBindTexture(GL_TEXTURE_2D, m_rootLayerTextureId);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ GLC(glBindTexture(GL_TEXTURE_2D, m_rootLayerTextureId));
+ GLC(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
+ GLC(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
+
+ // Get the max texture size supported by the system.
+ GLC(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize));
+
+ m_layerSharedValues = adoptPtr(new LayerChromium::SharedValues());
+ m_contentLayerSharedValues = adoptPtr(new ContentLayerChromium::SharedValues());
+ m_canvasLayerSharedValues = adoptPtr(new CanvasLayerChromium::SharedValues());
+ if (!m_layerSharedValues->initialized() || !m_contentLayerSharedValues->initialized() || !m_canvasLayerSharedValues->initialized()) {
+ cleanupSharedObjects();
+ return false;
+ }
return true;
}
+
+void LayerRendererChromium::cleanupSharedObjects()
+{
+ makeContextCurrent();
+
+ m_layerSharedValues.clear();
+ m_contentLayerSharedValues.clear();
+ m_canvasLayerSharedValues.clear();
+
+ if (m_scrollShaderProgram) {
+ GLC(glDeleteProgram(m_scrollShaderProgram));
+ m_scrollShaderProgram = 0;
+ }
+
+ if (m_rootLayerTextureId) {
+ GLC(glDeleteTextures(1, &m_rootLayerTextureId));
+ m_rootLayerTextureId = 0;
+ }
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h
index e4474b5..24bbe65 100644
--- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h
+++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h
@@ -34,6 +34,8 @@
#if USE(ACCELERATED_COMPOSITING)
+#include "CanvasLayerChromium.h"
+#include "ContentLayerChromium.h"
#include "IntRect.h"
#include "LayerChromium.h"
#include "SkBitmap.h"
@@ -51,16 +53,6 @@ namespace WebCore {
class GLES2Context;
-class ShaderProgram {
-public:
- ShaderProgram();
-
- unsigned m_shaderProgramId;
- int m_samplerLocation;
- int m_matrixLocation;
- int m_alphaLocation;
-};
-
// Class that handles drawing of composited render layers using GL.
class LayerRendererChromium : public Noncopyable {
public:
@@ -78,73 +70,58 @@ public:
void setNeedsDisplay() { m_needsDisplay = true; }
- // Frees the texture associated with the given layer.
- bool freeLayerTexture(LayerChromium*);
-
bool hardwareCompositing() const { return m_hardwareCompositing; }
void setRootLayerCanvasSize(const IntSize&);
GraphicsContext* rootLayerGraphicsContext() const { return m_rootLayerGraphicsContext.get(); }
-private:
- enum ShaderProgramType { DebugBorderProgram, ScrollLayerProgram, ContentLayerProgram, CanvasLayerProgram, NumShaderProgramTypes };
+ unsigned createLayerTexture();
- void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity, const IntRect& visibleRect);
+ static void debugGLCall(const char* command, const char* file, int line);
- void drawLayer(LayerChromium*);
+ const TransformationMatrix& projectionMatrix() const { return m_projectionMatrix; }
- void drawDebugBorder(LayerChromium*, const TransformationMatrix&);
+ void useShader(unsigned);
- void drawTexturedQuad(const TransformationMatrix& matrix, float width, float height, float opacity);
+ bool checkTextureSize(const IntSize&);
- bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect);
+ const LayerChromium::SharedValues* layerSharedValues() const { return m_layerSharedValues.get(); }
+ const ContentLayerChromium::SharedValues* contentLayerSharedValues() const { return m_contentLayerSharedValues.get(); }
+ const CanvasLayerChromium::SharedValues* canvasLayerSharedValues() const { return m_canvasLayerSharedValues.get(); }
- bool createLayerShader(ShaderProgramType, const char* vertexShaderSource, const char* fragmentShaderSource);
+private:
+ void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity);
- void useShaderProgram(ShaderProgramType);
+ void drawLayersRecursive(LayerChromium*);
- void bindCommonAttribLocations(ShaderProgramType);
+ void drawLayer(LayerChromium*);
- enum VboIds { Vertices, LayerElements };
+ bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect);
- // These are here only temporarily and should be removed once we switch over to GGL
bool makeContextCurrent();
- bool initializeSharedGLObjects();
- int getTextureId(LayerChromium*);
- int assignTextureForLayer(LayerChromium*);
-
- ShaderProgram m_shaderPrograms[NumShaderProgramTypes];
+ bool initializeSharedObjects();
+ void cleanupSharedObjects();
unsigned m_rootLayerTextureId;
int m_rootLayerTextureWidth;
int m_rootLayerTextureHeight;
- // Shader uniform and attribute locations.
- const int m_positionLocation;
- const int m_texCoordLocation;
- int m_samplerLocation;
- int m_matrixLocation;
- int m_alphaLocation;
- int m_borderColorLocation;
+ // Scroll shader uniform locations.
+ unsigned m_scrollShaderProgram;
+ int m_scrollShaderSamplerLocation;
+ int m_scrollShaderMatrixLocation;
- unsigned m_quadVboIds[3];
TransformationMatrix m_projectionMatrix;
RefPtr<LayerChromium> m_rootLayer;
- Vector<LayerChromium*> m_layerList;
-
bool m_needsDisplay;
IntPoint m_scrollPosition;
bool m_hardwareCompositing;
- ShaderProgramType m_currentShaderProgramType;
-
- // Map associating layers with textures ids used by the GL compositor.
- typedef HashMap<LayerChromium*, unsigned> TextureIdMap;
- TextureIdMap m_textureIdMap;
+ unsigned int m_currentShader;
#if PLATFORM(SKIA)
OwnPtr<skia::PlatformCanvas> m_rootLayerCanvas;
@@ -158,9 +135,33 @@ private:
IntSize m_rootLayerCanvasSize;
+ IntRect m_visibleRect;
+
+ int m_maxTextureSize;
+
+ // Store values that are shared between instances of each layer type
+ // associated with this instance of the compositor. Since there can be
+ // multiple instances of the compositor running in the same renderer process
+ // we cannot store these values in static variables.
+ OwnPtr<LayerChromium::SharedValues> m_layerSharedValues;
+ OwnPtr<ContentLayerChromium::SharedValues> m_contentLayerSharedValues;
+ OwnPtr<CanvasLayerChromium::SharedValues> m_canvasLayerSharedValues;
+
OwnPtr<GLES2Context> m_gles2Context;
};
+// Setting DEBUG_GL_CALLS to 1 will call glGetError() after almost every GL
+// call made by the compositor. Useful for debugging rendering issues but
+// will significantly degrade performance.
+#define DEBUG_GL_CALLS 0
+
+#if DEBUG_GL_CALLS && !defined ( NDEBUG )
+#define GLC(x) { (x), LayerRendererChromium::debugGLCall(#x, __FILE__, __LINE__); }
+#else
+#define GLC(x) (x)
+#endif
+
+
}
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/chromium/TilingData.cpp b/WebCore/platform/graphics/chromium/TilingData.cpp
index c52288d..4da242b 100755
--- a/WebCore/platform/graphics/chromium/TilingData.cpp
+++ b/WebCore/platform/graphics/chromium/TilingData.cpp
@@ -117,18 +117,22 @@ int TilingData::tilePositionX(int xIndex) const
{
ASSERT(xIndex >= 0 && xIndex < numTilesX());
- if (!xIndex)
- return 0;
- return tilePositionX(xIndex - 1) + tileSizeX(xIndex - 1);
+ int pos = 0;
+ for (int i = 0; i < xIndex; i++)
+ pos += tileSizeX(i);
+
+ return pos;
}
int TilingData::tilePositionY(int yIndex) const
{
ASSERT(yIndex >= 0 && yIndex < numTilesY());
- if (!yIndex)
- return 0;
- return tilePositionX(yIndex - 1) + tileSizeY(yIndex - 1);
+ int pos = 0;
+ for (int i = 0; i < yIndex; i++)
+ pos += tileSizeY(i);
+
+ return pos;
}
int TilingData::tileSizeX(int xIndex) const
diff --git a/WebCore/platform/graphics/chromium/VideoFrameChromium.h b/WebCore/platform/graphics/chromium/VideoFrameChromium.h
new file mode 100644
index 0000000..bbd677e
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/VideoFrameChromium.h
@@ -0,0 +1,81 @@
+/*
+ * 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 VideoFrameChromium_h
+#define VideoFrameChromium_h
+
+namespace WebCore {
+
+// A class that represents a video frame in chromium.
+class VideoFrameChromium {
+public:
+ static const unsigned cMaxPlanes;
+ static const unsigned cNumRGBPlanes;
+ static const unsigned cRGBPlane;
+ static const unsigned cNumYUVPlanes;
+ static const unsigned cYPlane;
+ static const unsigned cUPlane;
+ static const unsigned cVPlane;
+
+ // These enums must be kept in sync with WebKit::WebVideoFrame.
+ enum Format {
+ Invalid,
+ RGB555,
+ RGB565,
+ RGB24,
+ RGB32,
+ RGBA,
+ YV12,
+ YV16,
+ NV12,
+ Empty,
+ ASCII,
+ };
+
+ enum SurfaceType {
+ TypeSystemMemory,
+ TypeOMXBufferHead,
+ TypeEGLImage,
+ TypeMFBuffer,
+ TypeDirect3DSurface
+ };
+
+ virtual SurfaceType surfaceType() const = 0;
+ virtual Format format() const = 0;
+ virtual unsigned width() const = 0;
+ virtual unsigned height() const = 0;
+ virtual unsigned planes() const = 0;
+ virtual int stride(unsigned plane) const = 0;
+ virtual const void* data(unsigned plane) const = 0;
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/graphics/chromium/TransformLayerChromium.cpp b/WebCore/platform/graphics/chromium/VideoFrameProvider.h
index 6427eeb..f0bad08 100644
--- a/WebCore/platform/graphics/chromium/TransformLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/VideoFrameProvider.h
@@ -28,23 +28,28 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
+#ifndef VideoFrameProvider_h
+#define VideoFrameProvider_h
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "TransformLayerChromium.h"
+#include "VideoFrameChromium.h"
namespace WebCore {
-PassRefPtr<TransformLayerChromium> TransformLayerChromium::create(GraphicsLayerChromium* owner)
-{
- return adoptRef(new TransformLayerChromium(owner));
-}
+class VideoFrameProvider {
+public:
+ // This function returns a pointer to a VideoFrameChromium, which is
+ // the WebCore wrapper for a video frame in Chromium. getCurrentFrame()
+ // places a lock on the frame in Chromium. Calls to this method should
+ // always be followed with a call to putCurrentFrame().
+ // The ownership of the object is not transferred to the caller and
+ // the caller should not free the returned object.
+ virtual VideoFrameChromium* getCurrentFrame() = 0;
+ // This function releases the lock on the video frame in chromium. It should
+ // always be called after getCurrentFrame(). Frames passed into this method
+ // should no longer be referenced after the call is made.
+ virtual void putCurrentFrame(VideoFrameChromium*) = 0;
+};
-TransformLayerChromium::TransformLayerChromium(GraphicsLayerChromium* owner)
- : LayerChromium(owner)
-{
-}
+} // namespace WebCore
-}
-#endif // USE(ACCELERATED_COMPOSITING)
+#endif
diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
index 89b6ec1..7ff98b9 100644
--- a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
@@ -48,23 +48,24 @@
namespace WebCore {
-PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(GraphicsLayerChromium* owner)
+PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(GraphicsLayerChromium* owner,
+ VideoFrameProvider* provider)
{
- return adoptRef(new VideoLayerChromium(owner));
+ return adoptRef(new VideoLayerChromium(owner, provider));
}
-VideoLayerChromium::VideoLayerChromium(GraphicsLayerChromium* owner)
- : LayerChromium(owner)
- , m_allocatedTextureId(0)
+VideoLayerChromium::VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameProvider* provider)
+ : ContentLayerChromium(owner)
#if PLATFORM(SKIA)
, m_canvas(0)
, m_skiaContext(0)
#endif
, m_graphicsContext(0)
+ , m_provider(provider)
{
}
-void VideoLayerChromium::updateTextureContents(unsigned textureId)
+void VideoLayerChromium::updateContents()
{
RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
if (!backing || backing->paintingGoesToWindow())
@@ -109,9 +110,20 @@ void VideoLayerChromium::updateTextureContents(unsigned textureId)
// Bring the canvas into the coordinate system of the paint rect.
m_canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y()));
+ // FIXME: Remove this test when tiled layers are implemented.
+ m_skipsDraw = false;
+ if (!layerRenderer()->checkTextureSize(requiredTextureSize)) {
+ m_skipsDraw = true;
+ return;
+ }
+
+ unsigned textureId = m_contentsTexture;
+ if (!textureId)
+ textureId = layerRenderer()->createLayerTexture();
+
// If the texture id or size changed since last time, then we need to tell GL
// to re-allocate a texture.
- if (m_allocatedTextureId != textureId || requiredTextureSize != m_allocatedTextureSize)
+ if (m_contentsTexture != textureId || requiredTextureSize != m_allocatedTextureSize)
createTextureRect(requiredTextureSize, dirtyRect, textureId);
else
updateTextureRect(dirtyRect, textureId);
@@ -150,7 +162,7 @@ void VideoLayerChromium::createTextureRect(const IntSize& requiredTextureSize, c
ASSERT(bitmapSize == requiredTextureSize);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
- m_allocatedTextureId = textureId;
+ m_contentsTexture = textureId;
m_allocatedTextureSize = requiredTextureSize;
updateCompleted();
diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/WebCore/platform/graphics/chromium/VideoLayerChromium.h
index 746299f..3507cb2 100644
--- a/WebCore/platform/graphics/chromium/VideoLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.h
@@ -34,30 +34,31 @@
#if USE(ACCELERATED_COMPOSITING)
-#include "LayerChromium.h"
+#include "ContentLayerChromium.h"
+#include "VideoFrameProvider.h"
namespace WebCore {
// A Layer that contains a Video element.
-class VideoLayerChromium : public LayerChromium {
+class VideoLayerChromium : public ContentLayerChromium {
public:
- static PassRefPtr<VideoLayerChromium> create(GraphicsLayerChromium* owner = 0);
+ static PassRefPtr<VideoLayerChromium> create(GraphicsLayerChromium* owner = 0,
+ VideoFrameProvider* = 0);
virtual bool drawsContent() { return true; }
- virtual void updateTextureContents(unsigned textureId);
+ virtual void updateContents();
private:
- VideoLayerChromium(GraphicsLayerChromium* owner);
+ VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameProvider*);
void createTextureRect(const IntSize& requiredTextureSize, const IntRect& updateRect, unsigned textureId);
void updateTextureRect(const IntRect& updateRect, unsigned textureId);
void updateCompleted();
- unsigned m_allocatedTextureId;
- IntSize m_allocatedTextureSize;
#if PLATFORM(SKIA)
OwnPtr<skia::PlatformCanvas> m_canvas;
OwnPtr<PlatformContextSkia> m_skiaContext;
#endif
OwnPtr<GraphicsContext> m_graphicsContext;
+ OwnPtr<VideoFrameProvider> m_provider;
};
}
diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp
index 0bafc48..d9f00ce 100644
--- a/WebCore/platform/graphics/filters/FEComposite.cpp
+++ b/WebCore/platform/graphics/filters/FEComposite.cpp
@@ -136,7 +136,7 @@ void FEComposite::apply(Filter* filter)
break;
case FECOMPOSITE_OPERATOR_IN:
filterContext->save();
- filterContext->clipToImageBuffer(m_in->resultImage(), calculateDrawingRect(m_in2->scaledSubRegion()));
+ filterContext->clipToImageBuffer(m_in2->resultImage(), calculateDrawingRect(m_in2->scaledSubRegion()));
filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
filterContext->restore();
break;
diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
index 70465a0..44bb65a 100644
--- a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
+++ b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
@@ -200,6 +200,12 @@ TextStream& FEGaussianBlur::externalRepresentation(TextStream& ts, int indent) c
return ts;
}
+float FEGaussianBlur::calculateStdDeviation(float radius)
+{
+ // Blur radius represents 2/3 times the kernel size, the dest pixel is half of the radius applied 3 times
+ return max((radius * 2 / 3.f - 0.5f) / gGaussianKernelFactor, 0.f);
+}
+
} // namespace WebCore
#endif // ENABLE(FILTERS)
diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.h b/WebCore/platform/graphics/filters/FEGaussianBlur.h
index 4c7c43c..ad5c5a3 100644
--- a/WebCore/platform/graphics/filters/FEGaussianBlur.h
+++ b/WebCore/platform/graphics/filters/FEGaussianBlur.h
@@ -43,6 +43,8 @@ public:
void dump();
TextStream& externalRepresentation(TextStream&, int indent) const;
+ static float calculateStdDeviation(float);
+
private:
FEGaussianBlur(FilterEffect*, const float&, const float&);
static void kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight);
diff --git a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp
index c5022f9..96a639b 100644
--- a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp
+++ b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp
@@ -21,24 +21,178 @@
#include "GStreamerGWorld.h"
-#include "MediaPlayerPrivateGStreamer.h"
+#include "GOwnPtrGStreamer.h"
+
+#include <gst/gst.h>
+#include <gst/interfaces/xoverlay.h>
+
+#if PLATFORM(GTK)
+#include <gtk/gtk.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h> // for GDK_WINDOW_XID
+#endif
+#endif
using namespace std;
namespace WebCore {
-PassRefPtr<GStreamerGWorld> GStreamerGWorld::createGWorld(MediaPlayerPrivateGStreamer* player)
+gboolean gstGWorldSyncMessageCallback(GstBus* bus, GstMessage* message, gpointer data)
+{
+ ASSERT(GST_MESSAGE_TYPE(message) == GST_MESSAGE_ELEMENT);
+
+ GStreamerGWorld* gstGWorld = static_cast<GStreamerGWorld*>(data);
+
+ if (gst_structure_has_name(message->structure, "prepare-xwindow-id"))
+ gstGWorld->setWindowOverlay(message);
+ return TRUE;
+}
+
+PassRefPtr<GStreamerGWorld> GStreamerGWorld::createGWorld(GstElement* pipeline)
{
- return adoptRef(new GStreamerGWorld(player));
+ return adoptRef(new GStreamerGWorld(pipeline));
}
-GStreamerGWorld::GStreamerGWorld(MediaPlayerPrivateGStreamer* player)
- : m_player(player)
+GStreamerGWorld::GStreamerGWorld(GstElement* pipeline)
+ : m_pipeline(pipeline)
+ , m_dynamicPadName(0)
{
+ // XOverlay messages need to be handled synchronously.
+ GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline));
+ gst_bus_set_sync_handler(bus, gst_bus_sync_signal_handler, this);
+ g_signal_connect(bus, "sync-message::element", G_CALLBACK(gstGWorldSyncMessageCallback), this);
+ gst_object_unref(bus);
}
GStreamerGWorld::~GStreamerGWorld()
{
+ exitFullscreen();
+
+ m_pipeline = 0;
+}
+
+bool GStreamerGWorld::enterFullscreen()
+{
+ if (m_dynamicPadName)
+ return false;
+
+ if (!m_videoWindow)
+ m_videoWindow = PlatformVideoWindow::createWindow();
+
+ GstElement* platformVideoSink = gst_element_factory_make("autovideosink", "platformVideoSink");
+ GstElement* colorspace = gst_element_factory_make("ffmpegcolorspace", "colorspace");
+ GstElement* queue = gst_element_factory_make("queue", "queue");
+ GstElement* videoScale = gst_element_factory_make("videoscale", "videoScale");
+
+ // Get video sink bin and the tee inside.
+ GOwnPtr<GstElement> videoSink;
+ g_object_get(m_pipeline, "video-sink", &videoSink.outPtr(), NULL);
+ GstElement* tee = gst_bin_get_by_name(GST_BIN(videoSink.get()), "videoTee");
+
+ // Add and link a queue, ffmpegcolorspace and sink in the bin.
+ gst_bin_add_many(GST_BIN(videoSink.get()), platformVideoSink, videoScale, colorspace, queue, NULL);
+ gst_element_link_many(queue, colorspace, videoScale, platformVideoSink, NULL);
+
+ // Link a new src pad from tee to queue.
+ GstPad* srcPad = gst_element_get_request_pad(tee, "src%d");
+ GstPad* sinkPad = gst_element_get_static_pad(queue, "sink");
+ gst_pad_link(srcPad, sinkPad);
+ gst_object_unref(GST_OBJECT(sinkPad));
+
+ m_dynamicPadName = gst_pad_get_name(srcPad);
+
+ // Roll new elements to pipeline state.
+ gst_element_sync_state_with_parent(queue);
+ gst_element_sync_state_with_parent(colorspace);
+ gst_element_sync_state_with_parent(videoScale);
+ gst_element_sync_state_with_parent(platformVideoSink);
+
+ gst_object_unref(tee);
+
+ // Query the current media segment informations and send them towards
+ // the new tee branch downstream.
+
+ GstQuery* query = gst_query_new_segment(GST_FORMAT_TIME);
+ gboolean queryResult = gst_element_query(m_pipeline, query);
+
+ // See https://bugzilla.gnome.org/show_bug.cgi?id=620490.
+#if GST_CHECK_VERSION(0, 10, 30)
+ if (!queryResult) {
+ gst_query_unref(query);
+ gst_object_unref(GST_OBJECT(srcPad));
+ return true;
+ }
+#endif
+
+ GstFormat format;
+ gint64 position;
+ if (!gst_element_query_position(m_pipeline, &format, &position))
+ position = 0;
+
+ gdouble rate;
+ gint64 startValue, stopValue;
+ gst_query_parse_segment(query, &rate, &format, &startValue, &stopValue);
+
+ GstEvent* event = gst_event_new_new_segment(FALSE, rate, format, startValue, stopValue, position);
+ gst_pad_push_event(srcPad, event);
+
+ gst_query_unref(query);
+ gst_object_unref(GST_OBJECT(srcPad));
+ return true;
+}
+
+void GStreamerGWorld::exitFullscreen()
+{
+ if (!m_dynamicPadName)
+ return;
+
+ // Get video sink bin and the elements to remove.
+ GOwnPtr<GstElement> videoSink;
+ g_object_get(m_pipeline, "video-sink", &videoSink.outPtr(), NULL);
+ GstElement* tee = gst_bin_get_by_name(GST_BIN(videoSink.get()), "videoTee");
+ GstElement* platformVideoSink = gst_bin_get_by_name(GST_BIN(videoSink.get()), "platformVideoSink");
+ GstElement* queue = gst_bin_get_by_name(GST_BIN(videoSink.get()), "queue");
+ GstElement* colorspace = gst_bin_get_by_name(GST_BIN(videoSink.get()), "colorspace");
+ GstElement* videoScale = gst_bin_get_by_name(GST_BIN(videoSink.get()), "videoScale");
+
+ // Get pads to unlink and remove.
+ GstPad* srcPad = gst_element_get_static_pad(tee, m_dynamicPadName);
+ GstPad* sinkPad = gst_element_get_static_pad(queue, "sink");
+
+ // Unlink and release request pad.
+ gst_pad_unlink(srcPad, sinkPad);
+ gst_element_release_request_pad(tee, srcPad);
+ gst_object_unref(GST_OBJECT(srcPad));
+ gst_object_unref(GST_OBJECT(sinkPad));
+
+ // Unlink, remove and cleanup queue, ffmpegcolorspace, videoScale and sink.
+ gst_element_unlink_many(queue, colorspace, videoScale, platformVideoSink, NULL);
+ gst_bin_remove_many(GST_BIN(videoSink.get()), queue, colorspace, videoScale, platformVideoSink, NULL);
+ gst_element_set_state(queue, GST_STATE_NULL);
+ gst_element_set_state(colorspace, GST_STATE_NULL);
+ gst_element_set_state(videoScale, GST_STATE_NULL);
+ gst_element_set_state(platformVideoSink, GST_STATE_NULL);
+ gst_object_unref(queue);
+ gst_object_unref(colorspace);
+ gst_object_unref(videoScale);
+ gst_object_unref(platformVideoSink);
+
+ gst_object_unref(tee);
+ m_dynamicPadName = 0;
+}
+
+void GStreamerGWorld::setWindowOverlay(GstMessage* message)
+{
+ GstObject* sink = GST_MESSAGE_SRC(message);
+
+ if (!GST_IS_X_OVERLAY(sink))
+ return;
+
+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(sink), "force-aspect-ratio"))
+ g_object_set(sink, "force-aspect-ratio", TRUE, NULL);
+
+ if (m_videoWindow)
+ gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(sink), m_videoWindow->videoWindowId());
}
}
diff --git a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h
index b626298..659052a 100644
--- a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h
+++ b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h
@@ -23,25 +23,43 @@
#if ENABLE(VIDEO)
+#include "PlatformVideoWindow.h"
#include "RefCounted.h"
#include "RefPtr.h"
#include <glib.h>
+typedef struct _GstElement GstElement;
+typedef struct _GstMessage GstMessage;
+typedef struct _GstBus GstBus;
+typedef struct _GstBin GstBin;
namespace WebCore {
class MediaPlayerPrivateGStreamer;
+gboolean gstGWorldSyncMessageCallback(GstBus* bus, GstMessage* message, gpointer data);
class GStreamerGWorld : public RefCounted<GStreamerGWorld> {
+ friend gboolean gstGWorldSyncMessageCallback(GstBus* bus, GstMessage* message, gpointer data);
public:
- static PassRefPtr<GStreamerGWorld> createGWorld(MediaPlayerPrivateGStreamer*);
+ static PassRefPtr<GStreamerGWorld> createGWorld(GstElement*);
~GStreamerGWorld();
+ GstElement* pipeline() const { return m_pipeline; }
+
+ // Returns the full-screen window created
+ bool enterFullscreen();
+ void exitFullscreen();
+
+ void setWindowOverlay(GstMessage* message);
+ PlatformVideoWindow* platformVideoWindow() const { return m_videoWindow.get(); }
+
private:
- GStreamerGWorld(MediaPlayerPrivateGStreamer*);
- MediaPlayerPrivateGStreamer* m_player;
+ GStreamerGWorld(GstElement*);
+ GstElement* m_pipeline;
+ RefPtr<PlatformVideoWindow> m_videoWindow;
+ gchar* m_dynamicPadName;
};
}
diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
index 7184439..d9d2d97 100644
--- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
@@ -54,7 +54,6 @@
#include <GOwnPtr.h>
#include <gst/gst.h>
#include <gst/interfaces/mixer.h>
-#include <gst/interfaces/xoverlay.h>
#include <gst/video/video.h>
#include <limits>
#include <math.h>
@@ -1385,7 +1384,7 @@ void MediaPlayerPrivateGStreamer::createGSTPlayBin()
ASSERT(!m_playBin);
m_playBin = gst_element_factory_make("playbin2", "play");
- m_gstGWorld = GStreamerGWorld::createGWorld(this);
+ m_gstGWorld = GStreamerGWorld::createGWorld(m_playBin);
GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(m_playBin));
gst_bus_add_signal_watch(bus);
diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h b/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h
new file mode 100644
index 0000000..83dc5dd
--- /dev/null
+++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h
@@ -0,0 +1,54 @@
+/*
+ * 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 PlatformVideoWindow_h
+#define PlatformVideoWindow_h
+
+#if ENABLE(VIDEO)
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+#if PLATFORM(GTK)
+#include <gtk/gtk.h>
+typedef GtkWidget PlatformWindowType;
+#endif
+
+namespace WebCore {
+
+class PlatformVideoWindow : public RefCounted<PlatformVideoWindow> {
+ public:
+ static PassRefPtr<PlatformVideoWindow> createWindow() { return adoptRef(new PlatformVideoWindow()); }
+
+ PlatformVideoWindow();
+ ~PlatformVideoWindow();
+
+ PlatformWindowType* window() const { return m_window; }
+ gulong videoWindowId() const { return m_videoWindowId; }
+
+ private:
+ gulong m_videoWindowId;
+ PlatformWindowType* m_videoWindow;
+ PlatformWindowType* m_window;
+ };
+}
+
+#endif
+
+#endif
diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp
new file mode 100644
index 0000000..185f535
--- /dev/null
+++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "PlatformVideoWindow.h"
+
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h> // for GDK_WINDOW_XID
+#endif
+
+using namespace WebCore;
+
+PlatformVideoWindow::PlatformVideoWindow()
+{
+ m_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_events(m_window, GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK | GDK_FOCUS_CHANGE_MASK);
+
+ m_videoWindow = gtk_drawing_area_new();
+ gtk_widget_set_double_buffered(m_videoWindow, FALSE);
+ gtk_container_add(GTK_CONTAINER(m_window), m_videoWindow);
+
+ gtk_widget_realize(m_window);
+
+#ifdef GDK_WINDOWING_X11
+ m_videoWindowId = GDK_WINDOW_XID(gtk_widget_get_window(m_window));
+#endif
+
+}
+
+PlatformVideoWindow::~PlatformVideoWindow()
+{
+ if (m_videoWindow && m_window) {
+ gtk_container_remove(GTK_CONTAINER(m_window), m_videoWindow);
+ gtk_widget_destroy(m_videoWindow);
+ m_videoWindow = 0;
+ }
+
+ if (m_window) {
+ gtk_widget_destroy(m_window);
+ m_window = 0;
+ }
+
+ m_videoWindowId = 0;
+}
diff --git a/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp b/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
index d0b0274..821cc12 100644
--- a/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
+++ b/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
@@ -44,7 +44,7 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
if (type != "jpeg" && type != "png" && type != "tiff" && type != "ico" && type != "bmp")
return "data:,";
- GRefPtr<GdkPixbuf> pixbuf = cairoImageSurfaceToGdkPixbuf(m_data.m_surface);
+ PlatformRefPtr<GdkPixbuf> pixbuf = cairoImageSurfaceToGdkPixbuf(m_data.m_surface);
if (!pixbuf)
return "data:,";
diff --git a/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
index c591ddc..a600d73 100644
--- a/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
@@ -31,8 +31,10 @@ namespace WebCore {
FontCustomPlatformData::~FontCustomPlatformData()
{
+#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
if (m_atsContainer)
ATSFontDeactivate(m_atsContainer, NULL, kATSOptionFlagsDefault);
+#endif
CGFontRelease(m_cgFont);
}
diff --git a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm
index 33de3c3..d905b62 100644
--- a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm
+++ b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm
@@ -39,9 +39,10 @@ FontPlatformData::FontPlatformData(NSFont *nsFont, bool syntheticBold, bool synt
, m_isColorBitmapFont(false)
#endif
{
- if (nsFont)
- CFRetain(nsFont);
- m_size = nsFont ? [nsFont pointSize] : 0.0f;
+ ASSERT_ARG(nsFont, nsFont);
+
+ CFRetain(nsFont);
+ m_size = [nsFont pointSize];
#ifndef BUILDING_ON_TIGER
m_cgFont.adoptCF(CTFontCopyGraphicsFont(toCTFontRef(nsFont), 0));
m_atsuFontID = CTFontGetPlatformFont(toCTFontRef(nsFont), 0);
@@ -95,14 +96,17 @@ const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f)
void FontPlatformData::setFont(NSFont *font)
{
+ ASSERT_ARG(font, font);
+ ASSERT(m_font != reinterpret_cast<NSFont *>(-1));
+
if (m_font == font)
return;
- if (font)
- CFRetain(font);
- if (m_font && m_font != reinterpret_cast<NSFont *>(-1))
+
+ CFRetain(font);
+ if (m_font)
CFRelease(m_font);
m_font = font;
- m_size = font ? [font pointSize] : 0.0f;
+ m_size = [font pointSize];
#ifndef BUILDING_ON_TIGER
m_cgFont.adoptCF(CTFontCopyGraphicsFont(toCTFontRef(font), 0));
m_atsuFontID = CTFontGetPlatformFont(toCTFontRef(font), 0);
diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
index be1d278..ab4ef4b 100644
--- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
@@ -312,6 +312,16 @@ bool GraphicsContext3D::isGLES2Compliant() const
return false;
}
+bool GraphicsContext3D::isGLES2NPOTStrict() const
+{
+ return false;
+}
+
+bool GraphicsContext3D::isErrorGeneratedOnOutOfBoundsAccesses() const
+{
+ return false;
+}
+
void GraphicsContext3D::reshape(int width, int height)
{
if (width == m_currentWidth && height == m_currentHeight || !m_contextObj)
@@ -557,40 +567,16 @@ void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long
::glBufferData(target, size, 0, usage);
}
-void GraphicsContext3D::bufferData(unsigned long target, ArrayBuffer* array, unsigned long usage)
-{
- if (!array || !array->byteLength())
- return;
-
- ensureContext(m_contextObj);
- ::glBufferData(target, array->byteLength(), array->data(), usage);
-}
-
-void GraphicsContext3D::bufferData(unsigned long target, ArrayBufferView* array, unsigned long usage)
-{
- if (!array || !array->length())
- return;
-
- ensureContext(m_contextObj);
- ::glBufferData(target, array->byteLength(), array->baseAddress(), usage);
-}
-
-void GraphicsContext3D::bufferSubData(unsigned long target, long offset, ArrayBuffer* array)
+void GraphicsContext3D::bufferData(unsigned long target, int size, const void* data, unsigned long usage)
{
- if (!array || !array->byteLength())
- return;
-
ensureContext(m_contextObj);
- ::glBufferSubData(target, offset, array->byteLength(), array->data());
+ ::glBufferData(target, size, data, usage);
}
-void GraphicsContext3D::bufferSubData(unsigned long target, long offset, ArrayBufferView* array)
+void GraphicsContext3D::bufferSubData(unsigned long target, long offset, int size, const void* data)
{
- if (!array || !array->length())
- return;
-
ensureContext(m_contextObj);
- ::glBufferSubData(target, offset, array->byteLength(), array->baseAddress());
+ ::glBufferSubData(target, offset, size, data);
}
unsigned long GraphicsContext3D::checkFramebufferStatus(unsigned long target)
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
index cb4ca58..315cc00 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
@@ -1213,6 +1213,18 @@ void GraphicsLayerCA::updateContentsOpaque()
void GraphicsLayerCA::updateBackfaceVisibility()
{
+ if (m_structuralLayer && structuralLayerPurpose() == StructuralLayerForReplicaFlattening) {
+ [m_structuralLayer.get() setDoubleSided:m_backfaceVisibility];
+
+ if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
+ CALayer *currLayer = it->second.get();
+ [currLayer setDoubleSided:m_backfaceVisibility];
+ }
+ }
+ }
+
[m_layer.get() setDoubleSided:m_backfaceVisibility];
if (LayerMap* layerCloneMap = m_layerClones.get()) {
@@ -1243,7 +1255,7 @@ void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose)
// Release the structural layer.
m_structuralLayer = 0;
- // Update the properties of m_layer now that we no loner have a structural layer.
+ // Update the properties of m_layer now that we no longer have a structural layer.
updateLayerPosition();
updateLayerSize();
updateAnchorPoint();
@@ -1294,6 +1306,7 @@ void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose)
updateAnchorPoint();
updateTransform();
updateChildrenTransform();
+ updateBackfaceVisibility();
// Set properties of m_layer to their default values, since these are expressed on on the structural layer.
CGPoint point = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f);
diff --git a/WebCore/platform/graphics/qt/ContextShadow.cpp b/WebCore/platform/graphics/qt/ContextShadow.cpp
index 0511218..829ca82 100644
--- a/WebCore/platform/graphics/qt/ContextShadow.cpp
+++ b/WebCore/platform/graphics/qt/ContextShadow.cpp
@@ -28,8 +28,80 @@
#include "config.h"
#include "ContextShadow.h"
+#include <QTimerEvent>
+#include <wtf/Noncopyable.h>
+
namespace WebCore {
+// ContextShadow needs a scratch image as the buffer for the blur filter.
+// Instead of creating and destroying the buffer for every operation,
+// we create a buffer which will be automatically purged via a timer.
+
+class ShadowBuffer: public QObject {
+public:
+ ShadowBuffer(QObject* parent = 0);
+
+ QImage* scratchImage(const QSize& size);
+
+ void schedulePurge();
+
+protected:
+ void timerEvent(QTimerEvent* event);
+
+private:
+ QImage image;
+ int timerId;
+};
+
+ShadowBuffer::ShadowBuffer(QObject* parent)
+ : QObject(parent)
+ , timerId(0)
+{
+}
+
+QImage* ShadowBuffer::scratchImage(const QSize& size)
+{
+ int width = size.width();
+ int height = size.height();
+
+ // We do not need to recreate the buffer if the buffer is reasonably
+ // larger than the requested size. However, if the requested size is
+ // much smaller than our buffer, reduce our buffer so that we will not
+ // keep too many allocated pixels for too long.
+ if (!image.isNull() && (image.width() > width) && (image.height() > height))
+ if (((2 * width) > image.width()) && ((2 * height) > image.height())) {
+ image.fill(Qt::transparent);
+ return &image;
+ }
+
+ // Round to the nearest 32 pixels so we do not grow the buffer everytime
+ // there is larger request by 1 pixel.
+ width = (1 + (width >> 5)) << 5;
+ height = (1 + (height >> 5)) << 5;
+
+ image = QImage(width, height, QImage::Format_ARGB32_Premultiplied);
+ image.fill(Qt::transparent);
+ return &image;
+}
+
+void ShadowBuffer::schedulePurge()
+{
+ static const double BufferPurgeDelay = 2; // seconds
+ killTimer(timerId);
+ timerId = startTimer(BufferPurgeDelay * 1000);
+}
+
+void ShadowBuffer::timerEvent(QTimerEvent* event)
+{
+ if (event->timerId() == timerId) {
+ killTimer(timerId);
+ image = QImage();
+ }
+ QObject::timerEvent(event);
+}
+
+Q_GLOBAL_STATIC(ShadowBuffer, scratchShadowBuffer)
+
ContextShadow::ContextShadow()
: type(NoShadow)
, blurRadius(0)
@@ -203,54 +275,66 @@ static void shadowBlur(QImage& image, int radius, const QColor& shadowColor)
p.end();
}
-void ContextShadow::drawShadowRect(QPainter* p, const QRectF& rect)
+QPainter* ContextShadow::beginShadowLayer(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)) {
+ // We expand the area by the blur radius * 2 to give extra space
+ // for the blur transition.
+ int extra = (type == BlurShadow) ? blurRadius * 2 : 0;
+
+ QRectF shadowRect = rect.translated(offset);
+ QRectF bufferRect = shadowRect.adjusted(-extra, -extra, extra, extra);
+ m_layerRect = bufferRect.toAlignedRect();
+
+ QRect clipRect;
+ if (p->hasClipping())
+#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
+ clipRect = p->clipBoundingRect();
+#else
+ clipRect = p->clipRegion().boundingRect();
+#endif
+ else
+ clipRect = p->transform().inverted().mapRect(p->window());
+
+ if (!clipRect.contains(m_layerRect)) {
+
+ // No need to have the buffer larger than the clip.
+ m_layerRect = m_layerRect.intersected(clipRect);
+ if (m_layerRect.isEmpty())
+ return 0;
+
+ // We adjust again because the pixels at the borders are still
+ // potentially affected by the pixels outside the buffer.
+ if (type == BlurShadow)
+ m_layerRect.adjust(-extra, -extra, extra, extra);
+ }
- // No need to have the buffer larger that the clip.
- alignedBufferRect = alignedBufferRect.intersected(clipRect);
- if (alignedBufferRect.isEmpty())
- return;
+ ShadowBuffer* shadowBuffer = scratchShadowBuffer();
+ QImage* shadowImage = shadowBuffer->scratchImage(m_layerRect.size());
+ m_layerImage = QImage(*shadowImage);
- // 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);
- }
+ m_layerPainter = new QPainter;
+ m_layerPainter->begin(&m_layerImage);
+ m_layerPainter->setFont(p->font());
+ m_layerPainter->translate(offset);
- QImage shadowImage(alignedBufferRect.size(), QImage::Format_ARGB32_Premultiplied);
- shadowImage.fill(Qt::transparent);
- QPainter shadowPainter(&shadowImage);
+ // The origin is now the top left corner of the scratch image.
+ m_layerPainter->translate(-m_layerRect.topLeft());
- shadowPainter.fillRect(shadowRect.translated(-alignedBufferRect.topLeft()), color);
- shadowPainter.end();
+ return m_layerPainter;
+}
- shadowBlur(shadowImage, blurRadius, color);
+void ContextShadow::endShadowLayer(QPainter* p)
+{
+ m_layerPainter->end();
+ delete m_layerPainter;
+ m_layerPainter = 0;
- p->drawImage(alignedBufferRect.topLeft(), shadowImage);
+ if (type == BlurShadow)
+ shadowBlur(m_layerImage, blurRadius, color);
- return;
- }
+ p->drawImage(m_layerRect.topLeft(), m_layerImage);
- p->fillRect(rect.translated(offset), color);
+ scratchShadowBuffer()->schedulePurge();
}
-
}
diff --git a/WebCore/platform/graphics/qt/ContextShadow.h b/WebCore/platform/graphics/qt/ContextShadow.h
index e114ebc..7140340 100644
--- a/WebCore/platform/graphics/qt/ContextShadow.h
+++ b/WebCore/platform/graphics/qt/ContextShadow.h
@@ -58,12 +58,35 @@ public:
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);
+ // The pair beginShadowLayer and endShadowLayer creates a temporary image
+ // where the caller can draw onto, using the returned QPainter. This
+ // QPainter instance must be used only to draw between the call to
+ // beginShadowLayer and endShadowLayer.
+ //
+ // Note: multiple/nested shadow layer is NOT allowed.
+ //
+ // The current clip region will be used to optimize the size of the
+ // temporary image. Thus, the original painter should not change any
+ // clipping until endShadowLayer.
+ // If the shadow will be completely outside the clipping region,
+ // beginShadowLayer will return 0.
+ //
+ // The returned QPainter will have the transformation matrix and clipping
+ // properly initialized to start doing the painting (no need to account
+ // for the shadow offset), however it will not have the same render hints,
+ // pen, brush, etc as the passed QPainter. This is intentional, usually
+ // shadow has different properties than the shape which casts the shadow.
+ //
+ // Once endShadowLayer is called, the temporary image will be drawn
+ // with the original painter. If blur radius is specified, the shadow
+ // will be filtered first.
+ QPainter* beginShadowLayer(QPainter* p, const QRectF& rect);
+ void endShadowLayer(QPainter* p);
+private:
+ QRect m_layerRect;
+ QImage m_layerImage;
+ QPainter* m_layerPainter;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp
index 59320cb..2b246de 100644
--- a/WebCore/platform/graphics/qt/FontQt.cpp
+++ b/WebCore/platform/graphics/qt/FontQt.cpp
@@ -23,6 +23,7 @@
#include "Font.h"
#include "AffineTransform.h"
+#include "ContextShadow.h"
#include "FontDescription.h"
#include "FontFallbackList.h"
#include "FontSelector.h"
@@ -108,12 +109,6 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
QString string = fromRawDataWithoutRef(sanitized);
QPointF pt(point.x(), point.y());
- // text shadow
- FloatSize shadowSize;
- float shadowBlur;
- Color shadowColor;
- bool hasShadow = ctx->textDrawingMode() == cTextFill && ctx->getShadow(shadowSize, shadowBlur, shadowColor);
-
if (from > 0 || to < run.length()) {
if (isComplexText) {
QTextLayout layout(string, font);
@@ -125,32 +120,46 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
QFontMetrics fm(font);
int ascent = fm.ascent();
- QRectF clip(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
+ QRectF boundingRect(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
+ QRectF clip = boundingRect;
+
+ ContextShadow* ctxShadow = ctx->contextShadow();
- if (hasShadow) {
- // TODO: when blur support is added, the clip will need to account
- // for the blur radius
+ if (ctxShadow->type != ContextShadow::NoShadow) {
qreal dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
- if (shadowSize.width() > 0)
- dx2 = shadowSize.width();
+ if (ctxShadow->offset.x() > 0)
+ dx2 = ctxShadow->offset.x();
else
- dx1 = -shadowSize.width();
- if (shadowSize.height() > 0)
- dy2 = shadowSize.height();
+ dx1 = -ctxShadow->offset.x();
+ if (ctxShadow->offset.y() > 0)
+ dy2 = ctxShadow->offset.y();
else
- dy1 = -shadowSize.height();
+ dy1 = -ctxShadow->offset.y();
// expand the clip rect to include the text shadow as well
clip.adjust(dx1, dx2, dy1, dy2);
+ clip.adjust(-ctxShadow->blurRadius, -ctxShadow->blurRadius, ctxShadow->blurRadius, ctxShadow->blurRadius);
}
p->save();
p->setClipRect(clip.toRect(), Qt::IntersectClip);
pt.setY(pt.y() - ascent);
- if (hasShadow) {
- p->save();
- p->setPen(QColor(shadowColor));
- p->translate(shadowSize.width(), shadowSize.height());
- line.draw(p, pt);
- p->restore();
+
+ if (ctxShadow->type != ContextShadow::NoShadow) {
+ ContextShadow* ctxShadow = ctx->contextShadow();
+ if (ctxShadow->type != ContextShadow::BlurShadow) {
+ p->save();
+ p->setPen(ctxShadow->color);
+ p->translate(ctxShadow->offset);
+ line.draw(p, pt);
+ p->restore();
+ } else {
+ QPainter* shadowPainter = ctxShadow->beginShadowLayer(p, boundingRect);
+ if (shadowPainter) {
+ // Since it will be blurred anyway, we don't care about render hints.
+ shadowPainter->setPen(ctxShadow->color);
+ line.draw(shadowPainter, pt);
+ ctxShadow->endShadowLayer(p);
+ }
+ }
}
p->setPen(textFillPen);
line.draw(p, pt);
@@ -169,16 +178,29 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
// See QWebPagePrivate::QWebPagePrivate() where the default path is set to Complex for Qt 4.6 and earlier.
- if (!isComplexText)
+ if (!isComplexText && !(ctx->textDrawingMode() & cTextStroke))
flags |= Qt::TextBypassShaping;
#endif
- if (hasShadow) {
- // TODO: text shadow blur support
- p->save();
- p->setPen(QColor(shadowColor));
- p->translate(shadowSize.width(), shadowSize.height());
- p->drawText(pt, string, flags, run.padding());
- p->restore();
+ if (ctx->contextShadow()->type != ContextShadow::NoShadow) {
+ ContextShadow* ctxShadow = ctx->contextShadow();
+ if (ctxShadow->type != ContextShadow::BlurShadow) {
+ p->save();
+ p->setPen(ctxShadow->color);
+ p->translate(ctxShadow->offset);
+ p->drawText(pt, string, flags, run.padding());
+ p->restore();
+ } else {
+ QFontMetrics fm(font);
+ QRectF boundingRect(point.x(), point.y() - fm.ascent(), fm.width(string), fm.height());
+ QPainter* shadowPainter = ctxShadow->beginShadowLayer(p, boundingRect);
+ if (shadowPainter) {
+ // Since it will be blurred anyway, we don't care about render hints.
+ shadowPainter->setFont(p->font());
+ shadowPainter->setPen(ctxShadow->color);
+ shadowPainter->drawText(pt, string, flags, run.padding());
+ ctxShadow->endShadowLayer(p);
+ }
+ }
}
if (ctx->textDrawingMode() & cTextStroke) {
QPainterPath path;
diff --git a/WebCore/platform/graphics/qt/GradientQt.cpp b/WebCore/platform/graphics/qt/GradientQt.cpp
index 1f05a15..72bb009 100644
--- a/WebCore/platform/graphics/qt/GradientQt.cpp
+++ b/WebCore/platform/graphics/qt/GradientQt.cpp
@@ -46,8 +46,15 @@ QGradient* Gradient::platformGradient()
if (m_gradient)
return m_gradient;
+ bool reversed = m_r0 > m_r1;
+
+ qreal innerRadius = reversed ? m_r1 : m_r0;
+ qreal outerRadius = reversed ? m_r0 : m_r1;
+ QPointF center = reversed ? m_p0 : m_p1;
+ QPointF focalPoint = reversed ? m_p1 : m_p0;
+
if (m_radial)
- m_gradient = new QRadialGradient(m_p1.x(), m_p1.y(), m_r1, m_p0.x(), m_p0.y());
+ m_gradient = new QRadialGradient(center, outerRadius, focalPoint);
else
m_gradient = new QLinearGradient(m_p0.x(), m_p0.y(), m_p1.x(), m_p1.y());
@@ -65,9 +72,19 @@ QGradient* Gradient::platformGradient()
lastStop = stopIterator->stop + lastStopDiff;
else
lastStop = stopIterator->stop;
- if (m_radial && m_r0)
- lastStop = m_r0 / m_r1 + lastStop * (1.0f - m_r0 / m_r1);
- m_gradient->setColorAt(qMin(lastStop, qreal(1.0f)), stopColor);
+
+ if (m_radial && !qFuzzyCompare(1 + outerRadius, qreal(1))) {
+ lastStop = lastStop * (1.0f - innerRadius / outerRadius);
+ if (!reversed)
+ lastStop += innerRadius / outerRadius;
+ }
+
+ qreal stopPosition = qMin(lastStop, qreal(1.0f));
+
+ if (m_radial && reversed)
+ stopPosition = 1 - stopPosition;
+
+ m_gradient->setColorAt(stopPosition, stopColor);
// Keep the lastStop as orginal value, since the following stopColor depend it
lastStop = stopIterator->stop;
++stopIterator;
diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
index d5e7b3f..7918378 100644
--- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
@@ -20,18 +20,14 @@
#include "GraphicsContext3D.h"
-#include "ArrayBufferView.h"
#include "WebGLObject.h"
#include "CanvasRenderingContext.h"
-#include "Float32Array.h"
#include "GraphicsContext.h"
#include "HTMLCanvasElement.h"
#include "HostWindow.h"
#include "ImageBuffer.h"
-#include "Int32Array.h"
#include "NotImplemented.h"
#include "QWebPageClient.h"
-#include "Uint8Array.h"
#include <QAbstractScrollArea>
#include <QGLContext>
#include <wtf/UnusedParam.h>
@@ -89,6 +85,7 @@ typedef void (APIENTRY* glGenFramebuffersType) (GLsizei, GLuint*);
typedef void (APIENTRY* glGenRenderbuffersType) (GLsizei, GLuint*);
typedef void (APIENTRY* glGetActiveAttribType) (GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*);
typedef void (APIENTRY* glGetActiveUniformType) (GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*);
+typedef void (APIENTRY* glGetAttachedShadersType) (GLuint, GLsizei, GLsizei*, GLuint*);
typedef GLint (APIENTRY* glGetAttribLocationType) (GLuint, const char*);
typedef void (APIENTRY* glGetBufferParameterivType) (GLenum, GLenum, GLint*);
typedef void (APIENTRY* glGetFramebufferAttachmentParameterivType) (GLenum, GLenum, GLenum, GLint* params);
@@ -187,6 +184,7 @@ public:
glGenRenderbuffersType genRenderbuffers;
glGetActiveAttribType getActiveAttrib;
glGetActiveUniformType getActiveUniform;
+ glGetAttachedShadersType getAttachedShaders;
glGetAttribLocationType getAttribLocation;
glGetBufferParameterivType getBufferParameteriv;
glGetFramebufferAttachmentParameterivType getFramebufferAttachmentParameteriv;
@@ -276,6 +274,18 @@ bool GraphicsContext3D::isGLES2Compliant() const
#endif
}
+// Even with underlying GLES2 driver, the below flags should still be set to
+// false if extentions exist (and they almost always do).
+bool GraphicsContext3D::isGLES2NPOTStrict() const
+{
+ return false;
+}
+
+bool GraphicsContext3D::isErrorGeneratedOnOutOfBoundsAccesses() const
+{
+ return false;
+}
+
GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow)
: m_attrs(attrs)
@@ -349,6 +359,7 @@ GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attribut
genRenderbuffers = GET_PROC_ADDRESS(glGenRenderbuffers);
getActiveAttrib = GET_PROC_ADDRESS(glGetActiveAttrib);
getActiveUniform = GET_PROC_ADDRESS(glGetActiveUniform);
+ getAttachedShaders = GET_PROC_ADDRESS(glGetAttachedShaders);
getAttribLocation = GET_PROC_ADDRESS(glGetAttribLocation);
getBufferParameteriv = GET_PROC_ADDRESS(glGetBufferParameteriv);
getFramebufferAttachmentParameteriv = GET_PROC_ADDRESS(glGetFramebufferAttachmentParameteriv);
@@ -582,7 +593,7 @@ void GraphicsContext3D::activeTexture(unsigned long texture)
m_internal->activeTexture(texture);
}
-void GraphicsContext3D::attachShader(PlatformGLObject program, PlatformGLObject shader)
+void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader)
{
ASSERT(program);
ASSERT(shader);
@@ -590,33 +601,44 @@ void GraphicsContext3D::attachShader(PlatformGLObject program, PlatformGLObject
m_internal->attachShader((GLuint) program, (GLuint) shader);
}
-void GraphicsContext3D::bindAttribLocation(PlatformGLObject program, unsigned long index, const String& name)
+void GraphicsContext3D::getAttachedShaders(Platform3DObject program, int maxCount, int* count, unsigned int* shaders)
+{
+ if (!program) {
+ synthesizeGLError(INVALID_VALUE);
+ return;
+ }
+
+ m_internal->m_glWidget->makeCurrent();
+ getAttachedShaders((GLuint) program, maxCount, count, shaders);
+}
+
+void GraphicsContext3D::bindAttribLocation(Platform3DObject program, unsigned long index, const String& name)
{
ASSERT(program);
m_internal->m_glWidget->makeCurrent();
m_internal->bindAttribLocation((GLuint) program, index, name.utf8().data());
}
-void GraphicsContext3D::bindBuffer(unsigned long target, PlatformGLObject buffer)
+void GraphicsContext3D::bindBuffer(unsigned long target, Platform3DObject buffer)
{
m_internal->m_glWidget->makeCurrent();
- m_internal->bindBuffer(target, (GLuint) buffer->object());
+ m_internal->bindBuffer(target, (GLuint) buffer);
}
-void GraphicsContext3D::bindFramebuffer(unsigned long target, PlatformGLObject buffer)
+void GraphicsContext3D::bindFramebuffer(unsigned long target, Platform3DObject buffer)
{
m_internal->m_glWidget->makeCurrent();
m_internal->m_currentFbo = buffer ? (GLuint) buffer : m_internal->m_mainFbo;
m_internal->bindFramebuffer(target, m_internal->m_currentFbo);
}
-void GraphicsContext3D::bindRenderbuffer(unsigned long target, PlatformGLObject renderbuffer)
+void GraphicsContext3D::bindRenderbuffer(unsigned long target, Platform3DObject renderbuffer)
{
m_internal->m_glWidget->makeCurrent();
m_internal->bindRenderbuffer(target, (GLuint) renderbuffer);
}
-void GraphicsContext3D::bindTexture(unsigned long target, PlatformGLObject texture)
+void GraphicsContext3D::bindTexture(unsigned long target, Platform3DObject texture)
{
m_internal->m_glWidget->makeCurrent();
glBindTexture(target, (GLuint) texture);
@@ -658,22 +680,16 @@ void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long
m_internal->bufferData(target, size, /* data */ 0, usage);
}
-void GraphicsContext3D::bufferData(unsigned long target, ArrayBufferView* array, unsigned long usage)
+void GraphicsContext3D::bufferData(unsigned long target, int size, const void* data, unsigned long usage)
{
- if (!array || !array->length())
- return;
-
m_internal->m_glWidget->makeCurrent();
- m_internal->bufferData(target, array->byteLength(), array->baseAddress(), usage);
+ m_internal->bufferData(target, size, data, usage);
}
-void GraphicsContext3D::bufferSubData(unsigned long target, long offset, ArrayBufferView* array)
+void GraphicsContext3D::bufferSubData(unsigned long target, long offset, int size, const void* data)
{
- if (!array || !array->length())
- return;
-
m_internal->m_glWidget->makeCurrent();
- m_internal->bufferSubData(target, offset, array->byteLength(), array->baseAddress());
+ m_internal->bufferSubData(target, offset, size, data);
}
unsigned long GraphicsContext3D::checkFramebufferStatus(unsigned long target)
@@ -716,7 +732,7 @@ void GraphicsContext3D::colorMask(bool red, bool green, bool blue, bool alpha)
glColorMask(red, green, blue, alpha);
}
-void GraphicsContext3D::compileShader(PlatformGLObject shader)
+void GraphicsContext3D::compileShader(Platform3DObject shader)
{
ASSERT(shader);
m_internal->m_glWidget->makeCurrent();
@@ -763,7 +779,7 @@ void GraphicsContext3D::depthRange(double zNear, double zFar)
#endif
}
-void GraphicsContext3D::detachShader(PlatformGLObject program, PlatformGLObject shader)
+void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader)
{
ASSERT(program);
ASSERT(shader);
@@ -819,13 +835,13 @@ void GraphicsContext3D::flush()
glFlush();
}
-void GraphicsContext3D::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, PlatformGLObject buffer)
+void GraphicsContext3D::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, Platform3DObject buffer)
{
m_internal->m_glWidget->makeCurrent();
m_internal->framebufferRenderbuffer(target, attachment, renderbuffertarget, (GLuint) buffer);
}
-void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, PlatformGLObject texture, long level)
+void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, Platform3DObject texture, long level)
{
m_internal->m_glWidget->makeCurrent();
m_internal->framebufferTexture2D(target, attachment, textarget, (GLuint) texture, level);
@@ -843,7 +859,7 @@ void GraphicsContext3D::generateMipmap(unsigned long target)
m_internal->generateMipmap(target);
}
-bool GraphicsContext3D::getActiveAttrib(PlatformGLObject program, unsigned long index, ActiveInfo& info)
+bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, unsigned long index, ActiveInfo& info)
{
if (!program) {
synthesizeGLError(INVALID_VALUE);
@@ -875,7 +891,7 @@ bool GraphicsContext3D::getActiveAttrib(PlatformGLObject program, unsigned long
return true;
}
-bool GraphicsContext3D::getActiveUniform(PlatformGLObject program, unsigned long index, ActiveInfo& info)
+bool GraphicsContext3D::getActiveUniform(Platform3DObject program, unsigned long index, ActiveInfo& info)
{
if (!program) {
synthesizeGLError(INVALID_VALUE);
@@ -907,7 +923,7 @@ bool GraphicsContext3D::getActiveUniform(PlatformGLObject program, unsigned long
return true;
}
-int GraphicsContext3D::getAttribLocation(PlatformGLObject program, const String& name)
+int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name)
{
if (!program)
return -1;
@@ -946,7 +962,7 @@ void GraphicsContext3D::hint(unsigned long target, unsigned long mode)
glHint(target, mode);
}
-bool GraphicsContext3D::isBuffer(PlatformGLObject buffer)
+bool GraphicsContext3D::isBuffer(Platform3DObject buffer)
{
if (!buffer)
return false;
@@ -961,7 +977,7 @@ bool GraphicsContext3D::isEnabled(unsigned long cap)
return glIsEnabled(cap);
}
-bool GraphicsContext3D::isFramebuffer(PlatformGLObject framebuffer)
+bool GraphicsContext3D::isFramebuffer(Platform3DObject framebuffer)
{
if (!framebuffer)
return false;
@@ -970,7 +986,7 @@ bool GraphicsContext3D::isFramebuffer(PlatformGLObject framebuffer)
return m_internal->isFramebuffer((GLuint) framebuffer);
}
-bool GraphicsContext3D::isProgram(PlatformGLObject program)
+bool GraphicsContext3D::isProgram(Platform3DObject program)
{
if (!program)
return false;
@@ -979,7 +995,7 @@ bool GraphicsContext3D::isProgram(PlatformGLObject program)
return m_internal->isProgram((GLuint) program);
}
-bool GraphicsContext3D::isRenderbuffer(PlatformGLObject renderbuffer)
+bool GraphicsContext3D::isRenderbuffer(Platform3DObject renderbuffer)
{
if (!renderbuffer)
return false;
@@ -988,7 +1004,7 @@ bool GraphicsContext3D::isRenderbuffer(PlatformGLObject renderbuffer)
return m_internal->isRenderbuffer((GLuint) renderbuffer);
}
-bool GraphicsContext3D::isShader(PlatformGLObject shader)
+bool GraphicsContext3D::isShader(Platform3DObject shader)
{
if (!shader)
return false;
@@ -997,7 +1013,7 @@ bool GraphicsContext3D::isShader(PlatformGLObject shader)
return m_internal->isShader((GLuint) shader);
}
-bool GraphicsContext3D::isTexture(PlatformGLObject texture)
+bool GraphicsContext3D::isTexture(Platform3DObject texture)
{
if (!texture)
return false;
@@ -1012,7 +1028,7 @@ void GraphicsContext3D::lineWidth(double width)
glLineWidth(static_cast<float>(width));
}
-void GraphicsContext3D::linkProgram(PlatformGLObject program)
+void GraphicsContext3D::linkProgram(Platform3DObject program)
{
ASSERT(program);
m_internal->m_glWidget->makeCurrent();
@@ -1065,7 +1081,7 @@ void GraphicsContext3D::scissor(long x, long y, unsigned long width, unsigned lo
glScissor(x, y, width, height);
}
-void GraphicsContext3D::shaderSource(PlatformGLObject shader, const String& source)
+void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& source)
{
ASSERT(shader);
@@ -1247,7 +1263,7 @@ void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* a
m_internal->uniformMatrix4fv(location, size, transpose, array);
}
-void GraphicsContext3D::useProgram(PlatformGLObject program)
+void GraphicsContext3D::useProgram(Platform3DObject program)
{
ASSERT(program);
@@ -1255,7 +1271,7 @@ void GraphicsContext3D::useProgram(PlatformGLObject program)
m_internal->useProgram((GLuint) program);
}
-void GraphicsContext3D::validateProgram(PlatformGLObject program)
+void GraphicsContext3D::validateProgram(Platform3DObject program)
{
ASSERT(program);
@@ -1353,13 +1369,13 @@ void GraphicsContext3D::getIntegerv(unsigned long paramName, int* value)
glGetIntegerv(paramName, value);
}
-void GraphicsContext3D::getProgramiv(PlatformGLObject program, unsigned long paramName, int* value)
+void GraphicsContext3D::getProgramiv(Platform3DObject program, unsigned long paramName, int* value)
{
m_internal->m_glWidget->makeCurrent();
m_internal->getProgramiv((GLuint) program, paramName, value);
}
-String GraphicsContext3D::getProgramInfoLog(PlatformGLObject program)
+String GraphicsContext3D::getProgramInfoLog(Platform3DObject program)
{
m_internal->m_glWidget->makeCurrent();
@@ -1386,14 +1402,14 @@ void GraphicsContext3D::getRenderbufferParameteriv(unsigned long target, unsigne
m_internal->getRenderbufferParameteriv(target, paramName, value);
}
-void GraphicsContext3D::getShaderiv(PlatformGLObject shader, unsigned long paramName, int* value)
+void GraphicsContext3D::getShaderiv(Platform3DObject shader, unsigned long paramName, int* value)
{
ASSERT(shader);
m_internal->m_glWidget->makeCurrent();
m_internal->getShaderiv((GLuint) shader, paramName, value);
}
-String GraphicsContext3D::getShaderInfoLog(PlatformGLObject shader)
+String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader)
{
m_internal->m_glWidget->makeCurrent();
@@ -1413,7 +1429,7 @@ String GraphicsContext3D::getShaderInfoLog(PlatformGLObject shader)
return result;
}
-String GraphicsContext3D::getShaderSource(PlatformGLObject shader)
+String GraphicsContext3D::getShaderSource(Platform3DObject shader)
{
m_internal->m_glWidget->makeCurrent();
@@ -1445,19 +1461,19 @@ void GraphicsContext3D::getTexParameteriv(unsigned long target, unsigned long pa
glGetTexParameteriv(target, paramName, value);
}
-void GraphicsContext3D::getUniformfv(PlatformGLObject program, long location, float* value)
+void GraphicsContext3D::getUniformfv(Platform3DObject program, long location, float* value)
{
m_internal->m_glWidget->makeCurrent();
m_internal->getUniformfv((GLuint) program, location, value);
}
-void GraphicsContext3D::getUniformiv(PlatformGLObject program, long location, int* value)
+void GraphicsContext3D::getUniformiv(Platform3DObject program, long location, int* value)
{
m_internal->m_glWidget->makeCurrent();
m_internal->getUniformiv((GLuint) program, location, value);
}
-long GraphicsContext3D::getUniformLocation(PlatformGLObject program, const String& name)
+long GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name)
{
ASSERT(program);
@@ -1621,7 +1637,7 @@ bool GraphicsContext3D::getImageData(Image* image,
return false;
AlphaOp neededAlphaOp = kAlphaDoNothing;
- if (!premultiplyAlpha && *hasAlphaChannel)
+ if (!premultiplyAlpha)
// FIXME: must fetch the image data before the premultiplication step
neededAlphaOp = kAlphaDoUnmultiply;
QImage nativeImage = nativePixmap->toImage().convertToFormat(QImage::Format_ARGB32);
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index 1632804..41c9759 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -209,6 +209,15 @@ public:
return shadow.type != ContextShadow::NoShadow;
}
+ QRectF clipBoundingRect() const
+ {
+#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
+ return painter->clipBoundingRect();
+#else
+ return painter->clipRegion().boundingRect();
+#endif
+ }
+
private:
QPainter* painter;
};
@@ -247,6 +256,9 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
// Make sure the context starts in sync with our state.
setPlatformFillColor(fillColor(), DeviceColorSpace);
setPlatformStrokeColor(strokeColor(), DeviceColorSpace);
+
+ // Make sure we start with the correct join mode.
+ setLineJoin(MiterJoin);
}
}
@@ -636,56 +648,50 @@ void GraphicsContext::fillRect(const FloatRect& rect)
return;
QPainter* p = m_data->p();
- FloatRect normalizedRect = rect.normalized();
-
- QRectF shadowDestRect;
- QImage* shadowImage = 0;
- QPainter* pShadow = 0;
-
- if (m_data->hasShadow()) {
- shadowImage = new QImage(roundedIntSize(normalizedRect.size()), QImage::Format_ARGB32_Premultiplied);
- pShadow = new QPainter(shadowImage);
- shadowDestRect = normalizedRect;
- shadowDestRect.translate(m_data->shadow.offset);
-
- pShadow->setCompositionMode(QPainter::CompositionMode_Source);
- pShadow->fillRect(shadowImage->rect(), m_data->shadow.color);
- pShadow->setCompositionMode(QPainter::CompositionMode_DestinationIn);
- }
+ QRectF normalizedRect = rect.normalized();
+ ContextShadow* shadow = contextShadow();
if (m_common->state.fillPattern) {
AffineTransform affine;
- FloatRect rectM(rect);
QBrush brush(m_common->state.fillPattern->createPlatformPattern(affine));
QPixmap* image = m_common->state.fillPattern->tileImage()->nativeImageForCurrentFrame();
-
- 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());
+ QPainter* shadowPainter = m_data->hasShadow() ? shadow->beginShadowLayer(p, normalizedRect) : 0;
+ if (shadowPainter) {
+ drawRepeatPattern(shadowPainter, image, normalizedRect, m_common->state.fillPattern->repeatX(), m_common->state.fillPattern->repeatY());
+ shadowPainter->setCompositionMode(QPainter::CompositionMode_SourceIn);
+ shadowPainter->fillRect(normalizedRect, shadow->color);
+ shadow->endShadowLayer(p);
}
drawRepeatPattern(p, image, normalizedRect, m_common->state.fillPattern->repeatX(), m_common->state.fillPattern->repeatY());
} else if (m_common->state.fillGradient) {
QBrush brush(*m_common->state.fillGradient->platformGradient());
brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
-
- if (m_data->hasShadow()) {
- pShadow->fillRect(shadowImage->rect(), brush);
- pShadow->end();
- p->drawImage(shadowDestRect, *shadowImage, shadowImage->rect());
+ QPainter* shadowPainter = m_data->hasShadow() ? shadow->beginShadowLayer(p, normalizedRect) : 0;
+ if (shadowPainter) {
+ shadowPainter->fillRect(normalizedRect, brush);
+ shadowPainter->setCompositionMode(QPainter::CompositionMode_SourceIn);
+ shadowPainter->fillRect(normalizedRect, shadow->color);
+ shadow->endShadowLayer(p);
}
p->fillRect(normalizedRect, brush);
} else {
if (m_data->hasShadow()) {
- pShadow->fillRect(shadowImage->rect(), p->brush());
- pShadow->end();
- p->drawImage(shadowDestRect, *shadowImage, shadowImage->rect());
+ if (shadow->type == ContextShadow::BlurShadow) {
+ QPainter* shadowPainter = shadow->beginShadowLayer(p, normalizedRect);
+ if (shadowPainter) {
+ shadowPainter->fillRect(normalizedRect, p->brush());
+ shadow->endShadowLayer(p);
+ }
+ } else {
+ // Solid rectangle fill with no blur shadow can be done faster
+ // without using the shadow layer at all.
+ QColor shadowColor = shadow->color;
+ shadowColor.setAlphaF(shadowColor.alphaF() * p->brush().color().alphaF());
+ p->fillRect(normalizedRect.translated(shadow->offset), shadowColor);
+ }
}
p->fillRect(normalizedRect, p->brush());
}
-
- delete shadowImage;
- delete pShadow;
}
@@ -696,11 +702,25 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
m_data->solidColor.setColor(color);
QPainter* p = m_data->p();
+ QRectF normalizedRect = rect.normalized();
- if (m_data->hasShadow())
- m_data->shadow.drawShadowRect(p, rect);
+ if (m_data->hasShadow()) {
+ ContextShadow* shadow = contextShadow();
- p->fillRect(rect, m_data->solidColor);
+ if (shadow->type != ContextShadow::BlurShadow) {
+ // We do not need any layer for simple shadow.
+ p->fillRect(normalizedRect.translated(shadow->offset), shadow->color);
+ } else {
+ QPainter* shadowPainter = shadow->beginShadowLayer(p, normalizedRect);
+ if (shadowPainter) {
+ shadowPainter->setCompositionMode(QPainter::CompositionMode_Source);
+ shadowPainter->fillRect(normalizedRect, shadow->color);
+ shadow->endShadowLayer(p);
+ }
+ }
+ }
+
+ p->fillRect(normalizedRect, m_data->solidColor);
}
void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
@@ -742,6 +762,11 @@ PlatformPath* GraphicsContext::currentPath()
return &m_data->currentPath;
}
+ContextShadow* GraphicsContext::contextShadow()
+{
+ return &m_data->shadow;
+}
+
void GraphicsContext::clip(const FloatRect& rect)
{
if (paintingDisabled())
@@ -893,7 +918,7 @@ void GraphicsContext::beginTransparencyLayer(float opacity)
w = device->width();
h = device->height();
- QRectF clip = p->clipPath().boundingRect();
+ QRectF clip = m_data->clipBoundingRect();
QRectF deviceClip = p->transform().mapRect(clip);
x = int(qBound(qreal(0), deviceClip.x(), (qreal)w));
y = int(qBound(qreal(0), deviceClip.y(), (qreal)h));
@@ -1056,7 +1081,7 @@ void GraphicsContext::clipOut(const Path& path)
QPainterPath newClip;
newClip.setFillRule(Qt::OddEvenFill);
if (p->hasClipping()) {
- newClip.addRect(p->clipRegion().boundingRect());
+ newClip.addRect(m_data->clipBoundingRect());
newClip.addPath(clippedOut);
p->setClipPath(newClip, Qt::IntersectClip);
} else {
@@ -1126,7 +1151,7 @@ void GraphicsContext::clipOut(const IntRect& rect)
QPainterPath newClip;
newClip.setFillRule(Qt::OddEvenFill);
if (p->hasClipping()) {
- newClip.addRect(p->clipRegion().boundingRect());
+ newClip.addRect(m_data->clipBoundingRect());
newClip.addRect(QRect(rect));
p->setClipPath(newClip, Qt::IntersectClip);
} else {
@@ -1148,7 +1173,7 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
QPainterPath newClip;
newClip.setFillRule(Qt::OddEvenFill);
if (p->hasClipping()) {
- newClip.addRect(p->clipRegion().boundingRect());
+ newClip.addRect(m_data->clipBoundingRect());
newClip.addEllipse(QRect(rect));
p->setClipPath(newClip, Qt::IntersectClip);
} else {
diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/WebCore/platform/graphics/qt/GraphicsLayerQt.h
index f81bd3d..4282e64 100644
--- a/WebCore/platform/graphics/qt/GraphicsLayerQt.h
+++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.h
@@ -20,6 +20,9 @@
#ifndef GraphicsLayerQt_h
#define GraphicsLayerQt_h
+#if ENABLE(3D_CANVAS)
+#include "GraphicsContext3D.h"
+#endif
#include "GraphicsLayer.h"
#include "GraphicsLayerClient.h"
diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index 11ca377..ee01222 100644
--- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -216,11 +216,11 @@ PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& i
const uchar* bits = image.bits();
#endif
- quint32* destRows = reinterpret_cast<quint32*>(&data[desty * rect.width() + destx]);
+ quint32* destRows = reinterpret_cast_ptr<quint32*>(&data[desty * rect.width() + destx]);
if (multiplied == Unmultiplied) {
for (int y = 0; y < numRows; ++y) {
- const quint32* scanLine = reinterpret_cast<const quint32*>(bits + (y + originy) * bytesPerLine);
+ const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine);
for (int x = 0; x < numColumns; x++) {
QRgb pixel = scanLine[x + originx];
int alpha = qAlpha(pixel);
@@ -242,7 +242,7 @@ PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& i
}
} else {
for (int y = 0; y < numRows; ++y) {
- const quint32* scanLine = reinterpret_cast<const quint32*>(bits + (y + originy) * bytesPerLine);
+ const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine);
for (int x = 0; x < numColumns; x++) {
QRgb pixel = scanLine[x + originx];
// Convert RGB to BGR.
@@ -318,11 +318,11 @@ void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint&
uchar* bits = image.bits();
const int bytesPerLine = image.bytesPerLine();
- const quint32* srcScanLine = reinterpret_cast<const quint32*>(source->data()->data()->data() + originy * srcBytesPerRow + originx * 4);
+ const quint32* srcScanLine = reinterpret_cast_ptr<const quint32*>(source->data()->data()->data() + originy * srcBytesPerRow + originx * 4);
if (multiplied == Unmultiplied) {
for (int y = 0; y < numRows; ++y) {
- quint32* destScanLine = reinterpret_cast<quint32*>(bits + y * bytesPerLine);
+ quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine);
for (int x = 0; x < numColumns; x++) {
// Premultiply and convert BGR to RGB.
quint32 pixel = srcScanLine[x];
@@ -332,7 +332,7 @@ void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint&
}
} else {
for (int y = 0; y < numRows; ++y) {
- quint32* destScanLine = reinterpret_cast<quint32*>(bits + y * bytesPerLine);
+ quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine);
for (int x = 0; x < numColumns; x++) {
// Convert BGR to RGB.
quint32 pixel = srcScanLine[x];
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
index 858cc44..02bb110 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -37,17 +37,18 @@
namespace WebCore {
-ImageDecoder* ImageDecoder::create(const SharedBuffer& data)
+ImageDecoder* ImageDecoder::create(const SharedBuffer& data, bool premultiplyAlpha)
{
// We need at least 4 bytes to figure out what kind of image we're dealing with.
if (data.size() < 4)
return 0;
- return new ImageDecoderQt;
+ return new ImageDecoderQt(premultiplyAlpha);
}
-ImageDecoderQt::ImageDecoderQt()
- : m_repetitionCount(cAnimationNone)
+ImageDecoderQt::ImageDecoderQt(bool premultiplyAlpha)
+ : ImageDecoder(premultiplyAlpha)
+ , m_repetitionCount(cAnimationNone)
{
}
@@ -104,10 +105,15 @@ size_t ImageDecoderQt::frameCount()
// we will have to parse everything...
if (!imageCount)
forceLoadEverything();
- else
+ else {
m_frameBufferCache.resize(imageCount);
- } else
+ for (size_t i = 0; i < m_frameBufferCache.size(); ++i)
+ m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha);
+ }
+ } else {
m_frameBufferCache.resize(1);
+ m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha);
+ }
}
return m_frameBufferCache.size();
@@ -236,6 +242,8 @@ void ImageDecoderQt::forceLoadEverything()
// Otherwise, we want to forget about
// the last attempt to decode a image.
m_frameBufferCache.resize(imageCount - 1);
+ for (size_t i = 0; i < m_frameBufferCache.size(); ++i)
+ m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha);
if (imageCount == 1)
setFailed();
}
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h
index ceef884..5014d53 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.h
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h
@@ -41,7 +41,7 @@ namespace WebCore {
class ImageDecoderQt : public ImageDecoder
{
public:
- ImageDecoderQt();
+ ImageDecoderQt(bool premultiplyAlpha);
~ImageDecoderQt();
virtual void setData(SharedBuffer* data, bool allDataReceived);
diff --git a/WebCore/platform/graphics/qt/TransparencyLayer.h b/WebCore/platform/graphics/qt/TransparencyLayer.h
index 0d9c121..1a614ac 100644
--- a/WebCore/platform/graphics/qt/TransparencyLayer.h
+++ b/WebCore/platform/graphics/qt/TransparencyLayer.h
@@ -52,7 +52,7 @@ struct TransparencyLayer : FastAllocBase {
offset = rect.topLeft();
pixmap.fill(Qt::transparent);
painter.begin(&pixmap);
- painter.setRenderHint(QPainter::Antialiasing, p->testRenderHint(QPainter::Antialiasing));
+ painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.translate(-offset);
painter.setPen(p->pen());
painter.setBrush(p->brush());
diff --git a/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h b/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
index 9fb6a8b..553f203 100644
--- a/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
+++ b/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
@@ -46,9 +46,10 @@ namespace WebCore {
// is that NativeImagePtr = NativeImageSkia, yet callers have SkBitmap.
class BitmapImageSingleFrameSkia : public Image {
public:
- // Creates a new Image, by copying the pixel values out of |bitmap|.
- // If creation failed, returns null.
- static PassRefPtr<BitmapImageSingleFrameSkia> create(const SkBitmap&);
+ // Creates a new Image from the given SkBitmap. If "copyPixels" is true, a
+ // deep copy is done. Otherwise, a shallow copy is done (pixel data is
+ // ref'ed).
+ static PassRefPtr<BitmapImageSingleFrameSkia> create(const SkBitmap&, bool copyPixels);
virtual bool isBitmapImage() const { return true; }
@@ -77,8 +78,8 @@ protected:
private:
NativeImageSkia m_nativeImage;
- // Use create().
- BitmapImageSingleFrameSkia() { }
+ // Creates a new Image from the given SkBitmap, using a shallow copy.
+ explicit BitmapImageSingleFrameSkia(const SkBitmap&);
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
index ee0a874..61039f2 100644
--- a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
@@ -31,6 +31,7 @@
#include "GraphicsContext3D.h"
#include "Image.h"
+#include "ImageSource.h"
#include "NativeImageSkia.h"
#include <algorithm>
@@ -43,27 +44,28 @@ bool GraphicsContext3D::getImageData(Image* image,
bool premultiplyAlpha,
Vector<uint8_t>& outputVector)
{
- if (!image)
+ if (!image || !image->data())
return false;
- NativeImageSkia* skiaImage = image->nativeImageForCurrentFrame();
- if (!skiaImage)
+ ImageSource decoder(false);
+ decoder.setData(image->data(), true);
+ if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
return false;
- SkBitmap::Config skiaConfig = skiaImage->config();
- // FIXME: must support more image configurations.
+ bool hasAlpha = decoder.frameHasAlphaAtIndex(0);
+ OwnPtr<NativeImageSkia> pixels(decoder.createFrameAtIndex(0));
+ if (!pixels.get() || !pixels->isDataComplete() || !pixels->width() || !pixels->height())
+ return false;
+ SkBitmap::Config skiaConfig = pixels->config();
if (skiaConfig != SkBitmap::kARGB_8888_Config)
return false;
- SkBitmap& skiaImageRef = *skiaImage;
+ SkBitmap& skiaImageRef = *pixels;
SkAutoLockPixels lock(skiaImageRef);
- int height = skiaImage->height();
- int rowBytes = skiaImage->rowBytes();
- ASSERT(rowBytes == skiaImage->width() * 4);
- uint8_t* pixels = reinterpret_cast<uint8_t*>(skiaImage->getPixels());
- outputVector.resize(rowBytes * height);
+ ASSERT(pixels->rowBytes() == pixels->width() * 4);
+ outputVector.resize(pixels->rowBytes() * pixels->height());
AlphaOp neededAlphaOp = kAlphaDoNothing;
- if (!premultiplyAlpha)
- // FIXME: must fetch the image data before the premultiplication step
- neededAlphaOp = kAlphaDoUnmultiply;
- return packPixels(pixels, kSourceFormatBGRA8, skiaImage->width(), height, 0,
+ if (hasAlpha && premultiplyAlpha)
+ neededAlphaOp = kAlphaDoPremultiply;
+ return packPixels(reinterpret_cast<const uint8_t*>(pixels->getPixels()),
+ kSourceFormatBGRA8, pixels->width(), pixels->height(), 0,
format, type, neededAlphaOp, outputVector.data());
}
diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index fe7f6ce..1b20e26 100644
--- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -323,7 +323,6 @@ void GraphicsContext::addPath(const Path& path)
{
if (paintingDisabled())
return;
- platformContext()->prepareForSoftwareDraw();
platformContext()->addPath(*path.platformPath());
}
@@ -331,7 +330,6 @@ void GraphicsContext::beginPath()
{
if (paintingDisabled())
return;
- platformContext()->prepareForSoftwareDraw();
platformContext()->beginPath();
}
@@ -783,7 +781,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
}
#if USE(GLES2_RENDERING)
- if (platformContext()->useGPU() && !m_common->state.fillPattern && !m_common->state.fillGradient) {
+ if (platformContext()->useGPU() && !m_common->state.fillPattern && !m_common->state.fillGradient && !platformContext()->getDrawLooper()) {
platformContext()->prepareForHardwareDraw();
platformContext()->gpuCanvas()->fillRect(rect);
return;
diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index a63eec5..9403406 100644
--- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -89,12 +89,13 @@ GraphicsContext* ImageBuffer::context() const
bool ImageBuffer::drawsUsingCopy() const
{
- return true;
+ return false;
}
PassRefPtr<Image> ImageBuffer::copyImage() const
{
- return BitmapImageSingleFrameSkia::create(*m_data.m_platformContext.bitmap());
+ m_context->platformContext()->syncSoftwareCanvas();
+ return BitmapImageSingleFrameSkia::create(*m_data.m_platformContext.bitmap(), true);
}
void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const
@@ -107,15 +108,15 @@ void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const
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);
+ RefPtr<Image> image = BitmapImageSingleFrameSkia::create(*m_data.m_platformContext.bitmap(), context == m_context);
+ context->drawImage(image.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);
+ RefPtr<Image> image = BitmapImageSingleFrameSkia::create(*m_data.m_platformContext.bitmap(), context == m_context);
+ image->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 b514b1a..1ff87cc 100644
--- a/WebCore/platform/graphics/skia/ImageSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -419,8 +419,9 @@ static void drawBitmapGLES2(GraphicsContext* ctxt, NativeImageSkia* bitmap, cons
ASSERT(bitmap->config() == SkBitmap::kARGB_8888_Config);
ASSERT(bitmap->rowBytes() == bitmap->width() * 4);
texture = gpuCanvas->createTexture(bitmap, GLES2Texture::BGRA8, bitmap->width(), bitmap->height());
- ASSERT(bitmap->pixelRef());
- texture->load(bitmap->pixelRef()->pixels());
+ SkAutoLockPixels lock(*bitmap);
+ ASSERT(bitmap->getPixels());
+ texture->load(bitmap->getPixels());
}
gpuCanvas->drawTexturedRect(texture, srcRect, dstRect, styleColorSpace, compositeOp);
}
@@ -516,11 +517,19 @@ void BitmapImageSingleFrameSkia::draw(GraphicsContext* ctxt,
WebCoreCompositeToSkiaComposite(compositeOp));
}
-PassRefPtr<BitmapImageSingleFrameSkia> BitmapImageSingleFrameSkia::create(const SkBitmap& bitmap)
+BitmapImageSingleFrameSkia::BitmapImageSingleFrameSkia(const SkBitmap& bitmap)
+ : m_nativeImage(bitmap)
{
- RefPtr<BitmapImageSingleFrameSkia> image(adoptRef(new BitmapImageSingleFrameSkia()));
- bitmap.copyTo(&image->m_nativeImage, bitmap.config());
- return image.release();
+}
+
+PassRefPtr<BitmapImageSingleFrameSkia> BitmapImageSingleFrameSkia::create(const SkBitmap& bitmap, bool copyPixels)
+{
+ if (copyPixels) {
+ SkBitmap temp;
+ bitmap.copyTo(&temp, bitmap.config());
+ return adoptRef(new BitmapImageSingleFrameSkia(temp));
+ }
+ return adoptRef(new BitmapImageSingleFrameSkia(bitmap));
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/NativeImageSkia.cpp b/WebCore/platform/graphics/skia/NativeImageSkia.cpp
index 007a32c..28e0758 100644
--- a/WebCore/platform/graphics/skia/NativeImageSkia.cpp
+++ b/WebCore/platform/graphics/skia/NativeImageSkia.cpp
@@ -46,6 +46,14 @@ NativeImageSkia::NativeImageSkia()
{
}
+NativeImageSkia::NativeImageSkia(const SkBitmap& other)
+ : SkBitmap(other),
+ m_isDataComplete(false),
+ m_lastRequestSize(0, 0),
+ m_resizeRequests(0)
+{
+}
+
int NativeImageSkia::decodedSize() const
{
return getSize() + m_resizedImage.getSize();
diff --git a/WebCore/platform/graphics/skia/NativeImageSkia.h b/WebCore/platform/graphics/skia/NativeImageSkia.h
index 0718836..e26a5ea 100644
--- a/WebCore/platform/graphics/skia/NativeImageSkia.h
+++ b/WebCore/platform/graphics/skia/NativeImageSkia.h
@@ -43,6 +43,11 @@ class NativeImageSkia : public SkBitmap {
public:
NativeImageSkia();
+ // This constructor does a shallow copy of the passed-in SkBitmap (ie., it
+ // references the same pixel data and bumps the refcount). Use only when
+ // you want sharing semantics.
+ explicit NativeImageSkia(const SkBitmap&);
+
// Returns the number of bytes of image data. This includes the cached
// resized version if there is one.
int decodedSize() const;
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index 1161224..b9de0a2 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -733,11 +733,7 @@ void PlatformContextSkia::prepareForSoftwareDraw() const
if (m_state->m_xferMode == SkXfermode::kSrcOver_Mode) {
// Last drawn on hardware; clear out the canvas.
- m_canvas->save();
- SkRect bounds = {0, 0, m_canvas->getDevice()->width(), m_canvas->getDevice()->height()};
- m_canvas->clipRect(bounds, SkRegion::kReplace_Op);
- m_canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
- m_canvas->restore();
+ m_canvas->getDevice()->eraseColor(0);
// Start compositing into the empty canvas.
m_backingStoreState = Mixed;
} else {
@@ -753,6 +749,8 @@ void PlatformContextSkia::prepareForSoftwareDraw() const
readbackHardwareToSoftware();
m_backingStoreState = Software;
}
+ } else if (m_backingStoreState == None) {
+ m_backingStoreState = Software;
}
}
diff --git a/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp b/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp
index 35839f5..02c5b99 100644
--- a/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp
+++ b/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp
@@ -27,12 +27,12 @@
namespace WebCore {
-FontCustomPlatformDataCairo::~FontCustomPlatformDataCairo()
+FontCustomPlatformData::~FontCustomPlatformData()
{
cairo_font_face_destroy(m_fontFace);
}
-FontPlatformData FontCustomPlatformDataCairo::fontPlatformData(int size, bool bold, bool italic)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic)
{
return FontPlatformData(m_fontFace, size, bold, italic);
}
@@ -42,7 +42,7 @@ static void releaseData(void* data)
static_cast<SharedBuffer*>(data)->deref();
}
-FontCustomPlatformDataCairo* createFontCustomPlatformData(SharedBuffer* buffer)
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
{
ASSERT_ARG(buffer, buffer);
@@ -55,7 +55,7 @@ FontCustomPlatformDataCairo* createFontCustomPlatformData(SharedBuffer* buffer)
static cairo_user_data_key_t bufferKey;
cairo_font_face_set_user_data(fontFace, &bufferKey, buffer, releaseData);
- return new FontCustomPlatformDataCairo(fontFace);
+ return new FontCustomPlatformData(fontFace);
}
bool FontCustomPlatformData::supportsFormat(const String& format)
diff --git a/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h b/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h
index 2dbea51..525957f 100644
--- a/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h
+++ b/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 Apple Computer, Inc.
+ * Copyright (C) 2010 Brent Fulgham <bfulgham@webkit.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -31,12 +32,12 @@ namespace WebCore {
class FontPlatformData;
class SharedBuffer;
-struct FontCustomPlatformDataCairo : Noncopyable {
- FontCustomPlatformDataCairo(cairo_font_face_t* fontFace)
+struct FontCustomPlatformData : Noncopyable {
+ FontCustomPlatformData(cairo_font_face_t* fontFace)
: m_fontFace(fontFace)
{
}
- ~FontCustomPlatformDataCairo();
+ ~FontCustomPlatformData();
FontPlatformData fontPlatformData(int size, bool bold, bool italic);
@@ -45,7 +46,7 @@ struct FontCustomPlatformDataCairo : Noncopyable {
cairo_font_face_t* m_fontFace;
};
-FontCustomPlatformDataCairo* createFontCustomPlatformData(SharedBuffer*);
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer*);
}
diff --git a/WebCore/platform/graphics/win/WKCACFLayer.cpp b/WebCore/platform/graphics/win/WKCACFLayer.cpp
index b5f3427..bbe5883 100644
--- a/WebCore/platform/graphics/win/WKCACFLayer.cpp
+++ b/WebCore/platform/graphics/win/WKCACFLayer.cpp
@@ -44,6 +44,24 @@ namespace WebCore {
using namespace std;
+#ifndef NDEBUG
+void WKCACFLayer::internalCheckLayerConsistency()
+{
+ ASSERT(layer());
+ size_t n = sublayerCount();
+ for (size_t i = 0; i < n; ++i) {
+ // This will ASSERT in internalSublayerAtIndex if this entry doesn't have proper user data
+ WKCACFLayer* sublayer = internalSublayerAtIndex(i);
+
+ // Make sure we don't have any null entries in the list
+ ASSERT(sublayer);
+
+ // Make sure the each layer has a corresponding CACFLayer
+ ASSERT(sublayer->layer());
+ }
+}
+#endif
+
static void displayCallback(CACFLayerRef layer, CGContextRef context)
{
ASSERT_ARG(layer, WKCACFLayer::layer(layer));
@@ -161,7 +179,14 @@ WKCACFLayer::~WKCACFLayer()
// Our superlayer should be holding a reference to us, so there should be no way for us to be destroyed while we still have a superlayer.
ASSERT(!superlayer());
+ // Get rid of the children so we don't have any dangling references around
+ removeAllSublayers();
+
+#ifndef NDEBUG
+ CACFLayerSetUserData(layer(), reinterpret_cast<void*>(0xDEADBEEF));
+#else
CACFLayerSetUserData(layer(), 0);
+#endif
CACFLayerSetDisplayCallback(layer(), 0);
}
@@ -192,10 +217,11 @@ void WKCACFLayer::addSublayer(PassRefPtr<WKCACFLayer> sublayer)
void WKCACFLayer::internalInsertSublayer(PassRefPtr<WKCACFLayer> sublayer, size_t index)
{
- index = min(index, sublayerCount());
+ index = min(index, sublayerCount() + 1);
sublayer->removeFromSuperlayer();
CACFLayerInsertSublayer(layer(), sublayer->layer(), index);
setNeedsCommit();
+ checkLayerConsistency();
}
void WKCACFLayer::insertSublayerAboveLayer(PassRefPtr<WKCACFLayer> sublayer, const WKCACFLayer* reference)
@@ -268,12 +294,14 @@ void WKCACFLayer::adoptSublayers(WKCACFLayer* source)
sublayers.append(source->internalSublayerAtIndex(i));
setSublayers(sublayers);
+ source->checkLayerConsistency();
}
void WKCACFLayer::removeFromSuperlayer()
{
WKCACFLayer* superlayer = this->superlayer();
CACFLayerRemoveFromSuperlayer(layer());
+ checkLayerConsistency();
if (superlayer)
superlayer->setNeedsCommit();
diff --git a/WebCore/platform/graphics/win/WKCACFLayer.h b/WebCore/platform/graphics/win/WKCACFLayer.h
index abc04c8..7243508 100644
--- a/WebCore/platform/graphics/win/WKCACFLayer.h
+++ b/WebCore/platform/graphics/win/WKCACFLayer.h
@@ -60,7 +60,11 @@ public:
BottomLeft, BottomRight, Resize, ResizeAspect, ResizeAspectFill };
static PassRefPtr<WKCACFLayer> create(LayerType);
- static WKCACFLayer* layer(CACFLayerRef layer) { return static_cast<WKCACFLayer*>(CACFLayerGetUserData(layer)); }
+ static WKCACFLayer* layer(CACFLayerRef layer)
+ {
+ ASSERT(CACFLayerGetUserData(layer) != reinterpret_cast<void*>(0xDEADBEEF));
+ return static_cast<WKCACFLayer*>(CACFLayerGetUserData(layer));
+ }
virtual ~WKCACFLayer();
@@ -133,7 +137,11 @@ public:
void adoptSublayers(WKCACFLayer* source);
void removeAllSublayers() { internalRemoveAllSublayers(); }
- void setSublayers(const Vector<RefPtr<WKCACFLayer> >& sublayers) { internalSetSublayers(sublayers); }
+ void setSublayers(const Vector<RefPtr<WKCACFLayer> >& sublayers)
+ {
+ internalSetSublayers(sublayers);
+ checkLayerConsistency();
+ }
void insertSublayer(PassRefPtr<WKCACFLayer> layer, size_t index) { internalInsertSublayer(layer, index); }
@@ -244,6 +252,13 @@ protected:
// This should only be called from removeFromSuperlayer.
void removeSublayer(const WKCACFLayer*);
+ void checkLayerConsistency()
+ {
+#ifndef NDEBUG
+ internalCheckLayerConsistency();
+#endif
+ }
+
// Methods to be overridden for sublayer and rendering management
virtual WKCACFLayer* internalSublayerAtIndex(int) const;
@@ -259,6 +274,10 @@ protected:
virtual void internalSetNeedsDisplay(const CGRect* dirtyRect);
#ifndef NDEBUG
+ virtual void internalCheckLayerConsistency();
+#endif
+
+#ifndef NDEBUG
// Print this layer and its children to the console
void printLayer(int indent) const;
#endif
diff --git a/WebCore/platform/graphics/win/WebTiledLayer.cpp b/WebCore/platform/graphics/win/WebTiledLayer.cpp
index d8c02d2..01dd6ae 100755
--- a/WebCore/platform/graphics/win/WebTiledLayer.cpp
+++ b/WebCore/platform/graphics/win/WebTiledLayer.cpp
@@ -36,6 +36,26 @@ namespace WebCore {
using namespace std;
+#ifndef NDEBUG
+void WebTiledLayer::internalCheckLayerConsistency()
+{
+ WKCACFLayer::internalCheckLayerConsistency();
+
+ // Additionally make sure the tiled parent is valid
+ CFArrayRef sublayers = CACFLayerGetSublayers(layer());
+
+ // Make sure there is a tile parent and it is the same as we remember
+ size_t n = CFArrayGetCount(sublayers);
+ ASSERT(n > 0);
+ const void* element = CFArrayGetValueAtIndex(sublayers, 0);
+ ASSERT(m_tileParent.get() == element);
+
+ // Make sure the tile parent doesn't have user data. If it does, it is probably
+ // a WKCACFLayer in the wrong place.
+ ASSERT(!layer(m_tileParent.get()));
+}
+#endif
+
void WebTiledLayer::tileDisplayCallback(CACFLayerRef layer, CGContextRef context)
{
static_cast<WebTiledLayer*>(CACFLayerGetUserData(layer))->drawTile(layer, context);
diff --git a/WebCore/platform/graphics/win/WebTiledLayer.h b/WebCore/platform/graphics/win/WebTiledLayer.h
index fdf0205..b8ae320 100644
--- a/WebCore/platform/graphics/win/WebTiledLayer.h
+++ b/WebCore/platform/graphics/win/WebTiledLayer.h
@@ -56,6 +56,10 @@ protected:
virtual void internalSetNeedsDisplay(const CGRect* dirtyRect);
+#ifndef NDEBUG
+ virtual void internalCheckLayerConsistency();
+#endif
+
private:
static void tileDisplayCallback(CACFLayerRef, CGContextRef);
void drawTile(CACFLayerRef, CGContextRef);
diff --git a/WebCore/platform/gtk/ClipboardGtk.cpp b/WebCore/platform/gtk/ClipboardGtk.cpp
index 21ebe4c..b2c32a4 100644
--- a/WebCore/platform/gtk/ClipboardGtk.cpp
+++ b/WebCore/platform/gtk/ClipboardGtk.cpp
@@ -330,7 +330,7 @@ void ClipboardGtk::declareAndWriteDragImage(Element* element, const KURL& url, c
if (!image || !image->isLoaded())
return;
- GRefPtr<GdkPixbuf> pixbuf = adoptGRef(image->image()->getGdkPixbuf());
+ PlatformRefPtr<GdkPixbuf> pixbuf = adoptPlatformRef(image->image()->getGdkPixbuf());
if (!pixbuf)
return;
diff --git a/WebCore/platform/gtk/CursorGtk.cpp b/WebCore/platform/gtk/CursorGtk.cpp
index 41b0800..d1f1293 100644
--- a/WebCore/platform/gtk/CursorGtk.cpp
+++ b/WebCore/platform/gtk/CursorGtk.cpp
@@ -37,25 +37,39 @@
namespace WebCore {
-static GRefPtr<GdkCursor> createNamedCursor(CustomCursorType cursorType)
+static GdkPixmap* createPixmapFromBits(const unsigned char* bits, const IntSize& size)
+{
+ cairo_surface_t* dataSurface = cairo_image_surface_create_for_data(const_cast<unsigned char*>(bits), CAIRO_FORMAT_A1, size.width(), size.height(), size.width() / 8);
+ GdkPixmap* pixmap = gdk_pixmap_new(0, size.width(), size.height(), 1);
+ cairo_t* cr = gdk_cairo_create(pixmap);
+ cairo_set_source_surface(cr, dataSurface, 0, 0);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(cr);
+ cairo_destroy(cr);
+ cairo_surface_destroy(dataSurface);
+ return pixmap;
+}
+
+static PlatformRefPtr<GdkCursor> createNamedCursor(CustomCursorType cursorType)
{
CustomCursor cursor = CustomCursors[cursorType];
- GRefPtr<GdkCursor> c = adoptGRef(gdk_cursor_new_from_name(gdk_display_get_default(), cursor.name));
+ PlatformRefPtr<GdkCursor> c = adoptPlatformRef(gdk_cursor_new_from_name(gdk_display_get_default(), cursor.name));
if (c)
return c;
const GdkColor fg = { 0, 0, 0, 0 };
const GdkColor bg = { 65535, 65535, 65535, 65535 };
- GRefPtr<GdkPixmap> source = adoptGRef(gdk_bitmap_create_from_data(0, cursor.bits, 32, 32));
- GRefPtr<GdkPixmap> mask = adoptGRef(gdk_bitmap_create_from_data(0, cursor.mask_bits, 32, 32));
- return adoptGRef(gdk_cursor_new_from_pixmap(source.get(), mask.get(), &fg, &bg, cursor.hot_x, cursor.hot_y));
+ IntSize cursorSize = IntSize(32, 32);
+ PlatformRefPtr<GdkPixmap> source = adoptPlatformRef(createPixmapFromBits(cursor.bits, cursorSize));
+ PlatformRefPtr<GdkPixmap> mask = adoptPlatformRef(createPixmapFromBits(cursor.mask_bits, cursorSize));
+ return adoptPlatformRef(gdk_cursor_new_from_pixmap(source.get(), mask.get(), &fg, &bg, cursor.hot_x, cursor.hot_y));
}
-static GRefPtr<GdkCursor> createCustomCursor(Image* image, const IntPoint& hotSpot)
+static PlatformRefPtr<GdkCursor> createCustomCursor(Image* image, const IntPoint& hotSpot)
{
IntPoint effectiveHotSpot = determineHotSpot(image, hotSpot);
- GRefPtr<GdkPixbuf> pixbuf = adoptGRef(image->getGdkPixbuf());
- return adoptGRef(gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf.get(), effectiveHotSpot.x(), effectiveHotSpot.y()));
+ PlatformRefPtr<GdkPixbuf> pixbuf = adoptPlatformRef(image->getGdkPixbuf());
+ return adoptPlatformRef(gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf.get(), effectiveHotSpot.x(), effectiveHotSpot.y()));
}
void Cursor::ensurePlatformCursor() const
@@ -69,77 +83,77 @@ void Cursor::ensurePlatformCursor() const
m_platformCursor = 0;
break;
case Cursor::Cross:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_CROSS));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_CROSS));
break;
case Cursor::Hand:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_HAND2));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_HAND2));
break;
case Cursor::IBeam:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_XTERM));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_XTERM));
break;
case Cursor::Wait:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_WATCH));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_WATCH));
break;
case Cursor::Help:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_QUESTION_ARROW));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_QUESTION_ARROW));
break;
case Cursor::Move:
case Cursor::MiddlePanning:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_FLEUR));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_FLEUR));
break;
case Cursor::EastResize:
case Cursor::EastPanning:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_RIGHT_SIDE));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_RIGHT_SIDE));
break;
case Cursor::NorthResize:
case Cursor::NorthPanning:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_TOP_SIDE));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_TOP_SIDE));
break;
case Cursor::NorthEastResize:
case Cursor::NorthEastPanning:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_LEFT_SIDE));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_LEFT_SIDE));
break;
case Cursor::NorthWestResize:
case Cursor::NorthWestPanning:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_TOP_LEFT_CORNER));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_TOP_LEFT_CORNER));
break;
case Cursor::SouthResize:
case Cursor::SouthPanning:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_BOTTOM_SIDE));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_BOTTOM_SIDE));
break;
case Cursor::SouthEastResize:
case Cursor::SouthEastPanning:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER));
break;
case Cursor::SouthWestResize:
case Cursor::SouthWestPanning:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_BOTTOM_LEFT_CORNER));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_BOTTOM_LEFT_CORNER));
break;
case Cursor::WestResize:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_LEFT_SIDE));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_LEFT_SIDE));
break;
case Cursor::NorthSouthResize:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_TOP_TEE));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_TOP_TEE));
break;
case Cursor::EastWestResize:
case Cursor::WestPanning:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_LEFT_SIDE));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_LEFT_SIDE));
break;
case Cursor::NorthEastSouthWestResize:
case Cursor::NorthWestSouthEastResize:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_SIZING));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_SIZING));
break;
case Cursor::ColumnResize:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW));
break;
case Cursor::RowResize:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW));
break;
case Cursor::VerticalText:
m_platformCursor = createNamedCursor(CustomCursorVerticalText);
break;
case Cursor::Cell:
- m_platformCursor = adoptGRef(gdk_cursor_new(GDK_PLUS));
+ m_platformCursor = adoptPlatformRef(gdk_cursor_new(GDK_PLUS));
break;
case Cursor::ContextMenu:
m_platformCursor = createNamedCursor(CustomCursorContextMenu);
diff --git a/WebCore/platform/gtk/CursorGtk.h b/WebCore/platform/gtk/CursorGtk.h
index 85aaefa..568919b 100644
--- a/WebCore/platform/gtk/CursorGtk.h
+++ b/WebCore/platform/gtk/CursorGtk.h
@@ -47,7 +47,7 @@
*/
/* MOZ_CURSOR_VERTICAL_TEXT */
-static const char moz_vertical_text_bits[] = {
+static const unsigned char moz_vertical_text_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x06, 0x60, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -60,7 +60,7 @@ static const char moz_vertical_text_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static const char moz_vertical_text_mask_bits[] = {
+static const unsigned char moz_vertical_text_mask_bits[] = {
0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x0f, 0xf0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00,
@@ -74,7 +74,7 @@ static const char moz_vertical_text_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* MOZ_CURSOR_CONTEXT_MENU */
-static const char moz_menu_bits[] = {
+static const unsigned char moz_menu_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
0x7c, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0xfd, 0x00, 0x00,
@@ -87,7 +87,7 @@ static const char moz_menu_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static const char moz_menu_mask_bits[] = {
+static const unsigned char moz_menu_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
0xfe, 0x00, 0x00, 0x00, 0xfe, 0xfd, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00,
@@ -101,7 +101,7 @@ static const char moz_menu_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* MOZ_CURSOR_COPY */
-static const char moz_copy_bits[] = {
+static const unsigned char moz_copy_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
0x7c, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00,
@@ -114,7 +114,7 @@ static const char moz_copy_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static const char moz_copy_mask_bits[] = {
+static const unsigned char moz_copy_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
0xfe, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00,
@@ -128,7 +128,7 @@ static const char moz_copy_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* MOZ_CURSOR_ALIAS */
-static const char moz_alias_bits[] = {
+static const unsigned char moz_alias_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
0x7c, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00,
@@ -141,7 +141,7 @@ static const char moz_alias_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static const char moz_alias_mask_bits[] = {
+static const unsigned char moz_alias_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
0xfe, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00,
@@ -155,7 +155,7 @@ static const char moz_alias_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* MOZ_CURSOR_ZOOM_IN */
-static const char moz_zoom_in_bits[] = {
+static const unsigned char moz_zoom_in_bits[] = {
0xf0, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00,
0x62, 0x04, 0x00, 0x00, 0x61, 0x08, 0x00, 0x00, 0xf9, 0x09, 0x00, 0x00,
0xf9, 0x09, 0x00, 0x00, 0x61, 0x08, 0x00, 0x00, 0x62, 0x04, 0x00, 0x00,
@@ -168,7 +168,7 @@ static const char moz_zoom_in_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static const char moz_zoom_in_mask_bits[] = {
+static const unsigned char moz_zoom_in_mask_bits[] = {
0xf0, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00,
0xfe, 0x07, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00,
@@ -182,7 +182,7 @@ static const char moz_zoom_in_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* MOZ_CURSOR_ZOOM_OUT */
-static const char moz_zoom_out_bits[] = {
+static const unsigned char moz_zoom_out_bits[] = {
0xf0, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00,
0x02, 0x04, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xf9, 0x09, 0x00, 0x00,
0xf9, 0x09, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00,
@@ -195,7 +195,7 @@ static const char moz_zoom_out_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static const char moz_zoom_out_mask_bits[] = {
+static const unsigned char moz_zoom_out_mask_bits[] = {
0xf0, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00,
0xfe, 0x07, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00,
@@ -209,7 +209,7 @@ static const char moz_zoom_out_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* MOZ_CURSOR_NOT_ALLOWED */
-static const char moz_not_allowed_bits[] = {
+static const unsigned char moz_not_allowed_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00,
0xf0, 0xf0, 0x00, 0x00, 0x38, 0xc0, 0x01, 0x00, 0x7c, 0x80, 0x03, 0x00,
0xec, 0x00, 0x03, 0x00, 0xce, 0x01, 0x07, 0x00, 0x86, 0x03, 0x06, 0x00,
@@ -222,7 +222,7 @@ static const char moz_not_allowed_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static const char moz_not_allowed_mask_bits[] = {
+static const unsigned char moz_not_allowed_mask_bits[] = {
0x80, 0x1f, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00,
0xf8, 0xff, 0x01, 0x00, 0xfc, 0xf0, 0x03, 0x00, 0xfe, 0xc0, 0x07, 0x00,
0xfe, 0x81, 0x07, 0x00, 0xff, 0x83, 0x0f, 0x00, 0xcf, 0x07, 0x0f, 0x00,
@@ -236,7 +236,7 @@ static const char moz_not_allowed_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* MOZ_CURSOR_SPINNING */
-static const char moz_spinning_bits[] = {
+static const unsigned char moz_spinning_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
0x7c, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00,
@@ -249,7 +249,7 @@ static const char moz_spinning_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static const char moz_spinning_mask_bits[] = {
+static const unsigned char moz_spinning_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
0xfe, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x3b, 0x00, 0x00,
@@ -263,7 +263,7 @@ static const char moz_spinning_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* MOZ_CURSOR_NONE */
-static const char moz_none_bits[] = {
+static const unsigned char moz_none_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -276,7 +276,7 @@ static const char moz_none_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static const char moz_none_mask_bits[] = {
+static const unsigned char moz_none_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -290,7 +290,7 @@ static const char moz_none_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* MOZ_CURSOR_HAND_GRAB */
-static const char moz_hand_grab_bits[] = {
+static const unsigned char moz_hand_grab_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
0x60, 0x39, 0x00, 0x00, 0x90, 0x49, 0x00, 0x00, 0x90, 0x49, 0x01, 0x00,
0x20, 0xc9, 0x02, 0x00, 0x20, 0x49, 0x02, 0x00, 0x58, 0x40, 0x02, 0x00,
@@ -303,7 +303,7 @@ static const char moz_hand_grab_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static const char moz_hand_grab_mask_bits[] = {
+static const unsigned char moz_hand_grab_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x60, 0x3f, 0x00, 0x00,
0xf0, 0x7f, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00, 0xf8, 0xff, 0x03, 0x00,
0xf0, 0xff, 0x07, 0x00, 0xf8, 0xff, 0x07, 0x00, 0xfc, 0xff, 0x07, 0x00,
@@ -317,7 +317,7 @@ static const char moz_hand_grab_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* MOZ_CURSOR_HAND_GRABBING */
-static const char moz_hand_grabbing_bits[] = {
+static const unsigned char moz_hand_grabbing_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xc0, 0x36, 0x00, 0x00, 0x20, 0xc9, 0x00, 0x00, 0x20, 0x40, 0x01, 0x00,
@@ -330,7 +330,7 @@ static const char moz_hand_grabbing_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static const char moz_hand_grabbing_mask_bits[] = {
+static const unsigned char moz_hand_grabbing_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x36, 0x00, 0x00,
0xe0, 0xff, 0x00, 0x00, 0xf0, 0xff, 0x01, 0x00, 0xf0, 0xff, 0x03, 0x00,
@@ -359,8 +359,8 @@ enum CustomCursorType {
typedef struct {
const char* name;
- const char* bits;
- const char* mask_bits;
+ const unsigned char* bits;
+ const unsigned char* mask_bits;
int hot_x;
int hot_y;
} CustomCursor;
@@ -374,7 +374,7 @@ static const CustomCursor CustomCursors[] = {
{ "zoom-out", moz_zoom_out_bits, moz_zoom_out_mask_bits, 6, 6 },
{ "vertical-text", moz_vertical_text_bits, moz_vertical_text_mask_bits, 8, 4 },
{ "dnd-no-drop", moz_not_allowed_bits, moz_not_allowed_mask_bits, 9, 9 },
- { "progress", moz_spinning_bits, moz_spinning_mask_bits, 2, 2},
+ { "left_ptr_watch", moz_spinning_bits, moz_spinning_mask_bits, 2, 2},
{ "none", moz_none_bits, moz_none_mask_bits, 0, 0 },
{ "grab", moz_hand_grab_bits, moz_hand_grab_mask_bits, 10, 10 },
{ "grabbing", moz_hand_grabbing_bits, moz_hand_grabbing_mask_bits, 10, 10 }
diff --git a/WebCore/platform/gtk/DataObjectGtk.h b/WebCore/platform/gtk/DataObjectGtk.h
index a7d8baf..6f7149c 100644
--- a/WebCore/platform/gtk/DataObjectGtk.h
+++ b/WebCore/platform/gtk/DataObjectGtk.h
@@ -73,8 +73,8 @@ private:
String m_text;
String m_markup;
Vector<KURL> m_uriList;
- GRefPtr<GdkPixbuf> m_image;
- GRefPtr<GdkDragContext> m_dragContext;
+ PlatformRefPtr<GdkPixbuf> m_image;
+ PlatformRefPtr<GdkDragContext> m_dragContext;
RefPtr<Range> m_range;
};
diff --git a/WebCore/platform/gtk/GRefPtrGtk.cpp b/WebCore/platform/gtk/GRefPtrGtk.cpp
index 6647b99..83129cc 100644
--- a/WebCore/platform/gtk/GRefPtrGtk.cpp
+++ b/WebCore/platform/gtk/GRefPtrGtk.cpp
@@ -25,27 +25,27 @@
namespace WTF {
-template <> GtkTargetList* refGPtr(GtkTargetList* ptr)
+template <> GtkTargetList* refPlatformPtr(GtkTargetList* ptr)
{
if (ptr)
gtk_target_list_ref(ptr);
return ptr;
}
-template <> void derefGPtr(GtkTargetList* ptr)
+template <> void derefPlatformPtr(GtkTargetList* ptr)
{
if (ptr)
gtk_target_list_unref(ptr);
}
-template <> GdkCursor* refGPtr(GdkCursor* ptr)
+template <> GdkCursor* refPlatformPtr(GdkCursor* ptr)
{
if (ptr)
gdk_cursor_ref(ptr);
return ptr;
}
-template <> void derefGPtr(GdkCursor* ptr)
+template <> void derefPlatformPtr(GdkCursor* ptr)
{
if (ptr)
gdk_cursor_unref(ptr);
diff --git a/WebCore/platform/gtk/GRefPtrGtk.h b/WebCore/platform/gtk/GRefPtrGtk.h
index 77941f5..ea1b089 100644
--- a/WebCore/platform/gtk/GRefPtrGtk.h
+++ b/WebCore/platform/gtk/GRefPtrGtk.h
@@ -28,11 +28,11 @@ typedef struct _GdkCursor GdkCursor;
namespace WTF {
-template <> GtkTargetList* refGPtr(GtkTargetList* ptr);
-template <> void derefGPtr(GtkTargetList* ptr);
+template <> GtkTargetList* refPlatformPtr(GtkTargetList* ptr);
+template <> void derefPlatformPtr(GtkTargetList* ptr);
-template <> GdkCursor* refGPtr(GdkCursor* ptr);
-template <> void derefGPtr(GdkCursor* ptr);
+template <> GdkCursor* refPlatformPtr(GdkCursor* ptr);
+template <> void derefPlatformPtr(GdkCursor* ptr);
}
diff --git a/WebCore/platform/gtk/GtkVersioning.h b/WebCore/platform/gtk/GtkVersioning.h
index 6b45228..34e6081 100644
--- a/WebCore/platform/gtk/GtkVersioning.h
+++ b/WebCore/platform/gtk/GtkVersioning.h
@@ -47,6 +47,8 @@
#define gtk_widget_set_visible(widget, FALSE) GTK_WIDGET_UNSET_FLAGS((widget), GTK_VISIBLE)
#define gtk_widget_set_window(widget, new_window) (widget)->window = (new_window)
#define gtk_widget_set_can_focus(widget, TRUE) GTK_WIDGET_SET_FLAGS((widget), GTK_CAN_FOCUS)
+#define gtk_widget_get_allocation(widget, alloc) (*(alloc) = (widget)->allocation)
+#define gtk_widget_set_allocation(widget, alloc) ((widget)->allocation = *(alloc))
#endif // GTK_CHECK_VERSION(2, 18, 0)
#if !GTK_CHECK_VERSION(2, 14, 0)
diff --git a/WebCore/platform/gtk/PasteboardGtk.cpp b/WebCore/platform/gtk/PasteboardGtk.cpp
index a0069cf..ddb9768 100644
--- a/WebCore/platform/gtk/PasteboardGtk.cpp
+++ b/WebCore/platform/gtk/PasteboardGtk.cpp
@@ -103,7 +103,7 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String&)
Image* image = cachedImage->image();
ASSERT(image);
- GRefPtr<GdkPixbuf> pixbuf = adoptGRef(image->getGdkPixbuf());
+ PlatformRefPtr<GdkPixbuf> pixbuf = adoptPlatformRef(image->getGdkPixbuf());
DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard);
dataObject->setImage(pixbuf.get());
m_helper->writeClipboardContents(clipboard);
diff --git a/WebCore/platform/gtk/PasteboardHelper.cpp b/WebCore/platform/gtk/PasteboardHelper.cpp
index 2babe91..95df25f 100644
--- a/WebCore/platform/gtk/PasteboardHelper.cpp
+++ b/WebCore/platform/gtk/PasteboardHelper.cpp
@@ -245,7 +245,7 @@ Vector<GdkAtom> PasteboardHelper::dropAtomsForContext(GtkWidget* widget, GdkDrag
dropAtoms.append(netscapeURLAtom);
// For images, try to find the most applicable image type.
- GRefPtr<GtkTargetList> list(gtk_target_list_new(0, 0));
+ PlatformRefPtr<GtkTargetList> list(gtk_target_list_new(0, 0));
gtk_target_list_add_image_targets(list.get(), getIdForTargetType(TargetTypeImage), TRUE);
GdkAtom atom = gtk_drag_dest_find_target(widget, context, list.get());
if (atom != GDK_NONE)
diff --git a/WebCore/platform/gtk/PopupMenuGtk.h b/WebCore/platform/gtk/PopupMenuGtk.h
index fb4e7dd..d63e6d9 100644
--- a/WebCore/platform/gtk/PopupMenuGtk.h
+++ b/WebCore/platform/gtk/PopupMenuGtk.h
@@ -58,7 +58,7 @@ private:
PopupMenuClient* m_popupClient;
IntPoint m_menuPosition;
- GRefPtr<GtkMenu> m_popup;
+ PlatformRefPtr<GtkMenu> m_popup;
HashMap<GtkWidget*, int> m_indexMap;
};
diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp
index 36fccf0..5019f35 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.cpp
+++ b/WebCore/platform/gtk/RenderThemeGtk.cpp
@@ -148,7 +148,7 @@ RenderThemeGtk::RenderThemeGtk()
, m_pauseButton(0)
, m_seekBackButton(0)
, m_seekForwardButton(0)
- , m_partsTable(adoptGRef(g_hash_table_new_full(0, 0, 0, g_free)))
+ , m_partsTable(adoptPlatformRef(g_hash_table_new_full(0, 0, 0, g_free)))
{
if (!mozGtkRefCount) {
moz_gtk_init();
@@ -317,7 +317,7 @@ static bool paintMozillaGtkWidget(const RenderThemeGtk* theme, GtkThemeWidgetTyp
else if (type == MOZ_GTK_CHECKBUTTON || type == MOZ_GTK_RADIOBUTTON)
flags = theme->isChecked(o);
- GRefPtr<GdkDrawable> drawable(i.context->gdkDrawable());
+ PlatformRefPtr<GdkDrawable> drawable(i.context->gdkDrawable());
GdkRectangle paintRect, clipRect;
if (drawable) {
AffineTransform ctm = i.context->getCTM();
@@ -342,7 +342,7 @@ static bool paintMozillaGtkWidget(const RenderThemeGtk* theme, GtkThemeWidgetTyp
// In some situations, like during print previews, this GraphicsContext is not
// backed by a GdkDrawable. In those situations, we render onto a pixmap and then
// copy the rendered data back to the GraphicsContext via Cairo.
- drawable = adoptGRef(gdk_pixmap_new(0, rect.width(), rect.height(), gdk_visual_get_depth(gdk_visual_get_system())));
+ drawable = adoptPlatformRef(gdk_pixmap_new(0, rect.width(), rect.height(), gdk_visual_get_depth(gdk_visual_get_system())));
paintRect = clipRect = IntRect(0, 0, rect.width(), rect.height());
}
diff --git a/WebCore/platform/gtk/RenderThemeGtk.h b/WebCore/platform/gtk/RenderThemeGtk.h
index 71338d4..b9c076d 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.h
+++ b/WebCore/platform/gtk/RenderThemeGtk.h
@@ -190,7 +190,7 @@ private:
RefPtr<Image> m_seekBackButton;
RefPtr<Image> m_seekForwardButton;
Page* m_page;
- GRefPtr<GHashTable> m_partsTable;
+ PlatformRefPtr<GHashTable> m_partsTable;
};
diff --git a/WebCore/platform/gtk/ScrollViewGtk.cpp b/WebCore/platform/gtk/ScrollViewGtk.cpp
index 871a0bf..565123c 100644
--- a/WebCore/platform/gtk/ScrollViewGtk.cpp
+++ b/WebCore/platform/gtk/ScrollViewGtk.cpp
@@ -65,12 +65,20 @@ void ScrollView::platformDestroy()
PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation)
{
- if (orientation == HorizontalScrollbar && m_horizontalAdjustment)
- return ScrollbarGtk::createScrollbar(this, orientation, m_horizontalAdjustment);
- else if (orientation == VerticalScrollbar && m_verticalAdjustment)
- return ScrollbarGtk::createScrollbar(this, orientation, m_verticalAdjustment);
- else
+ // If this is an interior frame scrollbar, we want to create a scrollbar without
+ // passing a GtkAdjustment. This will cause the Scrollbar to create a native GTK+
+ // scrollbar.
+ if (parent())
return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
+
+ // If this is the main frame, we want to create a Scrollbar that does no painting
+ // and defers to our GtkAdjustment for all of its state. Note that the GtkAdjustment
+ // may be null here.
+ if (orientation == HorizontalScrollbar)
+ return ScrollbarGtk::createScrollbar(this, orientation, m_horizontalAdjustment);
+
+ // VerticalScrollbar
+ return ScrollbarGtk::createScrollbar(this, orientation, m_verticalAdjustment);
}
/*
diff --git a/WebCore/platform/gtk/ScrollbarGtk.cpp b/WebCore/platform/gtk/ScrollbarGtk.cpp
index 3b86ec9..8a1c4fa 100644
--- a/WebCore/platform/gtk/ScrollbarGtk.cpp
+++ b/WebCore/platform/gtk/ScrollbarGtk.cpp
@@ -81,8 +81,10 @@ ScrollbarGtk::ScrollbarGtk(ScrollbarClient* client, ScrollbarOrientation orienta
: Scrollbar(client, orientation, RegularScrollbar)
, m_adjustment(adjustment)
{
- g_object_ref(m_adjustment);
- g_signal_connect(m_adjustment, "value-changed", G_CALLBACK(ScrollbarGtk::gtkValueChanged), this);
+ if (m_adjustment) {
+ g_object_ref(m_adjustment);
+ g_signal_connect(m_adjustment, "value-changed", G_CALLBACK(ScrollbarGtk::gtkValueChanged), this);
+ }
// We have nothing to show as we are solely operating on the GtkAdjustment
resize(0, 0);
@@ -104,8 +106,10 @@ void ScrollbarGtk::attachAdjustment(GtkAdjustment* adjustment)
m_adjustment = adjustment;
- g_object_ref(m_adjustment);
- g_signal_connect(m_adjustment, "value-changed", G_CALLBACK(ScrollbarGtk::gtkValueChanged), this);
+ if (m_adjustment) {
+ g_object_ref(m_adjustment);
+ g_signal_connect(m_adjustment, "value-changed", G_CALLBACK(ScrollbarGtk::gtkValueChanged), this);
+ }
updateThumbProportion();
updateThumbPosition();
@@ -156,12 +160,18 @@ void ScrollbarGtk::frameRectsChanged()
void ScrollbarGtk::updateThumbPosition()
{
+ if (!m_adjustment)
+ return;
+
if (gtk_adjustment_get_value(m_adjustment) != m_currentPos)
gtk_adjustment_set_value(m_adjustment, m_currentPos);
}
void ScrollbarGtk::updateThumbProportion()
{
+ if (!m_adjustment)
+ return;
+
gtk_adjustment_configure(m_adjustment,
gtk_adjustment_get_value(m_adjustment),
gtk_adjustment_get_lower(m_adjustment),
diff --git a/WebCore/platform/gtk/gtk2drawing.c b/WebCore/platform/gtk/gtk2drawing.c
index 80e2c2a..349bde0 100644
--- a/WebCore/platform/gtk/gtk2drawing.c
+++ b/WebCore/platform/gtk/gtk2drawing.c
@@ -732,6 +732,7 @@ ConvertGtkState(GtkWidgetState* state)
return GTK_STATE_NORMAL;
}
+#ifdef GTK_API_VERSION_2
static gint
TSOffsetStyleGCArray(GdkGC** gcs, gint xorigin, gint yorigin)
{
@@ -741,10 +742,12 @@ TSOffsetStyleGCArray(GdkGC** gcs, gint xorigin, gint yorigin)
gdk_gc_set_ts_origin(gcs[i], xorigin, yorigin);
return MOZ_GTK_SUCCESS;
}
+#endif
static gint
TSOffsetStyleGCs(GtkStyle* style, gint xorigin, gint yorigin)
{
+#ifdef GTK_API_VERSION_2
TSOffsetStyleGCArray(style->fg_gc, xorigin, yorigin);
TSOffsetStyleGCArray(style->bg_gc, xorigin, yorigin);
TSOffsetStyleGCArray(style->light_gc, xorigin, yorigin);
@@ -754,6 +757,7 @@ TSOffsetStyleGCs(GtkStyle* style, gint xorigin, gint yorigin)
TSOffsetStyleGCArray(style->base_gc, xorigin, yorigin);
gdk_gc_set_ts_origin(style->black_gc, xorigin, yorigin);
gdk_gc_set_ts_origin(style->white_gc, xorigin, yorigin);
+#endif
return MOZ_GTK_SUCCESS;
}
@@ -1094,6 +1098,34 @@ calculate_arrow_rect(GtkWidget* arrow, GdkRectangle* rect,
}
static gint
+moz_gtk_scrolled_window_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state)
+{
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkShadowType shadow_type = (state->active) ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+ GtkStyle* style;
+ GtkAllocation allocation;
+ GtkWidget* widget;
+
+ ensure_scrolled_window_widget();
+ widget = gParts->scrolledWindowWidget;
+
+ gtk_widget_get_allocation(widget, &allocation);
+ allocation.x = rect->x;
+ allocation.y = rect->y;
+ allocation.width = rect->width;
+ allocation.height = rect->height;
+ gtk_widget_set_allocation(widget, &allocation);
+
+ style = gtk_widget_get_style(widget);
+ TSOffsetStyleGCs(style, rect->x - 1, rect->y - 1);
+ gtk_paint_box(style, drawable, state_type, shadow_type, cliprect,
+ widget, "scrolled_window", rect->x - 1, rect->y - 1,
+ rect->width + 2, rect->height + 2);
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkWidgetState* state,
GtkScrollbarButtonFlags flags,
@@ -1124,11 +1156,7 @@ moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
to determine where it should paint rounded corners on the buttons.
We need to trick them into drawing the buttons the way we want them. */
-#if GTK_CHECK_VERSION(2, 18, 0)
gtk_widget_get_allocation(scrollbar, &allocation);
-#else
- allocation = scrollbar->allocation;
-#endif
allocation.x = rect->x;
allocation.y = rect->y;
allocation.width = rect->width;
@@ -1163,6 +1191,7 @@ moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
}
+ gtk_widget_set_allocation(scrollbar, &allocation);
style = gtk_widget_get_style(scrollbar);
TSOffsetStyleGCs(style, rect->x, rect->y);
@@ -1214,10 +1243,6 @@ moz_gtk_scrollbar_trough_paint(GtkThemeWidgetType widget,
style = gtk_widget_get_style(GTK_WIDGET(scrollbar));
TSOffsetStyleGCs(style, rect->x, rect->y);
- gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_ACTIVE,
- cliprect, rect->x, rect->y,
- rect->width, rect->height);
-
gtk_paint_box(style, drawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN, cliprect,
GTK_WIDGET(scrollbar), "trough", rect->x, rect->y,
rect->width, rect->height);
@@ -1557,8 +1582,17 @@ moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect,
if (theme_honors_transparency) {
g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
} else {
+#ifndef GTK_API_VERSION_2
+ cairo_t* cr = gdk_cairo_create(drawable);
+ gdk_cairo_set_source_color(cr, (const GdkColor*)&style->base[bg_state]);
+ cairo_pattern_set_extend (cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
+ gdk_cairo_rectangle(cr, cliprect);
+ cairo_fill(cr);
+ cairo_destroy(cr);
+#else
gdk_draw_rectangle(drawable, style->base_gc[bg_state], TRUE,
cliprect->x, cliprect->y, cliprect->width, cliprect->height);
+#endif
g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(FALSE));
}
@@ -3047,6 +3081,7 @@ moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics)
"trough_border", &metrics->trough_border,
"stepper_size", &metrics->stepper_size,
"stepper_spacing", &metrics->stepper_spacing,
+ "trough_under_steppers", &metrics->trough_under_steppers,
NULL);
metrics->min_slider_size = gtk_range_get_min_slider_size(GTK_RANGE(gParts->horizScrollbarWidget));
@@ -3109,6 +3144,9 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
return moz_gtk_scrollbar_thumb_paint(widget, drawable, rect,
cliprect, state, direction);
break;
+ case MOZ_GTK_SCROLLED_WINDOW:
+ return moz_gtk_scrolled_window_paint(drawable, rect, cliprect, state);
+ break;
case MOZ_GTK_SCALE_HORIZONTAL:
case MOZ_GTK_SCALE_VERTICAL:
return moz_gtk_scale_paint(drawable, rect, cliprect, state,
diff --git a/WebCore/platform/gtk/gtkdrawing.h b/WebCore/platform/gtk/gtkdrawing.h
index b5a7feb..9d06d5d 100644
--- a/WebCore/platform/gtk/gtkdrawing.h
+++ b/WebCore/platform/gtk/gtkdrawing.h
@@ -75,6 +75,7 @@ typedef struct {
gint stepper_size;
gint stepper_spacing;
gint min_slider_size;
+ gboolean trough_under_steppers;
} MozGtkScrollbarMetrics;
typedef struct _GtkThemeParts {
@@ -180,6 +181,8 @@ typedef enum {
/* Paints the slider (thumb) of a GtkScrollbar. */
MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL,
MOZ_GTK_SCROLLBAR_THUMB_VERTICAL,
+ /* Paints the background of a scrolled window */
+ MOZ_GTK_SCROLLED_WINDOW,
/* Paints a GtkScale. */
MOZ_GTK_SCALE_HORIZONTAL,
MOZ_GTK_SCALE_VERTICAL,
diff --git a/WebCore/platform/image-decoders/ImageDecoder.cpp b/WebCore/platform/image-decoders/ImageDecoder.cpp
index 1946596..d4518fe 100644
--- a/WebCore/platform/image-decoders/ImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/ImageDecoder.cpp
@@ -52,11 +52,15 @@ static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const
return bytesExtracted;
}
+<<<<<<< HEAD
#if !OS(ANDROID)
// This method requires BMPImageDecoder, PNGImageDecoder, ICOImageDecoder and
// JPEGDecoder, which aren't used on Android, and which don't all compile.
// TODO: Find a better fix.
ImageDecoder* ImageDecoder::create(const SharedBuffer& data)
+=======
+ImageDecoder* ImageDecoder::create(const SharedBuffer& data, bool premultiplyAlpha)
+>>>>>>> webkit.org at r66079
{
// We need at least 4 bytes to figure out what kind of image we're dealing
// with.
@@ -68,24 +72,24 @@ ImageDecoder* ImageDecoder::create(const SharedBuffer& data)
// GIFs begin with GIF8(7 or 9).
if (strncmp(contents, "GIF8", 4) == 0)
- return new GIFImageDecoder();
+ return new GIFImageDecoder(premultiplyAlpha);
// Test for PNG.
if (!memcmp(contents, "\x89\x50\x4E\x47", 4))
- return new PNGImageDecoder();
+ return new PNGImageDecoder(premultiplyAlpha);
// JPEG
if (!memcmp(contents, "\xFF\xD8\xFF", 3))
- return new JPEGImageDecoder();
+ return new JPEGImageDecoder(premultiplyAlpha);
// BMP
if (strncmp(contents, "BM", 2) == 0)
- return new BMPImageDecoder();
+ return new BMPImageDecoder(premultiplyAlpha);
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
// CURs begin with 2-byte 0 followed by 2-byte 2.
if (!memcmp(contents, "\x00\x00\x01\x00", 4) || !memcmp(contents, "\x00\x00\x02\x00", 4))
- return new ICOImageDecoder();
+ return new ICOImageDecoder(premultiplyAlpha);
// Give up. We don't know what the heck this is.
return 0;
@@ -99,6 +103,7 @@ RGBA32Buffer::RGBA32Buffer()
, m_status(FrameEmpty)
, m_duration(0)
, m_disposalMethod(DisposeNotSpecified)
+ , m_premultiplyAlpha(true)
{
}
@@ -112,6 +117,7 @@ RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other)
setStatus(other.status());
setDuration(other.duration());
setDisposalMethod(other.disposalMethod());
+ setPremultiplyAlpha(other.premultiplyAlpha());
return *this;
}
diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h
index f32536c..4012168 100644
--- a/WebCore/platform/image-decoders/ImageDecoder.h
+++ b/WebCore/platform/image-decoders/ImageDecoder.h
@@ -124,12 +124,14 @@ namespace WebCore {
FrameStatus status() const { return m_status; }
unsigned duration() const { return m_duration; }
FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
+ bool premultiplyAlpha() const { return m_premultiplyAlpha; }
void setHasAlpha(bool alpha);
void setRect(const IntRect& r) { m_rect = r; }
void setStatus(FrameStatus status);
void setDuration(unsigned duration) { m_duration = duration; }
void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
+ void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; }
inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
{
@@ -151,7 +153,7 @@ namespace WebCore {
#elif PLATFORM(QT)
m_image = m_pixmap.toImage();
m_pixmap = QPixmap();
- return reinterpret_cast<QRgb*>(m_image.scanLine(y)) + x;
+ return reinterpret_cast_ptr<QRgb*>(m_image.scanLine(y)) + x;
#else
return m_bytes.data() + (y * width()) + x;
#endif
@@ -159,11 +161,10 @@ namespace WebCore {
inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
{
- // We store this data pre-multiplied.
- if (a == 0)
+ if (m_premultiplyAlpha && !a)
*dest = 0;
else {
- if (a < 255) {
+ if (m_premultiplyAlpha && a < 255) {
float alphaPercent = a / 255.0f;
r = static_cast<unsigned>(r * alphaPercent);
g = static_cast<unsigned>(g * alphaPercent);
@@ -202,6 +203,9 @@ namespace WebCore {
FrameDisposalMethod m_disposalMethod;
// What to do with this frame's data when
// initializing the next frame.
+ bool m_premultiplyAlpha;
+ // Whether to premultiply alpha into R, G, B
+ // channels; by default it's true.
};
// The ImageDecoder class represents a base class for specific image format
@@ -215,8 +219,9 @@ namespace WebCore {
// m_maxNumPixels. (Not supported by all image decoders yet)
class ImageDecoder : public Noncopyable {
public:
- ImageDecoder()
+ ImageDecoder(bool premultiplyAlpha)
: m_scaled(false)
+ , m_premultiplyAlpha(premultiplyAlpha)
, m_sizeAvailable(false)
, m_maxNumPixels(-1)
, m_isAllDataReceived(false)
@@ -229,7 +234,7 @@ namespace WebCore {
// Factory function to create an ImageDecoder. Ports that subclass
// ImageDecoder can provide their own implementation of this to avoid
// needing to write a dedicated setData() implementation.
- static ImageDecoder* create(const SharedBuffer& data);
+ static ImageDecoder* create(const SharedBuffer& data, bool premultiplyAlpha);
// The the filename extension usually associated with an undecoded image
// of this type.
@@ -343,6 +348,7 @@ namespace WebCore {
bool m_scaled;
Vector<int> m_scaledColumns;
Vector<int> m_scaledRows;
+ bool m_premultiplyAlpha;
private:
// Some code paths compute the size of the image as "width * height * 4"
diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
index 901f60d..1c117a8 100644
--- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
@@ -40,8 +40,9 @@ namespace WebCore {
// don't pack).
static const size_t sizeOfFileHeader = 14;
-BMPImageDecoder::BMPImageDecoder()
- : m_decodedOffset(0)
+BMPImageDecoder::BMPImageDecoder(bool premultiplyAlpha)
+ : ImageDecoder(premultiplyAlpha)
+ , m_decodedOffset(0)
{
}
@@ -68,8 +69,10 @@ RGBA32Buffer* BMPImageDecoder::frameBufferAtIndex(size_t index)
if (index)
return 0;
- if (m_frameBufferCache.isEmpty())
+ if (m_frameBufferCache.isEmpty()) {
m_frameBufferCache.resize(1);
+ m_frameBufferCache.first().setPremultiplyAlpha(m_premultiplyAlpha);
+ }
RGBA32Buffer* buffer = &m_frameBufferCache.first();
if (buffer->status() != RGBA32Buffer::FrameComplete)
diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
index b08b32b..3996bf9 100644
--- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
+++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
@@ -39,7 +39,7 @@ namespace WebCore {
// This class decodes the BMP image format.
class BMPImageDecoder : public ImageDecoder {
public:
- BMPImageDecoder();
+ BMPImageDecoder(bool premultiplyAlpha);
// ImageDecoder
virtual String filenameExtension() const { return "bmp"; }
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
index ec16da7..a2397ee 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -29,8 +29,9 @@
namespace WebCore {
-GIFImageDecoder::GIFImageDecoder()
- : m_alreadyScannedThisDataForFrameCount(true)
+GIFImageDecoder::GIFImageDecoder(bool premultiplyAlpha)
+ : ImageDecoder(premultiplyAlpha)
+ , m_alreadyScannedThisDataForFrameCount(true)
, m_repetitionCount(cAnimationLoopOnce)
, m_readOffset(0)
{
@@ -83,6 +84,8 @@ size_t GIFImageDecoder::frameCount()
reader.read((const unsigned char*)m_data->data(), m_data->size(), GIFFrameCountQuery, static_cast<unsigned>(-1));
m_alreadyScannedThisDataForFrameCount = true;
m_frameBufferCache.resize(reader.images_count);
+ for (int i = 0; i < reader.images_count; ++i)
+ m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha);
}
return m_frameBufferCache.size();
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
index e0f8173..21c1c57 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
@@ -36,7 +36,7 @@ namespace WebCore {
// This class decodes the GIF image format.
class GIFImageDecoder : public ImageDecoder {
public:
- GIFImageDecoder();
+ GIFImageDecoder(bool premultiplyAlpha);
virtual ~GIFImageDecoder();
enum GIFQuery { GIFFullQuery, GIFSizeQuery, GIFFrameCountQuery };
diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
index d667795..453efd2 100644
--- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
@@ -44,8 +44,9 @@ namespace WebCore {
static const size_t sizeOfDirectory = 6;
static const size_t sizeOfDirEntry = 16;
-ICOImageDecoder::ICOImageDecoder()
- : m_decodedOffset(0)
+ICOImageDecoder::ICOImageDecoder(bool premultiplyAlpha)
+ : ImageDecoder(premultiplyAlpha)
+ , m_decodedOffset(0)
{
}
@@ -96,8 +97,11 @@ bool ICOImageDecoder::setSize(unsigned width, unsigned height)
size_t ICOImageDecoder::frameCount()
{
decode(0, true);
- if (m_frameBufferCache.isEmpty())
+ if (m_frameBufferCache.isEmpty()) {
m_frameBufferCache.resize(m_dirEntries.size());
+ for (size_t i = 0; i < m_dirEntries.size(); ++i)
+ m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha);
+ }
// CAUTION: We must not resize m_frameBufferCache again after this, as
// decodeAtIndex() may give a BMPImageReader a pointer to one of the
// entries.
@@ -197,7 +201,7 @@ bool ICOImageDecoder::decodeAtIndex(size_t index)
}
if (!m_pngDecoders[index]) {
- m_pngDecoders[index].set(new PNGImageDecoder());
+ m_pngDecoders[index].set(new PNGImageDecoder(m_premultiplyAlpha));
setDataForPNGDecoderAtIndex(index);
}
// Fail if the size the PNGImageDecoder calculated does not match the size
diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
index 48024a2..e2ee9e3 100644
--- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
+++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
@@ -40,7 +40,7 @@ namespace WebCore {
// This class decodes the ICO and CUR image formats.
class ICOImageDecoder : public ImageDecoder {
public:
- ICOImageDecoder();
+ ICOImageDecoder(bool premultiplyAlpha);
virtual ~ICOImageDecoder();
// ImageDecoder
diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
index 4911bc9..6c6c782 100644
--- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -361,7 +361,8 @@ void term_source(j_decompress_ptr jd)
src->decoder->decoder()->jpegComplete();
}
-JPEGImageDecoder::JPEGImageDecoder()
+JPEGImageDecoder::JPEGImageDecoder(bool premultiplyAlpha)
+ : ImageDecoder(premultiplyAlpha)
{
}
@@ -391,8 +392,10 @@ RGBA32Buffer* JPEGImageDecoder::frameBufferAtIndex(size_t index)
if (index)
return 0;
- if (m_frameBufferCache.isEmpty())
+ if (m_frameBufferCache.isEmpty()) {
m_frameBufferCache.resize(1);
+ m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha);
+ }
RGBA32Buffer& frame = m_frameBufferCache[0];
if (frame.status() != RGBA32Buffer::FrameComplete)
diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
index 43b35fd..5047019 100644
--- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
+++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
@@ -37,7 +37,7 @@ namespace WebCore {
// This class decodes the JPEG image format.
class JPEGImageDecoder : public ImageDecoder {
public:
- JPEGImageDecoder();
+ JPEGImageDecoder(bool premultiplyAlpha);
virtual ~JPEGImageDecoder();
// ImageDecoder
diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
index 8186f33..940e4c4 100644
--- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -169,8 +169,9 @@ private:
unsigned m_currentBufferSize;
};
-PNGImageDecoder::PNGImageDecoder()
- : m_doNothingOnFailure(false)
+PNGImageDecoder::PNGImageDecoder(bool premultiplyAlpha)
+ : ImageDecoder(premultiplyAlpha)
+ , m_doNothingOnFailure(false)
{
}
@@ -200,8 +201,10 @@ RGBA32Buffer* PNGImageDecoder::frameBufferAtIndex(size_t index)
if (index)
return 0;
- if (m_frameBufferCache.isEmpty())
+ if (m_frameBufferCache.isEmpty()) {
m_frameBufferCache.resize(1);
+ m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha);
+ }
RGBA32Buffer& frame = m_frameBufferCache[0];
if (frame.status() != RGBA32Buffer::FrameComplete)
diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
index 145fc4d..763b88f 100644
--- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h
+++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
@@ -36,7 +36,7 @@ namespace WebCore {
// This class decodes the PNG image format.
class PNGImageDecoder : public ImageDecoder {
public:
- PNGImageDecoder();
+ PNGImageDecoder(bool premultiplyAlpha);
virtual ~PNGImageDecoder();
// ImageDecoder
diff --git a/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp b/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
index 928524a..c7e2114 100644
--- a/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
+++ b/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
@@ -36,6 +36,7 @@ RGBA32Buffer::RGBA32Buffer()
: m_status(FrameEmpty)
, m_duration(0)
, m_disposalMethod(DisposeNotSpecified)
+ , m_premultiplyAlpha(true)
{
}
@@ -52,6 +53,7 @@ RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other)
setStatus(other.status());
setDuration(other.duration());
setDisposalMethod(other.disposalMethod());
+ setPremultiplyAlpha(other.premultiplyAlpha());
return *this;
}
diff --git a/WebCore/platform/mock/SpeechInputClientMock.cpp b/WebCore/platform/mock/SpeechInputClientMock.cpp
index c3d74d1..6b64942 100644
--- a/WebCore/platform/mock/SpeechInputClientMock.cpp
+++ b/WebCore/platform/mock/SpeechInputClientMock.cpp
@@ -50,7 +50,7 @@ void SpeechInputClientMock::setListener(SpeechInputListener* listener)
m_listener = listener;
}
-bool SpeechInputClientMock::startRecognition(int requestId)
+bool SpeechInputClientMock::startRecognition(int requestId, const IntRect&)
{
if (m_timer.isActive())
return false;
diff --git a/WebCore/platform/mock/SpeechInputClientMock.h b/WebCore/platform/mock/SpeechInputClientMock.h
index 7d5fda2..ce83d3b 100644
--- a/WebCore/platform/mock/SpeechInputClientMock.h
+++ b/WebCore/platform/mock/SpeechInputClientMock.h
@@ -50,7 +50,7 @@ public:
// SpeechInputClient methods.
void setListener(SpeechInputListener*);
- bool startRecognition(int);
+ bool startRecognition(int, const IntRect&);
void stopRecording(int);
void cancelRecognition(int);
diff --git a/WebCore/platform/network/BlobData.cpp b/WebCore/platform/network/BlobData.cpp
index bb256d0..21e8917 100644
--- a/WebCore/platform/network/BlobData.cpp
+++ b/WebCore/platform/network/BlobData.cpp
@@ -64,6 +64,11 @@ void BlobData::appendData(const CString& data)
m_items.append(BlobDataItem(data));
}
+void BlobData::appendData(const CString& data, long long offset, long long length)
+{
+ m_items.append(BlobDataItem(data, offset, length));
+}
+
void BlobData::appendFile(const String& path)
{
m_items.append(BlobDataItem(path));
diff --git a/WebCore/platform/network/BlobData.h b/WebCore/platform/network/BlobData.h
index 17cdfdd..13e3b9c 100644
--- a/WebCore/platform/network/BlobData.h
+++ b/WebCore/platform/network/BlobData.h
@@ -45,14 +45,15 @@ struct BlobDataItem {
// Default constructor.
BlobDataItem()
- : offset(0)
+ : type(Data)
+ , offset(0)
, length(toEndOfFile)
, expectedModificationTime(doNotCheckFileChange)
{
}
- // Constructor for String type.
- BlobDataItem(const CString& data)
+ // Constructor for String type (complete string).
+ explicit BlobDataItem(const CString& data)
: type(Data)
, data(data)
, offset(0)
@@ -61,8 +62,18 @@ struct BlobDataItem {
{
}
+ // Constructor for String type (partial string).
+ BlobDataItem(const CString& data, long long offset, long long length)
+ : type(Data)
+ , data(data)
+ , offset(offset)
+ , length(length)
+ , expectedModificationTime(doNotCheckFileChange)
+ {
+ }
+
// Constructor for File type (complete file).
- BlobDataItem(const String& path)
+ explicit BlobDataItem(const String& path)
: type(File)
, path(path)
, offset(0)
@@ -105,11 +116,8 @@ struct BlobDataItem {
// For Blob type.
KURL url;
- // For File and Blob type.
long long offset;
long long length;
-
- // For File type only.
double expectedModificationTime;
};
@@ -140,8 +148,14 @@ public:
void appendBlob(const KURL&, long long offset, long long length);
private:
+ friend class BlobRegistryImpl;
+ friend class BlobStorageData;
+
BlobData() { }
+ // This is only exposed to BlobStorageData.
+ void appendData(const CString&, long long offset, long long length);
+
String m_contentType;
String m_contentDisposition;
BlobDataItemList m_items;
diff --git a/WebCore/platform/network/BlobRegistry.h b/WebCore/platform/network/BlobRegistry.h
index fcd7b1c..7e64233 100644
--- a/WebCore/platform/network/BlobRegistry.h
+++ b/WebCore/platform/network/BlobRegistry.h
@@ -38,6 +38,7 @@
namespace WebCore {
class BlobData;
+class BlobRegistry;
class KURL;
class ResourceError;
class ResourceHandle;
@@ -45,17 +46,23 @@ class ResourceHandleClient;
class ResourceRequest;
class ResourceResponse;
+// Returns a single instance of BlobRegistry.
+BlobRegistry& blobRegistry();
+
// BlobRegistry is not thread-safe. It should only be called from main thread.
class BlobRegistry {
public:
- static BlobRegistry& instance();
-
+ // Registers a blob URL referring to the specified blob data.
virtual void registerBlobURL(const KURL&, PassOwnPtr<BlobData>) = 0;
+
+ // Registers a blob URL referring to the blob data identified by the specified srcURL.
virtual void registerBlobURL(const KURL&, const KURL& srcURL) = 0;
+
virtual void unregisterBlobURL(const KURL&) = 0;
virtual PassRefPtr<ResourceHandle> createResourceHandle(const ResourceRequest&, ResourceHandleClient*) = 0;
virtual bool loadResourceSynchronously(const ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>& data) = 0;
+protected:
virtual ~BlobRegistry() { }
};
diff --git a/WebCore/platform/network/BlobRegistryImpl.cpp b/WebCore/platform/network/BlobRegistryImpl.cpp
index bbbb8f0..ee872e6 100644
--- a/WebCore/platform/network/BlobRegistryImpl.cpp
+++ b/WebCore/platform/network/BlobRegistryImpl.cpp
@@ -32,9 +32,6 @@
#include "BlobRegistryImpl.h"
-#include "FileStream.h"
-#include "FileStreamProxy.h"
-#include "FileSystem.h"
#include "ResourceError.h"
#include "ResourceHandle.h"
#include "ResourceLoader.h"
@@ -45,6 +42,15 @@
namespace WebCore {
+#if !PLATFORM(CHROMIUM)
+BlobRegistry& blobRegistry()
+{
+ ASSERT(isMainThread());
+ DEFINE_STATIC_LOCAL(BlobRegistryImpl, instance, ());
+ return instance;
+}
+#endif
+
bool BlobRegistryImpl::shouldLoadResource(const ResourceRequest& request) const
{
// If the resource is not fetched using the GET method, bail out.
@@ -72,30 +78,23 @@ bool BlobRegistryImpl::loadResourceSynchronously(const ResourceRequest& request,
return false;
}
-BlobRegistry& BlobRegistry::instance()
-{
- ASSERT(isMainThread());
- DEFINE_STATIC_LOCAL(BlobRegistryImpl, instance, ());
- return instance;
-}
-
-void BlobRegistryImpl::appendStorageItems(BlobStorageData* blobStorageData, const BlobStorageDataItemList& items)
+void BlobRegistryImpl::appendStorageItems(BlobStorageData* blobStorageData, const BlobDataItemList& items)
{
- for (BlobStorageDataItemList::const_iterator iter = items.begin(); iter != items.end(); ++iter) {
- if (iter->type == BlobStorageDataItem::Data)
- blobStorageData->appendData(iter->data, iter->offset, iter->length);
+ for (BlobDataItemList::const_iterator iter = items.begin(); iter != items.end(); ++iter) {
+ if (iter->type == BlobDataItem::Data)
+ blobStorageData->m_data.appendData(iter->data, iter->offset, iter->length);
else {
- ASSERT(iter->type == BlobStorageDataItem::File);
- blobStorageData->appendFile(iter->path, iter->offset, iter->length, iter->expectedModificationTime);
+ ASSERT(iter->type == BlobDataItem::File);
+ blobStorageData->m_data.appendFile(iter->path, iter->offset, iter->length, iter->expectedModificationTime);
}
}
}
-void BlobRegistryImpl::appendStorageItems(BlobStorageData* blobStorageData, const BlobStorageDataItemList& items, long long offset, long long length)
+void BlobRegistryImpl::appendStorageItems(BlobStorageData* blobStorageData, const BlobDataItemList& items, long long offset, long long length)
{
ASSERT(length != BlobDataItem::toEndOfFile);
- BlobStorageDataItemList::const_iterator iter = items.begin();
+ BlobDataItemList::const_iterator iter = items.begin();
if (offset) {
for (; iter != items.end(); ++iter) {
if (offset >= iter->length)
@@ -108,12 +107,13 @@ void BlobRegistryImpl::appendStorageItems(BlobStorageData* blobStorageData, cons
for (; iter != items.end() && length > 0; ++iter) {
long long currentLength = iter->length - offset;
long long newLength = currentLength > length ? length : currentLength;
- if (iter->type == BlobStorageDataItem::Data)
- blobStorageData->appendData(iter->data, iter->offset + offset, newLength);
+ if (iter->type == BlobDataItem::Data)
+ blobStorageData->m_data.appendData(iter->data, iter->offset + offset, newLength);
else {
- ASSERT(iter->type == BlobStorageDataItem::File);
- blobStorageData->appendFile(iter->path, iter->offset + offset, newLength, iter->expectedModificationTime);
+ ASSERT(iter->type == BlobDataItem::File);
+ blobStorageData->m_data.appendFile(iter->path, iter->offset + offset, newLength, iter->expectedModificationTime);
}
+ length -= newLength;
offset = 0;
}
}
@@ -122,17 +122,20 @@ void BlobRegistryImpl::registerBlobURL(const KURL& url, PassOwnPtr<BlobData> blo
{
ASSERT(isMainThread());
- RefPtr<BlobStorageData> blobStorageData = BlobStorageData::create();
- blobStorageData->setContentType(blobData->contentType());
- blobStorageData->setContentDisposition(blobData->contentDisposition());
+ RefPtr<BlobStorageData> blobStorageData = BlobStorageData::create(blobData->contentType(), blobData->contentDisposition());
+
+ // The blob data is stored in the "canonical" way. That is, it only contains a list of Data and File items.
+ // 1) The Data item is denoted by the raw data and the range.
+ // 2) The File item is denoted by the file path, the range and the expected modification time.
+ // All the Blob items in the passing blob data are resolved and expanded into a set of Data and File items.
for (BlobDataItemList::const_iterator iter = blobData->items().begin(); iter != blobData->items().end(); ++iter) {
switch (iter->type) {
case BlobDataItem::Data:
- blobStorageData->appendData(iter->data, 0, iter->data.length());
+ blobStorageData->m_data.appendData(iter->data, 0, iter->data.length());
break;
case BlobDataItem::File:
- blobStorageData->appendFile(iter->path, iter->offset, iter->length, iter->expectedModificationTime);
+ blobStorageData->m_data.appendFile(iter->path, iter->offset, iter->length, iter->expectedModificationTime);
break;
case BlobDataItem::Blob:
if (m_blobs.contains(iter->url.string()))
@@ -141,7 +144,6 @@ void BlobRegistryImpl::registerBlobURL(const KURL& url, PassOwnPtr<BlobData> blo
}
}
-
m_blobs.set(url.string(), blobStorageData);
}
@@ -154,9 +156,7 @@ void BlobRegistryImpl::registerBlobURL(const KURL& url, const KURL& srcURL)
if (!src)
return;
- RefPtr<BlobStorageData> blobStorageData = BlobStorageData::create();
- blobStorageData->setContentType(src->contentType());
- blobStorageData->setContentDisposition(src->contentDisposition());
+ RefPtr<BlobStorageData> blobStorageData = BlobStorageData::create(src->contentType(), src->contentDisposition());
appendStorageItems(blobStorageData.get(), src->items());
m_blobs.set(url.string(), blobStorageData);
diff --git a/WebCore/platform/network/BlobRegistryImpl.h b/WebCore/platform/network/BlobRegistryImpl.h
index 42693bc..f616664 100644
--- a/WebCore/platform/network/BlobRegistryImpl.h
+++ b/WebCore/platform/network/BlobRegistryImpl.h
@@ -63,8 +63,8 @@ public:
private:
bool shouldLoadResource(const ResourceRequest& request) const;
- void appendStorageItems(BlobStorageData*, const BlobStorageDataItemList&);
- void appendStorageItems(BlobStorageData*, const BlobStorageDataItemList&, long long offset, long long length);
+ void appendStorageItems(BlobStorageData*, const BlobDataItemList&);
+ void appendStorageItems(BlobStorageData*, const BlobDataItemList&, long long offset, long long length);
HashMap<String, RefPtr<BlobStorageData> > m_blobs;
};
diff --git a/WebCore/platform/network/BlobResourceHandle.cpp b/WebCore/platform/network/BlobResourceHandle.cpp
new file mode 100644
index 0000000..63335f6
--- /dev/null
+++ b/WebCore/platform/network/BlobResourceHandle.cpp
@@ -0,0 +1,589 @@
+/*
+ * 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"
+
+#if ENABLE(BLOB)
+
+#include "BlobResourceHandle.h"
+
+#include "AsyncFileStream.h"
+#include "BlobRegistryImpl.h"
+#include "FileStream.h"
+#include "FileSystem.h"
+#include "HTTPParsers.h"
+#include "KURL.h"
+#include "ResourceError.h"
+#include "ResourceLoader.h"
+#include "ResourceRequest.h"
+#include "ResourceResponse.h"
+
+namespace WebCore {
+
+static const unsigned bufferSize = 1024;
+static const int maxVectorLength = 0x7fffffff;
+static const long long positionNotSpecified = -1;
+
+static const int httpOK = 200;
+static const int httpPartialContent = 206;
+static const int httpNotAllowed = 403;
+static const int httpNotFound = 404;
+static const int httpRequestedRangeNotSatisfiable = 416;
+static const int httpInternalError = 500;
+static const char* httpOKText = "OK";
+static const char* httpPartialContentText = "Partial Content";
+static const char* httpNotAllowedText = "Not Allowed";
+static const char* httpNotFoundText = "Not Found";
+static const char* httpRequestedRangeNotSatisfiableText = "Requested Range Not Satisfiable";
+static const char* httpInternalErrorText = "Internal Server Error";
+
+static const int notFoundError = 1;
+static const int securityError = 2;
+static const int rangeError = 3;
+static const int notReadableError = 4;
+
+///////////////////////////////////////////////////////////////////////////////
+// BlobResourceSynchronousLoader
+
+namespace {
+
+class BlobResourceSynchronousLoader : public ResourceHandleClient {
+public:
+ BlobResourceSynchronousLoader(ResourceError&, ResourceResponse&, Vector<char>&);
+
+ virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);
+ virtual void didReceiveData(ResourceHandle*, const char*, int, int /*lengthReceived*/);
+ virtual void didFinishLoading(ResourceHandle*);
+ virtual void didFail(ResourceHandle*, const ResourceError&);
+
+private:
+ ResourceError& m_error;
+ ResourceResponse& m_response;
+ Vector<char>& m_data;
+};
+
+BlobResourceSynchronousLoader::BlobResourceSynchronousLoader(ResourceError& error, ResourceResponse& response, Vector<char>& data)
+ : m_error(error)
+ , m_response(response)
+ , m_data(data)
+{
+}
+
+void BlobResourceSynchronousLoader::didReceiveResponse(ResourceHandle* handle, const ResourceResponse& response)
+{
+ // We cannot handle the size that is more than maximum integer.
+ const int intMaxForLength = 0x7fffffff;
+ if (response.expectedContentLength() > intMaxForLength) {
+ m_error = ResourceError(String(), notReadableError, response.url(), String());
+ return;
+ }
+
+ m_response = response;
+
+ // Read all the data.
+ m_data.resize(static_cast<size_t>(response.expectedContentLength()));
+ static_cast<BlobResourceHandle*>(handle)->readSync(m_data.data(), static_cast<int>(m_data.size()));
+}
+
+void BlobResourceSynchronousLoader::didReceiveData(ResourceHandle*, const char*, int, int)
+{
+}
+
+void BlobResourceSynchronousLoader::didFinishLoading(ResourceHandle*)
+{
+}
+
+void BlobResourceSynchronousLoader::didFail(ResourceHandle*, const ResourceError& error)
+{
+ m_error = error;
+}
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BlobResourceHandle
+
+// static
+void BlobResourceHandle::loadResourceSynchronously(PassRefPtr<BlobStorageData> blobData, const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
+{
+ BlobResourceSynchronousLoader loader(error, response, data);
+ RefPtr<BlobResourceHandle> handle = BlobResourceHandle::create(blobData, request, &loader, false);
+ handle->start();
+}
+
+static void delayedStart(void* context)
+{
+ static_cast<BlobResourceHandle*>(context)->start();
+}
+
+BlobResourceHandle::BlobResourceHandle(PassRefPtr<BlobStorageData> blobData, const ResourceRequest& request, ResourceHandleClient* client, bool async)
+ : ResourceHandle(request, client, false, false)
+ , m_blobData(blobData)
+ , m_async(async)
+ , m_errorCode(0)
+ , m_aborted(false)
+ , m_rangeOffset(positionNotSpecified)
+ , m_rangeEnd(positionNotSpecified)
+ , m_rangeSuffixLength(positionNotSpecified)
+ , m_totalRemainingSize(0)
+ , m_currentItemReadSize(0)
+ , m_sizeItemCount(0)
+ , m_readItemCount(0)
+ , m_fileOpened(false)
+{
+ if (m_async) {
+ m_asyncStream = adoptRef(client->createAsyncFileStream(this));
+ callOnMainThread(delayedStart, this);
+ } else
+ m_stream = FileStream::create();
+}
+
+BlobResourceHandle::~BlobResourceHandle()
+{
+ if (m_async) {
+ if (m_asyncStream)
+ m_asyncStream->stop();
+ } else {
+ if (m_stream)
+ m_stream->stop();
+ }
+}
+
+void BlobResourceHandle::cancel()
+{
+ if (m_async) {
+ if (m_asyncStream) {
+ m_asyncStream->stop();
+ m_asyncStream = 0;
+ }
+ }
+
+ m_aborted = true;
+}
+
+void BlobResourceHandle::start()
+{
+ // Do not continue if the request is aborted or an error occurs.
+ if (m_aborted || m_errorCode)
+ return;
+
+ // If the blob data is not found, fail now.
+ if (!m_blobData) {
+ m_errorCode = notFoundError;
+ notifyResponse();
+ return;
+ }
+
+ // Parse the "Range" header we care about.
+ String range = firstRequest().httpHeaderField("Range");
+ if (!range.isEmpty() && !parseRange(range, m_rangeOffset, m_rangeEnd, m_rangeSuffixLength)) {
+ m_errorCode = rangeError;
+ notifyResponse();
+ return;
+ }
+
+ if (m_async)
+ getSizeForNext();
+ else {
+ for (size_t i = 0; i < m_blobData->items().size() && !m_aborted && !m_errorCode; ++i)
+ getSizeForNext();
+ notifyResponse();
+ }
+}
+
+void BlobResourceHandle::getSizeForNext()
+{
+ // Do we finish validating and counting size for all items?
+ if (m_sizeItemCount >= m_blobData->items().size()) {
+ seek();
+
+ // Start reading if in asynchronous mode.
+ if (m_async) {
+ notifyResponse();
+ m_buffer.resize(bufferSize);
+ readAsync();
+ }
+ return;
+ }
+
+ const BlobDataItem& item = m_blobData->items().at(m_sizeItemCount);
+ switch (item.type) {
+ case BlobDataItem::Data:
+ didGetSize(item.length);
+ break;
+ case BlobDataItem::File:
+ if (m_async)
+ m_asyncStream->getSize(item.path, item.expectedModificationTime);
+ else
+ didGetSize(m_stream->getSize(item.path, item.expectedModificationTime));
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+
+void BlobResourceHandle::didGetSize(long long size)
+{
+ // Do not continue if the request is aborted or an error occurs.
+ if (m_aborted || m_errorCode)
+ return;
+
+ // If the size is -1, it means the file has been moved or changed. Fail now.
+ if (size == -1) {
+ m_errorCode = notFoundError;
+ notifyResponse();
+ return;
+ }
+
+ // The size passed back is the size of the whole file. If the underlying item is a sliced file, we need to use the slice length.
+ const BlobDataItem& item = m_blobData->items().at(m_sizeItemCount);
+ if (item.type == BlobDataItem::File && item.length != BlobDataItem::toEndOfFile)
+ size = item.length;
+
+ // Cache the size.
+ m_itemLengthList.append(size);
+
+ // Count the size.
+ m_totalRemainingSize += size;
+ m_sizeItemCount++;
+
+ // Continue with the next item.
+ getSizeForNext();
+}
+
+void BlobResourceHandle::seek()
+{
+ // Convert from the suffix length to the range.
+ if (m_rangeSuffixLength != positionNotSpecified) {
+ m_rangeOffset = m_totalRemainingSize - m_rangeSuffixLength;
+ m_rangeEnd = m_rangeOffset + m_rangeSuffixLength - 1;
+ }
+
+ // Bail out if the range is not provided.
+ if (m_rangeOffset == positionNotSpecified)
+ return;
+
+ // Skip the initial items that are not in the range.
+ long long offset = m_rangeOffset;
+ for (m_readItemCount = 0; m_readItemCount < m_blobData->items().size() && offset >= m_itemLengthList[m_readItemCount]; ++m_readItemCount)
+ offset -= m_itemLengthList[m_readItemCount];
+
+ // Set the offset that need to jump to for the first item in the range.
+ m_currentItemReadSize = offset;
+
+ // Adjust the total remaining size in order not to go beyond the range.
+ if (m_rangeEnd != positionNotSpecified) {
+ long long rangeSize = m_rangeEnd - m_rangeOffset + 1;
+ if (m_totalRemainingSize > rangeSize)
+ m_totalRemainingSize = rangeSize;
+ } else
+ m_totalRemainingSize -= m_rangeOffset;
+}
+
+int BlobResourceHandle::readSync(char* buf, int length)
+{
+ ASSERT(!m_async);
+
+ int offset = 0;
+ int remaining = length;
+ while (remaining) {
+ // Do not continue if the request is aborted or an error occurs.
+ if (m_aborted || m_errorCode)
+ break;
+
+ // If there is no more remaining data to read, we are done.
+ if (!m_totalRemainingSize || m_readItemCount >= m_blobData->items().size())
+ break;
+
+ const BlobDataItem& item = m_blobData->items().at(m_readItemCount);
+ int bytesRead = 0;
+ if (item.type == BlobDataItem::Data)
+ bytesRead = readDataSync(item, buf + offset, remaining);
+ else if (item.type == BlobDataItem::File)
+ bytesRead = readFileSync(item, buf + offset, remaining);
+ else
+ ASSERT_NOT_REACHED();
+
+ if (bytesRead > 0) {
+ offset += bytesRead;
+ remaining -= bytesRead;
+ }
+ }
+
+ int result;
+ if (m_aborted || m_errorCode)
+ result = -1;
+ else
+ result = length - remaining;
+
+ notifyReceiveData(buf, result);
+ if (!result)
+ notifyFinish();
+
+ return result;
+}
+
+int BlobResourceHandle::readDataSync(const BlobDataItem& item, char* buf, int length)
+{
+ ASSERT(!m_async);
+
+ long long remaining = item.length - m_currentItemReadSize;
+ int bytesToRead = (length > remaining) ? static_cast<int>(remaining) : length;
+ if (bytesToRead > m_totalRemainingSize)
+ bytesToRead = static_cast<int>(m_totalRemainingSize);
+ memcpy(buf, item.data.data() + item.offset + m_currentItemReadSize, bytesToRead);
+ m_totalRemainingSize -= bytesToRead;
+
+ m_currentItemReadSize += bytesToRead;
+ if (m_currentItemReadSize == item.length) {
+ m_readItemCount++;
+ m_currentItemReadSize = 0;
+ }
+
+ return bytesToRead;
+}
+
+int BlobResourceHandle::readFileSync(const BlobDataItem& item, char* buf, int length)
+{
+ ASSERT(!m_async);
+
+ if (!m_fileOpened) {
+ long long bytesToRead = m_itemLengthList[m_readItemCount] - m_currentItemReadSize;
+ if (bytesToRead > m_totalRemainingSize)
+ bytesToRead = m_totalRemainingSize;
+ bool success = m_stream->openForRead(item.path, item.offset + m_currentItemReadSize, bytesToRead);
+ m_currentItemReadSize = 0;
+ if (!success) {
+ m_errorCode = notReadableError;
+ return 0;
+ }
+
+ m_fileOpened = true;
+ }
+
+ int bytesRead = m_stream->read(buf, length);
+ if (bytesRead < 0) {
+ m_errorCode = notReadableError;
+ return 0;
+ }
+ if (!bytesRead) {
+ m_stream->close();
+ m_fileOpened = false;
+ m_readItemCount++;
+ } else
+ m_totalRemainingSize -= bytesRead;
+
+ return bytesRead;
+}
+
+void BlobResourceHandle::readAsync()
+{
+ ASSERT(m_async);
+
+ // Do not continue if the request is aborted or an error occurs.
+ if (m_aborted || m_errorCode)
+ return;
+
+ // If there is no more remaining data to read, we are done.
+ if (!m_totalRemainingSize || m_readItemCount >= m_blobData->items().size()) {
+ notifyFinish();
+ return;
+ }
+
+ const BlobDataItem& item = m_blobData->items().at(m_readItemCount);
+ if (item.type == BlobDataItem::Data)
+ readDataAsync(item);
+ else if (item.type == BlobDataItem::File)
+ readFileAsync(item);
+ else
+ ASSERT_NOT_REACHED();
+}
+
+void BlobResourceHandle::readDataAsync(const BlobDataItem& item)
+{
+ ASSERT(m_async);
+
+ long long bytesToRead = item.length - m_currentItemReadSize;
+ if (bytesToRead > m_totalRemainingSize)
+ bytesToRead = m_totalRemainingSize;
+ consumeData(item.data.data() + item.offset + m_currentItemReadSize, static_cast<int>(bytesToRead));
+ m_currentItemReadSize = 0;
+}
+
+void BlobResourceHandle::readFileAsync(const BlobDataItem& item)
+{
+ ASSERT(m_async);
+
+ if (m_fileOpened) {
+ m_asyncStream->read(m_buffer.data(), m_buffer.size());
+ return;
+ }
+
+ long long bytesToRead = m_itemLengthList[m_readItemCount] - m_currentItemReadSize;
+ if (bytesToRead > m_totalRemainingSize)
+ bytesToRead = static_cast<int>(m_totalRemainingSize);
+ m_asyncStream->openForRead(item.path, item.offset + m_currentItemReadSize, bytesToRead);
+ m_fileOpened = true;
+ m_currentItemReadSize = 0;
+}
+
+void BlobResourceHandle::didOpen(bool success)
+{
+ ASSERT(m_async);
+
+ if (!success) {
+ failed(notReadableError);
+ return;
+ }
+
+ // Continue the reading.
+ readAsync();
+}
+
+void BlobResourceHandle::didRead(int bytesRead)
+{
+ consumeData(m_buffer.data(), bytesRead);
+}
+
+void BlobResourceHandle::consumeData(const char* data, int bytesRead)
+{
+ ASSERT(m_async);
+
+ m_totalRemainingSize -= bytesRead;
+
+ // Notify the client.
+ if (bytesRead)
+ notifyReceiveData(data, bytesRead);
+
+ if (m_fileOpened) {
+ // When the current item is a file item, the reading is completed only if bytesRead is 0.
+ if (!bytesRead) {
+ // Close the file.
+ m_fileOpened = false;
+ m_asyncStream->close();
+
+ // Move to the next item.
+ m_readItemCount++;
+ }
+ } else {
+ // Otherwise, we read the current text item as a whole and move to the next item.
+ m_readItemCount++;
+ }
+
+ // Continue the reading.
+ readAsync();
+}
+
+void BlobResourceHandle::failed(int errorCode)
+{
+ ASSERT(m_async);
+
+ // Notify the client.
+ notifyFail(errorCode);
+
+ // Close the file if needed.
+ if (m_fileOpened) {
+ m_fileOpened = false;
+ m_asyncStream->close();
+ }
+}
+
+void BlobResourceHandle::notifyResponse()
+{
+ if (!client())
+ return;
+
+ if (m_errorCode) {
+ notifyResponseOnError();
+ notifyFinish();
+ } else
+ notifyResponseOnSuccess();
+}
+
+void BlobResourceHandle::notifyResponseOnSuccess()
+{
+ bool isRangeRequest = m_rangeOffset != positionNotSpecified;
+ ResourceResponse response(firstRequest().url(), m_blobData->contentType(), m_totalRemainingSize, String(), String());
+ response.setExpectedContentLength(m_totalRemainingSize);
+ response.setHTTPStatusCode(isRangeRequest ? httpPartialContent : httpOK);
+ response.setHTTPStatusText(isRangeRequest ? httpPartialContentText : httpOKText);
+ if (!m_blobData->contentDisposition().isEmpty())
+ response.setHTTPHeaderField("Content-Disposition", m_blobData->contentDisposition());
+ client()->didReceiveResponse(this, response);
+}
+
+void BlobResourceHandle::notifyResponseOnError()
+{
+ ASSERT(m_errorCode);
+
+ ResourceResponse response(firstRequest().url(), String(), 0, String(), String());
+ switch (m_errorCode) {
+ case rangeError:
+ response.setHTTPStatusCode(httpRequestedRangeNotSatisfiable);
+ response.setHTTPStatusText(httpRequestedRangeNotSatisfiableText);
+ break;
+ case notFoundError:
+ response.setHTTPStatusCode(httpNotFound);
+ response.setHTTPStatusText(httpNotFoundText);
+ break;
+ case securityError:
+ response.setHTTPStatusCode(httpNotAllowed);
+ response.setHTTPStatusText(httpNotAllowedText);
+ break;
+ default:
+ response.setHTTPStatusCode(httpInternalError);
+ response.setHTTPStatusText(httpInternalErrorText);
+ break;
+ }
+ client()->didReceiveResponse(this, response);
+}
+
+void BlobResourceHandle::notifyReceiveData(const char* data, int bytesRead)
+{
+ if (client())
+ client()->didReceiveData(this, data, bytesRead, bytesRead);
+}
+
+void BlobResourceHandle::notifyFail(int errorCode)
+{
+ if (client())
+ client()->didFail(this, ResourceError(String(), errorCode, firstRequest().url(), String()));
+}
+
+void BlobResourceHandle::notifyFinish()
+{
+ if (client())
+ client()->didFinishLoading(this);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(BLOB)
+
diff --git a/WebCore/platform/network/BlobResourceHandle.h b/WebCore/platform/network/BlobResourceHandle.h
new file mode 100644
index 0000000..b2a0854
--- /dev/null
+++ b/WebCore/platform/network/BlobResourceHandle.h
@@ -0,0 +1,116 @@
+/*
+ * 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 BlobResourceHandle_h
+#define BlobResourceHandle_h
+
+#if ENABLE(BLOB)
+
+#include "FileStreamClient.h"
+#include "PlatformString.h"
+#include "ResourceHandle.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class AsyncFileStream;
+class BlobDataItem;
+class BlobStorageData;
+class FileStream;
+class ResourceHandleClient;
+class ResourceRequest;
+
+class BlobResourceHandle : public FileStreamClient, public ResourceHandle {
+public:
+ static PassRefPtr<BlobResourceHandle> create(PassRefPtr<BlobStorageData> blobData, const ResourceRequest& request, ResourceHandleClient* client, bool async = true)
+ {
+ return adoptRef(new BlobResourceHandle(blobData, request, client, async));
+ }
+
+ static void loadResourceSynchronously(PassRefPtr<BlobStorageData> blobData, const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data);
+
+ // FileStreamClient methods.
+ virtual void didGetSize(long long);
+ virtual void didOpen(bool);
+ virtual void didRead(int);
+
+ // ResourceHandle methods.
+ virtual void cancel();
+
+ void start();
+ int readSync(char*, int);
+
+private:
+ BlobResourceHandle(PassRefPtr<BlobStorageData>, const ResourceRequest&, ResourceHandleClient*, bool async);
+ virtual ~BlobResourceHandle();
+
+ void getSizeForNext();
+ void seek();
+ void consumeData(const char* data, int bytesRead);
+ void failed(int errorCode);
+
+ void readAsync();
+ void readDataAsync(const BlobDataItem&);
+ void readFileAsync(const BlobDataItem&);
+
+ int readDataSync(const BlobDataItem&, char*, int);
+ int readFileSync(const BlobDataItem&, char*, int);
+
+ void notifyResponse();
+ void notifyResponseOnSuccess();
+ void notifyResponseOnError();
+ void notifyReceiveData(const char*, int);
+ void notifyFail(int errorCode);
+ void notifyFinish();
+
+ RefPtr<BlobStorageData> m_blobData;
+ bool m_async;
+ RefPtr<AsyncFileStream> m_asyncStream; // For asynchronous loading.
+ RefPtr<FileStream> m_stream; // For synchronous loading.
+ Vector<char> m_buffer;
+ Vector<long long> m_itemLengthList;
+ int m_errorCode;
+ bool m_aborted;
+ long long m_rangeOffset;
+ long long m_rangeEnd;
+ long long m_rangeSuffixLength;
+ long long m_totalRemainingSize;
+ long long m_currentItemReadSize;
+ unsigned m_sizeItemCount;
+ unsigned m_readItemCount;
+ bool m_fileOpened;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(BLOB)
+
+#endif // BlobResourceHandle_h
diff --git a/WebCore/platform/network/BlobStorageData.h b/WebCore/platform/network/BlobStorageData.h
index f4125a4..6535e62 100644
--- a/WebCore/platform/network/BlobStorageData.h
+++ b/WebCore/platform/network/BlobStorageData.h
@@ -31,76 +31,33 @@
#ifndef BlobStorageData_h
#define BlobStorageData_h
-#include "PlatformString.h"
+#include "BlobData.h"
#include <wtf/PassRefPtr.h>
-#include <wtf/Vector.h>
-#include <wtf/text/CString.h>
+#include <wtf/RefCounted.h>
namespace WebCore {
-struct BlobStorageDataItem {
- enum BlobStoreDataItemType { Data, File };
- BlobStoreDataItemType type;
- long long offset;
- long long length;
-
- // For string data.
- CString data;
-
- // For file data.
- String path;
- double expectedModificationTime;
-
- BlobStorageDataItem(const CString& data, long long offset, long long length)
- : type(Data)
- , offset(offset)
- , length(length)
- , data(data)
- , expectedModificationTime(0)
- {
- }
-
- BlobStorageDataItem(const String& path, long long offset, long long length, double expectedModificationTime)
- : type(File)
- , offset(offset)
- , length(length)
- , path(path)
- , expectedModificationTime(expectedModificationTime)
- {
- }
-};
-
-typedef Vector<BlobStorageDataItem> BlobStorageDataItemList;
-
class BlobStorageData : public RefCounted<BlobStorageData> {
public:
- static PassRefPtr<BlobStorageData> create()
+ static PassRefPtr<BlobStorageData> create(const String& contentType, const String& contentDisposition)
{
- return adoptRef(new BlobStorageData());
+ return adoptRef(new BlobStorageData(contentType, contentDisposition));
}
- const String& contentType() const { return m_contentType; }
- void setContentType(const String& contentType) { m_contentType = contentType; }
-
- const String& contentDisposition() const { return m_contentDisposition; }
- void setContentDisposition(const String& contentDisposition) { m_contentDisposition = contentDisposition; }
-
- const BlobStorageDataItemList& items() const { return m_items; }
+ const String& contentType() const { return m_data.contentType(); }
+ const String& contentDisposition() const { return m_data.contentDisposition(); }
+ const BlobDataItemList& items() const { return m_data.items(); }
- void appendData(const CString& data, long long offset, long long length)
- {
- m_items.append(BlobStorageDataItem(data, offset, length));
- }
+private:
+ friend class BlobRegistryImpl;
- void appendFile(const String& path, long long offset, long long length, double expectedModificationTime)
+ BlobStorageData(const String& contentType, const String& contentDisposition)
{
- m_items.append(BlobStorageDataItem(path, offset, length, expectedModificationTime));
+ m_data.setContentType(contentType);
+ m_data.setContentDisposition(contentDisposition);
}
-private:
- String m_contentType;
- String m_contentDisposition;
- BlobStorageDataItemList m_items;
+ BlobData m_data;
};
} // namespace WebCore
diff --git a/WebCore/platform/network/CredentialStorage.cpp b/WebCore/platform/network/CredentialStorage.cpp
index 4fb7799..38f71a4 100644
--- a/WebCore/platform/network/CredentialStorage.cpp
+++ b/WebCore/platform/network/CredentialStorage.cpp
@@ -79,7 +79,6 @@ static String protectionSpaceMapKeyFromURL(const KURL& url)
ASSERT(index != notFound);
directoryURL = directoryURL.substring(0, (index != directoryURLPathStart) ? index : directoryURLPathStart + 1);
}
- ASSERT(directoryURL.length() == directoryURLPathStart + 1 || directoryURL[directoryURL.length() - 1] != '/');
return directoryURL;
}
diff --git a/WebCore/platform/network/FormData.cpp b/WebCore/platform/network/FormData.cpp
index 31506ea..4f2b365 100644
--- a/WebCore/platform/network/FormData.cpp
+++ b/WebCore/platform/network/FormData.cpp
@@ -139,6 +139,11 @@ PassRefPtr<FormData> FormData::deepCopy() const
formData->m_elements.append(FormDataElement(e.m_filename, e.m_shouldGenerateFile));
#endif
break;
+#if ENABLE(BLOB)
+ case FormDataElement::encodedBlob:
+ formData->m_elements.append(FormDataElement(e.m_blobURL));
+ break;
+#endif
}
}
return formData.release();
@@ -200,6 +205,11 @@ void FormData::appendFileRange(const String& filename, long long start, long lon
{
m_elements.append(FormDataElement(filename, start, length, expectedModificationTime, shouldGenerateFile));
}
+
+void FormData::appendBlob(const KURL& blobURL)
+{
+ m_elements.append(FormDataElement(blobURL));
+}
#endif
void FormData::appendKeyValuePairItems(const BlobItemList& items, const TextEncoding& encoding, bool isMultiPartForm, Document* document)
diff --git a/WebCore/platform/network/FormData.h b/WebCore/platform/network/FormData.h
index a1964e3..d7faa89 100644
--- a/WebCore/platform/network/FormData.h
+++ b/WebCore/platform/network/FormData.h
@@ -20,6 +20,7 @@
#ifndef FormData_h
#define FormData_h
+#include "KURL.h"
#include "PlatformString.h"
#include <wtf/Forward.h>
#include <wtf/RefCounted.h>
@@ -39,17 +40,25 @@ public:
#if ENABLE(BLOB)
FormDataElement(const String& filename, long long fileStart, long long fileLength, double expectedFileModificationTime, bool shouldGenerateFile) : m_type(encodedFile), m_filename(filename), m_fileStart(fileStart), m_fileLength(fileLength), m_expectedFileModificationTime(expectedFileModificationTime), m_shouldGenerateFile(shouldGenerateFile) { }
+ FormDataElement(const KURL& blobURL) : m_type(encodedBlob), m_blobURL(blobURL) { }
#else
FormDataElement(const String& filename, bool shouldGenerateFile) : m_type(encodedFile), m_filename(filename), m_shouldGenerateFile(shouldGenerateFile) { }
#endif
- enum { data, encodedFile } m_type;
+ enum {
+ data,
+ encodedFile
+#if ENABLE(BLOB)
+ , encodedBlob
+#endif
+ } m_type;
Vector<char> m_data;
String m_filename;
#if ENABLE(BLOB)
long long m_fileStart;
long long m_fileLength;
double m_expectedFileModificationTime;
+ KURL m_blobURL;
#endif
String m_generatedFilename;
bool m_shouldGenerateFile;
@@ -67,14 +76,16 @@ inline bool operator==(const FormDataElement& a, const FormDataElement& b)
if (a.m_type != b.m_type)
return false;
- if (a.m_data != b.m_data)
- return false;
+ if (a.m_type == FormDataElement::data)
+ return a.m_data == b.m_data;
+ if (a.m_type == FormDataElement::encodedFile)
#if ENABLE(BLOB)
- if (a.m_filename != b.m_filename || a.m_fileStart != b.m_fileStart || a.m_fileLength != b.m_fileLength || a.m_expectedFileModificationTime != b.m_expectedFileModificationTime)
+ return a.m_filename == b.m_filename && a.m_fileStart == b.m_fileStart && a.m_fileLength == b.m_fileLength && a.m_expectedFileModificationTime == b.m_expectedFileModificationTime;
+ if (a.m_type == FormDataElement::encodedBlob)
+ return a.m_blobURL == b.m_blobURL;
#else
- if (a.m_filename != b.m_filename)
+ return a.m_filename == b.m_filename;
#endif
- return false;
return true;
}
@@ -101,6 +112,7 @@ public:
void appendFile(const String& filename, bool shouldGenerateFile = false);
#if ENABLE(BLOB)
void appendFileRange(const String& filename, long long start, long long length, double expectedModificationTime, bool shouldGenerateFile = false);
+ void appendBlob(const KURL& blobURL);
#endif
void flatten(Vector<char>&) const; // omits files
diff --git a/WebCore/platform/network/HTTPParsers.cpp b/WebCore/platform/network/HTTPParsers.cpp
index b3f3d45..a1ba9d3 100644
--- a/WebCore/platform/network/HTTPParsers.cpp
+++ b/WebCore/platform/network/HTTPParsers.cpp
@@ -315,4 +315,61 @@ String extractReasonPhraseFromHTTPStatusLine(const String& statusLine)
return statusLine.substring(spacePos + 1);
}
+bool parseRange(const String& range, long long& rangeOffset, long long& rangeEnd, long long& rangeSuffixLength)
+{
+ // The format of "Range" header is defined in RFC 2616 Section 14.35.1.
+ // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1
+ // We don't support multiple range requests.
+
+ rangeOffset = rangeEnd = rangeSuffixLength = -1;
+
+ // The "bytes" unit identifier should be present.
+ static const char bytesStart[] = "bytes=";
+ if (!range.startsWith(bytesStart, false))
+ return false;
+ String byteRange = range.substring(sizeof(bytesStart) - 1);
+
+ // The '-' character needs to be present.
+ int index = byteRange.find('-');
+ if (index == -1)
+ return false;
+
+ // If the '-' character is at the beginning, the suffix length, which specifies the last N bytes, is provided.
+ // Example:
+ // -500
+ if (!index) {
+ String suffixLengthString = byteRange.substring(index + 1).stripWhiteSpace();
+ bool ok;
+ long long value = suffixLengthString.toInt64Strict(&ok);
+ if (ok)
+ rangeSuffixLength = value;
+ return true;
+ }
+
+ // Otherwise, the first-byte-position and the last-byte-position are provied.
+ // Examples:
+ // 0-499
+ // 500-
+ String firstBytePosStr = byteRange.left(index).stripWhiteSpace();
+ bool ok;
+ long long firstBytePos = firstBytePosStr.toInt64Strict(&ok);
+ if (!ok)
+ return false;
+
+ String lastBytePosStr = byteRange.substring(index + 1).stripWhiteSpace();
+ long long lastBytePos = -1;
+ if (!lastBytePosStr.isEmpty()) {
+ lastBytePos = lastBytePosStr.toInt64Strict(&ok);
+ if (!ok)
+ return false;
+ }
+
+ if (firstBytePos < 0 || !(lastBytePos == -1 || lastBytePos >= firstBytePos))
+ return false;
+
+ rangeOffset = firstBytePos;
+ rangeEnd = lastBytePos;
+ return true;
+}
+
}
diff --git a/WebCore/platform/network/HTTPParsers.h b/WebCore/platform/network/HTTPParsers.h
index 9d6971b..55b8c7b 100644
--- a/WebCore/platform/network/HTTPParsers.h
+++ b/WebCore/platform/network/HTTPParsers.h
@@ -59,6 +59,9 @@ void findCharsetInMediaType(const String& mediaType, unsigned int& charsetPos, u
XSSProtectionDisposition parseXSSProtectionHeader(const String&);
String extractReasonPhraseFromHTTPStatusLine(const String&);
+// -1 could be set to one of the return parameters to indicate the value is not specified.
+bool parseRange(const String&, long long& rangeOffset, long long& rangeEnd, long long& rangeSuffixLength);
+
}
#endif
diff --git a/WebCore/platform/network/ResourceHandle.cpp b/WebCore/platform/network/ResourceHandle.cpp
index 0575523..2da1d77 100644
--- a/WebCore/platform/network/ResourceHandle.cpp
+++ b/WebCore/platform/network/ResourceHandle.cpp
@@ -27,6 +27,7 @@
#include "ResourceHandle.h"
#include "ResourceHandleInternal.h"
+#include "BlobRegistry.h"
#include "DNS.h"
#include "Logging.h"
#include "ResourceHandleClient.h"
@@ -54,6 +55,14 @@ ResourceHandle::ResourceHandle(const ResourceRequest& request, ResourceHandleCli
PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request, ResourceHandleClient* client,
Frame* frame, bool defersLoading, bool shouldContentSniff)
{
+#if ENABLE(BLOB)
+ if (request.url().protocolIs("blob")) {
+ PassRefPtr<ResourceHandle> handle = blobRegistry().createResourceHandle(request, client);
+ if (handle)
+ return handle;
+ }
+#endif
+
RefPtr<ResourceHandle> newHandle(adoptRef(new ResourceHandle(request, client, defersLoading, shouldContentSniff)));
if (newHandle->d->m_scheduledFailureType != NoFailure)
diff --git a/WebCore/platform/network/ResourceHandle.h b/WebCore/platform/network/ResourceHandle.h
index 3dc38f8..1167715 100644
--- a/WebCore/platform/network/ResourceHandle.h
+++ b/WebCore/platform/network/ResourceHandle.h
@@ -98,9 +98,10 @@ class ResourceHandle : public RefCounted<ResourceHandle>
, public AuthenticationClient
#endif
{
-private:
+protected:
ResourceHandle(const ResourceRequest&, ResourceHandleClient*, bool defersLoading, bool shouldContentSniff);
+private:
enum FailureType {
NoFailure,
BlockedFailure,
diff --git a/WebCore/platform/network/ResourceHandleClient.h b/WebCore/platform/network/ResourceHandleClient.h
index 0098010..97c0f54 100644
--- a/WebCore/platform/network/ResourceHandleClient.h
+++ b/WebCore/platform/network/ResourceHandleClient.h
@@ -44,8 +44,10 @@ class NSCachedURLResponse;
#endif
namespace WebCore {
+ class AsyncFileStream;
class AuthenticationChallenge;
class Credential;
+ class FileStreamClient;
class KURL;
class ProtectionSpace;
class ResourceHandle;
@@ -92,6 +94,9 @@ namespace WebCore {
#if USE(CFNETWORK)
virtual bool shouldCacheResponse(ResourceHandle*, CFCachedURLResponseRef response) { return true; }
#endif
+#if ENABLE(BLOB)
+ virtual AsyncFileStream* createAsyncFileStream(FileStreamClient*) { return 0; }
+#endif
};
}
diff --git a/WebCore/platform/network/ResourceHandleInternal.h b/WebCore/platform/network/ResourceHandleInternal.h
index 7b6e960..24b00bf 100644
--- a/WebCore/platform/network/ResourceHandleInternal.h
+++ b/WebCore/platform/network/ResourceHandleInternal.h
@@ -92,7 +92,6 @@ namespace WebCore {
, m_connection(0)
#endif
#if USE(WININET)
- , m_fileHandle(INVALID_HANDLE_VALUE)
, m_fileLoadTimer(loader, &ResourceHandle::fileLoadTimer)
, m_resourceHandle(0)
, m_secondaryHandle(0)
@@ -170,7 +169,6 @@ namespace WebCore {
bool m_needsSiteSpecificQuirks;
#endif
#if USE(WININET)
- HANDLE m_fileHandle;
Timer<ResourceHandle> m_fileLoadTimer;
HINTERNET m_resourceHandle;
HINTERNET m_secondaryHandle;
diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm
index f7161ec..d014bb3 100644
--- a/WebCore/platform/network/mac/ResourceHandleMac.mm
+++ b/WebCore/platform/network/mac/ResourceHandleMac.mm
@@ -29,6 +29,7 @@
#import "AuthenticationChallenge.h"
#import "AuthenticationMac.h"
#import "Base64.h"
+#import "BlobRegistry.h"
#import "BlockExceptions.h"
#import "CredentialStorage.h"
#import "DocLoader.h"
@@ -464,6 +465,12 @@ void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, S
{
LOG(Network, "ResourceHandle::loadResourceSynchronously:%@ allowStoredCredentials:%u", request.nsURLRequest(), storedCredentials);
+#if ENABLE(BLOB)
+ if (request.url().protocolIs("blob"))
+ if (blobRegistry().loadResourceSynchronously(request, error, response, data))
+ return;
+#endif
+
NSError *nsError = nil;
NSURLResponse *nsURLResponse = nil;
NSData *result = nil;
diff --git a/WebCore/platform/network/win/ResourceHandleWin.cpp b/WebCore/platform/network/win/ResourceHandleWin.cpp
index 63c84a9..3dabd91 100644
--- a/WebCore/platform/network/win/ResourceHandleWin.cpp
+++ b/WebCore/platform/network/win/ResourceHandleWin.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -63,6 +64,20 @@ static const ResourceHandleEventHandler messageHandlers[] = {
&ResourceHandle::onRequestComplete
};
+static String queryHTTPHeader(HINTERNET requestHandle, DWORD infoLevel)
+{
+ DWORD bufferSize = 0;
+ HttpQueryInfoW(requestHandle, infoLevel, 0, &bufferSize, 0);
+
+ Vector<UChar> characters(bufferSize / sizeof(UChar));
+
+ if (!HttpQueryInfoW(requestHandle, infoLevel, characters.data(), &bufferSize, 0))
+ return String();
+
+ characters.removeLast(); // Remove NullTermination.
+ return String::adopt(characters);
+}
+
static int addToOutstandingJobs(ResourceHandle* job)
{
if (!jobIdMap)
@@ -122,6 +137,49 @@ static void initializeOffScreenResourceHandleWindow()
HWND_MESSAGE, 0, WebCore::instanceHandle(), 0);
}
+
+class WebCoreSynchronousLoader : public ResourceHandleClient, public Noncopyable {
+public:
+ WebCoreSynchronousLoader(ResourceError&, ResourceResponse&, Vector<char>&, const String& userAgent);
+
+ virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);
+ virtual void didReceiveData(ResourceHandle*, const char*, int, int lengthReceived);
+ virtual void didFinishLoading(ResourceHandle*);
+ virtual void didFail(ResourceHandle*, const ResourceError&);
+
+private:
+ ResourceError& m_error;
+ ResourceResponse& m_response;
+ Vector<char>& m_data;
+};
+
+WebCoreSynchronousLoader::WebCoreSynchronousLoader(ResourceError& error, ResourceResponse& response, Vector<char>& data, const String& userAgent)
+ : m_error(error)
+ , m_response(response)
+ , m_data(data)
+{
+}
+
+void WebCoreSynchronousLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
+{
+ m_response = response;
+}
+
+void WebCoreSynchronousLoader::didReceiveData(ResourceHandle*, const char* data, int length, int)
+{
+ m_data.append(data, length);
+}
+
+void WebCoreSynchronousLoader::didFinishLoading(ResourceHandle*)
+{
+}
+
+void WebCoreSynchronousLoader::didFail(ResourceHandle*, const ResourceError& error)
+{
+ m_error = error;
+}
+
+
ResourceHandleInternal::~ResourceHandleInternal()
{
if (m_fileHandle != INVALID_HANDLE_VALUE)
@@ -225,7 +283,6 @@ void ResourceHandle::onRequestComplete(LPARAM lParam)
}
HINTERNET handle = (request().httpMethod() == "POST") ? d->m_secondaryHandle : d->m_resourceHandle;
- BOOL ok = FALSE;
static const int bufferSize = 32768;
char buffer[bufferSize];
@@ -234,11 +291,31 @@ void ResourceHandle::onRequestComplete(LPARAM lParam)
buffers.lpvBuffer = buffer;
buffers.dwBufferLength = bufferSize;
- bool receivedAnyData = false;
+ BOOL ok = FALSE;
while ((ok = InternetReadFileExA(handle, &buffers, IRF_NO_WAIT, (DWORD_PTR)this)) && buffers.dwBufferLength) {
if (!hasReceivedResponse()) {
setHasReceivedResponse();
ResourceResponse response;
+ response.setURL(firstRequest().url());
+
+ String httpStatusText = queryHTTPHeader(d->m_requestHandle, HTTP_QUERY_STATUS_TEXT);
+ if (!httpStatusText.isNull())
+ response.setHTTPStatusText(httpStatusText);
+
+ String httpStatusCode = queryHTTPHeader(d->m_requestHandle, HTTP_QUERY_STATUS_CODE);
+ if (!httpStatusCode.isNull())
+ response.setHTTPStatusCode(httpStatusCode.toInt());
+
+ String httpContentLength = queryHTTPHeader(d->m_requestHandle, HTTP_QUERY_CONTENT_LENGTH);
+ if (!httpContentLength.isNull())
+ response.setExpectedContentLength(httpContentLength.toInt());
+
+ String httpContentType = queryHTTPHeader(d->m_requestHandle, HTTP_QUERY_CONTENT_TYPE);
+ if (!httpContentType.isNull()) {
+ response.setMimeType(extractMIMETypeFromMediaType(httpContentType));
+ response.setTextEncodingName(extractCharsetFromMediaType(httpContentType));
+ }
+
client()->didReceiveResponse(this, response);
}
client()->didReceiveData(this, buffer, buffers.dwBufferLength, 0);
@@ -333,20 +410,6 @@ bool ResourceHandle::start(Frame* frame)
{
ref();
if (request().url().isLocalFile()) {
- String path = request().url().path();
- // windows does not enjoy a leading slash on paths
- if (path[0] == '/')
- path = path.substring(1);
- // FIXME: This is wrong. Need to use wide version of this call.
- d->m_fileHandle = CreateFileA(path.utf8().data(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
- // FIXME: perhaps this error should be reported asynchronously for
- // consistency.
- if (d->m_fileHandle == INVALID_HANDLE_VALUE) {
- delete this;
- return false;
- }
-
d->m_fileLoadTimer.startOneShot(0.0);
return true;
} else {
@@ -409,9 +472,29 @@ bool ResourceHandle::start(Frame* frame)
}
}
-void ResourceHandle::fileLoadTimer(Timer<ResourceHandle>* timer)
+void ResourceHandle::fileLoadTimer(Timer<ResourceHandle>*)
{
+ RefPtr<ResourceHandle> protector(this);
+ deref(); // balances ref in start
+
+ String fileName = firstRequest().url().fileSystemPath();
+ HANDLE fileHandle = CreateFileW(fileName.charactersWithNullTermination(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+
+ if (fileHandle == INVALID_HANDLE_VALUE) {
+ client()->didFail(this, ResourceError());
+ return;
+ }
+
ResourceResponse response;
+
+ int dotPos = fileName.reverseFind('.');
+ int slashPos = fileName.reverseFind('/');
+
+ if (slashPos < dotPos && dotPos != -1) {
+ String ext = fileName.substring(dotPos + 1);
+ response.setMimeType(MIMETypeRegistry::getMIMETypeForExtension(ext));
+ }
+
client()->didReceiveResponse(this, response);
bool result = false;
@@ -420,16 +503,13 @@ void ResourceHandle::fileLoadTimer(Timer<ResourceHandle>* timer)
do {
const int bufferSize = 8192;
char buffer[bufferSize];
- result = ReadFile(d->m_fileHandle, &buffer, bufferSize, &bytesRead, NULL);
+ result = ReadFile(fileHandle, &buffer, bufferSize, &bytesRead, 0);
if (result && bytesRead)
client()->didReceiveData(this, buffer, bytesRead, 0);
- // Check for end of file.
+ // Check for end of file.
} while (result && bytesRead);
- // FIXME: handle errors better
-
- CloseHandle(d->m_fileHandle);
- d->m_fileHandle = INVALID_HANDLE_VALUE;
+ CloseHandle(fileHandle);
client()->didFinishLoading(this);
}
@@ -449,6 +529,16 @@ void ResourceHandle::cancel()
client()->didFail(this, ResourceError());
}
+void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame* frame)
+{
+ UNUSED_PARAM(storedCredentials);
+
+ WebCoreSynchronousLoader syncLoader(error, response, data, request.httpUserAgent());
+ ResourceHandle handle(request, &syncLoader, true, false);
+
+ handle.start(frame);
+}
+
void ResourceHandle::setHasReceivedResponse(bool b)
{
d->m_hasReceivedResponse = b;
@@ -459,4 +549,36 @@ bool ResourceHandle::hasReceivedResponse() const
return d->m_hasReceivedResponse;
}
+bool ResourceHandle::willLoadFromCache(ResourceRequest&, Frame*)
+{
+ notImplemented();
+ return false;
+}
+
+void prefetchDNS(const String&)
+{
+ notImplemented();
+}
+
+PassRefPtr<SharedBuffer> ResourceHandle::bufferedData()
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+bool ResourceHandle::supportsBufferedData()
+{
+ return false;
+}
+
+bool ResourceHandle::loadsBlocked()
+{
+ return false;
+}
+
+void ResourceHandle::platformSetDefersLoading(bool)
+{
+ notImplemented();
+}
+
} // namespace WebCore
diff --git a/WebCore/platform/qt/CursorQt.cpp b/WebCore/platform/qt/CursorQt.cpp
index 6017daa..227b80c 100644
--- a/WebCore/platform/qt/CursorQt.cpp
+++ b/WebCore/platform/qt/CursorQt.cpp
@@ -3,6 +3,7 @@
* Copyright (C) 2006 George Staikos <staikos@kde.org>
* Copyright (C) 2006 Charles Samuels <charles@kde.org>
* Copyright (C) 2008, 2009 Holger Hans Peter Freyther
+ * Copyright (C) 2010 University of Szeged
*
* All rights reserved.
*
@@ -43,329 +44,166 @@
namespace WebCore {
-Cursor::Cursor(PlatformCursor p)
- : m_platformCursor(p)
-{
-}
-
Cursor::Cursor(const Cursor& other)
- : m_platformCursor(other.m_platformCursor)
+ : m_type(other.m_type)
+ , m_image(other.m_image)
+ , m_hotSpot(other.m_hotSpot)
+#ifndef QT_NO_CURSOR
+ , m_platformCursor(other.m_platformCursor ? new QCursor(*other.m_platformCursor) : 0)
+#endif
{
}
Cursor::~Cursor()
{
-}
-
-Cursor::Cursor(Image* image, const IntPoint& hotSpot)
-{
#ifndef QT_NO_CURSOR
- IntPoint effectiveHotSpot = determineHotSpot(image, hotSpot);
- m_platformCursor = QCursor(*(image->nativeImageForCurrentFrame()), effectiveHotSpot.x(), effectiveHotSpot.y());
+ delete m_platformCursor;
#endif
}
Cursor& Cursor::operator=(const Cursor& other)
{
- m_platformCursor = other.m_platformCursor;
- return *this;
-}
-
-namespace {
-
-// FIXME: static deleter
-class Cursors : public Noncopyable {
-protected:
- Cursors()
+ m_type = other.m_type;
+ m_image = other.m_image;
+ m_hotSpot = other.m_hotSpot;
#ifndef QT_NO_CURSOR
- : CrossCursor(Qt::CrossCursor)
- , MoveCursor(Qt::SizeAllCursor)
- , PointerCursor(Qt::ArrowCursor)
- , PointingHandCursor(Qt::PointingHandCursor)
- , IBeamCursor(Qt::IBeamCursor)
- , WaitCursor(Qt::WaitCursor)
- , WhatsThisCursor(Qt::WhatsThisCursor)
- , SizeHorCursor(Qt::SizeHorCursor)
- , SizeVerCursor(Qt::SizeVerCursor)
- , SizeFDiagCursor(Qt::SizeFDiagCursor)
- , SizeBDiagCursor(Qt::SizeBDiagCursor)
- , SplitHCursor(Qt::SplitHCursor)
- , SplitVCursor(Qt::SplitVCursor)
- , NoDropCursor(Qt::ForbiddenCursor)
- , BlankCursor(Qt::BlankCursor)
- , ZoomInCursor(QCursor(QPixmap(QLatin1String(":/webkit/resources/zoomInCursor.png")), 7, 7))
- , ZoomOutCursor(QCursor(QPixmap(QLatin1String(":/webkit/resources/zoomOutCursor.png")), 7, 7))
- , VerticalTextCursor(QCursor(QPixmap(QLatin1String(":/webkit/resources/verticalTextCursor.png")), 7, 7))
- , CellCursor(QCursor(QPixmap(QLatin1String(":/webkit/resources/cellCursor.png")), 7, 7))
- , ContextMenuCursor(QCursor(QPixmap(QLatin1String(":/webkit/resources/contextMenuCursor.png")), 3, 2))
- , CopyCursor(QCursor(QPixmap(QLatin1String(":/webkit/resources/copyCursor.png")), 3, 2))
- , ProgressCursor(QCursor(QPixmap(QLatin1String(":/webkit/resources/progressCursor.png")), 3, 2))
- , AliasCursor(QCursor(QPixmap(QLatin1String(":/webkit/resources/aliasCursor.png")), 11, 3))
-
+ m_platformCursor = other.m_platformCursor ? new QCursor(*other.m_platformCursor) : 0;
#endif
- {
- }
-
- ~Cursors()
- {
- }
-
-public:
- static Cursors* self();
- static Cursors* s_self;
-
- Cursor CrossCursor;
- Cursor MoveCursor;
- Cursor PointerCursor;
- Cursor PointingHandCursor;
- Cursor IBeamCursor;
- Cursor WaitCursor;
- Cursor WhatsThisCursor;
- Cursor SizeHorCursor;
- Cursor SizeVerCursor;
- Cursor SizeFDiagCursor;
- Cursor SizeBDiagCursor;
- Cursor SplitHCursor;
- Cursor SplitVCursor;
- Cursor NoDropCursor;
- Cursor BlankCursor;
- Cursor ZoomInCursor;
- Cursor ZoomOutCursor;
- Cursor VerticalTextCursor;
- Cursor CellCursor;
- Cursor ContextMenuCursor;
- Cursor CopyCursor;
- Cursor ProgressCursor;
- Cursor AliasCursor;
-};
-
-Cursors* Cursors::s_self = 0;
-
-Cursors* Cursors::self()
-{
- if (!s_self)
- s_self = new Cursors();
-
- return s_self;
-}
-
-}
-
-const Cursor& pointerCursor()
-{
- return Cursors::self()->PointerCursor;
-}
-
-const Cursor& moveCursor()
-{
- return Cursors::self()->MoveCursor;
-}
-
-const Cursor& crossCursor()
-{
- return Cursors::self()->CrossCursor;
-}
-
-const Cursor& handCursor()
-{
- return Cursors::self()->PointingHandCursor;
-}
-
-const Cursor& iBeamCursor()
-{
- return Cursors::self()->IBeamCursor;
-}
-
-const Cursor& waitCursor()
-{
- return Cursors::self()->WaitCursor;
-}
-
-const Cursor& helpCursor()
-{
- return Cursors::self()->WhatsThisCursor;
-}
-
-const Cursor& eastResizeCursor()
-{
- return Cursors::self()->SizeHorCursor;
-}
-
-const Cursor& northResizeCursor()
-{
- return Cursors::self()->SizeVerCursor;
-}
-
-const Cursor& northEastResizeCursor()
-{
- return Cursors::self()->SizeBDiagCursor;
-}
-
-const Cursor& northWestResizeCursor()
-{
- return Cursors::self()->SizeFDiagCursor;
-}
-
-const Cursor& southResizeCursor()
-{
- return Cursors::self()->SizeVerCursor;
-}
-
-const Cursor& southEastResizeCursor()
-{
- return Cursors::self()->SizeFDiagCursor;
-}
-
-const Cursor& southWestResizeCursor()
-{
- return Cursors::self()->SizeBDiagCursor;
-}
-
-const Cursor& westResizeCursor()
-{
- return Cursors::self()->SizeHorCursor;
-}
-
-const Cursor& northSouthResizeCursor()
-{
- return Cursors::self()->SizeVerCursor;
-}
-
-const Cursor& eastWestResizeCursor()
-{
- return Cursors::self()->SizeHorCursor;
-}
-
-const Cursor& northEastSouthWestResizeCursor()
-{
- return Cursors::self()->SizeBDiagCursor;
-}
-
-const Cursor& northWestSouthEastResizeCursor()
-{
- return Cursors::self()->SizeFDiagCursor;
-}
-
-const Cursor& columnResizeCursor()
-{
- return Cursors::self()->SplitHCursor;
-}
-
-const Cursor& rowResizeCursor()
-{
- return Cursors::self()->SplitVCursor;
-}
-
-const Cursor& middlePanningCursor()
-{
- return moveCursor();
-}
-
-const Cursor& eastPanningCursor()
-{
- return eastResizeCursor();
-}
-
-const Cursor& northPanningCursor()
-{
- return northResizeCursor();
-}
-
-const Cursor& northEastPanningCursor()
-{
- return northEastResizeCursor();
-}
-
-const Cursor& northWestPanningCursor()
-{
- return northWestResizeCursor();
-}
-
-const Cursor& southPanningCursor()
-{
- return southResizeCursor();
-}
-
-const Cursor& southEastPanningCursor()
-{
- return southEastResizeCursor();
-}
-
-const Cursor& southWestPanningCursor()
-{
- return southWestResizeCursor();
-}
-
-const Cursor& westPanningCursor()
-{
- return westResizeCursor();
-}
-
-const Cursor& verticalTextCursor()
-{
- return Cursors::self()->VerticalTextCursor;
-}
-
-const Cursor& cellCursor()
-{
- return Cursors::self()->CellCursor;
-}
-
-const Cursor& contextMenuCursor()
-{
- return Cursors::self()->ContextMenuCursor;
-}
-
-const Cursor& noDropCursor()
-{
- return Cursors::self()->NoDropCursor;
-}
-
-const Cursor& copyCursor()
-{
- return Cursors::self()->CopyCursor;
-}
-
-const Cursor& progressCursor()
-{
- return Cursors::self()->ProgressCursor;
-}
-
-const Cursor& aliasCursor()
-{
- return Cursors::self()->AliasCursor;
-}
-
-const Cursor& noneCursor()
-{
- return Cursors::self()->BlankCursor;
-}
-
-const Cursor& notAllowedCursor()
-{
- return Cursors::self()->NoDropCursor;
-}
-
-const Cursor& zoomInCursor()
-{
- return Cursors::self()->ZoomInCursor;
-}
-
-const Cursor& zoomOutCursor()
-{
- return Cursors::self()->ZoomOutCursor;
+ return *this;
}
-const Cursor& grabCursor()
+static QCursor* createCustomCursor(Image* image, const IntPoint& hotSpot)
{
- notImplemented();
- return Cursors::self()->PointerCursor;
+#ifndef QT_NO_CURSOR
+ IntPoint effectiveHotSpot = determineHotSpot(image, hotSpot);
+ return new QCursor(*(image->nativeImageForCurrentFrame()), effectiveHotSpot.x(), effectiveHotSpot.y());
+#else
+ return 0;
+#endif
}
-const Cursor& grabbingCursor()
+void Cursor::ensurePlatformCursor() const
{
- notImplemented();
- return Cursors::self()->PointerCursor;
+#ifndef QT_NO_CURSOR
+ if (m_platformCursor)
+ return;
+
+ switch (m_type) {
+ case Pointer:
+ m_platformCursor = new QCursor(Qt::ArrowCursor);
+ break;
+ case Cross:
+ m_platformCursor = new QCursor(Qt::CrossCursor);
+ break;
+ case Hand:
+ m_platformCursor = new QCursor(Qt::PointingHandCursor);
+ break;
+ case IBeam:
+ m_platformCursor = new QCursor(Qt::IBeamCursor);
+ break;
+ case Wait:
+ m_platformCursor = new QCursor(Qt::WaitCursor);
+ break;
+ case Help:
+ m_platformCursor = new QCursor(Qt::WhatsThisCursor);
+ break;
+ case EastResize:
+ case EastPanning:
+ m_platformCursor = new QCursor(Qt::SizeHorCursor);
+ break;
+ case NorthResize:
+ case NorthPanning:
+ m_platformCursor = new QCursor(Qt::SizeVerCursor);
+ break;
+ case NorthEastResize:
+ case NorthEastPanning:
+ m_platformCursor = new QCursor(Qt::SizeBDiagCursor);
+ break;
+ case NorthWestResize:
+ case NorthWestPanning:
+ m_platformCursor = new QCursor(Qt::SizeFDiagCursor);
+ break;
+ case SouthResize:
+ case SouthPanning:
+ m_platformCursor = new QCursor(Qt::SizeVerCursor);
+ break;
+ case SouthEastResize:
+ case SouthEastPanning:
+ m_platformCursor = new QCursor(Qt::SizeFDiagCursor);
+ break;
+ case SouthWestResize:
+ case SouthWestPanning:
+ m_platformCursor = new QCursor(Qt::SizeBDiagCursor);
+ break;
+ case WestResize:
+ case WestPanning:
+ m_platformCursor = new QCursor(Qt::SizeHorCursor);
+ break;
+ case NorthSouthResize:
+ m_platformCursor = new QCursor(Qt::SizeVerCursor);
+ break;
+ case EastWestResize:
+ m_platformCursor = new QCursor(Qt::SizeHorCursor);
+ break;
+ case NorthEastSouthWestResize:
+ m_platformCursor = new QCursor(Qt::SizeBDiagCursor);
+ break;
+ case NorthWestSouthEastResize:
+ m_platformCursor = new QCursor(Qt::SizeFDiagCursor);
+ break;
+ case ColumnResize:
+ m_platformCursor = new QCursor(Qt::SplitHCursor);
+ break;
+ case RowResize:
+ m_platformCursor = new QCursor(Qt::SplitVCursor);
+ break;
+ case MiddlePanning:
+ case Move:
+ m_platformCursor = new QCursor(Qt::SizeAllCursor);
+ break;
+ case None:
+ m_platformCursor = new QCursor(Qt::BlankCursor);
+ break;
+ case NoDrop:
+ case NotAllowed:
+ m_platformCursor = new QCursor(Qt::ForbiddenCursor);
+ break;
+ case Grab:
+ case Grabbing:
+ notImplemented();
+ m_platformCursor = new QCursor(Qt::ArrowCursor);
+ break;
+ case VerticalText:
+ m_platformCursor = new QCursor(QPixmap(QLatin1String(":/webkit/resources/verticalTextCursor.png")), 7, 7);
+ break;
+ case Cell:
+ m_platformCursor = new QCursor(QPixmap(QLatin1String(":/webkit/resources/cellCursor.png")), 7, 7);
+ break;
+ case ContextMenu:
+ m_platformCursor = new QCursor(QPixmap(QLatin1String(":/webkit/resources/contextMenuCursor.png")), 3, 2);
+ break;
+ case Alias:
+ m_platformCursor = new QCursor(QPixmap(QLatin1String(":/webkit/resources/aliasCursor.png")), 11, 3);
+ break;
+ case Progress:
+ m_platformCursor = new QCursor(QPixmap(QLatin1String(":/webkit/resources/progressCursor.png")), 3, 2);
+ break;
+ case Copy:
+ m_platformCursor = new QCursor(QPixmap(QLatin1String(":/webkit/resources/copyCursor.png")), 3, 2);
+ break;
+ case ZoomIn:
+ m_platformCursor = new QCursor(QPixmap(QLatin1String(":/webkit/resources/zoomInCursor.png")), 7, 7);
+ break;
+ case ZoomOut:
+ m_platformCursor = new QCursor(QPixmap(QLatin1String(":/webkit/resources/zoomOutCursor.png")), 7, 7);
+ break;
+ case Custom:
+ m_platformCursor = createCustomCursor(m_image.get(), m_hotSpot);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+#endif
}
}
diff --git a/WebCore/platform/qt/PasteboardQt.cpp b/WebCore/platform/qt/PasteboardQt.cpp
index e1e6d84..fc53124 100644
--- a/WebCore/platform/qt/PasteboardQt.cpp
+++ b/WebCore/platform/qt/PasteboardQt.cpp
@@ -65,10 +65,7 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete,
text.replace(QChar(0xa0), QLatin1Char(' '));
md->setText(text);
- QString html = QLatin1String("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></head><body>");
- html += createMarkup(selectedRange, 0, AnnotateForInterchange, false, AbsoluteURLs);
- html += QLatin1String("</body></html>");
- md->setHtml(html);
+ md->setHtml(createMarkup(selectedRange, 0, AnnotateForInterchange, false, AbsoluteURLs));
#ifndef QT_NO_CLIPBOARD
QApplication::clipboard()->setMimeData(md, m_selectionMode ?
diff --git a/WebCore/platform/qt/WidgetQt.cpp b/WebCore/platform/qt/WidgetQt.cpp
index 0903b6e..e64d655 100644
--- a/WebCore/platform/qt/WidgetQt.cpp
+++ b/WebCore/platform/qt/WidgetQt.cpp
@@ -78,10 +78,10 @@ void Widget::setFocus(bool focused)
void Widget::setCursor(const Cursor& cursor)
{
#ifndef QT_NO_CURSOR
- QWebPageClient* pageClient = root()->hostWindow()->platformPageClient();
-
- if (pageClient)
- pageClient->setCursor(cursor.impl());
+ ScrollView* view = root();
+ if (!view)
+ return;
+ view->hostWindow()->setCursor(cursor);
#endif
}
diff --git a/WebCore/platform/sql/SQLiteStatement.cpp b/WebCore/platform/sql/SQLiteStatement.cpp
index 4dc80fb..037ec79 100644
--- a/WebCore/platform/sql/SQLiteStatement.cpp
+++ b/WebCore/platform/sql/SQLiteStatement.cpp
@@ -192,6 +192,14 @@ int SQLiteStatement::bindText(int index, const String& text)
return sqlite3_bind_text16(m_statement, index, characters, sizeof(UChar) * text.length(), SQLITE_TRANSIENT);
}
+int SQLiteStatement::bindInt(int index, int integer)
+{
+ ASSERT(m_isPrepared);
+ ASSERT(index > 0);
+ ASSERT(static_cast<unsigned>(index) <= bindParameterCount());
+
+ return sqlite3_bind_int(m_statement, index, integer);
+}
int SQLiteStatement::bindInt64(int index, int64_t integer)
{
@@ -251,6 +259,18 @@ int SQLiteStatement::columnCount()
return sqlite3_data_count(m_statement);
}
+bool SQLiteStatement::isColumnNull(int col)
+{
+ ASSERT(col >= 0);
+ if (!m_statement)
+ if (prepareAndStep() != SQLITE_ROW)
+ return false;
+ if (columnCount() <= col)
+ return false;
+
+ return sqlite3_column_type(m_statement, col) == SQLITE_NULL;
+}
+
String SQLiteStatement::getColumnName(int col)
{
ASSERT(col >= 0);
diff --git a/WebCore/platform/sql/SQLiteStatement.h b/WebCore/platform/sql/SQLiteStatement.h
index e62b4f0..1444f0e 100644
--- a/WebCore/platform/sql/SQLiteStatement.h
+++ b/WebCore/platform/sql/SQLiteStatement.h
@@ -42,6 +42,7 @@ public:
int prepare();
int bindBlob(int index, const void* blob, int size);
int bindText(int index, const String&);
+ int bindInt(int index, int);
int bindInt64(int index, int64_t);
int bindDouble(int index, double);
int bindNull(int index);
@@ -70,6 +71,7 @@ public:
// returned in the last step()
int columnCount();
+ bool isColumnNull(int col);
String getColumnName(int col);
SQLValue getColumnValue(int col);
String getColumnText(int col);
diff --git a/WebCore/platform/text/TextCodecLatin1.cpp b/WebCore/platform/text/TextCodecLatin1.cpp
index 4f9cbe0..2a217c5 100644
--- a/WebCore/platform/text/TextCodecLatin1.cpp
+++ b/WebCore/platform/text/TextCodecLatin1.cpp
@@ -164,7 +164,7 @@ String TextCodecLatin1::decode(const char* bytes, size_t length, bool, bool, boo
// Wait until we're at a properly aligned address, then read full CPU words.
if (!(reinterpret_cast<ptrdiff_t>(src) & (sizeof(uintptr_t) - 1))) {
while (src < alignedEnd) {
- uintptr_t chunk = *reinterpret_cast<const uintptr_t*>(src);
+ uintptr_t chunk = *reinterpret_cast_ptr<const uintptr_t*>(src);
if (chunk & NonASCIIMask<sizeof(uintptr_t)>::value())
goto useLookupTable;
diff --git a/WebCore/platform/text/qt/TextCodecQt.cpp b/WebCore/platform/text/qt/TextCodecQt.cpp
index 735d773..94a2b7b 100644
--- a/WebCore/platform/text/qt/TextCodecQt.cpp
+++ b/WebCore/platform/text/qt/TextCodecQt.cpp
@@ -110,7 +110,7 @@ String TextCodecQt::decode(const char* bytes, size_t length, bool flush, bool /*
int size = end - buf;
size = qMin(size, MaxInputChunkSize);
QString decoded = m_codec->toUnicode(buf, size, &m_state);
- unicode.append(decoded);
+ unicode.append(reinterpret_cast_ptr<const UChar*>(decoded.unicode()), decoded.length());
buf += size;
}
diff --git a/WebCore/platform/win/BitmapInfo.cpp b/WebCore/platform/win/BitmapInfo.cpp
index 514f722..610a27e 100644
--- a/WebCore/platform/win/BitmapInfo.cpp
+++ b/WebCore/platform/win/BitmapInfo.cpp
@@ -33,21 +33,14 @@
namespace WebCore {
-BitmapInfo bitmapInfoForSize(int width, int height, WORD bitCount)
+BitmapInfo bitmapInfoForSize(int width, int height, BitmapInfo::BitCount bitCount)
{
- ASSERT_ARG(bitCount, bitCount == 16 || bitCount == 32);
-
BitmapInfo bitmapInfo;
bitmapInfo.bmiHeader.biWidth = width;
bitmapInfo.bmiHeader.biHeight = height;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = bitCount;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
- bitmapInfo.bmiHeader.biSizeImage = 0;
- bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
- bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
- bitmapInfo.bmiHeader.biClrUsed = 0;
- bitmapInfo.bmiHeader.biClrImportant = 0;
return bitmapInfo;
}
@@ -58,12 +51,12 @@ BitmapInfo::BitmapInfo()
bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
}
-BitmapInfo BitmapInfo::create(const IntSize& size, WORD bitCount)
+BitmapInfo BitmapInfo::create(const IntSize& size, BitCount bitCount)
{
return bitmapInfoForSize(size.width(), size.height(), bitCount);
}
-BitmapInfo BitmapInfo::createBottomUp(const IntSize& size, WORD bitCount)
+BitmapInfo BitmapInfo::createBottomUp(const IntSize& size, BitCount bitCount)
{
return bitmapInfoForSize(size.width(), -size.height(), bitCount);
}
diff --git a/WebCore/platform/win/BitmapInfo.h b/WebCore/platform/win/BitmapInfo.h
index d1c3319..caf1b31 100644
--- a/WebCore/platform/win/BitmapInfo.h
+++ b/WebCore/platform/win/BitmapInfo.h
@@ -35,19 +35,30 @@
namespace WebCore {
struct BitmapInfo : public BITMAPINFO {
+ enum BitCount {
+ BitCount1 = 1,
+ BitCount4 = 4,
+ BitCount8 = 8,
+ BitCount16 = 16,
+ BitCount24 = 24,
+ BitCount32 = 32
+ };
+
BitmapInfo();
- static BitmapInfo create(const IntSize&, WORD bitCount = 32);
- static BitmapInfo createBottomUp(const IntSize&, WORD bitCount = 32);
+ static BitmapInfo create(const IntSize&, BitCount bitCount = BitCount32);
+ static BitmapInfo createBottomUp(const IntSize&, BitCount bitCount = BitCount32);
bool is16bit() const { return bmiHeader.biBitCount == 16; }
bool is32bit() const { return bmiHeader.biBitCount == 32; }
unsigned width() const { return abs(bmiHeader.biWidth); }
unsigned height() const { return abs(bmiHeader.biHeight); }
IntSize size() const { return IntSize(width(), height()); }
- unsigned paddedWidth() const { return is16bit() ? (width() + 1) & ~0x1 : width(); }
+ unsigned bytesPerLine() const { return (width() * bmiHeader.biBitCount + 7) / 8; }
+ unsigned paddedBytesPerLine() const { return (bytesPerLine() + 3) & ~0x3; }
+ unsigned paddedWidth() const { return paddedBytesPerLine() * 8 / bmiHeader.biBitCount; }
unsigned numPixels() const { return paddedWidth() * height(); }
- unsigned paddedBytesPerLine() const { return is16bit() ? paddedWidth() * 2 : width() * 4; }
- unsigned bytesPerLine() const { return width() * bmiHeader.biBitCount / 8; }};
+};
+
} // namespace WebCore
#endif // BitmapInfo_h
diff --git a/WebCore/platform/win/PopupMenuWin.cpp b/WebCore/platform/win/PopupMenuWin.cpp
index aaadc53..6e22024 100644
--- a/WebCore/platform/win/PopupMenuWin.cpp
+++ b/WebCore/platform/win/PopupMenuWin.cpp
@@ -581,7 +581,7 @@ void PopupMenuWin::paint(const IntRect& damageRect, HDC hdc)
}
if (!m_bmp) {
#if OS(WINCE)
- BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(clientRect().size(), 16);
+ BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(clientRect().size(), BitmapInfo::BitCount16);
#else
BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(clientRect().size());
#endif