Changeset 284380 in webkit


Ignore:
Timestamp:
Oct 18, 2021 10:17:56 AM (9 months ago)
Author:
Antti Koivisto
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.
Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r284377 r284380  
     12021-10-18  Antti Koivisto  <antti@apple.com>
     2
     3        background-clip:text doesn't paint correctly for inline box spanning multiple lines
     4        https://bugs.webkit.org/show_bug.cgi?id=231891
     5
     6        Reviewed by Alan Bujtas.
     7
     8        * fast/inline/inline-background-clip-text-multiline-expected.html: Added.
     9        * fast/inline/inline-background-clip-text-multiline.html: Added.
     10
    1112021-10-18  Ayumi Kojima  <ayumi_kojima@apple.com>
    212
  • trunk/LayoutTests/platform/win/TestExpectations

    r284334 r284380  
    29132913fast/inline/padding-ellipsis-right.html [ ImageOnlyFailure ]
    29142914fast/inline/inline-background-clip-text.html [ ImageOnlyFailure ]
     2915fast/inline/inline-background-clip-text-multiline.html [ ImageOnlyFailure ]
    29152916
    29162917# This test hardcodes the result of a platform-dependent font lookup algorithm.
  • trunk/Source/WebCore/ChangeLog

    r284371 r284380  
     12021-10-18  Antti Koivisto  <antti@apple.com>
     2
     3        background-clip:text doesn't paint correctly for inline box spanning multiple lines
     4        https://bugs.webkit.org/show_bug.cgi?id=231891
     5
     6        Reviewed by Alan Bujtas.
     7
     8        'background-clip: text' paints to a wrong position if the inline box spans multiple lines.
     9
     10        Test: fast/inline/inline-background-clip-text-multiline.html
     11
     12        * rendering/InlineBoxPainter.cpp:
     13        (WebCore::InlineBoxPainter::paintFillLayer):
     14        * rendering/RenderBox.cpp:
     15        (WebCore::RenderBox::paintFillLayer):
     16        * rendering/RenderBoxModelObject.cpp:
     17        (WebCore::RenderBoxModelObject::getBackgroundRoundedRect const):
     18        (WebCore::RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance const):
     19
     20        No need to pass box size separately as it now always matches the passed in border rect.
     21
     22        (WebCore::RenderBoxModelObject::paintFillLayerExtended):
     23
     24        The 'rect' parameter used to be either the border box rect of the box being painted or,
     25        in the case of multiline inline box background image, the image strip being painted.
     26
     27        Make the 'rect' parameter to always be the border box and pass the background image strip
     28        separately.
     29
     30        Use the background image strip only during background image painting.
     31
     32        * rendering/RenderBoxModelObject.h:
     33        (WebCore::RenderBoxModelObject::paintFillLayerExtended):
     34
    1352021-10-18  Kimmo Kinnunen  <kkinnunen@apple.com>
    236
  • trunk/Source/WebCore/rendering/InlineBoxPainter.cpp

    r283981 r284380  
    299299
    300300    if (!hasFillImageOrBorderRadious || hasSingleLine || m_isRootInlineBox) {
    301         renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, rect, BackgroundBleedNone, m_inlineBox, rect.size(), op);
     301        renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, rect, BackgroundBleedNone, m_inlineBox, { }, op);
    302302        return;
    303303    }
     
    307307        GraphicsContextStateSaver stateSaver(m_paintInfo.context());
    308308        m_paintInfo.context().clip({ rect.x(), rect.y(), LayoutUnit(m_inlineBox.rect().width()), LayoutUnit(m_inlineBox.rect().height()) });
    309         renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, rect, BackgroundBleedNone, m_inlineBox, rect.size(), op);
     309        renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, rect, BackgroundBleedNone, m_inlineBox, { }, op);
    310310        return;
    311311    }
     
    333333            totalLogicalWidth += box->logicalWidth();
    334334    }
    335     LayoutUnit stripX = rect.x() - (isHorizontal() ? logicalOffsetOnLine : 0_lu);
    336     LayoutUnit stripY = rect.y() - (isHorizontal() ? 0_lu : logicalOffsetOnLine);
    337     LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : LayoutUnit(m_inlineBox.rect().width());
    338     LayoutUnit stripHeight = isHorizontal() ? LayoutUnit(m_inlineBox.rect().height()) : totalLogicalWidth;
     335    LayoutRect backgroundImageStrip {
     336        rect.x() - (isHorizontal() ? logicalOffsetOnLine : 0_lu),
     337        rect.y() - (isHorizontal() ? 0_lu : logicalOffsetOnLine),
     338        isHorizontal() ? totalLogicalWidth : LayoutUnit(m_inlineBox.rect().width()),
     339        isHorizontal() ? LayoutUnit(m_inlineBox.rect().height()) : totalLogicalWidth
     340    };
    339341
    340342    GraphicsContextStateSaver stateSaver(m_paintInfo.context());
    341     m_paintInfo.context().clip({ rect.x(), rect.y(), LayoutUnit(m_inlineBox.rect().width()), LayoutUnit(m_inlineBox.rect().height()) });
    342     renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, LayoutRect(stripX, stripY, stripWidth, stripHeight), BackgroundBleedNone, m_inlineBox, rect.size(), op);
     343    m_paintInfo.context().clip(FloatRect { rect });
     344    renderer().paintFillLayerExtended(m_paintInfo, color, fillLayer, rect, BackgroundBleedNone, m_inlineBox, backgroundImageStrip, op);
    343345}
    344346
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r283893 r284380  
    18841884    BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderElement* backgroundObject, BaseBackgroundColorUsage baseBgColorUsage)
    18851885{
    1886     paintFillLayerExtended(paintInfo, c, fillLayer, rect, bleedAvoidance, { }, LayoutSize(), op, backgroundObject, baseBgColorUsage);
     1886    paintFillLayerExtended(paintInfo, c, fillLayer, rect, bleedAvoidance, { }, { }, op, backgroundObject, baseBgColorUsage);
    18871887}
    18881888
  • trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp

    r284334 r284380  
    624624}
    625625
    626 RoundedRect RenderBoxModelObject::getBackgroundRoundedRect(const LayoutRect& borderRect, const InlineIterator::InlineBoxIterator& box, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
     626RoundedRect RenderBoxModelObject::getBackgroundRoundedRect(const LayoutRect& borderRect, const InlineIterator::InlineBoxIterator& box,
    627627    bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
    628628{
    629629    RoundedRect border = style().getRoundedBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
    630630    if (box && (box->nextInlineBox() || box->previousInlineBox())) {
    631         RoundedRect segmentBorder = style().getRoundedBorderFor(LayoutRect(0_lu, 0_lu, inlineBoxWidth, inlineBoxHeight), includeLogicalLeftEdge, includeLogicalRightEdge);
     631        RoundedRect segmentBorder = style().getRoundedBorderFor(LayoutRect(0_lu, 0_lu, borderRect.width(), borderRect.height()), includeLogicalLeftEdge, includeLogicalRightEdge);
    632632        border.setRadii(segmentBorder.radii());
    633633    }
     
    685685}
    686686
    687 RoundedRect RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance(const GraphicsContext& context, const LayoutRect& borderRect, BackgroundBleedAvoidance bleedAvoidance, const InlineIterator::InlineBoxIterator& box, const LayoutSize& boxSize, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
     687RoundedRect RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance(const GraphicsContext& context, const LayoutRect& borderRect, BackgroundBleedAvoidance bleedAvoidance, const InlineIterator::InlineBoxIterator& box, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
    688688{
    689689    if (bleedAvoidance == BackgroundBleedShrinkBackground) {
    690690        // We shrink the rectangle by one device pixel on each side because the bleed is one pixel maximum.
    691         return getBackgroundRoundedRect(shrinkRectByOneDevicePixel(context, borderRect, document().deviceScaleFactor()), box, boxSize.width(), boxSize.height(),
     691        return getBackgroundRoundedRect(shrinkRectByOneDevicePixel(context, borderRect, document().deviceScaleFactor()), box,
    692692            includeLogicalLeftEdge, includeLogicalRightEdge);
    693693    }
     
    695695        return style().getRoundedInnerBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
    696696
    697     return getBackgroundRoundedRect(borderRect, box, boxSize.width(), boxSize.height(), includeLogicalLeftEdge, includeLogicalRightEdge);
     697    return getBackgroundRoundedRect(borderRect, box, includeLogicalLeftEdge, includeLogicalRightEdge);
    698698}
    699699
     
    738738
    739739void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& color, const FillLayer& bgLayer, const LayoutRect& rect,
    740     BackgroundBleedAvoidance bleedAvoidance, const InlineIterator::InlineBoxIterator& box, const LayoutSize& boxSize, CompositeOperator op, RenderElement* backgroundObject, BaseBackgroundColorUsage baseBgColorUsage)
     740    BackgroundBleedAvoidance bleedAvoidance, const InlineIterator::InlineBoxIterator& box, const LayoutRect& backgroundImageStrip, CompositeOperator op, RenderElement* backgroundObject, BaseBackgroundColorUsage baseBgColorUsage)
    741741{
    742742    GraphicsContext& context = paintInfo.context();
     
    813813
    814814        if (hasRoundedBorder && bleedAvoidance != BackgroundBleedUseTransparencyLayer) {
    815             FloatRoundedRect pixelSnappedBorder = backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, boxSize,
     815            FloatRoundedRect pixelSnappedBorder = backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box,
    816816                includeLeftEdge, includeRightEdge).pixelSnappedRoundedRectForPainting(deviceScaleFactor);
    817817            if (pixelSnappedBorder.isRenderable()) {
     
    841841    GraphicsContextStateSaver clipToBorderStateSaver(context, clipToBorderRadius);
    842842    if (clipToBorderRadius) {
    843         RoundedRect border = isBorderFill ? backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge) : getBackgroundRoundedRect(rect, box, boxSize.width(), boxSize.height(), includeLeftEdge, includeRightEdge);
     843        RoundedRect border = isBorderFill ? backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, includeLeftEdge, includeRightEdge) : getBackgroundRoundedRect(rect, box, includeLeftEdge, includeRightEdge);
    844844
    845845        // Clip to the padding or content boxes as necessary.
     
    955955    // no progressive loading of the background image
    956956    if (!baseBgColorOnly && shouldPaintBackgroundImage) {
    957         auto geometry = calculateBackgroundImageGeometry(paintInfo.paintContainer, bgLayer, rect.location(), scrolledPaintRect, backgroundObject);
     957        // Multiline inline boxes paint like the image was one long strip spanning lines. The backgroundImageStrip is this fictional rectangle.
     958        auto imageRect = backgroundImageStrip.isEmpty() ? scrolledPaintRect : backgroundImageStrip;
     959        auto paintOffset = backgroundImageStrip.isEmpty() ? rect.location() : backgroundImageStrip.location();
     960        auto geometry = calculateBackgroundImageGeometry(paintInfo.paintContainer, bgLayer, paintOffset, imageRect, backgroundObject);
    958961        geometry.clip(LayoutRect(pixelSnappedRect));
    959962        RefPtr<Image> image;
  • trunk/Source/WebCore/rendering/RenderBoxModelObject.h

    r283893 r284380  
    214214    bool paintNinePieceImage(GraphicsContext&, const LayoutRect&, const RenderStyle&, const NinePieceImage&, CompositeOperator = CompositeOperator::SourceOver);
    215215    void paintBoxShadow(const PaintInfo&, const LayoutRect&, const RenderStyle&, ShadowStyle, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
    216     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);
     216    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);
    217217
    218218    virtual bool boxShadowShouldBeAppliedToBackground(const LayoutPoint& absolutePaintPostion, BackgroundBleedAvoidance, const InlineIterator::InlineBoxIterator&) const;
     
    260260    bool borderObscuresBackgroundEdge(const FloatSize& contextScale) const;
    261261    bool borderObscuresBackground() const;
    262     RoundedRect backgroundRoundedRectAdjustedForBleedAvoidance(const GraphicsContext&, const LayoutRect&, BackgroundBleedAvoidance, const InlineIterator::InlineBoxIterator&, const LayoutSize&, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
     262    RoundedRect backgroundRoundedRectAdjustedForBleedAvoidance(const GraphicsContext&, const LayoutRect&, BackgroundBleedAvoidance, const InlineIterator::InlineBoxIterator&, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
    263263    LayoutRect borderInnerRectAdjustedForBleedAvoidance(const GraphicsContext&, const LayoutRect&, BackgroundBleedAvoidance) const;
    264264
     
    311311    LayoutSize calculateFillTileSize(const FillLayer&, const LayoutSize& scaledPositioningAreaSize) const;
    312312
    313     RoundedRect getBackgroundRoundedRect(const LayoutRect&, const InlineIterator::InlineBoxIterator&, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
    314         bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
     313    RoundedRect getBackgroundRoundedRect(const LayoutRect&, const InlineIterator::InlineBoxIterator&, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
    315314   
    316315    bool fixedBackgroundPaintsInLocalCoordinates() const;
Note: See TracChangeset for help on using the changeset viewer.