[Win][Direct2D] Implement basic SVG support
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Oct 2016 22:42:14 +0000 (22:42 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Oct 2016 22:42:14 +0000 (22:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163349

Reviewed by Brent Fulgham.

Direct2D needs access to the target graphics context when generating bitmap
images so that it can properly match pixel format and other settings.

Add implementations for a number of drawing primitives used in the SVG
test cases. Correct some differences between CG and Direct2D for drawing
different primitives.

No new tests. Tested by existing 'svg' tests.

* platform/graphics/BitmapImage.cpp:
       (WebCore::BitmapImage::frameImageAtIndex): Take optional target graphics
       context. Also pass the graphics context to the image decoder.
       (WebCore::BitmapImage::nativeImage): Accept an optional target context.
       (WebCore::BitmapImage::nativeImageForCurrentFrame): Ditto.
       (WebCore::BitmapImage::draw): Pass target graphics context to the
       'frameImageAtIndex' method.
* platform/graphics/BitmapImage.h:
* platform/graphics/Image.h:
* platform/graphics/ImageBuffer.cpp:
(WebCore::ImageBuffer::create): Moved from header. Add create function that
takes an optional GraphicsContext argument.
* platform/graphics/ImageBuffer.h:
* platform/graphics/ImageFrameCache.cpp: Add missing include needed to build
under Direct2D.
* platform/graphics/ImageSource.cpp:
(WebCore::ImageSource::setDecoderTargetContext): Added.
(WebCore::ImageSource::setRenderTarget): Deleted.
* platform/graphics/ImageSource.h:
* platform/graphics/Pattern.h:
* platform/graphics/win/GraphicsContextDirect2D.cpp:
(WebCore::GraphicsContextPlatformPrivate::endDraw): Log error state instead of crashing
each time.
(WebCore::GraphicsContext::drawEllipse): Ellipses are defined in D2D as a center, an
X-radius, and a Y-radius.
(WebCore::GraphicsContext::applyStrokePattern):
(WebCore::GraphicsContext::applyFillPattern):
(WebCore::GraphicsContext::clearRect): Use 'Clear' function if possible. Don't clear
anything if the clear rect is outside the drawing area.
(WebCore::GraphicsContext::strokeRect): Provide implementation (needed by SVG).
(WebCore::GraphicsContext::platformFillEllipse): Ellipses are defined in D2D as
a center, an X-radius, and a Y-radius.
(WebCore::GraphicsContext::platformStrokeEllipse): Ditto.
* platform/graphics/win/ImageBufferDirect2D.cpp:
(WebCore::ImageBuffer::createCompatibleBuffer): Accept optional GraphicsContext argument.
(WebCore::ImageBuffer::ImageBuffer): Ditto.
* platform/graphics/win/ImageDecoderDirect2D.cpp:
(WebCore::ImageDecoder::setTargetContext): Renamed from 'setRenderTarget'.
(WebCore::ImageDecoder::createFrameImageAtIndex): Take optional GraphicsContext argument.
(WebCore::ImageDecoder::setRenderTarget): Deleted.
* platform/graphics/win/ImageDecoderDirect2D.h:
* platform/graphics/win/ImageDirect2D.cpp:
(WebCore::BitmapImage::setRenderTarget): Deleted.
* platform/graphics/win/NativeImageDirect2D.cpp: Add missing include.
* platform/graphics/win/PatternDirect2D.cpp:
(WebCore::Pattern::createPlatformPattern): Revise for new signature.
* rendering/FilterEffectRenderer.cpp:
(WebCore::FilterEffectRenderer::allocateBackingStoreIfNeeded): Pass GraphicsContext
to ImageBuffer constructor.
(WebCore::FilterEffectRendererHelper::beginFilterEffect): Pass target context to
filter when allocating backing store.
* rendering/FilterEffectRenderer.h: Add GraphicsContext as argument to constructor.
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::hasFilterThatIsPainting): Supply GraphicsContext argument when
building new FilterEffectRenderer and helper.
(WebCore::RenderLayer::setupFilters): Ditto.
* svg/graphics/SVGImage.cpp:
(WebCore::SVGImage::nativeImageForCurrentFrame): Revise to take optional GraphicsContext
argument.
(WebCore::SVGImage::nativeImage): Ditto.
* svg/graphics/SVGImage.h:
* svg/graphics/SVGImageForContainer.cpp:
(WebCore::SVGImageForContainer::nativeImageForCurrentFrame): Ditto.
* svg/graphics/SVGImageForContainer.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207357 268f45cc-cd09-0410-ab3c-d52691b4dbfc

24 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/BitmapImage.cpp
Source/WebCore/platform/graphics/BitmapImage.h
Source/WebCore/platform/graphics/Image.h
Source/WebCore/platform/graphics/ImageBuffer.cpp
Source/WebCore/platform/graphics/ImageBuffer.h
Source/WebCore/platform/graphics/ImageFrameCache.cpp
Source/WebCore/platform/graphics/ImageSource.cpp
Source/WebCore/platform/graphics/ImageSource.h
Source/WebCore/platform/graphics/Pattern.h
Source/WebCore/platform/graphics/win/GraphicsContextDirect2D.cpp
Source/WebCore/platform/graphics/win/ImageBufferDirect2D.cpp
Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp
Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.h
Source/WebCore/platform/graphics/win/ImageDirect2D.cpp
Source/WebCore/platform/graphics/win/NativeImageDirect2D.cpp
Source/WebCore/platform/graphics/win/PatternDirect2D.cpp
Source/WebCore/rendering/FilterEffectRenderer.cpp
Source/WebCore/rendering/FilterEffectRenderer.h
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/svg/graphics/SVGImage.cpp
Source/WebCore/svg/graphics/SVGImage.h
Source/WebCore/svg/graphics/SVGImageForContainer.cpp
Source/WebCore/svg/graphics/SVGImageForContainer.h

index ee6c3d8..d76da11 100644 (file)
@@ -1,3 +1,84 @@
+2016-10-14  Brent Fulgham  <bfulgham@apple.com>
+
+        [Win][Direct2D] Implement basic SVG support
+        https://bugs.webkit.org/show_bug.cgi?id=163349
+
+        Reviewed by Brent Fulgham.
+
+        Direct2D needs access to the target graphics context when generating bitmap
+        images so that it can properly match pixel format and other settings.
+
+        Add implementations for a number of drawing primitives used in the SVG
+        test cases. Correct some differences between CG and Direct2D for drawing
+        different primitives.
+
+        No new tests. Tested by existing 'svg' tests.
+
+        * platform/graphics/BitmapImage.cpp:
+       (WebCore::BitmapImage::frameImageAtIndex): Take optional target graphics
+       context. Also pass the graphics context to the image decoder.
+       (WebCore::BitmapImage::nativeImage): Accept an optional target context.
+       (WebCore::BitmapImage::nativeImageForCurrentFrame): Ditto.
+       (WebCore::BitmapImage::draw): Pass target graphics context to the
+       'frameImageAtIndex' method.
+        * platform/graphics/BitmapImage.h:
+        * platform/graphics/Image.h:
+        * platform/graphics/ImageBuffer.cpp:
+        (WebCore::ImageBuffer::create): Moved from header. Add create function that
+        takes an optional GraphicsContext argument.
+        * platform/graphics/ImageBuffer.h:
+        * platform/graphics/ImageFrameCache.cpp: Add missing include needed to build
+        under Direct2D.
+        * platform/graphics/ImageSource.cpp:
+        (WebCore::ImageSource::setDecoderTargetContext): Added.
+        (WebCore::ImageSource::setRenderTarget): Deleted.
+        * platform/graphics/ImageSource.h:
+        * platform/graphics/Pattern.h:
+        * platform/graphics/win/GraphicsContextDirect2D.cpp:
+        (WebCore::GraphicsContextPlatformPrivate::endDraw): Log error state instead of crashing
+        each time.
+        (WebCore::GraphicsContext::drawEllipse): Ellipses are defined in D2D as a center, an
+        X-radius, and a Y-radius.
+        (WebCore::GraphicsContext::applyStrokePattern):
+        (WebCore::GraphicsContext::applyFillPattern):
+        (WebCore::GraphicsContext::clearRect): Use 'Clear' function if possible. Don't clear
+        anything if the clear rect is outside the drawing area.
+        (WebCore::GraphicsContext::strokeRect): Provide implementation (needed by SVG).
+        (WebCore::GraphicsContext::platformFillEllipse): Ellipses are defined in D2D as
+        a center, an X-radius, and a Y-radius.
+        (WebCore::GraphicsContext::platformStrokeEllipse): Ditto.
+        * platform/graphics/win/ImageBufferDirect2D.cpp:
+        (WebCore::ImageBuffer::createCompatibleBuffer): Accept optional GraphicsContext argument.
+        (WebCore::ImageBuffer::ImageBuffer): Ditto.
+        * platform/graphics/win/ImageDecoderDirect2D.cpp:
+        (WebCore::ImageDecoder::setTargetContext): Renamed from 'setRenderTarget'.
+        (WebCore::ImageDecoder::createFrameImageAtIndex): Take optional GraphicsContext argument.
+        (WebCore::ImageDecoder::setRenderTarget): Deleted.
+        * platform/graphics/win/ImageDecoderDirect2D.h:
+        * platform/graphics/win/ImageDirect2D.cpp:
+        (WebCore::BitmapImage::setRenderTarget): Deleted.
+        * platform/graphics/win/NativeImageDirect2D.cpp: Add missing include.
+        * platform/graphics/win/PatternDirect2D.cpp: 
+        (WebCore::Pattern::createPlatformPattern): Revise for new signature.
+        * rendering/FilterEffectRenderer.cpp:
+        (WebCore::FilterEffectRenderer::allocateBackingStoreIfNeeded): Pass GraphicsContext
+        to ImageBuffer constructor.
+        (WebCore::FilterEffectRendererHelper::beginFilterEffect): Pass target context to
+        filter when allocating backing store.
+        * rendering/FilterEffectRenderer.h: Add GraphicsContext as argument to constructor.
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::hasFilterThatIsPainting): Supply GraphicsContext argument when
+        building new FilterEffectRenderer and helper.
+        (WebCore::RenderLayer::setupFilters): Ditto.
+        * svg/graphics/SVGImage.cpp:
+        (WebCore::SVGImage::nativeImageForCurrentFrame): Revise to take optional GraphicsContext
+        argument.
+        (WebCore::SVGImage::nativeImage): Ditto.
+        * svg/graphics/SVGImage.h:
+        * svg/graphics/SVGImageForContainer.cpp:
+        (WebCore::SVGImageForContainer::nativeImageForCurrentFrame): Ditto.
+        * svg/graphics/SVGImageForContainer.h:
+
 2016-10-14  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed, rolling out r207319.
index 0c189c6..c65f7cb 100644 (file)
@@ -80,39 +80,39 @@ bool BitmapImage::dataChanged(bool allDataReceived)
     return m_source.dataChanged(data(), allDataReceived);
 }
 
-NativeImagePtr BitmapImage::frameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
+NativeImagePtr BitmapImage::frameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const GraphicsContext* targetContext)
 {
     if (frameHasInvalidNativeImageAtIndex(index, subsamplingLevel)) {
         LOG(Images, "BitmapImage %p frameImageAtIndex - subsamplingLevel was %d, resampling", this, static_cast<int>(frameSubsamplingLevelAtIndex(index)));
         invalidatePlatformData();
     }
 
-    return m_source.frameImageAtIndex(index, subsamplingLevel);
+    return m_source.frameImageAtIndex(index, subsamplingLevel, targetContext);
 }
 
-NativeImagePtr BitmapImage::nativeImage()
+NativeImagePtr BitmapImage::nativeImage(const GraphicsContext* targetContext)
 {
-    return frameImageAtIndex(0);
+    return frameImageAtIndex(0, SubsamplingLevel::Default, targetContext);
 }
 
-NativeImagePtr BitmapImage::nativeImageForCurrentFrame()
+NativeImagePtr BitmapImage::nativeImageForCurrentFrame(const GraphicsContext* targetContext)
 {
-    return frameImageAtIndex(m_currentFrame);
+    return frameImageAtIndex(m_currentFrame, SubsamplingLevel::Default, targetContext);
 }
 
 #if USE(CG)
-NativeImagePtr BitmapImage::nativeImageOfSize(const IntSize& size)
+NativeImagePtr BitmapImage::nativeImageOfSize(const IntSize& size, const GraphicsContext* targetContext)
 {
     size_t count = frameCount();
 
     for (size_t i = 0; i < count; ++i) {
-        auto image = frameImageAtIndex(i);
+        auto image = frameImageAtIndex(i, SubsamplingLevel::Default, targetContext);
         if (image && nativeImageSize(image) == size)
             return image;
     }
 
     // Fallback to the first frame image if we can't find the right size
-    return frameImageAtIndex(0);
+    return frameImageAtIndex(0, SubsamplingLevel::Default, targetContext);
 }
 
 Vector<NativeImagePtr> BitmapImage::framesNativeImages()
@@ -141,10 +141,6 @@ void BitmapImage::draw(GraphicsContext& context, const FloatRect& destRect, cons
     if (destRect.isEmpty() || srcRect.isEmpty())
         return;
 
-#if USE(DIRECT2D)
-    setRenderTarget(context);
-#endif
-
 #if PLATFORM(IOS)
     startAnimation(DoNotCatchUp);
 #else
@@ -161,7 +157,7 @@ void BitmapImage::draw(GraphicsContext& context, const FloatRect& destRect, cons
     SubsamplingLevel subsamplingLevel = m_source.subsamplingLevelForScale(scale);
     LOG(Images, "BitmapImage %p draw - subsamplingLevel %d at scale %.4f", this, static_cast<int>(subsamplingLevel), scale);
 
-    auto image = frameImageAtIndex(m_currentFrame, subsamplingLevel);
+    auto image = frameImageAtIndex(m_currentFrame, subsamplingLevel, &context);
     if (!image) // If it's too early we won't have an image yet.
         return;
 
index 74c22a2..092ae63 100644 (file)
@@ -117,21 +117,18 @@ public:
     Evas_Object* getEvasObject(Evas*) override;
 #endif
 
-    WEBCORE_EXPORT NativeImagePtr nativeImage() override;
-    NativeImagePtr nativeImageForCurrentFrame() override;
+    WEBCORE_EXPORT NativeImagePtr nativeImage(const GraphicsContext* = nullptr) override;
+    NativeImagePtr nativeImageForCurrentFrame(const GraphicsContext* = nullptr) override;
 #if USE(CG)
-    NativeImagePtr nativeImageOfSize(const IntSize&) override;
+    NativeImagePtr nativeImageOfSize(const IntSize&, const GraphicsContext* = nullptr) override;
     Vector<NativeImagePtr> framesNativeImages() override;
 #endif
-#if USE(DIRECT2D)
-    void setRenderTarget(GraphicsContext&);
-#endif
 
 protected:
     WEBCORE_EXPORT BitmapImage(NativeImagePtr&&, ImageObserver* = nullptr);
     WEBCORE_EXPORT BitmapImage(ImageObserver* = nullptr);
 
-    NativeImagePtr frameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
+    NativeImagePtr frameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, const GraphicsContext* = nullptr);
 
     // Called to invalidate cached data. When |destroyAll| is true, we wipe out
     // the entire frame buffer cache and tell the image source to destroy
index a1d0952..915018f 100644 (file)
@@ -137,9 +137,9 @@ public:
 
     enum TileRule { StretchTile, RoundTile, SpaceTile, RepeatTile };
 
-    virtual NativeImagePtr nativeImage() { return nullptr; }
-    virtual NativeImagePtr nativeImageOfSize(const IntSize&) { return nullptr; }
-    virtual NativeImagePtr nativeImageForCurrentFrame() { return nullptr; }
+    virtual NativeImagePtr nativeImage(const GraphicsContext* = nullptr) { return nullptr; }
+    virtual NativeImagePtr nativeImageOfSize(const IntSize&, const GraphicsContext* = nullptr) { return nullptr; }
+    virtual NativeImagePtr nativeImageForCurrentFrame(const GraphicsContext* = nullptr) { return nullptr; }
     virtual ImageOrientation orientationForCurrentFrame() const { return ImageOrientation(); }
     virtual Vector<NativeImagePtr> framesNativeImages() { return { }; }
 
index ef986c9..eae4c4e 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * 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
@@ -37,6 +38,26 @@ namespace WebCore {
 static const float MaxClampedLength = 4096;
 static const float MaxClampedArea = MaxClampedLength * MaxClampedLength;
 
+std::unique_ptr<ImageBuffer> ImageBuffer::create(const FloatSize& size, RenderingMode renderingMode, float resolutionScale, ColorSpace colorSpace)
+{
+    bool success = false;
+    std::unique_ptr<ImageBuffer> buffer(new ImageBuffer(size, resolutionScale, colorSpace, renderingMode, success));
+    if (!success)
+        return nullptr;
+    return buffer;
+}
+
+#if USE(DIRECT2D)
+std::unique_ptr<ImageBuffer> ImageBuffer::create(const FloatSize& size, RenderingMode renderingMode, const GraphicsContext* targetContext, float resolutionScale, ColorSpace colorSpace)
+{
+    bool success = false;
+    std::unique_ptr<ImageBuffer> buffer(new ImageBuffer(size, resolutionScale, colorSpace, renderingMode, targetContext, success));
+    if (!success)
+        return nullptr;
+    return buffer;
+}
+#endif
+
 bool ImageBuffer::sizeNeedsClamping(const FloatSize& size)
 {
     if (size.isEmpty())
index 63080ee..f819720 100644 (file)
 #include "IntSize.h"
 #include "ImageBufferData.h"
 #include "PlatformLayer.h"
+#include <memory>
 #include <runtime/Uint8ClampedArray.h>
 #include <wtf/Forward.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
 
-#if PLATFORM(WIN)
-interface ID2D1RenderTarget;
-#endif
-
 namespace WebCore {
 
 class FloatRect;
@@ -74,14 +71,10 @@ class ImageBuffer {
     friend class IOSurface;
 public:
     // Will return a null pointer on allocation failure.
-    static std::unique_ptr<ImageBuffer> create(const FloatSize& size, RenderingMode renderingMode, float resolutionScale = 1, ColorSpace colorSpace = ColorSpaceSRGB)
-    {
-        bool success = false;
-        std::unique_ptr<ImageBuffer> buffer(new ImageBuffer(size, resolutionScale, colorSpace, renderingMode, success));
-        if (!success)
-            return nullptr;
-        return buffer;
-    }
+    WEBCORE_EXPORT static std::unique_ptr<ImageBuffer> create(const FloatSize&, RenderingMode, float resolutionScale = 1, ColorSpace = ColorSpaceSRGB);
+#if USE(DIRECT2D)
+    WEBCORE_EXPORT static std::unique_ptr<ImageBuffer> create(const FloatSize&, RenderingMode, const GraphicsContext*, float resolutionScale = 1, ColorSpace = ColorSpaceSRGB);
+#endif
 
     // Create an image buffer compatible with the context, with suitable resolution for drawing into the buffer and then into this context.
     static std::unique_ptr<ImageBuffer> createCompatibleBuffer(const FloatSize&, const GraphicsContext&);
@@ -182,7 +175,7 @@ private:
 #if USE(CG)
     ImageBuffer(const FloatSize&, float resolutionScale, CGColorSpaceRef, RenderingMode, bool& success);
 #elif USE(DIRECT2D)
-    ImageBuffer(const FloatSize&, float resolutionScale, ColorSpace, RenderingMode, ID2D1RenderTarget*, bool& success);
+    ImageBuffer(const FloatSize&, float resolutionScale, ColorSpace, RenderingMode, const GraphicsContext*, bool& success);
 #endif
 };
 
index fbfd601..4b948e5 100644 (file)
@@ -31,6 +31,9 @@
 
 #if USE(CG)
 #include "ImageDecoderCG.h"
+#elif USE(DIRECT2D)
+#include "ImageDecoderDirect2D.h"
+#include <WinCodec.h>
 #else
 #include "ImageDecoder.h"
 #endif
index 8256034..e835beb 100644 (file)
@@ -115,15 +115,18 @@ bool ImageSource::ensureDecoderAvailable(SharedBuffer* data)
     return true;
 }
 
-#if USE(DIRECT2D)
-void ImageSource::setRenderTarget(GraphicsContext& context)
+void ImageSource::setDecoderTargetContext(const GraphicsContext* targetContext)
 {
+#if USE(DIRECT2D)
     if (!isDecoderAvailable())
         return;
 
-    m_decoder->setRenderTarget(context.platformContext());
-}
+    if (targetContext)
+        m_decoder->setTargetContext(targetContext->platformContext());
+#else
+    UNUSED_PARAM(targetContext);
 #endif
+}
 
 void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
 {
@@ -209,6 +212,13 @@ NativeImagePtr ImageSource::createFrameImageAtIndex(size_t index, SubsamplingLev
     return isDecoderAvailable() ? m_decoder->createFrameImageAtIndex(index, subsamplingLevel) : nullptr;
 }
 
+NativeImagePtr ImageSource::frameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const GraphicsContext* targetContext)
+{
+    setDecoderTargetContext(targetContext);
+
+    return m_frameCache.frameImageAtIndex(index, subsamplingLevel);
+}
+
 void ImageSource::dump(TextStream& ts)
 {
     ts.dumpProperty("type", filenameExtension());
index ccdf7f1..76e9809 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010, 2012, 2014, 2016 Apple Inc.  All rights reserved.
+ * Copyright (C) 2004-2008, 2010, 2012, 2014, 2016 Apple Inc.  All rights reserved.
  * Copyright (C) 2007-2008 Torch Mobile, Inc.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -59,10 +59,6 @@ public:
     bool ensureDecoderAvailable(SharedBuffer*);
     bool isDecoderAvailable() const { return m_decoder.get(); }
 
-#if USE(DIRECT2D)
-    void setRenderTarget(GraphicsContext&);
-#endif
-
     void setData(SharedBuffer* data, bool allDataReceived);
     bool dataChanged(SharedBuffer* data, bool allDataReceived);
 
@@ -93,7 +89,7 @@ public:
     unsigned frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel = SubsamplingLevel::Default) { return m_frameCache.frameBytesAtIndex(index, subsamplingLevel); }
     float frameDurationAtIndex(size_t index) { return m_frameCache.frameDurationAtIndex(index); }
     ImageOrientation frameOrientationAtIndex(size_t index) { return m_frameCache.frameOrientationAtIndex(index); }
-    NativeImagePtr frameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel = SubsamplingLevel::Default) { return m_frameCache.frameImageAtIndex(index, subsamplingLevel); }
+    NativeImagePtr frameImageAtIndex(size_t index, SubsamplingLevel = SubsamplingLevel::Default, const GraphicsContext* targetContext = nullptr);
 
     SubsamplingLevel maximumSubsamplingLevel();
     SubsamplingLevel subsamplingLevelForScale(float);
@@ -104,7 +100,9 @@ private:
     void clearFrameBufferCache(size_t);
     void clear(bool destroyAll, size_t count, SharedBuffer* data);
     void dump(TextStream&);
-    
+
+    void setDecoderTargetContext(const GraphicsContext*);
+
     ImageFrameCache m_frameCache;
     std::unique_ptr<ImageDecoder> m_decoder;
 
index 01a73b6..256fa2d 100644 (file)
@@ -39,7 +39,6 @@ typedef struct CGPattern* CGPatternRef;
 typedef CGPatternRef PlatformPatternPtr;
 #elif USE(DIRECT2D)
 interface ID2D1BitmapBrush;
-interface ID2D1RenderTarget;
 typedef ID2D1BitmapBrush* PlatformPatternPtr;
 #elif USE(CAIRO)
 #include <cairo.h>
@@ -51,6 +50,7 @@ typedef void* PlatformPatternPtr;
 namespace WebCore {
 
 class AffineTransform;
+class GraphicsContext;
 class Image;
 
 class Pattern final : public RefCounted<Pattern> {
@@ -66,7 +66,7 @@ public:
 #if !USE(DIRECT2D)
     PlatformPatternPtr createPlatformPattern(const AffineTransform& userSpaceTransformation) const;
 #else
-    PlatformPatternPtr createPlatformPattern(ID2D1RenderTarget*, float alpha, const AffineTransform& userSpaceTransformation) const;
+    PlatformPatternPtr createPlatformPattern(const GraphicsContext&, float alpha, const AffineTransform& userSpaceTransformation) const;
 #endif
     void setPatternSpaceTransform(const AffineTransform& patternSpaceTransformation);
     const AffineTransform& getPatternSpaceTransform() { return m_patternSpaceTransformation; };
index fa9fb4c..7bea0b6 100644 (file)
@@ -338,7 +338,8 @@ void GraphicsContextPlatformPrivate::endDraw()
     D2D1_TAG first, second;
     HRESULT hr = m_renderTarget->EndDraw(&first, &second);
 
-    RELEASE_ASSERT(SUCCEEDED(hr));
+    if (!SUCCEEDED(hr))
+        WTFLogAlways("Failed in GraphicsContextPlatformPrivate::endDraw: hr=%ld, first=%ld, second=%ld", hr, first, second);
 }
 
 void GraphicsContextPlatformPrivate::restore()
@@ -736,7 +737,7 @@ void GraphicsContext::drawEllipse(const FloatRect& rect)
         return;
     }
 
-    auto ellipse = D2D1::Ellipse(D2D1::Point2F(rect.x(), rect.y()), rect.width(), rect.height());
+    auto ellipse = D2D1::Ellipse(rect.center(), 0.5 * rect.width(), 0.5 * rect.height());
 
     auto context = platformContext();
 
@@ -758,7 +759,7 @@ void GraphicsContext::applyStrokePattern()
     AffineTransform userToBaseCTM; // FIXME: This isn't really needed on Windows
 
     const float patternAlpha = 1;
-    m_data->m_patternStrokeBrush = adoptCOM(m_state.strokePattern->createPlatformPattern(context, patternAlpha, userToBaseCTM));
+    m_data->m_patternStrokeBrush = adoptCOM(m_state.strokePattern->createPlatformPattern(*this, patternAlpha, userToBaseCTM));
 }
 
 void GraphicsContext::applyFillPattern()
@@ -770,7 +771,7 @@ void GraphicsContext::applyFillPattern()
     AffineTransform userToBaseCTM; // FIXME: This isn't really needed on Windows
 
     const float patternAlpha = 1;
-    m_data->m_patternFillBrush = adoptCOM(m_state.fillPattern->createPlatformPattern(context, patternAlpha, userToBaseCTM));
+    m_data->m_patternFillBrush = adoptCOM(m_state.fillPattern->createPlatformPattern(*this, patternAlpha, userToBaseCTM));
 }
 
 void GraphicsContext::drawPath(const Path& path)
@@ -1329,24 +1330,58 @@ void GraphicsContext::clearRect(const FloatRect& rect)
         return;
     }
 
-    auto context = platformContext();
-
-    context->SetTags(1, __LINE__);
-
     drawWithoutShadow(rect, [this, rect](ID2D1RenderTarget* renderTarget) {
-        FloatSize renderTargetSize = renderTarget->GetSize();
-        if (rect.size() == renderTargetSize)
+        FloatRect renderTargetRect(FloatPoint(), renderTarget->GetSize());
+        FloatRect rectToClear(rect);
+
+        if (rectToClear.contains(renderTargetRect)) {
+            renderTarget->SetTags(1, __LINE__);
             renderTarget->Clear();
-        else
-            renderTarget->FillRectangle(rect, m_data->brushWithColor(colorWithGlobalAlpha(fillColor())).get());
+            return;
+        }
+
+        if (!rectToClear.intersects(renderTargetRect))
+            return;
+
+        renderTarget->SetTags(1, __LINE__);
+        rectToClear.intersect(renderTargetRect);
+        renderTarget->FillRectangle(rectToClear, m_data->brushWithColor(colorWithGlobalAlpha(fillColor())).get());
     });
 }
 
 void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
 {
-    (void)rect;
-    (void)lineWidth;
-    notImplemented();
+    if (paintingDisabled())
+        return;
+
+    if (isRecording()) {
+        m_displayListRecorder->strokeRect(rect, lineWidth);
+        return;
+    }
+
+    if (m_state.strokeGradient) {
+        auto drawFunction = [this, rect, lineWidth](ID2D1RenderTarget* renderTarget) {
+            renderTarget->SetTags(1, __LINE__);
+            const D2D1_RECT_F d2dRect = rect;
+            renderTarget->DrawRectangle(&d2dRect, m_state.strokeGradient->createPlatformGradientIfNecessary(renderTarget), lineWidth, m_data->strokeStyle());
+        };
+
+        if (hasShadow())
+            drawWithShadow(rect, drawFunction);
+        else
+            drawWithoutShadow(rect, drawFunction);
+        return;
+    }
+
+    if (m_state.strokePattern)
+        applyStrokePattern();
+
+    drawWithoutShadow(rect, [this, rect, lineWidth](ID2D1RenderTarget* renderTarget) {
+        renderTarget->SetTags(1, __LINE__);
+        const D2D1_RECT_F d2dRect = rect;
+        auto brush = m_state.strokePattern ? patternStrokeBrush() : solidStrokeBrush();
+        renderTarget->DrawRectangle(&d2dRect, brush, lineWidth, m_data->strokeStyle());
+    });
 }
 
 void GraphicsContext::setLineCap(LineCap cap)
@@ -1813,7 +1848,7 @@ void GraphicsContext::platformFillEllipse(const FloatRect& ellipse)
         return;
     }
 
-    auto d2dEllipse = D2D1::Ellipse(D2D1::Point2F(ellipse.x(), ellipse.y()), ellipse.width(), ellipse.height());
+    auto d2dEllipse = D2D1::Ellipse(ellipse.center(), 0.5 * ellipse.width(), 0.5 * ellipse.height());
 
     platformContext()->SetTags(1, __LINE__);
 
@@ -1835,7 +1870,7 @@ void GraphicsContext::platformStrokeEllipse(const FloatRect& ellipse)
         return;
     }
 
-    auto d2dEllipse = D2D1::Ellipse(D2D1::Point2F(ellipse.x(), ellipse.y()), ellipse.width(), ellipse.height());
+    auto d2dEllipse = D2D1::Ellipse(ellipse.center(), 0.5 * ellipse.width(), 0.5 * ellipse.height());
 
     platformContext()->SetTags(1, __LINE__);
 
index 5734868..a94836e 100644 (file)
@@ -66,7 +66,7 @@ std::unique_ptr<ImageBuffer> ImageBuffer::createCompatibleBuffer(const FloatSize
     RenderingMode renderingMode = context.renderingMode();
     IntSize scaledSize = ImageBuffer::compatibleBufferSize(size, context);
     bool success = false;
-    std::unique_ptr<ImageBuffer> buffer(new ImageBuffer(scaledSize, 1, ColorSpaceSRGB, renderingMode, context.platformContext(), success));
+    std::unique_ptr<ImageBuffer> buffer(new ImageBuffer(scaledSize, 1, ColorSpaceSRGB, renderingMode, &context, success));
 
     if (!success)
         return nullptr;
@@ -76,7 +76,7 @@ std::unique_ptr<ImageBuffer> ImageBuffer::createCompatibleBuffer(const FloatSize
     return buffer;
 }
 
-ImageBuffer::ImageBuffer(const FloatSize& size, float resolutionScale, ColorSpace /*colorSpace*/, RenderingMode renderingMode, ID2D1RenderTarget* renderTarget, bool& success)
+ImageBuffer::ImageBuffer(const FloatSize& size, float resolutionScale, ColorSpace /*colorSpace*/, RenderingMode renderingMode, const GraphicsContext* targetContext, bool& success)
     : m_logicalSize(size)
     , m_resolutionScale(resolutionScale)
 {
@@ -101,6 +101,7 @@ ImageBuffer::ImageBuffer(const FloatSize& size, float resolutionScale, ColorSpac
     if (numBytes.hasOverflowed())
         return;
 
+    auto renderTarget = targetContext ? targetContext->platformContext() : nullptr;
     if (!renderTarget)
         renderTarget = GraphicsContext::defaultRenderTarget();
     RELEASE_ASSERT(renderTarget);
index 0f1bcb1..a51961f 100644 (file)
@@ -187,14 +187,14 @@ unsigned ImageDecoder::frameBytesAtIndex(size_t index, SubsamplingLevel subsampl
     return width * height * 4;
 }
 
-void ImageDecoder::setRenderTarget(ID2D1RenderTarget* renderTarget)
+void ImageDecoder::setTargetContext(ID2D1RenderTarget* renderTarget)
 {
     m_renderTarget = renderTarget;
 }
 
 NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, DecodingMode) const
 {
-    if (!m_nativeDecoder)
+    if (!m_nativeDecoder || !m_renderTarget)
         return nullptr;
 
     COMPtr<IWICBitmapFrameDecode> frame;
@@ -211,10 +211,6 @@ NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLe
     if (!SUCCEEDED(hr))
         return nullptr;
 
-    ASSERT(m_renderTarget);
-    if (!m_renderTarget)
-        return nullptr;
-
     COMPtr<ID2D1Bitmap> bitmap;
     hr = m_renderTarget->CreateBitmapFromWicBitmap(converter.get(), nullptr, &bitmap);
     if (!SUCCEEDED(hr))
index dd002cb..e538267 100644 (file)
@@ -73,7 +73,7 @@ public:
     bool isAllDataReceived() const { return m_isAllDataReceived; }
     void clearFrameBufferCache(size_t) { }
 
-    void setRenderTarget(ID2D1RenderTarget*);
+    void setTargetContext(ID2D1RenderTarget*);
 
     static IWICImagingFactory* systemImagingFactory();
 
index c81757f..2507c1c 100644 (file)
@@ -92,11 +92,6 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext& ctxt, const Float
     draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), compositeOp, BlendModeNormal, ImageOrientationDescription());
 }
 
-void BitmapImage::setRenderTarget(GraphicsContext& context)
-{
-    m_source.setRenderTarget(context);
-}
-
 void Image::drawPattern(GraphicsContext& ctxt, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform,
     const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
 {
index fd61380..ad277a9 100644 (file)
@@ -32,6 +32,7 @@
 #include "GraphicsContext.h"
 #include "IntSize.h"
 #include "NotImplemented.h"
+#include <d2d1.h>
 
 namespace WebCore {
 
index 2f4fd4b..1b9229e 100644 (file)
 
 namespace WebCore {
 
-ID2D1BitmapBrush* Pattern::createPlatformPattern(ID2D1RenderTarget* renderTarget, float alpha, const AffineTransform& userSpaceTransformation) const
+ID2D1BitmapBrush* Pattern::createPlatformPattern(const GraphicsContext& context, float alpha, const AffineTransform& userSpaceTransformation) const
 {
-    RELEASE_ASSERT(renderTarget);
-
-    FloatRect tileRect = tileImage()->rect();
-
     AffineTransform patternTransform = userSpaceTransformation * m_patternSpaceTransformation;
     auto bitmapBrushProperties = D2D1::BitmapBrushProperties();
     bitmapBrushProperties.extendModeX = m_repeatX ? D2D1_EXTEND_MODE_WRAP : D2D1_EXTEND_MODE_CLAMP;
@@ -52,9 +48,14 @@ ID2D1BitmapBrush* Pattern::createPlatformPattern(ID2D1RenderTarget* renderTarget
     brushProperties.transform = patternTransform;
     brushProperties.opacity = alpha;
 
+    auto patternImage = tileImage();
+
+    auto platformContext = context.platformContext();
+    RELEASE_ASSERT(platformContext);
+
     ID2D1BitmapBrush* patternBrush = nullptr;
-    HRESULT hr = renderTarget->CreateBitmapBrush(tileImage()->nativeImage().get(), &bitmapBrushProperties, &brushProperties, &patternBrush);
-    ASSERT(hr);
+    HRESULT hr = platformContext->CreateBitmapBrush(patternImage->nativeImage(&context).get(), &bitmapBrushProperties, &brushProperties, &patternBrush);
+    ASSERT(SUCCEEDED(hr));
     return patternBrush;
 }
 
index ba511cc..8c67554 100644 (file)
 #include <algorithm>
 #include <wtf/MathExtras.h>
 
+#if USE(DIRECT2D)
+#include <d2d1.h>
+#endif
+
 namespace WebCore {
 
 static inline void endMatrixRow(Vector<float>& parameters)
@@ -313,15 +317,21 @@ bool FilterEffectRenderer::updateBackingStoreRect(const FloatRect& filterRect)
     return true;
 }
 
-void FilterEffectRenderer::allocateBackingStoreIfNeeded()
+void FilterEffectRenderer::allocateBackingStoreIfNeeded(const GraphicsContext& targetContext)
 {
     // At this point the effect chain has been built, and the
     // source image sizes set. We just need to attach the graphic
     // buffer if we have not yet done so.
     if (!m_graphicsBufferAttached) {
         IntSize logicalSize(m_sourceDrawingRegion.width(), m_sourceDrawingRegion.height());
-        if (!sourceImage() || sourceImage()->logicalSize() != logicalSize)
+        if (!sourceImage() || sourceImage()->logicalSize() != logicalSize) {
+#if USE(DIRECT2D)
+            setSourceImage(ImageBuffer::create(logicalSize, renderingMode(), &targetContext, filterScale()));
+#else
+            UNUSED_PARAM(targetContext);
             setSourceImage(ImageBuffer::create(logicalSize, renderingMode(), filterScale()));
+#endif
+        }
         m_graphicsBufferAttached = true;
     }
 }
@@ -396,7 +406,7 @@ bool FilterEffectRendererHelper::beginFilterEffect()
     ASSERT(m_renderLayer);
     
     FilterEffectRenderer* filter = m_renderLayer->filterRenderer();
-    filter->allocateBackingStoreIfNeeded();
+    filter->allocateBackingStoreIfNeeded(m_targetContext);
     // Paint into the context that represents the SourceGraphic of the filter.
     GraphicsContext* sourceGraphicsContext = filter->inputContext();
     if (!sourceGraphicsContext || filter->filterRegion().isEmpty() || ImageBuffer::sizeNeedsClamping(filter->filterRegion().size())) {
index c731adb..2ed8870 100644 (file)
@@ -40,6 +40,7 @@
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 
+
 namespace WebCore {
 
 class Document;
@@ -57,8 +58,9 @@ enum FilterConsumer {
 class FilterEffectRendererHelper {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    FilterEffectRendererHelper(bool haveFilterEffect)
-        : m_haveFilterEffect(haveFilterEffect)
+    FilterEffectRendererHelper(bool haveFilterEffect, GraphicsContext& targetContext)
+        : m_targetContext(targetContext)
+        , m_haveFilterEffect(haveFilterEffect)
     {
     }
     
@@ -77,6 +79,7 @@ private:
     RenderLayer* m_renderLayer { nullptr }; // FIXME: this is mainly used to get the FilterEffectRenderer. FilterEffectRendererHelper should be weaned off it.
     LayoutPoint m_paintOffset;
     LayoutRect m_repaintRect;
+    const GraphicsContext& m_targetContext;
     bool m_haveFilterEffect { false };
     bool m_startedFilterEffect { false };
 };
@@ -107,7 +110,7 @@ public:
     bool build(RenderElement*, const FilterOperations&, FilterConsumer);
     PassRefPtr<FilterEffect> buildReferenceFilter(RenderElement*, PassRefPtr<FilterEffect> previousEffect, ReferenceFilterOperation*);
     bool updateBackingStoreRect(const FloatRect& filterRect);
-    void allocateBackingStoreIfNeeded();
+    void allocateBackingStoreIfNeeded(const GraphicsContext&);
     void clearIntermediateResults();
     void apply();
     
index 0c4d1bf..3543528 100644 (file)
@@ -4168,7 +4168,7 @@ bool RenderLayer::hasFilterThatIsPainting(GraphicsContext& context, PaintLayerFl
     if (!hasPaintedFilter)
         return false;
 
-    auto filterPainter = std::make_unique<FilterEffectRendererHelper>(hasPaintedFilter);
+    auto filterPainter = std::make_unique<FilterEffectRendererHelper>(hasPaintedFilter, context);
     if (!filterPainter->haveFilterEffect())
         return false;
 
@@ -4182,7 +4182,7 @@ std::unique_ptr<FilterEffectRendererHelper> RenderLayer::setupFilters(GraphicsCo
 
     FilterInfo* filterInfo = FilterInfo::getIfExists(*this);
     bool hasPaintedFilter = filterInfo && filterInfo->renderer() && paintsWithFilters();
-    auto filterPainter = std::make_unique<FilterEffectRendererHelper>(hasPaintedFilter);
+    auto filterPainter = std::make_unique<FilterEffectRendererHelper>(hasPaintedFilter, context);
 
     LayoutRect filterRepaintRect = filterInfo->dirtySourceRect();
     filterRepaintRect.move(offsetFromRoot);
index a6a733f..c5a4ba0 100644 (file)
 #include <runtime/JSCInlines.h>
 #include <runtime/JSLock.h>
 
+#if USE(DIRECT2D)
+#include "COMPtr.h"
+#include <d2d1.h>
+#endif
+
 namespace WebCore {
 
 SVGImage::SVGImage(ImageObserver& observer, const URL& url)
@@ -187,7 +192,7 @@ void SVGImage::drawForContainer(GraphicsContext& context, const FloatSize contai
 #if USE(CAIRO)
 // Passes ownership of the native image to the caller so NativeImagePtr needs
 // to be a smart pointer type.
-NativeImagePtr SVGImage::nativeImageForCurrentFrame()
+NativeImagePtr SVGImage::nativeImageForCurrentFrame(const GraphicsContext*)
 {
     if (!m_page)
         return nullptr;
@@ -204,6 +209,38 @@ NativeImagePtr SVGImage::nativeImageForCurrentFrame()
 }
 #endif
 
+#if USE(DIRECT2D)
+NativeImagePtr SVGImage::nativeImage(const GraphicsContext* targetContext)
+{
+    ASSERT(targetContext);
+    if (!m_page || !targetContext)
+        return nullptr;
+
+    auto platformContext = targetContext->platformContext();
+    ASSERT(platformContext);
+
+    // Draw the SVG into a bitmap.
+    COMPtr<ID2D1BitmapRenderTarget> nativeImageTarget;
+    HRESULT hr = platformContext->CreateCompatibleRenderTarget(IntSize(rect().size()), &nativeImageTarget);
+    ASSERT(SUCCEEDED(hr));
+
+    nativeImageTarget->BeginDraw();
+    GraphicsContext localContext(nativeImageTarget.get());
+    localContext.setDidBeginDraw(true);
+
+    draw(localContext, rect(), rect(), CompositeSourceOver, BlendModeNormal, ImageOrientationDescription());
+
+    hr = nativeImageTarget->Flush();
+    ASSERT(SUCCEEDED(hr));
+
+    COMPtr<ID2D1Bitmap> nativeImage;
+    hr = nativeImageTarget->GetBitmap(&nativeImage);
+    ASSERT(SUCCEEDED(hr));
+
+    return nativeImage;
+}
+#endif
+
 void SVGImage::drawPatternForContainer(GraphicsContext& context, const FloatSize& containerSize, float zoom, const FloatRect& srcRect,
     const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator compositeOp, const FloatRect& dstRect, BlendMode blendMode)
 {
index e32a401..80bb9df 100644 (file)
@@ -66,7 +66,10 @@ public:
     void resetAnimation() final;
 
 #if USE(CAIRO)
-    NativeImagePtr nativeImageForCurrentFrame() final;
+    NativeImagePtr nativeImageForCurrentFrame(const GraphicsContext* = nullptr) final;
+#endif
+#if USE(DIRECT2D)
+    NativeImagePtr nativeImage(const GraphicsContext* = nullptr) final;
 #endif
 
 private:
index bb6fb5a..482c394 100644 (file)
@@ -46,9 +46,9 @@ void SVGImageForContainer::drawPattern(GraphicsContext& context, const FloatRect
     m_image->drawPatternForContainer(context, m_containerSize, m_zoom, srcRect, patternTransform, phase, spacing, compositeOp, dstRect, blendMode);
 }
 
-NativeImagePtr SVGImageForContainer::nativeImageForCurrentFrame()
+NativeImagePtr SVGImageForContainer::nativeImageForCurrentFrame(const GraphicsContext* targetContext)
 {
-    return m_image->nativeImageForCurrentFrame();
+    return m_image->nativeImageForCurrentFrame(targetContext);
 }
 
 } // namespace WebCore
index c3051a7..c42728d 100644 (file)
@@ -63,7 +63,7 @@ public:
     // FIXME: Implement this to be less conservative.
     bool currentFrameKnownToBeOpaque() const final { return false; }
 
-    NativeImagePtr nativeImageForCurrentFrame() final;
+    NativeImagePtr nativeImageForCurrentFrame(const GraphicsContext* = nullptr) final;
 
 private:
     SVGImageForContainer(SVGImage* image, const FloatSize& containerSize, float zoom)