summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/graphics/cairo
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/platform/graphics/cairo
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/platform/graphics/cairo')
-rw-r--r--Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairo.h59
-rw-r--r--Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoImpl.cpp63
-rw-r--r--Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoImpl.h43
-rw-r--r--Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoX11.cpp74
-rw-r--r--Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoX11.h46
-rw-r--r--Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp161
-rw-r--r--Source/WebCore/platform/graphics/cairo/CairoUniquePtr.h (renamed from Source/WebCore/platform/graphics/cairo/DrawingBufferCairo.cpp)39
-rw-r--r--Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp130
-rw-r--r--Source/WebCore/platform/graphics/cairo/CairoUtilities.h50
-rw-r--r--Source/WebCore/platform/graphics/cairo/DrawErrorUnderline.h8
-rw-r--r--Source/WebCore/platform/graphics/cairo/FloatRectCairo.cpp8
-rw-r--r--Source/WebCore/platform/graphics/cairo/FontCairo.cpp252
-rw-r--r--Source/WebCore/platform/graphics/cairo/FontCairoHarfbuzzNG.cpp53
-rw-r--r--Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h16
-rw-r--r--Source/WebCore/platform/graphics/cairo/GradientCairo.cpp12
-rw-r--r--Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp194
-rw-r--r--Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp708
-rw-r--r--Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h22
-rw-r--r--Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp370
-rw-r--r--Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h37
-rw-r--r--Source/WebCore/platform/graphics/cairo/ImageCairo.cpp23
-rw-r--r--Source/WebCore/platform/graphics/cairo/IntRectCairo.cpp6
-rw-r--r--Source/WebCore/platform/graphics/cairo/NativeImageCairo.cpp105
-rw-r--r--Source/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp52
-rw-r--r--Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h44
-rw-r--r--Source/WebCore/platform/graphics/cairo/PathCairo.cpp62
-rw-r--r--Source/WebCore/platform/graphics/cairo/PatternCairo.cpp10
-rw-r--r--Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp34
-rw-r--r--Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h10
-rw-r--r--Source/WebCore/platform/graphics/cairo/PlatformPathCairo.cpp15
-rw-r--r--Source/WebCore/platform/graphics/cairo/PlatformPathCairo.h4
-rw-r--r--Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp45
-rw-r--r--Source/WebCore/platform/graphics/cairo/RefPtrCairo.h10
-rw-r--r--Source/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp13
34 files changed, 1897 insertions, 881 deletions
diff --git a/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairo.h b/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairo.h
new file mode 100644
index 000000000..63828c761
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairo.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011,2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef BackingStoreBackendCairo_h
+#define BackingStoreBackendCairo_h
+
+#if USE(CAIRO)
+
+#include "IntRect.h"
+#include "RefPtrCairo.h"
+#include <wtf/FastMalloc.h>
+#include <wtf/Noncopyable.h>
+
+typedef struct _cairo_surface cairo_surface_t;
+
+namespace WebCore {
+
+class BackingStoreBackendCairo {
+ WTF_MAKE_NONCOPYABLE(BackingStoreBackendCairo);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ virtual ~BackingStoreBackendCairo() { }
+
+ cairo_surface_t* surface() const { return m_surface.get(); }
+ const IntSize& size() const { return m_size; }
+
+ virtual void scroll(const IntRect& scrollRect, const IntSize& scrollOffset) = 0;
+
+protected:
+ BackingStoreBackendCairo(const IntSize& size)
+ : m_size(size)
+ {
+ }
+
+ RefPtr<cairo_surface_t> m_surface;
+ IntSize m_size;
+};
+
+
+} // namespace WebCore
+
+#endif // USE(CAIRO)
+
+#endif // BackingStoreBackendCairo_h
diff --git a/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoImpl.cpp b/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoImpl.cpp
new file mode 100644
index 000000000..40d06dbf8
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoImpl.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011,2014 Igalia S.L.
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "BackingStoreBackendCairoImpl.h"
+
+#if USE(CAIRO)
+
+#include "CairoUtilities.h"
+
+namespace WebCore {
+
+BackingStoreBackendCairoImpl::BackingStoreBackendCairoImpl(cairo_surface_t* surface, const IntSize& size)
+ : BackingStoreBackendCairo(size)
+{
+ m_surface = surface;
+
+ // We keep two copies of the surface here, which will double the memory usage, but increase
+ // scrolling performance since we do not have to keep reallocating a memory region during
+ // quick scrolling requests.
+ double xScale, yScale;
+ cairoSurfaceGetDeviceScale(m_surface.get(), xScale, yScale);
+ IntSize scaledSize = size;
+ scaledSize.scale(xScale, yScale);
+ m_scrollSurface = adoptRef(cairo_surface_create_similar(surface, CAIRO_CONTENT_COLOR_ALPHA, scaledSize.width(), scaledSize.height()));
+}
+
+BackingStoreBackendCairoImpl::~BackingStoreBackendCairoImpl()
+{
+}
+
+void BackingStoreBackendCairoImpl::scroll(const IntRect& scrollRect, const IntSize& scrollOffset)
+{
+ IntRect targetRect = scrollRect;
+ targetRect.move(scrollOffset);
+ targetRect.shiftMaxXEdgeTo(targetRect.maxX() - scrollOffset.width());
+ targetRect.shiftMaxYEdgeTo(targetRect.maxY() - scrollOffset.height());
+ if (targetRect.isEmpty())
+ return;
+
+ copyRectFromOneSurfaceToAnother(m_surface.get(), m_scrollSurface.get(), scrollOffset, targetRect);
+ copyRectFromOneSurfaceToAnother(m_scrollSurface.get(), m_surface.get(), IntSize(), targetRect);
+}
+
+} // namespace WebCore
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoImpl.h b/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoImpl.h
new file mode 100644
index 000000000..b1a0149bb
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoImpl.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013,2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef BackingStoreBackendCairoImpl_h
+#define BackingStoreBackendCairoImpl_h
+
+#include "BackingStoreBackendCairo.h"
+
+#if USE(CAIRO)
+
+namespace WebCore {
+
+class BackingStoreBackendCairoImpl final : public BackingStoreBackendCairo {
+public:
+ BackingStoreBackendCairoImpl(cairo_surface_t*, const IntSize&);
+ virtual ~BackingStoreBackendCairoImpl();
+
+ void scroll(const IntRect&, const IntSize&) override;
+
+private:
+ RefPtr<cairo_surface_t> m_scrollSurface;
+};
+
+} // namespace WebCore
+
+#endif // USE(CAIRO)
+
+#endif // BackingStoreBackendCairoImpl_h
diff --git a/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoX11.cpp b/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoX11.cpp
new file mode 100644
index 000000000..437dafc82
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoX11.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011,2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "BackingStoreBackendCairoX11.h"
+
+#if USE(CAIRO) && PLATFORM(X11)
+
+#include "CairoUtilities.h"
+#include <cairo-xlib.h>
+
+namespace WebCore {
+
+BackingStoreBackendCairoX11::BackingStoreBackendCairoX11(unsigned long rootWindowID, Visual* visual, int depth, const IntSize& size, float deviceScaleFactor)
+ : BackingStoreBackendCairo(size)
+{
+ IntSize scaledSize = size;
+ scaledSize.scale(deviceScaleFactor);
+
+ auto* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
+ m_pixmap = XCreatePixmap(display, rootWindowID, scaledSize.width(), scaledSize.height(), depth);
+ m_gc.reset(XCreateGC(display, m_pixmap.get(), 0, nullptr));
+
+ m_surface = adoptRef(cairo_xlib_surface_create(display, m_pixmap.get(), visual, scaledSize.width(), scaledSize.height()));
+ cairoSurfaceSetDeviceScale(m_surface.get(), deviceScaleFactor, deviceScaleFactor);
+}
+
+BackingStoreBackendCairoX11::~BackingStoreBackendCairoX11()
+{
+ // The pixmap needs to exist when the surface is destroyed, so begin by clearing it.
+ m_surface = nullptr;
+}
+
+void BackingStoreBackendCairoX11::scroll(const IntRect& scrollRect, const IntSize& scrollOffset)
+{
+ IntRect targetRect = scrollRect;
+ targetRect.move(scrollOffset);
+ targetRect.intersect(scrollRect);
+ if (targetRect.isEmpty())
+ return;
+
+ double xScale, yScale;
+ cairoSurfaceGetDeviceScale(m_surface.get(), xScale, yScale);
+ ASSERT(xScale == yScale);
+
+ IntSize scaledScrollOffset = scrollOffset;
+ targetRect.scale(xScale);
+ scaledScrollOffset.scale(xScale, yScale);
+
+ cairo_surface_flush(m_surface.get());
+ XCopyArea(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native(), m_pixmap.get(), m_pixmap.get(), m_gc.get(),
+ targetRect.x() - scaledScrollOffset.width(), targetRect.y() - scaledScrollOffset.height(),
+ targetRect.width(), targetRect.height(), targetRect.x(), targetRect.y());
+ cairo_surface_mark_dirty_rectangle(m_surface.get(), targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height());
+}
+
+} // namespace WebCore
+
+#endif // USE(CAIRO) && PLATFORM(X11)
diff --git a/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoX11.h b/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoX11.h
new file mode 100644
index 000000000..3441809f5
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/BackingStoreBackendCairoX11.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013,2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef BackingStoreBackendCairoX11_h
+#define BackingStoreBackendCairoX11_h
+
+#include "BackingStoreBackendCairo.h"
+
+#if USE(CAIRO) && PLATFORM(X11)
+#include "XUniquePtr.h"
+#include "XUniqueResource.h"
+
+namespace WebCore {
+
+class BackingStoreBackendCairoX11 final : public BackingStoreBackendCairo {
+public:
+ BackingStoreBackendCairoX11(unsigned long rootWindowID, Visual*, int depth, const IntSize&, float deviceScaleFactor);
+ virtual ~BackingStoreBackendCairoX11();
+
+ void scroll(const IntRect& scrollRect, const IntSize& scrollOffset) override;
+
+private:
+ XUniquePixmap m_pixmap;
+ XUniqueGC m_gc;
+};
+
+} // namespace WebCore
+
+#endif // USE(CAIRO) && PLATFORM(X11)
+
+#endif // GtkWidgetBackingStoreX11_h
diff --git a/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp b/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp
deleted file mode 100644
index 4611a306a..000000000
--- a/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
- * Copyright (C) 2007 Alp Toker <alp@atoker.com>
- * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "BitmapImage.h"
-
-#include "CairoUtilities.h"
-#include "ImageObserver.h"
-#include "PlatformContextCairo.h"
-#include "Timer.h"
-#include <cairo.h>
-
-namespace WebCore {
-
-BitmapImage::BitmapImage(PassRefPtr<cairo_surface_t> nativeImage, ImageObserver* observer)
- : Image(observer)
- , m_size(cairoSurfaceSize(nativeImage.get()))
- , m_currentFrame(0)
- , m_repetitionCount(cAnimationNone)
- , m_repetitionCountStatus(Unknown)
- , m_repetitionsComplete(0)
- , m_decodedSize(m_size.width() * m_size.height() * 4)
- , m_frameCount(1)
- , m_isSolidColor(false)
- , m_checkedForSolidColor(false)
- , m_animationFinished(true)
- , m_allDataReceived(true)
- , m_haveSize(true)
- , m_sizeAvailable(true)
- , m_haveFrameCount(true)
-{
- m_frames.grow(1);
- m_frames[0].m_hasAlpha = cairo_surface_get_content(nativeImage.get()) != CAIRO_CONTENT_COLOR;
- m_frames[0].m_frame = nativeImage;
- m_frames[0].m_haveMetadata = true;
-
- checkForSolidColor();
-}
-
-void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op,
- BlendMode blendMode, ImageOrientationDescription description)
-{
- if (!dst.width() || !dst.height() || !src.width() || !src.height())
- return;
-
- startAnimation();
-
- RefPtr<cairo_surface_t> surface = frameAtIndex(m_currentFrame);
- if (!surface) // If it's too early we won't have an image yet.
- return;
-
- if (mayFillWithSolidColor()) {
- fillWithSolidColor(context, dst, solidColor(), styleColorSpace, op);
- return;
- }
-
- context->save();
-
- // Set the compositing operation.
- if (op == CompositeSourceOver && blendMode == BlendModeNormal && !frameHasAlphaAtIndex(m_currentFrame))
- context->setCompositeOperation(CompositeCopy);
- else
- context->setCompositeOperation(op, blendMode);
-
-#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
- IntSize scaledSize = cairoSurfaceSize(surface.get());
- FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(src, scaledSize);
-#else
- FloatRect adjustedSrcRect(src);
-#endif
-
- ImageOrientation frameOrientation(description.imageOrientation());
- if (description.respectImageOrientation() == RespectImageOrientation)
- frameOrientation = frameOrientationAtIndex(m_currentFrame);
-
- FloatRect dstRect = dst;
-
- if (frameOrientation != DefaultImageOrientation) {
- // ImageOrientation expects the origin to be at (0, 0).
- context->translate(dstRect.x(), dstRect.y());
- dstRect.setLocation(FloatPoint());
- context->concatCTM(frameOrientation.transformFromDefault(dstRect.size()));
- if (frameOrientation.usesWidthAsHeight()) {
- // The destination rectangle will have it's width and height already reversed for the orientation of
- // the image, as it was needed for page layout, so we need to reverse it back here.
- dstRect = FloatRect(dstRect.x(), dstRect.y(), dstRect.height(), dstRect.width());
- }
- }
-
- context->platformContext()->drawSurfaceToContext(surface.get(), dstRect, adjustedSrcRect, context);
-
- context->restore();
-
- if (imageObserver())
- imageObserver()->didDraw(this);
-}
-
-void BitmapImage::checkForSolidColor()
-{
- m_isSolidColor = false;
- m_checkedForSolidColor = true;
-
- if (frameCount() > 1)
- return;
-
- RefPtr<cairo_surface_t> surface = frameAtIndex(m_currentFrame);
- if (!surface) // If it's too early we won't have an image yet.
- return;
-
- if (cairo_surface_get_type(surface.get()) != CAIRO_SURFACE_TYPE_IMAGE)
- return;
-
- IntSize size = cairoSurfaceSize(surface.get());
-
- if (size.width() != 1 || size.height() != 1)
- return;
-
- unsigned* pixelColor = reinterpret_cast_ptr<unsigned*>(cairo_image_surface_get_data(surface.get()));
- m_solidColor = colorFromPremultipliedARGB(*pixelColor);
-
- m_isSolidColor = true;
-}
-
-bool FrameData::clear(bool clearMetadata)
-{
- if (clearMetadata)
- m_haveMetadata = false;
-
- if (m_frame) {
- m_frame.clear();
- return true;
- }
- return false;
-}
-
-} // namespace WebCore
-
diff --git a/Source/WebCore/platform/graphics/cairo/DrawingBufferCairo.cpp b/Source/WebCore/platform/graphics/cairo/CairoUniquePtr.h
index 738e49381..f7a5007d2 100644
--- a/Source/WebCore/platform/graphics/cairo/DrawingBufferCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/CairoUniquePtr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2016 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -13,38 +13,35 @@
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
+#pragma once
-#if ENABLE(ACCELERATED_2D_CANVAS) || USE(3D_GRAPHICS)
-
-#include "DrawingBuffer.h"
-
-#include "Extensions3D.h"
+#include <cairo.h>
+#include <memory>
namespace WebCore {
-#if USE(ACCELERATED_COMPOSITING)
-
-unsigned DrawingBuffer::frontColorBuffer() const
-{
- return colorBuffer();
-}
+template<typename T> struct CairoPtrDeleter {
+ void operator()(T* ptr) const = delete;
+};
-void DrawingBuffer::paintCompositedResultsToCanvas(ImageBuffer*)
-{
-}
-#endif
+template<typename T>
+using CairoUniquePtr = std::unique_ptr<T, CairoPtrDeleter<T>>;
-}
+template<> struct CairoPtrDeleter<cairo_font_options_t> {
+ void operator() (cairo_font_options_t* ptr) const
+ {
+ cairo_font_options_destroy(ptr);
+ }
+};
-#endif
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp b/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp
index 98207e4b2..8a3ff33d0 100644
--- a/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp
+++ b/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp
@@ -11,10 +11,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -27,16 +27,19 @@
#include "config.h"
#include "CairoUtilities.h"
+#if USE(CAIRO)
+
#include "AffineTransform.h"
#include "Color.h"
#include "FloatPoint.h"
#include "FloatRect.h"
#include "IntRect.h"
-#include "OwnPtrCairo.h"
#include "Path.h"
#include "PlatformPathCairo.h"
#include "RefPtrCairo.h"
+#include "Region.h"
#include <wtf/Assertions.h>
+#include <wtf/NeverDestroyed.h>
#include <wtf/Vector.h>
#if ENABLE(ACCELERATED_2D_CANVAS)
@@ -45,6 +48,14 @@
namespace WebCore {
+#if USE(FREETYPE) && !PLATFORM(GTK)
+const cairo_font_options_t* getDefaultCairoFontOptions()
+{
+ static NeverDestroyed<cairo_font_options_t*> options = cairo_font_options_create();
+ return options;
+}
+#endif
+
void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr)
{
cairo_set_antialias(dstCr, cairo_get_antialias(srcCr));
@@ -64,15 +75,20 @@ void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr)
void setSourceRGBAFromColor(cairo_t* context, const Color& color)
{
- float red, green, blue, alpha;
- color.getRGBA(red, green, blue, alpha);
- cairo_set_source_rgba(context, red, green, blue, alpha);
+ if (color.isExtended())
+ cairo_set_source_rgba(context, color.asExtended().red(), color.asExtended().green(), color.asExtended().blue(), color.asExtended().alpha());
+ else {
+ float red, green, blue, alpha;
+ color.getRGBA(red, green, blue, alpha);
+ cairo_set_source_rgba(context, red, green, blue, alpha);
+ }
}
void appendPathToCairoContext(cairo_t* to, cairo_t* from)
{
- OwnPtr<cairo_path_t> cairoPath = adoptPtr(cairo_copy_path(from));
- cairo_append_path(to, cairoPath.get());
+ auto cairoPath = cairo_copy_path(from);
+ cairo_append_path(to, cairoPath);
+ cairo_path_destroy(cairoPath);
}
void setPathOnCairoContext(cairo_t* to, cairo_t* from)
@@ -101,7 +117,7 @@ void appendRegionToCairoContext(cairo_t* to, const cairo_region_t* region)
}
}
-cairo_operator_t toCairoOperator(CompositeOperator op)
+static cairo_operator_t toCairoCompositeOperator(CompositeOperator op)
{
switch (op) {
case CompositeClear:
@@ -136,11 +152,12 @@ cairo_operator_t toCairoOperator(CompositeOperator op)
return CAIRO_OPERATOR_SOURCE;
}
}
-cairo_operator_t toCairoOperator(BlendMode blendOp)
+
+cairo_operator_t toCairoOperator(CompositeOperator op, BlendMode blendOp)
{
switch (blendOp) {
case BlendModeNormal:
- return CAIRO_OPERATOR_OVER;
+ return toCairoCompositeOperator(op);
case BlendModeMultiply:
return CAIRO_OPERATOR_MULTIPLY;
case BlendModeScreen:
@@ -198,8 +215,46 @@ void drawPatternToCairoContext(cairo_t* cr, cairo_surface_t* image, const IntSiz
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
+ // Due to a limitation in pixman, cairo cannot handle transformation matrices with values bigger than 32768. If the value is
+ // bigger, cairo is not able to paint anything, and this is the reason for the missing backgrounds reported in
+ // https://bugs.webkit.org/show_bug.cgi?id=154283.
+
+ // When drawing a pattern there are 2 matrices that can overflow this limitation, and they are the current transformation
+ // matrix (which translates user space coordinates to coordinates of the output device) and the pattern matrix (which translates
+ // user space coordinates to pattern coordinates). The overflow happens only in the translation components of the matrices.
+
+ // To avoid the problem in the transformation matrix what we do is remove the translation components of the transformation matrix
+ // and perform the translation by moving the destination rectangle instead. For this, we get its translation components (which are in
+ // device coordinates) and divide them by the scale factor to take them to user space coordinates. Then we move the transformation
+ // matrix by the opposite of that amount (which will zero the translation components of the transformation matrix), and move
+ // the destination rectangle by the same amount. We also need to apply the same translation to the pattern matrix, so we get the
+ // same pattern coordinates for the new destination rectangle.
+
+ cairo_matrix_t ctm;
+ cairo_get_matrix(cr, &ctm);
+ double dx = 0, dy = 0;
+ cairo_matrix_transform_point(&ctm, &dx, &dy);
+ double xScale = 1, yScale = 1;
+ cairo_matrix_transform_distance(&ctm, &xScale, &yScale);
+
+ dx = dx / xScale;
+ dy = dy / yScale;
+ cairo_translate(cr, -dx, -dy);
+ FloatRect adjustedDestRect(destRect);
+ adjustedDestRect.move(dx, dy);
+
+ // Regarding the pattern matrix, what we do is reduce the translation component of the matrix taking advantage of the fact that we
+ // are drawing a repeated pattern. This means that, assuming that (w, h) is the size of the pattern, samplig it at (x, y) is the same
+ // than sampling it at (x mod w, y mod h), so we transform the translation component of the pattern matrix in that way.
+
cairo_matrix_t patternMatrix = cairo_matrix_t(patternTransform);
- cairo_matrix_t phaseMatrix = {1, 0, 0, 1, phase.x() + tileRect.x() * patternTransform.a(), phase.y() + tileRect.y() * patternTransform.d()};
+ // dx and dy are added here as well to compensate the previous translation of the destination rectangle.
+ double phaseOffsetX = phase.x() + tileRect.x() * patternTransform.a() + dx;
+ double phaseOffsetY = phase.y() + tileRect.y() * patternTransform.d() + dy;
+ // this is where we perform the (x mod w, y mod h) metioned above, but with floats instead of integers.
+ phaseOffsetX -= std::trunc(phaseOffsetX / (tileRect.width() * patternTransform.a())) * tileRect.width() * patternTransform.a();
+ phaseOffsetY -= std::trunc(phaseOffsetY / (tileRect.height() * patternTransform.d())) * tileRect.height() * patternTransform.d();
+ cairo_matrix_t phaseMatrix = {1, 0, 0, 1, phaseOffsetX, phaseOffsetY};
cairo_matrix_t combined;
cairo_matrix_multiply(&combined, &patternMatrix, &phaseMatrix);
cairo_matrix_invert(&combined);
@@ -208,13 +263,13 @@ void drawPatternToCairoContext(cairo_t* cr, cairo_surface_t* image, const IntSiz
cairo_set_operator(cr, op);
cairo_set_source(cr, pattern);
cairo_pattern_destroy(pattern);
- cairo_rectangle(cr, destRect.x(), destRect.y(), destRect.width(), destRect.height());
+ cairo_rectangle(cr, adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.width(), adjustedDestRect.height());
cairo_fill(cr);
cairo_restore(cr);
}
-PassRefPtr<cairo_surface_t> copyCairoImageSurface(cairo_surface_t* originalSurface)
+RefPtr<cairo_surface_t> copyCairoImageSurface(cairo_surface_t* originalSurface)
{
// Cairo doesn't provide a way to copy a cairo_surface_t.
// See http://lists.cairographics.org/archives/cairo/2007-June/010877.html
@@ -260,6 +315,29 @@ IntSize cairoSurfaceSize(cairo_surface_t* surface)
}
}
+void flipImageSurfaceVertically(cairo_surface_t* surface)
+{
+ ASSERT(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE);
+
+ IntSize size = cairoSurfaceSize(surface);
+ ASSERT(!size.isEmpty());
+
+ int stride = cairo_image_surface_get_stride(surface);
+ int halfHeight = size.height() / 2;
+
+ uint8_t* source = static_cast<uint8_t*>(cairo_image_surface_get_data(surface));
+ std::unique_ptr<uint8_t[]> tmp = std::make_unique<uint8_t[]>(stride);
+
+ for (int i = 0; i < halfHeight; ++i) {
+ uint8_t* top = source + (i * stride);
+ uint8_t* bottom = source + ((size.height()-i-1) * stride);
+
+ memcpy(tmp.get(), top, stride);
+ memcpy(top, bottom, stride);
+ memcpy(bottom, tmp.get(), stride);
+ }
+}
+
void cairoSurfaceSetDeviceScale(cairo_surface_t* surface, double xScale, double yScale)
{
// This function was added pretty much simultaneous to when 1.13 was branched.
@@ -271,4 +349,28 @@ void cairoSurfaceSetDeviceScale(cairo_surface_t* surface, double xScale, double
ASSERT_UNUSED(yScale, 1 == yScale);
#endif
}
+
+void cairoSurfaceGetDeviceScale(cairo_surface_t* surface, double& xScale, double& yScale)
+{
+#if HAVE(CAIRO_SURFACE_SET_DEVICE_SCALE)
+ cairo_surface_get_device_scale(surface, &xScale, &yScale);
+#else
+ UNUSED_PARAM(surface);
+ xScale = 1;
+ yScale = 1;
+#endif
+}
+
+RefPtr<cairo_region_t> toCairoRegion(const Region& region)
+{
+ RefPtr<cairo_region_t> cairoRegion = adoptRef(cairo_region_create());
+ for (const auto& rect : region.rects()) {
+ cairo_rectangle_int_t cairoRect = rect;
+ cairo_region_union_rectangle(cairoRegion.get(), &cairoRect);
+ }
+ return cairoRegion;
+}
+
} // namespace WebCore
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/CairoUtilities.h b/Source/WebCore/platform/graphics/cairo/CairoUtilities.h
index df3680c01..9528e0210 100644
--- a/Source/WebCore/platform/graphics/cairo/CairoUtilities.h
+++ b/Source/WebCore/platform/graphics/cairo/CairoUtilities.h
@@ -11,10 +11,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -24,8 +24,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef CairoUtilities_h
-#define CairoUtilities_h
+#pragma once
+
+#if USE(CAIRO)
#include "GraphicsTypes.h"
#include "IntSize.h"
@@ -34,6 +35,10 @@
// This function was added pretty much simultaneous to when 1.13 was branched.
#define HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR >= 13)
+#if USE(FREETYPE)
+#include <cairo-ft.h>
+#endif
+
namespace WebCore {
class AffineTransform;
class Color;
@@ -42,6 +47,32 @@ class FloatPoint;
class IntSize;
class IntRect;
class Path;
+class Region;
+
+#if USE(FREETYPE)
+class CairoFtFaceLocker {
+public:
+ CairoFtFaceLocker(cairo_scaled_font_t* scaledFont)
+ : m_scaledFont(scaledFont)
+ , m_ftFace(cairo_ft_scaled_font_lock_face(scaledFont))
+ {
+ }
+
+ ~CairoFtFaceLocker()
+ {
+ if (m_ftFace)
+ cairo_ft_scaled_font_unlock_face(m_scaledFont);
+ }
+
+ FT_Face ftFace() const { return m_ftFace; }
+
+private:
+ cairo_scaled_font_t* m_scaledFont { nullptr };
+ FT_Face m_ftFace { nullptr };
+};
+
+const cairo_font_options_t* getDefaultCairoFontOptions();
+#endif
void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr);
void setSourceRGBAFromColor(cairo_t*, const Color&);
@@ -49,18 +80,21 @@ void appendPathToCairoContext(cairo_t* to, cairo_t* from);
void setPathOnCairoContext(cairo_t* to, cairo_t* from);
void appendWebCorePathToCairoContext(cairo_t* context, const Path& path);
void appendRegionToCairoContext(cairo_t*, const cairo_region_t*);
-cairo_operator_t toCairoOperator(CompositeOperator op);
-cairo_operator_t toCairoOperator(BlendMode blendOp);
+cairo_operator_t toCairoOperator(CompositeOperator, BlendMode = BlendModeNormal);
void drawPatternToCairoContext(cairo_t* cr, cairo_surface_t* image, const IntSize& imageSize, const FloatRect& tileRect,
const AffineTransform& patternTransform, const FloatPoint& phase, cairo_operator_t op, const FloatRect& destRect);
-PassRefPtr<cairo_surface_t> copyCairoImageSurface(cairo_surface_t*);
+RefPtr<cairo_surface_t> copyCairoImageSurface(cairo_surface_t*);
void copyRectFromCairoSurfaceToContext(cairo_surface_t* from, cairo_t* to, const IntSize& offset, const IntRect&);
void copyRectFromOneSurfaceToAnother(cairo_surface_t* from, cairo_surface_t* to, const IntSize& offset, const IntRect&, const IntSize& = IntSize(), cairo_operator_t = CAIRO_OPERATOR_OVER);
IntSize cairoSurfaceSize(cairo_surface_t*);
+void flipImageSurfaceVertically(cairo_surface_t*);
void cairoSurfaceSetDeviceScale(cairo_surface_t*, double xScale, double yScale);
+void cairoSurfaceGetDeviceScale(cairo_surface_t*, double& xScale, double& yScale);
+
+RefPtr<cairo_region_t> toCairoRegion(const Region&);
} // namespace WebCore
-#endif // CairoUtilities_h
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/DrawErrorUnderline.h b/Source/WebCore/platform/graphics/cairo/DrawErrorUnderline.h
index 4eca4e4c5..ececc562d 100644
--- a/Source/WebCore/platform/graphics/cairo/DrawErrorUnderline.h
+++ b/Source/WebCore/platform/graphics/cairo/DrawErrorUnderline.h
@@ -21,11 +21,11 @@
*
*/
-#if USE(CAIRO)
-
#ifndef DrawErrorUnderline_h
#define DrawErrorUnderline_h
+#if USE(CAIRO)
+
#include <cairo.h>
//
@@ -101,6 +101,6 @@ static inline void drawErrorUnderline(cairo_t* cr, double x, double y, double wi
cairo_fill(cr);
}
-#endif // DrawErrorUnderline_h
+#endif // USE(CAIRO)
-#endif
+#endif // DrawErrorUnderline_h
diff --git a/Source/WebCore/platform/graphics/cairo/FloatRectCairo.cpp b/Source/WebCore/platform/graphics/cairo/FloatRectCairo.cpp
index 9f86f747e..ede90c90f 100644
--- a/Source/WebCore/platform/graphics/cairo/FloatRectCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/FloatRectCairo.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,6 +26,8 @@
#include "config.h"
#include "FloatRect.h"
+#if USE(CAIRO)
+
#include <cairo.h>
namespace WebCore {
@@ -43,3 +45,5 @@ FloatRect::operator cairo_rectangle_t() const
}
} // namespace WebCore
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp
index a09e555d2..a712d0011 100644
--- a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp
@@ -1,9 +1,10 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
* Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com>
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) 2010 Holger Hans Peter Freyther
+ * Copyright (C) 2014 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -14,10 +15,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -28,29 +29,32 @@
*/
#include "config.h"
-#include "Font.h"
+#include "FontCascade.h"
+
+#if USE(CAIRO)
#include "AffineTransform.h"
#include "CairoUtilities.h"
+#include "Font.h"
#include "GlyphBuffer.h"
#include "Gradient.h"
#include "GraphicsContext.h"
#include "ImageBuffer.h"
#include "Pattern.h"
#include "PlatformContextCairo.h"
+#include "PlatformPathCairo.h"
#include "ShadowBlur.h"
-#include "SimpleFontData.h"
namespace WebCore {
-static void drawGlyphsToContext(cairo_t* context, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs)
+static void drawGlyphsToContext(cairo_t* context, const Font& font, GlyphBufferGlyph* glyphs, unsigned numGlyphs)
{
cairo_matrix_t originalTransform;
- float syntheticBoldOffset = font->syntheticBoldOffset();
+ float syntheticBoldOffset = font.syntheticBoldOffset();
if (syntheticBoldOffset)
cairo_get_matrix(context, &originalTransform);
- cairo_set_scaled_font(context, font->platformData().scaledFont());
+ cairo_set_scaled_font(context, font.platformData().scaledFont());
cairo_show_glyphs(context, glyphs, numGlyphs);
if (syntheticBoldOffset) {
@@ -62,21 +66,21 @@ static void drawGlyphsToContext(cairo_t* context, const SimpleFontData* font, Gl
cairo_set_matrix(context, &originalTransform);
}
-static void drawGlyphsShadow(GraphicsContext* graphicsContext, const FloatPoint& point, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs)
+static void drawGlyphsShadow(GraphicsContext& graphicsContext, const FloatPoint& point, const Font& font, GlyphBufferGlyph* glyphs, unsigned numGlyphs)
{
- ShadowBlur& shadow = graphicsContext->platformContext()->shadowBlur();
+ ShadowBlur& shadow = graphicsContext.platformContext()->shadowBlur();
- if (!(graphicsContext->textDrawingMode() & TextModeFill) || shadow.type() == ShadowBlur::NoShadow)
+ if (!(graphicsContext.textDrawingMode() & TextModeFill) || shadow.type() == ShadowBlur::NoShadow)
return;
- if (!graphicsContext->mustUseShadowBlur()) {
+ if (!graphicsContext.mustUseShadowBlur()) {
// Optimize non-blurry shadows, by just drawing text without the ShadowBlur.
- cairo_t* context = graphicsContext->platformContext()->cr();
+ cairo_t* context = graphicsContext.platformContext()->cr();
cairo_save(context);
- FloatSize shadowOffset(graphicsContext->state().shadowOffset);
+ FloatSize shadowOffset(graphicsContext.state().shadowOffset);
cairo_translate(context, shadowOffset.width(), shadowOffset.height());
- setSourceRGBAFromColor(context, graphicsContext->state().shadowColor);
+ setSourceRGBAFromColor(context, graphicsContext.state().shadowColor);
drawGlyphsToContext(context, font, glyphs, numGlyphs);
cairo_restore(context);
@@ -84,7 +88,7 @@ static void drawGlyphsShadow(GraphicsContext* graphicsContext, const FloatPoint&
}
cairo_text_extents_t extents;
- cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents);
+ cairo_scaled_font_glyph_extents(font.platformData().scaledFont(), glyphs, numGlyphs, &extents);
FloatRect fontExtentsRect(point.x() + extents.x_bearing, point.y() + extents.y_bearing, extents.width, extents.height);
if (GraphicsContext* shadowContext = shadow.beginShadowLayer(graphicsContext, fontExtentsRect)) {
@@ -93,29 +97,29 @@ static void drawGlyphsShadow(GraphicsContext* graphicsContext, const FloatPoint&
}
}
-void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
- int from, int numGlyphs, const FloatPoint& point) const
+void FontCascade::drawGlyphs(GraphicsContext& context, const Font& font, const GlyphBuffer& glyphBuffer,
+ unsigned from, unsigned numGlyphs, const FloatPoint& point, FontSmoothingMode)
{
- if (!font->platformData().size())
+ if (!font.platformData().size())
return;
GlyphBufferGlyph* glyphs = const_cast<GlyphBufferGlyph*>(glyphBuffer.glyphs(from));
float offset = point.x();
- for (int i = 0; i < numGlyphs; i++) {
+ for (unsigned i = 0; i < numGlyphs; i++) {
glyphs[i].x = offset;
glyphs[i].y = point.y();
offset += glyphBuffer.advanceAt(from + i).width();
}
- PlatformContextCairo* platformContext = context->platformContext();
+ PlatformContextCairo* platformContext = context.platformContext();
drawGlyphsShadow(context, point, font, glyphs, numGlyphs);
cairo_t* cr = platformContext->cr();
cairo_save(cr);
- if (context->textDrawingMode() & TextModeFill) {
- platformContext->prepareForFilling(context->state(), PlatformContextCairo::AdjustPatternForGlobalAlpha);
+ if (context.textDrawingMode() & TextModeFill) {
+ platformContext->prepareForFilling(context.state(), PlatformContextCairo::AdjustPatternForGlobalAlpha);
drawGlyphsToContext(cr, font, glyphs, numGlyphs);
}
@@ -123,12 +127,12 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
// twice the size of the width of the text we will not ask cairo to stroke
// the text as even one single stroke would cover the full wdth of the text.
// See https://bugs.webkit.org/show_bug.cgi?id=33759.
- if (context->textDrawingMode() & TextModeStroke && context->strokeThickness() < 2 * offset) {
- platformContext->prepareForStroking(context->state());
- cairo_set_line_width(cr, context->strokeThickness());
+ if (context.textDrawingMode() & TextModeStroke && context.strokeThickness() < 2 * offset) {
+ platformContext->prepareForStroking(context.state());
+ cairo_set_line_width(cr, context.strokeThickness());
// This may disturb the CTM, but we are going to call cairo_restore soon after.
- cairo_set_scaled_font(cr, font->platformData().scaledFont());
+ cairo_set_scaled_font(cr, font.platformData().scaledFont());
cairo_glyph_path(cr, glyphs, numGlyphs);
cairo_stroke(cr);
}
@@ -136,4 +140,198 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
cairo_restore(cr);
}
+#if ENABLE(CSS3_TEXT_DECORATION_SKIP_INK)
+struct GlyphIterationState {
+ GlyphIterationState(FloatPoint startingPoint, FloatPoint currentPoint, float centerOfLine, float minX, float maxX)
+ : startingPoint(startingPoint)
+ , currentPoint(currentPoint)
+ , centerOfLine(centerOfLine)
+ , minX(minX)
+ , maxX(maxX)
+ {
+ }
+ FloatPoint startingPoint;
+ FloatPoint currentPoint;
+ float centerOfLine;
+ float minX;
+ float maxX;
+};
+
+static bool findIntersectionPoint(float y, FloatPoint p1, FloatPoint p2, float& x)
+{
+ x = p1.x() + (y - p1.y()) * (p2.x() - p1.x()) / (p2.y() - p1.y());
+ return (p1.y() < y && p2.y() > y) || (p1.y() > y && p2.y() < y);
+}
+
+static void updateX(GlyphIterationState& state, float x)
+{
+ state.minX = std::min(state.minX, x);
+ state.maxX = std::max(state.maxX, x);
+}
+
+// This function is called by Path::apply and is therefore invoked for each contour in a glyph. This
+// function models each contours as a straight line and calculates the intersections between each
+// pseudo-contour and the vertical center of the underline found in GlyphIterationState::centerOfLine.
+// It keeps track of the leftmost and rightmost intersection in GlyphIterationState::minX and
+// GlyphIterationState::maxX.
+static void findPathIntersections(GlyphIterationState& state, const PathElement& element)
+{
+ bool doIntersection = false;
+ FloatPoint point = FloatPoint();
+ switch (element.type) {
+ case PathElementMoveToPoint:
+ state.startingPoint = element.points[0];
+ state.currentPoint = element.points[0];
+ break;
+ case PathElementAddLineToPoint:
+ doIntersection = true;
+ point = element.points[0];
+ break;
+ case PathElementAddQuadCurveToPoint:
+ doIntersection = true;
+ point = element.points[1];
+ break;
+ case PathElementAddCurveToPoint:
+ doIntersection = true;
+ point = element.points[2];
+ break;
+ case PathElementCloseSubpath:
+ doIntersection = true;
+ point = state.startingPoint;
+ break;
+ }
+
+ if (!doIntersection)
+ return;
+
+ float x;
+ if (findIntersectionPoint(state.centerOfLine, state.currentPoint, point, x))
+ updateX(state, x);
+
+ state.currentPoint = point;
}
+
+class CairoGlyphToPathTranslator final : public GlyphToPathTranslator {
+public:
+ CairoGlyphToPathTranslator(const TextRun& textRun, const GlyphBuffer& glyphBuffer, const FloatPoint& textOrigin)
+ : m_index(0)
+ , m_textRun(textRun)
+ , m_glyphBuffer(glyphBuffer)
+ , m_fontData(glyphBuffer.fontAt(m_index))
+ , m_translation(AffineTransform().translate(textOrigin.x(), textOrigin.y()))
+ {
+ }
+
+ bool containsMorePaths() final { return m_index != m_glyphBuffer.size(); }
+ Path path() final;
+ std::pair<float, float> extents() final;
+ GlyphUnderlineType underlineType() final;
+ void advance() final;
+
+private:
+ unsigned m_index;
+ const TextRun& m_textRun;
+ const GlyphBuffer& m_glyphBuffer;
+ const Font* m_fontData;
+ AffineTransform m_translation;
+};
+
+Path CairoGlyphToPathTranslator::path()
+{
+ Path path;
+ path.ensurePlatformPath();
+
+ cairo_glyph_t cairoGlyph = { m_glyphBuffer.glyphAt(m_index), 0, 0 };
+ cairo_set_scaled_font(path.platformPath()->context(), m_fontData->platformData().scaledFont());
+ cairo_glyph_path(path.platformPath()->context(), &cairoGlyph, 1);
+
+ float syntheticBoldOffset = m_fontData->syntheticBoldOffset();
+ if (syntheticBoldOffset) {
+ cairo_translate(path.platformPath()->context(), syntheticBoldOffset, 0);
+ cairo_show_glyphs(path.platformPath()->context(), &cairoGlyph, 1);
+ }
+
+ path.transform(m_translation);
+ return path;
+}
+
+std::pair<float, float> CairoGlyphToPathTranslator::extents()
+{
+ FloatPoint beginning = m_translation.mapPoint(FloatPoint());
+ FloatSize end = m_translation.mapSize(m_glyphBuffer.advanceAt(m_index));
+ return std::make_pair(static_cast<float>(beginning.x()), static_cast<float>(beginning.x() + end.width()));
+}
+
+GlyphToPathTranslator::GlyphUnderlineType CairoGlyphToPathTranslator::underlineType()
+{
+ return computeUnderlineType(m_textRun, m_glyphBuffer, m_index);
+}
+
+void CairoGlyphToPathTranslator::advance()
+{
+ GlyphBufferAdvance advance = m_glyphBuffer.advanceAt(m_index);
+ m_translation = m_translation.translate(advance.width(), advance.height());
+ ++m_index;
+ if (m_index < m_glyphBuffer.size())
+ m_fontData = m_glyphBuffer.fontAt(m_index);
+}
+
+DashArray FontCascade::dashesForIntersectionsWithRect(const TextRun& run, const FloatPoint& textOrigin, const FloatRect& lineExtents) const
+{
+ if (isLoadingCustomFonts())
+ return DashArray();
+
+ GlyphBuffer glyphBuffer;
+ glyphBuffer.saveOffsetsInString();
+ float deltaX;
+ if (codePath(run) != FontCascade::Complex)
+ deltaX = getGlyphsAndAdvancesForSimpleText(run, 0, run.length(), glyphBuffer);
+ else
+ deltaX = getGlyphsAndAdvancesForComplexText(run, 0, run.length(), glyphBuffer);
+
+ if (!glyphBuffer.size())
+ return DashArray();
+
+ // FIXME: Handle SVG + non-SVG interleaved runs. https://bugs.webkit.org/show_bug.cgi?id=133778
+ FloatPoint origin = FloatPoint(textOrigin.x() + deltaX, textOrigin.y());
+ CairoGlyphToPathTranslator translator(run, glyphBuffer, origin);
+ DashArray result;
+ for (int index = 0; translator.containsMorePaths(); ++index, translator.advance()) {
+ float centerOfLine = lineExtents.y() + (lineExtents.height() / 2);
+ GlyphIterationState info = GlyphIterationState(FloatPoint(), FloatPoint(), centerOfLine, lineExtents.x() + lineExtents.width(), lineExtents.x());
+ const Font* localFontData = glyphBuffer.fontAt(index);
+ if (!localFontData) {
+ // The advances will get all messed up if we do anything other than bail here.
+ result.clear();
+ break;
+ }
+ switch (translator.underlineType()) {
+ case GlyphToPathTranslator::GlyphUnderlineType::SkipDescenders: {
+ Path path = translator.path();
+ path.apply([&info](const PathElement& pathElement) {
+ findPathIntersections(info, pathElement);
+ });
+ if (info.minX < info.maxX) {
+ result.append(info.minX - lineExtents.x());
+ result.append(info.maxX - lineExtents.x());
+ }
+ break;
+ }
+ case GlyphToPathTranslator::GlyphUnderlineType::SkipGlyph: {
+ std::pair<float, float> extents = translator.extents();
+ result.append(extents.first - lineExtents.x());
+ result.append(extents.second - lineExtents.x());
+ break;
+ }
+ case GlyphToPathTranslator::GlyphUnderlineType::DrawOverGlyph:
+ // Nothing to do
+ break;
+ }
+ }
+ return result;
+}
+#endif // ENABLE(CSS3_TEXT_DECORATION_SKIP_INK)
+
+} // namespace WebCore
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/FontCairoHarfbuzzNG.cpp b/Source/WebCore/platform/graphics/cairo/FontCairoHarfbuzzNG.cpp
index 0c940c5d6..cc37d7d58 100644
--- a/Source/WebCore/platform/graphics/cairo/FontCairoHarfbuzzNG.cpp
+++ b/Source/WebCore/platform/graphics/cairo/FontCairoHarfbuzzNG.cpp
@@ -11,10 +11,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -25,48 +25,44 @@
*/
#include "config.h"
-#include "Font.h"
+#include "FontCascade.h"
+
+#if USE(CAIRO)
+#include "Font.h"
#include "GraphicsContext.h"
#include "HarfBuzzShaper.h"
+#include "LayoutRect.h"
#include "Logging.h"
#include "NotImplemented.h"
#include "PlatformContextCairo.h"
-#include "SimpleFontData.h"
#include <cairo.h>
namespace WebCore {
-float Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int, int) const
+float FontCascade::getGlyphsAndAdvancesForComplexText(const TextRun& run, unsigned, unsigned, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot /* forTextEmphasis */) const
{
- GlyphBuffer glyphBuffer;
HarfBuzzShaper shaper(this, run);
- if (shaper.shape(&glyphBuffer)) {
- FloatPoint startPoint = point;
- float startX = startPoint.x();
- drawGlyphBuffer(context, run, glyphBuffer, startPoint);
- return startPoint.x() - startX;
+ if (!shaper.shape(&glyphBuffer)) {
+ LOG_ERROR("Shaper couldn't shape glyphBuffer.");
+ return 0;
}
- LOG_ERROR("Shaper couldn't shape glyphBuffer.");
- return 0;
-}
-void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
-{
- notImplemented();
+ // FIXME: Mac returns an initial advance here.
+ return 0;
}
-bool Font::canReturnFallbackFontsForComplexText()
+bool FontCascade::canReturnFallbackFontsForComplexText()
{
return false;
}
-bool Font::canExpandAroundIdeographsInComplexText()
+bool FontCascade::canExpandAroundIdeographsInComplexText()
{
return false;
}
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
+float FontCascade::floatWidthForComplexText(const TextRun& run, HashSet<const Font*>*, GlyphOverflow*) const
{
HarfBuzzShaper shaper(this, run);
if (shaper.shape())
@@ -75,7 +71,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
return 0;
}
-int Font::offsetForPositionForComplexText(const TextRun& run, float x, bool) const
+int FontCascade::offsetForPositionForComplexText(const TextRun& run, float x, bool) const
{
HarfBuzzShaper shaper(this, run);
if (shaper.shape())
@@ -84,13 +80,18 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float x, bool) con
return 0;
}
-FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
+void FontCascade::adjustSelectionRectForComplexText(const TextRun& run, LayoutRect& selectionRect, unsigned from, unsigned to) const
{
HarfBuzzShaper shaper(this, run);
- if (shaper.shape())
- return shaper.selectionRect(point, h, from, to);
+ if (shaper.shape()) {
+ // FIXME: This should mimic Mac port.
+ FloatRect rect = shaper.selectionRect(FloatPoint(selectionRect.location()), selectionRect.height().toInt(), from, to);
+ selectionRect = LayoutRect(rect);
+ return;
+ }
LOG_ERROR("Shaper couldn't shape text run.");
- return FloatRect();
}
-}
+} // namespace WebCore
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
index 1514526c2..c95ef9b5b 100644
--- a/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
+++ b/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
@@ -22,9 +22,9 @@
#ifndef FontCustomPlatformData_h
#define FontCustomPlatformData_h
-#include "FontOrientation.h"
-#include "FontRenderingMode.h"
-#include "FontWidthVariant.h"
+#if USE(CAIRO)
+
+#include "TextFlags.h"
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
@@ -33,6 +33,7 @@ typedef struct _cairo_font_face cairo_font_face_t;
namespace WebCore {
+class FontDescription;
class FontPlatformData;
class SharedBuffer;
@@ -41,16 +42,17 @@ struct FontCustomPlatformData {
public:
FontCustomPlatformData(FT_Face, SharedBuffer&);
~FontCustomPlatformData();
- FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
+ FontPlatformData fontPlatformData(const FontDescription&, bool bold, bool italic);
static bool supportsFormat(const String&);
private:
- FT_Face m_freeTypeFace;
cairo_font_face_t* m_fontFace;
};
std::unique_ptr<FontCustomPlatformData> createFontCustomPlatformData(SharedBuffer&);
-}
+} // namespace WebCore
+
+#endif // USE(CAIRO)
-#endif
+#endif // FontCustomPlatformData_h
diff --git a/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp b/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp
index e0cfe3e65..724d832cc 100644
--- a/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
*
* Redistribution and use in source and binary forms, with or without
@@ -11,10 +11,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -27,6 +27,8 @@
#include "config.h"
#include "Gradient.h"
+#if USE(CAIRO)
+
#include "GraphicsContext.h"
#include "PlatformContextCairo.h"
#include <cairo.h>
@@ -106,4 +108,6 @@ void Gradient::fill(GraphicsContext* context, const FloatRect& rect)
context->restore();
}
-} //namespace
+} // namespace WebCore
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp
index 940265a9a..b4ae79e4a 100644
--- a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp
@@ -12,10 +12,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -27,7 +27,9 @@
#include "config.h"
-#if USE(3D_GRAPHICS)
+#if USE(CAIRO)
+
+#if ENABLE(GRAPHICS_CONTEXT_3D)
#include "GraphicsContext3D.h"
#include "CairoUtilities.h"
@@ -38,13 +40,11 @@
#include "PlatformContextCairo.h"
#include "RefPtrCairo.h"
#include <cairo.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
#if PLATFORM(WIN)
-#include "GLSLANG/ShaderLang.h"
+#include <GLSLANG/ShaderLang.h>
#else
-#include "ShaderLang.h"
+#include <ANGLE/ShaderLang.h>
#endif
#if USE(OPENGL_ES_2)
@@ -54,9 +54,13 @@
#include "OpenGLShims.h"
#endif
+#if USE(TEXTURE_MAPPER)
+#include "TextureMapperGC3DPlatformLayer.h"
+#endif
+
namespace WebCore {
-PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attributes, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle)
+RefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3DAttributes attributes, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle)
{
// This implementation doesn't currently support rendering directly to the HostWindow.
if (renderStyle == RenderDirectlyToHostWindow)
@@ -73,24 +77,30 @@ PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attri
if (!success)
return 0;
- RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(attributes, hostWindow, renderStyle));
- return context.release();
+ return adoptRef(new GraphicsContext3D(attributes, hostWindow, renderStyle));
}
-GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attributes, HostWindow*, GraphicsContext3D::RenderStyle renderStyle)
+GraphicsContext3D::GraphicsContext3D(GraphicsContext3DAttributes attributes, HostWindow*, GraphicsContext3D::RenderStyle renderStyle)
: m_currentWidth(0)
, m_currentHeight(0)
- , m_compiler(isGLES2Compliant() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT)
, m_attrs(attributes)
, m_texture(0)
, m_compositorTexture(0)
, m_fbo(0)
- , m_depthStencilBuffer(0)
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ , m_intermediateTexture(0)
+#endif
+ , m_layerComposited(false)
, m_multisampleFBO(0)
, m_multisampleDepthStencilBuffer(0)
, m_multisampleColorBuffer(0)
- , m_private(GraphicsContext3DPrivate::create(this, renderStyle))
{
+#if USE(TEXTURE_MAPPER)
+ m_texmapLayer = std::make_unique<TextureMapperGC3DPlatformLayer>(*this, renderStyle);
+#else
+ m_private = std::make_unique<GraphicsContext3DPrivate>(this, renderStyle);
+#endif
+
makeContextCurrent();
validateAttributes();
@@ -109,9 +119,24 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attributes, H
::glGenFramebuffers(1, &m_fbo);
::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
- m_state.boundFBO = m_fbo;
- if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth))
- ::glGenRenderbuffers(1, &m_depthStencilBuffer);
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ ::glGenTextures(1, &m_compositorTexture);
+ ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ ::glGenTextures(1, &m_intermediateTexture);
+ ::glBindTexture(GL_TEXTURE_2D, m_intermediateTexture);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ ::glBindTexture(GL_TEXTURE_2D, 0);
+#endif
+
// Create a multisample FBO.
if (m_attrs.antialias) {
@@ -121,9 +146,51 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attributes, H
::glGenRenderbuffers(1, &m_multisampleColorBuffer);
if (m_attrs.stencil || m_attrs.depth)
::glGenRenderbuffers(1, &m_multisampleDepthStencilBuffer);
+ } else {
+ // Bind canvas FBO.
+ glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
+ m_state.boundFBO = m_fbo;
+#if USE(OPENGL_ES_2)
+ if (m_attrs.depth)
+ glGenRenderbuffers(1, &m_depthBuffer);
+ if (m_attrs.stencil)
+ glGenRenderbuffers(1, &m_stencilBuffer);
+#endif
+ if (m_attrs.stencil || m_attrs.depth)
+ glGenRenderbuffers(1, &m_depthStencilBuffer);
}
}
+#if !USE(OPENGL_ES_2)
+ ::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+
+ if (GLContext::current()->version() >= 320) {
+ m_usingCoreProfile = true;
+
+ // From version 3.2 on we use the OpenGL Core profile, so request that ouput to the shader compiler.
+ // OpenGL version 3.2 uses GLSL version 1.50.
+ m_compiler = ANGLEWebKitBridge(SH_GLSL_150_CORE_OUTPUT);
+
+ // From version 3.2 on we use the OpenGL Core profile, and we need a VAO for rendering.
+ // A VAO could be created and bound by each component using GL rendering (TextureMapper, WebGL, etc). This is
+ // a simpler solution: the first GraphicsContext3D created on a GLContext will create and bind a VAO for that context.
+ GC3Dint currentVAO = 0;
+ getIntegerv(GraphicsContext3D::VERTEX_ARRAY_BINDING, &currentVAO);
+ if (!currentVAO) {
+ m_vao = createVertexArray();
+ bindVertexArray(m_vao);
+ }
+ } else {
+ // For lower versions request the compatibility output to the shader compiler.
+ m_compiler = ANGLEWebKitBridge(SH_GLSL_COMPATIBILITY_OUTPUT);
+
+ // GL_POINT_SPRITE is needed in lower versions.
+ ::glEnable(GL_POINT_SPRITE);
+ }
+#else
+ m_compiler = ANGLEWebKitBridge(SH_ESSL_OUTPUT);
+#endif
+
// ANGLE initialization.
ShBuiltInResources ANGLEResources;
ShInitBuiltInResources(&ANGLEResources);
@@ -145,18 +212,18 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attributes, H
m_compiler.setResources(ANGLEResources);
-#if !USE(OPENGL_ES_2)
- ::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
- ::glEnable(GL_POINT_SPRITE);
-#endif
-
::glClearColor(0, 0, 0, 0);
}
GraphicsContext3D::~GraphicsContext3D()
{
+#if USE(TEXTURE_MAPPER)
+ if (m_texmapLayer->renderStyle() == RenderToCurrentGLContext)
+ return;
+#else
if (m_private->renderStyle() == RenderToCurrentGLContext)
return;
+#endif
makeContextCurrent();
if (m_texture)
@@ -169,11 +236,24 @@ GraphicsContext3D::~GraphicsContext3D()
if (m_attrs.stencil || m_attrs.depth)
::glDeleteRenderbuffers(1, &m_multisampleDepthStencilBuffer);
::glDeleteFramebuffers(1, &m_multisampleFBO);
- } else {
- if (m_attrs.stencil || m_attrs.depth)
+ } else if (m_attrs.stencil || m_attrs.depth) {
+#if USE(OPENGL_ES_2)
+ if (m_depthBuffer)
+ glDeleteRenderbuffers(1, &m_depthBuffer);
+
+ if (m_stencilBuffer)
+ glDeleteRenderbuffers(1, &m_stencilBuffer);
+#endif
+ if (m_depthStencilBuffer)
::glDeleteRenderbuffers(1, &m_depthStencilBuffer);
}
::glDeleteFramebuffers(1, &m_fbo);
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ ::glDeleteTextures(1, &m_intermediateTexture);
+#endif
+
+ if (m_vao)
+ deleteVertexArray(m_vao);
}
GraphicsContext3D::ImageExtractor::~ImageExtractor()
@@ -187,17 +267,21 @@ bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool
if (!m_image)
return false;
// We need this to stay in scope because the native image is just a shallow copy of the data.
- m_decoder = new ImageSource(premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied, ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied);
+ AlphaOption alphaOption = premultiplyAlpha ? AlphaOption::Premultiplied : AlphaOption::NotPremultiplied;
+ GammaAndColorProfileOption gammaAndColorProfileOption = ignoreGammaAndColorProfile ? GammaAndColorProfileOption::Ignored : GammaAndColorProfileOption::Applied;
+ m_decoder = new ImageSource(nullptr, alphaOption, gammaAndColorProfileOption);
+
if (!m_decoder)
return false;
- ImageSource& decoder = *m_decoder;
+ ImageSource& decoder = *m_decoder;
m_alphaOp = AlphaDoNothing;
+
if (m_image->data()) {
decoder.setData(m_image->data(), true);
- if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
+ if (!decoder.frameCount())
return false;
- m_imageSurface = decoder.createFrameAtIndex(0);
+ m_imageSurface = decoder.createFrameImageAtIndex(0);
} else {
m_imageSurface = m_image->nativeImageForCurrentFrame();
// 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value is 0xFF for each pixel,
@@ -209,9 +293,10 @@ bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool
// if m_imageSurface is not an image, extract a copy of the surface
if (m_imageSurface && cairo_surface_get_type(m_imageSurface.get()) != CAIRO_SURFACE_TYPE_IMAGE) {
- RefPtr<cairo_surface_t> tmpSurface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, m_imageWidth, m_imageHeight));
- copyRectFromOneSurfaceToAnother(m_imageSurface.get(), tmpSurface.get(), IntSize(), IntRect(0, 0, m_imageWidth, m_imageHeight), IntSize(), CAIRO_OPERATOR_SOURCE);
- m_imageSurface = tmpSurface.release();
+ IntSize surfaceSize = cairoSurfaceSize(m_imageSurface.get());
+ auto tmpSurface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, surfaceSize.width(), surfaceSize.height()));
+ copyRectFromOneSurfaceToAnother(m_imageSurface.get(), tmpSurface.get(), IntSize(), IntRect(IntPoint(), surfaceSize), IntSize(), CAIRO_OPERATOR_SOURCE);
+ m_imageSurface = WTFMove(tmpSurface);
}
}
@@ -272,24 +357,37 @@ void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imag
context->restore();
}
-void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>)
+void GraphicsContext3D::setContextLostCallback(std::unique_ptr<ContextLostCallback>)
{
}
-void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback>)
+void GraphicsContext3D::setErrorMessageCallback(std::unique_ptr<ErrorMessageCallback>)
{
}
bool GraphicsContext3D::makeContextCurrent()
{
- if (!m_private)
- return false;
- return m_private->makeContextCurrent();
+#if USE(TEXTURE_MAPPER)
+ if (m_texmapLayer)
+ return m_texmapLayer->makeContextCurrent();
+#else
+ if (m_private)
+ return m_private->makeContextCurrent();
+#endif
+ return false;
+}
+
+void GraphicsContext3D::checkGPUStatusIfNecessary()
+{
}
PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D()
{
+#if USE(TEXTURE_MAPPER)
+ return m_texmapLayer->platformContext();
+#else
return m_private->platformContext();
+#endif
}
Platform3DObject GraphicsContext3D::platformTexture() const
@@ -306,13 +404,33 @@ bool GraphicsContext3D::isGLES2Compliant() const
#endif
}
-#if USE(ACCELERATED_COMPOSITING)
PlatformLayer* GraphicsContext3D::platformLayer() const
{
+#if USE(TEXTURE_MAPPER)
+ return m_texmapLayer.get();
+#else
return m_private.get();
+#endif
+}
+
+#if PLATFORM(GTK)
+Extensions3D& GraphicsContext3D::getExtensions()
+{
+ if (!m_extensions) {
+#if USE(OPENGL_ES_2)
+ // glGetStringi is not available on GLES2.
+ m_extensions = std::make_unique<Extensions3DOpenGLES>(this, false);
+#else
+ // From OpenGL 3.2 on we use the Core profile, and there we must use glGetStringi.
+ m_extensions = std::make_unique<Extensions3DOpenGL>(this, GLContext::current()->version() >= 320);
+#endif
+ }
+ return *m_extensions;
}
#endif
} // namespace WebCore
-#endif // USE(3D_GRAPHICS)
+#endif // ENABLE(GRAPHICS_CONTEXT_3D)
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 0fa750396..ac4b4a089 100644
--- a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
* Copyright (C) 2008, 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) 2008 Nuanti Ltd.
@@ -17,10 +17,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -37,30 +37,29 @@
#include "AffineTransform.h"
#include "CairoUtilities.h"
+#include "DisplayListRecorder.h"
#include "DrawErrorUnderline.h"
#include "FloatConversion.h"
#include "FloatRect.h"
+#include "FloatRoundedRect.h"
#include "Font.h"
#include "GraphicsContextPlatformPrivateCairo.h"
+#include "ImageBuffer.h"
#include "IntRect.h"
#include "NotImplemented.h"
-#include "OwnPtrCairo.h"
#include "Path.h"
#include "Pattern.h"
#include "PlatformContextCairo.h"
#include "PlatformPathCairo.h"
#include "RefPtrCairo.h"
#include "ShadowBlur.h"
-#include "SimpleFontData.h"
#include "TransformationMatrix.h"
#include <cairo.h>
#include <math.h>
#include <stdio.h>
#include <wtf/MathExtras.h>
-#if PLATFORM(GTK)
-#include <gdk/gdk.h>
-#elif PLATFORM(WIN)
+#if PLATFORM(WIN)
#include <cairo-win32.h>
#endif
@@ -71,36 +70,31 @@ namespace WebCore {
// A helper which quickly fills a rectangle with a simple color fill.
static inline void fillRectWithColor(cairo_t* cr, const FloatRect& rect, const Color& color)
{
- if (!color.alpha() && cairo_get_operator(cr) == CAIRO_OPERATOR_OVER)
+ if (!color.isVisible() && cairo_get_operator(cr) == CAIRO_OPERATOR_OVER)
return;
+
setSourceRGBAFromColor(cr, color);
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
cairo_fill(cr);
}
-static void addConvexPolygonToContext(cairo_t* context, size_t numPoints, const FloatPoint* points)
-{
- cairo_move_to(context, points[0].x(), points[0].y());
- for (size_t i = 1; i < numPoints; i++)
- cairo_line_to(context, points[i].x(), points[i].y());
- cairo_close_path(context);
-}
-
enum PathDrawingStyle {
Fill = 1,
Stroke = 2,
FillAndStroke = Fill + Stroke
};
-static inline void drawPathShadow(GraphicsContext* context, PathDrawingStyle drawingStyle)
+static inline void drawPathShadow(GraphicsContext& context, PathDrawingStyle drawingStyle)
{
- ShadowBlur& shadow = context->platformContext()->shadowBlur();
+ ShadowBlur& shadow = context.platformContext()->shadowBlur();
if (shadow.type() == ShadowBlur::NoShadow)
return;
// Calculate the extents of the rendered solid paths.
- cairo_t* cairoContext = context->platformContext()->cr();
- OwnPtr<cairo_path_t> path = adoptPtr(cairo_copy_path(cairoContext));
+ cairo_t* cairoContext = context.platformContext()->cr();
+ std::unique_ptr<cairo_path_t, void(*)(cairo_path_t*)> path(cairo_copy_path(cairoContext), [](cairo_path_t* path) {
+ cairo_path_destroy(path);
+ });
FloatRect solidFigureExtents;
double x0 = 0;
@@ -130,14 +124,14 @@ static inline void drawPathShadow(GraphicsContext* context, PathDrawingStyle dra
if (drawingStyle & Fill) {
cairo_save(cairoShadowContext);
cairo_append_path(cairoShadowContext, path.get());
- shadowContext->platformContext()->prepareForFilling(context->state(), PlatformContextCairo::NoAdjustment);
+ shadowContext->platformContext()->prepareForFilling(context.state(), PlatformContextCairo::NoAdjustment);
cairo_fill(cairoShadowContext);
cairo_restore(cairoShadowContext);
}
if (drawingStyle & Stroke) {
cairo_append_path(cairoShadowContext, path.get());
- shadowContext->platformContext()->prepareForStroking(context->state(), PlatformContextCairo::DoNotPreserveAlpha);
+ shadowContext->platformContext()->prepareForStroking(context.state(), PlatformContextCairo::DoNotPreserveAlpha);
cairo_stroke(cairoShadowContext);
}
@@ -150,44 +144,45 @@ static inline void drawPathShadow(GraphicsContext* context, PathDrawingStyle dra
cairo_append_path(cairoContext, path.get());
}
-static inline void fillCurrentCairoPath(GraphicsContext* context)
+static inline void fillCurrentCairoPath(GraphicsContext& context)
{
- cairo_t* cr = context->platformContext()->cr();
+ cairo_t* cr = context.platformContext()->cr();
cairo_save(cr);
- context->platformContext()->prepareForFilling(context->state(), PlatformContextCairo::AdjustPatternForGlobalAlpha);
+ context.platformContext()->prepareForFilling(context.state(), PlatformContextCairo::AdjustPatternForGlobalAlpha);
cairo_fill(cr);
cairo_restore(cr);
}
-static inline void shadowAndFillCurrentCairoPath(GraphicsContext* context)
+static inline void shadowAndFillCurrentCairoPath(GraphicsContext& context)
{
drawPathShadow(context, Fill);
fillCurrentCairoPath(context);
}
-static inline void shadowAndStrokeCurrentCairoPath(GraphicsContext* context)
+static inline void shadowAndStrokeCurrentCairoPath(GraphicsContext& context)
{
drawPathShadow(context, Stroke);
- context->platformContext()->prepareForStroking(context->state());
- cairo_stroke(context->platformContext()->cr());
+ context.platformContext()->prepareForStroking(context.state());
+ cairo_stroke(context.platformContext()->cr());
}
GraphicsContext::GraphicsContext(cairo_t* cr)
- : m_updatingControlTints(false),
- m_transparencyCount(0)
{
+ if (!cr)
+ return;
+
m_data = new GraphicsContextPlatformPrivateToplevel(new PlatformContextCairo(cr));
}
void GraphicsContext::platformInit(PlatformContextCairo* platformContext)
{
+ if (!platformContext)
+ return;
+
m_data = new GraphicsContextPlatformPrivate(platformContext);
- if (platformContext)
- m_data->syncContext(platformContext->cr());
- else
- setPaintingDisabled(true);
+ m_data->syncContext(platformContext->cr());
}
void GraphicsContext::platformDestroy()
@@ -200,6 +195,11 @@ AffineTransform GraphicsContext::getCTM(IncludeDeviceScale) const
if (paintingDisabled())
return AffineTransform();
+ if (isRecording()) {
+ WTFLogAlways("GraphicsContext::getCTM() is not yet compatible with recording contexts.");
+ return AffineTransform();
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_matrix_t m;
cairo_get_matrix(cr, &m);
@@ -213,28 +213,34 @@ PlatformContextCairo* GraphicsContext::platformContext() const
void GraphicsContext::savePlatformState()
{
+ ASSERT(!isRecording());
platformContext()->save();
m_data->save();
}
void GraphicsContext::restorePlatformState()
{
+ ASSERT(!isRecording());
platformContext()->restore();
m_data->restore();
platformContext()->shadowBlur().setShadowValues(FloatSize(m_state.shadowBlur, m_state.shadowBlur),
m_state.shadowOffset,
m_state.shadowColor,
- m_state.shadowColorSpace,
m_state.shadowsIgnoreTransforms);
}
// Draws a filled rectangle with a stroked border.
-void GraphicsContext::drawRect(const IntRect& rect)
+void GraphicsContext::drawRect(const FloatRect& rect, float borderThickness)
{
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawRect(rect, borderThickness);
+ return;
+ }
+
ASSERT(!rect.isEmpty());
cairo_t* cr = platformContext()->cr();
@@ -247,108 +253,132 @@ void GraphicsContext::drawRect(const IntRect& rect)
FloatRect r(rect);
r.inflate(-.5f);
cairo_rectangle(cr, r.x(), r.y(), r.width(), r.height());
- cairo_set_line_width(cr, 1.0);
+ cairo_set_line_width(cr, 1.0); // borderThickness?
cairo_stroke(cr);
}
cairo_restore(cr);
}
-static double calculateStrokePatternOffset(int distance, int patternWidth)
+void GraphicsContext::drawNativeImage(const NativeImagePtr& image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode blendMode, ImageOrientation orientation)
{
- // Example: 80 pixels with a width of 30 pixels. Remainder is 20.
- // The maximum pixels of line we could paint will be 50 pixels.
- int remainder = distance % patternWidth;
- int numSegments = (distance - remainder) / patternWidth;
+ if (paintingDisabled())
+ return;
- // Special case 1px dotted borders for speed.
- if (patternWidth == 1)
- return 1;
+ if (isRecording()) {
+ m_displayListRecorder->drawNativeImage(image, imageSize, destRect, srcRect, op, blendMode, orientation);
+ return;
+ }
- bool evenNumberOfSegments = !(numSegments % 2);
- if (remainder)
- evenNumberOfSegments = !evenNumberOfSegments;
+ platformContext()->save();
- if (evenNumberOfSegments) {
- if (remainder)
- return (patternWidth - remainder) + (remainder / 2);
- return patternWidth / 2;
+ // Set the compositing operation.
+ if (op == CompositeSourceOver && blendMode == BlendModeNormal)
+ setCompositeOperation(CompositeCopy);
+ else
+ setCompositeOperation(op, blendMode);
+
+ FloatRect dst = destRect;
+
+ if (orientation != DefaultImageOrientation) {
+ // ImageOrientation expects the origin to be at (0, 0).
+ translate(dst.x(), dst.y());
+ dst.setLocation(FloatPoint());
+ concatCTM(orientation.transformFromDefault(dst.size()));
+ if (orientation.usesWidthAsHeight()) {
+ // The destination rectangle will have its width and height already reversed for the orientation of
+ // the image, as it was needed for page layout, so we need to reverse it back here.
+ dst = FloatRect(dst.x(), dst.y(), dst.height(), dst.width());
+ }
}
- // Odd number of segments.
- if (remainder)
- return (patternWidth - remainder) / 2.f;
- return 0;
+ platformContext()->drawSurfaceToContext(image.get(), dst, srcRect, *this);
+ platformContext()->restore();
}
-static void drawLineOnCairoContext(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point1, const FloatPoint& point2)
+// This is only used to draw borders, so we should not draw shadows.
+void GraphicsContext::drawLine(const FloatPoint& point1, const FloatPoint& point2)
{
- StrokeStyle style = graphicsContext->strokeStyle();
- if (style == NoStroke)
+ if (paintingDisabled())
return;
- const Color& strokeColor = graphicsContext->strokeColor();
- int strokeThickness = floorf(graphicsContext->strokeThickness());
- if (graphicsContext->strokeThickness() < 1)
- strokeThickness = 1;
+ if (strokeStyle() == NoStroke)
+ return;
- int patternWidth = 0;
- if (style == DottedStroke)
- patternWidth = strokeThickness;
- else if (style == DashedStroke)
- patternWidth = 3 * strokeThickness;
+ if (isRecording()) {
+ m_displayListRecorder->drawLine(point1, point2);
+ return;
+ }
- bool isVerticalLine = point1.x() == point2.x();
- FloatPoint point1OnPixelBoundaries = point1;
- FloatPoint point2OnPixelBoundaries = point2;
- GraphicsContext::adjustLineToPixelBoundaries(point1OnPixelBoundaries, point2OnPixelBoundaries, strokeThickness, style);
+ const Color& strokeColor = this->strokeColor();
+ float thickness = strokeThickness();
+ bool isVerticalLine = (point1.x() + thickness == point2.x());
+ float strokeWidth = isVerticalLine ? point2.y() - point1.y() : point2.x() - point1.x();
+ if (!thickness || !strokeWidth)
+ return;
- if (patternWidth) {
- // Do a rect fill of our endpoints. This ensures we always have the
- // appearance of being a border. We then draw the actual dotted/dashed line.
- FloatRect firstRect(point1OnPixelBoundaries, FloatSize(strokeThickness, strokeThickness));
- FloatRect secondRect(point2OnPixelBoundaries, FloatSize(strokeThickness, strokeThickness));
+ cairo_t* cairoContext = platformContext()->cr();
+ StrokeStyle strokeStyle = this->strokeStyle();
+ float cornerWidth = 0;
+ bool drawsDashedLine = strokeStyle == DottedStroke || strokeStyle == DashedStroke;
+
+ if (drawsDashedLine) {
+ cairo_save(cairoContext);
+ // Figure out end points to ensure we always paint corners.
+ cornerWidth = dashedLineCornerWidthForStrokeWidth(strokeWidth);
if (isVerticalLine) {
- firstRect.move(-strokeThickness / 2, -strokeThickness);
- secondRect.move(-strokeThickness / 2, 0);
+ fillRectWithColor(cairoContext, FloatRect(point1.x(), point1.y(), thickness, cornerWidth), strokeColor);
+ fillRectWithColor(cairoContext, FloatRect(point1.x(), point2.y() - cornerWidth, thickness, cornerWidth), strokeColor);
} else {
- firstRect.move(-strokeThickness, -strokeThickness / 2);
- secondRect.move(0, -strokeThickness / 2);
+ fillRectWithColor(cairoContext, FloatRect(point1.x(), point1.y(), cornerWidth, thickness), strokeColor);
+ fillRectWithColor(cairoContext, FloatRect(point2.x() - cornerWidth, point1.y(), cornerWidth, thickness), strokeColor);
+ }
+ strokeWidth -= 2 * cornerWidth;
+ float patternWidth = dashedLinePatternWidthForStrokeWidth(strokeWidth);
+ // Check if corner drawing sufficiently covers the line.
+ if (strokeWidth <= patternWidth + 1) {
+ cairo_restore(cairoContext);
+ return;
}
- fillRectWithColor(context, firstRect, strokeColor);
- fillRectWithColor(context, secondRect, strokeColor);
- int distance = (isVerticalLine ? (point2.y() - point1.y()) : (point2.x() - point1.x())) - 2 * strokeThickness;
- double patternOffset = calculateStrokePatternOffset(distance, patternWidth);
- double patternWidthAsDouble = patternWidth;
- cairo_set_dash(context, &patternWidthAsDouble, 1, patternOffset);
+ float patternOffset = dashedLinePatternOffsetForPatternAndStrokeWidth(patternWidth, strokeWidth);
+ const double dashedLine[2] = { static_cast<double>(patternWidth), static_cast<double>(patternWidth) };
+ cairo_set_dash(cairoContext, dashedLine, 2, patternOffset);
+ } else {
+ setSourceRGBAFromColor(cairoContext, strokeColor);
+ if (thickness < 1)
+ cairo_set_line_width(cairoContext, 1);
}
- setSourceRGBAFromColor(context, strokeColor);
- cairo_set_line_width(context, strokeThickness);
- cairo_move_to(context, point1OnPixelBoundaries.x(), point1OnPixelBoundaries.y());
- cairo_line_to(context, point2OnPixelBoundaries.x(), point2OnPixelBoundaries.y());
- cairo_stroke(context);
-}
-// This is only used to draw borders, so we should not draw shadows.
-void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
-{
- if (paintingDisabled())
- return;
+ auto centeredPoints = centerLineAndCutOffCorners(isVerticalLine, cornerWidth, point1, point2);
+ auto p1 = centeredPoints[0];
+ auto p2 = centeredPoints[1];
- cairo_t* cairoContext = platformContext()->cr();
- cairo_save(cairoContext);
- drawLineOnCairoContext(this, cairoContext, point1, point2);
- cairo_restore(cairoContext);
+ if (shouldAntialias())
+ cairo_set_antialias(cairoContext, CAIRO_ANTIALIAS_NONE);
+
+ cairo_new_path(cairoContext);
+ cairo_move_to(cairoContext, p1.x(), p1.y());
+ cairo_line_to(cairoContext, p2.x(), p2.y());
+ cairo_stroke(cairoContext);
+ if (drawsDashedLine)
+ cairo_restore(cairoContext);
+ if (shouldAntialias())
+ cairo_set_antialias(cairoContext, CAIRO_ANTIALIAS_DEFAULT);
}
// This method is only used to draw the little circles used in lists.
-void GraphicsContext::drawEllipse(const IntRect& rect)
+void GraphicsContext::drawEllipse(const FloatRect& rect)
{
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawEllipse(rect);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_save(cr);
float yRadius = .5 * rect.height();
@@ -358,7 +388,7 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
cairo_arc(cr, 0., 0., 1., 0., 2 * piFloat);
cairo_restore(cr);
- if (fillColor().alpha()) {
+ if (fillColor().isVisible()) {
setSourceRGBAFromColor(cr, fillColor());
cairo_fill_preserve(cr);
}
@@ -371,67 +401,19 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
cairo_new_path(cr);
}
-void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
+void GraphicsContext::fillPath(const Path& path)
{
- if (paintingDisabled())
+ if (paintingDisabled() || path.isEmpty())
return;
- if (npoints <= 1)
+ if (isRecording()) {
+ m_displayListRecorder->fillPath(path);
return;
-
- cairo_t* cr = platformContext()->cr();
-
- cairo_save(cr);
- cairo_set_antialias(cr, shouldAntialias ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
- addConvexPolygonToContext(cr, npoints, points);
-
- if (fillColor().alpha()) {
- setSourceRGBAFromColor(cr, fillColor());
- cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
- cairo_fill_preserve(cr);
}
- if (strokeStyle() != NoStroke) {
- setSourceRGBAFromColor(cr, strokeColor());
- cairo_set_line_width(cr, strokeThickness());
- cairo_stroke(cr);
- } else
- cairo_new_path(cr);
-
- cairo_restore(cr);
-}
-
-void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased)
-{
- if (paintingDisabled())
- return;
-
- if (numPoints <= 1)
- return;
-
- cairo_t* cr = platformContext()->cr();
-
- cairo_new_path(cr);
- cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
- cairo_antialias_t savedAntialiasRule = cairo_get_antialias(cr);
-
- cairo_set_antialias(cr, antialiased ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
- cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
- addConvexPolygonToContext(cr, numPoints, points);
- cairo_clip(cr);
-
- cairo_set_antialias(cr, savedAntialiasRule);
- cairo_set_fill_rule(cr, savedFillRule);
-}
-
-void GraphicsContext::fillPath(const Path& path)
-{
- if (paintingDisabled() || path.isEmpty())
- return;
-
cairo_t* cr = platformContext()->cr();
setPathOnCairoContext(cr, path.platformPath()->context());
- shadowAndFillCurrentCairoPath(this);
+ shadowAndFillCurrentCairoPath(*this);
}
void GraphicsContext::strokePath(const Path& path)
@@ -439,9 +421,14 @@ void GraphicsContext::strokePath(const Path& path)
if (paintingDisabled() || path.isEmpty())
return;
+ if (isRecording()) {
+ m_displayListRecorder->strokePath(path);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
setPathOnCairoContext(cr, path.platformPath()->context());
- shadowAndStrokeCurrentCairoPath(this);
+ shadowAndStrokeCurrentCairoPath(*this);
}
void GraphicsContext::fillRect(const FloatRect& rect)
@@ -449,18 +436,28 @@ void GraphicsContext::fillRect(const FloatRect& rect)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->fillRect(rect);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
- shadowAndFillCurrentCairoPath(this);
+ shadowAndFillCurrentCairoPath(*this);
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
{
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->fillRect(rect, color);
+ return;
+ }
+
if (hasShadow())
- platformContext()->shadowBlur().drawRectShadow(this, rect, RoundedRect::Radii());
+ platformContext()->shadowBlur().drawRectShadow(*this, FloatRoundedRect(rect));
fillRectWithColor(platformContext()->cr(), rect, color);
}
@@ -470,6 +467,11 @@ void GraphicsContext::clip(const FloatRect& rect)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->clip(rect);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
@@ -492,15 +494,44 @@ void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->clipPath(path, clipRule);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
if (!path.isNull())
setPathOnCairoContext(cr, path.platformPath()->context());
+
+ cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
cairo_set_fill_rule(cr, clipRule == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
cairo_clip(cr);
+ cairo_set_fill_rule(cr, savedFillRule);
+
+ m_data->clip(path);
+}
+
+void GraphicsContext::clipToImageBuffer(ImageBuffer& buffer, const FloatRect& destRect)
+{
+ if (paintingDisabled())
+ return;
+
+ RefPtr<Image> image = buffer.copyImage(DontCopyBackingStore);
+ RefPtr<cairo_surface_t> surface = image->nativeImageForCurrentFrame();
+ if (surface)
+ platformContext()->pushImageMask(surface.get(), destRect);
}
IntRect GraphicsContext::clipBounds() const
{
+ if (paintingDisabled())
+ return IntRect();
+
+ if (isRecording()) {
+ WTFLogAlways("Getting the clip bounds not yet supported with display lists");
+ return IntRect(-2048, -2048, 4096, 4096); // FIXME: display lists.
+ }
+
double x1, x2, y1, y2;
cairo_clip_extents(platformContext()->cr(), &x1, &y1, &x2, &y2);
return enclosingIntRect(FloatRect(x1, y1, x2 - x1, y2 - y1));
@@ -510,11 +541,13 @@ static inline void adjustFocusRingColor(Color& color)
{
#if !PLATFORM(GTK)
// Force the alpha to 50%. This matches what the Mac does with outline rings.
- color.setRGB(makeRGBA(color.red(), color.green(), color.blue(), 127));
+ color = Color(makeRGBA(color.red(), color.green(), color.blue(), 127));
+#else
+ UNUSED_PARAM(color);
#endif
}
-static inline void adjustFocusRingLineWidth(int& width)
+static inline void adjustFocusRingLineWidth(float& width)
{
#if PLATFORM(GTK)
width = 2;
@@ -532,8 +565,11 @@ static inline StrokeStyle focusRingStrokeStyle()
#endif
}
-void GraphicsContext::drawFocusRing(const Path& path, int width, int /* offset */, const Color& color)
+void GraphicsContext::drawFocusRing(const Path& path, float width, float /* offset */, const Color& color)
{
+ if (paintingDisabled())
+ return;
+
// FIXME: We should draw paths that describe a rectangle with rounded corners
// so as to be consistent with how we draw rectangular focus rings.
Color ringColor = color;
@@ -542,109 +578,91 @@ void GraphicsContext::drawFocusRing(const Path& path, int width, int /* offset *
cairo_t* cr = platformContext()->cr();
cairo_save(cr);
+ cairo_push_group(cr);
appendWebCorePathToCairoContext(cr, path);
setSourceRGBAFromColor(cr, ringColor);
cairo_set_line_width(cr, width);
setPlatformStrokeStyle(focusRingStrokeStyle());
- cairo_stroke(cr);
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+ cairo_stroke_preserve(cr);
+
+ cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
+ cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
+ cairo_fill(cr);
+
+ cairo_pop_group_to_source(cr);
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+ cairo_paint(cr);
cairo_restore(cr);
}
-void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int /* offset */, const Color& color)
+void GraphicsContext::drawFocusRing(const Vector<FloatRect>& rects, float width, float /* offset */, const Color& color)
{
if (paintingDisabled())
return;
- unsigned rectCount = rects.size();
-
- cairo_t* cr = platformContext()->cr();
- cairo_save(cr);
- cairo_push_group(cr);
- cairo_new_path(cr);
-
+ Path path;
#if PLATFORM(GTK)
-#ifdef GTK_API_VERSION_2
- GdkRegion* reg = gdk_region_new();
-#else
- cairo_region_t* reg = cairo_region_create();
-#endif
-
- for (unsigned i = 0; i < rectCount; i++) {
-#ifdef GTK_API_VERSION_2
- GdkRectangle rect = rects[i];
- gdk_region_union_with_rect(reg, &rect);
-#else
- cairo_rectangle_int_t rect = rects[i];
- cairo_region_union_rectangle(reg, &rect);
-#endif
- }
- gdk_cairo_region(cr, reg);
-#ifdef GTK_API_VERSION_2
- gdk_region_destroy(reg);
-#else
- cairo_region_destroy(reg);
-#endif
+ for (const auto& rect : rects)
+ path.addRect(rect);
#else
+ unsigned rectCount = rects.size();
int radius = (width - 1) / 2;
- Path path;
+ Path subPath;
for (unsigned i = 0; i < rectCount; ++i) {
if (i > 0)
- path.clear();
- path.addRoundedRect(rects[i], FloatSize(radius, radius));
- appendWebCorePathToCairoContext(cr, path);
+ subPath.clear();
+ subPath.addRoundedRect(rects[i], FloatSize(radius, radius));
+ path.addPath(subPath, AffineTransform());
}
#endif
- Color ringColor = color;
- adjustFocusRingColor(ringColor);
- adjustFocusRingLineWidth(width);
- setSourceRGBAFromColor(cr, ringColor);
- cairo_set_line_width(cr, width);
- setPlatformStrokeStyle(focusRingStrokeStyle());
-
- cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
- cairo_stroke_preserve(cr);
-
- cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
- cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
- cairo_fill(cr);
-
- cairo_pop_group_to_source(cr);
- cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
- cairo_paint(cr);
- cairo_restore(cr);
+ drawFocusRing(path, width, 0, color);
}
-FloatRect GraphicsContext::computeLineBoundsForText(const FloatPoint& origin, float width, bool)
+void GraphicsContext::drawLineForText(const FloatPoint& origin, float width, bool printing, bool doubleUnderlines, StrokeStyle)
{
- return FloatRect(origin, FloatSize(width, strokeThickness()));
+ DashArray widths;
+ widths.append(width);
+ widths.append(0);
+ drawLinesForText(origin, widths, printing, doubleUnderlines);
}
-void GraphicsContext::drawLineForText(const FloatPoint& origin, float width, bool printing)
+void GraphicsContext::drawLinesForText(const FloatPoint& point, const DashArray& widths, bool printing, bool doubleUnderlines, StrokeStyle)
{
if (paintingDisabled())
return;
- cairo_t* cairoContext = platformContext()->cr();
- cairo_save(cairoContext);
-
- // This bumping of <1 stroke thicknesses matches the one in drawLineOnCairoContext.
- FloatPoint endPoint(origin + IntSize(width, 0));
- FloatRect lineExtents = computeLineBoundsForText(origin, width, printing);
+ if (widths.size() <= 0)
+ return;
- ShadowBlur& shadow = platformContext()->shadowBlur();
- if (GraphicsContext* shadowContext = shadow.beginShadowLayer(this, lineExtents)) {
- drawLineOnCairoContext(this, shadowContext->platformContext()->cr(), origin, endPoint);
- shadow.endShadowLayer(this);
+ if (isRecording()) {
+ m_displayListRecorder->drawLinesForText(point, widths, printing, doubleUnderlines, strokeThickness());
+ return;
}
- drawLineOnCairoContext(this, cairoContext, origin, endPoint);
- cairo_restore(cairoContext);
-}
+ Color localStrokeColor(strokeColor());
-void GraphicsContext::drawLinesForText(const FloatPoint& point, const DashArray& widths, bool printing)
-{
+ FloatRect bounds = computeLineBoundsAndAntialiasingModeForText(point, widths.last(), printing, localStrokeColor);
+
+ Vector<FloatRect, 4> dashBounds;
+ ASSERT(!(widths.size() % 2));
+ dashBounds.reserveInitialCapacity(dashBounds.size() / 2);
for (size_t i = 0; i < widths.size(); i += 2)
- drawLineForText(FloatPoint(point.x() + widths[i], point.y()), widths[i+1] - widths[i], printing);
+ dashBounds.append(FloatRect(FloatPoint(bounds.x() + widths[i], bounds.y()), FloatSize(widths[i+1] - widths[i], bounds.height())));
+
+ if (doubleUnderlines) {
+ // The space between double underlines is equal to the height of the underline
+ for (size_t i = 0; i < widths.size(); i += 2)
+ dashBounds.append(FloatRect(FloatPoint(bounds.x() + widths[i], bounds.y() + 2 * bounds.height()), FloatSize(widths[i+1] - widths[i], bounds.height())));
+ }
+
+ cairo_t* cr = platformContext()->cr();
+ cairo_save(cr);
+
+ for (auto& dash : dashBounds)
+ fillRectWithColor(cr, dash, localStrokeColor);
+
+ cairo_restore(cr);
}
void GraphicsContext::updateDocumentMarkerResources()
@@ -679,6 +697,14 @@ void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& origin, float
FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect, RoundingMode)
{
+ if (paintingDisabled())
+ return frect;
+
+ if (isRecording()) {
+ WTFLogAlways("GraphicsContext::roundToDevicePixels() is not yet compatible with recording contexts.");
+ return frect;
+ }
+
FloatRect result;
double x = frect.x();
double y = frect.y();
@@ -701,7 +727,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect, RoundingM
width = 1;
else
width = round(width);
- if (height > -1 && width < 0)
+ if (height > -1 && height < 0)
height = -1;
else if (height > 0 && height < 1)
height = 1;
@@ -719,18 +745,23 @@ void GraphicsContext::translate(float x, float y)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->translate(x, y);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_translate(cr, x, y);
m_data->translate(x, y);
}
-void GraphicsContext::setPlatformFillColor(const Color&, ColorSpace)
+void GraphicsContext::setPlatformFillColor(const Color&)
{
// Cairo contexts can't hold separate fill and stroke colors
// so we set them just before we actually fill or stroke
}
-void GraphicsContext::setPlatformStrokeColor(const Color&, ColorSpace)
+void GraphicsContext::setPlatformStrokeColor(const Color&)
{
// Cairo contexts can't hold separate fill and stroke colors
// so we set them just before we actually fill or stroke
@@ -741,17 +772,21 @@ void GraphicsContext::setPlatformStrokeThickness(float strokeThickness)
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
cairo_set_line_width(platformContext()->cr(), strokeThickness);
}
void GraphicsContext::setPlatformStrokeStyle(StrokeStyle strokeStyle)
{
- static double dashPattern[] = {5.0, 5.0};
- static double dotPattern[] = {1.0, 1.0};
+ static const double dashPattern[] = { 5.0, 5.0 };
+ static const double dotPattern[] = { 1.0, 1.0 };
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
switch (strokeStyle) {
case NoStroke:
// FIXME: is it the right way to emulate NoStroke?
@@ -771,7 +806,7 @@ void GraphicsContext::setPlatformStrokeStyle(StrokeStyle strokeStyle)
}
}
-void GraphicsContext::setURLForRect(const URL&, const IntRect&)
+void GraphicsContext::setURLForRect(const URL&, const FloatRect&)
{
notImplemented();
}
@@ -781,6 +816,11 @@ void GraphicsContext::concatCTM(const AffineTransform& transform)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->concatCTM(transform);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
const cairo_matrix_t matrix = cairo_matrix_t(transform);
cairo_transform(cr, &matrix);
@@ -792,13 +832,18 @@ void GraphicsContext::setCTM(const AffineTransform& transform)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ WTFLogAlways("GraphicsContext::setCTM() is not compatible with recording contexts.");
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
const cairo_matrix_t matrix = cairo_matrix_t(transform);
cairo_set_matrix(cr, &matrix);
m_data->setCTM(transform);
}
-void GraphicsContext::setPlatformShadow(FloatSize const& size, float, Color const&, ColorSpace)
+void GraphicsContext::setPlatformShadow(FloatSize const& size, float, Color const&)
{
if (paintingDisabled())
return;
@@ -813,7 +858,6 @@ void GraphicsContext::setPlatformShadow(FloatSize const& size, float, Color cons
platformContext()->shadowBlur().setShadowValues(FloatSize(m_state.shadowBlur, m_state.shadowBlur),
m_state.shadowOffset,
m_state.shadowColor,
- m_state.shadowColorSpace,
m_state.shadowsIgnoreTransforms);
}
@@ -830,6 +874,8 @@ void GraphicsContext::beginPlatformTransparencyLayer(float opacity)
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
cairo_t* cr = platformContext()->cr();
cairo_push_group(cr);
m_data->layers.append(opacity);
@@ -840,6 +886,8 @@ void GraphicsContext::endPlatformTransparencyLayer()
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
cairo_t* cr = platformContext()->cr();
cairo_pop_group_to_source(cr);
@@ -857,6 +905,11 @@ void GraphicsContext::clearRect(const FloatRect& rect)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->clearRect(rect);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_save(cr);
@@ -871,11 +924,16 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float width)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->strokeRect(rect, width);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_save(cr);
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
cairo_set_line_width(cr, width);
- shadowAndStrokeCurrentCairoPath(this);
+ shadowAndStrokeCurrentCairoPath(*this);
cairo_restore(cr);
}
@@ -884,6 +942,11 @@ void GraphicsContext::setLineCap(LineCap lineCap)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->setLineCap(lineCap);
+ return;
+ }
+
cairo_line_cap_t cairoCap = CAIRO_LINE_CAP_BUTT;
switch (lineCap) {
case ButtCap:
@@ -899,9 +962,29 @@ void GraphicsContext::setLineCap(LineCap lineCap)
cairo_set_line_cap(platformContext()->cr(), cairoCap);
}
+static inline bool isDashArrayAllZero(const DashArray& dashes)
+{
+ for (auto& dash : dashes) {
+ if (dash)
+ return false;
+ }
+ return true;
+}
+
void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
{
- cairo_set_dash(platformContext()->cr(), dashes.data(), dashes.size(), dashOffset);
+ if (paintingDisabled())
+ return;
+
+ if (isRecording()) {
+ m_displayListRecorder->setLineDash(dashes, dashOffset);
+ return;
+ }
+
+ if (isDashArrayAllZero(dashes))
+ cairo_set_dash(platformContext()->cr(), 0, 0, 0);
+ else
+ cairo_set_dash(platformContext()->cr(), dashes.data(), dashes.size(), dashOffset);
}
void GraphicsContext::setLineJoin(LineJoin lineJoin)
@@ -909,6 +992,11 @@ void GraphicsContext::setLineJoin(LineJoin lineJoin)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->setLineJoin(lineJoin);
+ return;
+ }
+
cairo_line_join_t cairoJoin = CAIRO_LINE_JOIN_MITER;
switch (lineJoin) {
case MiterJoin:
@@ -929,10 +1017,16 @@ void GraphicsContext::setMiterLimit(float miter)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ // Maybe this should be part of the state.
+ m_displayListRecorder->setMiterLimit(miter);
+ return;
+ }
+
cairo_set_miter_limit(platformContext()->cr(), miter);
}
-void GraphicsContext::setAlpha(float alpha)
+void GraphicsContext::setPlatformAlpha(float alpha)
{
platformContext()->setGlobalAlpha(alpha);
}
@@ -942,39 +1036,12 @@ void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op, BlendM
if (paintingDisabled())
return;
- cairo_operator_t cairo_op;
- if (blendOp == BlendModeNormal)
- cairo_op = toCairoOperator(op);
- else
- cairo_op = toCairoOperator(blendOp);
-
- cairo_set_operator(platformContext()->cr(), cairo_op);
-}
-
-void GraphicsContext::clip(const Path& path, WindRule windRule)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = platformContext()->cr();
- OwnPtr<cairo_path_t> pathCopy;
- if (!path.isNull()) {
- pathCopy = adoptPtr(cairo_copy_path(path.platformPath()->context()));
- cairo_append_path(cr, pathCopy.get());
- }
- cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
- if (windRule == RULE_NONZERO)
- cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
- else
- cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
- cairo_clip(cr);
- cairo_set_fill_rule(cr, savedFillRule);
- m_data->clip(path);
+ cairo_set_operator(platformContext()->cr(), toCairoOperator(op, blendOp));
}
void GraphicsContext::canvasClip(const Path& path, WindRule windRule)
{
- clip(path, windRule);
+ clipPath(path, windRule);
}
void GraphicsContext::clipOut(const Path& path)
@@ -982,6 +1049,11 @@ void GraphicsContext::clipOut(const Path& path)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->clipOut(path);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
double x1, y1, x2, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
@@ -999,6 +1071,11 @@ void GraphicsContext::rotate(float radians)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->rotate(radians);
+ return;
+ }
+
cairo_rotate(platformContext()->cr(), radians);
m_data->rotate(radians);
}
@@ -1008,15 +1085,25 @@ void GraphicsContext::scale(const FloatSize& size)
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->scale(size);
+ return;
+ }
+
cairo_scale(platformContext()->cr(), size.width(), size.height());
m_data->scale(size);
}
-void GraphicsContext::clipOut(const IntRect& r)
+void GraphicsContext::clipOut(const FloatRect& r)
{
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->clipOut(r);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
double x1, y1, x2, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
@@ -1028,31 +1115,38 @@ void GraphicsContext::clipOut(const IntRect& r)
cairo_set_fill_rule(cr, savedFillRule);
}
-void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace)
+void GraphicsContext::platformFillRoundedRect(const FloatRoundedRect& rect, const Color& color)
{
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
if (hasShadow())
- platformContext()->shadowBlur().drawRectShadow(this, r, RoundedRect::Radii(topLeft, topRight, bottomLeft, bottomRight));
+ platformContext()->shadowBlur().drawRectShadow(*this, rect);
cairo_t* cr = platformContext()->cr();
cairo_save(cr);
Path path;
- path.addRoundedRect(r, topLeft, topRight, bottomLeft, bottomRight);
+ path.addRoundedRect(rect);
appendWebCorePathToCairoContext(cr, path);
setSourceRGBAFromColor(cr, color);
cairo_fill(cr);
cairo_restore(cr);
}
-void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const RoundedRect& roundedHoleRect, const Color& color, ColorSpace)
+void GraphicsContext::fillRectWithRoundedHole(const FloatRect& rect, const FloatRoundedRect& roundedHoleRect, const Color& color)
{
if (paintingDisabled() || !color.isValid())
return;
+ if (isRecording()) {
+ m_displayListRecorder->fillRectWithRoundedHole(rect, roundedHoleRect, color);
+ return;
+ }
+
if (this->mustUseShadowBlur())
- platformContext()->shadowBlur().drawInsetShadow(this, rect, roundedHoleRect.rect(), roundedHoleRect.radii());
+ platformContext()->shadowBlur().drawInsetShadow(*this, rect, roundedHoleRect);
Path path;
path.addRect(rect);
@@ -1064,57 +1158,57 @@ void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const Rounded
cairo_t* cr = platformContext()->cr();
cairo_save(cr);
setPathOnCairoContext(platformContext()->cr(), path.platformPath()->context());
- fillCurrentCairoPath(this);
+ fillCurrentCairoPath(*this);
cairo_restore(cr);
}
-#if PLATFORM(GTK)
-void GraphicsContext::setGdkExposeEvent(GdkEventExpose* expose)
+void GraphicsContext::drawPattern(Image& image, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
{
- m_data->expose = expose;
-}
+ if (paintingDisabled())
+ return;
-GdkEventExpose* GraphicsContext::gdkExposeEvent() const
-{
- return m_data->expose;
-}
+ if (isRecording()) {
+ m_displayListRecorder->drawPattern(image, destRect, tileRect, patternTransform, phase, spacing, op, blendMode);
+ return;
+ }
-GdkWindow* GraphicsContext::gdkWindow() const
-{
- if (!m_data->expose)
- return 0;
+ RefPtr<cairo_surface_t> surface = image.nativeImageForCurrentFrame();
+ if (!surface) // If it's too early we won't have an image yet.
+ return;
- return m_data->expose->window;
+ cairo_t* cr = platformContext()->cr();
+ drawPatternToCairoContext(cr, surface.get(), IntSize(image.size()), tileRect, patternTransform, phase, toCairoOperator(op, blendMode), destRect);
}
-#endif
void GraphicsContext::setPlatformShouldAntialias(bool enable)
{
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
// When true, use the default Cairo backend antialias mode (usually this
// enables standard 'grayscale' antialiasing); false to explicitly disable
- // antialiasing. This is the same strategy as used in drawConvexPolygon().
+ // antialiasing.
cairo_set_antialias(platformContext()->cr(), enable ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
}
-void GraphicsContext::setImageInterpolationQuality(InterpolationQuality quality)
+void GraphicsContext::setPlatformImageInterpolationQuality(InterpolationQuality quality)
{
- platformContext()->setImageInterpolationQuality(quality);
-}
+ ASSERT(!isRecording());
-InterpolationQuality GraphicsContext::imageInterpolationQuality() const
-{
- return platformContext()->imageInterpolationQuality();
+ platformContext()->setImageInterpolationQuality(quality);
}
bool GraphicsContext::isAcceleratedContext() const
{
+ if (isRecording())
+ return false;
+
return cairo_surface_get_type(cairo_get_target(platformContext()->cr())) == CAIRO_SURFACE_TYPE_GL;
}
-#if ENABLE(3D_RENDERING) && USE(TEXTURE_MAPPER)
+#if ENABLE(3D_TRANSFORMS) && USE(TEXTURE_MAPPER)
TransformationMatrix GraphicsContext::get3DTransform() const
{
// FIXME: Can we approximate the transformation better than this?
@@ -1130,7 +1224,7 @@ void GraphicsContext::set3DTransform(const TransformationMatrix& transform)
{
setCTM(transform.toAffineTransform());
}
-#endif
+#endif // ENABLE(3D_TRANSFORMS) && USE(TEXTURE_MAPPER)
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h b/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
index fc7c8a5d4..b2d25d6a7 100644
--- a/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
* Copyright (C) 2008 Brent Fulgham <bfulgham@gmail.com>
*
@@ -12,10 +12,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -30,17 +30,15 @@
#include "GraphicsContext.h"
+#if USE(CAIRO)
+
#include "PlatformContextCairo.h"
#include "RefPtrCairo.h"
#include <cairo.h>
#include <math.h>
#include <stdio.h>
-#include <wtf/MathExtras.h>
-#if PLATFORM(GTK)
-#include <pango/pango.h>
-typedef struct _GdkExposeEvent GdkExposeEvent;
-#elif PLATFORM(WIN)
+#if PLATFORM(WIN)
#include <cairo-win32.h>
#endif
@@ -50,9 +48,6 @@ class GraphicsContextPlatformPrivate {
public:
GraphicsContextPlatformPrivate(PlatformContextCairo* newPlatformContext)
: platformContext(newPlatformContext)
-#if PLATFORM(GTK)
- , expose(0)
-#endif
#if PLATFORM(WIN) || (PLATFORM(GTK) && OS(WINDOWS))
// NOTE: These may note be needed: review and remove once Cairo implementation is complete
, m_hdc(0)
@@ -96,9 +91,6 @@ public:
PlatformContextCairo* platformContext;
Vector<float> layers;
-#if PLATFORM(GTK)
- GdkEventExpose* expose;
-#endif
#if PLATFORM(WIN) || (PLATFORM(GTK) && OS(WINDOWS))
HDC m_hdc;
bool m_shouldIncludeChildWindows;
@@ -124,4 +116,6 @@ public:
} // namespace WebCore
+#endif // USE(CAIRO)
+
#endif // GraphicsContextPlatformPrivateCairo_h
diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index 0d97204f4..041373a01 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -13,10 +13,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -29,6 +29,8 @@
#include "config.h"
#include "ImageBuffer.h"
+#if USE(CAIRO)
+
#include "BitmapImage.h"
#include "CairoUtilities.h"
#include "Color.h"
@@ -39,82 +41,201 @@
#include "PlatformContextCairo.h"
#include "RefPtrCairo.h"
#include <cairo.h>
+#include <runtime/JSCInlines.h>
+#include <runtime/TypedArrayInlines.h>
#include <wtf/Vector.h>
#include <wtf/text/Base64.h>
#include <wtf/text/WTFString.h>
#if ENABLE(ACCELERATED_2D_CANVAS)
#include "GLContext.h"
-#include "OpenGLShims.h"
#include "TextureMapperGL.h"
#include <cairo-gl.h>
+
+#if USE(OPENGL_ES_2)
+#include <GLES2/gl2.h>
+#else
+#include "OpenGLShims.h"
+#endif
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+#include "TextureMapperPlatformLayerBuffer.h"
+#include "TextureMapperPlatformLayerProxy.h"
+#endif
#endif
using namespace std;
namespace WebCore {
-ImageBufferData::ImageBufferData(const IntSize& size)
+ImageBufferData::ImageBufferData(const IntSize& size, RenderingMode renderingMode)
: m_platformContext(0)
, m_size(size)
+ , m_renderingMode(renderingMode)
#if ENABLE(ACCELERATED_2D_CANVAS)
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ , m_compositorTexture(0)
+#endif
, m_texture(0)
#endif
{
+#if ENABLE(ACCELERATED_2D_CANVAS) && USE(COORDINATED_GRAPHICS_THREADED)
+ if (m_renderingMode == RenderingMode::Accelerated)
+ m_platformLayerProxy = adoptRef(new TextureMapperPlatformLayerProxy);
+#endif
+}
+
+ImageBufferData::~ImageBufferData()
+{
+ if (m_renderingMode != Accelerated)
+ return;
+
+#if ENABLE(ACCELERATED_2D_CANVAS)
+ GLContext* previousActiveContext = GLContext::current();
+ PlatformDisplay::sharedDisplayForCompositing().sharingGLContext()->makeContextCurrent();
+
+ if (m_texture)
+ glDeleteTextures(1, &m_texture);
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ if (m_compositorTexture)
+ glDeleteTextures(1, &m_compositorTexture);
+#endif
+
+ if (previousActiveContext)
+ previousActiveContext->makeContextCurrent();
+#endif
}
#if ENABLE(ACCELERATED_2D_CANVAS)
-PassRefPtr<cairo_surface_t> createCairoGLSurface(const IntSize& size, uint32_t& texture)
+#if USE(COORDINATED_GRAPHICS_THREADED)
+void ImageBufferData::createCompositorBuffer()
+{
+ auto* context = PlatformDisplay::sharedDisplayForCompositing().sharingGLContext();
+ context->makeContextCurrent();
+
+ glGenTextures(1, &m_compositorTexture);
+ glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexImage2D(GL_TEXTURE_2D, 0 , GL_RGBA, m_size.width(), m_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+ m_compositorSurface = adoptRef(cairo_gl_surface_create_for_texture(context->cairoDevice(), CAIRO_CONTENT_COLOR_ALPHA, m_compositorTexture, m_size.width(), m_size.height()));
+ m_compositorCr = adoptRef(cairo_create(m_compositorSurface.get()));
+ cairo_set_antialias(m_compositorCr.get(), CAIRO_ANTIALIAS_NONE);
+}
+
+void ImageBufferData::swapBuffersIfNeeded()
+{
+ GLContext* previousActiveContext = GLContext::current();
+
+ if (!m_compositorTexture) {
+ createCompositorBuffer();
+ LockHolder holder(m_platformLayerProxy->lock());
+ m_platformLayerProxy->pushNextBuffer(std::make_unique<TextureMapperPlatformLayerBuffer>(m_compositorTexture, m_size, TextureMapperGL::ShouldBlend));
+ }
+
+ // It would be great if we could just swap the buffers here as we do with webgl, but that breaks the cases
+ // where one frame uses the content already rendered in the previous frame. So we just copy the content
+ // into the compositor buffer.
+ cairo_set_source_surface(m_compositorCr.get(), m_surface.get(), 0, 0);
+ cairo_set_operator(m_compositorCr.get(), CAIRO_OPERATOR_SOURCE);
+ cairo_paint(m_compositorCr.get());
+
+ if (previousActiveContext)
+ previousActiveContext->makeContextCurrent();
+}
+#endif
+
+void clearSurface(cairo_surface_t* surface)
+{
+ if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS)
+ return;
+
+ RefPtr<cairo_t> cr = adoptRef(cairo_create(surface));
+ cairo_set_operator(cr.get(), CAIRO_OPERATOR_CLEAR);
+ cairo_paint(cr.get());
+}
+
+void ImageBufferData::createCairoGLSurface()
{
- GLContext::sharingContext()->makeContextCurrent();
+ auto* context = PlatformDisplay::sharedDisplayForCompositing().sharingGLContext();
+ context->makeContextCurrent();
// We must generate the texture ourselves, because there is no Cairo API for extracting it
// from a pre-existing surface.
- glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glGenTextures(1, &m_texture);
+ glBindTexture(GL_TEXTURE_2D, m_texture);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, size.width(), size.height(), 0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA, m_size.width(), m_size.height(), 0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- GLContext* context = GLContext::sharingContext();
cairo_device_t* device = context->cairoDevice();
// Thread-awareness is a huge performance hit on non-Intel drivers.
cairo_gl_device_set_thread_aware(device, FALSE);
- return adoptRef(cairo_gl_surface_create_for_texture(device, CAIRO_CONTENT_COLOR_ALPHA, texture, size.width(), size.height()));
+ m_surface = adoptRef(cairo_gl_surface_create_for_texture(device, CAIRO_CONTENT_COLOR_ALPHA, m_texture, m_size.width(), m_size.height()));
+ clearSurface(m_surface.get());
}
#endif
-ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode renderingMode, bool& success)
- : m_data(size)
- , m_size(size)
+ImageBuffer::ImageBuffer(const FloatSize& size, float resolutionScale, ColorSpace, RenderingMode renderingMode, bool& success)
+ : m_data(IntSize(size), renderingMode)
, m_logicalSize(size)
+ , m_resolutionScale(resolutionScale)
{
success = false; // Make early return mean error.
+
+ float scaledWidth = ceilf(m_resolutionScale * size.width());
+ float scaledHeight = ceilf(m_resolutionScale * size.height());
+
+ // FIXME: Should we automatically use a lower resolution?
+ if (!FloatSize(scaledWidth, scaledHeight).isExpressibleAsIntSize())
+ return;
+
+ m_size = IntSize(scaledWidth, scaledHeight);
+ m_data.m_size = m_size;
+
if (m_size.isEmpty())
return;
#if ENABLE(ACCELERATED_2D_CANVAS)
- if (renderingMode == Accelerated)
- m_data.m_surface = createCairoGLSurface(size, m_data.m_texture);
- else
+ if (m_data.m_renderingMode == Accelerated) {
+ m_data.createCairoGLSurface();
+ if (!m_data.m_surface || cairo_surface_status(m_data.m_surface.get()) != CAIRO_STATUS_SUCCESS)
+ m_data.m_renderingMode = Unaccelerated; // If allocation fails, fall back to non-accelerated path.
+ }
+ if (m_data.m_renderingMode == Unaccelerated)
#else
- ASSERT_UNUSED(renderingMode, renderingMode != Accelerated);
+ ASSERT(m_data.m_renderingMode != Accelerated);
#endif
- m_data.m_surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size.width(), size.height()));
+ {
+ static cairo_user_data_key_t s_surfaceDataKey;
+
+ int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, m_size.width());
+ auto* surfaceData = fastZeroedMalloc(m_size.height() * stride);
+
+ m_data.m_surface = adoptRef(cairo_image_surface_create_for_data(static_cast<unsigned char*>(surfaceData), CAIRO_FORMAT_ARGB32, m_size.width(), m_size.height(), stride));
+ cairo_surface_set_user_data(m_data.m_surface.get(), &s_surfaceDataKey, surfaceData, [](void* data) { fastFree(data); });
+ }
if (cairo_surface_status(m_data.m_surface.get()) != CAIRO_STATUS_SUCCESS)
return; // create will notice we didn't set m_initialized and fail.
+ cairoSurfaceSetDeviceScale(m_data.m_surface.get(), m_resolutionScale, m_resolutionScale);
+
RefPtr<cairo_t> cr = adoptRef(cairo_create(m_data.m_surface.get()));
m_data.m_platformContext.setCr(cr.get());
- m_context = adoptPtr(new GraphicsContext(&m_data.m_platformContext));
+ m_data.m_context = std::make_unique<GraphicsContext>(&m_data.m_platformContext);
success = true;
}
@@ -122,18 +243,29 @@ ImageBuffer::~ImageBuffer()
{
}
-GraphicsContext* ImageBuffer::context() const
+std::unique_ptr<ImageBuffer> ImageBuffer::createCompatibleBuffer(const FloatSize& size, const GraphicsContext& context)
+{
+ return createCompatibleBuffer(size, ColorSpaceSRGB, context);
+}
+
+GraphicsContext& ImageBuffer::context() const
+{
+ return *m_data.m_context;
+}
+
+RefPtr<Image> ImageBuffer::sinkIntoImage(std::unique_ptr<ImageBuffer> imageBuffer, ScaleBehavior scaleBehavior)
{
- return m_context.get();
+ return imageBuffer->copyImage(DontCopyBackingStore, scaleBehavior);
}
-PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBehavior) const
+RefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBehavior) const
{
+ // copyCairoImageSurface inherits surface's device scale factor.
if (copyBehavior == CopyBackingStore)
return BitmapImage::create(copyCairoImageSurface(m_data.m_surface.get()));
// BitmapImage will release the passed in surface on destruction
- return BitmapImage::create(m_data.m_surface);
+ return BitmapImage::create(RefPtr<cairo_surface_t>(m_data.m_surface));
}
BackingStoreCopy ImageBuffer::fastCopyImageMode()
@@ -141,24 +273,24 @@ BackingStoreCopy ImageBuffer::fastCopyImageMode()
return DontCopyBackingStore;
}
-void ImageBuffer::clip(GraphicsContext* context, const FloatRect& maskRect) const
+void ImageBuffer::drawConsuming(std::unique_ptr<ImageBuffer> imageBuffer, GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode blendMode)
{
- context->platformContext()->pushImageMask(m_data.m_surface.get(), maskRect);
+ imageBuffer->draw(destContext, destRect, srcRect, op, blendMode);
}
-void ImageBuffer::draw(GraphicsContext* destinationContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
- CompositeOperator op, BlendMode blendMode, bool useLowQualityScale)
+void ImageBuffer::draw(GraphicsContext& destinationContext, const FloatRect& destRect, const FloatRect& srcRect,
+ CompositeOperator op, BlendMode blendMode)
{
- BackingStoreCopy copyMode = destinationContext == context() ? CopyBackingStore : DontCopyBackingStore;
+ BackingStoreCopy copyMode = &destinationContext == &context() ? CopyBackingStore : DontCopyBackingStore;
RefPtr<Image> image = copyImage(copyMode);
- destinationContext->drawImage(image.get(), styleColorSpace, destRect, srcRect, op, blendMode, ImageOrientationDescription(), useLowQualityScale);
+ destinationContext.drawImage(*image, destRect, srcRect, ImagePaintingOptions(op, blendMode, ImageOrientationDescription()));
}
-void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
- const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, BlendMode)
+void ImageBuffer::drawPattern(GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect, const AffineTransform& patternTransform,
+ const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode)
{
- RefPtr<Image> image = copyImage(DontCopyBackingStore);
- image->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+ if (RefPtr<Image> image = copyImage(DontCopyBackingStore))
+ image->drawPattern(context, destRect, srcRect, patternTransform, phase, spacing, op);
}
void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
@@ -181,10 +313,10 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
*pixel = premultipliedARGBFromColor(pixelColor);
}
}
- cairo_surface_mark_dirty_rectangle(m_data.m_surface.get(), 0, 0, m_size.width(), m_size.height());
+ cairo_surface_mark_dirty_rectangle(m_data.m_surface.get(), 0, 0, m_logicalSize.width(), m_logicalSize.height());
}
-PassRefPtr<cairo_surface_t> copySurfaceToImageAndAdjustRect(cairo_surface_t* surface, IntRect& rect)
+RefPtr<cairo_surface_t> copySurfaceToImageAndAdjustRect(cairo_surface_t* surface, IntRect& rect)
{
cairo_surface_type_t surfaceType = cairo_surface_get_type(surface);
@@ -199,9 +331,11 @@ PassRefPtr<cairo_surface_t> copySurfaceToImageAndAdjustRect(cairo_surface_t* sur
}
template <Multiply multiplied>
-PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBufferData& data, const IntSize& size)
+RefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const IntRect& logicalRect, const ImageBufferData& data, const IntSize& size, const IntSize& logicalSize, float resolutionScale)
{
RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4);
+ if (!result)
+ return nullptr;
if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height())
result->zeroFill();
@@ -228,13 +362,17 @@ PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe
endy = size.height();
int numRows = endy - originy;
+ // The size of the derived surface is in BackingStoreCoordinateSystem.
+ // We need to set the device scale for the derived surface from this ImageBuffer.
IntRect imageRect(originx, originy, numColumns, numRows);
RefPtr<cairo_surface_t> imageSurface = copySurfaceToImageAndAdjustRect(data.m_surface.get(), imageRect);
+ cairoSurfaceSetDeviceScale(imageSurface.get(), resolutionScale, resolutionScale);
originx = imageRect.x();
originy = imageRect.y();
if (imageSurface != data.m_surface.get()) {
- IntRect area = intersection(rect, IntRect(0, 0, size.width(), size.height()));
- copyRectFromOneSurfaceToAnother(data.m_surface.get(), imageSurface.get(), IntSize(-area.x(), -area.y()), IntRect(IntPoint(), area.size()), IntSize(), CAIRO_OPERATOR_SOURCE);
+ // This cairo surface operation is done in LogicalCoordinateSystem.
+ IntRect logicalArea = intersection(logicalRect, IntRect(0, 0, logicalSize.width(), logicalSize.height()));
+ copyRectFromOneSurfaceToAnother(data.m_surface.get(), imageSurface.get(), IntSize(-logicalArea.x(), -logicalArea.y()), IntRect(IntPoint(), logicalArea.size()), IntSize(), CAIRO_OPERATOR_SOURCE);
}
unsigned char* dataSrc = cairo_image_surface_get_data(imageSurface.get());
@@ -275,53 +413,91 @@ PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe
return result.release();
}
-PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem) const
+template<typename Unit>
+inline Unit logicalUnit(const Unit& value, ImageBuffer::CoordinateSystem coordinateSystemOfValue, float resolutionScale)
{
- return getImageData<Unmultiplied>(rect, m_data, m_size);
+ if (coordinateSystemOfValue == ImageBuffer::LogicalCoordinateSystem || resolutionScale == 1.0)
+ return value;
+ Unit result(value);
+ result.scale(1.0 / resolutionScale);
+ return result;
}
-PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem) const
+template<typename Unit>
+inline Unit backingStoreUnit(const Unit& value, ImageBuffer::CoordinateSystem coordinateSystemOfValue, float resolutionScale)
{
- return getImageData<Premultiplied>(rect, m_data, m_size);
+ if (coordinateSystemOfValue == ImageBuffer::BackingStoreCoordinateSystem || resolutionScale == 1.0)
+ return value;
+ Unit result(value);
+ result.scale(resolutionScale);
+ return result;
}
-void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem)
+RefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem coordinateSystem) const
{
+ IntRect logicalRect = logicalUnit(rect, coordinateSystem, m_resolutionScale);
+ IntRect backingStoreRect = backingStoreUnit(rect, coordinateSystem, m_resolutionScale);
+ return getImageData<Unmultiplied>(backingStoreRect, logicalRect, m_data, m_size, m_logicalSize, m_resolutionScale);
+}
- ASSERT(sourceRect.width() > 0);
- ASSERT(sourceRect.height() > 0);
+RefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem coordinateSystem) const
+{
+ IntRect logicalRect = logicalUnit(rect, coordinateSystem, m_resolutionScale);
+ IntRect backingStoreRect = backingStoreUnit(rect, coordinateSystem, m_resolutionScale);
+ return getImageData<Premultiplied>(backingStoreRect, logicalRect, m_data, m_size, m_logicalSize, m_resolutionScale);
+}
- int originx = sourceRect.x();
- int destx = destPoint.x() + sourceRect.x();
+void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem coordinateSystem)
+{
+ IntRect scaledSourceRect = backingStoreUnit(sourceRect, coordinateSystem, m_resolutionScale);
+ IntSize scaledSourceSize = backingStoreUnit(sourceSize, coordinateSystem, m_resolutionScale);
+ IntPoint scaledDestPoint = backingStoreUnit(destPoint, coordinateSystem, m_resolutionScale);
+ IntRect logicalSourceRect = logicalUnit(sourceRect, coordinateSystem, m_resolutionScale);
+ IntPoint logicalDestPoint = logicalUnit(destPoint, coordinateSystem, m_resolutionScale);
+
+ ASSERT(scaledSourceRect.width() > 0);
+ ASSERT(scaledSourceRect.height() > 0);
+
+ int originx = scaledSourceRect.x();
+ int destx = scaledDestPoint.x() + scaledSourceRect.x();
+ int logicalDestx = logicalDestPoint.x() + logicalSourceRect.x();
ASSERT(destx >= 0);
ASSERT(destx < m_size.width());
ASSERT(originx >= 0);
- ASSERT(originx <= sourceRect.maxX());
+ ASSERT(originx <= scaledSourceRect.maxX());
- int endx = destPoint.x() + sourceRect.maxX();
+ int endx = scaledDestPoint.x() + scaledSourceRect.maxX();
+ int logicalEndx = logicalDestPoint.x() + logicalSourceRect.maxX();
ASSERT(endx <= m_size.width());
int numColumns = endx - destx;
+ int logicalNumColumns = logicalEndx - logicalDestx;
- int originy = sourceRect.y();
- int desty = destPoint.y() + sourceRect.y();
+ int originy = scaledSourceRect.y();
+ int desty = scaledDestPoint.y() + scaledSourceRect.y();
+ int logicalDesty = logicalDestPoint.y() + logicalSourceRect.y();
ASSERT(desty >= 0);
ASSERT(desty < m_size.height());
ASSERT(originy >= 0);
- ASSERT(originy <= sourceRect.maxY());
+ ASSERT(originy <= scaledSourceRect.maxY());
- int endy = destPoint.y() + sourceRect.maxY();
+ int endy = scaledDestPoint.y() + scaledSourceRect.maxY();
+ int logicalEndy = logicalDestPoint.y() + logicalSourceRect.maxY();
ASSERT(endy <= m_size.height());
int numRows = endy - desty;
+ int logicalNumRows = logicalEndy - logicalDesty;
+ // The size of the derived surface is in BackingStoreCoordinateSystem.
+ // We need to set the device scale for the derived surface from this ImageBuffer.
IntRect imageRect(destx, desty, numColumns, numRows);
RefPtr<cairo_surface_t> imageSurface = copySurfaceToImageAndAdjustRect(m_data.m_surface.get(), imageRect);
+ cairoSurfaceSetDeviceScale(imageSurface.get(), m_resolutionScale, m_resolutionScale);
destx = imageRect.x();
desty = imageRect.y();
unsigned char* pixelData = cairo_image_surface_get_data(imageSurface.get());
- unsigned srcBytesPerRow = 4 * sourceSize.width();
+ unsigned srcBytesPerRow = 4 * scaledSourceSize.width();
int stride = cairo_image_surface_get_stride(imageSurface.get());
unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4;
@@ -351,10 +527,13 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c
srcRows += srcBytesPerRow;
}
- cairo_surface_mark_dirty_rectangle(imageSurface.get(), destx, desty, numColumns, numRows);
+ // This cairo surface operation is done in LogicalCoordinateSystem.
+ cairo_surface_mark_dirty_rectangle(imageSurface.get(), logicalDestx, logicalDesty, logicalNumColumns, logicalNumRows);
- if (imageSurface != m_data.m_surface.get())
- copyRectFromOneSurfaceToAnother(imageSurface.get(), m_data.m_surface.get(), IntSize(), IntRect(0, 0, numColumns, numRows), IntSize(destPoint.x() + sourceRect.x(), destPoint.y() + sourceRect.y()), CAIRO_OPERATOR_SOURCE);
+ if (imageSurface != m_data.m_surface.get()) {
+ // This cairo surface operation is done in LogicalCoordinateSystem.
+ copyRectFromOneSurfaceToAnother(imageSurface.get(), m_data.m_surface.get(), IntSize(), IntRect(0, 0, logicalNumColumns, logicalNumRows), IntSize(logicalDestPoint.x() + logicalSourceRect.x(), logicalDestPoint.y() + logicalSourceRect.y()), CAIRO_OPERATOR_SOURCE);
+ }
}
#if !PLATFORM(GTK)
@@ -372,11 +551,11 @@ static bool encodeImage(cairo_surface_t* image, const String& mimeType, Vector<c
return cairo_surface_write_to_png_stream(image, writeFunction, output) == CAIRO_STATUS_SUCCESS;
}
-String ImageBuffer::toDataURL(const String& mimeType, const double*, CoordinateSystem) const
+String ImageBuffer::toDataURL(const String& mimeType, std::optional<double> quality, CoordinateSystem) const
{
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
- cairo_surface_t* image = cairo_get_target(context()->platformContext()->cr());
+ cairo_surface_t* image = cairo_get_target(context().platformContext()->cr());
Vector<char> encodedImage;
if (!image || !encodeImage(image, mimeType, &encodedImage))
@@ -389,26 +568,20 @@ String ImageBuffer::toDataURL(const String& mimeType, const double*, CoordinateS
}
#endif
-#if ENABLE(ACCELERATED_2D_CANVAS)
-void ImageBufferData::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity)
+#if ENABLE(ACCELERATED_2D_CANVAS) && !USE(COORDINATED_GRAPHICS_THREADED)
+void ImageBufferData::paintToTextureMapper(TextureMapper& textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity)
{
- if (textureMapper->accelerationMode() != TextureMapper::OpenGLMode) {
- notImplemented();
- return;
- }
-
ASSERT(m_texture);
// Cairo may change the active context, so we make sure to change it back after flushing.
- GLContext* previousActiveContext = GLContext::getCurrent();
+ GLContext* previousActiveContext = GLContext::current();
cairo_surface_flush(m_surface.get());
previousActiveContext->makeContextCurrent();
- static_cast<TextureMapperGL*>(textureMapper)->drawTexture(m_texture, TextureMapperGL::ShouldBlend, m_size, targetRect, matrix, opacity);
+ static_cast<TextureMapperGL&>(textureMapper).drawTexture(m_texture, TextureMapperGL::ShouldBlend, m_size, targetRect, matrix, opacity);
}
#endif
-#if USE(ACCELERATED_COMPOSITING)
PlatformLayer* ImageBuffer::platformLayer() const
{
#if ENABLE(ACCELERATED_2D_CANVAS)
@@ -417,6 +590,59 @@ PlatformLayer* ImageBuffer::platformLayer() const
#endif
return 0;
}
+
+bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D&, GC3Denum target, Platform3DObject destinationTexture, GC3Denum internalformat, bool premultiplyAlpha, bool flipY)
+{
+#if ENABLE(ACCELERATED_2D_CANVAS)
+ ASSERT_WITH_MESSAGE(m_resolutionScale == 1.0, "Since the HiDPI Canvas feature is removed, the resolution factor here is always 1.");
+ if (premultiplyAlpha || flipY)
+ return false;
+
+ if (!m_data.m_texture)
+ return false;
+
+ GC3Denum bindTextureTarget;
+ switch (target) {
+ case GL_TEXTURE_2D:
+ bindTextureTarget = GL_TEXTURE_2D;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ bindTextureTarget = GL_TEXTURE_CUBE_MAP;
+ break;
+ default:
+ return false;
+ }
+
+ cairo_surface_flush(m_data.m_surface.get());
+
+ std::unique_ptr<GLContext> context = GLContext::createOffscreenContext(&PlatformDisplay::sharedDisplayForCompositing());
+ context->makeContextCurrent();
+ uint32_t fbo;
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_data.m_texture, 0);
+ glBindTexture(bindTextureTarget, destinationTexture);
+ glCopyTexImage2D(target, 0, internalformat, 0, 0, m_size.width(), m_size.height(), 0);
+ glBindTexture(bindTextureTarget, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glFlush();
+ glDeleteFramebuffers(1, &fbo);
+ return true;
+#else
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(destinationTexture);
+ UNUSED_PARAM(internalformat);
+ UNUSED_PARAM(premultiplyAlpha);
+ UNUSED_PARAM(flipY);
+ return false;
#endif
+}
} // namespace WebCore
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h b/Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h
index 72ea4c34f..93d817614 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h
+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -23,12 +23,19 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef ImageBufferDataCairo_h
+#define ImageBufferDataCairo_h
+
+#if USE(CAIRO)
+
#include "PlatformContextCairo.h"
#include "RefPtrCairo.h"
#if ENABLE(ACCELERATED_2D_CANVAS)
+#include "PlatformLayer.h"
#include "TextureMapper.h"
#include "TextureMapperPlatformLayer.h"
+#include "TextureMapperPlatformLayerProxy.h"
#endif
namespace WebCore {
@@ -37,20 +44,40 @@ class IntSize;
class ImageBufferData
#if ENABLE(ACCELERATED_2D_CANVAS)
- : public TextureMapperPlatformLayer
+ : public PlatformLayer
#endif
{
public:
- ImageBufferData(const IntSize&);
+ ImageBufferData(const IntSize&, RenderingMode);
+ virtual ~ImageBufferData();
RefPtr<cairo_surface_t> m_surface;
PlatformContextCairo m_platformContext;
+ std::unique_ptr<GraphicsContext> m_context;
IntSize m_size;
+ RenderingMode m_renderingMode;
#if ENABLE(ACCELERATED_2D_CANVAS)
- virtual void paintToTextureMapper(TextureMapper*, const FloatRect& target, const TransformationMatrix&, float opacity);
+ void createCairoGLSurface();
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ RefPtr<TextureMapperPlatformLayerProxy> proxy() const override { return m_platformLayerProxy.copyRef(); }
+ void swapBuffersIfNeeded() override;
+ void createCompositorBuffer();
+
+ RefPtr<TextureMapperPlatformLayerProxy> m_platformLayerProxy;
+ RefPtr<cairo_surface_t> m_compositorSurface;
+ uint32_t m_compositorTexture;
+ RefPtr<cairo_t> m_compositorCr;
+#else
+ virtual void paintToTextureMapper(TextureMapper&, const FloatRect& target, const TransformationMatrix&, float opacity);
+#endif
uint32_t m_texture;
#endif
};
} // namespace WebCore
+
+#endif // USE(CAIRO)
+
+#endif // ImageBufferDataCairo_h
diff --git a/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp
index 46a39b45b..4e5365958 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
*
@@ -12,10 +12,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -31,30 +31,21 @@
#if USE(CAIRO)
#include "AffineTransform.h"
-#include "CairoUtilities.h"
#include "Color.h"
#include "GraphicsContext.h"
#include "ImageObserver.h"
-#include "PlatformContextCairo.h"
-#include <cairo.h>
-#include <math.h>
namespace WebCore {
-void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform,
- const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect, BlendMode)
+void Image::drawPattern(GraphicsContext& context, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform,
+ const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
{
- RefPtr<cairo_surface_t> surface = nativeImageForCurrentFrame();
- if (!surface) // If it's too early we won't have an image yet.
- return;
-
- cairo_t* cr = context->platformContext()->cr();
- drawPatternToCairoContext(cr, surface.get(), size(), tileRect, patternTransform, phase, toCairoOperator(op), destRect);
+ context.drawPattern(*this, destRect, tileRect, patternTransform, phase, spacing, op, blendMode);
if (imageObserver())
imageObserver()->didDraw(this);
}
-}
+} // namespace WebCore
#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/IntRectCairo.cpp b/Source/WebCore/platform/graphics/cairo/IntRectCairo.cpp
index cef3af905..054bd2ac3 100644
--- a/Source/WebCore/platform/graphics/cairo/IntRectCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/IntRectCairo.cpp
@@ -21,6 +21,8 @@
#include "config.h"
#include "IntRect.h"
+#if USE(CAIRO)
+
#include <cairo.h>
namespace WebCore {
@@ -37,4 +39,6 @@ IntRect::operator cairo_rectangle_int_t() const
return r;
}
-}
+} // namespace WebCore
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/NativeImageCairo.cpp b/Source/WebCore/platform/graphics/cairo/NativeImageCairo.cpp
new file mode 100644
index 000000000..69b7bb0f8
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/NativeImageCairo.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "NativeImage.h"
+
+#if USE(CAIRO)
+
+#include "CairoUtilities.h"
+#include "PlatformContextCairo.h"
+#include <cairo.h>
+
+namespace WebCore {
+
+IntSize nativeImageSize(const NativeImagePtr& image)
+{
+ return image ? cairoSurfaceSize(image.get()) : IntSize();
+}
+
+bool nativeImageHasAlpha(const NativeImagePtr& image)
+{
+ return !image || cairo_surface_get_content(image.get()) != CAIRO_CONTENT_COLOR;
+}
+
+Color nativeImageSinglePixelSolidColor(const NativeImagePtr& image)
+{
+ if (!image || nativeImageSize(image) != IntSize(1, 1))
+ return Color();
+
+ if (cairo_surface_get_type(image.get()) != CAIRO_SURFACE_TYPE_IMAGE)
+ return Color();
+
+ RGBA32* pixel = reinterpret_cast_ptr<RGBA32*>(cairo_image_surface_get_data(image.get()));
+ return colorFromPremultipliedARGB(*pixel);
+}
+
+float subsamplingScale(GraphicsContext&, const FloatRect&, const FloatRect&)
+{
+ return 1;
+}
+
+void drawNativeImage(const NativeImagePtr& image, GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect, const IntSize&, CompositeOperator op, BlendMode mode, const ImageOrientation& orientation)
+{
+ context.save();
+
+ // Set the compositing operation.
+ if (op == CompositeSourceOver && mode == BlendModeNormal && !nativeImageHasAlpha(image))
+ context.setCompositeOperation(CompositeCopy);
+ else
+ context.setCompositeOperation(op, mode);
+
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+ IntSize scaledSize = nativeImageSize(image);
+ FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(srcRect, scaledSize);
+#else
+ FloatRect adjustedSrcRect(srcRect);
+#endif
+
+ FloatRect adjustedDestRect = destRect;
+
+ if (orientation != DefaultImageOrientation) {
+ // ImageOrientation expects the origin to be at (0, 0).
+ context.translate(destRect.x(), destRect.y());
+ adjustedDestRect.setLocation(FloatPoint());
+ context.concatCTM(orientation.transformFromDefault(adjustedDestRect.size()));
+ if (orientation.usesWidthAsHeight()) {
+ // The destination rectangle will have it's width and height already reversed for the orientation of
+ // the image, as it was needed for page layout, so we need to reverse it back here.
+ adjustedDestRect.setSize(adjustedDestRect.size().transposedSize());
+ }
+ }
+
+ context.platformContext()->drawSurfaceToContext(image.get(), adjustedDestRect, adjustedSrcRect, context);
+ context.restore();
+}
+
+void clearNativeImageSubimages(const NativeImagePtr&)
+{
+}
+
+} // namespace WebCore
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp b/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp
deleted file mode 100644
index 1594e7b5d..000000000
--- a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2010 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-#include "OwnPtrCairo.h"
-
-#if USE(FREETYPE)
-#include <cairo-ft.h>
-#include <fontconfig/fcfreetype.h>
-#endif
-
-#include <cairo.h>
-
-namespace WTF {
-
-#if USE(FREETYPE)
-template <> void deleteOwnedPtr<FcObjectSet>(FcObjectSet* ptr)
-{
- if (ptr)
- FcObjectSetDestroy(ptr);
-}
-
-template <> void deleteOwnedPtr<FcFontSet>(FcFontSet* ptr)
-{
- if (ptr)
- FcFontSetDestroy(ptr);
-}
-#endif
-
-template <> void deleteOwnedPtr<cairo_path_t>(cairo_path_t* ptr)
-{
- if (ptr)
- cairo_path_destroy(ptr);
-}
-
-} // namespace WTF
diff --git a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h b/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h
deleted file mode 100644
index 3704b6a17..000000000
--- a/Source/WebCore/platform/graphics/cairo/OwnPtrCairo.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2010 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifndef OwnPtrCairo_h
-#define OwnPtrCairo_h
-
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
-
-#if USE(FREETYPE)
-typedef struct _FcObjectSet FcObjectSet;
-typedef struct _FcFontSet FcFontSet;
-#endif
-
-typedef struct cairo_path cairo_path_t;
-
-namespace WTF {
-
-#if USE(FREETYPE)
-template <> void deleteOwnedPtr<FcObjectSet>(FcObjectSet*);
-template <> void deleteOwnedPtr<FcFontSet>(FcFontSet*);
-#endif
-
-template <> void deleteOwnedPtr<cairo_path_t>(cairo_path_t*);
-
-} // namespace WTF
-
-#endif
diff --git a/Source/WebCore/platform/graphics/cairo/PathCairo.cpp b/Source/WebCore/platform/graphics/cairo/PathCairo.cpp
index 5fac5f0b9..6ab79100c 100644
--- a/Source/WebCore/platform/graphics/cairo/PathCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/PathCairo.cpp
@@ -26,10 +26,11 @@
#include "config.h"
#include "Path.h"
+#if USE(CAIRO)
+
#include "AffineTransform.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
-#include "OwnPtrCairo.h"
#include "PlatformPathCairo.h"
#include "StrokeStyleApplier.h"
#include <cairo.h>
@@ -57,8 +58,9 @@ Path::Path(const Path& other)
return;
cairo_t* cr = ensurePlatformPath()->context();
- OwnPtr<cairo_path_t> pathCopy = adoptPtr(cairo_copy_path(other.platformPath()->context()));
- cairo_append_path(cr, pathCopy.get());
+ auto pathCopy = cairo_copy_path(other.platformPath()->context());
+ cairo_append_path(cr, pathCopy);
+ cairo_path_destroy(pathCopy);
}
PlatformPathPtr Path::ensurePlatformPath()
@@ -81,8 +83,9 @@ Path& Path::operator=(const Path& other)
} else {
clear();
cairo_t* cr = ensurePlatformPath()->context();
- OwnPtr<cairo_path_t> pathCopy = adoptPtr(cairo_copy_path(other.platformPath()->context()));
- cairo_append_path(cr, pathCopy.get());
+ auto pathCopy = cairo_copy_path(other.platformPath()->context());
+ cairo_append_path(cr, pathCopy);
+ cairo_path_destroy(pathCopy);
}
return *this;
@@ -281,6 +284,22 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
addArc(p, radius, sa, ea, anticlockwise);
}
+void Path::addEllipse(FloatPoint point, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise)
+{
+ cairo_t* cr = ensurePlatformPath()->context();
+ cairo_save(cr);
+ cairo_translate(cr, point.x(), point.y());
+ cairo_rotate(cr, rotation);
+ cairo_scale(cr, radiusX, radiusY);
+
+ if (anticlockwise)
+ cairo_arc_negative(cr, 0, 0, 1, startAngle, endAngle);
+ else
+ cairo_arc(cr, 0, 0, 1, startAngle, endAngle);
+
+ cairo_restore(cr);
+}
+
void Path::addEllipse(const FloatRect& rect)
{
cairo_t* cr = ensurePlatformPath()->context();
@@ -293,6 +312,24 @@ void Path::addEllipse(const FloatRect& rect)
cairo_restore(cr);
}
+void Path::addPath(const Path& path, const AffineTransform& transform)
+{
+ if (path.isNull())
+ return;
+
+ cairo_matrix_t matrix(transform);
+ if (cairo_matrix_invert(&matrix) != CAIRO_STATUS_SUCCESS)
+ return;
+
+ cairo_t* cr = path.platformPath()->context();
+ cairo_save(cr);
+ cairo_transform(cr, &matrix);
+ auto pathCopy = cairo_copy_path(cr);
+ cairo_restore(cr);
+ cairo_append_path(ensurePlatformPath()->context(), pathCopy);
+ cairo_path_destroy(pathCopy);
+}
+
void Path::closeSubpath()
{
cairo_t* cr = ensurePlatformPath()->context();
@@ -353,13 +390,13 @@ bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point)
return cairo_in_stroke(cr, point.x(), point.y());
}
-void Path::apply(void* info, PathApplierFunction function) const
+void Path::apply(const PathApplierFunction& function) const
{
if (isNull())
return;
cairo_t* cr = platformPath()->context();
- OwnPtr<cairo_path_t> pathCopy = adoptPtr(cairo_copy_path(cr));
+ auto pathCopy = cairo_copy_path(cr);
cairo_path_data_t* data;
PathElement pelement;
FloatPoint points[3];
@@ -371,26 +408,27 @@ void Path::apply(void* info, PathApplierFunction function) const
case CAIRO_PATH_MOVE_TO:
pelement.type = PathElementMoveToPoint;
pelement.points[0] = FloatPoint(data[1].point.x,data[1].point.y);
- function(info, &pelement);
+ function(pelement);
break;
case CAIRO_PATH_LINE_TO:
pelement.type = PathElementAddLineToPoint;
pelement.points[0] = FloatPoint(data[1].point.x,data[1].point.y);
- function(info, &pelement);
+ function(pelement);
break;
case CAIRO_PATH_CURVE_TO:
pelement.type = PathElementAddCurveToPoint;
pelement.points[0] = FloatPoint(data[1].point.x,data[1].point.y);
pelement.points[1] = FloatPoint(data[2].point.x,data[2].point.y);
pelement.points[2] = FloatPoint(data[3].point.x,data[3].point.y);
- function(info, &pelement);
+ function(pelement);
break;
case CAIRO_PATH_CLOSE_PATH:
pelement.type = PathElementCloseSubpath;
- function(info, &pelement);
+ function(pelement);
break;
}
}
+ cairo_path_destroy(pathCopy);
}
void Path::transform(const AffineTransform& trans)
@@ -402,3 +440,5 @@ void Path::transform(const AffineTransform& trans)
}
} // namespace WebCore
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/PatternCairo.cpp b/Source/WebCore/platform/graphics/cairo/PatternCairo.cpp
index 8870d3e03..81bc7ce96 100644
--- a/Source/WebCore/platform/graphics/cairo/PatternCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/PatternCairo.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,6 +26,8 @@
#include "config.h"
#include "Pattern.h"
+#if USE(CAIRO)
+
#include "AffineTransform.h"
#include "GraphicsContext.h"
#include <cairo.h>
@@ -50,4 +52,6 @@ cairo_pattern_t* Pattern::createPlatformPattern(const AffineTransform&) const
return pattern;
}
-}
+} // namespace WebCore
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp
index fc2b2b0fc..65d7eeee9 100644
--- a/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp
@@ -12,10 +12,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -28,10 +28,11 @@
#include "config.h"
#include "PlatformContextCairo.h"
+#if USE(CAIRO)
+
#include "CairoUtilities.h"
#include "Gradient.h"
#include "GraphicsContext.h"
-#include "OwnPtrCairo.h"
#include "Pattern.h"
#include <cairo.h>
@@ -136,9 +137,13 @@ void PlatformContextCairo::pushImageMask(cairo_surface_t* surface, const FloatRe
cairo_push_group(m_cr.get());
cairo_set_operator(m_cr.get(), CAIRO_OPERATOR_SOURCE);
- cairo_set_source_surface(m_cr.get(), currentTarget, 0, 0);
- cairo_rectangle(m_cr.get(), rect.x(), rect.y(), rect.width(), rect.height());
+ // To avoid the limit of Pixman backend, we need to reduce the size of pattern matrix
+ // See https://bugs.webkit.org/show_bug.cgi?id=154283
+ cairo_set_source_surface(m_cr.get(), currentTarget, rect.x(), rect.y());
+ cairo_translate(m_cr.get(), rect.x(), rect.y());
+ cairo_rectangle(m_cr.get(), 0, 0, rect.width(), rect.height());
cairo_fill(m_cr.get());
+ cairo_translate(m_cr.get(), -rect.x(), -rect.y());
}
static void drawPatternToCairoContext(cairo_t* cr, cairo_pattern_t* pattern, const FloatRect& destRect, float alpha)
@@ -154,7 +159,7 @@ static void drawPatternToCairoContext(cairo_t* cr, cairo_pattern_t* pattern, con
cairo_fill(cr);
}
-void PlatformContextCairo::drawSurfaceToContext(cairo_surface_t* surface, const FloatRect& destRect, const FloatRect& originalSrcRect, GraphicsContext* context)
+void PlatformContextCairo::drawSurfaceToContext(cairo_surface_t* surface, const FloatRect& destRect, const FloatRect& originalSrcRect, GraphicsContext& context)
{
// Avoid invalid cairo matrix with small values.
if (std::fabs(destRect.width()) < 0.5f || std::fabs(destRect.height()) < 0.5f)
@@ -197,11 +202,11 @@ void PlatformContextCairo::drawSurfaceToContext(cairo_surface_t* surface, const
cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_FAST);
break;
case InterpolationMedium:
- case InterpolationHigh:
- cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_BILINEAR);
- break;
case InterpolationDefault:
- cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_BILINEAR);
+ cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_GOOD);
+ break;
+ case InterpolationHigh:
+ cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_BEST);
break;
}
cairo_pattern_set_extend(pattern.get(), CAIRO_EXTEND_PAD);
@@ -215,7 +220,7 @@ void PlatformContextCairo::drawSurfaceToContext(cairo_surface_t* surface, const
cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, leftPadding, topPadding };
cairo_pattern_set_matrix(pattern.get(), &matrix);
- ShadowBlur& shadow = context->platformContext()->shadowBlur();
+ ShadowBlur& shadow = context.platformContext()->shadowBlur();
if (shadow.type() != ShadowBlur::NoShadow) {
if (GraphicsContext* shadowContext = shadow.beginShadowLayer(context, destRect)) {
drawPatternToCairoContext(shadowContext->platformContext()->cr(), pattern.get(), destRect, 1);
@@ -304,7 +309,7 @@ void PlatformContextCairo::clipForPatternFilling(const GraphicsContextState& sta
ASSERT(state.fillPattern);
// Hold current cairo path in a variable for restoring it after configuring the pattern clip rectangle.
- OwnPtr<cairo_path_t> currentPath = adoptPtr(cairo_copy_path(m_cr.get()));
+ auto currentPath = cairo_copy_path(m_cr.get());
cairo_new_path(m_cr.get());
// Initialize clipping extent from current cairo clip extents, then shrink if needed according to pattern.
@@ -335,7 +340,10 @@ void PlatformContextCairo::clipForPatternFilling(const GraphicsContextState& sta
}
// Restoring cairo path.
- cairo_append_path(m_cr.get(), currentPath.get());
+ cairo_append_path(m_cr.get(), currentPath);
+ cairo_path_destroy(currentPath);
}
} // namespace WebCore
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h
index d7f1205f7..642a3052c 100644
--- a/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h
+++ b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,6 +26,8 @@
#ifndef PlatformContextCairo_h
#define PlatformContextCairo_h
+#if USE(CAIRO)
+
#include "GraphicsContext.h"
#include "RefPtrCairo.h"
#include "ShadowBlur.h"
@@ -56,7 +58,7 @@ public:
float globalAlpha() const;
void pushImageMask(cairo_surface_t*, const FloatRect&);
- void drawSurfaceToContext(cairo_surface_t*, const FloatRect& destRect, const FloatRect& srcRect, GraphicsContext*);
+ void drawSurfaceToContext(cairo_surface_t*, const FloatRect& destRect, const FloatRect& srcRect, GraphicsContext&);
void setImageInterpolationQuality(InterpolationQuality);
InterpolationQuality imageInterpolationQuality() const;
@@ -84,4 +86,6 @@ private:
} // namespace WebCore
+#endif // USE(CAIRO)
+
#endif // PlatformContextCairo_h
diff --git a/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.cpp b/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.cpp
index 3a7d5128a..14c8d9bcd 100644
--- a/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.cpp
@@ -20,20 +20,23 @@
#include "config.h"
#include "PlatformPathCairo.h"
+#if USE(CAIRO)
+
#include <cairo.h>
namespace WebCore {
-static cairo_surface_t* getPathSurface()
+static cairo_surface_t* pathSurface()
{
- return cairo_image_surface_create(CAIRO_FORMAT_A8, 1, 1);
+ static cairo_surface_t* s_pathSurface = cairo_image_surface_create(CAIRO_FORMAT_A8, 1, 1);
+ return s_pathSurface;
}
-static cairo_surface_t* gPathSurface = getPathSurface();
-
CairoPath::CairoPath()
- : m_cr(adoptRef(cairo_create(gPathSurface)))
+ : m_cr(adoptRef(cairo_create(pathSurface())))
{
}
-}
+} // namespace WebCore
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.h b/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.h
index 938b942a4..5f1059446 100644
--- a/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.h
+++ b/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.h
@@ -21,6 +21,8 @@
#ifndef PlatformPathCairo_h
#define PlatformPathCairo_h
+#if USE(CAIRO)
+
#include "RefPtrCairo.h"
namespace WebCore {
@@ -40,4 +42,6 @@ private:
} // namespace WebCore
+#endif // USE(CAIRO)
+
#endif // PlatformPathCairo_h
diff --git a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp
index 0f55f5797..61a0369f5 100644
--- a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp
@@ -19,6 +19,8 @@
#include "config.h"
#include "RefPtrCairo.h"
+#if USE(CAIRO)
+
#include <cairo.h>
#if USE(FREETYPE)
@@ -30,89 +32,102 @@ namespace WTF {
template<> void refIfNotNull(cairo_t* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
cairo_reference(ptr);
}
template<> void derefIfNotNull(cairo_t* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
cairo_destroy(ptr);
}
template<> void refIfNotNull(cairo_surface_t* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
cairo_surface_reference(ptr);
}
template<> void derefIfNotNull(cairo_surface_t* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
cairo_surface_destroy(ptr);
}
template<> void refIfNotNull(cairo_font_face_t* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
cairo_font_face_reference(ptr);
}
template<> void derefIfNotNull(cairo_font_face_t* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
cairo_font_face_destroy(ptr);
}
template<> void refIfNotNull(cairo_scaled_font_t* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
cairo_scaled_font_reference(ptr);
}
template<> void derefIfNotNull(cairo_scaled_font_t* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
cairo_scaled_font_destroy(ptr);
}
template<> void refIfNotNull(cairo_pattern_t* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
cairo_pattern_reference(ptr);
}
template<> void derefIfNotNull(cairo_pattern_t* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
cairo_pattern_destroy(ptr);
}
template<> void refIfNotNull(cairo_region_t* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
cairo_region_reference(ptr);
}
template<> void derefIfNotNull(cairo_region_t* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
cairo_region_destroy(ptr);
}
#if USE(FREETYPE)
template<> void refIfNotNull(FcPattern* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
FcPatternReference(ptr);
}
template<> void derefIfNotNull(FcPattern* ptr)
{
- if (LIKELY(ptr != 0))
+ if (LIKELY(ptr))
FcPatternDestroy(ptr);
}
-#endif
+template<> void refIfNotNull(FcConfig* ptr)
+{
+ if (LIKELY(ptr))
+ FcConfigReference(ptr);
+}
+template<> void derefIfNotNull(FcConfig* ptr)
+{
+ if (LIKELY(ptr))
+ FcConfigDestroy(ptr);
}
+#endif
+
+} // namespace WTF
+
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h
index 0e1baf50a..8e92f4e6d 100644
--- a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h
+++ b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h
@@ -20,6 +20,8 @@
#ifndef RefPtrCairo_h
#define RefPtrCairo_h
+#if USE(CAIRO)
+
#include <wtf/RefPtr.h>
typedef struct _cairo cairo_t;
@@ -31,6 +33,7 @@ typedef struct _cairo_region cairo_region_t;
#if USE(FREETYPE)
typedef struct _FcPattern FcPattern;
+typedef struct _FcConfig FcConfig;
#endif
namespace WTF {
@@ -56,8 +59,13 @@ template<> void derefIfNotNull(cairo_region_t*);
#if USE(FREETYPE)
template<> void refIfNotNull(FcPattern* ptr);
template<> void derefIfNotNull(FcPattern* ptr);
+
+template<> void refIfNotNull(FcConfig* ptr);
+template<> void derefIfNotNull(FcConfig* ptr);
#endif
-}
+} // namespace WTF
+
+#endif // USE(CAIRO)
#endif // RefPtrCairo_h
diff --git a/Source/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp b/Source/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp
index bebc4a321..a5cc372f8 100644
--- a/Source/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp
@@ -9,10 +9,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -23,12 +23,13 @@
*/
#include "config.h"
-#include "AffineTransform.h"
#include "TransformationMatrix.h"
+#if USE(CAIRO)
+
+#include "AffineTransform.h"
#include "FloatRect.h"
#include "IntRect.h"
-
#include <cairo.h>
namespace WebCore {
@@ -61,6 +62,6 @@ AffineTransform::operator cairo_matrix_t() const
return m;
}
-}
+} // namespace WebCore
-// vim: ts=4 sw=4 et
+#endif // USE(CAIRO)