/*
 * 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->createBrush(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->createBrush(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 LineCap::Round:
        capStyle = D2D1_CAP_STYLE_ROUND;
        break;
    case LineCap::Square:
        capStyle = D2D1_CAP_STYLE_SQUARE;
        break;
    case LineCap::Butt:
    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 LineJoin::Round:
        joinStyle = D2D1_LINE_JOIN_ROUND;
        break;
    case LineJoin::Bevel:
        joinStyle = D2D1_LINE_JOIN_BEVEL;
        break;
    case LineJoin::Miter:
    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, 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, 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() == TextDrawingMode::Fill && 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.colorWithAlphaMultipliedBy(fillColor.alphaAsFloat());
        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 drawPlatformImage(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());
    drawPlatformImage(platformContext, deviceBitmap.get(), imageSize, destRect, srcRect, options, globalAlpha, shadowState);
}

void drawPlatformImage(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)
