/*
 * Copyright (C) 2020 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``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 ITS 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 "DisplayBoxDecorationPainter.h"

#if ENABLE(LAYOUT_FORMATTING_CONTEXT)

#include "BorderEdge.h" // For BoxSideSet.
#include "Color.h"
#include "DisplayBoxDecorationData.h"
#include "DisplayBoxModelBox.h"
#include "DisplayBoxRareGeometry.h"
#include "DisplayPaintingContext.h"
#include "DisplayStyle.h"
#include "DisplayTree.h"
#include "FillLayer.h"
#include "GeometryUtilities.h"
#include "GraphicsContext.h"
#include "IntRect.h"
#include "LayoutPoint.h"
#include "ShadowData.h"

namespace WebCore {
namespace Display {

class BorderPainter {
public:
    BorderPainter(const RectEdges<BorderEdge>& edges, const FloatRoundedRect& borderRect, BackgroundBleedAvoidance bleedAvoidance, bool includeLeftEdge, bool includeRightEdge)
        : m_edges(edges)
        , m_borderRect(borderRect)
        , m_bleedAvoidance(bleedAvoidance)
        , m_includeLeftEdge(includeLeftEdge)
        , m_includeRightEdge(includeRightEdge)
    {
    }
    
    void paintBorders(PaintingContext&) const;

private:
    static bool edgesShareColor(const BorderEdge& firstEdge, const BorderEdge& secondEdge)
    {
        return firstEdge.color() == secondEdge.color();
    }

    static bool borderStyleFillsBorderArea(BorderStyle style)
    {
        return !(style == BorderStyle::Dotted || style == BorderStyle::Dashed || style == BorderStyle::Double);
    }

    static bool borderStyleHasInnerDetail(BorderStyle style)
    {
        return style == BorderStyle::Groove || style == BorderStyle::Ridge || style == BorderStyle::Double;
    }

    static bool styleRequiresClipPolygon(BorderStyle style)
    {
        return style == BorderStyle::Dotted || style == BorderStyle::Dashed; // These are drawn with a stroke, so we have to clip to get corner miters.
    }

    static bool borderStyleIsDottedOrDashed(BorderStyle style)
    {
        return style == BorderStyle::Dotted || style == BorderStyle::Dashed;
    }

    static bool borderWillArcInnerEdge(const FloatSize& firstRadius, const FloatSize& secondRadius)
    {
        return !firstRadius.isZero() || !secondRadius.isZero();
    }

    static bool borderStyleHasUnmatchedColorsAtCorner(BorderStyle, BoxSide, BoxSide adjacentSide);
    static bool borderStylesRequireMitre(BoxSide, BoxSide adjacentSide, BorderStyle, BorderStyle adjacentStyle);
    static FloatRoundedRect calculateAdjustedInnerBorder(const FloatRoundedRect& innerBorder, BoxSide);
    static void calculateBorderStyleColor(BorderStyle, BoxSide, Color&);

    FloatRect borderInnerRectAdjustedForBleedAvoidance(const PaintingContext&) const;

    bool colorsMatchAtCorner(BoxSide, BoxSide adjacentSide) const;
    bool colorNeedsAntiAliasAtCorner(BoxSide, BoxSide adjacentSide) const;
    bool willBeOverdrawn(BoxSide, BoxSide adjacentSide) const;
    bool joinRequiresMitre(BoxSide, BoxSide adjacentSide, bool allowOverdraw) const;

    void clipBorderSidePolygon(PaintingContext&, const FloatRoundedRect& outerBorder, const FloatRoundedRect& innerBorder, BoxSide, bool firstEdgeMatches, bool secondEdgeMatches) const;

    void drawLineForBoxSide(PaintingContext&, const FloatRect&, BoxSide, Color, BorderStyle, float adjacentWidth1, float adjacentWidth2, bool antialias) const;
    void drawBoxSideFromPath(PaintingContext&, const FloatRect& borderRect, const Path& borderPath, float thickness, float drawThickness, BoxSide, Color, BorderStyle) const;

    void paintOneBorderSide(PaintingContext&, const FloatRoundedRect& outerBorder, const FloatRoundedRect& innerBorder, const FloatRect& sideRect, BoxSide, const Path*, bool antialias, const Color* overrideColor) const;
    void paintBorderSides(PaintingContext&, const FloatRoundedRect& outerBorder, const FloatRoundedRect& innerBorder, FloatSize innerBorderBleedAdjustment, BoxSideSet, bool antialias, const Color* overrideColor = nullptr) const;
    void paintTranslucentBorderSides(PaintingContext&, const FloatRoundedRect& outerBorder, const FloatRoundedRect& innerBorder, FloatSize innerBorderBleedAdjustment, BoxSideSet, bool antialias) const;

    const RectEdges<BorderEdge>& m_edges;
    const FloatRoundedRect m_borderRect;
    const BackgroundBleedAvoidance m_bleedAvoidance;
    const bool m_includeLeftEdge;
    const bool m_includeRightEdge;
};

// BorderStyle::Outset darkens the bottom and right (and maybe lightens the top and left)
// BorderStyle::Inset darkens the top and left (and maybe lightens the bottom and right)
bool BorderPainter::borderStyleHasUnmatchedColorsAtCorner(BorderStyle style, BoxSide side, BoxSide adjacentSide)
{
    // These styles match at the top/left and bottom/right.
    if (style == BorderStyle::Inset || style == BorderStyle::Groove || style == BorderStyle::Ridge || style == BorderStyle::Outset) {
        BoxSideSet topRightSides = { BoxSideFlag::Top, BoxSideFlag::Right };
        BoxSideSet bottomLeftSides = { BoxSideFlag::Bottom, BoxSideFlag::Left };

        BoxSideSet usedSides { edgeFlagForSide(side), edgeFlagForSide(adjacentSide) };
        return usedSides == topRightSides || usedSides == bottomLeftSides;
    }
    return false;
}

bool BorderPainter::colorsMatchAtCorner(BoxSide side, BoxSide adjacentSide) const
{
    auto& edge = m_edges.at(side);
    auto& adjacentEdge = m_edges.at(adjacentSide);

    if (edge.shouldRender() != adjacentEdge.shouldRender())
        return false;

    if (!edgesShareColor(edge, adjacentEdge))
        return false;

    return !borderStyleHasUnmatchedColorsAtCorner(edge.style(), side, adjacentSide);
}

bool BorderPainter::colorNeedsAntiAliasAtCorner(BoxSide side, BoxSide adjacentSide) const
{
    auto& edge = m_edges.at(side);
    auto& adjacentEdge = m_edges.at(adjacentSide);

    if (edge.color().isOpaque())
        return false;

    if (edge.shouldRender() != adjacentEdge.shouldRender())
        return false;

    if (!edgesShareColor(edge, adjacentEdge))
        return true;

    return borderStyleHasUnmatchedColorsAtCorner(edge.style(), side, adjacentSide);
}

void BorderPainter::calculateBorderStyleColor(BorderStyle style, BoxSide side, Color& color)
{
    ASSERT(style == BorderStyle::Inset || style == BorderStyle::Outset);

    // This values were derived empirically.
    constexpr float baseDarkColorLuminance { 0.014443844f }; // Luminance of SRGBA<uint8_t> { 32, 32, 32 }
    constexpr float baseLightColorLuminance { 0.83077f }; // Luminance of SRGBA<uint8_t> { 235, 235, 235 }

    enum Operation { Darken, Lighten };

    Operation operation = (side == BoxSide::Top || side == BoxSide::Left) == (style == BorderStyle::Inset) ? Darken : Lighten;

    // Here we will darken the border decoration color when needed. This will yield a similar behavior as in FF.
    if (operation == Darken) {
        if (color.luminance() > baseDarkColorLuminance)
            color = color.darkened();
    } else {
        if (color.luminance() < baseLightColorLuminance)
            color = color.lightened();
    }
}

// This assumes that we draw in order: top, bottom, left, right.
bool BorderPainter::willBeOverdrawn(BoxSide side, BoxSide adjacentSide) const
{
    switch (side) {
    case BoxSide::Top:
    case BoxSide::Bottom: {
        auto& edge = m_edges.at(side);
        auto& adjacentEdge = m_edges.at(adjacentSide);

        if (adjacentEdge.presentButInvisible())
            return false;

        if (!edgesShareColor(edge, adjacentEdge) && !adjacentEdge.color().isOpaque())
            return false;
        
        if (!borderStyleFillsBorderArea(adjacentEdge.style()))
            return false;

        return true;
    }
    case BoxSide::Left:
    case BoxSide::Right:
        // These draw last, so are never overdrawn.
        return false;
    }
    return false;
}

bool BorderPainter::borderStylesRequireMitre(BoxSide side, BoxSide adjacentSide, BorderStyle style, BorderStyle adjacentStyle)
{
    if (style == BorderStyle::Double || adjacentStyle == BorderStyle::Double || adjacentStyle == BorderStyle::Groove || adjacentStyle == BorderStyle::Ridge)
        return true;

    if (borderStyleIsDottedOrDashed(style) != borderStyleIsDottedOrDashed(adjacentStyle))
        return true;

    if (style != adjacentStyle)
        return true;

    return borderStyleHasUnmatchedColorsAtCorner(style, side, adjacentSide);
}

FloatRoundedRect BorderPainter::calculateAdjustedInnerBorder(const FloatRoundedRect& innerBorder, BoxSide side)
{
    // Expand the inner border as necessary to make it a rounded rect (i.e. radii contained within each edge).
    // This function relies on the fact we only get radii not contained within each edge if one of the radii
    // for an edge is zero, so we can shift the arc towards the zero radius corner.
    auto newRadii = innerBorder.radii();
    auto newRect = innerBorder.rect();

    float overshoot;
    float maxRadii;

    switch (side) {
    case BoxSide::Top:
        overshoot = newRadii.topLeft().width() + newRadii.topRight().width() - newRect.width();
        if (overshoot > 0) {
            ASSERT(!(newRadii.topLeft().width() && newRadii.topRight().width()));
            newRect.setWidth(newRect.width() + overshoot);
            if (!newRadii.topLeft().width())
                newRect.move(-overshoot, 0);
        }
        newRadii.setBottomLeft({ });
        newRadii.setBottomRight({ });
        maxRadii = std::max(newRadii.topLeft().height(), newRadii.topRight().height());
        if (maxRadii > newRect.height())
            newRect.setHeight(maxRadii);
        break;

    case BoxSide::Bottom:
        overshoot = newRadii.bottomLeft().width() + newRadii.bottomRight().width() - newRect.width();
        if (overshoot > 0) {
            ASSERT(!(newRadii.bottomLeft().width() && newRadii.bottomRight().width()));
            newRect.setWidth(newRect.width() + overshoot);
            if (!newRadii.bottomLeft().width())
                newRect.move(-overshoot, 0);
        }
        newRadii.setTopLeft({ });
        newRadii.setTopRight({ });
        maxRadii = std::max(newRadii.bottomLeft().height(), newRadii.bottomRight().height());
        if (maxRadii > newRect.height()) {
            newRect.move(0, newRect.height() - maxRadii);
            newRect.setHeight(maxRadii);
        }
        break;

    case BoxSide::Left:
        overshoot = newRadii.topLeft().height() + newRadii.bottomLeft().height() - newRect.height();
        if (overshoot > 0) {
            ASSERT(!(newRadii.topLeft().height() && newRadii.bottomLeft().height()));
            newRect.setHeight(newRect.height() + overshoot);
            if (!newRadii.topLeft().height())
                newRect.move(0, -overshoot);
        }
        newRadii.setTopRight({ });
        newRadii.setBottomRight({ });
        maxRadii = std::max(newRadii.topLeft().width(), newRadii.bottomLeft().width());
        if (maxRadii > newRect.width())
            newRect.setWidth(maxRadii);
        break;

    case BoxSide::Right:
        overshoot = newRadii.topRight().height() + newRadii.bottomRight().height() - newRect.height();
        if (overshoot > 0) {
            ASSERT(!(newRadii.topRight().height() && newRadii.bottomRight().height()));
            newRect.setHeight(newRect.height() + overshoot);
            if (!newRadii.topRight().height())
                newRect.move(0, -overshoot);
        }
        newRadii.setTopLeft({ });
        newRadii.setBottomLeft({ });
        maxRadii = std::max(newRadii.topRight().width(), newRadii.bottomRight().width());
        if (maxRadii > newRect.width()) {
            newRect.move(newRect.width() - maxRadii, 0);
            newRect.setWidth(maxRadii);
        }
        break;
    }

    return FloatRoundedRect { newRect, newRadii };
}

bool BorderPainter::joinRequiresMitre(BoxSide side, BoxSide adjacentSide, bool allowOverdraw) const
{
    auto& edge = m_edges.at(side);
    auto& adjacentEdge = m_edges.at(adjacentSide);

    if ((edge.isTransparent() && adjacentEdge.isTransparent()) || !adjacentEdge.isPresent())
        return false;

    if (allowOverdraw && willBeOverdrawn(side, adjacentSide))
        return false;

    if (!edgesShareColor(edge, adjacentEdge))
        return true;

    if (borderStylesRequireMitre(side, adjacentSide, edge.style(), adjacentEdge.style()))
        return true;
    
    return false;
}

void BorderPainter::drawBoxSideFromPath(PaintingContext& paintingContext, const FloatRect& borderRect, const Path& borderPath, float thickness, float drawThickness, BoxSide side, Color color, BorderStyle borderStyle) const
{
    if (thickness <= 0)
        return;

    if (borderStyle == BorderStyle::Double && thickness < 3)
        borderStyle = BorderStyle::Solid;

    switch (borderStyle) {
    case BorderStyle::None:
    case BorderStyle::Hidden:
        return;
    case BorderStyle::Dotted:
    case BorderStyle::Dashed: {
        paintingContext.context.setStrokeColor(color);

        // The stroke is doubled here because the provided path is the
        // outside edge of the border so half the stroke is clipped off.
        // The extra multiplier is so that the clipping mask can antialias
        // the edges to prevent jaggies.
        paintingContext.context.setStrokeThickness(drawThickness * 2 * 1.1f);
        paintingContext.context.setStrokeStyle(borderStyle == BorderStyle::Dashed ? DashedStroke : DottedStroke);

        // If the number of dashes that fit in the path is odd and non-integral then we
        // will have an awkwardly-sized dash at the end of the path. To try to avoid that
        // here, we simply make the whitespace dashes ever so slightly bigger.
        // FIXME: This could be even better if we tried to manipulate the dash offset
        // and possibly the gapLength to get the corners dash-symmetrical.
        float dashLength = thickness * ((borderStyle == BorderStyle::Dashed) ? 3.0f : 1.0f);
        float gapLength = dashLength;
        float numberOfDashes = borderPath.length() / dashLength;
        // Don't try to show dashes if we have less than 2 dashes + 2 gaps.
        // FIXME: should do this test per side.
        if (numberOfDashes >= 4) {
            bool evenNumberOfFullDashes = !((int)numberOfDashes % 2);
            bool integralNumberOfDashes = !(numberOfDashes - (int)numberOfDashes);
            if (!evenNumberOfFullDashes && !integralNumberOfDashes) {
                float numberOfGaps = numberOfDashes / 2;
                gapLength += (dashLength  / numberOfGaps);
            }

            DashArray lineDash;
            lineDash.append(dashLength);
            lineDash.append(gapLength);
            paintingContext.context.setLineDash(lineDash, dashLength);
        }
        
        // FIXME: stroking the border path causes issues with tight corners:
        // https://bugs.webkit.org/show_bug.cgi?id=58711
        // Also, to get the best appearance we should stroke a path between the two borders.
        paintingContext.context.strokePath(borderPath);
        return;
    }
    case BorderStyle::Double: {
        // Get the inner border rects for both the outer border line and the inner border line
        // FIXME: Rect edges.
        float outerBorderTopWidth = m_edges.top().outerWidth();
        float innerBorderTopWidth = m_edges.top().innerWidth();

        float outerBorderRightWidth = m_edges.right().outerWidth();
        float innerBorderRightWidth = m_edges.right().innerWidth();

        float outerBorderBottomWidth = m_edges.bottom().outerWidth();
        float innerBorderBottomWidth = m_edges.bottom().innerWidth();

        float outerBorderLeftWidth = m_edges.left().outerWidth();
        float innerBorderLeftWidth = m_edges.left().innerWidth();

        // Draw inner border line
        {
            GraphicsContextStateSaver stateSaver(paintingContext.context);
            auto innerClip = roundedInsetBorderForRect(borderRect, m_borderRect.radii(), { innerBorderTopWidth, innerBorderRightWidth, innerBorderBottomWidth, innerBorderLeftWidth }, m_includeLeftEdge, m_includeRightEdge);
            
            paintingContext.context.clipRoundedRect(innerClip);
            drawBoxSideFromPath(paintingContext, borderRect, borderPath, thickness, drawThickness, side, color, BorderStyle::Solid);
        }

        // Draw outer border line
        {
            GraphicsContextStateSaver stateSaver(paintingContext.context);
            auto outerRect = borderRect;
            if (m_bleedAvoidance == BackgroundBleedAvoidance::UseTransparencyLayer) {
                outerRect.inflate(1);
                ++outerBorderTopWidth;
                ++outerBorderBottomWidth;
                ++outerBorderLeftWidth;
                ++outerBorderRightWidth;
            }

            auto outerClip = roundedInsetBorderForRect(outerRect, m_borderRect.radii(), { outerBorderTopWidth, outerBorderRightWidth, outerBorderBottomWidth, outerBorderLeftWidth }, m_includeLeftEdge, m_includeRightEdge);
            paintingContext.context.clipOutRoundedRect(outerClip);
            drawBoxSideFromPath(paintingContext, borderRect, borderPath, thickness, drawThickness, side, color, BorderStyle::Solid);
        }
        return;
    }
    case BorderStyle::Ridge:
    case BorderStyle::Groove:
    {
        BorderStyle s1;
        BorderStyle s2;
        if (borderStyle == BorderStyle::Groove) {
            s1 = BorderStyle::Inset;
            s2 = BorderStyle::Outset;
        } else {
            s1 = BorderStyle::Outset;
            s2 = BorderStyle::Inset;
        }
        
        // Paint full border
        drawBoxSideFromPath(paintingContext, borderRect, borderPath, thickness, drawThickness, side, color, s1);

        // Paint inner only
        GraphicsContextStateSaver stateSaver(paintingContext.context);
        // FIXME: Should have pixel snapped these at display tree generation time.
        // FIXME: RectEdges
        float topWidth { m_edges.top().widthForPainting() / 2 };
        float bottomWidth { m_edges.bottom().widthForPainting() / 2 };
        float leftWidth { m_edges.left().widthForPainting() / 2 };
        float rightWidth { m_edges.right().widthForPainting() / 2 };

        auto clipRect = roundedInsetBorderForRect(borderRect, m_borderRect.radii(), { topWidth, rightWidth, bottomWidth, leftWidth }, m_includeLeftEdge, m_includeRightEdge);

        paintingContext.context.clipRoundedRect(clipRect);
        drawBoxSideFromPath(paintingContext, borderRect, borderPath, thickness, drawThickness, side, color, s2);
        return;
    }
    case BorderStyle::Inset:
    case BorderStyle::Outset:
        calculateBorderStyleColor(borderStyle, side, color);
        break;
    default:
        break;
    }

    paintingContext.context.setStrokeStyle(NoStroke);
    paintingContext.context.setFillColor(color);
    paintingContext.context.drawRect(borderRect);
}

void BorderPainter::clipBorderSidePolygon(PaintingContext& paintingContext, const FloatRoundedRect& outerBorder, const FloatRoundedRect& innerBorder, BoxSide side, bool firstEdgeMatches, bool secondEdgeMatches) const
{
    const FloatRect& outerRect = outerBorder.rect();
    const FloatRect& innerRect = innerBorder.rect();

    // For each side, create a quad that encompasses all parts of that side that may draw,
    // including areas inside the innerBorder.
    //
    //         0----------------3
    //       0  \              /  0
    //       |\  1----------- 2  /|
    //       | 1                1 |
    //       | |                | |
    //       | |                | |
    //       | 2                2 |
    //       |/  1------------2  \|
    //       3  /              \  3
    //         0----------------3
    //
    Vector<FloatPoint> quad;
    quad.reserveInitialCapacity(4);
    switch (side) {
    case BoxSide::Top:
        quad.uncheckedAppend(outerRect.minXMinYCorner());
        quad.uncheckedAppend(innerRect.minXMinYCorner());
        quad.uncheckedAppend(innerRect.maxXMinYCorner());
        quad.uncheckedAppend(outerRect.maxXMinYCorner());

        if (!innerBorder.radii().topLeft().isZero())
            findIntersection(outerRect.minXMinYCorner(), innerRect.minXMinYCorner(), innerRect.minXMaxYCorner(), innerRect.maxXMinYCorner(), quad[1]);

        if (!innerBorder.radii().topRight().isZero())
            findIntersection(outerRect.maxXMinYCorner(), innerRect.maxXMinYCorner(), innerRect.minXMinYCorner(), innerRect.maxXMaxYCorner(), quad[2]);
        break;

    case BoxSide::Left:
        quad.uncheckedAppend(outerRect.minXMinYCorner());
        quad.uncheckedAppend(innerRect.minXMinYCorner());
        quad.uncheckedAppend(innerRect.minXMaxYCorner());
        quad.uncheckedAppend(outerRect.minXMaxYCorner());

        if (!innerBorder.radii().topLeft().isZero())
            findIntersection(outerRect.minXMinYCorner(), innerRect.minXMinYCorner(), innerRect.minXMaxYCorner(), innerRect.maxXMinYCorner(), quad[1]);

        if (!innerBorder.radii().bottomLeft().isZero())
            findIntersection(outerRect.minXMaxYCorner(), innerRect.minXMaxYCorner(), innerRect.minXMinYCorner(), innerRect.maxXMaxYCorner(), quad[2]);
        break;

    case BoxSide::Bottom:
        quad.uncheckedAppend(outerRect.minXMaxYCorner());
        quad.uncheckedAppend(innerRect.minXMaxYCorner());
        quad.uncheckedAppend(innerRect.maxXMaxYCorner());
        quad.uncheckedAppend(outerRect.maxXMaxYCorner());

        if (!innerBorder.radii().bottomLeft().isZero())
            findIntersection(outerRect.minXMaxYCorner(), innerRect.minXMaxYCorner(), innerRect.minXMinYCorner(), innerRect.maxXMaxYCorner(), quad[1]);

        if (!innerBorder.radii().bottomRight().isZero())
            findIntersection(outerRect.maxXMaxYCorner(), innerRect.maxXMaxYCorner(), innerRect.maxXMinYCorner(), innerRect.minXMaxYCorner(), quad[2]);
        break;

    case BoxSide::Right:
        quad.uncheckedAppend(outerRect.maxXMinYCorner());
        quad.uncheckedAppend(innerRect.maxXMinYCorner());
        quad.uncheckedAppend(innerRect.maxXMaxYCorner());
        quad.uncheckedAppend(outerRect.maxXMaxYCorner());

        if (!innerBorder.radii().topRight().isZero())
            findIntersection(outerRect.maxXMinYCorner(), innerRect.maxXMinYCorner(), innerRect.minXMinYCorner(), innerRect.maxXMaxYCorner(), quad[1]);

        if (!innerBorder.radii().bottomRight().isZero())
            findIntersection(outerRect.maxXMaxYCorner(), innerRect.maxXMaxYCorner(), innerRect.maxXMinYCorner(), innerRect.minXMaxYCorner(), quad[2]);
        break;
    }

    // If the border matches both of its adjacent sides, don't anti-alias the clip, and
    // if neither side matches, anti-alias the clip.
    if (firstEdgeMatches == secondEdgeMatches) {
        bool wasAntialiased = paintingContext.context.shouldAntialias();
        paintingContext.context.setShouldAntialias(!firstEdgeMatches);
        paintingContext.context.clipPath(Path::polygonPathFromPoints(quad), WindRule::NonZero);
        paintingContext.context.setShouldAntialias(wasAntialiased);
        return;
    }

    // Square off the end which shouldn't be affected by antialiasing, and clip.
    Vector<FloatPoint> firstQuad = {
        quad[0],
        quad[1],
        quad[2],
        side == BoxSide::Top || side == BoxSide::Bottom ? FloatPoint(quad[3].x(), quad[2].y()) : FloatPoint(quad[2].x(), quad[3].y()),
        quad[3]
    };
    bool wasAntialiased = paintingContext.context.shouldAntialias();
    paintingContext.context.setShouldAntialias(!firstEdgeMatches);
    paintingContext.context.clipPath(Path::polygonPathFromPoints(firstQuad), WindRule::NonZero);

    Vector<FloatPoint> secondQuad = {
        quad[0],
        side == BoxSide::Top || side == BoxSide::Bottom ? FloatPoint(quad[0].x(), quad[1].y()) : FloatPoint(quad[1].x(), quad[0].y()),
        quad[1],
        quad[2],
        quad[3]
    };
    // Antialiasing affects the second side.
    paintingContext.context.setShouldAntialias(!secondEdgeMatches);
    paintingContext.context.clipPath(Path::polygonPathFromPoints(secondQuad), WindRule::NonZero);

    paintingContext.context.setShouldAntialias(wasAntialiased);
}

void BorderPainter::drawLineForBoxSide(PaintingContext& paintingContext, const FloatRect& rect, BoxSide side, Color color, BorderStyle borderStyle, float adjacentWidth1, float adjacentWidth2, bool antialias) const
{
    auto drawBorderRect = [&](const FloatRect& rect) {
        if (rect.isEmpty())
            return;
        paintingContext.context.drawRect(rect);
    };

    auto drawLineFor = [&](const FloatRect& rect, BoxSide side, BorderStyle borderStyle, const FloatSize& adjacent) {
        if (rect.isEmpty())
            return;
        drawLineForBoxSide(paintingContext, rect, side, color, borderStyle, adjacent.width(), adjacent.height(), antialias);
    };
    
    auto& edge = m_edges.at(side);

    const float deviceScaleFactor = paintingContext.deviceScaleFactor;
    float x1 = rect.x();
    float x2 = rect.maxX();
    float y1 = rect.y();
    float y2 = rect.maxY();
    float thickness;
    float length;
    if (side == BoxSide::Top || side == BoxSide::Bottom) {
        thickness = y2 - y1;
        length = x2 - x1;
    } else {
        thickness = x2 - x1;
        length = y2 - y1;
    }
    // FIXME: We really would like this check to be an ASSERT as we don't want to draw empty borders. However
    // nothing guarantees that the following recursive calls to drawLineForBoxSide will have non-null dimensions.
    if (!thickness || !length)
        return;

    switch (borderStyle) {
    case BorderStyle::None:
    case BorderStyle::Hidden:
        return;
    case BorderStyle::Dotted:
    case BorderStyle::Dashed: {
        bool wasAntialiased = paintingContext.context.shouldAntialias();
        StrokeStyle oldStrokeStyle = paintingContext.context.strokeStyle();
        paintingContext.context.setShouldAntialias(antialias);
        paintingContext.context.setStrokeColor(color);
        paintingContext.context.setStrokeThickness(thickness);
        paintingContext.context.setStrokeStyle(borderStyle == BorderStyle::Dashed ? DashedStroke : DottedStroke);
        paintingContext.context.drawLine({ x1, y1 }, { x2, y2 });
        paintingContext.context.setShouldAntialias(wasAntialiased);
        paintingContext.context.setStrokeStyle(oldStrokeStyle);
        break;
    }
    case BorderStyle::Double: {
        float thirdOfThickness = ceilToDevicePixel(thickness / 3, deviceScaleFactor);
        if (!adjacentWidth1 && !adjacentWidth2) {
            StrokeStyle oldStrokeStyle = paintingContext.context.strokeStyle();
            paintingContext.context.setStrokeStyle(NoStroke);
            paintingContext.context.setFillColor(color);

            bool wasAntialiased = paintingContext.context.shouldAntialias();
            paintingContext.context.setShouldAntialias(antialias);

            switch (side) {
            case BoxSide::Top:
                drawBorderRect({ x1, y1, length, edge.outerWidth() });
                drawBorderRect({ x1, y2 - edge.innerWidth(), length, edge.innerWidth() });
                break;
            case BoxSide::Bottom:
                drawBorderRect({ x1, y2 - edge.outerWidth(), length, edge.outerWidth() });
                drawBorderRect({ x1, y1, length, edge.innerWidth() });
                break;
            case BoxSide::Left:
                drawBorderRect({ x1, y1, edge.outerWidth(), length });
                drawBorderRect({ x2 - edge.innerWidth(), y1, edge.innerWidth(), length });
                break;
            case BoxSide::Right:
                drawBorderRect({ x2 - edge.outerWidth(), y1, edge.outerWidth(), length });
                drawBorderRect({ x1, y1, edge.innerWidth(), length });
                break;
            }

            paintingContext.context.setShouldAntialias(wasAntialiased);
            paintingContext.context.setStrokeStyle(oldStrokeStyle);
        } else {
            float adjacent1BigThird = ceilToDevicePixel(adjacentWidth1 / 3, deviceScaleFactor);
            float adjacent2BigThird = ceilToDevicePixel(adjacentWidth2 / 3, deviceScaleFactor);

            float offset1 = floorToDevicePixel(fabs(adjacentWidth1) * 2 / 3, deviceScaleFactor);
            float offset2 = floorToDevicePixel(fabs(adjacentWidth2) * 2 / 3, deviceScaleFactor);

            float mitreOffset1 = adjacentWidth1 < 0 ? offset1 : 0;
            float mitreOffset2 = adjacentWidth1 > 0 ? offset1 : 0;
            float mitreOffset3 = adjacentWidth2 < 0 ? offset2 : 0;
            float mitreOffset4 = adjacentWidth2 > 0 ? offset2 : 0;

            FloatRect paintBorderRect;
            switch (side) {
            case BoxSide::Top:
                paintBorderRect = snapRectToDevicePixels(LayoutRect(x1 + mitreOffset1, y1, (x2 - mitreOffset3) - (x1 + mitreOffset1), thirdOfThickness), deviceScaleFactor);
                drawLineFor(paintBorderRect, side, BorderStyle::Solid, FloatSize(adjacent1BigThird, adjacent2BigThird));

                paintBorderRect = snapRectToDevicePixels(LayoutRect(x1 + mitreOffset2, y2 - thirdOfThickness, (x2 - mitreOffset4) - (x1 + mitreOffset2), thirdOfThickness), deviceScaleFactor);
                drawLineFor(paintBorderRect, side, BorderStyle::Solid, FloatSize(adjacent1BigThird, adjacent2BigThird));
                break;
            case BoxSide::Left:
                paintBorderRect = snapRectToDevicePixels(LayoutRect(x1, y1 + mitreOffset1, thirdOfThickness, (y2 - mitreOffset3) - (y1 + mitreOffset1)), deviceScaleFactor);
                drawLineFor(paintBorderRect, side, BorderStyle::Solid, FloatSize(adjacent1BigThird, adjacent2BigThird));

                paintBorderRect = snapRectToDevicePixels(LayoutRect(x2 - thirdOfThickness, y1 + mitreOffset2, thirdOfThickness, (y2 - mitreOffset4) - (y1 + mitreOffset2)), deviceScaleFactor);
                drawLineFor(paintBorderRect, side, BorderStyle::Solid, FloatSize(adjacent1BigThird, adjacent2BigThird));
                break;
            case BoxSide::Bottom:
                paintBorderRect = snapRectToDevicePixels(LayoutRect(x1 + mitreOffset2, y1, (x2 - mitreOffset4) - (x1 + mitreOffset2), thirdOfThickness), deviceScaleFactor);
                drawLineFor(paintBorderRect, side, BorderStyle::Solid, FloatSize(adjacent1BigThird, adjacent2BigThird));

                paintBorderRect = snapRectToDevicePixels(LayoutRect(x1 + mitreOffset1, y2 - thirdOfThickness, (x2 - mitreOffset3) - (x1 + mitreOffset1), thirdOfThickness), deviceScaleFactor);
                drawLineFor(paintBorderRect, side, BorderStyle::Solid, FloatSize(adjacent1BigThird, adjacent2BigThird));
                break;
            case BoxSide::Right:
                paintBorderRect = snapRectToDevicePixels(LayoutRect(x1, y1 + mitreOffset2, thirdOfThickness, (y2 - mitreOffset4) - (y1 + mitreOffset2)), deviceScaleFactor);
                drawLineFor(paintBorderRect, side, BorderStyle::Solid, FloatSize(adjacent1BigThird, adjacent2BigThird));

                paintBorderRect = snapRectToDevicePixels(LayoutRect(x2 - thirdOfThickness, y1 + mitreOffset1, thirdOfThickness, (y2 - mitreOffset3) - (y1 + mitreOffset1)), deviceScaleFactor);
                drawLineFor(paintBorderRect, side, BorderStyle::Solid, FloatSize(adjacent1BigThird, adjacent2BigThird));
                break;
            }
        }
        break;
    }
    case BorderStyle::Ridge:
    case BorderStyle::Groove: {
        BorderStyle s1;
        BorderStyle s2;
        if (borderStyle == BorderStyle::Groove) {
            s1 = BorderStyle::Inset;
            s2 = BorderStyle::Outset;
        } else {
            s1 = BorderStyle::Outset;
            s2 = BorderStyle::Inset;
        }

        float adjacent1BigHalf = ceilToDevicePixel(adjacentWidth1 / 2, deviceScaleFactor);
        float adjacent2BigHalf = ceilToDevicePixel(adjacentWidth2 / 2, deviceScaleFactor);

        float adjacent1SmallHalf = floorToDevicePixel(adjacentWidth1 / 2, deviceScaleFactor);
        float adjacent2SmallHalf = floorToDevicePixel(adjacentWidth2 / 2, deviceScaleFactor);

        float offset1 = 0;
        float offset2 = 0;
        float offset3 = 0;
        float offset4 = 0;

        if (((side == BoxSide::Top || side == BoxSide::Left) && adjacentWidth1 < 0) || ((side == BoxSide::Bottom || side == BoxSide::Right) && adjacentWidth1 > 0))
            offset1 = floorToDevicePixel(adjacentWidth1 / 2, deviceScaleFactor);

        if (((side == BoxSide::Top || side == BoxSide::Left) && adjacentWidth2 < 0) || ((side == BoxSide::Bottom || side == BoxSide::Right) && adjacentWidth2 > 0))
            offset2 = ceilToDevicePixel(adjacentWidth2 / 2, deviceScaleFactor);

        if (((side == BoxSide::Top || side == BoxSide::Left) && adjacentWidth1 > 0) || ((side == BoxSide::Bottom || side == BoxSide::Right) && adjacentWidth1 < 0))
            offset3 = floorToDevicePixel(fabs(adjacentWidth1) / 2, deviceScaleFactor);

        if (((side == BoxSide::Top || side == BoxSide::Left) && adjacentWidth2 > 0) || ((side == BoxSide::Bottom || side == BoxSide::Right) && adjacentWidth2 < 0))
            offset4 = ceilToDevicePixel(adjacentWidth2 / 2, deviceScaleFactor);

        float adjustedX = ceilToDevicePixel((x1 + x2) / 2, deviceScaleFactor);
        float adjustedY = ceilToDevicePixel((y1 + y2) / 2, deviceScaleFactor);
        // Quads can't use the default snapping rect functions.
        x1 = roundToDevicePixel(x1, deviceScaleFactor);
        x2 = roundToDevicePixel(x2, deviceScaleFactor);
        y1 = roundToDevicePixel(y1, deviceScaleFactor);
        y2 = roundToDevicePixel(y2, deviceScaleFactor);

        switch (side) {
        case BoxSide::Top:
            drawLineFor(FloatRect(FloatPoint(x1 + offset1, y1), FloatPoint(x2 - offset2, adjustedY)), side, s1, FloatSize(adjacent1BigHalf, adjacent2BigHalf));
            drawLineFor(FloatRect(FloatPoint(x1 + offset3, adjustedY), FloatPoint(x2 - offset4, y2)), side, s2, FloatSize(adjacent1SmallHalf, adjacent2SmallHalf));
            break;
        case BoxSide::Left:
            drawLineFor(FloatRect(FloatPoint(x1, y1 + offset1), FloatPoint(adjustedX, y2 - offset2)), side, s1, FloatSize(adjacent1BigHalf, adjacent2BigHalf));
            drawLineFor(FloatRect(FloatPoint(adjustedX, y1 + offset3), FloatPoint(x2, y2 - offset4)), side, s2, FloatSize(adjacent1SmallHalf, adjacent2SmallHalf));
            break;
        case BoxSide::Bottom:
            drawLineFor(FloatRect(FloatPoint(x1 + offset1, y1), FloatPoint(x2 - offset2, adjustedY)), side, s2, FloatSize(adjacent1BigHalf, adjacent2BigHalf));
            drawLineFor(FloatRect(FloatPoint(x1 + offset3, adjustedY), FloatPoint(x2 - offset4, y2)), side, s1, FloatSize(adjacent1SmallHalf, adjacent2SmallHalf));
            break;
        case BoxSide::Right:
            drawLineFor(FloatRect(FloatPoint(x1, y1 + offset1), FloatPoint(adjustedX, y2 - offset2)), side, s2, FloatSize(adjacent1BigHalf, adjacent2BigHalf));
            drawLineFor(FloatRect(FloatPoint(adjustedX, y1 + offset3), FloatPoint(x2, y2 - offset4)), side, s1, FloatSize(adjacent1SmallHalf, adjacent2SmallHalf));
            break;
        }
        break;
    }
    case BorderStyle::Inset:
    case BorderStyle::Outset:
        calculateBorderStyleColor(borderStyle, side, color);
        FALLTHROUGH;
    case BorderStyle::Solid: {
        StrokeStyle oldStrokeStyle = paintingContext.context.strokeStyle();
        ASSERT(x2 >= x1);
        ASSERT(y2 >= y1);
        if (!adjacentWidth1 && !adjacentWidth2) {
            paintingContext.context.setStrokeStyle(NoStroke);
            paintingContext.context.setFillColor(color);
            bool wasAntialiased = paintingContext.context.shouldAntialias();
            paintingContext.context.setShouldAntialias(antialias);
            drawBorderRect(snapRectToDevicePixels(LayoutRect(x1, y1, x2 - x1, y2 - y1), deviceScaleFactor));
            paintingContext.context.setShouldAntialias(wasAntialiased);
            paintingContext.context.setStrokeStyle(oldStrokeStyle);
            return;
        }

        // FIXME: These roundings should be replaced by ASSERT(device pixel positioned) when all the callers have transitioned to device pixels.
        x1 = roundToDevicePixel(x1, deviceScaleFactor);
        y1 = roundToDevicePixel(y1, deviceScaleFactor);
        x2 = roundToDevicePixel(x2, deviceScaleFactor);
        y2 = roundToDevicePixel(y2, deviceScaleFactor);

        Vector<FloatPoint> quad;
        quad.reserveInitialCapacity(4);
        switch (side) {
        case BoxSide::Top:
            quad.uncheckedAppend({ x1 + std::max<float>(-adjacentWidth1, 0), y1 });
            quad.uncheckedAppend({ x1 + std::max<float>( adjacentWidth1, 0), y2 });
            quad.uncheckedAppend({ x2 - std::max<float>( adjacentWidth2, 0), y2 });
            quad.uncheckedAppend({ x2 - std::max<float>(-adjacentWidth2, 0), y1 });
            break;
        case BoxSide::Bottom:
            quad.uncheckedAppend({ x1 + std::max<float>( adjacentWidth1, 0), y1 });
            quad.uncheckedAppend({ x1 + std::max<float>(-adjacentWidth1, 0), y2 });
            quad.uncheckedAppend({ x2 - std::max<float>(-adjacentWidth2, 0), y2 });
            quad.uncheckedAppend({ x2 - std::max<float>( adjacentWidth2, 0), y1 });
            break;
        case BoxSide::Left:
            quad.uncheckedAppend({ x1, y1 + std::max<float>(-adjacentWidth1, 0) });
            quad.uncheckedAppend({ x1, y2 - std::max<float>(-adjacentWidth2, 0) });
            quad.uncheckedAppend({ x2, y2 - std::max<float>( adjacentWidth2, 0) });
            quad.uncheckedAppend({ x2, y1 + std::max<float>( adjacentWidth1, 0) });
            break;
        case BoxSide::Right:
            quad.uncheckedAppend({ x1, y1 + std::max<float>( adjacentWidth1, 0) });
            quad.uncheckedAppend({ x1, y2 - std::max<float>( adjacentWidth2, 0) });
            quad.uncheckedAppend({ x2, y2 - std::max<float>(-adjacentWidth2, 0) });
            quad.uncheckedAppend({ x2, y1 + std::max<float>(-adjacentWidth1, 0) });
            break;
        }

        paintingContext.context.setStrokeStyle(NoStroke);
        paintingContext.context.setFillColor(color);
        bool wasAntialiased = paintingContext.context.shouldAntialias();
        paintingContext.context.setShouldAntialias(antialias);
        paintingContext.context.fillPath(Path::polygonPathFromPoints(quad));
        paintingContext.context.setShouldAntialias(wasAntialiased);

        paintingContext.context.setStrokeStyle(oldStrokeStyle);
        break;
    }
    }
}

void BorderPainter::paintOneBorderSide(PaintingContext& paintingContext, const FloatRoundedRect& outerBorder, const FloatRoundedRect& innerBorder, const FloatRect& sideRect, BoxSide side, const Path* path, bool antialias, const Color* overrideColor) const
{
    auto& edgeToRender = m_edges.at(side);
    ASSERT(edgeToRender.widthForPainting());
    
    auto adjacentSides = adjacentSidesForSide(side);
    
    auto& adjacentEdge1 = m_edges.at(adjacentSides.first);
    auto& adjacentEdge2 = m_edges.at(adjacentSides.second);

    bool mitreAdjacentSide1 = joinRequiresMitre(side, adjacentSides.first, !antialias);
    bool mitreAdjacentSide2 = joinRequiresMitre(side, adjacentSides.second, !antialias);
    
    bool adjacentSide1StylesMatch = colorsMatchAtCorner(side, adjacentSides.first);
    bool adjacentSide2StylesMatch = colorsMatchAtCorner(side, adjacentSides.second);

    const Color& colorToPaint = overrideColor ? *overrideColor : edgeToRender.color();

    if (path) {
        GraphicsContextStateSaver stateSaver(paintingContext.context);

        clipBorderSidePolygon(paintingContext, outerBorder, innerBorder, side, adjacentSide1StylesMatch, adjacentSide2StylesMatch);

        if (!innerBorder.isRenderable())
            paintingContext.context.clipOutRoundedRect(FloatRoundedRect(calculateAdjustedInnerBorder(innerBorder, side)));

        float thickness = std::max(std::max(edgeToRender.widthForPainting(), adjacentEdge1.widthForPainting()), adjacentEdge2.widthForPainting());
        drawBoxSideFromPath(paintingContext, outerBorder.rect(), *path, edgeToRender.widthForPainting(), thickness, side, colorToPaint, edgeToRender.style());
        return;
    }

    bool clipForStyle = styleRequiresClipPolygon(edgeToRender.style()) && (mitreAdjacentSide1 || mitreAdjacentSide2);
    bool clipAdjacentSide1 = colorNeedsAntiAliasAtCorner(side, adjacentSides.first) && mitreAdjacentSide1;
    bool clipAdjacentSide2 = colorNeedsAntiAliasAtCorner(side, adjacentSides.second) && mitreAdjacentSide2;
    bool shouldClip = clipForStyle || clipAdjacentSide1 || clipAdjacentSide2;
    
    GraphicsContextStateSaver clipStateSaver(paintingContext.context, shouldClip);
    if (shouldClip) {
        bool aliasAdjacentSide1 = clipAdjacentSide1 || (clipForStyle && mitreAdjacentSide1);
        bool aliasAdjacentSide2 = clipAdjacentSide2 || (clipForStyle && mitreAdjacentSide2);
        clipBorderSidePolygon(paintingContext, outerBorder, innerBorder, side, !aliasAdjacentSide1, !aliasAdjacentSide2);
        // Since we clipped, no need to draw with a mitre.
        mitreAdjacentSide1 = false;
        mitreAdjacentSide2 = false;
    }
    drawLineForBoxSide(paintingContext, sideRect, side, colorToPaint, edgeToRender.style(), mitreAdjacentSide1 ? adjacentEdge1.widthForPainting() : 0, mitreAdjacentSide2 ? adjacentEdge2.widthForPainting() : 0, antialias);
}

void BorderPainter::paintBorderSides(PaintingContext& paintingContext, const FloatRoundedRect& outerBorder, const FloatRoundedRect& innerBorder, FloatSize innerBorderBleedAdjustment, BoxSideSet edgeSet, bool antialias, const Color* overrideColor) const
{
    bool renderRadii = outerBorder.isRounded();

    Path roundedPath;
    if (renderRadii)
        roundedPath.addRoundedRect(outerBorder);

    auto paintOneSide = [&](BoxSide side) {
        auto& edge = m_edges.at(side);
        if (!edge.shouldRender() || !edgeSet.contains(edgeFlagForSide(side)))
            return;

        auto sideRect = outerBorder.rect();
        FloatSize firstRadius;
        FloatSize secondRadius;

        switch (side) {
        case BoxSide::Top:
            sideRect.setHeight(edge.widthForPainting() + innerBorderBleedAdjustment.height());
            firstRadius = innerBorder.radii().topLeft();
            secondRadius = innerBorder.radii().topRight();
            break;
        case BoxSide::Right:
            sideRect.shiftXEdgeTo(sideRect.maxX() - edge.widthForPainting() - innerBorderBleedAdjustment.width());
            firstRadius = innerBorder.radii().bottomRight();
            secondRadius = innerBorder.radii().topRight();
            break;
        case BoxSide::Bottom:
            sideRect.shiftYEdgeTo(sideRect.maxY() - edge.widthForPainting() - innerBorderBleedAdjustment.height());
            firstRadius = innerBorder.radii().bottomLeft();
            secondRadius = innerBorder.radii().bottomRight();
            break;
        case BoxSide::Left:
            sideRect.setWidth(edge.widthForPainting() + innerBorderBleedAdjustment.width());
            firstRadius = innerBorder.radii().bottomLeft();
            secondRadius = innerBorder.radii().topLeft();
            break;
        }

        bool usePath = renderRadii && (borderStyleHasInnerDetail(edge.style()) || borderWillArcInnerEdge(firstRadius, secondRadius));
        paintOneBorderSide(paintingContext, outerBorder, innerBorder, sideRect, side, usePath ? &roundedPath : nullptr, antialias, overrideColor);
    };

    paintOneSide(BoxSide::Top);
    paintOneSide(BoxSide::Bottom);
    paintOneSide(BoxSide::Left);
    paintOneSide(BoxSide::Right);
}

void BorderPainter::paintTranslucentBorderSides(PaintingContext& paintingContext, const FloatRoundedRect& outerBorder, const FloatRoundedRect& innerBorder, FloatSize innerBorderBleedAdjustment, BoxSideSet edgesToDraw, bool antialias) const
{
    // willBeOverdrawn assumes that we draw in order: top, bottom, left, right.
    // This is different from BoxSide enum order.
    static constexpr std::array<BoxSide, 4> paintOrderSides = { BoxSide::Top, BoxSide::Bottom, BoxSide::Left, BoxSide::Right };

    while (edgesToDraw) {
        // Find undrawn edges sharing a color.
        Color commonColor;
        
        BoxSideSet commonColorEdgeSet;
        for (auto side : paintOrderSides) {
            if (!edgesToDraw.contains(edgeFlagForSide(side)))
                continue;

            auto& edge = m_edges.at(side);
            bool includeEdge;
            if (commonColorEdgeSet.isEmpty()) {
                commonColor = edge.color();
                includeEdge = true;
            } else
                includeEdge = edge.color() == commonColor;

            if (includeEdge)
                commonColorEdgeSet.add(edgeFlagForSide(side));
        }

        bool useTransparencyLayer = includesAdjacentEdges(commonColorEdgeSet) && !commonColor.isOpaque();
        {
            auto transparencyScope = TransparencyLayerScope { paintingContext.context, commonColor.alphaAsFloat(), useTransparencyLayer };
            if (useTransparencyLayer)
                commonColor = commonColor.opaqueColor();

            paintBorderSides(paintingContext, outerBorder, innerBorder, innerBorderBleedAdjustment, commonColorEdgeSet, antialias, &commonColor);
        }
        
        edgesToDraw.remove(commonColorEdgeSet);
    }
}

static FloatRect shrinkRectByOneDevicePixel(const PaintingContext& paintingContext, const FloatRect& rect)
{
    auto shrunkRect = rect;
    auto transform = paintingContext.context.getCTM();
    shrunkRect.inflateX(-ceilToDevicePixel(1.0f / transform.xScale(), paintingContext.deviceScaleFactor));
    shrunkRect.inflateY(-ceilToDevicePixel(1.0f / transform.yScale(), paintingContext.deviceScaleFactor));
    return shrunkRect;
}

FloatRect BorderPainter::borderInnerRectAdjustedForBleedAvoidance(const PaintingContext& paintingContext) const
{
    if (m_bleedAvoidance != BackgroundBleedAvoidance::BackgroundOverBorder)
        return m_borderRect.rect();

    // We shrink the rectangle by one device pixel on each side to make it fully overlap the anti-aliased background border
    return shrinkRectByOneDevicePixel(paintingContext, m_borderRect.rect());
}

void BorderPainter::paintBorders(PaintingContext& paintingContext) const
{
    bool haveAlphaColor = false;
    bool haveAllSolidEdges = true;
    bool haveAllDoubleEdges = true;
    int numEdgesVisible = 4;
    bool allEdgesShareColor = true;
    std::optional<BoxSide> firstVisibleSide;
    BoxSideSet edgesToDraw;

    for (auto side : allBoxSides) {
        auto& currEdge = m_edges.at(side);

        if (currEdge.shouldRender())
            edgesToDraw.add(edgeFlagForSide(side));

        if (currEdge.presentButInvisible()) {
            --numEdgesVisible;
            allEdgesShareColor = false;
            continue;
        }
        
        if (!currEdge.widthForPainting()) {
            --numEdgesVisible;
            continue;
        }

        if (!firstVisibleSide)
            firstVisibleSide = side;
        else if (currEdge.color() != m_edges.at(*firstVisibleSide).color())
            allEdgesShareColor = false;

        if (!currEdge.color().isOpaque())
            haveAlphaColor = true;
        
        if (currEdge.style() != BorderStyle::Solid)
            haveAllSolidEdges = false;

        if (currEdge.style() != BorderStyle::Double)
            haveAllDoubleEdges = false;
    }

    FloatRoundedRect innerBorderRect = roundedInsetBorderForRect(borderInnerRectAdjustedForBleedAvoidance(paintingContext), m_borderRect.radii(), borderWidths(m_edges), m_includeLeftEdge, m_includeRightEdge);

    // FIXME: If no corner intersects the clip region, we can pretend outerBorder is rectangular to improve performance.
    
    if ((haveAllSolidEdges || haveAllDoubleEdges) && allEdgesShareColor && innerBorderRect.isRenderable()) {
        // Fast path for drawing all solid edges and all unrounded double edges
        if (numEdgesVisible == 4 && (m_borderRect.isRounded() || haveAlphaColor) && (haveAllSolidEdges || (!m_borderRect.isRounded() && !innerBorderRect.isRounded()))) {
            Path path;
            
            if (m_borderRect.isRounded() && m_bleedAvoidance != BackgroundBleedAvoidance::UseTransparencyLayer)
                path.addRoundedRect(m_borderRect);
            else
                path.addRect(m_borderRect.rect());

            if (haveAllDoubleEdges) {
                auto innerThirdRect = m_borderRect.rect();
                auto outerThirdRect = m_borderRect.rect();

                for (auto side : allBoxSides) {
                    auto& edge = m_edges.at(side);
                    float outerWidth = edge.outerWidth();
                    float innerWidth = edge.innerWidth();
                    switch (side) {
                    case BoxSide::Top:
                        innerThirdRect.shiftYEdgeTo(innerThirdRect.y() + innerWidth);
                        outerThirdRect.shiftYEdgeTo(outerThirdRect.y() + outerWidth);
                        break;
                    case BoxSide::Right:
                        innerThirdRect.setWidth(innerThirdRect.width() - innerWidth);
                        outerThirdRect.setWidth(outerThirdRect.width() - outerWidth);
                        break;
                    case BoxSide::Bottom:
                        innerThirdRect.setHeight(innerThirdRect.height() - innerWidth);
                        outerThirdRect.setHeight(outerThirdRect.height() - outerWidth);
                        break;
                    case BoxSide::Left:
                        innerThirdRect.shiftXEdgeTo(innerThirdRect.x() + innerWidth);
                        outerThirdRect.shiftXEdgeTo(outerThirdRect.x() + outerWidth);
                        break;
                    }
                }

                auto outerThirdRoundedRect = m_borderRect;
                outerThirdRoundedRect.setRect(outerThirdRect);

                if (outerThirdRoundedRect.isRounded() && m_bleedAvoidance != BackgroundBleedAvoidance::UseTransparencyLayer)
                    path.addRoundedRect(outerThirdRoundedRect);
                else
                    path.addRect(outerThirdRoundedRect.rect());

                auto innerThirdRoundedRect = innerBorderRect;
                innerThirdRoundedRect.setRect(innerThirdRect);
                if (innerThirdRoundedRect.isRounded())
                    path.addRoundedRect(innerThirdRoundedRect);
                else
                    path.addRect(innerThirdRoundedRect.rect());
            }

            if (innerBorderRect.isRounded())
                path.addRoundedRect(innerBorderRect);
            else
                path.addRect(innerBorderRect.rect());
            
            paintingContext.context.setFillRule(WindRule::EvenOdd);
            paintingContext.context.setFillColor(m_edges.top().color());
            paintingContext.context.fillPath(path);
            return;
        }

        // Avoid creating transparent layers
        if (haveAllSolidEdges && numEdgesVisible != 4 && !m_borderRect.isRounded() && haveAlphaColor) {
            Path path;

            auto calculateSideRect = [&](const BorderEdge& edge, BoxSide side) {
                auto sideRect = m_borderRect.rect();
                auto width = edge.widthForPainting();

                switch (side) {
                case BoxSide::Top:
                    sideRect.setHeight(width);
                    break;
                case BoxSide::Right:
                    sideRect.shiftXEdgeTo(sideRect.maxX() - width);
                    break;
                case BoxSide::Bottom:
                    sideRect.shiftYEdgeTo(sideRect.maxY() - width);
                    break;
                case BoxSide::Left:
                    sideRect.setWidth(width);
                    break;
                }

                return sideRect;
            };

            for (auto side : allBoxSides) {
                auto& edge = m_edges.at(side);
                if (edge.shouldRender()) {
                    auto sideRect = calculateSideRect(edge, side);
                    path.addRect(sideRect);
                }
            }

            paintingContext.context.setFillRule(WindRule::NonZero);
            paintingContext.context.setFillColor(m_edges.at(*firstVisibleSide).color());
            paintingContext.context.fillPath(path);
            return;
        }
    }

    bool clipToOuterBorder = m_borderRect.isRounded();
    GraphicsContextStateSaver stateSaver(paintingContext.context, clipToOuterBorder);
    if (clipToOuterBorder) {
        // Clip to the inner and outer radii rects.
        if (m_bleedAvoidance != BackgroundBleedAvoidance::UseTransparencyLayer)
            paintingContext.context.clipRoundedRect(m_borderRect);

        if (innerBorderRect.isRenderable())
            paintingContext.context.clipOutRoundedRect(innerBorderRect);
    }

    bool shouldAntialiasLines = !paintingContext.context.getCTM().isIdentityOrTranslationOrFlipped();

    // If only one edge visible antialiasing doesn't create seams
    bool antialias = shouldAntialiasLines || numEdgesVisible == 1;

    auto unadjustedInnerBorder = innerBorderRect;
    FloatSize innerBorderBleedAdjustment;
    if (m_bleedAvoidance == BackgroundBleedAvoidance::BackgroundOverBorder) {
        unadjustedInnerBorder = roundedInsetBorderForRect(m_borderRect.rect(), m_borderRect.radii(), borderWidths(m_edges), m_includeLeftEdge, m_includeRightEdge);
        innerBorderBleedAdjustment = innerBorderRect.rect().location() - unadjustedInnerBorder.rect().location();
    }

    if (haveAlphaColor)
        paintTranslucentBorderSides(paintingContext, m_borderRect, innerBorderRect, innerBorderBleedAdjustment, edgesToDraw, antialias); // FIXME.
    else
        paintBorderSides(paintingContext, m_borderRect, innerBorderRect, innerBorderBleedAdjustment, edgesToDraw, antialias);
}

BoxDecorationPainter::BoxDecorationPainter(const BoxModelBox& box, PaintingContext& paintingContext, bool includeLeftEdge, bool includeRightEdge)
    : m_box(box)
    , m_borderRect(box.borderRoundedRect())
    , m_bleedAvoidance(determineBackgroundBleedAvoidance(box, paintingContext))
    , m_includeLeftEdge(includeLeftEdge)
    , m_includeRightEdge(includeRightEdge)
{
}

void BoxDecorationPainter::paintBorders(PaintingContext& paintingContext) const
{
    auto* boxDecorationData = m_box.boxDecorationData();
    if (!boxDecorationData)
        return;

    if (boxDecorationData->hasBorderImage()) {
        // border-image is not affected by border-radius.
        // FIXME: Implement border-image painting.
        return;
    }

    auto outerBorder = borderRoundedRect();
    BorderPainter painter(boxDecorationData->borderEdges(), outerBorder, m_bleedAvoidance, m_includeLeftEdge, m_includeRightEdge);
    painter.paintBorders(paintingContext);
}

void BoxDecorationPainter::paintFillLayer(PaintingContext& paintingContext, const FillLayer& layer, const FillLayerImageGeometry& geometry) const
{
    GraphicsContextStateSaver stateSaver(paintingContext.context, false);

    auto clipRectForLayer = [](const BoxModelBox& box, const FillLayer& layer) -> UnadjustedAbsoluteFloatRect {
        switch (layer.clip()) {
        case FillBox::Border:
            return box.absoluteBorderBoxRect();
        case FillBox::Padding:
            return box.absolutePaddingBoxRect();
        case FillBox::Content:
            return box.absoluteContentBoxRect();
        case FillBox::Text:
        case FillBox::NoClip:
            break;
        }
        return { };
    };

    switch (layer.clip()) {
    case FillBox::Border:
    case FillBox::Padding:
    case FillBox::Content: {
        stateSaver.save();
        paintingContext.context.clip(clipRectForLayer(m_box, layer));
        break;
    }
    case FillBox::Text:
    case FillBox::NoClip:
        break;
    }

    // FIXME: Handle background compositing modes.

    auto* backgroundImage = layer.image();
    CompositeOperator op = CompositeOperator::SourceOver;

    if (geometry.destRect().isEmpty())
        return;

    auto image = backgroundImage->image(nullptr, geometry.tileSize());
    if (!image)
        return;

    // FIXME: call image->updateFromSettings().

    ImagePaintingOptions options = {
        op == CompositeOperator::SourceOver ? layer.composite() : op,
        layer.blendMode(),
        DecodingMode::Synchronous,
        ImageOrientation::FromImage,
        InterpolationQuality::Default
    };

    paintingContext.context.drawTiledImage(*image, geometry.destRect(), toFloatPoint(geometry.relativePhase()), geometry.tileSize(), geometry.spaceSize(), options);
}

void BoxDecorationPainter::paintBoxShadow(PaintingContext& paintingContext, ShadowStyle shadowStyle) const
{
    if (!m_box.style().boxShadow())
        return;

    auto borderRect = shadowStyle == ShadowStyle::Inset ? innerBorderRoundedRect() : borderRoundedRect();
    auto* boxDecorationData = m_box.boxDecorationData();
    bool hasBorderRadius = m_box.hasBorderRadius();

    bool hasOpaqueBackground = m_box.style().backgroundColor().isOpaque();

    auto paintNormalShadow = [&](const ShadowData& shadow) {
        // FIXME: Snapping here isn't ideal. It would be better to compute a rect which is border rect + offset + spread, and snap that at tree building time.
        auto shadowOffset = roundSizeToDevicePixels({ shadow.x().value(), shadow.y().value() }, paintingContext.deviceScaleFactor);
        float shadowPaintingExtent = ceilToDevicePixel(shadow.paintingExtent(), paintingContext.deviceScaleFactor);
        float shadowSpread = roundToDevicePixel(shadow.spread().value(), paintingContext.deviceScaleFactor);
        auto shadowRadius = shadow.radius();

        auto fillRect = borderRect;
        fillRect.inflate(shadowSpread);
        if (fillRect.isEmpty())
            return;

        auto shadowRect = borderRect.rect();
        shadowRect.inflate(shadowPaintingExtent + shadowSpread);
        shadowRect.move(shadowOffset);

        GraphicsContextStateSaver stateSaver(paintingContext.context);
        paintingContext.context.clip(shadowRect);

        // Move the fill just outside the clip, adding at least 1 pixel of separation so that the fill does not
        // bleed in (due to antialiasing) if the context is transformed.
        float xOffset = shadowRect.width() + std::max<float>(0, shadowOffset.width()) + shadowPaintingExtent + 2 * shadowSpread + 1.0f;
        auto extraOffset = FloatSize { std::ceil(xOffset), 0 };
        shadowOffset -= extraOffset;
        fillRect.move(extraOffset);

        auto rectToClipOut = borderRect;
        auto adjustedFillRect = fillRect;

        auto shadowRectOrigin = fillRect.rect().location() + shadowOffset;
        auto adjustedShadowOffset = shadowRectOrigin - adjustedFillRect.rect().location();

        paintingContext.context.setShadow(adjustedShadowOffset, shadowRadius.value(), shadow.color(), shadow.isWebkitBoxShadow() ? ShadowRadiusMode::Legacy : ShadowRadiusMode::Default);

        if (hasBorderRadius) {
            // If the box is opaque, it is unnecessary to clip it out. However, doing so saves time
            // when painting the shadow. On the other hand, it introduces subpixel gaps along the
            // corners. Those are avoided by insetting the clipping path by one pixel.
            if (hasOpaqueBackground)
                rectToClipOut.inflateWithRadii(-1.0f);

            if (!rectToClipOut.isEmpty())
                paintingContext.context.clipOutRoundedRect(rectToClipOut);

            auto influenceRect = FloatRoundedRect { shadowRect, borderRect.radii() };
            influenceRect.expandRadii(2 * shadowPaintingExtent + shadowSpread);

            // FIXME: Optimize for clipped-out corners
            adjustedFillRect.expandRadii(shadowSpread);
            if (!adjustedFillRect.isRenderable())
                adjustedFillRect.adjustRadii();
            paintingContext.context.fillRoundedRect(adjustedFillRect, Color::black);
        } else {
            // If the box is opaque, it is unnecessary to clip it out. However, doing so saves time
            // when painting the shadow. On the other hand, it introduces subpixel gaps along the
            // edges if they are not pixel-aligned. Those are avoided by insetting the clipping path
            // by one pixel.
            if (hasOpaqueBackground) {
                // FIXME: The function to decide on the policy based on the transform should be a named function.
                // FIXME: It's not clear if this check is right. What about integral scale factors?
                AffineTransform transform = paintingContext.context.getCTM();
                if (transform.a() != 1 || (transform.d() != 1 && transform.d() != -1) || transform.b() || transform.c())
                    rectToClipOut.inflate(-1.0f);
            }

            if (!rectToClipOut.isEmpty())
                paintingContext.context.clipOut(rectToClipOut.rect());

            paintingContext.context.fillRect(adjustedFillRect.rect(), Color::black);
        }
    };

    auto paintInsetShadow = [&](const ShadowData& shadow) {
        auto shadowOffset = roundSizeToDevicePixels({ shadow.x().value(), shadow.y().value() }, paintingContext.deviceScaleFactor);
        float shadowPaintingExtent = ceilToDevicePixel(shadow.paintingExtent(), paintingContext.deviceScaleFactor);
        float shadowSpread = roundToDevicePixel(shadow.spread().value(), paintingContext.deviceScaleFactor);
        auto shadowRadius = shadow.radius();

        auto holeRect = borderRect.rect();
        holeRect.inflate(-shadowSpread);

        if (!m_includeLeftEdge) {
            // FIXME: Need to take writing mode into account.
            holeRect.shiftXEdgeBy(-(std::max<float>(shadowOffset.width(), 0) + shadowPaintingExtent + shadowSpread));
        }

        if (!m_includeRightEdge) {
            // FIXME: Need to take writing mode into account.
            holeRect.setWidth(holeRect.width() - std::min<float>(shadowOffset.width(), 0) + shadowPaintingExtent + shadowSpread);
        }

        auto roundedHoleRect = FloatRoundedRect { holeRect, borderRect.radii() };
        if (shadowSpread && roundedHoleRect.isRounded()) {
            auto roundedRectCorrectingForSpread = [&]() {
                bool horizontal = true; // FIXME: Handle writing modes.
                auto borderWidth = borderWidths(boxDecorationData->borderEdges());

                float leftWidth { (!horizontal || m_includeLeftEdge) ? borderWidth.left() + shadowSpread : 0 };
                float rightWidth { (!horizontal || m_includeRightEdge) ? borderWidth.right() + shadowSpread : 0 };
                float topWidth { (horizontal || m_includeLeftEdge) ? borderWidth.top() + shadowSpread : 0 };
                float bottomWidth { (horizontal || m_includeRightEdge) ? borderWidth.bottom() + shadowSpread : 0 };

                return roundedInsetBorderForRect(m_borderRect.rect(), m_borderRect.radii(), { topWidth, rightWidth, bottomWidth, leftWidth }, m_includeLeftEdge, m_includeRightEdge);
            }();
            roundedHoleRect.setRadii(roundedRectCorrectingForSpread.radii());
        }

        if (roundedHoleRect.isEmpty()) {
            if (hasBorderRadius)
                paintingContext.context.fillRoundedRect(borderRect, shadow.color());
            else
                paintingContext.context.fillRect(borderRect.rect(), shadow.color());
            return;
        }

        auto areaCastingShadowInHole = [](const FloatRect& holeRect, float shadowExtent, float shadowSpread, FloatSize shadowOffset) {
            auto bounds(holeRect);
            
            bounds.inflate(shadowExtent);

            if (shadowSpread < 0)
                bounds.inflate(-shadowSpread);
            
            auto offsetBounds = bounds;
            offsetBounds.move(-shadowOffset);
            return unionRect(bounds, offsetBounds);
        };

        Color fillColor = shadow.color().opaqueColor();
        auto shadowCastingRect = areaCastingShadowInHole(borderRect.rect(), shadowPaintingExtent, shadowSpread, shadowOffset);

        GraphicsContextStateSaver stateSaver(paintingContext.context);
        if (hasBorderRadius)
            paintingContext.context.clipRoundedRect(borderRect);
        else
            paintingContext.context.clip(borderRect.rect());

        float xOffset = shadowCastingRect.width() + std::max<float>(0, shadowOffset.width()) + shadowPaintingExtent - 2 * shadowSpread + 1.0f;
        auto extraOffset = FloatSize { std::ceil(xOffset), 0 };

        paintingContext.context.translate(extraOffset);
        shadowOffset -= extraOffset;

        paintingContext.context.setShadow(shadowOffset, shadowRadius.value(), shadow.color(), shadow.isWebkitBoxShadow() ? ShadowRadiusMode::Legacy : ShadowRadiusMode::Default);
        paintingContext.context.fillRectWithRoundedHole(shadowCastingRect, roundedHoleRect, fillColor);
    };


    for (auto* shadow = m_box.style().boxShadow(); shadow; shadow = shadow->next()) {
        if (shadow->style() != shadowStyle)
            continue;

        LayoutSize shadowOffset(shadow->x().value(), shadow->y().value());
        if (shadowOffset.isZero() && shadow->radius().isZero() && shadow->spread().isZero())
            continue;

        if (shadow->style() == ShadowStyle::Normal)
            paintNormalShadow(*shadow);
        else
            paintInsetShadow(*shadow);
    }
}

void BoxDecorationPainter::paintBackgroundImages(PaintingContext& paintingContext) const
{
    const auto& style = m_box.style();

    Vector<const FillLayer*, 8> layers;

    for (auto* layer = style.backgroundLayers(); layer; layer = layer->next())
        layers.append(layer);

    auto* boxDecorationData = m_box.boxDecorationData();
    ASSERT(boxDecorationData);

    auto& layerGeometryList = boxDecorationData->backgroundImageGeometry();

    for (int i = layers.size() - 1; i >=0; --i) {
        const auto* layer = layers[i];
        const auto& geometry = layerGeometryList[i];
        paintFillLayer(paintingContext, *layer, geometry);
    }
}

FloatRoundedRect BoxDecorationPainter::innerBorderRoundedRect() const
{
    return m_box.innerBorderRoundedRect();
}

FloatRoundedRect BoxDecorationPainter::backgroundRoundedRectAdjustedForBleedAvoidance(const PaintingContext& paintingContext) const
{
    if (m_bleedAvoidance == BackgroundBleedAvoidance::ShrinkBackground) {
        // We shrink the rectangle by one device pixel on each side because the bleed is one pixel maximum.
        return roundedRectWithIncludedRadii(shrinkRectByOneDevicePixel(paintingContext, m_borderRect.rect()), m_borderRect.radii(), m_includeLeftEdge, m_includeRightEdge);
    }

    if (m_bleedAvoidance == BackgroundBleedAvoidance::BackgroundOverBorder)
        return innerBorderRoundedRect();

    return roundedRectWithIncludedRadii(m_borderRect.rect(), m_borderRect.radii(), m_includeLeftEdge, m_includeRightEdge);
}

void BoxDecorationPainter::paintBackground(PaintingContext& paintingContext) const
{
    auto borderBoxRect = m_box.absoluteBorderBoxRect();
    const auto& style = m_box.style();

    if (style.hasBackground()) {
        GraphicsContextStateSaver stateSaver(paintingContext.context, false);
        if (m_bleedAvoidance != BackgroundBleedAvoidance::UseTransparencyLayer && m_box.hasBorderRadius()) {
            stateSaver.save();
            auto outerBorder = backgroundRoundedRectAdjustedForBleedAvoidance(paintingContext);
            paintingContext.context.clipRoundedRect(outerBorder);
        }
    
        paintingContext.context.fillRect(borderBoxRect, style.backgroundColor());

        if (style.hasBackgroundImage())
            paintBackgroundImages(paintingContext);
    }
}

BackgroundBleedAvoidance BoxDecorationPainter::determineBackgroundBleedAvoidance(const BoxModelBox& box, PaintingContext& paintingContext)
{
    if (paintingContext.context.paintingDisabled())
        return BackgroundBleedAvoidance::None;

    auto& style = box.style();
    auto* boxDecorationData = box.boxDecorationData();
    
    auto hasBackgroundAndRoundedBorder = [&] {
        if (!boxDecorationData)
            return false;

        // FIXME: Consult border-image.
        return style.hasBackground() && boxDecorationData->hasBorder() && box.hasBorderRadius();
    };

    if (!hasBackgroundAndRoundedBorder())
        return BackgroundBleedAvoidance::None;

    auto ctm = paintingContext.context.getCTM();
    auto contextScaling = FloatSize { static_cast<float>(ctm.xScale()), static_cast<float>(ctm.yScale()) };
    if (boxDecorationData->borderObscuresBackgroundEdge(contextScaling))
        return BackgroundBleedAvoidance::ShrinkBackground;

    if (boxDecorationData->borderObscuresBackground() && style.backgroundHasOpaqueTopLayer())
        return BackgroundBleedAvoidance::BackgroundOverBorder;

    return BackgroundBleedAvoidance::UseTransparencyLayer;
}

void BoxDecorationPainter::paintBackgroundAndBorders(PaintingContext& paintingContext) const
{
    // FIXME: Table decoration painting is special.
    
    switch (m_bleedAvoidance) {
    case BackgroundBleedAvoidance::BackgroundOverBorder:
        paintBoxShadow(paintingContext, ShadowStyle::Normal);
        paintBorders(paintingContext);
        paintBackground(paintingContext);
        paintBoxShadow(paintingContext, ShadowStyle::Inset);
        break;

    case BackgroundBleedAvoidance::UseTransparencyLayer: {
        paintBoxShadow(paintingContext, ShadowStyle::Normal);
        GraphicsContextStateSaver stateSaver(paintingContext.context);
        auto outerBorder = borderRoundedRect();
        paintingContext.context.clipRoundedRect(outerBorder);
        paintingContext.context.beginTransparencyLayer(1);

        paintBackground(paintingContext);
        paintBoxShadow(paintingContext, ShadowStyle::Inset);
        paintBorders(paintingContext);

        paintingContext.context.endTransparencyLayer();
        break;
    }
    
    case BackgroundBleedAvoidance::ShrinkBackground:
    case BackgroundBleedAvoidance::None:
        paintBoxShadow(paintingContext, ShadowStyle::Normal);
        paintBackground(paintingContext);
        paintBoxShadow(paintingContext, ShadowStyle::Inset);
        paintBorders(paintingContext);
        break;
    }
}

} // namespace Display
} // namespace WebCore

#endif // ENABLE(LAYOUT_FORMATTING_CONTEXT)
