Changeset 237903 in webkit


Ignore:
Timestamp:
Nov 6, 2018 5:22:41 PM (3 years ago)
Author:
mmaxfield@apple.com
Message:

Implement text-underline-offset and text-decoration-thickness
https://bugs.webkit.org/show_bug.cgi?id=190774

Reviewed by Dean Jackson.

Source/WebCore:

Because of our existing infrastructure for text decorations, adding support for these
is fairly simple. This patch updates our existing functions to handle thick & placed
underlines, as well as updating our repaint code to correcly handle repainting them.
It also handles animations.

Tests: animations/text-decoration-thickness.html

animations/text-underline-offset.html
fast/css3-text/css3-text-decoration/text-decoration-offset-2.html
fast/css3-text/css3-text-decoration/text-decoration-offset-3.html
fast/css3-text/css3-text-decoration/text-decoration-offset-auto-length.html
fast/css3-text/css3-text-decoration/text-decoration-offset-baseline.html
fast/css3-text/css3-text-decoration/text-decoration-offset-from-font-auto.html
fast/css3-text/css3-text-decoration/text-decoration-offset-from-font-length.html
fast/css3-text/css3-text-decoration/text-decoration-offset-repaint.html
fast/css3-text/css3-text-decoration/text-decoration-offset-under-auto.html
fast/css3-text/css3-text-decoration/text-decoration-offset-under-length.html
fast/css3-text/css3-text-decoration/text-decoration-offset.html
fast/css3-text/css3-text-decoration/text-decoration-thickness-length.html
fast/css3-text/css3-text-decoration/text-decoration-thickness-repaint.html

  • page/animation/CSSPropertyAnimation.cpp:

(WebCore::blendFunc):
(WebCore::CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap):

  • platform/graphics/FontMetrics.h:

(WebCore::FontMetrics::underlinePosition const):
(WebCore::FontMetrics::setUnderlinePosition):
(WebCore::FontMetrics::underlineThickness const):
(WebCore::FontMetrics::setUnderlineThickness):

  • platform/graphics/cocoa/FontCocoa.mm:

(WebCore::Font::platformInit):

  • rendering/InlineFlowBox.cpp:

(WebCore::InlineFlowBox::addToLine):

  • rendering/SimpleLineLayout.cpp:

(WebCore::SimpleLineLayout::canUseForStyle):

  • rendering/TextDecorationPainter.cpp:

(WebCore::TextDecorationPainter::paintTextDecoration):

  • rendering/style/RenderStyle.cpp:

(WebCore::RenderStyle::changeAffectsVisualOverflow const):

  • rendering/style/TextDecorationThickness.h:

(WebCore::TextDecorationThickness::resolve const):

  • style/InlineTextBoxStyle.cpp:

(WebCore::computeUnderlineOffset):
(WebCore::visualOverflowForDecorations):

  • style/InlineTextBoxStyle.h:

(WebCore::textDecorationStrokeThickness): Deleted.

LayoutTests:

  • animations/text-decoration-thickness-expected.txt: Added.
  • animations/text-decoration-thickness.html: Added.
  • animations/text-underline-offset-expected.txt: Added.
  • animations/text-underline-offset.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-2-expected-mismatch.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-2.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-3-expected-mismatch.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-3.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-auto-length-expected.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-auto-length.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-baseline-expected.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-baseline.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-expected-mismatch.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-from-font-auto-expected.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-from-font-auto.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-from-font-length-expected.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-from-font-length.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-repaint-expected.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-repaint.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-under-auto-expected.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-under-auto.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-under-length-expected.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset-under-length.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-offset.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-thickness-length-expected.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-thickness-length.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-thickness-repaint-expected.html: Added.
  • fast/css3-text/css3-text-decoration/text-decoration-thickness-repaint.html: Added.
Location:
trunk
Files:
28 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r237902 r237903  
     12018-11-06  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        Implement text-underline-offset and text-decoration-thickness
     4        https://bugs.webkit.org/show_bug.cgi?id=190774
     5
     6        Reviewed by Dean Jackson.
     7
     8        * animations/text-decoration-thickness-expected.txt: Added.
     9        * animations/text-decoration-thickness.html: Added.
     10        * animations/text-underline-offset-expected.txt: Added.
     11        * animations/text-underline-offset.html: Added.
     12        * fast/css3-text/css3-text-decoration/text-decoration-offset-2-expected-mismatch.html: Added.
     13        * fast/css3-text/css3-text-decoration/text-decoration-offset-2.html: Added.
     14        * fast/css3-text/css3-text-decoration/text-decoration-offset-3-expected-mismatch.html: Added.
     15        * fast/css3-text/css3-text-decoration/text-decoration-offset-3.html: Added.
     16        * fast/css3-text/css3-text-decoration/text-decoration-offset-auto-length-expected.html: Added.
     17        * fast/css3-text/css3-text-decoration/text-decoration-offset-auto-length.html: Added.
     18        * fast/css3-text/css3-text-decoration/text-decoration-offset-baseline-expected.html: Added.
     19        * fast/css3-text/css3-text-decoration/text-decoration-offset-baseline.html: Added.
     20        * fast/css3-text/css3-text-decoration/text-decoration-offset-expected-mismatch.html: Added.
     21        * fast/css3-text/css3-text-decoration/text-decoration-offset-from-font-auto-expected.html: Added.
     22        * fast/css3-text/css3-text-decoration/text-decoration-offset-from-font-auto.html: Added.
     23        * fast/css3-text/css3-text-decoration/text-decoration-offset-from-font-length-expected.html: Added.
     24        * fast/css3-text/css3-text-decoration/text-decoration-offset-from-font-length.html: Added.
     25        * fast/css3-text/css3-text-decoration/text-decoration-offset-repaint-expected.html: Added.
     26        * fast/css3-text/css3-text-decoration/text-decoration-offset-repaint.html: Added.
     27        * fast/css3-text/css3-text-decoration/text-decoration-offset-under-auto-expected.html: Added.
     28        * fast/css3-text/css3-text-decoration/text-decoration-offset-under-auto.html: Added.
     29        * fast/css3-text/css3-text-decoration/text-decoration-offset-under-length-expected.html: Added.
     30        * fast/css3-text/css3-text-decoration/text-decoration-offset-under-length.html: Added.
     31        * fast/css3-text/css3-text-decoration/text-decoration-offset.html: Added.
     32        * fast/css3-text/css3-text-decoration/text-decoration-thickness-length-expected.html: Added.
     33        * fast/css3-text/css3-text-decoration/text-decoration-thickness-length.html: Added.
     34        * fast/css3-text/css3-text-decoration/text-decoration-thickness-repaint-expected.html: Added.
     35        * fast/css3-text/css3-text-decoration/text-decoration-thickness-repaint.html: Added.
     36
    1372018-11-06  Dean Jackson  <dino@apple.com>
    238
  • trunk/Source/WebCore/ChangeLog

    r237895 r237903  
     12018-11-06  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        Implement text-underline-offset and text-decoration-thickness
     4        https://bugs.webkit.org/show_bug.cgi?id=190774
     5
     6        Reviewed by Dean Jackson.
     7
     8        Because of our existing infrastructure for text decorations, adding support for these
     9        is fairly simple. This patch updates our existing functions to handle thick & placed
     10        underlines, as well as updating our repaint code to correcly handle repainting them.
     11        It also handles animations.
     12
     13        Tests: animations/text-decoration-thickness.html
     14               animations/text-underline-offset.html
     15               fast/css3-text/css3-text-decoration/text-decoration-offset-2.html
     16               fast/css3-text/css3-text-decoration/text-decoration-offset-3.html
     17               fast/css3-text/css3-text-decoration/text-decoration-offset-auto-length.html
     18               fast/css3-text/css3-text-decoration/text-decoration-offset-baseline.html
     19               fast/css3-text/css3-text-decoration/text-decoration-offset-from-font-auto.html
     20               fast/css3-text/css3-text-decoration/text-decoration-offset-from-font-length.html
     21               fast/css3-text/css3-text-decoration/text-decoration-offset-repaint.html
     22               fast/css3-text/css3-text-decoration/text-decoration-offset-under-auto.html
     23               fast/css3-text/css3-text-decoration/text-decoration-offset-under-length.html
     24               fast/css3-text/css3-text-decoration/text-decoration-offset.html
     25               fast/css3-text/css3-text-decoration/text-decoration-thickness-length.html
     26               fast/css3-text/css3-text-decoration/text-decoration-thickness-repaint.html
     27
     28        * page/animation/CSSPropertyAnimation.cpp:
     29        (WebCore::blendFunc):
     30        (WebCore::CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap):
     31        * platform/graphics/FontMetrics.h:
     32        (WebCore::FontMetrics::underlinePosition const):
     33        (WebCore::FontMetrics::setUnderlinePosition):
     34        (WebCore::FontMetrics::underlineThickness const):
     35        (WebCore::FontMetrics::setUnderlineThickness):
     36        * platform/graphics/cocoa/FontCocoa.mm:
     37        (WebCore::Font::platformInit):
     38        * rendering/InlineFlowBox.cpp:
     39        (WebCore::InlineFlowBox::addToLine):
     40        * rendering/SimpleLineLayout.cpp:
     41        (WebCore::SimpleLineLayout::canUseForStyle):
     42        * rendering/TextDecorationPainter.cpp:
     43        (WebCore::TextDecorationPainter::paintTextDecoration):
     44        * rendering/style/RenderStyle.cpp:
     45        (WebCore::RenderStyle::changeAffectsVisualOverflow const):
     46        * rendering/style/TextDecorationThickness.h:
     47        (WebCore::TextDecorationThickness::resolve const):
     48        * style/InlineTextBoxStyle.cpp:
     49        (WebCore::computeUnderlineOffset):
     50        (WebCore::visualOverflowForDecorations):
     51        * style/InlineTextBoxStyle.h:
     52        (WebCore::textDecorationStrokeThickness): Deleted.
     53
    1542018-11-06  John Wilander  <wilander@apple.com>
    255
  • trunk/Source/WebCore/page/animation/CSSPropertyAnimation.cpp

    r233935 r237903  
    261261}
    262262
     263static inline TextUnderlineOffset blendFunc(const CSSPropertyBlendingClient* anim, const TextUnderlineOffset& from, const TextUnderlineOffset& to, double progress)
     264{
     265    if (from.isLength() && to.isLength())
     266        return TextUnderlineOffset::createWithLength(blendFunc(anim, from.lengthValue(), to.lengthValue(), progress));
     267    return TextUnderlineOffset::createWithAuto();
     268}
     269
     270static inline TextDecorationThickness blendFunc(const CSSPropertyBlendingClient* anim, const TextDecorationThickness& from, const TextDecorationThickness& to, double progress)
     271{
     272    if (from.isLength() && to.isLength())
     273        return TextDecorationThickness::createWithLength(blendFunc(anim, from.lengthValue(), to.lengthValue(), progress));
     274    return TextDecorationThickness::createWithAuto();
     275}
     276
    263277static inline LengthBox blendFunc(const CSSPropertyBlendingClient* anim, const LengthBox& from, const LengthBox& to, double progress)
    264278{
     
    16861700        new PropertyWrapper<FontSelectionValue>(CSSPropertyFontStretch, &RenderStyle::fontStretch, &RenderStyle::setFontStretch),
    16871701        new PropertyWrapperFontStyle(),
     1702        new PropertyWrapper<TextDecorationThickness>(CSSPropertyTextDecorationThickness, &RenderStyle::textDecorationThickness, &RenderStyle::setTextDecorationThickness),
     1703        new PropertyWrapper<TextUnderlineOffset>(CSSPropertyTextUnderlineOffset, &RenderStyle::textUnderlineOffset, &RenderStyle::setTextUnderlineOffset),
    16881704    };
    16891705    const unsigned animatableLonghandPropertiesCount = WTF_ARRAY_LENGTH(animatableLonghandPropertyWrappers);
  • trunk/Source/WebCore/platform/graphics/FontMetrics.h

    r218799 r237903  
    103103    void setZeroWidth(float zeroWidth) { m_zeroWidth = zeroWidth; }
    104104
     105    float underlinePosition() const { return m_underlinePosition; }
     106    void setUnderlinePosition(float underlinePosition) { m_underlinePosition = underlinePosition; }
     107
     108    float underlineThickness() const { return m_underlineThickness; }
     109    void setUnderlineThickness(float underlineThickness) { m_underlineThickness = underlineThickness; }
     110
    105111private:
    106112    friend class Font;
     
    126132    float m_xHeight { 0 };
    127133    float m_capHeight { 0 };
     134    float m_underlinePosition { 0 };
     135    float m_underlineThickness { 0 };
    128136};
    129137
  • trunk/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm

    r237845 r237903  
    199199    m_fontMetrics.setXHeight(xHeight);
    200200    m_fontMetrics.setLineSpacing(lineSpacing);
     201    m_fontMetrics.setUnderlinePosition(-CTFontGetUnderlinePosition(m_platformData.font()));
     202    m_fontMetrics.setUnderlineThickness(CTFontGetUnderlineThickness(m_platformData.font()));
    201203}
    202204
  • trunk/Source/WebCore/rendering/InlineFlowBox.cpp

    r237893 r237903  
    164164                hasMarkers = textBox->hasMarkers();
    165165            }
    166             if (childStyle->letterSpacing() < 0 || childStyle->textShadow() || childStyle->textEmphasisMark() != TextEmphasisMark::None || childStyle->hasPositiveStrokeWidth() || hasMarkers)
     166            if (childStyle->letterSpacing() < 0 || childStyle->textShadow() || childStyle->textEmphasisMark() != TextEmphasisMark::None || childStyle->hasPositiveStrokeWidth() || hasMarkers || !childStyle->textUnderlineOffset().isAuto() || !childStyle->textDecorationThickness().isAuto() || childStyle->textUnderlinePosition() != TextUnderlinePosition::Auto)
    167167                child->clearKnownToHaveNoOverflow();
    168168        } else if (child->renderer().isReplaced()) {
  • trunk/Source/WebCore/rendering/SimpleLineLayout.cpp

    r237893 r237903  
    202202    if (style.textOverflow() == TextOverflow::Ellipsis)
    203203        SET_REASON_AND_RETURN_IF_NEEDED(FlowHasTextOverflow, reasons, includeReasons);
    204     if ((style.textDecorationsInEffect() & TextDecoration::Underline) && style.textUnderlinePosition() == TextUnderlinePosition::Under)
     204    if ((style.textDecorationsInEffect() & TextDecoration::Underline) && (style.textUnderlinePosition() != TextUnderlinePosition::Auto || !style.textUnderlineOffset().isAuto() || !style.textDecorationThickness().isAuto()))
    205205        SET_REASON_AND_RETURN_IF_NEEDED(FlowHasUnsupportedUnderlineDecoration, reasons, includeReasons);
    206206    // Non-visible overflow should be pretty easy to support.
  • trunk/Source/WebCore/rendering/TextDecorationPainter.cpp

    r237845 r237903  
    212212{
    213213    const auto& fontMetrics = m_lineStyle.fontMetrics();
    214     float textDecorationThickness = textDecorationStrokeThickness(m_lineStyle.computedFontPixelSize());
     214    float textDecorationThickness = m_lineStyle.textDecorationThickness().resolve(m_lineStyle.computedFontSize(), fontMetrics);
    215215    FloatPoint localOrigin = boxOrigin;
    216216
     
    286286        // These decorations should match the visual overflows computed in visualOverflowForDecorations().
    287287        if (m_decorations.contains(TextDecoration::Underline)) {
    288             int offset = computeUnderlineOffset(m_lineStyle.textUnderlinePosition(), m_lineStyle.fontMetrics(), m_inlineTextBox, textDecorationThickness);
     288            float textDecorationBaseFontSize = 16;
     289            auto defaultGap = m_lineStyle.computedFontSize() / textDecorationBaseFontSize;
     290            int offset = computeUnderlineOffset(m_lineStyle.textUnderlinePosition(), m_lineStyle.textUnderlineOffset(), m_lineStyle.fontMetrics(), m_inlineTextBox, defaultGap);
    289291            float wavyOffset = m_styles.underlineStyle == TextDecorationStyle::Wavy ? m_wavyOffset : 0;
    290292            FloatRect rect(localOrigin, FloatSize(m_width, textDecorationThickness));
  • trunk/Source/WebCore/rendering/style/RenderStyle.cpp

    r237697 r237903  
    537537
    538538    if (m_inheritedFlags.textDecorations != other.m_inheritedFlags.textDecorations
    539         || m_visualData->textDecoration != other.m_visualData->textDecoration
    540         || m_rareNonInheritedData->textDecorationStyle != other.m_rareNonInheritedData->textDecorationStyle) {
    541         // Underlines are always drawn outside of their textbox bounds when text-underline-position: under;
    542         // is specified. We can take an early out here.
    543         if (textUnderlinePosition() == TextUnderlinePosition::Under
    544             || other.textUnderlinePosition() == TextUnderlinePosition::Under)
    545             return true;
    546         return visualOverflowForDecorations(*this, nullptr) != visualOverflowForDecorations(other, nullptr);
     539        || m_rareNonInheritedData->textDecorationStyle != other.m_rareNonInheritedData->textDecorationStyle
     540        || m_rareInheritedData->textDecorationThickness != other.m_rareInheritedData->textDecorationThickness
     541        || m_rareInheritedData->textUnderlineOffset != other.m_rareInheritedData->textUnderlineOffset
     542        || m_rareInheritedData->textUnderlinePosition != other.m_rareInheritedData->textUnderlinePosition) {
     543        return true;
    547544    }
    548545
  • trunk/Source/WebCore/rendering/style/TextDecorationThickness.h

    r237843 r237903  
    7676    }
    7777
     78    float resolve(float fontSize, const FontMetrics& metrics) const
     79    {
     80        if (isAuto()) {
     81            const float textDecorationBaseFontSize = 16;
     82            return fontSize / textDecorationBaseFontSize;
     83        }
     84        if (isFromFont())
     85            return metrics.underlineThickness();
     86        ASSERT(isLength());
     87        return m_length;
     88    }
     89
    7890    bool operator==(const TextDecorationThickness& other) const
    7991    {
  • trunk/Source/WebCore/style/InlineTextBoxStyle.cpp

    r237844 r237903  
    3333namespace WebCore {
    3434   
    35 int computeUnderlineOffset(TextUnderlinePosition underlinePosition, const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, int textDecorationThickness)
     35int computeUnderlineOffset(TextUnderlinePosition underlinePosition, TextUnderlineOffset underlineOffset, const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, int textDecorationThickness)
    3636{
    3737    // This represents the gap between the baseline and the closest edge of the underline.
     
    4949   
    5050    auto resolvedUnderlinePosition = underlinePosition;
    51     if (resolvedUnderlinePosition == TextUnderlinePosition::Auto) {
     51    if (resolvedUnderlinePosition == TextUnderlinePosition::Auto && underlineOffset.isAuto()) {
    5252        if (inlineTextBox)
    5353            resolvedUnderlinePosition = inlineTextBox->root().baselineType() == IdeographicBaseline ? TextUnderlinePosition::Under : TextUnderlinePosition::Auto;
     
    5858    switch (resolvedUnderlinePosition) {
    5959    case TextUnderlinePosition::Auto:
     60        if (underlineOffset.isAuto())
     61            return fontMetrics.ascent() + gap;
     62        return fontMetrics.ascent() + underlineOffset.lengthValue();
    6063    case TextUnderlinePosition::FromFont:
    61         return fontMetrics.ascent() + gap;
     64        return fontMetrics.ascent() + fontMetrics.underlinePosition() + underlineOffset.lengthOr(0);
    6265    case TextUnderlinePosition::Under: {
    6366        ASSERT(inlineTextBox);
     
    7679            offset -= inlineTextBox->logicalBottom();
    7780        }
    78         return inlineTextBox->logicalHeight() + gap + std::max<float>(offset, 0);
     81        return inlineTextBox->logicalHeight() + gap + std::max<float>(offset, 0) + underlineOffset.lengthOr(0);
    7982    }
    8083    }
     
    106109        return GlyphOverflow();
    107110
    108     float strokeThickness = textDecorationStrokeThickness(lineStyle.computedFontPixelSize());
     111    float strokeThickness = lineStyle.textDecorationThickness().resolve(lineStyle.computedFontSize(), lineStyle.fontMetrics());
    109112    WavyStrokeParameters wavyStrokeParameters;
    110113    float wavyOffset = 0;
     
    125128        // Compensate for the integral ceiling in GraphicsContext::computeLineBoundsAndAntialiasingModeForText()
    126129        int underlineOffset = 1;
    127         underlineOffset += computeUnderlineOffset(lineStyle.textUnderlinePosition(), lineStyle.fontMetrics(), inlineTextBox, strokeThickness);
     130        float textDecorationBaseFontSize = 16;
     131        auto defaultGap = lineStyle.computedFontSize() / textDecorationBaseFontSize;
     132        underlineOffset += computeUnderlineOffset(lineStyle.textUnderlinePosition(), lineStyle.textUnderlineOffset(), lineStyle.fontMetrics(), inlineTextBox, defaultGap);
    128133        if (decorationStyle == TextDecorationStyle::Wavy) {
    129134            extendIntToFloat(overflowResult.bottom, underlineOffset + wavyOffset + wavyStrokeParameters.controlPointDistance + strokeThickness - height);
  • trunk/Source/WebCore/style/InlineTextBoxStyle.h

    r237844 r237903  
    3434class RenderStyle;
    3535
    36 inline float textDecorationStrokeThickness(float fontSize)
    37 {
    38     const float textDecorationBaseFontSize = 16;
    39     return fontSize / textDecorationBaseFontSize;
    40 }
    41 
    4236inline float wavyOffsetFromDecoration()
    4337{
     
    5852WavyStrokeParameters getWavyStrokeParameters(float fontSize);
    5953GlyphOverflow visualOverflowForDecorations(const RenderStyle& lineStyle, const InlineTextBox*);
    60 int computeUnderlineOffset(TextUnderlinePosition, const FontMetrics&, const InlineTextBox*, int textDecorationThickness);
     54int computeUnderlineOffset(TextUnderlinePosition, TextUnderlineOffset, const FontMetrics&, const InlineTextBox*, int textDecorationThickness);
    6155   
    6256} // namespace WebCore
Note: See TracChangeset for help on using the changeset viewer.