Changeset 150259 in webkit


Ignore:
Timestamp:
May 17, 2013 8:26:30 AM (11 years ago)
Author:
akling@apple.com
Message:

Changes in text-only properties shouldn't cause repaints unless there is actually text.
<http://webkit.org/b/116250>

Reviewed by Antti Koivisto.

Add a new StyleDifferenceRepaintIfText value to the repertoire of RenderStyle::diff().
This result means that the renderer only needs to repaint if one of its immediate children contains text.

This lets us avoid repainting the same pixels when hovering over constructs like:

<style>

a { text-decoration: none; }
a:hover { text-decoration: underline; }

</style>
<a href="http://is.gd/andersca">

<img src="cool-hat.jpg">

</a>

Since the change in text-decoration has no effect on the rendering of the <img> element,
we'll now be smart enough to avoid repainting it.

  • rendering/style/RenderStyleConstants.h:
  • rendering/style/RenderStyle.cpp:

(WebCore::RenderStyle::diff):

Move checking of text-only properties until the very end, and return StyleDifferenceRepaintIfText
in case a difference is found, giving precedence to StyleDifferenceRepaint.

  • rendering/RenderObject.h:
  • rendering/RenderObject.cpp:

(WebCore::RenderObject::hasImmediateNonWhitespaceTextChild):

Helper to check if a RenderObject has at least one RenderText child containing more than just
collapsible whitespace.

(WebCore::RenderObject::shouldRepaintForStyleDifference):

Helper to check if a StyleDifference is either ...Repaint or ...RepaintIfText and the renderer
has an immediate text child.

(WebCore::RenderObject::styleWillChange):
(WebCore::RenderObject::setStyle):

Don't repaint for StyleDifferenceRepaintIfText unless hasImmediateNonWhitespaceTextChild().

  • rendering/RenderBox.cpp:

(WebCore::RenderBox::styleDidChange):

  • rendering/svg/SVGResourcesCache.cpp:

(WebCore::SVGResourcesCache::clientStyleChanged):

Tweak for new StyleDifference enum value.

  • rendering/RenderText.h:
  • rendering/RenderText.cpp:

(WebCore::RenderText::isAllCollapsibleWhitespace):

Made this const.

Location:
trunk/Source/WebCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r150258 r150259  
     12013-05-16  Andreas Kling  <akling@apple.com>
     2
     3        Changes in text-only properties shouldn't cause repaints unless there is actually text.
     4        <http://webkit.org/b/116250>
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Add a new StyleDifferenceRepaintIfText value to the repertoire of RenderStyle::diff().
     9        This result means that the renderer only needs to repaint if one of its immediate children contains text.
     10
     11        This lets us avoid repainting the same pixels when hovering over constructs like:
     12
     13            <style>
     14                a { text-decoration: none; }
     15                a:hover { text-decoration: underline; }
     16            </style>
     17            <a href="http://is.gd/andersca">
     18                <img src="cool-hat.jpg">
     19            </a>
     20
     21        Since the change in text-decoration has no effect on the rendering of the <img> element,
     22        we'll now be smart enough to avoid repainting it.
     23
     24        * rendering/style/RenderStyleConstants.h:
     25        * rendering/style/RenderStyle.cpp:
     26        (WebCore::RenderStyle::diff):
     27
     28            Move checking of text-only properties until the very end, and return StyleDifferenceRepaintIfText
     29            in case a difference is found, giving precedence to StyleDifferenceRepaint.
     30
     31        * rendering/RenderObject.h:
     32        * rendering/RenderObject.cpp:
     33        (WebCore::RenderObject::hasImmediateNonWhitespaceTextChild):
     34
     35            Helper to check if a RenderObject has at least one RenderText child containing more than just
     36            collapsible whitespace.
     37
     38        (WebCore::RenderObject::shouldRepaintForStyleDifference):
     39
     40            Helper to check if a StyleDifference is either ...Repaint or ...RepaintIfText and the renderer
     41            has an immediate text child.
     42
     43        (WebCore::RenderObject::styleWillChange):
     44        (WebCore::RenderObject::setStyle):
     45
     46            Don't repaint for StyleDifferenceRepaintIfText unless hasImmediateNonWhitespaceTextChild().
     47
     48        * rendering/RenderBox.cpp:
     49        (WebCore::RenderBox::styleDidChange):
     50        * rendering/svg/SVGResourcesCache.cpp:
     51        (WebCore::SVGResourcesCache::clientStyleChanged):
     52
     53            Tweak for new StyleDifference enum value.
     54
     55        * rendering/RenderText.h:
     56        * rendering/RenderText.cpp:
     57        (WebCore::RenderText::isAllCollapsibleWhitespace):
     58
     59            Made this const.
     60
    1612013-05-17  Lamarque V. Souza  <Lamarque.Souza@basyskom.com>
    262
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r150214 r150259  
    277277
    278278    // Our opaqueness might have changed without triggering layout.
    279     if (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintLayer) {
     279    if (diff >= StyleDifferenceRepaint && diff <= StyleDifferenceRepaintLayer) {
    280280        RenderObject* parentToInvalidate = parent();
    281281        for (unsigned i = 0; i < backgroundObscurationTestMaxDepth && parentToInvalidate; ++i) {
  • trunk/Source/WebCore/rendering/RenderObject.cpp

    r150108 r150259  
    17591759}
    17601760
     1761inline bool RenderObject::hasImmediateNonWhitespaceTextChild() const
     1762{
     1763    for (const RenderObject* r = firstChild(); r; r = r->nextSibling()) {
     1764        if (r->isText() && !toRenderText(r)->isAllCollapsibleWhitespace())
     1765            return true;
     1766    }
     1767    return false;
     1768}
     1769
     1770inline bool RenderObject::shouldRepaintForStyleDifference(StyleDifference diff) const
     1771{
     1772    return diff == StyleDifferenceRepaint || (diff == StyleDifferenceRepaintIfText && hasImmediateNonWhitespaceTextChild());
     1773}
     1774
    17611775void RenderObject::setStyle(PassRefPtr<RenderStyle> style)
    17621776{
     
    18191833            setNeedsSimplifiedNormalFlowLayout();
    18201834    }
    1821    
    1822     if (updatedDiff == StyleDifferenceRepaintLayer || updatedDiff == StyleDifferenceRepaint) {
     1835
     1836    if (updatedDiff == StyleDifferenceRepaintLayer || shouldRepaintForStyleDifference(updatedDiff)) {
    18231837        // Do a repaint with the new style now, e.g., for example if we go from
    18241838        // not having an outline to having an outline.
     
    18641878        }
    18651879
    1866         if (m_parent && (diff == StyleDifferenceRepaint || newStyle->outlineSize() < m_style->outlineSize()))
     1880        if (m_parent && (newStyle->outlineSize() < m_style->outlineSize() || shouldRepaintForStyleDifference(diff)))
    18671881            repaint();
    18681882        if (isFloating() && (m_style->floating() != newStyle->floating()))
  • trunk/Source/WebCore/rendering/RenderObject.h

    r149653 r150259  
    10241024    void removeFromRenderFlowThread();
    10251025    void removeFromRenderFlowThreadRecursive(RenderFlowThread*);
     1026
     1027    bool shouldRepaintForStyleDifference(StyleDifference) const;
     1028    bool hasImmediateNonWhitespaceTextChild() const;
    10261029
    10271030    RenderStyle* cachedFirstLineStyle() const;
  • trunk/Source/WebCore/rendering/RenderText.cpp

    r149673 r150259  
    11811181}
    11821182
    1183 bool RenderText::isAllCollapsibleWhitespace()
     1183bool RenderText::isAllCollapsibleWhitespace() const
    11841184{
    11851185    unsigned length = textLength();
  • trunk/Source/WebCore/rendering/RenderText.h

    r149967 r150259  
    131131    void checkConsistency() const;
    132132
    133     bool isAllCollapsibleWhitespace();
     133    bool isAllCollapsibleWhitespace() const;
    134134
    135135    bool canUseSimpleFontCodePath() const { return m_canUseSimpleFontCodePath; }
  • trunk/Source/WebCore/rendering/style/RenderStyle.cpp

    r149700 r150259  
    676676        return StyleDifferenceRepaintLayer;
    677677
    678     if (inherited->color != other->inherited->color
    679         || inherited_flags._visibility != other->inherited_flags._visibility
    680         || inherited_flags._text_decorations != other->inherited_flags._text_decorations
     678    if (inherited_flags._visibility != other->inherited_flags._visibility
    681679        || inherited_flags.m_printColorAdjust != other->inherited_flags.m_printColorAdjust
    682680        || inherited_flags._insideLink != other->inherited_flags._insideLink
    683681        || surround->border != other->surround->border
    684682        || *m_background.get() != *other->m_background.get()
    685         || visual->textDecoration != other->visual->textDecoration
    686683        || rareInheritedData->userModify != other->rareInheritedData->userModify
    687684        || rareInheritedData->userSelect != other->rareInheritedData->userSelect
    688685        || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
    689686        || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
    690 #if ENABLE(CSS3_TEXT)
    691         || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle
    692         || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor
    693 #endif // CSS3_TEXT
    694         || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
    695         || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
    696         || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
    697         || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill
    698687        || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
    699688        return StyleDifferenceRepaint;
     
    710699            return StyleDifferenceRepaint;
    711700
    712 
    713701#if USE(ACCELERATED_COMPOSITING)
    714702    if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
     
    721709    }
    722710#endif
     711
     712    if (inherited->color != other->inherited->color
     713        || inherited_flags._text_decorations != other->inherited_flags._text_decorations
     714        || visual->textDecoration != other->visual->textDecoration
     715#if ENABLE(CSS3_TEXT)
     716        || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle
     717        || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor
     718#endif // CSS3_TEXT
     719        || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
     720        || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
     721        || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
     722        || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill)
     723        return StyleDifferenceRepaintIfText;
    723724
    724725    // Cursors are not checked, since they will be set appropriately in response to mouse events,
  • trunk/Source/WebCore/rendering/style/RenderStyleConstants.h

    r148949 r150259  
    3636
    3737// The difference between two styles.  The following values are used:
    38 // (1) StyleDifferenceEqual - The two styles are identical
    39 // (2) StyleDifferenceRecompositeLayer - The layer needs its position and transform updated, but no repaint
    40 // (3) StyleDifferenceRepaint - The object just needs to be repainted.
    41 // (4) StyleDifferenceRepaintLayer - The layer and its descendant layers needs to be repainted.
    42 // (5) StyleDifferenceLayoutPositionedMovementOnly - Only the position of this positioned object has been updated
    43 // (6) StyleDifferenceSimplifiedLayout - Only overflow needs to be recomputed
    44 // (7) StyleDifferenceSimplifiedLayoutAndPositionedMovement - Both positioned movement and simplified layout updates are required.
    45 // (8) StyleDifferenceLayout - A full layout is required.
     38// - StyleDifferenceEqual - The two styles are identical
     39// - StyleDifferenceRecompositeLayer - The layer needs its position and transform updated, but no repaint
     40// - StyleDifferenceRepaint - The object just needs to be repainted.
     41// - StyleDifferenceRepaintIfText - The object needs to be repainted if it contains text.
     42// - StyleDifferenceRepaintLayer - The layer and its descendant layers needs to be repainted.
     43// - StyleDifferenceLayoutPositionedMovementOnly - Only the position of this positioned object has been updated
     44// - StyleDifferenceSimplifiedLayout - Only overflow needs to be recomputed
     45// - StyleDifferenceSimplifiedLayoutAndPositionedMovement - Both positioned movement and simplified layout updates are required.
     46// - StyleDifferenceLayout - A full layout is required.
    4647enum StyleDifference {
    4748    StyleDifferenceEqual,
     
    5051#endif
    5152    StyleDifferenceRepaint,
     53    StyleDifferenceRepaintIfText,
    5254    StyleDifferenceRepaintLayer,
    5355    StyleDifferenceLayoutPositionedMovementOnly,
  • trunk/Source/WebCore/rendering/svg/SVGResourcesCache.cpp

    r149684 r150259  
    130130
    131131    // In this case the proper SVGFE*Element will decide whether the modified CSS properties require a relayout or repaint.
    132     if (renderer->isSVGResourceFilterPrimitive() && diff == StyleDifferenceRepaint)
     132    if (renderer->isSVGResourceFilterPrimitive() && (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintIfText))
    133133        return;
    134134
Note: See TracChangeset for help on using the changeset viewer.