Title: [284380] trunk
Revision
284380
Author
an...@apple.com
Date
2021-10-18 10:17:56 -0700 (Mon, 18 Oct 2021)

Log Message

background-clip:text doesn't paint correctly for inline box spanning multiple lines
https://bugs.webkit.org/show_bug.cgi?id=231891

Reviewed by Alan Bujtas.

Source/WebCore:

'background-clip: text' paints to a wrong position if the inline box spans multiple lines.

Test: fast/inline/inline-background-clip-text-multiline.html

* rendering/InlineBoxPainter.cpp:
(WebCore::InlineBoxPainter::paintFillLayer):
* rendering/RenderBox.cpp:
(WebCore::RenderBox::paintFillLayer):
* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::getBackgroundRoundedRect const):
(WebCore::RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance const):

No need to pass box size separately as it now always matches the passed in border rect.

(WebCore::RenderBoxModelObject::paintFillLayerExtended):

The 'rect' parameter used to be either the border box rect of the box being painted or,
in the case of multiline inline box background image, the image strip being painted.

Make the 'rect' parameter to always be the border box and pass the background image strip
separately.

Use the background image strip only during background image painting.

* rendering/RenderBoxModelObject.h:
(WebCore::RenderBoxModelObject::paintFillLayerExtended):

LayoutTests:

* fast/inline/inline-background-clip-text-multiline-expected.html: Added.
* fast/inline/inline-background-clip-text-multiline.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (284379 => 284380)


--- trunk/LayoutTests/ChangeLog	2021-10-18 17:16:46 UTC (rev 284379)
+++ trunk/LayoutTests/ChangeLog	2021-10-18 17:17:56 UTC (rev 284380)
@@ -1,3 +1,13 @@
+2021-10-18  Antti Koivisto  <an...@apple.com>
+
+        background-clip:text doesn't paint correctly for inline box spanning multiple lines
+        https://bugs.webkit.org/show_bug.cgi?id=231891
+
+        Reviewed by Alan Bujtas.
+
+        * fast/inline/inline-background-clip-text-multiline-expected.html: Added.
+        * fast/inline/inline-background-clip-text-multiline.html: Added.
+
 2021-10-18  Ayumi Kojima  <ayumi_koj...@apple.com>
 
         [ iOS 15 ] Rebaselining 4 fast tests.

Added: trunk/LayoutTests/fast/inline/inline-background-clip-text-multiline-expected.html (0 => 284380)


--- trunk/LayoutTests/fast/inline/inline-background-clip-text-multiline-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/inline/inline-background-clip-text-multiline-expected.html	2021-10-18 17:17:56 UTC (rev 284380)
@@ -0,0 +1,17 @@
+<style>
+div {
+    font-family: 'Ahem';
+}
+.clip {
+    color: transparent;
+    background-image: linear-gradient(60deg, blue, yellow, blue, yellow, blue);
+}
+.space {
+    color: white;
+}
+</style>
+<div>a <span class="clip">b<br>
+c<span class="space">w</span>d<br>
+<span>e<span class="space">w</span></span>f</span>
+</div>
+

Added: trunk/LayoutTests/fast/inline/inline-background-clip-text-multiline.html (0 => 284380)


--- trunk/LayoutTests/fast/inline/inline-background-clip-text-multiline.html	                        (rev 0)
+++ trunk/LayoutTests/fast/inline/inline-background-clip-text-multiline.html	2021-10-18 17:17:56 UTC (rev 284380)
@@ -0,0 +1,14 @@
+<style>
+div {
+    font-family: 'Ahem';
+}
+.clip {
+    color: transparent;
+    background-image: linear-gradient(60deg, blue, yellow, blue, yellow, blue);
+    background-clip: text;
+}
+</style>
+<div>a <span class="clip">b<br>
+c d<br>
+<span>e </span>f</span>
+</div>

Modified: trunk/LayoutTests/platform/win/TestExpectations (284379 => 284380)


--- trunk/LayoutTests/platform/win/TestExpectations	2021-10-18 17:16:46 UTC (rev 284379)
+++ trunk/LayoutTests/platform/win/TestExpectations	2021-10-18 17:17:56 UTC (rev 284380)
@@ -2912,6 +2912,7 @@
 
 fast/inline/padding-ellipsis-right.html [ ImageOnlyFailure ]
 fast/inline/inline-background-clip-text.html [ ImageOnlyFailure ]
+fast/inline/inline-background-clip-text-multiline.html [ ImageOnlyFailure ]
 
 # This test hardcodes the result of a platform-dependent font lookup algorithm.
 fast/text/fallback-language-han.html [ Skip ]

Modified: trunk/Source/WebCore/ChangeLog (284379 => 284380)


--- trunk/Source/WebCore/ChangeLog	2021-10-18 17:16:46 UTC (rev 284379)
+++ trunk/Source/WebCore/ChangeLog	2021-10-18 17:17:56 UTC (rev 284380)
@@ -1,3 +1,37 @@
+2021-10-18  Antti Koivisto  <an...@apple.com>
+
+        background-clip:text doesn't paint correctly for inline box spanning multiple lines
+        https://bugs.webkit.org/show_bug.cgi?id=231891
+
+        Reviewed by Alan Bujtas.
+
+        'background-clip: text' paints to a wrong position if the inline box spans multiple lines.
+
+        Test: fast/inline/inline-background-clip-text-multiline.html
+
+        * rendering/InlineBoxPainter.cpp:
+        (WebCore::InlineBoxPainter::paintFillLayer):
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::paintFillLayer):
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::getBackgroundRoundedRect const):
+        (WebCore::RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance const):
+
+        No need to pass box size separately as it now always matches the passed in border rect.
+
+        (WebCore::RenderBoxModelObject::paintFillLayerExtended):
+
+        The 'rect' parameter used to be either the border box rect of the box being painted or,
+        in the case of multiline inline box background image, the image strip being painted.
+
+        Make the 'rect' parameter to always be the border box and pass the background image strip
+        separately.
+
+        Use the background image strip only during background image painting.
+
+        * rendering/RenderBoxModelObject.h:
+        (WebCore::RenderBoxModelObject::paintFillLayerExtended):
+
 2021-10-18  Kimmo Kinnunen  <kkinnu...@apple.com>
 
         Cocoa GraphicsContextGLOpenGL should not use WebGLLayer

Modified: trunk/Source/WebCore/rendering/InlineBoxPainter.cpp (284379 => 284380)


--- trunk/Source/WebCore/rendering/InlineBoxPainter.cpp	2021-10-18 17:16:46 UTC (rev 284379)
+++ trunk/Source/WebCore/rendering/InlineBoxPainter.cpp	2021-10-18 17:17:56 UTC (rev 284380)
@@ -298,7 +298,7 @@
     bool hasSingleLine = !m_inlineBox.previousInlineBox() && !m_inlineBox.nextInlineBox();
 
     if (!hasFillImageOrBorderRadious || hasSingleLine || m_isRootInlineBox) {
-        renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, rect, BackgroundBleedNone, m_inlineBox, rect.size(), op);
+        renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, rect, BackgroundBleedNone, m_inlineBox, { }, op);
         return;
     }
 
@@ -306,7 +306,7 @@
     if (renderer().style().boxDecorationBreak() == BoxDecorationBreak::Clone) {
         GraphicsContextStateSaver stateSaver(m_paintInfo.context());
         m_paintInfo.context().clip({ rect.x(), rect.y(), LayoutUnit(m_inlineBox.rect().width()), LayoutUnit(m_inlineBox.rect().height()) });
-        renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, rect, BackgroundBleedNone, m_inlineBox, rect.size(), op);
+        renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, rect, BackgroundBleedNone, m_inlineBox, { }, op);
         return;
     }
 #endif
@@ -332,14 +332,16 @@
         for (auto box = m_inlineBox.iterator(); box; box.traversePreviousInlineBox())
             totalLogicalWidth += box->logicalWidth();
     }
-    LayoutUnit stripX = rect.x() - (isHorizontal() ? logicalOffsetOnLine : 0_lu);
-    LayoutUnit stripY = rect.y() - (isHorizontal() ? 0_lu : logicalOffsetOnLine);
-    LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : LayoutUnit(m_inlineBox.rect().width());
-    LayoutUnit stripHeight = isHorizontal() ? LayoutUnit(m_inlineBox.rect().height()) : totalLogicalWidth;
+    LayoutRect backgroundImageStrip {
+        rect.x() - (isHorizontal() ? logicalOffsetOnLine : 0_lu),
+        rect.y() - (isHorizontal() ? 0_lu : logicalOffsetOnLine),
+        isHorizontal() ? totalLogicalWidth : LayoutUnit(m_inlineBox.rect().width()),
+        isHorizontal() ? LayoutUnit(m_inlineBox.rect().height()) : totalLogicalWidth
+    };
 
     GraphicsContextStateSaver stateSaver(m_paintInfo.context());
-    m_paintInfo.context().clip({ rect.x(), rect.y(), LayoutUnit(m_inlineBox.rect().width()), LayoutUnit(m_inlineBox.rect().height()) });
-    renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, LayoutRect(stripX, stripY, stripWidth, stripHeight), BackgroundBleedNone, m_inlineBox, rect.size(), op);
+    m_paintInfo.context().clip(FloatRect { rect });
+    renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, rect, BackgroundBleedNone, m_inlineBox, backgroundImageStrip, op);
 }
 
 void InlineBoxPainter::paintBoxShadow(ShadowStyle shadowStyle, const LayoutRect& paintRect)

Modified: trunk/Source/WebCore/rendering/RenderBox.cpp (284379 => 284380)


--- trunk/Source/WebCore/rendering/RenderBox.cpp	2021-10-18 17:16:46 UTC (rev 284379)
+++ trunk/Source/WebCore/rendering/RenderBox.cpp	2021-10-18 17:17:56 UTC (rev 284380)
@@ -1883,7 +1883,7 @@
 void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer& fillLayer, const LayoutRect& rect,
     BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderElement* backgroundObject, BaseBackgroundColorUsage baseBgColorUsage)
 {
-    paintFillLayerExtended(paintInfo, c, fillLayer, rect, bleedAvoidance, { }, LayoutSize(), op, backgroundObject, baseBgColorUsage);
+    paintFillLayerExtended(paintInfo, c, fillLayer, rect, bleedAvoidance, { }, { }, op, backgroundObject, baseBgColorUsage);
 }
 
 static StyleImage* findLayerUsedImage(WrappedImagePtr image, const FillLayer& layers)

Modified: trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp (284379 => 284380)


--- trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp	2021-10-18 17:16:46 UTC (rev 284379)
+++ trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp	2021-10-18 17:17:56 UTC (rev 284380)
@@ -623,12 +623,12 @@
     return minimumValueForLength(padding, w);
 }
 
-RoundedRect RenderBoxModelObject::getBackgroundRoundedRect(const LayoutRect& borderRect, const InlineIterator::InlineBoxIterator& box, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
+RoundedRect RenderBoxModelObject::getBackgroundRoundedRect(const LayoutRect& borderRect, const InlineIterator::InlineBoxIterator& box,
     bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
 {
     RoundedRect border = style().getRoundedBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
     if (box && (box->nextInlineBox() || box->previousInlineBox())) {
-        RoundedRect segmentBorder = style().getRoundedBorderFor(LayoutRect(0_lu, 0_lu, inlineBoxWidth, inlineBoxHeight), includeLogicalLeftEdge, includeLogicalRightEdge);
+        RoundedRect segmentBorder = style().getRoundedBorderFor(LayoutRect(0_lu, 0_lu, borderRect.width(), borderRect.height()), includeLogicalLeftEdge, includeLogicalRightEdge);
         border.setRadii(segmentBorder.radii());
     }
     return border;
@@ -684,17 +684,17 @@
     return shrinkRectByOneDevicePixel(context, rect, document().deviceScaleFactor());
 }
 
-RoundedRect RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance(const GraphicsContext& context, const LayoutRect& borderRect, BackgroundBleedAvoidance bleedAvoidance, const InlineIterator::InlineBoxIterator& box, const LayoutSize& boxSize, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+RoundedRect RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance(const GraphicsContext& context, const LayoutRect& borderRect, BackgroundBleedAvoidance bleedAvoidance, const InlineIterator::InlineBoxIterator& box, 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.
-        return getBackgroundRoundedRect(shrinkRectByOneDevicePixel(context, borderRect, document().deviceScaleFactor()), box, boxSize.width(), boxSize.height(),
+        return getBackgroundRoundedRect(shrinkRectByOneDevicePixel(context, borderRect, document().deviceScaleFactor()), box,
             includeLogicalLeftEdge, includeLogicalRightEdge);
     }
     if (bleedAvoidance == BackgroundBleedBackgroundOverBorder)
         return style().getRoundedInnerBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
 
-    return getBackgroundRoundedRect(borderRect, box, boxSize.width(), boxSize.height(), includeLogicalLeftEdge, includeLogicalRightEdge);
+    return getBackgroundRoundedRect(borderRect, box, includeLogicalLeftEdge, includeLogicalRightEdge);
 }
 
 static void applyBoxShadowForBackground(GraphicsContext& context, const RenderStyle& style)
@@ -737,7 +737,7 @@
 }
 
 void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& color, const FillLayer& bgLayer, const LayoutRect& rect,
-    BackgroundBleedAvoidance bleedAvoidance, const InlineIterator::InlineBoxIterator& box, const LayoutSize& boxSize, CompositeOperator op, RenderElement* backgroundObject, BaseBackgroundColorUsage baseBgColorUsage)
+    BackgroundBleedAvoidance bleedAvoidance, const InlineIterator::InlineBoxIterator& box, const LayoutRect& backgroundImageStrip, CompositeOperator op, RenderElement* backgroundObject, BaseBackgroundColorUsage baseBgColorUsage)
 {
     GraphicsContext& context = paintInfo.context();
 
@@ -812,7 +812,7 @@
             applyBoxShadowForBackground(context, style());
 
         if (hasRoundedBorder && bleedAvoidance != BackgroundBleedUseTransparencyLayer) {
-            FloatRoundedRect pixelSnappedBorder = backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, boxSize,
+            FloatRoundedRect pixelSnappedBorder = backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box,
                 includeLeftEdge, includeRightEdge).pixelSnappedRoundedRectForPainting(deviceScaleFactor);
             if (pixelSnappedBorder.isRenderable()) {
                 CompositeOperator previousOperator = context.compositeOperation();
@@ -840,7 +840,7 @@
     bool clipToBorderRadius = hasRoundedBorder && !(isBorderFill && bleedAvoidance == BackgroundBleedUseTransparencyLayer);
     GraphicsContextStateSaver clipToBorderStateSaver(context, clipToBorderRadius);
     if (clipToBorderRadius) {
-        RoundedRect border = isBorderFill ? backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge) : getBackgroundRoundedRect(rect, box, boxSize.width(), boxSize.height(), includeLeftEdge, includeRightEdge);
+        RoundedRect border = isBorderFill ? backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, includeLeftEdge, includeRightEdge) : getBackgroundRoundedRect(rect, box, includeLeftEdge, includeRightEdge);
 
         // Clip to the padding or content boxes as necessary.
         if (bgLayer.clip() == FillBox::Content) {
@@ -954,7 +954,10 @@
 
     // no progressive loading of the background image
     if (!baseBgColorOnly && shouldPaintBackgroundImage) {
-        auto geometry = calculateBackgroundImageGeometry(paintInfo.paintContainer, bgLayer, rect.location(), scrolledPaintRect, backgroundObject);
+        // Multiline inline boxes paint like the image was one long strip spanning lines. The backgroundImageStrip is this fictional rectangle.
+        auto imageRect = backgroundImageStrip.isEmpty() ? scrolledPaintRect : backgroundImageStrip;
+        auto paintOffset = backgroundImageStrip.isEmpty() ? rect.location() : backgroundImageStrip.location();
+        auto geometry = calculateBackgroundImageGeometry(paintInfo.paintContainer, bgLayer, paintOffset, imageRect, backgroundObject);
         geometry.clip(LayoutRect(pixelSnappedRect));
         RefPtr<Image> image;
         if (!geometry.destRect().isEmpty() && (image = bgImage->image(backgroundObject ? backgroundObject : this, geometry.tileSize()))) {

Modified: trunk/Source/WebCore/rendering/RenderBoxModelObject.h (284379 => 284380)


--- trunk/Source/WebCore/rendering/RenderBoxModelObject.h	2021-10-18 17:16:46 UTC (rev 284379)
+++ trunk/Source/WebCore/rendering/RenderBoxModelObject.h	2021-10-18 17:17:56 UTC (rev 284380)
@@ -213,7 +213,7 @@
     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, const InlineIterator::InlineBoxIterator&, const LayoutSize& = LayoutSize(), CompositeOperator = CompositeOperator::SourceOver, RenderElement* backgroundObject = nullptr, BaseBackgroundColorUsage = BaseBackgroundColorUse);
+    void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer&, const LayoutRect&, BackgroundBleedAvoidance, const InlineIterator::InlineBoxIterator&, const LayoutRect& backgroundImageStrip = { }, CompositeOperator = CompositeOperator::SourceOver, RenderElement* backgroundObject = nullptr, BaseBackgroundColorUsage = BaseBackgroundColorUse);
 
     virtual bool boxShadowShouldBeAppliedToBackground(const LayoutPoint& absolutePaintPostion, BackgroundBleedAvoidance, const InlineIterator::InlineBoxIterator&) const;
 
@@ -259,7 +259,7 @@
         const LayoutRect& paintRect, RenderElement* = nullptr) const;
     bool borderObscuresBackgroundEdge(const FloatSize& contextScale) const;
     bool borderObscuresBackground() const;
-    RoundedRect backgroundRoundedRectAdjustedForBleedAvoidance(const GraphicsContext&, const LayoutRect&, BackgroundBleedAvoidance, const InlineIterator::InlineBoxIterator&, const LayoutSize&, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
+    RoundedRect backgroundRoundedRectAdjustedForBleedAvoidance(const GraphicsContext&, const LayoutRect&, BackgroundBleedAvoidance, const InlineIterator::InlineBoxIterator&, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
     LayoutRect borderInnerRectAdjustedForBleedAvoidance(const GraphicsContext&, const LayoutRect&, BackgroundBleedAvoidance) const;
 
     InterpolationQuality chooseInterpolationQuality(GraphicsContext&, Image&, const void*, const LayoutSize&);
@@ -310,8 +310,7 @@
 
     LayoutSize calculateFillTileSize(const FillLayer&, const LayoutSize& scaledPositioningAreaSize) const;
 
-    RoundedRect getBackgroundRoundedRect(const LayoutRect&, const InlineIterator::InlineBoxIterator&, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
-        bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
+    RoundedRect getBackgroundRoundedRect(const LayoutRect&, const InlineIterator::InlineBoxIterator&, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
     
     bool fixedBackgroundPaintsInLocalCoordinates() const;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to