/*
 * Copyright (C) 2006-2019 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.
 * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
 * Copyright (C) 2010, 2011 Igalia S.L.
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 * Copyright (C) 2012, Intel Corporation
 *
 * 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 "Direct2DOperations.h"

#if USE(DIRECT2D)

#include "Direct2DUtilities.h"
#include "FloatConversion.h"
#include "FloatRect.h"
#include "GraphicsContextPlatformPrivateDirect2D.h"
#include "Image.h"
#include "ImageBuffer.h"
#include "ImageDecoderDirect2D.h"
#include "NotImplemented.h"
#include "Path.h"
#include "PlatformContextDirect2D.h"
#include "ShadowBlur.h"
#include <algorithm>
#include <d2d1.h>

namespace WebCore {
namespace Direct2D {

enum PatternAdjustment { NoAdjustment, AdjustPatternForGlobalAlpha };
enum AlphaPreservation { DoNotPreserveAlpha, PreserveAlpha };

// FIXME: Replace once GraphicsContext::dashedLineCornerWidthForStrokeWidth()
// is refactored as a static public function.
static float dashedLineCornerWidthForStrokeWidth(float strokeWidth, StrokeStyle strokeStyle, float strokeThickness)
{
    return strokeStyle == DottedStroke ? strokeThickness : std::min(2.0f * strokeThickness, std::max(strokeThickness, strokeWidth / 3.0f));
}

// FIXME: Replace once GraphicsContext::dashedLinePatternWidthForStrokeWidth()
// is refactored as a static public function.
static float dashedLinePatternWidthForStrokeWidth(float strokeWidth, StrokeStyle strokeStyle, float strokeThickness)
{
    return strokeStyle == DottedStroke ? strokeThickness : std::min(3.0f * strokeThickness, std::max(strokeThickness, strokeWidth / 3.0f));
}

// FIXME: Replace once GraphicsContext::dashedLinePatternOffsetForPatternAndStrokeWidth()
// is refactored as a static public function.
static float dashedLinePatternOffsetForPatternAndStrokeWidth(float patternWidth, float strokeWidth)
{
    // Pattern starts with full fill and ends with the empty fill.
    // 1. Let's start with the empty phase after the corner.
    // 2. Check if we've got odd or even number of patterns and whether they fully cover the line.
    // 3. In case of even number of patterns and/or remainder, move the pattern start position
    // so that the pattern is balanced between the corners.
    float patternOffset = patternWidth;
    int numberOfSegments = std::floor(strokeWidth / patternWidth);
    bool oddNumberOfSegments = numberOfSegments % 2;
    float remainder = strokeWidth - (numberOfSegments * patternWidth);
    if (oddNumberOfSegments && remainder)
        patternOffset -= remainder / 2.0f;
    else if (!oddNumberOfSegments) {
        if (remainder)
            patternOffset += patternOffset - (patternWidth + remainder) / 2.0f;
        else
            patternOffset += patternWidth / 2.0f;
    }

    return patternOffset;
}

// FIXME: Replace once GraphicsContext::centerLineAndCutOffCorners()
// is refactored as a static public function.
static Vector<FloatPoint> centerLineAndCutOffCorners(bool isVerticalLine, float cornerWidth, FloatPoint point1, FloatPoint point2)
{
    // Center line and cut off corners for pattern painting.
    if (isVerticalLine) {
        float centerOffset = (point2.x() - point1.x()) / 2.0f;
        point1.move(centerOffset, cornerWidth);
        point2.move(-centerOffset, -cornerWidth);
    } else {
        float centerOffset = (point2.y() - point1.y()) / 2.0f;
        point1.move(cornerWidth, centerOffset);
        point2.move(-cornerWidth, -centerOffset);
    }

    return { point1, point2 };
}


namespace State {

void setStrokeThickness(PlatformContextDirect2D& platformContext, float strokeThickness)
{
    platformContext.setStrokeThickness(strokeThickness);
}

void setStrokeStyle(PlatformContextDirect2D& platformContext, StrokeStyle strokeStyle)
{
    platformContext.setStrokeStyle(strokeStyle);
}

void setCompositeOperation(PlatformContextDirect2D& platformContext, CompositeOperator compositeOperation, BlendMode blendMode)
{

    D2D1_BLEND_MODE targetBlendMode = D2D1_BLEND_MODE_MULTIPLY;
    D2D1_COMPOSITE_MODE targetCompositeMode = D2D1_COMPOSITE_MODE_FORCE_DWORD;

    if (blendMode != BlendMode::Normal) {
        switch (blendMode) {
        case BlendMode::Multiply:
            targetBlendMode = D2D1_BLEND_MODE_MULTIPLY;
            break;
        case BlendMode::Screen:
            targetBlendMode = D2D1_BLEND_MODE_SCREEN;
            break;
        case BlendMode::Overlay:
            targetBlendMode = D2D1_BLEND_MODE_OVERLAY;
            break;
        case BlendMode::Darken:
            targetBlendMode = D2D1_BLEND_MODE_DARKEN;
            break;
        case BlendMode::Lighten:
            targetBlendMode = D2D1_BLEND_MODE_LIGHTEN;
            break;
        case BlendMode::ColorDodge:
            targetBlendMode = D2D1_BLEND_MODE_COLOR_DODGE;
            break;
        case BlendMode::ColorBurn:
            targetBlendMode = D2D1_BLEND_MODE_COLOR_BURN;
            break;
        case BlendMode::HardLight:
            targetBlendMode = D2D1_BLEND_MODE_HARD_LIGHT;
            break;
        case BlendMode::SoftLight:
            targetBlendMode = D2D1_BLEND_MODE_SOFT_LIGHT;
            break;
        case BlendMode::Difference:
            targetBlendMode = D2D1_BLEND_MODE_DIFFERENCE;
            break;
        case BlendMode::Exclusion:
            targetBlendMode = D2D1_BLEND_MODE_EXCLUSION;
            break;
        case BlendMode::Hue:
            targetBlendMode = D2D1_BLEND_MODE_HUE;
            break;
        case BlendMode::Saturation:
            targetBlendMode = D2D1_BLEND_MODE_SATURATION;
            break;
        case BlendMode::Color:
            targetBlendMode = D2D1_BLEND_MODE_COLOR;
            break;
        case BlendMode::Luminosity:
            targetBlendMode = D2D1_BLEND_MODE_LUMINOSITY;
            break;
        case BlendMode::PlusDarker:
            targetBlendMode = D2D1_BLEND_MODE_DARKER_COLOR;
            break;
        case BlendMode::PlusLighter:
            targetBlendMode = D2D1_BLEND_MODE_LIGHTER_COLOR;
            break;
        default:
            break;
        }
    } else {
        switch (compositeOperation) {
        case CompositeOperator::Clear:
            // FIXME: targetBlendMode = D2D1_BLEND_MODE_CLEAR;
            break;
        case CompositeOperator::Copy:
            targetCompositeMode = D2D1_COMPOSITE_MODE_SOURCE_COPY;
            break;
        case CompositeOperator::SourceOver:
            targetCompositeMode = D2D1_COMPOSITE_MODE_SOURCE_OVER;
            break;
        case CompositeOperator::SourceIn:
            targetCompositeMode = D2D1_COMPOSITE_MODE_SOURCE_IN;
            break;
        case CompositeOperator::SourceOut:
            targetCompositeMode = D2D1_COMPOSITE_MODE_SOURCE_OUT;
            break;
        case CompositeOperator::SourceAtop:
            targetCompositeMode = D2D1_COMPOSITE_MODE_SOURCE_ATOP;
            break;
        case CompositeOperator::DestinationOver:
            targetCompositeMode = D2D1_COMPOSITE_MODE_DESTINATION_OVER;
            break;
        case CompositeOperator::DestinationIn:
            targetCompositeMode = D2D1_COMPOSITE_MODE_DESTINATION_IN;
            break;
        case CompositeOperator::DestinationOut:
            targetCompositeMode = D2D1_COMPOSITE_MODE_DESTINATION_OUT;
            break;
        case CompositeOperator::DestinationAtop:
            targetCompositeMode = D2D1_COMPOSITE_MODE_DESTINATION_ATOP;
            break;
        case CompositeOperator::XOR:
            targetCompositeMode = D2D1_COMPOSITE_MODE_XOR;
            break;
        case CompositeOperator::PlusDarker:
            targetBlendMode = D2D1_BLEND_MODE_DARKEN;
            break;
        case CompositeOperator::PlusLighter:
            targetBlendMode = D2D1_BLEND_MODE_LIGHTEN;
            break;
        case CompositeOperator::Difference:
            targetBlendMode = D2D1_BLEND_MODE_DIFFERENCE;
            break;
        }
    }

    platformContext.setBlendAndCompositeMode(targetBlendMode, targetCompositeMode);
}

void setShouldAntialias(PlatformContextDirect2D& platformContext, bool enable)
{
    auto antialiasMode = enable ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED;
    platformContext.renderTarget()->SetAntialiasMode(antialiasMode);
}

void setCTM(PlatformContextDirect2D& platformContext, const AffineTransform& transform)
{
    ASSERT(platformContext.renderTarget());
    platformContext.renderTarget()->SetTransform(transform);

    if (auto* graphicsContextPrivate = platformContext.graphicsContextPrivate())
        graphicsContextPrivate->setCTM(transform);
}

AffineTransform getCTM(PlatformContextDirect2D& platformContext)
{
    ASSERT(platformContext.renderTarget());
    D2D1_MATRIX_3X2_F currentTransform;
    platformContext.renderTarget()->GetTransform(&currentTransform);
    return currentTransform;
}

IntRect getClipBounds(PlatformContextDirect2D& platformContext)
{
    D2D1_SIZE_F clipSize;
    if (auto clipLayer = platformContext.clipLayer())
        clipSize = clipLayer->GetSize();
    else
        clipSize = platformContext.renderTarget()->GetSize();

    FloatRect clipBounds(IntPoint(), clipSize);

    return enclosingIntRect(clipBounds);
}

FloatRect roundToDevicePixels(PlatformContextDirect2D& platformContext, const FloatRect& rect)
{
    notImplemented();

    return rect;
}

bool isAcceleratedContext(PlatformContextDirect2D& platformContext)
{
    auto renderProperties = D2D1::RenderTargetProperties();
    renderProperties.type = D2D1_RENDER_TARGET_TYPE_HARDWARE;
    return platformContext.renderTarget()->IsSupported(&renderProperties);
}

} // namespace State

FillSource::FillSource(const GraphicsContextState& state, const GraphicsContext& context)
    : globalAlpha(state.alpha)
    , color(state.fillColor)
    , fillRule(state.fillRule)
{
    ASSERT(context.hasPlatformContext());
    auto& platformContext = *context.platformContext();

    if (state.fillPattern) {
        AffineTransform userToBaseCTM; // FIXME: This isn't really needed on Windows
        brush = state.fillPattern->createPlatformPattern(context, state.alpha, userToBaseCTM);
    } else if (state.fillGradient && !state.fillGradient->stops().isEmpty())
        brush = state.fillGradient->createPlatformGradientIfNecessary(platformContext.renderTarget());
    else
        brush = platformContext.brushWithColor(color);
}

StrokeSource::StrokeSource(const GraphicsContextState& state, const GraphicsContext& context)
    : globalAlpha(state.alpha)
    , thickness(state.strokeThickness)
    , color(state.strokeColor)
{
    ASSERT(context.hasPlatformContext());
    auto& platformContext = *context.platformContext();

    if (state.strokePattern) {
        AffineTransform userToBaseCTM; // FIXME: This isn't really needed on Windows
        brush = state.strokePattern->createPlatformPattern(context, state.alpha, userToBaseCTM);
    } else if (state.strokeGradient)
        brush = state.strokeGradient->createPlatformGradientIfNecessary(platformContext.renderTarget());
    else
        brush = platformContext.brushWithColor(color);
}

ShadowState::ShadowState(const GraphicsContextState& state)
    : offset(state.shadowOffset)
    , blur(state.shadowBlur)
    , color(state.shadowColor)
    , ignoreTransforms(state.shadowsIgnoreTransforms)
    , globalAlpha(state.alpha)
    , globalCompositeOperator(state.compositeOperator)
{
}

bool ShadowState::isVisible() const
{
    return color.isVisible() && (offset.width() || offset.height() || blur);
}

bool ShadowState::isRequired(PlatformContextDirect2D& platformContext) const
{
    // We can't avoid ShadowBlur if the shadow has blur.
    if (color.isVisible() && blur)
        return true;

    // We can avoid ShadowBlur and optimize, since we're not drawing on a
    // canvas and box shadows are affected by the transformation matrix.
    if (!ignoreTransforms)
        return false;

    // We can avoid ShadowBlur, since there are no transformations to apply to the canvas.
    if (State::getCTM(platformContext).isIdentity())
        return false;

    // Otherwise, no chance avoiding ShadowBlur.
    return true;
}

void setLineCap(PlatformContextDirect2D& platformContext, LineCap lineCap)
{
    D2D1_CAP_STYLE capStyle = D2D1_CAP_STYLE_FLAT;
    switch (lineCap) {
    case RoundCap:
        capStyle = D2D1_CAP_STYLE_ROUND;
        break;
    case SquareCap:
        capStyle = D2D1_CAP_STYLE_SQUARE;
        break;
    case ButtCap:
    default:
        capStyle = D2D1_CAP_STYLE_FLAT;
        break;
    }

    platformContext.setLineCap(capStyle);
}

void setLineDash(PlatformContextDirect2D& platformContext, const DashArray& dashes, float dashOffset)
{
    platformContext.setDashes(dashes);
    platformContext.setDashOffset(dashOffset);
}

void setLineJoin(PlatformContextDirect2D& platformContext, LineJoin lineJoin)
{
    D2D1_LINE_JOIN joinStyle = D2D1_LINE_JOIN_MITER;
    switch (lineJoin) {
    case RoundJoin:
        joinStyle = D2D1_LINE_JOIN_ROUND;
        break;
    case BevelJoin:
        joinStyle = D2D1_LINE_JOIN_BEVEL;
        break;
    case MiterJoin:
    default:
        joinStyle = D2D1_LINE_JOIN_MITER;
        break;
    }

    platformContext.setLineJoin(joinStyle);
}

void setMiterLimit(PlatformContextDirect2D& platformContext, float miterLimit)
{
    platformContext.setMiterLimit(miterLimit);
}

void fillRect(PlatformContextDirect2D& platformContext, const FloatRect& rect, const FillSource& fillSource, const ShadowState& shadowState)
{
    auto context = platformContext.renderTarget();

    platformContext.setTags(1, __LINE__);
    drawWithShadow(platformContext, rect, shadowState, [&platformContext, rect, &fillSource](ID2D1RenderTarget* renderTarget) {
        const D2D1_RECT_F d2dRect = rect;
        renderTarget->FillRectangle(&d2dRect, fillSource.brush.get());
    });
}

void fillRect(PlatformContextDirect2D& platformContext, const FloatRect& rect, const Color& color, const ShadowState& shadowState)
{
    auto context = platformContext.renderTarget();

    platformContext.setTags(1, __LINE__);
    drawWithShadow(platformContext, rect, shadowState, [&platformContext, color, rect](ID2D1RenderTarget* renderTarget) {
        const D2D1_RECT_F d2dRect = rect;
        renderTarget->FillRectangle(&d2dRect, platformContext.brushWithColor(color).get());
    });
}

void fillRoundedRect(PlatformContextDirect2D& platformContext, const FloatRoundedRect& rect, const Color& color, const ShadowState& shadowState)
{
    auto context = platformContext.renderTarget();

    platformContext.setTags(1, __LINE__);

    const FloatRect& r = rect.rect();
    const FloatRoundedRect::Radii& radii = rect.radii();
    bool equalWidths = (radii.topLeft().width() == radii.topRight().width() && radii.topRight().width() == radii.bottomLeft().width() && radii.bottomLeft().width() == radii.bottomRight().width());
    bool equalHeights = (radii.topLeft().height() == radii.bottomLeft().height() && radii.bottomLeft().height() == radii.topRight().height() && radii.topRight().height() == radii.bottomRight().height());
    bool hasCustomFill = false; // FIXME: Why isn't a FillSource passed to this function?
    if (!hasCustomFill && equalWidths && equalHeights && radii.topLeft().width() * 2 == r.width() && radii.topLeft().height() * 2 == r.height()) {
        drawWithShadow(platformContext, r, shadowState, [&platformContext, color, rect, radii, r](ID2D1RenderTarget* renderTarget) {
            auto roundedRect = D2D1::RoundedRect(r, radii.topLeft().width(), radii.topLeft().height());
            renderTarget->FillRoundedRectangle(&roundedRect, platformContext.brushWithColor(color).get());
        });
    } else {
        Path path;
        path.addRoundedRect(rect);
        fillPath(platformContext, path, color, shadowState);
    }
}

void fillRectWithRoundedHole(PlatformContextDirect2D& platformContext, const FloatRect& rect, const FloatRoundedRect& roundedHoleRect, const FillSource& fillSource, const ShadowState& shadowState)
{
    auto context = platformContext.renderTarget();

    platformContext.setTags(1, __LINE__);

    Path path;
    path.addRect(rect);

    if (!roundedHoleRect.radii().isZero())
        path.addRoundedRect(roundedHoleRect);
    else
        path.addRect(roundedHoleRect.rect());

    FillSource fillWithHoleSource = fillSource;
    fillWithHoleSource.fillRule = WindRule::EvenOdd;

    fillPath(platformContext, path, fillWithHoleSource, shadowState);
}

void fillRectWithGradient(PlatformContextDirect2D& platformContext, const FloatRect& rect, ID2D1Brush* gradient)
{
    platformContext.setTags(1, __LINE__);
    drawWithoutShadow(platformContext, [&platformContext, rect, &gradient](ID2D1RenderTarget* renderTarget) {
        const D2D1_RECT_F d2dRect = rect;
        renderTarget->FillRectangle(&d2dRect, gradient);
    });
}

void fillPath(PlatformContextDirect2D& platformContext, const Path& path, const FillSource& fillSource, const ShadowState& shadowState)
{
    path.closeAnyOpenGeometries(D2D1_FIGURE_END_OPEN);

    auto context = platformContext.renderTarget();

    platformContext.setTags(1, __LINE__);

    COMPtr<ID2D1GeometryGroup> pathToFill;
    path.createGeometryWithFillMode(fillSource.fillRule, pathToFill);

    platformContext.setTags(1, __LINE__);
    Function<void(ID2D1RenderTarget*)> drawFunction = [&platformContext, &pathToFill, &fillSource](ID2D1RenderTarget* renderTarget) {
        renderTarget->FillGeometry(pathToFill.get(), fillSource.brush.get());
    };

    if (shadowState.isVisible()) {
        FloatRect boundingRect = path.fastBoundingRect();
        drawWithShadow(platformContext, boundingRect, shadowState, WTFMove(drawFunction));
    } else
        drawWithoutShadow(platformContext, WTFMove(drawFunction));
}

void fillPath(PlatformContextDirect2D& platformContext, const Path& path, const Color& color, const ShadowState& shadowState)
{
    auto context = platformContext.renderTarget();

    platformContext.setTags(1, __LINE__);

    COMPtr<ID2D1GeometryGroup> pathToFill;
    path.createGeometryWithFillMode(WindRule::EvenOdd, pathToFill);

    platformContext.setTags(1, __LINE__);

    Function<void(ID2D1RenderTarget*)> drawFunction = [&platformContext, &pathToFill, color](ID2D1RenderTarget* renderTarget) {
        renderTarget->FillGeometry(pathToFill.get(), platformContext.brushWithColor(color).get());
    };

    if (shadowState.isVisible()) {
        FloatRect boundingRect = path.fastBoundingRect();
        drawWithShadow(platformContext, boundingRect, shadowState, WTFMove(drawFunction));
    } else
        drawWithoutShadow(platformContext, WTFMove(drawFunction));
}

void strokeRect(PlatformContextDirect2D& platformContext, const FloatRect& rect, float lineWidth, const StrokeSource& strokeSource, const ShadowState& shadowState)
{
    drawWithShadow(platformContext, rect, shadowState, [&platformContext, &strokeSource, rect, lineWidth](ID2D1RenderTarget* renderTarget) {
        platformContext.setTags(1, __LINE__);
        const D2D1_RECT_F d2dRect = rect;
        renderTarget->DrawRectangle(&d2dRect, strokeSource.brush.get(), lineWidth, platformContext.strokeStyle());
    });
}

void strokePath(PlatformContextDirect2D& platformContext, const Path& path, const StrokeSource& strokeSource, const ShadowState& shadowState)
{
    auto context = platformContext.renderTarget();
    
    platformContext.setTags(1, __LINE__);

    Function<void(ID2D1RenderTarget*)> drawFunction = [&platformContext, &path, &strokeSource](ID2D1RenderTarget* renderTarget) {
        renderTarget->DrawGeometry(path.platformPath(), strokeSource.brush.get(), strokeSource.thickness, platformContext.strokeStyle());
    };

    if (shadowState.isVisible()) {
        auto boundingRect = path.fastBoundingRectForStroke(platformContext);
        drawWithShadow(platformContext, boundingRect, shadowState, WTFMove(drawFunction));
    } else
        drawWithoutShadow(platformContext, WTFMove(drawFunction));
}

void drawPath(PlatformContextDirect2D& platformContext, const Path& path, const StrokeSource& strokeSource, const ShadowState&)
{
    auto context = platformContext.renderTarget();

    path.closeAnyOpenGeometries(D2D1_FIGURE_END_OPEN);

    platformContext.setTags(1, __LINE__);

    drawWithoutShadow(platformContext, [&platformContext, &strokeSource, &path](ID2D1RenderTarget* renderTarget) {
        renderTarget->DrawGeometry(path.platformPath(), strokeSource.brush.get(), strokeSource.thickness, platformContext.strokeStyle());
    });

    flush(platformContext);
}

static void drawWithShadowHelper(ID2D1RenderTarget* context, ID2D1BitmapRenderTarget* bitmapTarget, const FloatRect& boundingRect, const Color& shadowColor, const FloatSize& shadowOffset, float shadowBlur)
{
    COMPtr<ID2D1Bitmap> currentCanvas = Direct2D::createBitmapCopyFromContext(bitmapTarget);
    if (!currentCanvas)
        return;

    COMPtr<ID2D1DeviceContext> shadowDeviceContext;
    HRESULT hr = bitmapTarget->QueryInterface(&shadowDeviceContext);
    RELEASE_ASSERT(SUCCEEDED(hr));

    // Create the shadow effect
    COMPtr<ID2D1Effect> shadowEffect;
    hr = shadowDeviceContext->CreateEffect(CLSID_D2D1Shadow, &shadowEffect);
    RELEASE_ASSERT(SUCCEEDED(hr));

    shadowEffect->SetInput(0, currentCanvas.get());
    shadowEffect->SetValue(D2D1_SHADOW_PROP_COLOR, static_cast<D2D1_VECTOR_4F>(shadowColor));

    float blurDeviation = 0.5 * shadowBlur;
    shadowEffect->SetValue(D2D1_SHADOW_PROP_BLUR_STANDARD_DEVIATION, blurDeviation);

    COMPtr<ID2D1Effect> shadowTransformEffect;
    hr = shadowDeviceContext->CreateEffect(CLSID_D2D12DAffineTransform, &shadowTransformEffect);
    RELEASE_ASSERT(SUCCEEDED(hr));

    shadowTransformEffect->SetInputEffect(0, shadowEffect.get());

    // Must flip the axis for the shadow offset, since Direct2D's Y axis is inverted.
    auto shadowTranslation = D2D1::Matrix3x2F::Translation(shadowOffset.width(), -shadowOffset.height());
    shadowTransformEffect->SetValue(D2D1_2DAFFINETRANSFORM_PROP_TRANSFORM_MATRIX, shadowTranslation);

    COMPtr<ID2D1Effect> compositor;
    hr = shadowDeviceContext->CreateEffect(CLSID_D2D1Composite, &compositor);
    RELEASE_ASSERT(SUCCEEDED(hr));

    compositor->SetInputEffect(0, shadowTransformEffect.get());
    compositor->SetInput(1, currentCanvas.get());

    shadowDeviceContext->BeginDraw();
    shadowDeviceContext->Clear(D2D1::ColorF(0, 0, 0, 0));
    shadowDeviceContext->DrawImage(compositor.get());
    hr = shadowDeviceContext->EndDraw();
    RELEASE_ASSERT(SUCCEEDED(hr));

    COMPtr<ID2D1Bitmap> bitmap;
    hr = bitmapTarget->GetBitmap(&bitmap);
    RELEASE_ASSERT(SUCCEEDED(hr));

    IntSize pixelSize = context->GetPixelSize();
    COMPtr<ID2D1Bitmap> cropped = Direct2D::createBitmap(bitmapTarget, pixelSize);
    if (!cropped)
        return;

    auto scaleFactor = bitmapResolution(context);

    FloatRect scaledBoundingRect(boundingRect);
    scaledBoundingRect.scale(scaleFactor.width(), scaleFactor.height());

    // Take the magnitude of the offset. If the origin was outside the drawing context, we stretched to include those points,
    // and so we need to crop them out. If the origin was inside, we want to honor the offset.
    int x = clampTo<int>(std::abs(scaledBoundingRect.x()));
    int y = clampTo<int>(std::abs(scaledBoundingRect.y()));
    int width = clampTo<int>(scaledBoundingRect.width());
    int height = clampTo<int>(scaledBoundingRect.height());

    IntRect outputRect(IntPoint(x, y), IntSize(width, height));
    IntRect destContextRect(IntPoint(), pixelSize);
    if (outputRect.intersects(destContextRect))
        outputRect.intersect(destContextRect);

    D2D1_RECT_U cropRect = outputRect;
    auto targetPoint = D2D1::Point2U();
    cropped->CopyFromBitmap(&targetPoint, bitmap.get(), &cropRect);

    context->DrawBitmap(cropped.get());
}

void drawWithShadow(PlatformContextDirect2D& platformContext, FloatRect boundingRect, const ShadowState& shadowState, WTF::Function<void(ID2D1RenderTarget*)>&& drawCommands)
{
    if (!shadowState.isVisible()) {
        drawWithoutShadow(platformContext, WTFMove(drawCommands));
        return;
    }

    platformContext.notifyPreDrawObserver();

    auto* context = platformContext.renderTarget();

    FloatSize renderTargetSize = context->GetSize();
    const FloatRect contextRect(FloatPoint(), renderTargetSize);
    FloatRect workingContextRect(contextRect);

    if (boundingRect.isInfinite())
        boundingRect = workingContextRect;

    if (!contextRect.contains(boundingRect))
        workingContextRect.unite(boundingRect);

    workingContextRect.expand(std::abs(shadowState.offset.width()) + shadowState.blur, std::abs(shadowState.offset.height()) + shadowState.blur);

    auto scaleFactor = bitmapResolution(context);

    workingContextRect.scale(scaleFactor);

    IntSize pixelDimensions(clampTo<int>(workingContextRect.width()), clampTo<int>(workingContextRect.height()));

    // Render the current geometry to a bitmap context
    COMPtr<ID2D1BitmapRenderTarget> bitmapTarget = createBitmapRenderTargetOfSize(pixelDimensions, context);

    D2D1_MATRIX_3X2_F currentTransform;
    bitmapTarget->GetTransform(&currentTransform);

    if (!contextRect.contains(boundingRect.location())) {
        auto translation = D2D1::Matrix3x2F::Translation(-boundingRect.location().x(), -boundingRect.location().y());
        bitmapTarget->SetTransform(translation * currentTransform);
    }

    bitmapTarget->BeginDraw();
    drawCommands(bitmapTarget.get());
    HRESULT hr = bitmapTarget->EndDraw();
    RELEASE_ASSERT(SUCCEEDED(hr));

    bitmapTarget->SetTransform(currentTransform);

    drawWithShadowHelper(context, bitmapTarget.get(), boundingRect, shadowState.color, shadowState.offset, shadowState.blur);
    platformContext.notifyPostDrawObserver();
}

void drawWithoutShadow(PlatformContextDirect2D& platformContext, WTF::Function<void(ID2D1RenderTarget*)>&& drawCommands)
{
    platformContext.notifyPreDrawObserver();
    drawCommands(platformContext.renderTarget());
    platformContext.notifyPostDrawObserver();
}

void clearRect(PlatformContextDirect2D& platformContext, const FloatRect& rect)
{
    drawWithoutShadow(platformContext, [&platformContext, rect](ID2D1RenderTarget* renderTarget) {
        FloatRect renderTargetRect(FloatPoint(), renderTarget->GetSize());

        D2D1::Matrix3x2F matrix;
        renderTarget->GetTransform(&matrix);

        AffineTransform transform(matrix);

        FloatRect rectToClear(rect);
        if (!transform.preservesAxisAlignment()) {
            COMPtr<ID2D1RectangleGeometry> rectangle;
            HRESULT hr = GraphicsContext::systemFactory()->CreateRectangleGeometry(rectToClear, &rectangle);
            RELEASE_ASSERT(SUCCEEDED(hr));
            renderTarget->FillGeometry(rectangle.get(), platformContext.brushWithColor(D2D1::ColorF(0, 0, 0, 0)).get());
            return;
        }

        rectToClear = transform.mapRect(rectToClear);

        if (rectToClear.contains(renderTargetRect)) {
            platformContext.setTags(1, __LINE__);
            renderTarget->Clear(D2D1::ColorF(0, 0, 0, 0));
            return;
        }

        platformContext.setTags(1, __LINE__);
        renderTarget->PushAxisAlignedClip(rectToClear, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
        renderTarget->Clear(D2D1::ColorF(0, 0, 0, 0));
        renderTarget->PopAxisAlignedClip();
    });
}


void drawGlyphs(PlatformContextDirect2D& platformContext, const FillSource& fillSource, const StrokeSource& strokeSource, const ShadowState& shadowState, const FloatPoint& point, const Font& font, double syntheticBoldOffset, const Vector<unsigned short>& glyphs, const Vector<float>& horizontalAdvances, const Vector<DWRITE_GLYPH_OFFSET>& glyphOffsets, float xOffset, TextDrawingModeFlags textDrawingMode, float strokeThickness, const FloatSize& shadowOffset, const Color& shadowColor)
{
    auto renderTarget = platformContext.renderTarget();
    const FontPlatformData& platformData = font.platformData();

    PlatformContextStateSaver stateSaver(platformContext);

    D2D1_MATRIX_3X2_F matrix;
    renderTarget->GetTransform(&matrix);

    /*
    // FIXME: Get Synthetic Oblique working
    if (platformData.syntheticOblique()) {
        static float skew = -tanf(syntheticObliqueAngle() * piFloat / 180.0f);
        auto skewMatrix = D2D1::Matrix3x2F::Skew(skew, 0);
        context->SetTransform(matrix * skewMatrix);
    }
    */

    RELEASE_ASSERT(platformData.dwFont());
    RELEASE_ASSERT(platformData.dwFontFace());

    DWRITE_GLYPH_RUN glyphRun;
    glyphRun.fontFace = platformData.dwFontFace();
    glyphRun.fontEmSize = platformData.size();
    glyphRun.glyphCount = glyphs.size();
    glyphRun.glyphIndices = glyphs.data();
    glyphRun.glyphAdvances = horizontalAdvances.data();
    glyphRun.glyphOffsets = nullptr;
    glyphRun.isSideways = platformData.orientation() == FontOrientation::Vertical;
    glyphRun.bidiLevel = 0;

    /*
    // FIXME(): Get Shadows working
    FloatSize shadowOffset;
    float shadowBlur;
    Color shadowColor;
    graphicsContext.getShadow(shadowOffset, shadowBlur, shadowColor);

    bool hasSimpleShadow = graphicsContext.textDrawingMode() == TextModeFill && shadowColor.isValid() && !shadowBlur && (!graphicsContext.shadowsIgnoreTransforms() || graphicsContext.getCTM().isIdentityOrTranslationOrFlipped());
    if (hasSimpleShadow) {
        // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
        graphicsContext.clearShadow();
        Color fillColor = graphicsContext.fillColor();
        Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
        float shadowTextX = point.x() + shadowOffset.width();
        // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative.
        float shadowTextY = point.y() + shadowOffset.height() * (graphicsContext.shadowsIgnoreTransforms() ? -1 : 1);

        auto shadowBrush = graphicsContext.brushWithColor(shadowFillColor);
        context->DrawGlyphRun(D2D1::Point2F(shadowTextX, shadowTextY), &glyphRun, shadowBrush);
        if (font.syntheticBoldOffset())
            context->DrawGlyphRun(D2D1::Point2F(shadowTextX + font.syntheticBoldOffset(), shadowTextY), &glyphRun, shadowBrush);
    }
    */

    renderTarget->DrawGlyphRun(D2D1::Point2F(point.x(), point.y()), &glyphRun, fillSource.brush.get());
    // if (font.syntheticBoldOffset())
    //     context->DrawGlyphRun(D2D1::Point2F(point.x() + font.syntheticBoldOffset(), point.y()), &glyphRun, graphicsContext.solidFillBrush());

    // if (hasSimpleShadow)
    //     graphicsContext.setShadow(shadowOffset, shadowBlur, shadowColor);

    stateSaver.restore();
    platformContext.notifyPostDrawObserver();
}


void drawNativeImage(PlatformContextDirect2D& platformContext, IWICBitmap* image, const FloatSize& originalImageSize, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options, float globalAlpha, const ShadowState& shadowState)
{
    auto nativeImageSize = bitmapSize(image);
    COMPtr<ID2D1Bitmap> deviceBitmap;
    HRESULT hr = platformContext.renderTarget()->CreateBitmapFromWicBitmap(image, &deviceBitmap);
    if (!SUCCEEDED(hr))
        return;

    auto imageSize = bitmapSize(deviceBitmap.get());
    drawNativeImage(platformContext, deviceBitmap.get(), imageSize, destRect, srcRect, options, globalAlpha, shadowState);
}

void drawNativeImage(PlatformContextDirect2D& platformContext, ID2D1Bitmap* image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options, float globalAlpha, const ShadowState& shadowState)
{
    auto bitmapSize = image->GetSize();

    float currHeight = options.orientation().usesWidthAsHeight() ? bitmapSize.width : bitmapSize.height;
    if (currHeight <= srcRect.y())
        return;

    auto context = platformContext.renderTarget();

    D2D1_MATRIX_3X2_F ctm;
    context->GetTransform(&ctm);

    AffineTransform transform(ctm);

    PlatformContextStateSaver stateSaver(platformContext);

    bool shouldUseSubimage = false;

    // If the source rect is a subportion of the image, then we compute an inflated destination rect that will hold the entire image
    // and then set a clip to the portion that we want to display.
    FloatRect adjustedDestRect = destRect;

    if (srcRect.size() != imageSize) {
        // FIXME: Implement image scaling
        notImplemented();
    }

    // If the image is only partially loaded, then shrink the destination rect that we're drawing into accordingly.
    if (!shouldUseSubimage && currHeight < imageSize.height())
        adjustedDestRect.setHeight(adjustedDestRect.height() * currHeight / imageSize.height());

    State::setCompositeOperation(platformContext, options.compositeOperator(), options.blendMode());

    // ImageOrientation expects the origin to be at (0, 0).
    transform.translate(adjustedDestRect.x(), adjustedDestRect.y());
    context->SetTransform(transform);
    adjustedDestRect.setLocation(FloatPoint());

    if (options.orientation() != ImageOrientation::None) {
        concatCTM(platformContext, options.orientation().transformFromDefault(adjustedDestRect.size()));
        if (options.orientation().usesWidthAsHeight()) {
            // The destination rect 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 = FloatRect(adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.height(), adjustedDestRect.width());
        }
    }

    platformContext.setTags(1, __LINE__);
    drawWithShadow(platformContext, adjustedDestRect, shadowState, [image, adjustedDestRect, globalAlpha, srcRect](ID2D1RenderTarget* renderTarget) {
        renderTarget->DrawBitmap(image, adjustedDestRect, globalAlpha, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, srcRect);
    });

    if (!stateSaver.didSave())
        context->SetTransform(ctm);
}

void drawPattern(PlatformContextDirect2D& platformContext, COMPtr<ID2D1Bitmap>&& tileImage, const IntSize& size, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, CompositeOperator compositeOperator, BlendMode blendMode)
{
    auto context = platformContext.renderTarget();
    PlatformContextStateSaver stateSaver(platformContext);

    clip(platformContext, destRect);

    State::setCompositeOperation(platformContext, compositeOperator, blendMode);

    auto bitmapBrushProperties = D2D1::BitmapBrushProperties();
    bitmapBrushProperties.extendModeX = D2D1_EXTEND_MODE_WRAP;
    bitmapBrushProperties.extendModeY = D2D1_EXTEND_MODE_WRAP;

    // Create a brush transformation so we paint using the section of the image we care about.
    AffineTransform transformation = patternTransform;
    transformation.translate(destRect.location());

    auto brushProperties = D2D1::BrushProperties();
    brushProperties.transform = transformation;
    brushProperties.opacity = 1.0f;

    // If we only want a subset of the bitmap, we need to create a cropped bitmap image. According to the documentation,
    // this does not allocate new bitmap memory.
    if (size.width() > destRect.width() || size.height() > destRect.height()) {
        float dpiX = 0;
        float dpiY = 0;
        tileImage->GetDpi(&dpiX, &dpiY);
        auto bitmapProperties = D2D1::BitmapProperties(tileImage->GetPixelFormat(), dpiX, dpiY);
        COMPtr<ID2D1Bitmap> subImage;
        HRESULT hr = context->CreateBitmap(IntSize(tileRect.size()), bitmapProperties, &subImage);
        if (SUCCEEDED(hr)) {
            D2D1_RECT_U finishRect = IntRect(tileRect);
            hr = subImage->CopyFromBitmap(nullptr, tileImage.get(), &finishRect);
            if (SUCCEEDED(hr))
                tileImage = subImage;
        }
    }

    COMPtr<ID2D1BitmapBrush> patternBrush;
    HRESULT hr = context->CreateBitmapBrush(tileImage.get(), &bitmapBrushProperties, &brushProperties, &patternBrush);
    ASSERT(SUCCEEDED(hr));
    if (!SUCCEEDED(hr))
        return;

    drawWithoutShadow(platformContext, [destRect, patternBrush](ID2D1RenderTarget* renderTarget) {
        const D2D1_RECT_F d2dRect = destRect;
        renderTarget->FillRectangle(&d2dRect, patternBrush.get());
    });
}

void drawRect(PlatformContextDirect2D& platformContext, const FloatRect& rect, float borderThickness, const Color& fillColor, StrokeStyle strokeStyle, const Color& strokeColor)
{
    // FIXME: this function does not handle patterns and gradients like drawPath does, it probably should.
    ASSERT(!rect.isEmpty());

    platformContext.setTags(1, __LINE__);
    drawWithoutShadow(platformContext, [&platformContext, rect, fillColor, strokeColor, strokeStyle](ID2D1RenderTarget* renderTarget) {
        const D2D1_RECT_F d2dRect = rect;
        auto fillBrush = platformContext.brushWithColor(fillColor);
        renderTarget->FillRectangle(&d2dRect, fillBrush.get());
        if (strokeStyle != NoStroke) {
            auto strokeBrush = platformContext.brushWithColor(strokeColor);
            renderTarget->DrawRectangle(&d2dRect, strokeBrush.get(), platformContext.strokeThickness(), platformContext.strokeStyle());
        }
    });
}

void drawLine(PlatformContextDirect2D& platformContext, const FloatPoint& point1, const FloatPoint& point2, StrokeStyle strokeStyle, const Color& strokeColor, float strokeThickness, bool shouldAntialias)
{
    bool isVerticalLine = (point1.x() + strokeThickness == point2.x());
    float strokeWidth = isVerticalLine ? point2.y() - point1.y() : point2.x() - point1.x();
    if (!strokeThickness || !strokeWidth)
        return;

    auto context = platformContext.renderTarget();

    float cornerWidth = 0;
    bool drawsDashedLine = strokeStyle == DottedStroke || strokeStyle == DashedStroke;

    COMPtr<ID2D1StrokeStyle> d2dStrokeStyle;
    PlatformContextStateSaver stateSaver(platformContext, drawsDashedLine);
    if (drawsDashedLine) {
        // Figure out end points to ensure we always paint corners.
        cornerWidth = dashedLineCornerWidthForStrokeWidth(strokeWidth, strokeStyle, strokeThickness);
        strokeWidth -= 2 * cornerWidth;
        float patternWidth = dashedLinePatternWidthForStrokeWidth(strokeWidth, strokeStyle, strokeThickness);
        // Check if corner drawing sufficiently covers the line.
        if (strokeWidth <= patternWidth + 1)
            return;

        float patternOffset = dashedLinePatternOffsetForPatternAndStrokeWidth(patternWidth, strokeWidth);
        const float dashes[2] = { patternWidth, patternWidth };
        auto strokeStyleProperties = platformContext.strokeStyleProperties();
        GraphicsContext::systemFactory()->CreateStrokeStyle(&strokeStyleProperties, dashes, ARRAYSIZE(dashes), &d2dStrokeStyle);

        platformContext.setPatternWidth(patternWidth);
        platformContext.setPatternOffset(patternOffset);
        platformContext.setDashes(DashArray(2, patternWidth));

        d2dStrokeStyle = platformContext.strokeStyle();
    }

    auto centeredPoints = centerLineAndCutOffCorners(isVerticalLine, cornerWidth, point1, point2);
    auto p1 = centeredPoints[0];
    auto p2 = centeredPoints[1];

    platformContext.setTags(1, __LINE__);

    drawWithoutShadow(platformContext, [&platformContext, p1, p2, d2dStrokeStyle, strokeColor, strokeThickness](ID2D1RenderTarget* renderTarget) {
        renderTarget->DrawLine(p1, p2, platformContext.brushWithColor(strokeColor).get(), strokeThickness, d2dStrokeStyle.get());
    });
}

void drawLinesForText(PlatformContextDirect2D&, const FloatPoint&, float, const DashArray&, bool, bool, const Color&)
{
    notImplemented();
}

void drawDotsForDocumentMarker(PlatformContextDirect2D&, const FloatRect&, DocumentMarkerLineStyle)
{
    notImplemented();
}

void fillEllipse(PlatformContextDirect2D& platformContext, const FloatRect& rect, const Color& fillColor, StrokeStyle strokeStyle, const Color& strokeColor, float strokeThickness)
{
    auto ellipse = D2D1::Ellipse(rect.center(), 0.5 * rect.width(), 0.5 * rect.height());

    platformContext.setTags(1, __LINE__);
    drawWithoutShadow(platformContext, [&platformContext, ellipse, fillColor, strokeStyle, strokeColor, strokeThickness](ID2D1RenderTarget* renderTarget) {
        auto fillBrush = platformContext.brushWithColor(fillColor);
        renderTarget->FillEllipse(&ellipse, fillBrush.get());
        if (strokeStyle != StrokeStyle::NoStroke) {
            auto strokeBrush = platformContext.brushWithColor(strokeColor);
            renderTarget->DrawEllipse(&ellipse, strokeBrush.get(), strokeThickness, platformContext.strokeStyle());
        }
    });
}

void drawEllipse(PlatformContextDirect2D& platformContext, const FloatRect& rect, StrokeStyle strokeStyle, const Color& strokeColor, float strokeThickness)
{
    if (strokeStyle == StrokeStyle::NoStroke)
        return;

    auto ellipse = D2D1::Ellipse(rect.center(), 0.5 * rect.width(), 0.5 * rect.height());

    platformContext.setTags(1, __LINE__);
    drawWithoutShadow(platformContext, [&platformContext, ellipse, strokeColor, strokeThickness](ID2D1RenderTarget* renderTarget) {
        auto strokeBrush = platformContext.brushWithColor(strokeColor);
        renderTarget->DrawEllipse(&ellipse, strokeBrush.get(), strokeThickness, platformContext.strokeStyle());
    });
}

void drawFocusRing(PlatformContextDirect2D&, const Path&, float, const Color&)
{
    notImplemented();
}

void drawFocusRing(PlatformContextDirect2D&, const Vector<FloatRect>&, float, const Color&)
{
    notImplemented();
}

void flush(PlatformContextDirect2D& platformContext)
{
    ASSERT(platformContext.renderTarget());
    D2D1_TAG first, second;
    HRESULT hr = platformContext.renderTarget()->Flush(&first, &second);

    RELEASE_ASSERT(SUCCEEDED(hr));
}

void save(PlatformContextDirect2D& platformContext)
{
    platformContext.save();

    if (auto* graphicsContextPrivate = platformContext.graphicsContextPrivate())
        graphicsContextPrivate->save();
}

void restore(PlatformContextDirect2D& platformContext)
{
    platformContext.restore();

    if (auto* graphicsContextPrivate = platformContext.graphicsContextPrivate())
        graphicsContextPrivate->restore();
}

void translate(PlatformContextDirect2D& platformContext, float x, float y)
{
    ASSERT(platformContext.renderTarget());

    D2D1_MATRIX_3X2_F currentTransform;
    platformContext.renderTarget()->GetTransform(&currentTransform);

    auto translation = D2D1::Matrix3x2F::Translation(x, y);
    platformContext.renderTarget()->SetTransform(translation * currentTransform);

    if (auto* graphicsContextPrivate = platformContext.graphicsContextPrivate())
        graphicsContextPrivate->translate(x, y);
}

void rotate(PlatformContextDirect2D& platformContext, float angleInRadians)
{
    ASSERT(platformContext.renderTarget());

    D2D1_MATRIX_3X2_F currentTransform;
    platformContext.renderTarget()->GetTransform(&currentTransform);

    auto rotation = D2D1::Matrix3x2F::Rotation(rad2deg(angleInRadians));
    platformContext.renderTarget()->SetTransform(rotation * currentTransform);

    if (auto* graphicsContextPrivate = platformContext.graphicsContextPrivate())
        graphicsContextPrivate->rotate(angleInRadians);
}

void scale(PlatformContextDirect2D& platformContext, const FloatSize& size)
{
    ASSERT(platformContext.renderTarget());

    D2D1_MATRIX_3X2_F currentTransform;
    platformContext.renderTarget()->GetTransform(&currentTransform);

    auto scale = D2D1::Matrix3x2F::Scale(size);
    platformContext.renderTarget()->SetTransform(scale * currentTransform);

    if (auto* graphicsContextPrivate = platformContext.graphicsContextPrivate())
        graphicsContextPrivate->scale(size);
}

void concatCTM(PlatformContextDirect2D& platformContext, const AffineTransform& affineTransform)
{
    ASSERT(platformContext.renderTarget());

    D2D1_MATRIX_3X2_F currentTransform;
    platformContext.renderTarget()->GetTransform(&currentTransform);

    D2D1_MATRIX_3X2_F transformToConcat = affineTransform;
    platformContext.renderTarget()->SetTransform(transformToConcat * currentTransform);

    if (auto* graphicsContextPrivate = platformContext.graphicsContextPrivate())
        graphicsContextPrivate->concatCTM(affineTransform);
}

void beginTransparencyLayer(PlatformContextDirect2D& platformContext, float opacity)
{
    PlatformContextDirect2D::TransparencyLayerState transparencyLayer;
    transparencyLayer.opacity = opacity;

    transparencyLayer.renderTarget = createBitmapRenderTarget(platformContext.renderTarget());

    platformContext.m_transparencyLayerStack.append(WTFMove(transparencyLayer));

    platformContext.m_transparencyLayerStack.last().renderTarget->BeginDraw();
    platformContext.m_transparencyLayerStack.last().renderTarget->Clear(D2D1::ColorF(0, 0, 0, 0));
}

void endTransparencyLayer(PlatformContextDirect2D& platformContext)
{
    auto currentLayer = platformContext.m_transparencyLayerStack.takeLast();
    auto renderTarget = currentLayer.renderTarget;
    if (!renderTarget)
        return;

    HRESULT hr = renderTarget->EndDraw();
    RELEASE_ASSERT(SUCCEEDED(hr));

    auto context = platformContext.renderTarget();

    if (currentLayer.hasShadow)
        drawWithShadowHelper(context, renderTarget.get(), FloatRect(), currentLayer.shadowColor, currentLayer.shadowOffset, currentLayer.shadowBlur);
    else {
        COMPtr<ID2D1Bitmap> bitmap;
        hr = renderTarget->GetBitmap(&bitmap);
        RELEASE_ASSERT(SUCCEEDED(hr));

        COMPtr<ID2D1BitmapBrush> bitmapBrush;
        auto bitmapBrushProperties = D2D1::BitmapBrushProperties();
        auto brushProperties = D2D1::BrushProperties();
        HRESULT hr = context->CreateBitmapBrush(bitmap.get(), bitmapBrushProperties, brushProperties, &bitmapBrush);
        RELEASE_ASSERT(SUCCEEDED(hr));

        auto size = bitmap->GetSize();
        auto rectInDIP = D2D1::RectF(0, 0, size.width, size.height);
        context->FillRectangle(rectInDIP, bitmapBrush.get());
    }
}

void clip(PlatformContextDirect2D& platformContext, const FloatRect& rect)
{
    platformContext.renderTarget()->PushAxisAlignedClip(rect, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
    platformContext.pushClip(PlatformContextDirect2D::AxisAlignedClip);

    if (auto* graphicsContextPrivate = platformContext.graphicsContextPrivate())
        graphicsContextPrivate->clip(rect);
}

void clipOut(PlatformContextDirect2D& platformContext, const FloatRect& rect)
{
    Path path;
    path.addRect(rect);

    clipOut(platformContext, path);
}

void clipOut(PlatformContextDirect2D& platformContext, const Path& path)
{
    // To clip Out we need the intersection of the infinite
    // clipping rect and the path we just created.
    D2D1_SIZE_F rendererSize = platformContext.renderTarget()->GetSize();
    FloatRect clipBounds(0, 0, rendererSize.width, rendererSize.height);

    Path boundingRect;
    boundingRect.addRect(clipBounds);
    boundingRect.appendGeometry(path.platformPath());

    COMPtr<ID2D1GeometryGroup> pathToClip;
    boundingRect.createGeometryWithFillMode(WindRule::EvenOdd, pathToClip);
    clipPath(platformContext, pathToClip.get());
}

void clipPath(PlatformContextDirect2D& platformContext, const Path& path, WindRule clipRule)
{
    if (path.isEmpty()) {
        Direct2D::clip(platformContext, FloatRect());
        return;
    }

    COMPtr<ID2D1GeometryGroup> pathToClip;
    path.createGeometryWithFillMode(clipRule, pathToClip);

    clipPath(platformContext, pathToClip.get());

    if (auto* graphicsContextPrivate = platformContext.graphicsContextPrivate())
        graphicsContextPrivate->clip(path);
}

void clipPath(PlatformContextDirect2D& platformContext, ID2D1Geometry* path)
{
    COMPtr<ID2D1Layer> clipLayer;
    HRESULT hr = platformContext.renderTarget()->CreateLayer(&clipLayer);
    if (!SUCCEEDED(hr))
        return;

    platformContext.renderTarget()->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), path), clipLayer.get());
    platformContext.pushRenderClip(PlatformContextDirect2D::LayerClip);
    platformContext.setActiveLayer(WTFMove(clipLayer));
}

void clipToImageBuffer(PlatformContextDirect2D&, ID2D1RenderTarget*, const FloatRect&)
{
    notImplemented();
}


void copyBits(const uint8_t* srcRows, unsigned rowCount, unsigned colCount, unsigned srcStride, unsigned destStride, uint8_t* destRows)
{
    for (unsigned y = 0; y < rowCount; ++y) {
        // Source data may be power-of-two sized, so we need to only copy the bits that
        // correspond to the rectangle supplied by the caller.
        const uint32_t* srcRow = reinterpret_cast<const uint32_t*>(srcRows + srcStride * y);
        uint32_t* destRow = reinterpret_cast<uint32_t*>(destRows + destStride * y);
        memcpy(destRow, srcRow, colCount);
    }
}

} // namespace Direct2D

} // namespace WebCore

#endif // USE(DIRECT2D)
