Changeset 286955 in webkit


Ignore:
Timestamp:
Dec 13, 2021 10:23:00 AM (7 months ago)
Author:
ntim@apple.com
Message:

Fix paint order of CSS text decorations
https://bugs.webkit.org/show_bug.cgi?id=227445

Reviewed by Simon Fraser.

Source/WebCore:

  • rendering/TextBoxPainter.cpp:

(WebCore::TextBoxPainter::paintForegroundAndDecorations):
(WebCore::TextBoxPainter::createDecorationPainter):
(WebCore::TextBoxPainter::paintBackgroundDecorations):
(WebCore::TextBoxPainter::paintForegroundDecorations):
(WebCore::TextBoxPainter::paintDecoration): Deleted.

  • rendering/TextBoxPainter.h:
  • rendering/TextDecorationPainter.cpp:

(WebCore::TextDecorationPainter::paintBackgroundDecorations):
(WebCore::TextDecorationPainter::paintForegroundDecorations):
(WebCore::TextDecorationPainter::paintLineThrough):
(WebCore::TextDecorationPainter::paintTextDecoration): Deleted.

  • rendering/TextDecorationPainter.h:

LayoutTests:

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r286952 r286955  
     12021-12-13  Tim Nguyen  <ntim@apple.com>
     2
     3        Fix paint order of CSS text decorations
     4        https://bugs.webkit.org/show_bug.cgi?id=227445
     5
     6        Reviewed by Simon Fraser.
     7
     8        * TestExpectations:
     9
    1102021-12-13  Sergio Villar Senin  <svillar@igalia.com>
    211
  • trunk/LayoutTests/TestExpectations

    r286952 r286955  
    34323432webkit.org/b/230041 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-color-selection-pseudo-01.html [ ImageOnlyFailure ]
    34333433webkit.org/b/203530 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-line-recalc.html [ ImageOnlyFailure ]
    3434 webkit.org/b/203531 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-propagation-shadow.html [ ImageOnlyFailure ]
    34353434webkit.org/b/203528 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-thickness-linethrough-001.html [ ImageOnlyFailure ]
    34363435webkit.org/b/203528 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-thickness-overline-001.html [ ImageOnlyFailure ]
     
    34723471imported/w3c/web-platform-tests/css/css-text-decor/text-emphasis-style-string-001.xht [ ImageOnlyFailure ]
    34733472webkit.org/b/230083 imported/w3c/web-platform-tests/css/css-text-decor/text-underline-offset-001.html [ ImageOnlyFailure ]
    3474 imported/w3c/web-platform-tests/css/css-text-decor/text-underline-offset-zero-position.html [ ImageOnlyFailure ]
    34753473
    34763474# wpt css-position failures
  • trunk/Source/WebCore/ChangeLog

    r286953 r286955  
     12021-12-13  Tim Nguyen  <ntim@apple.com>
     2
     3        Fix paint order of CSS text decorations
     4        https://bugs.webkit.org/show_bug.cgi?id=227445
     5
     6        Reviewed by Simon Fraser.
     7
     8        * rendering/TextBoxPainter.cpp:
     9        (WebCore::TextBoxPainter::paintForegroundAndDecorations):
     10        (WebCore::TextBoxPainter::createDecorationPainter):
     11        (WebCore::TextBoxPainter::paintBackgroundDecorations):
     12        (WebCore::TextBoxPainter::paintForegroundDecorations):
     13        (WebCore::TextBoxPainter::paintDecoration): Deleted.
     14        * rendering/TextBoxPainter.h:
     15        * rendering/TextDecorationPainter.cpp:
     16        (WebCore::TextDecorationPainter::paintBackgroundDecorations):
     17        (WebCore::TextDecorationPainter::paintForegroundDecorations):
     18        (WebCore::TextDecorationPainter::paintLineThrough):
     19        (WebCore::TextDecorationPainter::paintTextDecoration): Deleted.
     20        * rendering/TextDecorationPainter.h:
     21
    1222021-12-13  Jer Noble  <jer.noble@apple.com>
    223
  • trunk/Source/WebCore/rendering/TextBoxPainter.cpp

    r284437 r286955  
    189189    auto coalescedStyledMarkedTexts = StyledMarkedText::coalesceAdjacentWithEqualForeground(styledMarkedTexts);
    190190
    191     for (auto& markedText : coalescedStyledMarkedTexts)
    192         paintForeground(markedText);
    193 
    194191    auto textDecorations = m_style.textDecorationsInEffect();
    195192    bool highlightDecorations = !MarkedText::collectForHighlights(m_renderer, m_selectableRange, MarkedText::PaintPhase::Decoration).isEmpty();
     
    225222        auto coalescedStyledMarkedTexts = StyledMarkedText::coalesceAdjacentWithEqualDecorations(styledMarkedTexts);
    226223
     224        for (auto& markedText : coalescedStyledMarkedTexts) {
     225            unsigned startOffset = markedText.startOffset;
     226            unsigned endOffset = markedText.endOffset;
     227            if (startOffset < endOffset) {
     228                // Avoid measuring the text when the entire line box is selected as an optimization.
     229                FloatRect snappedSelectionRect = m_paintRect;
     230                if (startOffset || endOffset != m_paintTextRun.length()) {
     231                    LayoutRect selectionRect = { m_paintRect.x(), m_paintRect.y(), m_paintRect.width(), m_paintRect.height() };
     232                    fontCascade().adjustSelectionRectForText(m_paintTextRun, selectionRect, startOffset, endOffset);
     233                    snappedSelectionRect = snapRectToDevicePixelsWithWritingDirection(selectionRect, m_document.deviceScaleFactor(), m_paintTextRun.ltr());
     234                }
     235
     236                TextDecorationPainter decorationPainter = createDecorationPainter(markedText, textDecorationSelectionClipOutRect, snappedSelectionRect);
     237                paintBackgroundDecorations(decorationPainter, markedText, snappedSelectionRect);
     238                paintForeground(markedText);
     239                paintForegroundDecorations(decorationPainter, snappedSelectionRect);
     240            }
     241        }
     242    } else {
    227243        for (auto& markedText : coalescedStyledMarkedTexts)
    228             paintDecoration(markedText, textDecorationSelectionClipOutRect);
     244            paintForeground(markedText);
    229245    }
    230246}
     
    340356}
    341357
    342 void TextBoxPainter::paintDecoration(const StyledMarkedText& markedText, const FloatRect& clipOutRect)
    343 {
    344     // 1. Compute text selection
    345     unsigned startOffset = markedText.startOffset;
    346     unsigned endOffset = markedText.endOffset;
    347     if (startOffset >= endOffset)
    348         return;
    349 
     358TextDecorationPainter TextBoxPainter::createDecorationPainter(const StyledMarkedText& markedText, const FloatRect& clipOutRect, const FloatRect& snappedSelectionRect)
     359{
    350360    GraphicsContext& context = m_paintInfo.context();
    351     const FontCascade& font = fontCascade();
    352361
    353362    updateGraphicsContext(context, markedText.style.textStyles);
     
    359368    // Note that if the text is truncated, we let the thing being painted in the truncation
    360369    // draw its own decoration.
    361 
    362     // Avoid measuring the text when the entire line box is selected as an optimization.
    363     FloatRect snappedSelectionRect = m_paintRect;
    364     if (startOffset || endOffset != m_paintTextRun.length()) {
    365         LayoutRect selectionRect = { m_paintRect.x(), m_paintRect.y(), m_paintRect.width(), m_paintRect.height() };
    366         font.adjustSelectionRectForText(m_paintTextRun, selectionRect, startOffset, endOffset);
    367         snappedSelectionRect = snapRectToDevicePixelsWithWritingDirection(selectionRect, m_document.deviceScaleFactor(), m_paintTextRun.ltr());
    368     }
    369 
    370     // 2. Paint
     370    GraphicsContextStateSaver stateSaver { context, false };
     371    bool isDraggedContent = markedText.type == MarkedText::DraggedContent;
     372    if (isDraggedContent || !clipOutRect.isEmpty()) {
     373        stateSaver.save();
     374        if (isDraggedContent)
     375            context.setAlpha(markedText.style.alpha);
     376        if (!clipOutRect.isEmpty())
     377            context.clipOut(clipOutRect);
     378    }
     379
     380    // Create painter
     381    const FontCascade& font = fontCascade();
    371382    auto textDecorations = m_style.textDecorationsInEffect();
    372383    textDecorations.add(TextDecorationPainter::textDecorationsInEffectForStyle(markedText.style.textDecorationStyles));
     
    381392    }
    382393
    383     {
    384         GraphicsContextStateSaver stateSaver { context, false };
    385         bool isDraggedContent = markedText.type == MarkedText::DraggedContent;
    386         if (isDraggedContent || !clipOutRect.isEmpty()) {
    387             stateSaver.save();
    388             if (isDraggedContent)
    389                 context.setAlpha(markedText.style.alpha);
    390             if (!clipOutRect.isEmpty())
    391                 context.clipOut(clipOutRect);
    392         }
    393         decorationPainter.paintTextDecoration(m_paintTextRun.subRun(startOffset, endOffset - startOffset), textOriginFromPaintRect(snappedSelectionRect), snappedSelectionRect.location());
    394     }
    395 
    396     if (isCombinedText)
     394    return decorationPainter;
     395}
     396
     397void TextBoxPainter::paintBackgroundDecorations(TextDecorationPainter& decorationPainter, const StyledMarkedText& markedText, const FloatRect& snappedSelectionRect)
     398{
     399    decorationPainter.paintBackgroundDecorations(m_paintTextRun.subRun(markedText.startOffset, markedText.endOffset - markedText.startOffset), textOriginFromPaintRect(snappedSelectionRect), snappedSelectionRect.location());
     400
     401    if (textBox().isCombinedText()) {
     402        GraphicsContext& context = m_paintInfo.context();
    397403        context.concatCTM(rotation(m_paintRect, Counterclockwise));
     404    }
     405}
     406
     407void TextBoxPainter::paintForegroundDecorations(TextDecorationPainter& decorationPainter, const FloatRect& snappedSelectionRect)
     408{
     409    decorationPainter.paintForegroundDecorations(snappedSelectionRect.location());
     410
     411    if (textBox().isCombinedText()) {
     412        GraphicsContext& context = m_paintInfo.context();
     413        context.concatCTM(rotation(m_paintRect, Counterclockwise));
     414    }
    398415}
    399416
  • trunk/Source/WebCore/rendering/TextBoxPainter.h

    r284334 r286955  
    4040class RenderText;
    4141class ShadowData;
     42class TextDecorationPainter;
    4243struct CompositionUnderline;
    4344struct MarkedText;
     
    7273    void paintBackground(const StyledMarkedText&);
    7374    void paintForeground(const StyledMarkedText&);
    74     void paintDecoration(const StyledMarkedText&, const FloatRect& clipOutRect);
     75    TextDecorationPainter createDecorationPainter(const StyledMarkedText&, const FloatRect&, const FloatRect&);
     76    void paintBackgroundDecorations(TextDecorationPainter&, const StyledMarkedText&, const FloatRect&);
     77    void paintForegroundDecorations(TextDecorationPainter&, const FloatRect&);
    7578    void paintCompositionUnderline(const CompositionUnderline&);
    7679    void paintPlatformDocumentMarker(const MarkedText&);
  • trunk/Source/WebCore/rendering/TextDecorationPainter.cpp

    r285904 r286955  
    202202}
    203203
    204 void TextDecorationPainter::paintTextDecoration(const TextRun& textRun, const FloatPoint& textOrigin, const FloatPoint& boxOrigin)
     204// Paint text-shadow, underline, overline
     205void TextDecorationPainter::paintBackgroundDecorations(const TextRun& textRun, const FloatPoint& textOrigin, const FloatPoint& boxOrigin)
    205206{
    206207    const auto& fontMetrics = m_lineStyle.fontMetrics();
     
    229230                m_context.drawLineForText(rect, m_isPrinting, style == TextDecorationStyle::Double, strokeStyle);
    230231            }
    231         } else {
    232             ASSERT(decoration == TextDecorationLine::LineThrough);
    233             m_context.drawLineForText(rect, m_isPrinting, style == TextDecorationStyle::Double, strokeStyle);
    234         }
     232        } else
     233            ASSERT_NOT_REACHED();
    235234    };
    236235
     
    294293            paintDecoration(TextDecorationLine::Overline, m_styles.overlineStyle, m_styles.overlineColor, rect);
    295294        }
    296         if (m_decorations.contains(TextDecorationLine::LineThrough)) {
    297             FloatRect rect(localOrigin, FloatSize(m_width, textDecorationThickness));
    298             float autoTextDecorationThickness = TextDecorationThickness::createWithAuto().resolve(m_lineStyle.computedFontSize(), fontMetrics);
    299             auto center = 2 * fontMetrics.floatAscent() / 3 + autoTextDecorationThickness / 2;
    300             rect.move(0, center - textDecorationThickness / 2);
    301             paintDecoration(TextDecorationLine::LineThrough, m_styles.linethroughStyle, m_styles.linethroughColor, rect);
    302         }
     295
     296        // We only want to paint the shadow, hence the transparent color, not the actual line-through,
     297        // which will be painted in paintForegroundDecorations().
     298        if (shadow && m_decorations.contains(TextDecorationLine::LineThrough))
     299            paintLineThrough(Color::transparentBlack, textDecorationThickness, localOrigin);
    303300    } while (shadow);
    304301
     
    307304    else if (m_shadow)
    308305        m_context.clearShadow();
     306}
     307
     308void TextDecorationPainter::paintForegroundDecorations(const FloatPoint& boxOrigin)
     309{
     310    if (!m_decorations.contains(TextDecorationLine::LineThrough))
     311        return;
     312
     313    float textDecorationThickness = m_lineStyle.textDecorationThickness().resolve(m_lineStyle.computedFontSize(), m_lineStyle.fontMetrics());
     314    paintLineThrough(m_styles.linethroughColor, textDecorationThickness, boxOrigin);
     315}
     316
     317void TextDecorationPainter::paintLineThrough(const Color& color, float thickness, const FloatPoint& localOrigin)
     318{
     319    const auto& fontMetrics = m_lineStyle.fontMetrics();
     320    FloatRect rect(localOrigin, FloatSize(m_width, thickness));
     321    float autoTextDecorationThickness = TextDecorationThickness::createWithAuto().resolve(m_lineStyle.computedFontSize(), fontMetrics);
     322    auto center = 2 * fontMetrics.floatAscent() / 3 + autoTextDecorationThickness / 2;
     323    rect.move(0, center - thickness / 2);
     324
     325    m_context.setStrokeColor(color);
     326
     327    TextDecorationStyle style = m_styles.linethroughStyle;
     328    auto strokeStyle = textDecorationStyleToStrokeStyle(style);
     329
     330    if (style == TextDecorationStyle::Wavy)
     331        strokeWavyTextDecoration(m_context, rect, m_lineStyle.computedFontPixelSize());
     332    else
     333        m_context.drawLineForText(rect, m_isPrinting, style == TextDecorationStyle::Double, strokeStyle);
    309334}
    310335
  • trunk/Source/WebCore/rendering/TextDecorationPainter.h

    r285904 r286955  
    5353    void setShadowColorFilter(const FilterOperations* colorFilter) { m_shadowColorFilter = colorFilter; }
    5454
    55     void paintTextDecoration(const TextRun&, const FloatPoint& textOrigin, const FloatPoint& boxOrigin);
     55    void paintBackgroundDecorations(const TextRun&, const FloatPoint& textOrigin, const FloatPoint& boxOrigin);
     56    void paintForegroundDecorations(const FloatPoint& boxOrigin);
     57    void paintLineThrough(const Color&, float thickness, const FloatPoint& localOrigin);
    5658
    5759    struct Styles {
  • trunk/Source/WebCore/style/InlineTextBoxStyle.cpp

    r285904 r286955  
    190190
    191191    // These metrics must match where underlines get drawn.
    192     // FIXME: Share the code in TextDecorationPainter::paintTextDecoration() so we can just query it for the painted geometry.
     192    // FIXME: Share the code in TextDecorationPainter::paintBackgroundDecorations() so we can just query it for the painted geometry.
    193193    if (decoration & TextDecorationLine::Underline) {
    194194        // Compensate for the integral ceiling in GraphicsContext::computeLineBoundsAndAntialiasingModeForText()
Note: See TracChangeset for help on using the changeset viewer.