Title: [282959] trunk/Source/WebCore
Revision
282959
Author
[email protected]
Date
2021-09-23 07:11:56 -0700 (Thu, 23 Sep 2021)

Log Message

Factor LegacyInlineFlowBox painting into a class
https://bugs.webkit.org/show_bug.cgi?id=230683

Reviewed by Alan Bujtas.

Introduce InlineBoxPainter, similar to TextBoxPainter.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* rendering/InlineBoxPainter.cpp: Added.
(WebCore::InlineBoxPainter::InlineBoxPainter):
(WebCore::InlineBoxPainter::paint):
(WebCore::clipRectForNinePieceImageStrip):
(WebCore::InlineBoxPainter::paintMask):
(WebCore::InlineBoxPainter::paintDecorations):
(WebCore::InlineBoxPainter::style const):
(WebCore::InlineBoxPainter::constrainToLineTopAndBottomIfNeeded const):
(WebCore::InlineBoxPainter::paintFillLayers):
(WebCore::InlineBoxPainter::paintFillLayer):
(WebCore::InlineBoxPainter::paintBoxShadow):
* rendering/InlineBoxPainter.h: Added.
(WebCore::InlineBoxPainter::renderer const):
(WebCore::InlineBoxPainter::isHorizontal const):
* rendering/LegacyInlineFlowBox.cpp:
(WebCore::LegacyInlineFlowBox::paint):
(WebCore::LegacyInlineFlowBox::paintFillLayers): Deleted.
(WebCore::LegacyInlineFlowBox::paintFillLayer): Deleted.
(WebCore::LegacyInlineFlowBox::paintBoxShadow): Deleted.
(WebCore::LegacyInlineFlowBox::constrainToLineTopAndBottomIfNeeded const): Deleted.
(WebCore::clipRectForNinePieceImageStrip): Deleted.
(WebCore::LegacyInlineFlowBox::paintBoxDecorations): Deleted.
(WebCore::LegacyInlineFlowBox::paintMask): Deleted.
* rendering/LegacyInlineFlowBox.h:
* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::getBackgroundRoundedRect const):
(WebCore::RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance const):
(WebCore::RenderBoxModelObject::paintMaskForTextFillBox):
(WebCore::RenderBoxModelObject::paintFillLayerExtended):
(WebCore::RenderBoxModelObject::boxShadowShouldBeAppliedToBackground const):
* rendering/RenderBoxModelObject.h:
* rendering/RenderImage.cpp:
(WebCore::RenderImage::boxShadowShouldBeAppliedToBackground const):
* rendering/RenderImage.h:
* rendering/RenderTableCell.cpp:
(WebCore::RenderTableCell::boxShadowShouldBeAppliedToBackground const):
* rendering/RenderTableCell.h:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (282958 => 282959)


--- trunk/Source/WebCore/ChangeLog	2021-09-23 13:08:26 UTC (rev 282958)
+++ trunk/Source/WebCore/ChangeLog	2021-09-23 14:11:56 UTC (rev 282959)
@@ -1,3 +1,52 @@
+2021-09-23  Antti Koivisto  <[email protected]>
+
+        Factor LegacyInlineFlowBox painting into a class
+        https://bugs.webkit.org/show_bug.cgi?id=230683
+
+        Reviewed by Alan Bujtas.
+
+        Introduce InlineBoxPainter, similar to TextBoxPainter.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * rendering/InlineBoxPainter.cpp: Added.
+        (WebCore::InlineBoxPainter::InlineBoxPainter):
+        (WebCore::InlineBoxPainter::paint):
+        (WebCore::clipRectForNinePieceImageStrip):
+        (WebCore::InlineBoxPainter::paintMask):
+        (WebCore::InlineBoxPainter::paintDecorations):
+        (WebCore::InlineBoxPainter::style const):
+        (WebCore::InlineBoxPainter::constrainToLineTopAndBottomIfNeeded const):
+        (WebCore::InlineBoxPainter::paintFillLayers):
+        (WebCore::InlineBoxPainter::paintFillLayer):
+        (WebCore::InlineBoxPainter::paintBoxShadow):
+        * rendering/InlineBoxPainter.h: Added.
+        (WebCore::InlineBoxPainter::renderer const):
+        (WebCore::InlineBoxPainter::isHorizontal const):
+        * rendering/LegacyInlineFlowBox.cpp:
+        (WebCore::LegacyInlineFlowBox::paint):
+        (WebCore::LegacyInlineFlowBox::paintFillLayers): Deleted.
+        (WebCore::LegacyInlineFlowBox::paintFillLayer): Deleted.
+        (WebCore::LegacyInlineFlowBox::paintBoxShadow): Deleted.
+        (WebCore::LegacyInlineFlowBox::constrainToLineTopAndBottomIfNeeded const): Deleted.
+        (WebCore::clipRectForNinePieceImageStrip): Deleted.
+        (WebCore::LegacyInlineFlowBox::paintBoxDecorations): Deleted.
+        (WebCore::LegacyInlineFlowBox::paintMask): Deleted.
+        * rendering/LegacyInlineFlowBox.h:
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::getBackgroundRoundedRect const):
+        (WebCore::RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance const):
+        (WebCore::RenderBoxModelObject::paintMaskForTextFillBox):
+        (WebCore::RenderBoxModelObject::paintFillLayerExtended):
+        (WebCore::RenderBoxModelObject::boxShadowShouldBeAppliedToBackground const):
+        * rendering/RenderBoxModelObject.h:
+        * rendering/RenderImage.cpp:
+        (WebCore::RenderImage::boxShadowShouldBeAppliedToBackground const):
+        * rendering/RenderImage.h:
+        * rendering/RenderTableCell.cpp:
+        (WebCore::RenderTableCell::boxShadowShouldBeAppliedToBackground const):
+        * rendering/RenderTableCell.h:
+
 2021-09-23  Andres Gonzalez  <[email protected]>
 
         Remove AXDRTElementIdAttribute from the AX object platform wrapper interface.

Modified: trunk/Source/WebCore/Sources.txt (282958 => 282959)


--- trunk/Source/WebCore/Sources.txt	2021-09-23 13:08:26 UTC (rev 282958)
+++ trunk/Source/WebCore/Sources.txt	2021-09-23 14:11:56 UTC (rev 282959)
@@ -2207,6 +2207,7 @@
 rendering/HitTestResult.cpp
 rendering/HitTestingTransformState.cpp
 rendering/ImageQualityController.cpp
+rendering/InlineBoxPainter.cpp
 rendering/InlineIterator.cpp
 rendering/LayerAncestorClippingStack.cpp
 rendering/LayerOverlapMap.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (282958 => 282959)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-09-23 13:08:26 UTC (rev 282958)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-09-23 14:11:56 UTC (rev 282959)
@@ -5339,6 +5339,7 @@
 		E4E94D6122FF158A00DD191F /* LegacyLineLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A1AC7822FAFD500017B75B /* LegacyLineLayout.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E4F0BE3125712F6E009E7431 /* CaretRectComputation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F0BE2E25710A75009E7431 /* CaretRectComputation.h */; };
 		E4F38D1B2626F13B007B1064 /* DefaultResourceLoadPriority.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F38D192626F13B007B1064 /* DefaultResourceLoadPriority.h */; };
+		E4F819C626FB4EBF0094E162 /* InlineBoxPainter.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F819C526FB4EBF0094E162 /* InlineBoxPainter.h */; };
 		E4F9EEF3156DA00700D23E7E /* StyleSheetContents.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F9EEF1156D84C400D23E7E /* StyleSheetContents.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E50620842540919C00C43091 /* ContactsRequestData.h in Headers */ = {isa = PBXBuildFile; fileRef = E50620832540919B00C43091 /* ContactsRequestData.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E516699120FF9918009D2C27 /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = E516698F20FF9916009D2C27 /* [email protected] */; };
@@ -16607,6 +16608,8 @@
 		E4F0BE3025710A76009E7431 /* CaretRectComputation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CaretRectComputation.cpp; sourceTree = "<group>"; };
 		E4F38D192626F13B007B1064 /* DefaultResourceLoadPriority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DefaultResourceLoadPriority.h; sourceTree = "<group>"; };
 		E4F38D1C2626F144007B1064 /* DefaultResourceLoadPriority.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DefaultResourceLoadPriority.cpp; sourceTree = "<group>"; };
+		E4F819C226FB4EAF0094E162 /* InlineBoxPainter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InlineBoxPainter.cpp; sourceTree = "<group>"; };
+		E4F819C526FB4EBF0094E162 /* InlineBoxPainter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineBoxPainter.h; sourceTree = "<group>"; };
 		E4F9EEF0156D84C400D23E7E /* StyleSheetContents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleSheetContents.cpp; sourceTree = "<group>"; };
 		E4F9EEF1156D84C400D23E7E /* StyleSheetContents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleSheetContents.h; sourceTree = "<group>"; };
 		E4FB4B35239BEB10003C336A /* LayoutIntegrationInlineContent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutIntegrationInlineContent.cpp; sourceTree = "<group>"; };
@@ -29905,6 +29908,8 @@
 				9307F1D60AF2D59000DBA31A /* HitTestResult.h */,
 				B51A2F4017D7D5DA0072517A /* ImageQualityController.cpp */,
 				B51A2F3E17D7D3A40072517A /* ImageQualityController.h */,
+				E4F819C226FB4EAF0094E162 /* InlineBoxPainter.cpp */,
+				E4F819C526FB4EBF0094E162 /* InlineBoxPainter.h */,
 				930C90DC19CF965300D6C21A /* InlineIterator.cpp */,
 				BCE789151120D6080060ECE5 /* InlineIterator.h */,
 				0FEC120B22BF2CC7004E9D35 /* LayerAncestorClippingStack.cpp */,
@@ -32899,10 +32904,12 @@
 				51EEAA741BEFFAB100218008 /* IndexValueEntry.h in Headers */,
 				517138F81BF128BB000D5F01 /* IndexValueStore.h in Headers */,
 				CD063F831E23FA8900812BE3 /* InitDataRegistry.h in Headers */,
+				E4F819C626FB4EBF0094E162 /* InlineBoxPainter.h in Headers */,
 				E30592641E27A3AD00D57C98 /* InlineClassicScript.h in Headers */,
 				6FE198172178397C00446F08 /* InlineContentBreaker.h in Headers */,
 				111FA1C826F0F30F003B8F16 /* InlineDamage.h in Headers */,
 				11513D0326D981E8004D3FAA /* InlineDisplayContentBuilder.h in Headers */,
+				6F91421125152138004E4FEA /* InlineDisplayLine.h in Headers */,
 				6F7CA3CA208C2B2E002F29AB /* InlineFormattingContext.h in Headers */,
 				47C4D57D26508BCB00C7AB1F /* InlineFormattingGeometry.h in Headers */,
 				6FE636E82647962900F0951E /* InlineFormattingQuirks.h in Headers */,
@@ -32916,7 +32923,6 @@
 				11C3227D26D958CE00328F4D /* InlineLineBoxBuilder.h in Headers */,
 				6F6EE74326D44EE300374CDA /* InlineLineBoxVerticalAligner.h in Headers */,
 				6F26EB48234004A5006906E2 /* InlineLineBuilder.h in Headers */,
-				6F91421125152138004E4FEA /* InlineDisplayLine.h in Headers */,
 				6FC3F9472516756700A49BEA /* InlineLineRun.h in Headers */,
 				F45775CE241437D5002DF1A0 /* InlinePathData.h in Headers */,
 				6F40DA822513033A00EC04B7 /* InlineRect.h in Headers */,

Added: trunk/Source/WebCore/rendering/InlineBoxPainter.cpp (0 => 282959)


--- trunk/Source/WebCore/rendering/InlineBoxPainter.cpp	                        (rev 0)
+++ trunk/Source/WebCore/rendering/InlineBoxPainter.cpp	2021-09-23 14:11:56 UTC (rev 282959)
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2021 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 "InlineBoxPainter.h"
+
+#include "GraphicsContext.h"
+#include "LegacyInlineFlowBox.h"
+#include "PaintInfo.h"
+#include "RenderBlockFlow.h"
+#include "RenderInline.h"
+#include "RenderLayer.h"
+#include "RenderView.h"
+
+namespace WebCore {
+
+InlineBoxPainter::InlineBoxPainter(const LegacyInlineFlowBox& inlineBox, PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+    : m_inlineBox(inlineBox)
+    , m_paintInfo(paintInfo)
+    , m_paintOffset(paintOffset)
+    , m_renderer(m_inlineBox.renderer())
+    , m_isFirstLine(m_inlineBox.isFirstLine())
+    , m_isRootInlineBox(is<RenderBlockFlow>(m_renderer))
+    , m_isHorizontal(m_inlineBox.isHorizontal())
+{
+}
+
+InlineBoxPainter::~InlineBoxPainter() = default;
+
+void InlineBoxPainter::paint()
+{
+    if (m_paintInfo.phase == PaintPhase::Outline || m_paintInfo.phase == PaintPhase::SelfOutline) {
+        if (renderer().style().visibility() != Visibility::Visible || !renderer().hasOutline() || m_isRootInlineBox)
+            return;
+
+        auto& inlineFlow = downcast<RenderInline>(renderer());
+        RenderBlock* containingBlock = nullptr;
+
+        bool containingBlockPaintsContinuationOutline = inlineFlow.continuation() || inlineFlow.isContinuation();
+        if (containingBlockPaintsContinuationOutline) {
+            // FIXME: See https://bugs.webkit.org/show_bug.cgi?id=54690. We currently don't reconnect inline continuations
+            // after a child removal. As a result, those merged inlines do not get seperated and hence not get enclosed by
+            // anonymous blocks. In this case, it is better to bail out and paint it ourself.
+            RenderBlock* enclosingAnonymousBlock = renderer().containingBlock();
+            if (!enclosingAnonymousBlock->isAnonymousBlock())
+                containingBlockPaintsContinuationOutline = false;
+            else {
+                containingBlock = enclosingAnonymousBlock->containingBlock();
+                for (auto* box = &renderer(); box != containingBlock; box = &box->parent()->enclosingBoxModelObject()) {
+                    if (box->hasSelfPaintingLayer()) {
+                        containingBlockPaintsContinuationOutline = false;
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (containingBlockPaintsContinuationOutline) {
+            // Add ourselves to the containing block of the entire continuation so that it can
+            // paint us atomically.
+            containingBlock->addContinuationWithOutline(downcast<RenderInline>(renderer().element()->renderer()));
+        } else if (!inlineFlow.isContinuation())
+            m_paintInfo.outlineObjects->add(&inlineFlow);
+
+        return;
+    }
+
+    if (m_paintInfo.phase == PaintPhase::Mask) {
+        paintMask();
+        return;
+    }
+
+    paintDecorations();
+}
+
+static LayoutRect clipRectForNinePieceImageStrip(const LegacyInlineFlowBox* box, const NinePieceImage& image, const LayoutRect& paintRect)
+{
+    LayoutRect clipRect(paintRect);
+    auto& style = box->renderer().style();
+    LayoutBoxExtent outsets = style.imageOutsets(image);
+    if (box->isHorizontal()) {
+        clipRect.setY(paintRect.y() - outsets.top());
+        clipRect.setHeight(paintRect.height() + outsets.top() + outsets.bottom());
+        if (box->includeLogicalLeftEdge()) {
+            clipRect.setX(paintRect.x() - outsets.left());
+            clipRect.setWidth(paintRect.width() + outsets.left());
+        }
+        if (box->includeLogicalRightEdge())
+            clipRect.setWidth(clipRect.width() + outsets.right());
+    } else {
+        clipRect.setX(paintRect.x() - outsets.left());
+        clipRect.setWidth(paintRect.width() + outsets.left() + outsets.right());
+        if (box->includeLogicalLeftEdge()) {
+            clipRect.setY(paintRect.y() - outsets.top());
+            clipRect.setHeight(paintRect.height() + outsets.top());
+        }
+        if (box->includeLogicalRightEdge())
+            clipRect.setHeight(clipRect.height() + outsets.bottom());
+    }
+    return clipRect;
+}
+
+void InlineBoxPainter::paintMask()
+{
+    if (!m_paintInfo.shouldPaintWithinRoot(renderer()) || renderer().style().visibility() != Visibility::Visible || m_paintInfo.phase != PaintPhase::Mask)
+        return;
+
+    LayoutRect frameRect(m_inlineBox.frameRect());
+    constrainToLineTopAndBottomIfNeeded(frameRect);
+
+    // Move x/y to our coordinates.
+    LayoutRect localRect(frameRect);
+    m_inlineBox.root().blockFlow().flipForWritingMode(localRect);
+    LayoutPoint adjustedPaintOffset = m_paintOffset + localRect.location();
+
+    const NinePieceImage& maskNinePieceImage = renderer().style().maskBoxImage();
+    StyleImage* maskBoxImage = renderer().style().maskBoxImage().image();
+
+    // Figure out if we need to push a transparency layer to render our mask.
+    bool pushTransparencyLayer = false;
+    bool compositedMask = renderer().hasLayer() && renderer().layer()->hasCompositedMask();
+    bool flattenCompositingLayers = renderer().view().frameView().paintBehavior().contains(PaintBehavior::FlattenCompositingLayers);
+    CompositeOperator compositeOp = CompositeOperator::SourceOver;
+    if (!compositedMask || flattenCompositingLayers) {
+        if ((maskBoxImage && renderer().style().maskLayers().hasImage()) || renderer().style().maskLayers().next())
+            pushTransparencyLayer = true;
+
+        compositeOp = CompositeOperator::DestinationIn;
+        if (pushTransparencyLayer) {
+            m_paintInfo.context().setCompositeOperation(CompositeOperator::DestinationIn);
+            m_paintInfo.context().beginTransparencyLayer(1.0f);
+            compositeOp = CompositeOperator::SourceOver;
+        }
+    }
+
+    LayoutRect paintRect = LayoutRect(adjustedPaintOffset, frameRect.size());
+
+    paintFillLayers(Color(), renderer().style().maskLayers(), paintRect, compositeOp);
+
+    bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(&renderer(), renderer().style().effectiveZoom());
+    if (!hasBoxImage || !maskBoxImage->isLoaded()) {
+        if (pushTransparencyLayer)
+            m_paintInfo.context().endTransparencyLayer();
+        return; // Don't paint anything while we wait for the image to load.
+    }
+
+    bool hasSingleLine = !m_inlineBox.prevLineBox() && !m_inlineBox.nextLineBox();
+    if (hasSingleLine)
+        renderer().paintNinePieceImage(m_paintInfo.context(), LayoutRect(adjustedPaintOffset, frameRect.size()), renderer().style(), maskNinePieceImage, compositeOp);
+    else {
+        // We have a mask image that spans multiple lines.
+        // We need to adjust _tx and _ty by the width of all previous lines.
+        LayoutUnit logicalOffsetOnLine;
+        for (auto* curr = m_inlineBox.prevLineBox(); curr; curr = curr->prevLineBox())
+            logicalOffsetOnLine += curr->logicalWidth();
+        LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
+        for (auto* curr = &m_inlineBox; curr; curr = curr->nextLineBox())
+            totalLogicalWidth += curr->logicalWidth();
+        LayoutUnit stripX = adjustedPaintOffset.x() - (isHorizontal() ? logicalOffsetOnLine : 0_lu);
+        LayoutUnit stripY = adjustedPaintOffset.y() - (isHorizontal() ? 0_lu : logicalOffsetOnLine);
+        LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
+        LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
+
+        LayoutRect clipRect = clipRectForNinePieceImageStrip(&m_inlineBox, maskNinePieceImage, paintRect);
+        GraphicsContextStateSaver stateSaver(m_paintInfo.context());
+        m_paintInfo.context().clip(clipRect);
+        renderer().paintNinePieceImage(m_paintInfo.context(), LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer().style(), maskNinePieceImage, compositeOp);
+    }
+
+    if (pushTransparencyLayer)
+        m_paintInfo.context().endTransparencyLayer();
+}
+
+void InlineBoxPainter::paintDecorations()
+{
+    if (!m_paintInfo.shouldPaintWithinRoot(renderer()) || renderer().style().visibility() != Visibility::Visible || m_paintInfo.phase != PaintPhase::Foreground)
+        return;
+
+    if (!m_isRootInlineBox && !renderer().hasVisibleBoxDecorations())
+        return;
+
+    auto& style = this->style();
+    // You can use p::first-line to specify a background. If so, the root inline boxes for
+    // a line may actually have to paint a background.
+    if (m_isRootInlineBox && (!m_isFirstLine || &style == &renderer().style()))
+        return;
+
+    LayoutRect frameRect(m_inlineBox.frameRect());
+    constrainToLineTopAndBottomIfNeeded(frameRect);
+
+    // Move x/y to our coordinates.
+    LayoutRect localRect(frameRect);
+    m_inlineBox.root().blockFlow().flipForWritingMode(localRect);
+
+    LayoutPoint adjustedPaintoffset = m_paintOffset + localRect.location();
+    GraphicsContext& context = m_paintInfo.context();
+    LayoutRect paintRect = LayoutRect(adjustedPaintoffset, frameRect.size());
+    // Shadow comes first and is behind the background and border.
+    if (!renderer().boxShadowShouldBeAppliedToBackground(adjustedPaintoffset, BackgroundBleedNone, &m_inlineBox))
+        paintBoxShadow(ShadowStyle::Normal, paintRect);
+
+    auto color = style.visitedDependentColor(CSSPropertyBackgroundColor);
+    auto compositeOp = renderer().document().compositeOperatorForBackgroundColor(color, renderer());
+
+    color = style.colorByApplyingColorFilter(color);
+
+    paintFillLayers(color, style.backgroundLayers(), paintRect, compositeOp);
+    paintBoxShadow(ShadowStyle::Inset, paintRect);
+
+    // :first-line cannot be used to put borders on a line. Always paint borders with our
+    // non-first-line style.
+    if (m_isRootInlineBox || !renderer().style().hasVisibleBorderDecoration())
+        return;
+
+    const NinePieceImage& borderImage = renderer().style().borderImage();
+    StyleImage* borderImageSource = borderImage.image();
+    bool hasBorderImage = borderImageSource && borderImageSource->canRender(&renderer(), style.effectiveZoom());
+    if (hasBorderImage && !borderImageSource->isLoaded())
+        return; // Don't paint anything while we wait for the image to load.
+
+    bool hasSingleLine = !m_inlineBox.prevLineBox() && !m_inlineBox.nextLineBox();
+    if (!hasBorderImage || hasSingleLine) {
+        renderer().paintBorder(m_paintInfo, paintRect, style, BackgroundBleedNone, m_inlineBox.includeLogicalLeftEdge(), m_inlineBox.includeLogicalRightEdge());
+        return;
+    }
+
+    // We have a border image that spans multiple lines.
+    // We need to adjust tx and ty by the width of all previous lines.
+    // Think of border image painting on inlines as though you had one long line, a single continuous
+    // strip. Even though that strip has been broken up across multiple lines, you still paint it
+    // as though you had one single line. This means each line has to pick up the image where
+    // the previous line left off.
+    // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
+    // but it isn't even clear how this should work at all.
+    LayoutUnit logicalOffsetOnLine;
+    for (auto* curr = m_inlineBox.prevLineBox(); curr; curr = curr->prevLineBox())
+        logicalOffsetOnLine += curr->logicalWidth();
+    LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
+    for (auto* curr = &m_inlineBox; curr; curr = curr->nextLineBox())
+        totalLogicalWidth += curr->logicalWidth();
+
+    LayoutUnit stripX = adjustedPaintoffset.x() - (isHorizontal() ? logicalOffsetOnLine : 0_lu);
+    LayoutUnit stripY = adjustedPaintoffset.y() - (isHorizontal() ? 0_lu : logicalOffsetOnLine);
+    LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
+    LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
+
+    LayoutRect clipRect = clipRectForNinePieceImageStrip(&m_inlineBox, borderImage, paintRect);
+    GraphicsContextStateSaver stateSaver(context);
+    context.clip(clipRect);
+    renderer().paintBorder(m_paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), style);
+}
+
+void InlineBoxPainter::paintFillLayers(const Color& color, const FillLayer& fillLayer, const LayoutRect& rect, CompositeOperator op)
+{
+    Vector<const FillLayer*, 8> layers;
+    for (auto* layer = &fillLayer; layer; layer = layer->next())
+        layers.append(layer);
+    layers.reverse();
+    for (auto* layer : layers)
+        paintFillLayer(color, *layer, rect, op);
+}
+
+void InlineBoxPainter::paintFillLayer(const Color& color, const FillLayer& fillLayer, const LayoutRect& rect, CompositeOperator op)
+{
+    auto* image = fillLayer.image();
+    bool hasFillImage = image && image->canRender(&renderer(), renderer().style().effectiveZoom());
+    bool hasFillImageOrBorderRadious = hasFillImage || renderer().style().hasBorderRadius();
+    bool hasSingleLine = !m_inlineBox.prevLineBox() && !m_inlineBox.nextLineBox();
+
+    if (!hasFillImageOrBorderRadious || hasSingleLine || m_isRootInlineBox) {
+        renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, rect, BackgroundBleedNone, &m_inlineBox, rect.size(), op);
+        return;
+    }
+
+#if ENABLE(CSS_BOX_DECORATION_BREAK)
+    if (renderer().style().boxDecorationBreak() == BoxDecorationBreak::Clone) {
+        GraphicsContextStateSaver stateSaver(m_paintInfo.context());
+        m_paintInfo.context().clip({ rect.x(), rect.y(), LayoutUnit(m_inlineBox.width()), LayoutUnit(m_inlineBox.height()) });
+        renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, rect, BackgroundBleedNone, &m_inlineBox, rect.size(), op);
+        return;
+    }
+#endif
+
+    // We have a fill image that spans multiple lines.
+    // We need to adjust tx and ty by the width of all previous lines.
+    // Think of background painting on inlines as though you had one long line, a single continuous
+    // strip. Even though that strip has been broken up across multiple lines, you still paint it
+    // as though you had one single line. This means each line has to pick up the background where
+    // the previous line left off.
+    LayoutUnit logicalOffsetOnLine;
+    LayoutUnit totalLogicalWidth;
+    if (renderer().style().direction() == TextDirection::LTR) {
+        for (auto* curr = m_inlineBox.prevLineBox(); curr; curr = curr->prevLineBox())
+            logicalOffsetOnLine += curr->logicalWidth();
+        totalLogicalWidth = logicalOffsetOnLine;
+        for (auto* curr = &m_inlineBox; curr; curr = curr->nextLineBox())
+            totalLogicalWidth += curr->logicalWidth();
+    } else {
+        for (auto* curr = m_inlineBox.nextLineBox(); curr; curr = curr->nextLineBox())
+            logicalOffsetOnLine += curr->logicalWidth();
+        totalLogicalWidth = logicalOffsetOnLine;
+        for (auto* curr = &m_inlineBox; curr; curr = curr->prevLineBox())
+            totalLogicalWidth += curr->logicalWidth();
+    }
+    LayoutUnit stripX = rect.x() - (isHorizontal() ? logicalOffsetOnLine : 0_lu);
+    LayoutUnit stripY = rect.y() - (isHorizontal() ? 0_lu : logicalOffsetOnLine);
+    LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : LayoutUnit(m_inlineBox.width());
+    LayoutUnit stripHeight = isHorizontal() ? LayoutUnit(m_inlineBox.height()) : totalLogicalWidth;
+
+    GraphicsContextStateSaver stateSaver(m_paintInfo.context());
+    m_paintInfo.context().clip({ rect.x(), rect.y(), LayoutUnit(m_inlineBox.width()), LayoutUnit(m_inlineBox.height()) });
+    renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, LayoutRect(stripX, stripY, stripWidth, stripHeight), BackgroundBleedNone, &m_inlineBox, rect.size(), op);
+}
+
+void InlineBoxPainter::paintBoxShadow(ShadowStyle shadowStyle, const LayoutRect& paintRect)
+{
+    bool hasSingleLine = !m_inlineBox.prevLineBox() && !m_inlineBox.nextLineBox();
+    if (hasSingleLine || m_isRootInlineBox) {
+        renderer().paintBoxShadow(m_paintInfo, paintRect, style(), shadowStyle);
+        return;
+    }
+
+    // FIXME: We can do better here in the multi-line case. We want to push a clip so that the shadow doesn't
+    // protrude incorrectly at the edges, and we want to possibly include shadows cast from the previous/following lines
+    renderer().paintBoxShadow(m_paintInfo, paintRect, style(), shadowStyle, m_inlineBox.includeLogicalLeftEdge(), m_inlineBox.includeLogicalRightEdge());
+}
+
+void InlineBoxPainter::constrainToLineTopAndBottomIfNeeded(LayoutRect& rect) const
+{
+    if (renderer().document().inNoQuirksMode())
+        return;
+    if (m_inlineBox.hasTextChildren())
+        return;
+    if (m_inlineBox.descendantsHaveSameLineHeightAndBaseline() && m_inlineBox.hasTextDescendants())
+        return;
+
+    LayoutUnit logicalTop = isHorizontal() ? rect.y() : rect.x();
+    LayoutUnit logicalHeight = isHorizontal() ? rect.height() : rect.width();
+
+    LayoutUnit bottom = std::min(m_inlineBox.root().lineBottom(), logicalTop + logicalHeight);
+    logicalTop = std::max(m_inlineBox.root().lineTop(), logicalTop);
+    logicalHeight = bottom - logicalTop;
+    if (isHorizontal()) {
+        rect.setY(logicalTop);
+        rect.setHeight(logicalHeight);
+    } else {
+        rect.setX(logicalTop);
+        rect.setWidth(logicalHeight);
+    }
+}
+
+const RenderStyle& InlineBoxPainter::style() const
+{
+    return m_isFirstLine ? renderer().firstLineStyle() : renderer().style();
+}
+
+}

Added: trunk/Source/WebCore/rendering/InlineBoxPainter.h (0 => 282959)


--- trunk/Source/WebCore/rendering/InlineBoxPainter.h	                        (rev 0)
+++ trunk/Source/WebCore/rendering/InlineBoxPainter.h	2021-09-23 14:11:56 UTC (rev 282959)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+#include "FloatRect.h"
+#include "GraphicsTypes.h"
+#include "LayoutRect.h"
+#include "ShadowData.h"
+
+namespace WebCore {
+
+class Color;
+class FillLayer;
+class LegacyInlineFlowBox;
+class RenderBoxModelObject;
+class RenderStyle;
+struct PaintInfo;
+
+class InlineBoxPainter {
+public:
+    InlineBoxPainter(const LegacyInlineFlowBox&, PaintInfo&, const LayoutPoint& paintOffset);
+    ~InlineBoxPainter();
+
+    void paint();
+
+private:
+    void paintMask();
+    void paintDecorations();
+    void paintFillLayers(const Color&, const FillLayer&, const LayoutRect& paintRect, CompositeOperator);
+    void paintFillLayer(const Color&, const FillLayer&, const LayoutRect& paintRect, CompositeOperator);
+    void paintBoxShadow(ShadowStyle, const LayoutRect& paintRect);
+
+    void constrainToLineTopAndBottomIfNeeded(LayoutRect&) const;
+
+    const RenderStyle& style() const;
+    // FIXME: Make RenderBoxModelObject functions const.
+    RenderBoxModelObject& renderer() const { return const_cast<RenderBoxModelObject&>(m_renderer); }
+    bool isHorizontal() const { return m_isHorizontal; }
+
+    const LegacyInlineFlowBox& m_inlineBox;
+    PaintInfo& m_paintInfo;
+    const LayoutPoint m_paintOffset;
+    const RenderBoxModelObject& m_renderer;
+    const bool m_isFirstLine;
+    const bool m_isRootInlineBox;
+    const bool m_isHorizontal;
+};
+
+}

Modified: trunk/Source/WebCore/rendering/LegacyInlineFlowBox.cpp (282958 => 282959)


--- trunk/Source/WebCore/rendering/LegacyInlineFlowBox.cpp	2021-09-23 13:08:26 UTC (rev 282958)
+++ trunk/Source/WebCore/rendering/LegacyInlineFlowBox.cpp	2021-09-23 14:11:56 UTC (rev 282959)
@@ -25,6 +25,7 @@
 #include "FontCascade.h"
 #include "GraphicsContext.h"
 #include "HitTestResult.h"
+#include "InlineBoxPainter.h"
 #include "LegacyEllipsisBox.h"
 #include "LegacyInlineTextBox.h"
 #include "LegacyRootInlineBox.h"
@@ -1112,45 +1113,8 @@
         return;
 
     if (paintInfo.phase != PaintPhase::ChildOutlines) {
-        if (paintInfo.phase == PaintPhase::Outline || paintInfo.phase == PaintPhase::SelfOutline) {
-            // Add ourselves to the paint info struct's list of inlines that need to paint their
-            // outlines.
-            if (renderer().style().visibility() == Visibility::Visible && renderer().hasOutline() && !isRootInlineBox()) {
-                RenderInline& inlineFlow = downcast<RenderInline>(renderer());
-
-                RenderBlock* containingBlock = nullptr;
-                bool containingBlockPaintsContinuationOutline = inlineFlow.continuation() || inlineFlow.isContinuation();
-                if (containingBlockPaintsContinuationOutline) {
-                    // FIXME: See https://bugs.webkit.org/show_bug.cgi?id=54690. We currently don't reconnect inline continuations
-                    // after a child removal. As a result, those merged inlines do not get seperated and hence not get enclosed by
-                    // anonymous blocks. In this case, it is better to bail out and paint it ourself.
-                    RenderBlock* enclosingAnonymousBlock = renderer().containingBlock();
-                    if (!enclosingAnonymousBlock->isAnonymousBlock())
-                        containingBlockPaintsContinuationOutline = false;
-                    else {
-                        containingBlock = enclosingAnonymousBlock->containingBlock();
-                        for (auto* box = &renderer(); box != containingBlock; box = &box->parent()->enclosingBoxModelObject()) {
-                            if (box->hasSelfPaintingLayer()) {
-                                containingBlockPaintsContinuationOutline = false;
-                                break;
-                            }
-                        }
-                    }
-                }
-
-                if (containingBlockPaintsContinuationOutline) {
-                    // Add ourselves to the containing block of the entire continuation so that it can
-                    // paint us atomically.
-                    containingBlock->addContinuationWithOutline(downcast<RenderInline>(renderer().element()->renderer()));
-                } else if (!inlineFlow.isContinuation())
-                    paintInfo.outlineObjects->add(&inlineFlow);
-            }
-        } else if (paintInfo.phase == PaintPhase::Mask)
-            paintMask(paintInfo, paintOffset);
-        else {
-            // Paint our background, border and box-shadow.
-            paintBoxDecorations(paintInfo, paintOffset);
-        }
+        InlineBoxPainter painter(*this, paintInfo, paintOffset);
+        painter.paint();
     }
 
     if (paintInfo.phase == PaintPhase::Mask)
@@ -1170,16 +1134,6 @@
     }
 }
 
-void LegacyInlineFlowBox::paintFillLayers(const PaintInfo& paintInfo, const Color& color, const FillLayer& fillLayer, const LayoutRect& rect, CompositeOperator op)
-{
-    Vector<const FillLayer*, 8> layers;
-    for (auto* layer = &fillLayer; layer; layer = layer->next())
-        layers.append(layer);
-    layers.reverse();
-    for (auto* layer : layers)
-        paintFillLayer(paintInfo, color, *layer, rect, op);
-}
-
 bool LegacyInlineFlowBox::boxShadowCanBeAppliedToBackground(const FillLayer& lastBackgroundLayer) const
 {
     // The checks here match how paintFillLayer() decides whether to clip (if it does, the shadow
@@ -1189,257 +1143,6 @@
     return (!hasFillImage && !renderer().style().hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent();
 }
 
-void LegacyInlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& color, const FillLayer& fillLayer, const LayoutRect& rect, CompositeOperator op)
-{
-    auto* image = fillLayer.image();
-    bool hasFillImage = image && image->canRender(&renderer(), renderer().style().effectiveZoom());
-    if ((!hasFillImage && !renderer().style().hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent())
-        renderer().paintFillLayerExtended(paintInfo, color, fillLayer, rect, BackgroundBleedNone, this, rect.size(), op);
-#if ENABLE(CSS_BOX_DECORATION_BREAK)
-    else if (renderer().style().boxDecorationBreak() == BoxDecorationBreak::Clone) {
-        GraphicsContextStateSaver stateSaver(paintInfo.context());
-        paintInfo.context().clip({ rect.x(), rect.y(), LayoutUnit(width()), LayoutUnit(height()) });
-        renderer().paintFillLayerExtended(paintInfo, color, fillLayer, rect, BackgroundBleedNone, this, rect.size(), op);
-    }
-#endif
-    else {
-        // We have a fill image that spans multiple lines.
-        // We need to adjust tx and ty by the width of all previous lines.
-        // Think of background painting on inlines as though you had one long line, a single continuous
-        // strip. Even though that strip has been broken up across multiple lines, you still paint it
-        // as though you had one single line. This means each line has to pick up the background where
-        // the previous line left off.
-        LayoutUnit logicalOffsetOnLine;
-        LayoutUnit totalLogicalWidth;
-        if (renderer().style().direction() == TextDirection::LTR) {
-            for (auto* curr = prevLineBox(); curr; curr = curr->prevLineBox())
-                logicalOffsetOnLine += curr->logicalWidth();
-            totalLogicalWidth = logicalOffsetOnLine;
-            for (auto* curr = this; curr; curr = curr->nextLineBox())
-                totalLogicalWidth += curr->logicalWidth();
-        } else {
-            for (auto* curr = nextLineBox(); curr; curr = curr->nextLineBox())
-                logicalOffsetOnLine += curr->logicalWidth();
-            totalLogicalWidth = logicalOffsetOnLine;
-            for (auto* curr = this; curr; curr = curr->prevLineBox())
-                totalLogicalWidth += curr->logicalWidth();
-        }
-        LayoutUnit stripX = rect.x() - (isHorizontal() ? logicalOffsetOnLine : 0_lu);
-        LayoutUnit stripY = rect.y() - (isHorizontal() ? 0_lu : logicalOffsetOnLine);
-        LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : LayoutUnit(width());
-        LayoutUnit stripHeight = isHorizontal() ? LayoutUnit(height()) : totalLogicalWidth;
-
-        GraphicsContextStateSaver stateSaver(paintInfo.context());
-        paintInfo.context().clip({ rect.x(), rect.y(), LayoutUnit(width()), LayoutUnit(height()) });
-        renderer().paintFillLayerExtended(paintInfo, color, fillLayer, LayoutRect(stripX, stripY, stripWidth, stripHeight), BackgroundBleedNone, this, rect.size(), op);
-    }
-}
-
-void LegacyInlineFlowBox::paintBoxShadow(const PaintInfo& info, const RenderStyle& style, ShadowStyle shadowStyle, const LayoutRect& paintRect)
-{
-    if ((!prevLineBox() && !nextLineBox()) || !parent())
-        renderer().paintBoxShadow(info, paintRect, style, shadowStyle);
-    else {
-        // FIXME: We can do better here in the multi-line case. We want to push a clip so that the shadow doesn't
-        // protrude incorrectly at the edges, and we want to possibly include shadows cast from the previous/following lines
-        renderer().paintBoxShadow(info, paintRect, style, shadowStyle, includeLogicalLeftEdge(), includeLogicalRightEdge());
-    }
-}
-
-void LegacyInlineFlowBox::constrainToLineTopAndBottomIfNeeded(LayoutRect& rect) const
-{
-    bool noQuirksMode = renderer().document().inNoQuirksMode();
-    if (!noQuirksMode && !hasTextChildren() && !(descendantsHaveSameLineHeightAndBaseline() && hasTextDescendants())) {
-        const LegacyRootInlineBox& rootBox = root();
-        LayoutUnit logicalTop = isHorizontal() ? rect.y() : rect.x();
-        LayoutUnit logicalHeight = isHorizontal() ? rect.height() : rect.width();
-        LayoutUnit bottom = std::min(rootBox.lineBottom(), logicalTop + logicalHeight);
-        logicalTop = std::max(rootBox.lineTop(), logicalTop);
-        logicalHeight = bottom - logicalTop;
-        if (isHorizontal()) {
-            rect.setY(logicalTop);
-            rect.setHeight(logicalHeight);
-        } else {
-            rect.setX(logicalTop);
-            rect.setWidth(logicalHeight);
-        }
-    }
-}
-
-static LayoutRect clipRectForNinePieceImageStrip(LegacyInlineFlowBox* box, const NinePieceImage& image, const LayoutRect& paintRect)
-{
-    LayoutRect clipRect(paintRect);
-    auto& style = box->renderer().style();
-    LayoutBoxExtent outsets = style.imageOutsets(image);
-    if (box->isHorizontal()) {
-        clipRect.setY(paintRect.y() - outsets.top());
-        clipRect.setHeight(paintRect.height() + outsets.top() + outsets.bottom());
-        if (box->includeLogicalLeftEdge()) {
-            clipRect.setX(paintRect.x() - outsets.left());
-            clipRect.setWidth(paintRect.width() + outsets.left());
-        }
-        if (box->includeLogicalRightEdge())
-            clipRect.setWidth(clipRect.width() + outsets.right());
-    } else {
-        clipRect.setX(paintRect.x() - outsets.left());
-        clipRect.setWidth(paintRect.width() + outsets.left() + outsets.right());
-        if (box->includeLogicalLeftEdge()) {
-            clipRect.setY(paintRect.y() - outsets.top());
-            clipRect.setHeight(paintRect.height() + outsets.top());
-        }
-        if (box->includeLogicalRightEdge())
-            clipRect.setHeight(clipRect.height() + outsets.bottom());
-    }
-    return clipRect;
-}
-
-void LegacyInlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
-{
-    if (!paintInfo.shouldPaintWithinRoot(renderer()) || renderer().style().visibility() != Visibility::Visible || paintInfo.phase != PaintPhase::Foreground)
-        return;
-
-    // You can use p::first-line to specify a background. If so, the root line boxes for
-    // a line may actually have to paint a background.
-    if (parent() && !renderer().hasVisibleBoxDecorations())
-        return;
-    const RenderStyle& lineStyle = this->lineStyle();
-    if (!parent() && (!isFirstLine() || &lineStyle == &renderer().style()))
-        return;
-
-    LayoutRect frameRect(this->frameRect());
-    constrainToLineTopAndBottomIfNeeded(frameRect);
-    
-    // Move x/y to our coordinates.
-    LayoutRect localRect(frameRect);
-    flipForWritingMode(localRect);
-
-    LayoutPoint adjustedPaintoffset = paintOffset + localRect.location();
-    GraphicsContext& context = paintInfo.context();
-    LayoutRect paintRect = LayoutRect(adjustedPaintoffset, frameRect.size());
-    // Shadow comes first and is behind the background and border.
-    if (!renderer().boxShadowShouldBeAppliedToBackground(adjustedPaintoffset, BackgroundBleedNone, this))
-        paintBoxShadow(paintInfo, lineStyle, ShadowStyle::Normal, paintRect);
-
-    auto color = lineStyle.visitedDependentColor(CSSPropertyBackgroundColor);
-    auto compositeOp = renderer().document().compositeOperatorForBackgroundColor(color, renderer());
-
-    color = lineStyle.colorByApplyingColorFilter(color);
-
-    paintFillLayers(paintInfo, color, lineStyle.backgroundLayers(), paintRect, compositeOp);
-    paintBoxShadow(paintInfo, lineStyle, ShadowStyle::Inset, paintRect);
-
-    // :first-line cannot be used to put borders on a line. Always paint borders with our
-    // non-first-line style.
-    if (!parent() || !renderer().style().hasVisibleBorderDecoration())
-        return;
-    const NinePieceImage& borderImage = renderer().style().borderImage();
-    StyleImage* borderImageSource = borderImage.image();
-    bool hasBorderImage = borderImageSource && borderImageSource->canRender(&renderer(), lineStyle.effectiveZoom());
-    if (hasBorderImage && !borderImageSource->isLoaded())
-        return; // Don't paint anything while we wait for the image to load.
-
-    // The simple case is where we either have no border image or we are the only box for this object. In those
-    // cases only a single call to draw is required.
-    if (!hasBorderImage || (!prevLineBox() && !nextLineBox()))
-        renderer().paintBorder(paintInfo, paintRect, lineStyle, BackgroundBleedNone, includeLogicalLeftEdge(), includeLogicalRightEdge());
-    else {
-        // We have a border image that spans multiple lines.
-        // We need to adjust tx and ty by the width of all previous lines.
-        // Think of border image painting on inlines as though you had one long line, a single continuous
-        // strip. Even though that strip has been broken up across multiple lines, you still paint it
-        // as though you had one single line. This means each line has to pick up the image where
-        // the previous line left off.
-        // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
-        // but it isn't even clear how this should work at all.
-        LayoutUnit logicalOffsetOnLine;
-        for (auto* curr = prevLineBox(); curr; curr = curr->prevLineBox())
-            logicalOffsetOnLine += curr->logicalWidth();
-        LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
-        for (auto* curr = this; curr; curr = curr->nextLineBox())
-            totalLogicalWidth += curr->logicalWidth();
-        LayoutUnit stripX = adjustedPaintoffset.x() - (isHorizontal() ? logicalOffsetOnLine : 0_lu);
-        LayoutUnit stripY = adjustedPaintoffset.y() - (isHorizontal() ? 0_lu : logicalOffsetOnLine);
-        LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
-        LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
-
-        LayoutRect clipRect = clipRectForNinePieceImageStrip(this, borderImage, paintRect);
-        GraphicsContextStateSaver stateSaver(context);
-        context.clip(clipRect);
-        renderer().paintBorder(paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), lineStyle);
-    }
-}
-
-void LegacyInlineFlowBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
-{
-    if (!paintInfo.shouldPaintWithinRoot(renderer()) || renderer().style().visibility() != Visibility::Visible || paintInfo.phase != PaintPhase::Mask)
-        return;
-
-    LayoutRect frameRect(this->frameRect());
-    constrainToLineTopAndBottomIfNeeded(frameRect);
-    
-    // Move x/y to our coordinates.
-    LayoutRect localRect(frameRect);
-    flipForWritingMode(localRect);
-    LayoutPoint adjustedPaintOffset = paintOffset + localRect.location();
-
-    const NinePieceImage& maskNinePieceImage = renderer().style().maskBoxImage();
-    StyleImage* maskBoxImage = renderer().style().maskBoxImage().image();
-
-    // Figure out if we need to push a transparency layer to render our mask.
-    bool pushTransparencyLayer = false;
-    bool compositedMask = renderer().hasLayer() && renderer().layer()->hasCompositedMask();
-    bool flattenCompositingLayers = renderer().view().frameView().paintBehavior().contains(PaintBehavior::FlattenCompositingLayers);
-    CompositeOperator compositeOp = CompositeOperator::SourceOver;
-    if (!compositedMask || flattenCompositingLayers) {
-        if ((maskBoxImage && renderer().style().maskLayers().hasImage()) || renderer().style().maskLayers().next())
-            pushTransparencyLayer = true;
-        
-        compositeOp = CompositeOperator::DestinationIn;
-        if (pushTransparencyLayer) {
-            paintInfo.context().setCompositeOperation(CompositeOperator::DestinationIn);
-            paintInfo.context().beginTransparencyLayer(1.0f);
-            compositeOp = CompositeOperator::SourceOver;
-        }
-    }
-
-    LayoutRect paintRect = LayoutRect(adjustedPaintOffset, frameRect.size());
-    paintFillLayers(paintInfo, Color(), renderer().style().maskLayers(), paintRect, compositeOp);
-    
-    bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(&renderer(), renderer().style().effectiveZoom());
-    if (!hasBoxImage || !maskBoxImage->isLoaded()) {
-        if (pushTransparencyLayer)
-            paintInfo.context().endTransparencyLayer();
-        return; // Don't paint anything while we wait for the image to load.
-    }
-
-    // The simple case is where we are the only box for this object. In those
-    // cases only a single call to draw is required.
-    if (!prevLineBox() && !nextLineBox())
-        renderer().paintNinePieceImage(paintInfo.context(), LayoutRect(adjustedPaintOffset, frameRect.size()), renderer().style(), maskNinePieceImage, compositeOp);
-    else {
-        // We have a mask image that spans multiple lines.
-        // We need to adjust _tx and _ty by the width of all previous lines.
-        LayoutUnit logicalOffsetOnLine;
-        for (auto* curr = prevLineBox(); curr; curr = curr->prevLineBox())
-            logicalOffsetOnLine += curr->logicalWidth();
-        LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
-        for (auto* curr = this; curr; curr = curr->nextLineBox())
-            totalLogicalWidth += curr->logicalWidth();
-        LayoutUnit stripX = adjustedPaintOffset.x() - (isHorizontal() ? logicalOffsetOnLine : 0_lu);
-        LayoutUnit stripY = adjustedPaintOffset.y() - (isHorizontal() ? 0_lu : logicalOffsetOnLine);
-        LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
-        LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
-
-        LayoutRect clipRect = clipRectForNinePieceImageStrip(this, maskNinePieceImage, paintRect);
-        GraphicsContextStateSaver stateSaver(paintInfo.context());
-        paintInfo.context().clip(clipRect);
-        renderer().paintNinePieceImage(paintInfo.context(), LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer().style(), maskNinePieceImage, compositeOp);
-    }
-    
-    if (pushTransparencyLayer)
-        paintInfo.context().endTransparencyLayer();
-}
-
 LegacyInlineBox* LegacyInlineFlowBox::firstLeafDescendant() const
 {
     LegacyInlineBox* leaf = nullptr;

Modified: trunk/Source/WebCore/rendering/LegacyInlineFlowBox.h (282958 => 282959)


--- trunk/Source/WebCore/rendering/LegacyInlineFlowBox.h	2021-09-23 13:08:26 UTC (rev 282958)
+++ trunk/Source/WebCore/rendering/LegacyInlineFlowBox.h	2021-09-23 14:11:56 UTC (rev 282959)
@@ -115,11 +115,6 @@
 
     void clearTruncation() override;
 
-    void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
-    void paintMask(PaintInfo&, const LayoutPoint&);
-    void paintFillLayers(const PaintInfo&, const Color&, const FillLayer&, const LayoutRect&, CompositeOperator = CompositeOperator::SourceOver);
-    void paintFillLayer(const PaintInfo&, const Color&, const FillLayer&, const LayoutRect&, CompositeOperator = CompositeOperator::SourceOver);
-    void paintBoxShadow(const PaintInfo&, const RenderStyle&, ShadowStyle, const LayoutRect&);
     void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override;
     bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom, HitTestAction) override;
 
@@ -305,7 +300,6 @@
     void addTextBoxVisualOverflow(LegacyInlineTextBox&, GlyphOverflowAndFallbackFontsMap&, LayoutRect& logicalVisualOverflow);
     void addOutlineVisualOverflow(LayoutRect& logicalVisualOverflow);
     void addReplacedChildOverflow(const LegacyInlineBox*, LayoutRect& logicalLayoutOverflow, LayoutRect& logicalVisualOverflow);
-    void constrainToLineTopAndBottomIfNeeded(LayoutRect&) const;
 
 private:
     unsigned m_includeLogicalLeftEdge : 1;

Modified: trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp (282958 => 282959)


--- trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp	2021-09-23 13:08:26 UTC (rev 282958)
+++ trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp	2021-09-23 14:11:56 UTC (rev 282959)
@@ -621,7 +621,7 @@
     return minimumValueForLength(padding, w);
 }
 
-RoundedRect RenderBoxModelObject::getBackgroundRoundedRect(const LayoutRect& borderRect, LegacyInlineFlowBox* box, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
+RoundedRect RenderBoxModelObject::getBackgroundRoundedRect(const LayoutRect& borderRect, const LegacyInlineFlowBox* box, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
     bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
 {
     RoundedRect border = style().getRoundedBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
@@ -682,7 +682,7 @@
     return shrinkRectByOneDevicePixel(context, rect, document().deviceScaleFactor());
 }
 
-RoundedRect RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance(const GraphicsContext& context, const LayoutRect& borderRect, BackgroundBleedAvoidance bleedAvoidance, LegacyInlineFlowBox* box, const LayoutSize& boxSize, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+RoundedRect RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance(const GraphicsContext& context, const LayoutRect& borderRect, BackgroundBleedAvoidance bleedAvoidance, const LegacyInlineFlowBox* box, const LayoutSize& boxSize, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
 {
     if (bleedAvoidance == BackgroundBleedShrinkBackground) {
         // We shrink the rectangle by one device pixel on each side because the bleed is one pixel maximum.
@@ -710,7 +710,7 @@
     return view().imageQualityController().chooseInterpolationQuality(context, this, image, layer, size);
 }
 
-void RenderBoxModelObject::paintMaskForTextFillBox(ImageBuffer* maskImage, const FloatRect& maskRect, LegacyInlineFlowBox* box, const LayoutRect& scrolledPaintRect)
+void RenderBoxModelObject::paintMaskForTextFillBox(ImageBuffer* maskImage, const FloatRect& maskRect, const LegacyInlineFlowBox* box, const LayoutRect& scrolledPaintRect)
 {
     GraphicsContext& maskImageContext = maskImage->context();
     maskImageContext.translate(-maskRect.location());
@@ -720,7 +720,7 @@
     PaintInfo info(maskImageContext, LayoutRect { maskRect }, PaintPhase::TextClip, PaintBehavior::ForceBlackText);
     if (box) {
         const LegacyRootInlineBox& rootBox = box->root();
-        box->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(), scrolledPaintRect.y() - box->y()), rootBox.lineTop(), rootBox.lineBottom());
+        const_cast<LegacyInlineFlowBox*>(box)->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(), scrolledPaintRect.y() - box->y()), rootBox.lineTop(), rootBox.lineBottom());
     } else {
         LayoutSize localOffset = is<RenderBox>(*this) ? downcast<RenderBox>(*this).locationOffset() : LayoutSize();
         paint(info, scrolledPaintRect.location() - localOffset);
@@ -728,7 +728,7 @@
 }
 
 void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& color, const FillLayer& bgLayer, const LayoutRect& rect,
-    BackgroundBleedAvoidance bleedAvoidance, LegacyInlineFlowBox* box, const LayoutSize& boxSize, CompositeOperator op, RenderElement* backgroundObject, BaseBackgroundColorUsage baseBgColorUsage)
+    BackgroundBleedAvoidance bleedAvoidance, const LegacyInlineFlowBox* box, const LayoutSize& boxSize, CompositeOperator op, RenderElement* backgroundObject, BaseBackgroundColorUsage baseBgColorUsage)
 {
     GraphicsContext& context = paintInfo.context();
 
@@ -2326,7 +2326,7 @@
     return true;
 }
 
-bool RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(const LayoutPoint&, BackgroundBleedAvoidance bleedAvoidance, LegacyInlineFlowBox* inlineFlowBox) const
+bool RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(const LayoutPoint&, BackgroundBleedAvoidance bleedAvoidance, const LegacyInlineFlowBox* inlineFlowBox) const
 {
     if (bleedAvoidance != BackgroundBleedNone)
         return false;

Modified: trunk/Source/WebCore/rendering/RenderBoxModelObject.h (282958 => 282959)


--- trunk/Source/WebCore/rendering/RenderBoxModelObject.h	2021-09-23 13:08:26 UTC (rev 282958)
+++ trunk/Source/WebCore/rendering/RenderBoxModelObject.h	2021-09-23 14:11:56 UTC (rev 282959)
@@ -210,9 +210,9 @@
     void paintBorder(const PaintInfo&, const LayoutRect&, const RenderStyle&, BackgroundBleedAvoidance = BackgroundBleedNone, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
     bool paintNinePieceImage(GraphicsContext&, const LayoutRect&, const RenderStyle&, const NinePieceImage&, CompositeOperator = CompositeOperator::SourceOver);
     void paintBoxShadow(const PaintInfo&, const LayoutRect&, const RenderStyle&, ShadowStyle, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
-    void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer&, const LayoutRect&, BackgroundBleedAvoidance, LegacyInlineFlowBox* = nullptr, const LayoutSize& = LayoutSize(), CompositeOperator = CompositeOperator::SourceOver, RenderElement* backgroundObject = nullptr, BaseBackgroundColorUsage = BaseBackgroundColorUse);
+    void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer&, const LayoutRect&, BackgroundBleedAvoidance, const LegacyInlineFlowBox*  = nullptr, const LayoutSize& = LayoutSize(), CompositeOperator = CompositeOperator::SourceOver, RenderElement* backgroundObject = nullptr, BaseBackgroundColorUsage = BaseBackgroundColorUse);
 
-    virtual bool boxShadowShouldBeAppliedToBackground(const LayoutPoint& absolutePaintPostion, BackgroundBleedAvoidance, LegacyInlineFlowBox* = nullptr) const;
+    virtual bool boxShadowShouldBeAppliedToBackground(const LayoutPoint& absolutePaintPostion, BackgroundBleedAvoidance, const LegacyInlineFlowBox*  = nullptr) const;
 
     // Overridden by subclasses to determine line height and baseline position.
     virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0;
@@ -256,7 +256,7 @@
         const LayoutRect& paintRect, RenderElement* = nullptr) const;
     bool borderObscuresBackgroundEdge(const FloatSize& contextScale) const;
     bool borderObscuresBackground() const;
-    RoundedRect backgroundRoundedRectAdjustedForBleedAvoidance(const GraphicsContext&, const LayoutRect&, BackgroundBleedAvoidance, LegacyInlineFlowBox*, const LayoutSize&, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
+    RoundedRect backgroundRoundedRectAdjustedForBleedAvoidance(const GraphicsContext&, const LayoutRect&, BackgroundBleedAvoidance, const LegacyInlineFlowBox* , const LayoutSize&, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
     LayoutRect borderInnerRectAdjustedForBleedAvoidance(const GraphicsContext&, const LayoutRect&, BackgroundBleedAvoidance) const;
 
     InterpolationQuality chooseInterpolationQuality(GraphicsContext&, Image&, const void*, const LayoutSize&);
@@ -307,7 +307,7 @@
 
     LayoutSize calculateFillTileSize(const FillLayer&, const LayoutSize& scaledPositioningAreaSize) const;
 
-    RoundedRect getBackgroundRoundedRect(const LayoutRect&, LegacyInlineFlowBox*, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
+    RoundedRect getBackgroundRoundedRect(const LayoutRect&, const LegacyInlineFlowBox* , LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
         bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
     
     bool fixedBackgroundPaintsInLocalCoordinates() const;
@@ -326,7 +326,7 @@
     void drawBoxSideFromPath(GraphicsContext&, const LayoutRect&, const Path&, const BorderEdges&,
         float thickness, float drawThickness, BoxSide, const RenderStyle&,
         Color, BorderStyle, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge);
-    void paintMaskForTextFillBox(ImageBuffer*, const FloatRect&, LegacyInlineFlowBox*, const LayoutRect&);
+    void paintMaskForTextFillBox(ImageBuffer*, const FloatRect&, const LegacyInlineFlowBox* , const LayoutRect&);
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/rendering/RenderImage.cpp (282958 => 282959)


--- trunk/Source/WebCore/rendering/RenderImage.cpp	2021-09-23 13:08:26 UTC (rev 282958)
+++ trunk/Source/WebCore/rendering/RenderImage.cpp	2021-09-23 14:11:56 UTC (rev 282959)
@@ -691,7 +691,7 @@
     return drawResult;
 }
 
-bool RenderImage::boxShadowShouldBeAppliedToBackground(const LayoutPoint& paintOffset, BackgroundBleedAvoidance bleedAvoidance, LegacyInlineFlowBox*) const
+bool RenderImage::boxShadowShouldBeAppliedToBackground(const LayoutPoint& paintOffset, BackgroundBleedAvoidance bleedAvoidance, const LegacyInlineFlowBox*) const
 {
     if (!RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(paintOffset, bleedAvoidance))
         return false;

Modified: trunk/Source/WebCore/rendering/RenderImage.h (282958 => 282959)


--- trunk/Source/WebCore/rendering/RenderImage.h	2021-09-23 13:08:26 UTC (rev 282958)
+++ trunk/Source/WebCore/rendering/RenderImage.h	2021-09-23 14:11:56 UTC (rev 282959)
@@ -121,7 +121,7 @@
     void notifyFinished(CachedResource&, const NetworkLoadMetrics&) final;
     bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) final;
 
-    bool boxShadowShouldBeAppliedToBackground(const LayoutPoint& paintOffset, BackgroundBleedAvoidance, LegacyInlineFlowBox*) const final;
+    bool boxShadowShouldBeAppliedToBackground(const LayoutPoint& paintOffset, BackgroundBleedAvoidance, const LegacyInlineFlowBox*) const final;
 
     IntSize imageSizeForError(CachedImage*) const;
     void repaintOrMarkForLayout(ImageSizeChangeType, const IntRect* = nullptr);

Modified: trunk/Source/WebCore/rendering/RenderTableCell.cpp (282958 => 282959)


--- trunk/Source/WebCore/rendering/RenderTableCell.cpp	2021-09-23 13:08:26 UTC (rev 282958)
+++ trunk/Source/WebCore/rendering/RenderTableCell.cpp	2021-09-23 14:11:56 UTC (rev 282959)
@@ -1347,7 +1347,7 @@
     paintMaskImages(paintInfo, paintRect);
 }
 
-bool RenderTableCell::boxShadowShouldBeAppliedToBackground(const LayoutPoint&, BackgroundBleedAvoidance, LegacyInlineFlowBox*) const
+bool RenderTableCell::boxShadowShouldBeAppliedToBackground(const LayoutPoint&, BackgroundBleedAvoidance, const LegacyInlineFlowBox*) const
 {
     return false;
 }

Modified: trunk/Source/WebCore/rendering/RenderTableCell.h (282958 => 282959)


--- trunk/Source/WebCore/rendering/RenderTableCell.h	2021-09-23 13:08:26 UTC (rev 282958)
+++ trunk/Source/WebCore/rendering/RenderTableCell.h	2021-09-23 14:11:56 UTC (rev 282959)
@@ -151,7 +151,7 @@
     void paintBoxDecorations(PaintInfo&, const LayoutPoint&) override;
     void paintMask(PaintInfo&, const LayoutPoint&) override;
 
-    bool boxShadowShouldBeAppliedToBackground(const LayoutPoint& paintOffset, BackgroundBleedAvoidance, LegacyInlineFlowBox*) const override;
+    bool boxShadowShouldBeAppliedToBackground(const LayoutPoint& paintOffset, BackgroundBleedAvoidance, const LegacyInlineFlowBox*) const override;
 
     LayoutSize offsetFromContainer(RenderElement&, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const override;
     std::optional<LayoutRect> computeVisibleRectInContainer(const LayoutRect&, const RenderLayerModelObject* container, VisibleRectContext) const override;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to