[Win][Direct2D] Add D2D Bitmap Image handling code
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Oct 2016 20:22:57 +0000 (20:22 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Oct 2016 20:22:57 +0000 (20:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=162761

Reviewed by Dean Jackson.

This patch lands a set of new files that implement
Image and BitmapImage features on Windows using
Direct2D.

The desired ID2D1RenderTarget handle is needed by the
image decoder so that it can load the resulting bitmap
into the GPU.

No new tests until complete backend lands.

* platform/graphics/BitmapImage.cpp:
(WebCore::BitmapImage::draw): Tell the Direct2D image decoder
which render target to use.
* platform/graphics/BitmapImage.h:
* platform/graphics/ImageBuffer.cpp:
* platform/graphics/ImageBuffer.h:
* platform/graphics/ImageBufferData.h:
* platform/graphics/ImageFrameCache.cpp:
(WebCore::ImageFrameCache::setRenderTarget): Added.
* platform/graphics/ImageFrameCache.h:
(WebCore::ImageFrameCache::decoder): Added.
* platform/graphics/ImageSource.cpp:
* platform/graphics/ImageSource.h:
(WebCore::ImageSource::setRenderTarget):
* platform/graphics/win/ImageBufferDataDirect2D.cpp: Added.
* platform/graphics/win/ImageBufferDataDirect2D.h: Added.
* platform/graphics/win/ImageBufferDirect2D.cpp: Added.
* platform/graphics/win/ImageCGWin.cpp:
* platform/graphics/win/ImageDecoderDirect2D.cpp: Added.
* platform/graphics/win/ImageDecoderDirect2D.h: Added.
* platform/graphics/win/ImageDirect2D.cpp: Added.
* platform/graphics/win/NativeImageDirect2D.cpp: Added.

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

19 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/BitmapImage.cpp
Source/WebCore/platform/graphics/BitmapImage.h
Source/WebCore/platform/graphics/ImageBuffer.cpp
Source/WebCore/platform/graphics/ImageBuffer.h
Source/WebCore/platform/graphics/ImageBufferData.h
Source/WebCore/platform/graphics/ImageFrameCache.cpp
Source/WebCore/platform/graphics/ImageFrameCache.h
Source/WebCore/platform/graphics/ImageSource.cpp
Source/WebCore/platform/graphics/ImageSource.h
Source/WebCore/platform/graphics/NativeImage.h
Source/WebCore/platform/graphics/win/ImageBufferDataDirect2D.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/win/ImageBufferDataDirect2D.h [new file with mode: 0644]
Source/WebCore/platform/graphics/win/ImageBufferDirect2D.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/win/ImageCGWin.cpp
Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.h [new file with mode: 0644]
Source/WebCore/platform/graphics/win/ImageDirect2D.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/win/NativeImageDirect2D.cpp [new file with mode: 0644]

index a504418..d3386e5 100644 (file)
@@ -1,3 +1,43 @@
+2016-10-03  Brent Fulgham  <bfulgham@apple.com>
+
+        [Win][Direct2D] Add D2D Bitmap Image handling code
+        https://bugs.webkit.org/show_bug.cgi?id=162761
+
+        Reviewed by Dean Jackson.
+
+        This patch lands a set of new files that implement
+        Image and BitmapImage features on Windows using
+        Direct2D.
+
+        The desired ID2D1RenderTarget handle is needed by the
+        image decoder so that it can load the resulting bitmap
+        into the GPU.
+
+        No new tests until complete backend lands.
+
+        * platform/graphics/BitmapImage.cpp:
+        (WebCore::BitmapImage::draw): Tell the Direct2D image decoder
+        which render target to use.
+        * platform/graphics/BitmapImage.h:
+        * platform/graphics/ImageBuffer.cpp:
+        * platform/graphics/ImageBuffer.h:
+        * platform/graphics/ImageBufferData.h:
+        * platform/graphics/ImageFrameCache.cpp:
+        (WebCore::ImageFrameCache::setRenderTarget): Added.
+        * platform/graphics/ImageFrameCache.h:
+        (WebCore::ImageFrameCache::decoder): Added.
+        * platform/graphics/ImageSource.cpp:
+        * platform/graphics/ImageSource.h:
+        (WebCore::ImageSource::setRenderTarget):
+        * platform/graphics/win/ImageBufferDataDirect2D.cpp: Added.
+        * platform/graphics/win/ImageBufferDataDirect2D.h: Added.
+        * platform/graphics/win/ImageBufferDirect2D.cpp: Added.
+        * platform/graphics/win/ImageCGWin.cpp:
+        * platform/graphics/win/ImageDecoderDirect2D.cpp: Added.
+        * platform/graphics/win/ImageDecoderDirect2D.h: Added.
+        * platform/graphics/win/ImageDirect2D.cpp: Added.
+        * platform/graphics/win/NativeImageDirect2D.cpp: Added.
+
 2016-10-03  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [SOUP] Remove unused methods toSoupMessage from ResourceRequest/Response
index 77eaf4a..0c189c6 100644 (file)
@@ -141,6 +141,10 @@ 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
index ac14573..5629c60 100644 (file)
@@ -122,6 +122,9 @@ public:
     NativeImagePtr nativeImageOfSize(const IntSize&) override;
     Vector<NativeImagePtr> framesNativeImages() override;
 #endif
+#if USE(DIRECT2D)
+    void setRenderTarget(GraphicsContext&);
+#endif
 
 protected:
     WEBCORE_EXPORT BitmapImage(NativeImagePtr&&, ImageObserver* = nullptr);
index 15c1633..ef986c9 100644 (file)
@@ -81,7 +81,7 @@ FloatRect ImageBuffer::clampedRect(const FloatRect& rect)
     return FloatRect(rect.location(), clampedSize(rect.size()));
 }
 
-#if !USE(CG)
+#if !(USE(CG) || USE(DIRECT2D))
 FloatSize ImageBuffer::sizeForDestinationSize(FloatSize size) const
 {
     return size;
index f013343..63080ee 100644 (file)
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
 
+#if PLATFORM(WIN)
+interface ID2D1RenderTarget;
+#endif
+
 namespace WebCore {
 
 class FloatRect;
@@ -149,6 +153,8 @@ private:
     RetainPtr<CGImageRef> copyNativeImage(BackingStoreCopy = CopyBackingStore) const;
     static RetainPtr<CGImageRef> sinkIntoNativeImage(std::unique_ptr<ImageBuffer>);
     void flushContext() const;
+#elif USE(DIRECT2D)
+    void flushContext() const;
 #endif
     
     void draw(GraphicsContext&, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1), CompositeOperator = CompositeSourceOver, BlendMode = BlendModeNormal);
@@ -175,6 +181,8 @@ private:
     WEBCORE_EXPORT ImageBuffer(const FloatSize&, float resolutionScale, ColorSpace, RenderingMode, bool& success);
 #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);
 #endif
 };
 
index fbdae7a..f89ec0d 100644 (file)
@@ -25,6 +25,8 @@
 
 #if USE(CG)
 #include "ImageBufferDataCG.h"
+#elif USE(DIRECT2D)
+#include "ImageBufferDataDirect2D.h"
 #elif USE(CAIRO)
 #include "ImageBufferDataCairo.h"
 #endif
index fbfd601..e7a4171 100644 (file)
 
 #if USE(CG)
 #include "ImageDecoderCG.h"
+#elif USE(DIRECT2D)
+#include "GraphicsContext.h"
+#include "ImageDecoderDirect2D.h"
+#include <WinCodec.h>
 #else
 #include "ImageDecoder.h"
 #endif
@@ -374,4 +378,12 @@ NativeImagePtr ImageFrameCache::frameImageAtIndex(size_t index, SubsamplingLevel
     return frameMetadataAtIndex<NativeImagePtr, (&ImageFrame::nativeImage)>(index, subsamplingLevel, ImageFrame::Caching::MetadataAndImage);
 }
 
+#if USE(DIRECT2D)
+void ImageFrameCache::setRenderTarget(GraphicsContext& context)
+{
+    if (m_decoder)
+        m_decoder->setRenderTarget(context.platformContext());
+}
+#endif
+
 }
index e12c323..7ba9798 100644 (file)
@@ -33,6 +33,7 @@
 
 namespace WebCore {
 
+class GraphicsContext;
 class Image;
 class ImageDecoder;
 
@@ -43,6 +44,8 @@ public:
     ImageFrameCache(NativeImagePtr&&);
 
     void setDecoder(ImageDecoder* decoder) { m_decoder = decoder; }
+    ImageDecoder* decoder() const { return m_decoder; }
+
     unsigned decodedSize() const { return m_decodedSize; }
     void destroyDecodedData(bool destroyAll = true, size_t count = 0);
     bool destroyDecodedDataIfNecessary(bool destroyAll = true, size_t count = 0);
@@ -79,6 +82,10 @@ public:
     ImageOrientation frameOrientationAtIndex(size_t);
     NativeImagePtr frameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
 
+#if USE(DIRECT2D)
+    void setRenderTarget(GraphicsContext&);
+#endif
+
 private:
     template<typename T, T (ImageDecoder::*functor)() const>
     T metadata(const T& defaultValue, Optional<T>* cachedValue = nullptr);
index 47206c6..92baba8 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 849d4e0..31648dc 100644 (file)
@@ -38,6 +38,7 @@
 
 namespace WebCore {
 
+class GraphicsContext;
 class ImageDecoder;
 class ImageOrientation;
 class IntPoint;
@@ -95,6 +96,10 @@ public:
     void setAllowSubsampling(bool allowSubsampling) { m_allowSubsampling = allowSubsampling; }
     NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
 
+#if USE(DIRECT2D)
+    void setRenderTarget(GraphicsContext& context) { m_frameCache.setRenderTarget(context); }
+#endif
+
 private:
     void clearFrameBufferCache(size_t);
     void clear(bool destroyAll, size_t count, SharedBuffer* data);
index bec356d..4a4f1d0 100644 (file)
@@ -39,6 +39,11 @@ typedef struct CGImage* CGImageRef;
 #include "SharedBitmap.h"
 #endif
 
+#if USE(DIRECT2D)
+#include "COMPtr.h"
+#include <d2d1.h>
+#endif
+
 namespace WebCore {
 
 class Color;
@@ -48,6 +53,8 @@ class GraphicsContext;
 
 #if USE(CG)
 typedef RetainPtr<CGImageRef> NativeImagePtr;
+#elif USE(DIRECT2D)
+typedef COMPtr<ID2D1Bitmap> NativeImagePtr;
 #elif USE(CAIRO)
 typedef RefPtr<cairo_surface_t> NativeImagePtr;
 #elif USE(WINGDI)
diff --git a/Source/WebCore/platform/graphics/win/ImageBufferDataDirect2D.cpp b/Source/WebCore/platform/graphics/win/ImageBufferDataDirect2D.cpp
new file mode 100644 (file)
index 0000000..3e6cd82
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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 "ImageBufferData.h"
+
+#if USE(DIRECT2D)
+
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+#include <d2d1.h>
+#include <runtime/JSCInlines.h>
+#include <runtime/TypedArrayInlines.h>
+#include <runtime/Uint8ClampedArray.h>
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+RefPtr<Uint8ClampedArray> ImageBufferData::getData(const IntRect&, const IntSize&, bool /* accelerateRendering */, bool /* unmultiplied */, float /* resolutionScale */) const
+{
+    notImplemented();
+    return nullptr;
+}
+
+void ImageBufferData::putData(Uint8ClampedArray*& /* source */, const IntSize& /* sourceSize */, const IntRect& /* sourceRect */, const IntPoint& /* destPoint */, const IntSize& /* size */, bool /* accelerateRendering */, bool /* unmultiplied */, float /* resolutionScale */)
+{
+    notImplemented();
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/platform/graphics/win/ImageBufferDataDirect2D.h b/Source/WebCore/platform/graphics/win/ImageBufferDataDirect2D.h
new file mode 100644 (file)
index 0000000..bbf3c72
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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 "Image.h"
+#include "IntSize.h"
+#include <runtime/Uint8ClampedArray.h>
+#include <wtf/CheckedArithmetic.h>
+#include <wtf/RefPtr.h>
+#include <wtf/RetainPtr.h>
+
+interface ID2D1RenderTarget;
+
+namespace WebCore {
+
+struct ImageBufferData {
+    IntSize backingStoreSize;
+    Checked<unsigned, RecordOverflow> bytesPerRow;
+
+    // Only for software ImageBuffers.
+    void* data { nullptr };
+    std::unique_ptr<GraphicsContext> context;
+    ID2D1RenderTarget* m_compatibleTarget { nullptr };
+
+    RefPtr<Uint8ClampedArray> getData(const IntRect&, const IntSize&, bool accelerateRendering, bool unmultiplied, float resolutionScale) const;
+    void putData(Uint8ClampedArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize&, bool accelerateRendering, bool unmultiplied, float resolutionScale);
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/win/ImageBufferDirect2D.cpp b/Source/WebCore/platform/graphics/win/ImageBufferDirect2D.cpp
new file mode 100644 (file)
index 0000000..5734868
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * 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 "ImageBuffer.h"
+
+#if USE(DIRECT2D)
+
+#include "BitmapImage.h"
+#include "COMPtr.h"
+#include "GraphicsContext.h"
+#include "ImageData.h"
+#include "IntRect.h"
+#include "MIMETypeRegistry.h"
+#include "NotImplemented.h"
+#include <d2d1.h>
+#include <math.h>
+#include <wtf/Assertions.h>
+#include <wtf/CheckedArithmetic.h>
+#include <wtf/MainThread.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/text/Base64.h>
+#include <wtf/text/WTFString.h>
+
+#if PLATFORM(COCOA)
+#include "WebCoreSystemInterface.h"
+#endif
+
+
+namespace WebCore {
+
+static FloatSize scaleSizeToUserSpace(const FloatSize& logicalSize, const IntSize& backingStoreSize, const IntSize& internalSize)
+{
+    float xMagnification = static_cast<float>(backingStoreSize.width()) / internalSize.width();
+    float yMagnification = static_cast<float>(backingStoreSize.height()) / internalSize.height();
+    return FloatSize(logicalSize.width() * xMagnification, logicalSize.height() * yMagnification);
+}
+
+std::unique_ptr<ImageBuffer> ImageBuffer::createCompatibleBuffer(const FloatSize& size, const GraphicsContext& context)
+{
+    if (size.isEmpty())
+        return nullptr;
+
+    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));
+
+    if (!success)
+        return nullptr;
+
+    // Set up a corresponding scale factor on the graphics context.
+    buffer->context().scale(FloatSize(scaledSize.width() / size.width(), scaledSize.height() / size.height()));
+    return buffer;
+}
+
+ImageBuffer::ImageBuffer(const FloatSize& size, float resolutionScale, ColorSpace /*colorSpace*/, RenderingMode renderingMode, ID2D1RenderTarget* renderTarget, bool& success)
+    : m_logicalSize(size)
+    , m_resolutionScale(resolutionScale)
+{
+    success = false; // Make early return mean failure.
+    float scaledWidth = std::ceil(resolutionScale * size.width());
+    float scaledHeight = std::ceil(resolutionScale * size.height());
+
+    // FIXME: Should we automatically use a lower resolution?
+    if (!FloatSize(scaledWidth, scaledHeight).isExpressibleAsIntSize())
+        return;
+
+    m_size = IntSize(scaledWidth, scaledHeight);
+    m_data.backingStoreSize = m_size;
+
+    bool accelerateRendering = renderingMode == Accelerated;
+    if (m_size.width() <= 0 || m_size.height() <= 0)
+        return;
+
+    // Prevent integer overflows
+    m_data.bytesPerRow = 4 * Checked<unsigned, RecordOverflow>(m_data.backingStoreSize.width());
+    Checked<size_t, RecordOverflow> numBytes = Checked<unsigned, RecordOverflow>(m_data.backingStoreSize.height()) * m_data.bytesPerRow;
+    if (numBytes.hasOverflowed())
+        return;
+
+    if (!renderTarget)
+        renderTarget = GraphicsContext::defaultRenderTarget();
+    RELEASE_ASSERT(renderTarget);
+
+    COMPtr<ID2D1BitmapRenderTarget> bitmapContext;
+    HRESULT hr = renderTarget->CreateCompatibleRenderTarget(FloatSize(m_logicalSize), &bitmapContext);
+    if (!bitmapContext || !SUCCEEDED(hr))
+        return;
+
+    m_data.context = std::make_unique<GraphicsContext>(bitmapContext.get());
+    m_data.m_compatibleTarget = renderTarget;
+
+    success = true;
+}
+
+ImageBuffer::ImageBuffer(const FloatSize& size, float resolutionScale, ColorSpace imageColorSpace, RenderingMode renderingMode, bool& success)
+    : ImageBuffer(size, resolutionScale, imageColorSpace, renderingMode, nullptr, success)
+{
+}
+
+ImageBuffer::~ImageBuffer()
+{
+}
+
+FloatSize ImageBuffer::sizeForDestinationSize(FloatSize destinationSize) const
+{
+    return scaleSizeToUserSpace(destinationSize, m_data.backingStoreSize, internalSize());
+}
+
+GraphicsContext& ImageBuffer::context() const
+{
+    return *m_data.context;
+}
+
+void ImageBuffer::flushContext() const
+{
+    if (!context().didBeginDraw())
+        return;
+
+    HRESULT hr = context().platformContext()->Flush();
+    ASSERT(SUCCEEDED(hr));
+}
+
+RefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBehavior scaleBehavior) const
+{
+    notImplemented();
+    return nullptr;
+}
+
+RefPtr<Image> ImageBuffer::sinkIntoImage(std::unique_ptr<ImageBuffer> imageBuffer, ScaleBehavior scaleBehavior)
+{
+    IntSize internalSize = imageBuffer->internalSize();
+    IntSize logicalSize = imageBuffer->logicalSize();
+    IntSize backingStoreSize = imageBuffer->m_data.backingStoreSize;
+    float resolutionScale = imageBuffer->m_resolutionScale;
+
+    notImplemented();
+    return nullptr;
+}
+
+BackingStoreCopy ImageBuffer::fastCopyImageMode()
+{
+    return DontCopyBackingStore;
+}
+
+void ImageBuffer::drawConsuming(std::unique_ptr<ImageBuffer> imageBuffer, GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode blendMode)
+{
+    imageBuffer->draw(destContext, destRect, srcRect, op, blendMode);
+}
+
+void ImageBuffer::draw(GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode blendMode)
+{
+    auto bitmapTarget = reinterpret_cast<ID2D1BitmapRenderTarget*>(context().platformContext());
+    auto outputTarget = destContext.platformContext();
+
+    COMPtr<ID2D1Bitmap> image;
+    HRESULT hr = bitmapTarget->GetBitmap(&image);
+    if (!SUCCEEDED(hr))
+        return;
+
+    // If the render targets for the source and destination contexts do not match, move the image over.
+    if (destContext.platformContext() != m_data.m_compatibleTarget) {
+        COMPtr<ID2D1Bitmap> sourceImage = image;
+        image = nullptr;
+
+        auto bitmapProperties = D2D1::BitmapProperties();
+        GraphicsContext::systemFactory()->GetDesktopDpi(&bitmapProperties.dpiX, &bitmapProperties.dpiY);
+        hr = outputTarget->CreateSharedBitmap(__uuidof(ID2D1Bitmap), sourceImage.get(), &bitmapProperties, &image);
+        if (!SUCCEEDED(hr))
+            return;
+    }
+
+    FloatRect adjustedSrcRect = srcRect;
+    adjustedSrcRect.scale(m_resolutionScale, m_resolutionScale);
+
+    destContext.drawNativeImage(image, image->GetSize(), destRect, adjustedSrcRect, op, blendMode);
+}
+
+void ImageBuffer::drawPattern(GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
+{
+    FloatRect adjustedSrcRect = srcRect;
+    adjustedSrcRect.scale(m_resolutionScale, m_resolutionScale);
+
+    if (!context().isAcceleratedContext()) {
+        if (&destContext == &context() || destContext.isAcceleratedContext()) {
+            if (RefPtr<Image> copy = copyImage(CopyBackingStore)) // Drawing into our own buffer, need to deep copy.
+                copy->drawPattern(destContext, destRect, adjustedSrcRect, patternTransform, phase, spacing, op, blendMode);
+        } else {
+            if (RefPtr<Image> imageForRendering = copyImage(DontCopyBackingStore))
+                imageForRendering->drawPattern(destContext, destRect, adjustedSrcRect, patternTransform, phase, spacing, op, blendMode);
+        }
+    } else {
+        if (RefPtr<Image> copy = copyImage(CopyBackingStore))
+            copy->drawPattern(destContext, destRect, adjustedSrcRect, patternTransform, phase, spacing, op, blendMode);
+    }
+}
+
+RefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem coordinateSystem) const
+{
+    if (context().isAcceleratedContext())
+        flushContext();
+
+    IntRect srcRect = rect;
+    if (coordinateSystem == LogicalCoordinateSystem)
+        srcRect.scale(m_resolutionScale);
+
+    return m_data.getData(srcRect, internalSize(), context().isAcceleratedContext(), true, 1);
+}
+
+RefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem coordinateSystem) const
+{
+    if (context().isAcceleratedContext())
+        flushContext();
+
+    IntRect srcRect = rect;
+    if (coordinateSystem == LogicalCoordinateSystem)
+        srcRect.scale(m_resolutionScale);
+
+    return m_data.getData(srcRect, internalSize(), context().isAcceleratedContext(), false, 1);
+}
+
+void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem coordinateSystem)
+{
+    if (context().isAcceleratedContext())
+        flushContext();
+
+    IntRect scaledSourceRect = sourceRect;
+    IntSize scaledSourceSize = sourceSize;
+    if (coordinateSystem == LogicalCoordinateSystem) {
+        scaledSourceRect.scale(m_resolutionScale);
+        scaledSourceSize.scale(m_resolutionScale);
+    }
+
+    m_data.putData(source, scaledSourceSize, scaledSourceRect, destPoint, internalSize(), context().isAcceleratedContext(), multiplied == Unmultiplied, 1);
+}
+
+String ImageBuffer::toDataURL(const String& mimeType, const double* quality, CoordinateSystem) const
+{
+    notImplemented();
+    return ASCIILiteral("data:,");
+}
+
+String ImageDataToDataURL(const ImageData& source, const String& mimeType, const double* quality)
+{
+    notImplemented();
+    return ASCIILiteral("data:,");
+}
+
+void ImageBuffer::transformColorSpace(ColorSpace, ColorSpace)
+{
+    notImplemented();
+}
+
+} // namespace WebCore
+
+#endif
index 9ac559c..d11253a 100644 (file)
@@ -26,6 +26,8 @@
 #include "config.h"
 #include "Image.h"
 
+#if USE(CG)
+
 #include "BitmapImage.h"
 #include "BitmapInfo.h"
 #include "GraphicsContextCG.h"
@@ -106,3 +108,5 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext& ctxt, const Float
 }
 
 } // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp b/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp
new file mode 100644 (file)
index 0000000..e6ae277
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * 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 "ImageDecoderDirect2D.h"
+
+#if USE(DIRECT2D)
+
+#include "GraphicsContext.h"
+#include "ImageOrientation.h"
+#include "IntPoint.h"
+#include "IntSize.h"
+#include "Logging.h"
+#include "NotImplemented.h"
+#include "SharedBuffer.h"
+#include <WinCodec.h>
+#include <d2d1.h>
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+ImageDecoder::ImageDecoder()
+{
+}
+
+IWICImagingFactory* ImageDecoder::systemImagingFactory()
+{
+    static IWICImagingFactory* wicImagingFactory = nullptr;
+    if (!wicImagingFactory) {
+        HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&wicImagingFactory);
+        RELEASE_ASSERT(SUCCEEDED(hr));
+    }
+
+    return wicImagingFactory;
+}
+
+size_t ImageDecoder::bytesDecodedToDetermineProperties()
+{
+    // Set to match value used for CoreGraphics.
+    return 13088;
+}
+
+String ImageDecoder::filenameExtension() const
+{
+    notImplemented();
+    return String();
+}
+
+bool ImageDecoder::isSizeAvailable() const
+{
+    return m_nativeDecoder ? true : false;
+}
+
+IntSize ImageDecoder::size() const
+{
+    if (!m_nativeDecoder)
+        return IntSize();
+
+    COMPtr<IWICBitmapFrameDecode> frame;
+    HRESULT hr = m_nativeDecoder->GetFrame(0, &frame);
+    if (!SUCCEEDED(hr))
+        return IntSize();
+
+    UINT width, height;
+    hr = frame->GetSize(&width, &height);
+    if (!SUCCEEDED(hr))
+        return IntSize();
+
+    return IntSize(width, height);
+}
+
+size_t ImageDecoder::frameCount() const
+{
+    if (!m_nativeDecoder)
+        return 0;
+
+    UINT count;
+    HRESULT hr = m_nativeDecoder->GetFrameCount(&count);
+    if (!SUCCEEDED(hr))
+        return 0;
+
+    return count;
+}
+
+RepetitionCount ImageDecoder::repetitionCount() const
+{
+    return RepetitionCountNone;
+}
+
+Optional<IntPoint> ImageDecoder::hotSpot() const
+{
+    return IntPoint();
+}
+
+IntSize ImageDecoder::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
+{
+    if (!m_nativeDecoder)
+        return IntSize();
+
+    COMPtr<IWICBitmapFrameDecode> frame;
+    HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
+    if (!SUCCEEDED(hr))
+        return IntSize();
+
+    UINT width, height;
+    hr = frame->GetSize(&width, &height);
+    if (!SUCCEEDED(hr))
+        return IntSize();
+
+    return IntSize(width, height);
+}
+
+bool ImageDecoder::frameIsCompleteAtIndex(size_t index) const
+{
+    if (!m_nativeDecoder)
+        return false;
+
+    COMPtr<IWICBitmapFrameDecode> frame;
+    HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
+    if (!SUCCEEDED(hr))
+        return false;
+
+    return true;
+}
+
+ImageOrientation ImageDecoder::frameOrientationAtIndex(size_t index) const
+{
+    notImplemented();
+    return ImageOrientation();
+}
+
+float ImageDecoder::frameDurationAtIndex(size_t index) const
+{
+    notImplemented();
+    return 0;
+}
+
+bool ImageDecoder::frameAllowSubsamplingAtIndex(size_t) const
+{
+    notImplemented();
+    return true;
+}
+
+bool ImageDecoder::frameHasAlphaAtIndex(size_t index) const
+{
+    notImplemented();
+    return true;
+}
+
+unsigned ImageDecoder::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
+{
+    if (!m_nativeDecoder)
+        return 0;
+
+    COMPtr<IWICBitmapFrameDecode> frame;
+    HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
+    if (!SUCCEEDED(hr))
+        return 0;
+
+    UINT width, height;
+    hr = frame->GetSize(&width, &height);
+    if (!SUCCEEDED(hr))
+        return 0;
+
+    return width * height * 4;
+}
+
+void ImageDecoder::setRenderTarget(ID2D1RenderTarget* renderTarget)
+{
+    m_renderTarget = renderTarget;
+}
+
+NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
+{
+    if (!m_nativeDecoder)
+        return nullptr;
+
+    COMPtr<IWICBitmapFrameDecode> frame;
+    HRESULT hr = m_nativeDecoder->GetFrame(0, &frame);
+    if (!SUCCEEDED(hr))
+        return nullptr;
+
+    COMPtr<IWICFormatConverter> converter;
+    hr = systemImagingFactory()->CreateFormatConverter(&converter);
+    if (!SUCCEEDED(hr))
+        return nullptr;
+
+    hr = converter->Initialize(frame.get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.f, WICBitmapPaletteTypeCustom);
+    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))
+        return nullptr;
+
+    return bitmap;
+}
+
+void ImageDecoder::setData(SharedBuffer& data, bool allDataReceived)
+{
+    if (allDataReceived)
+        return;
+
+    COMPtr<IWICStream> stream;
+    HRESULT hr = systemImagingFactory()->CreateStream(&stream);
+    if (!SUCCEEDED(hr))
+        return;
+
+    char* dataPtr = const_cast<char*>(data.data());
+    hr = stream->InitializeFromMemory(reinterpret_cast<BYTE*>(dataPtr), data.size());
+    if (!SUCCEEDED(hr))
+        return;
+
+    m_nativeDecoder = nullptr;
+
+    hr = systemImagingFactory()->CreateDecoderFromStream(stream.get(), nullptr, WICDecodeMetadataCacheOnDemand, &m_nativeDecoder);
+    ASSERT(SUCCEEDED(hr));
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.h b/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.h
new file mode 100644 (file)
index 0000000..61ca4da
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "COMPtr.h"
+#include "ImageSource.h"
+#include "IntSize.h"
+#include <wtf/Optional.h>
+
+interface ID2D1RenderTarget;
+interface IWICBitmapDecoder;
+interface IWICImagingFactory;
+
+namespace WebCore {
+
+class ImageDecoder {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ImageDecoder();
+    
+    static std::unique_ptr<ImageDecoder> create(const SharedBuffer&, AlphaOption, GammaAndColorProfileOption)
+    {
+        return std::make_unique<ImageDecoder>();
+    }
+    
+    static size_t bytesDecodedToDetermineProperties();
+    
+    String filenameExtension() const;
+    bool isSizeAvailable() const;
+    
+    // Always original size, without subsampling.
+    IntSize size() const;
+    size_t frameCount() const;
+
+    RepetitionCount repetitionCount() const;
+    Optional<IntPoint> hotSpot() const;
+    
+    IntSize frameSizeAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
+    bool frameIsCompleteAtIndex(size_t) const;
+    ImageOrientation frameOrientationAtIndex(size_t) const;
+    
+    float frameDurationAtIndex(size_t) const;
+    bool frameHasAlphaAtIndex(size_t) const;
+    bool frameAllowSubsamplingAtIndex(size_t) const;
+    unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
+    
+    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
+    
+    void setData(SharedBuffer&, bool allDataReceived);
+    bool isAllDataReceived() const { return m_isAllDataReceived; }
+    void clearFrameBufferCache(size_t) { }
+
+    void setRenderTarget(ID2D1RenderTarget*);
+
+    static IWICImagingFactory* systemImagingFactory();
+
+protected:
+    bool m_isAllDataReceived { false };
+    mutable IntSize m_size;
+    COMPtr<IWICBitmapDecoder> m_nativeDecoder;
+    COMPtr<ID2D1RenderTarget> m_renderTarget;
+};
+
+}
diff --git a/Source/WebCore/platform/graphics/win/ImageDirect2D.cpp b/Source/WebCore/platform/graphics/win/ImageDirect2D.cpp
new file mode 100644 (file)
index 0000000..c81757f
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2006-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 "Image.h"
+
+#include "BitmapImage.h"
+#include "BitmapInfo.h"
+#include "GraphicsContext.h"
+#include "ImageObserver.h"
+#include "NotImplemented.h"
+#include <d2d1.h>
+#include <windows.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+RefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap)
+{
+    DIBSECTION dibSection;
+    if (!GetObject(hBitmap, sizeof(DIBSECTION), &dibSection))
+        return nullptr;
+
+    ASSERT(dibSection.dsBm.bmBitsPixel == 32);
+    if (dibSection.dsBm.bmBitsPixel != 32)
+        return nullptr;
+
+    ASSERT(dibSection.dsBm.bmBits);
+    if (!dibSection.dsBm.bmBits)
+        return nullptr;
+
+    notImplemented();
+
+    return nullptr;
+}
+
+bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, const IntSize* size)
+{
+    ASSERT(bmp);
+
+    BITMAP bmpInfo;
+    GetObject(bmp, sizeof(BITMAP), &bmpInfo);
+
+    ASSERT(bmpInfo.bmBitsPixel == 32);
+    int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
+    
+    notImplemented();
+
+    return true;
+}
+
+void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext& ctxt, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator compositeOp)
+{
+    size_t frames = frameCount();
+    for (size_t i = 0; i < frames; ++i) {
+        auto image = frameImageAtIndex(i).get();
+        auto imageSize = image->GetSize();
+        if (image && clampTo<size_t>(imageSize.height) == static_cast<size_t>(srcSize.height()) && clampTo<size_t>(imageSize.width) == static_cast<size_t>(srcSize.width())) {
+            size_t currentFrame = m_currentFrame;
+            m_currentFrame = i;
+            draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), compositeOp, BlendModeNormal, ImageOrientationDescription());
+            m_currentFrame = currentFrame;
+            return;
+        }
+    }
+
+    // No image of the correct size was found, fallback to drawing the current frame
+    FloatSize imageSize = BitmapImage::size();
+    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)
+{
+    if (!nativeImageForCurrentFrame())
+        return;
+
+    ctxt.drawPattern(*this, destRect, tileRect, patternTransform, phase, spacing, op, blendMode);
+
+    if (imageObserver())
+        imageObserver()->didDraw(this);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/win/NativeImageDirect2D.cpp b/Source/WebCore/platform/graphics/win/NativeImageDirect2D.cpp
new file mode 100644 (file)
index 0000000..fd61380
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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"
+
+#include "Color.h"
+#include "FloatRect.h"
+#include "GeometryUtilities.h"
+#include "GraphicsContext.h"
+#include "IntSize.h"
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+IntSize nativeImageSize(const NativeImagePtr& image)
+{
+    return image ? IntSize(image->GetSize()) : IntSize();
+}
+
+bool nativeImageHasAlpha(const NativeImagePtr& image)
+{
+    if (!image)
+        return false;
+
+    auto alphaMode = image->GetPixelFormat().alphaMode;
+    return (alphaMode >= D2D1_ALPHA_MODE_PREMULTIPLIED) && (alphaMode <= D2D1_ALPHA_MODE_STRAIGHT);
+}
+
+Color nativeImageSinglePixelSolidColor(const NativeImagePtr& image)
+{
+    if (!image || nativeImageSize(image) != IntSize(1, 1))
+        return Color();
+
+    notImplemented();
+
+    return Color();
+}
+
+float subsamplingScale(GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect)
+{
+    D2D1_MATRIX_3X2_F ctm;
+    context.platformContext()->GetTransform(&ctm);
+
+    AffineTransform transform(ctm);
+
+    auto transformedDestinationRect = transform.mapRect(destRect);
+    return std::min<float>(1, std::max(transformedDestinationRect.width() / srcRect.width(), transformedDestinationRect.height() / srcRect.height()));
+}
+
+void drawNativeImage(const NativeImagePtr& image, GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect, const IntSize& srcSize, CompositeOperator compositeOp, BlendMode blendMode, const ImageOrientation& orientation)
+{
+    auto platformContext = context.platformContext();
+
+    // Subsampling may have given us an image that is smaller than size().
+    IntSize subsampledImageSize = nativeImageSize(image);
+
+    // srcRect is in the coordinates of the unsubsampled image, so we have to map it to the subsampled image.
+    FloatRect adjustedSrcRect = srcRect;
+    if (subsampledImageSize != srcSize)
+        adjustedSrcRect = mapRect(srcRect, FloatRect({ }, srcSize), FloatRect({ }, subsampledImageSize));
+
+    float opacity = 1.0f;
+
+    if (!context.didBeginDraw())
+        platformContext->BeginDraw();
+
+    platformContext->DrawBitmap(image.get(), destRect, opacity, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, adjustedSrcRect);
+
+    HRESULT hr = S_OK;
+    if (!context.didBeginDraw())
+        hr = platformContext->EndDraw();
+    else
+        hr = platformContext->Flush();
+
+    ASSERT(SUCCEEDED(hr));
+}
+
+void clearNativeImageSubimages(const NativeImagePtr& image)
+{
+    notImplemented();
+
+#if CACHE_SUBIMAGES
+    if (image)
+        subimageCache().clearImage(image.get());
+#endif
+}
+
+
+}