Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / style / RenderStyle.cpp
index ff89737..c042728 100644 (file)
 #include "core/rendering/style/RenderStyle.h"
 
 #include <algorithm>
-#include "RuntimeEnabledFeatures.h"
 #include "core/css/resolver/StyleResolver.h"
 #include "core/rendering/RenderTheme.h"
 #include "core/rendering/TextAutosizer.h"
+#include "core/rendering/style/AppliedTextDecoration.h"
+#include "core/rendering/style/BorderEdge.h"
 #include "core/rendering/style/ContentData.h"
-#include "core/rendering/style/CursorList.h"
+#include "core/rendering/style/DataEquivalency.h"
 #include "core/rendering/style/QuotesData.h"
+#include "core/rendering/style/RenderStyleConstants.h"
 #include "core/rendering/style/ShadowList.h"
 #include "core/rendering/style/StyleImage.h"
 #include "core/rendering/style/StyleInheritedData.h"
 #include "platform/LengthFunctions.h"
+#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/fonts/Font.h"
 #include "platform/fonts/FontSelector.h"
 #include "platform/geometry/FloatRoundedRect.h"
 #include "wtf/MathExtras.h"
 
-using namespace std;
-
-namespace WebCore {
+namespace blink {
 
 struct SameSizeAsBorderValue {
     RGBA32 m_color;
@@ -123,7 +124,6 @@ ALWAYS_INLINE RenderStyle::RenderStyle(DefaultStyleTag)
     rareNonInheritedData.init();
     rareNonInheritedData.access()->m_deprecatedFlexibleBox.init();
     rareNonInheritedData.access()->m_flexibleBox.init();
-    rareNonInheritedData.access()->m_marquee.init();
     rareNonInheritedData.access()->m_multiCol.init();
     rareNonInheritedData.access()->m_transform.init();
     rareNonInheritedData.access()->m_willChange.init();
@@ -180,9 +180,10 @@ StyleRecalcChange RenderStyle::stylePropagationDiff(const RenderStyle* oldStyle,
     if (oldStyle->display() != newStyle->display()
         || oldStyle->hasPseudoStyle(FIRST_LETTER) != newStyle->hasPseudoStyle(FIRST_LETTER)
         || oldStyle->columnSpan() != newStyle->columnSpan()
-        || oldStyle->specifiesColumns() != newStyle->specifiesColumns()
         || !oldStyle->contentDataEquivalent(newStyle)
-        || oldStyle->hasTextCombine() != newStyle->hasTextCombine())
+        || oldStyle->hasTextCombine() != newStyle->hasTextCombine()
+        || oldStyle->justifyItems() != newStyle->justifyItems()
+        || oldStyle->alignItems() != newStyle->alignItems())
         return Reattach;
 
     if (*oldStyle == *newStyle)
@@ -196,6 +197,21 @@ StyleRecalcChange RenderStyle::stylePropagationDiff(const RenderStyle* oldStyle,
     return NoInherit;
 }
 
+ItemPosition RenderStyle::resolveAlignment(const RenderStyle* parentStyle, const RenderStyle* childStyle, ItemPosition resolvedAutoPositionForRenderer)
+{
+    // The auto keyword computes to the parent's align-items computed value, or to "stretch", if not set or "auto".
+    if (childStyle->alignSelf() == ItemPositionAuto)
+        return (parentStyle->alignItems() == ItemPositionAuto) ? resolvedAutoPositionForRenderer : parentStyle->alignItems();
+    return childStyle->alignSelf();
+}
+
+ItemPosition RenderStyle::resolveJustification(const RenderStyle* parentStyle, const RenderStyle* childStyle, ItemPosition resolvedAutoPositionForRenderer)
+{
+    if (childStyle->justifySelf() == ItemPositionAuto)
+        return (parentStyle->justifyItems() == ItemPositionAuto) ? resolvedAutoPositionForRenderer : parentStyle->justifyItems();
+    return childStyle->justifySelf();
+}
+
 void RenderStyle::inheritFrom(const RenderStyle* inheritParent, IsAtShadowBoundary isAtShadowBoundary)
 {
     if (isAtShadowBoundary == AtShadowBoundary) {
@@ -219,21 +235,20 @@ void RenderStyle::copyNonInheritedFrom(const RenderStyle* other)
     surround = other->surround;
     rareNonInheritedData = other->rareNonInheritedData;
     // The flags are copied one-by-one because noninherited_flags contains a bunch of stuff other than real style data.
-    noninherited_flags._effectiveDisplay = other->noninherited_flags._effectiveDisplay;
-    noninherited_flags._originalDisplay = other->noninherited_flags._originalDisplay;
-    noninherited_flags._overflowX = other->noninherited_flags._overflowX;
-    noninherited_flags._overflowY = other->noninherited_flags._overflowY;
-    noninherited_flags._vertical_align = other->noninherited_flags._vertical_align;
-    noninherited_flags._clear = other->noninherited_flags._clear;
-    noninherited_flags._position = other->noninherited_flags._position;
-    noninherited_flags._floating = other->noninherited_flags._floating;
-    noninherited_flags._table_layout = other->noninherited_flags._table_layout;
-    noninherited_flags._unicodeBidi = other->noninherited_flags._unicodeBidi;
-    noninherited_flags._page_break_before = other->noninherited_flags._page_break_before;
-    noninherited_flags._page_break_after = other->noninherited_flags._page_break_after;
-    noninherited_flags._page_break_inside = other->noninherited_flags._page_break_inside;
+    noninherited_flags.effectiveDisplay = other->noninherited_flags.effectiveDisplay;
+    noninherited_flags.originalDisplay = other->noninherited_flags.originalDisplay;
+    noninherited_flags.overflowX = other->noninherited_flags.overflowX;
+    noninherited_flags.overflowY = other->noninherited_flags.overflowY;
+    noninherited_flags.verticalAlign = other->noninherited_flags.verticalAlign;
+    noninherited_flags.clear = other->noninherited_flags.clear;
+    noninherited_flags.position = other->noninherited_flags.position;
+    noninherited_flags.floating = other->noninherited_flags.floating;
+    noninherited_flags.tableLayout = other->noninherited_flags.tableLayout;
+    noninherited_flags.unicodeBidi = other->noninherited_flags.unicodeBidi;
+    noninherited_flags.pageBreakBefore = other->noninherited_flags.pageBreakBefore;
+    noninherited_flags.pageBreakAfter = other->noninherited_flags.pageBreakAfter;
+    noninherited_flags.pageBreakInside = other->noninherited_flags.pageBreakInside;
     noninherited_flags.explicitInheritance = other->noninherited_flags.explicitInheritance;
-    noninherited_flags.currentColor = other->noninherited_flags.currentColor;
     noninherited_flags.hasViewportUnits = other->noninherited_flags.hasViewportUnits;
     if (m_svgStyle != other->m_svgStyle)
         m_svgStyle.access()->copyNonInheritedFrom(other->m_svgStyle.get());
@@ -367,328 +382,346 @@ static bool positionedObjectMovedOnly(const LengthBox& a, const LengthBox& b, co
     return true;
 }
 
-StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
+StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle& other) const
 {
-    changedContextSensitiveProperties = ContextSensitivePropertyNone;
-
     // Note, we use .get() on each DataRef below because DataRef::operator== will do a deep
     // compare, which is duplicate work when we're going to compare each property inside
     // this function anyway.
 
-    StyleDifference svgChange = StyleDifferenceEqual;
-    if (m_svgStyle.get() != other->m_svgStyle.get()) {
-        svgChange = m_svgStyle->diff(other->m_svgStyle.get());
-        if (svgChange == StyleDifferenceLayout)
-            return svgChange;
+    StyleDifference diff;
+    if (m_svgStyle.get() != other.m_svgStyle.get())
+        diff = m_svgStyle->diff(other.m_svgStyle.get());
+
+    if ((!diff.needsFullLayout() || !diff.needsPaintInvalidation()) && diffNeedsFullLayoutAndPaintInvalidation(other)) {
+        diff.setNeedsFullLayout();
+        diff.setNeedsPaintInvalidationObject();
     }
 
-    if (m_box.get() != other->m_box.get()) {
-        if (m_box->width() != other->m_box->width()
-            || m_box->minWidth() != other->m_box->minWidth()
-            || m_box->maxWidth() != other->m_box->maxWidth()
-            || m_box->height() != other->m_box->height()
-            || m_box->minHeight() != other->m_box->minHeight()
-            || m_box->maxHeight() != other->m_box->maxHeight())
-            return StyleDifferenceLayout;
+    if (!diff.needsFullLayout() && diffNeedsFullLayout(other))
+        diff.setNeedsFullLayout();
 
-        if (m_box->verticalAlign() != other->m_box->verticalAlign())
-            return StyleDifferenceLayout;
+    if (!diff.needsFullLayout() && surround->margin != other.surround->margin) {
+        // Relative-positioned elements collapse their margins so need a full layout.
+        if (position() == AbsolutePosition || position() == FixedPosition)
+            diff.setNeedsPositionedMovementLayout();
+        else
+            diff.setNeedsFullLayout();
+    }
 
-        if (m_box->boxSizing() != other->m_box->boxSizing())
-            return StyleDifferenceLayout;
+    if (!diff.needsFullLayout() && position() != StaticPosition && surround->offset != other.surround->offset) {
+        // Optimize for the case where a positioned layer is moving but not changing size.
+        if (positionedObjectMovedOnly(surround->offset, other.surround->offset, m_box->width()))
+            diff.setNeedsPositionedMovementLayout();
+        else
+            diff.setNeedsFullLayout();
     }
 
-    if (surround.get() != other->surround.get()) {
-        if (surround->margin != other->surround->margin)
-            return StyleDifferenceLayout;
+    if (diffNeedsPaintInvalidationLayer(other))
+        diff.setNeedsPaintInvalidationLayer();
+    else if (diffNeedsPaintInvalidationObject(other))
+        diff.setNeedsPaintInvalidationObject();
 
-        if (surround->padding != other->surround->padding)
-            return StyleDifferenceLayout;
+    updatePropertySpecificDifferences(other, diff);
 
-        // If our border widths change, then we need to layout. Other changes to borders only necessitate a repaint.
-        if (borderLeftWidth() != other->borderLeftWidth()
-            || borderTopWidth() != other->borderTopWidth()
-            || borderBottomWidth() != other->borderBottomWidth()
-            || borderRightWidth() != other->borderRightWidth())
-            return StyleDifferenceLayout;
+    // Cursors are not checked, since they will be set appropriately in response to mouse events,
+    // so they don't need to cause any paint invalidation or layout.
+
+    // Animations don't need to be checked either. We always set the new style on the RenderObject, so we will get a chance to fire off
+    // the resulting transition properly.
+
+    return diff;
+}
+
+bool RenderStyle::diffNeedsFullLayoutAndPaintInvalidation(const RenderStyle& other) const
+{
+    // FIXME: Not all cases in this method need both full layout and paint invalidation.
+    // Should move cases into diffNeedsFullLayout() if
+    // - don't need paint invalidation at all;
+    // - or the renderer knows how to exactly invalidate paints caused by the layout change
+    //   instead of forced full paint invalidation.
+
+    if (surround.get() != other.surround.get()) {
+        // If our border widths change, then we need to layout. Other changes to borders only necessitate a paint invalidation.
+        if (borderLeftWidth() != other.borderLeftWidth()
+            || borderTopWidth() != other.borderTopWidth()
+            || borderBottomWidth() != other.borderBottomWidth()
+            || borderRightWidth() != other.borderRightWidth())
+            return true;
     }
 
-    if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
-        if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance
-            || rareNonInheritedData->marginBeforeCollapse != other->rareNonInheritedData->marginBeforeCollapse
-            || rareNonInheritedData->marginAfterCollapse != other->rareNonInheritedData->marginAfterCollapse
-            || rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp
-            || rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow
-            || rareNonInheritedData->m_wrapFlow != other->rareNonInheritedData->m_wrapFlow
-            || rareNonInheritedData->m_wrapThrough != other->rareNonInheritedData->m_wrapThrough
-            || rareNonInheritedData->m_shapeMargin != other->rareNonInheritedData->m_shapeMargin
-            || rareNonInheritedData->m_shapePadding != other->rareNonInheritedData->m_shapePadding
-            || rareNonInheritedData->m_order != other->rareNonInheritedData->m_order
-            || rareNonInheritedData->m_alignContent != other->rareNonInheritedData->m_alignContent
-            || rareNonInheritedData->m_alignItems != other->rareNonInheritedData->m_alignItems
-            || rareNonInheritedData->m_alignSelf != other->rareNonInheritedData->m_alignSelf
-            || rareNonInheritedData->m_justifyContent != other->rareNonInheritedData->m_justifyContent
-            || rareNonInheritedData->m_grid.get() != other->rareNonInheritedData->m_grid.get()
-            || rareNonInheritedData->m_gridItem.get() != other->rareNonInheritedData->m_gridItem.get()
-            || rareNonInheritedData->m_textCombine != other->rareNonInheritedData->m_textCombine
-            || rareNonInheritedData->hasFilters() != other->rareNonInheritedData->hasFilters())
-            return StyleDifferenceLayout;
-
-        if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get()
-            && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other->rareNonInheritedData->m_deprecatedFlexibleBox.get())
-            return StyleDifferenceLayout;
-
-        if (rareNonInheritedData->m_flexibleBox.get() != other->rareNonInheritedData->m_flexibleBox.get()
-            && *rareNonInheritedData->m_flexibleBox.get() != *other->rareNonInheritedData->m_flexibleBox.get())
-            return StyleDifferenceLayout;
+    if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+        if (rareNonInheritedData->m_appearance != other.rareNonInheritedData->m_appearance
+            || rareNonInheritedData->marginBeforeCollapse != other.rareNonInheritedData->marginBeforeCollapse
+            || rareNonInheritedData->marginAfterCollapse != other.rareNonInheritedData->marginAfterCollapse
+            || rareNonInheritedData->lineClamp != other.rareNonInheritedData->lineClamp
+            || rareNonInheritedData->textOverflow != other.rareNonInheritedData->textOverflow
+            || rareNonInheritedData->m_wrapFlow != other.rareNonInheritedData->m_wrapFlow
+            || rareNonInheritedData->m_wrapThrough != other.rareNonInheritedData->m_wrapThrough
+            || rareNonInheritedData->m_shapeMargin != other.rareNonInheritedData->m_shapeMargin
+            || rareNonInheritedData->m_order != other.rareNonInheritedData->m_order
+            || rareNonInheritedData->m_justifyContent != other.rareNonInheritedData->m_justifyContent
+            || rareNonInheritedData->m_grid.get() != other.rareNonInheritedData->m_grid.get()
+            || rareNonInheritedData->m_gridItem.get() != other.rareNonInheritedData->m_gridItem.get()
+            || rareNonInheritedData->m_textCombine != other.rareNonInheritedData->m_textCombine
+            || rareNonInheritedData->hasFilters() != other.rareNonInheritedData->hasFilters())
+            return true;
 
-        // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
-        if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
-            return StyleDifferenceLayout;
+        if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other.rareNonInheritedData->m_deprecatedFlexibleBox.get()
+            && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other.rareNonInheritedData->m_deprecatedFlexibleBox.get())
+            return true;
+
+        if (rareNonInheritedData->m_flexibleBox.get() != other.rareNonInheritedData->m_flexibleBox.get()
+            && *rareNonInheritedData->m_flexibleBox.get() != *other.rareNonInheritedData->m_flexibleBox.get())
+            return true;
 
-        if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
-            return StyleDifferenceLayout;
+        // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
+        if (!rareNonInheritedData->shadowDataEquivalent(*other.rareNonInheritedData.get()))
+            return true;
 
-        if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get()
-            && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
-            return StyleDifferenceLayout;
+        if (!rareNonInheritedData->reflectionDataEquivalent(*other.rareNonInheritedData.get()))
+            return true;
 
-        if (!transformDataEquivalent(other)) {
-            // Don't return early here; instead take note of the type of
-            // change, and deal with it when looking at compositing.
-            changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
-        }
+        if (rareNonInheritedData->m_multiCol.get() != other.rareNonInheritedData->m_multiCol.get()
+            && *rareNonInheritedData->m_multiCol.get() != *other.rareNonInheritedData->m_multiCol.get())
+            return true;
 
         // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
         const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
-        const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
+        const CounterDirectiveMap* mapB = other.rareNonInheritedData->m_counterDirectives.get();
         if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
-            return StyleDifferenceLayout;
+            return true;
 
         // We only need do layout for opacity changes if adding or losing opacity could trigger a change
         // in us being a stacking context.
-        if (hasAutoZIndex() != other->hasAutoZIndex() && rareNonInheritedData->hasOpacity() != other->rareNonInheritedData->hasOpacity()) {
+        if (hasAutoZIndex() != other.hasAutoZIndex() && rareNonInheritedData->hasOpacity() != other.rareNonInheritedData->hasOpacity()) {
             // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
             // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
             // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
             // In addition we need to solve the floating object issue when layers come and go. Right now
             // a full layout is necessary to keep floating object lists sane.
-            return StyleDifferenceLayout;
+            return true;
         }
     }
 
-    if (rareInheritedData.get() != other->rareInheritedData.get()) {
-        if (rareInheritedData->highlight != other->rareInheritedData->highlight
-            || rareInheritedData->indent != other->rareInheritedData->indent
-            || rareInheritedData->m_textAlignLast != other->rareInheritedData->m_textAlignLast
-            || rareInheritedData->m_textIndentLine != other->rareInheritedData->m_textIndentLine
-            || rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom
-            || rareInheritedData->wordBreak != other->rareInheritedData->wordBreak
-            || rareInheritedData->overflowWrap != other->rareInheritedData->overflowWrap
-            || rareInheritedData->lineBreak != other->rareInheritedData->lineBreak
-            || rareInheritedData->textSecurity != other->rareInheritedData->textSecurity
-            || rareInheritedData->hyphens != other->rareInheritedData->hyphens
-            || rareInheritedData->hyphenationLimitBefore != other->rareInheritedData->hyphenationLimitBefore
-            || rareInheritedData->hyphenationLimitAfter != other->rareInheritedData->hyphenationLimitAfter
-            || rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString
-            || rareInheritedData->locale != other->rareInheritedData->locale
-            || rareInheritedData->m_rubyPosition != other->rareInheritedData->m_rubyPosition
-            || rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark
-            || rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition
-            || rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark
-            || rareInheritedData->m_textJustify != other->rareInheritedData->m_textJustify
-            || rareInheritedData->m_textOrientation != other->rareInheritedData->m_textOrientation
-            || rareInheritedData->m_tabSize != other->rareInheritedData->m_tabSize
-            || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain
-            || rareInheritedData->listStyleImage != other->rareInheritedData->listStyleImage
-            || rareInheritedData->textStrokeWidth != other->rareInheritedData->textStrokeWidth)
-            return StyleDifferenceLayout;
-
-        if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
-            return StyleDifferenceLayout;
-
-        if (!QuotesData::equals(rareInheritedData->quotes.get(), other->rareInheritedData->quotes.get()))
-            return StyleDifferenceLayout;
+    if (rareInheritedData.get() != other.rareInheritedData.get()) {
+        if (rareInheritedData->highlight != other.rareInheritedData->highlight
+            || rareInheritedData->indent != other.rareInheritedData->indent
+            || rareInheritedData->m_textAlignLast != other.rareInheritedData->m_textAlignLast
+            || rareInheritedData->m_textIndentLine != other.rareInheritedData->m_textIndentLine
+            || rareInheritedData->m_effectiveZoom != other.rareInheritedData->m_effectiveZoom
+            || rareInheritedData->wordBreak != other.rareInheritedData->wordBreak
+            || rareInheritedData->overflowWrap != other.rareInheritedData->overflowWrap
+            || rareInheritedData->lineBreak != other.rareInheritedData->lineBreak
+            || rareInheritedData->textSecurity != other.rareInheritedData->textSecurity
+            || rareInheritedData->hyphens != other.rareInheritedData->hyphens
+            || rareInheritedData->hyphenationLimitBefore != other.rareInheritedData->hyphenationLimitBefore
+            || rareInheritedData->hyphenationLimitAfter != other.rareInheritedData->hyphenationLimitAfter
+            || rareInheritedData->hyphenationString != other.rareInheritedData->hyphenationString
+            || rareInheritedData->locale != other.rareInheritedData->locale
+            || rareInheritedData->m_rubyPosition != other.rareInheritedData->m_rubyPosition
+            || rareInheritedData->textEmphasisMark != other.rareInheritedData->textEmphasisMark
+            || rareInheritedData->textEmphasisPosition != other.rareInheritedData->textEmphasisPosition
+            || rareInheritedData->textEmphasisCustomMark != other.rareInheritedData->textEmphasisCustomMark
+            || rareInheritedData->m_textJustify != other.rareInheritedData->m_textJustify
+            || rareInheritedData->m_textOrientation != other.rareInheritedData->m_textOrientation
+            || rareInheritedData->m_tabSize != other.rareInheritedData->m_tabSize
+            || rareInheritedData->m_lineBoxContain != other.rareInheritedData->m_lineBoxContain
+            || rareInheritedData->listStyleImage != other.rareInheritedData->listStyleImage
+            || rareInheritedData->textStrokeWidth != other.rareInheritedData->textStrokeWidth)
+            return true;
+
+        if (!rareInheritedData->shadowDataEquivalent(*other.rareInheritedData.get()))
+            return true;
+
+        if (!rareInheritedData->quotesDataEquivalent(*other.rareInheritedData.get()))
+            return true;
     }
 
-    if (visual->m_textAutosizingMultiplier != other->visual->m_textAutosizingMultiplier)
-        return StyleDifferenceLayout;
+    if (inherited->textAutosizingMultiplier != other.inherited->textAutosizingMultiplier)
+        return true;
 
-    if (inherited.get() != other->inherited.get()) {
-        if (inherited->line_height != other->inherited->line_height
-        || inherited->font != other->inherited->font
-        || inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing
-        || inherited->vertical_border_spacing != other->inherited->vertical_border_spacing)
-        return StyleDifferenceLayout;
+    if (inherited.get() != other.inherited.get()) {
+        if (inherited->line_height != other.inherited->line_height
+            || inherited->font != other.inherited->font
+            || inherited->horizontal_border_spacing != other.inherited->horizontal_border_spacing
+            || inherited->vertical_border_spacing != other.inherited->vertical_border_spacing)
+            return true;
     }
 
-    if (inherited_flags._box_direction != other->inherited_flags._box_direction
-        || inherited_flags.m_rtlOrdering != other->inherited_flags.m_rtlOrdering
-        || inherited_flags._text_align != other->inherited_flags._text_align
-        || inherited_flags._text_transform != other->inherited_flags._text_transform
-        || inherited_flags._direction != other->inherited_flags._direction
-        || inherited_flags._white_space != other->inherited_flags._white_space
-        || inherited_flags.m_writingMode != other->inherited_flags.m_writingMode)
-        return StyleDifferenceLayout;
-
-    if (noninherited_flags._overflowX != other->noninherited_flags._overflowX
-        || noninherited_flags._overflowY != other->noninherited_flags._overflowY
-        || noninherited_flags._clear != other->noninherited_flags._clear
-        || noninherited_flags._unicodeBidi != other->noninherited_flags._unicodeBidi
-        || noninherited_flags._position != other->noninherited_flags._position
-        || noninherited_flags._floating != other->noninherited_flags._floating
-        || noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay
-        || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
-        return StyleDifferenceLayout;
-
-    if (noninherited_flags._effectiveDisplay >= FIRST_TABLE_DISPLAY && noninherited_flags._effectiveDisplay <= LAST_TABLE_DISPLAY) {
-        if (inherited_flags._border_collapse != other->inherited_flags._border_collapse
-            || inherited_flags._empty_cells != other->inherited_flags._empty_cells
-            || inherited_flags._caption_side != other->inherited_flags._caption_side
-            || noninherited_flags._table_layout != other->noninherited_flags._table_layout)
-            return StyleDifferenceLayout;
+    if (inherited_flags._box_direction != other.inherited_flags._box_direction
+        || inherited_flags.m_rtlOrdering != other.inherited_flags.m_rtlOrdering
+        || inherited_flags._text_align != other.inherited_flags._text_align
+        || inherited_flags._text_transform != other.inherited_flags._text_transform
+        || inherited_flags._direction != other.inherited_flags._direction
+        || inherited_flags._white_space != other.inherited_flags._white_space
+        || inherited_flags.m_writingMode != other.inherited_flags.m_writingMode)
+        return true;
+
+    if (noninherited_flags.overflowX != other.noninherited_flags.overflowX
+        || noninherited_flags.overflowY != other.noninherited_flags.overflowY
+        || noninherited_flags.clear != other.noninherited_flags.clear
+        || noninherited_flags.unicodeBidi != other.noninherited_flags.unicodeBidi
+        || noninherited_flags.floating != other.noninherited_flags.floating
+        || noninherited_flags.originalDisplay != other.noninherited_flags.originalDisplay)
+        return true;
+
+    if (noninherited_flags.effectiveDisplay >= FIRST_TABLE_DISPLAY && noninherited_flags.effectiveDisplay <= LAST_TABLE_DISPLAY) {
+        if (inherited_flags._border_collapse != other.inherited_flags._border_collapse
+            || inherited_flags._empty_cells != other.inherited_flags._empty_cells
+            || inherited_flags._caption_side != other.inherited_flags._caption_side
+            || noninherited_flags.tableLayout != other.noninherited_flags.tableLayout)
+            return true;
 
         // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
         // does not, so these style differences can be width differences.
         if (inherited_flags._border_collapse
-            && ((borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE)
-                || (borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN)
-                || (borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE)
-                || (borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN)
-                || (borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE)
-                || (borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN)
-                || (borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE)
-                || (borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN)))
-            return StyleDifferenceLayout;
-    } else if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
-        if (inherited_flags._list_style_type != other->inherited_flags._list_style_type
-            || inherited_flags._list_style_position != other->inherited_flags._list_style_position)
-            return StyleDifferenceLayout;
+            && ((borderTopStyle() == BHIDDEN && other.borderTopStyle() == BNONE)
+                || (borderTopStyle() == BNONE && other.borderTopStyle() == BHIDDEN)
+                || (borderBottomStyle() == BHIDDEN && other.borderBottomStyle() == BNONE)
+                || (borderBottomStyle() == BNONE && other.borderBottomStyle() == BHIDDEN)
+                || (borderLeftStyle() == BHIDDEN && other.borderLeftStyle() == BNONE)
+                || (borderLeftStyle() == BNONE && other.borderLeftStyle() == BHIDDEN)
+                || (borderRightStyle() == BHIDDEN && other.borderRightStyle() == BNONE)
+                || (borderRightStyle() == BNONE && other.borderRightStyle() == BHIDDEN)))
+            return true;
+    } else if (noninherited_flags.effectiveDisplay == LIST_ITEM) {
+        if (inherited_flags._list_style_type != other.inherited_flags._list_style_type
+            || inherited_flags._list_style_position != other.inherited_flags._list_style_position)
+            return true;
     }
 
-    if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
-        return StyleDifferenceLayout;
+    if ((visibility() == COLLAPSE) != (other.visibility() == COLLAPSE))
+        return true;
 
-    if (m_background->outline() != other->m_background->outline()) {
+    if (!m_background->outline().visuallyEqual(other.m_background->outline())) {
         // FIXME: We only really need to recompute the overflow but we don't have an optimized layout for it.
-        return StyleDifferenceLayout;
+        return true;
     }
 
-    // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
-    // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
-    // but have to return StyleDifferenceLayout, that's why  this if branch comes after all branches
-    // that are relevant for SVG and might return StyleDifferenceLayout.
-    if (svgChange != StyleDifferenceEqual)
-        return svgChange;
-
-    // NOTE: This block must be last in this function for the StyleDifferenceLayoutPositionedMovementOnly
-    // optimization to work properly.
-    if (position() != StaticPosition && surround->offset != other->surround->offset) {
-        // Optimize for the case where a positioned layer is moving but not changing size.
-        if ((position() == AbsolutePosition || position() == FixedPosition)
-            && positionedObjectMovedOnly(surround->offset, other->surround->offset, m_box->width())
-            && repaintOnlyDiff(other, changedContextSensitiveProperties) == StyleDifferenceEqual)
-            return StyleDifferenceLayoutPositionedMovementOnly;
-        // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet.
-        // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
-        // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
-        return StyleDifferenceLayout;
-    }
+    // Movement of non-static-positioned object is special cased in RenderStyle::visualInvalidationDiff().
 
-    StyleDifference repaintDifference = repaintOnlyDiff(other, changedContextSensitiveProperties);
-    ASSERT(repaintDifference <= StyleDifferenceRepaintLayer);
-    return repaintDifference;
+    return false;
 }
 
-StyleDifference RenderStyle::repaintOnlyDiff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
+bool RenderStyle::diffNeedsFullLayout(const RenderStyle& other) const
 {
-    if (position() != StaticPosition && (m_box->zIndex() != other->m_box->zIndex() || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex()
-        || visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip))
-        return StyleDifferenceRepaintLayer;
+    if (m_box.get() != other.m_box.get()) {
+        if (m_box->width() != other.m_box->width()
+            || m_box->minWidth() != other.m_box->minWidth()
+            || m_box->maxWidth() != other.m_box->maxWidth()
+            || m_box->height() != other.m_box->height()
+            || m_box->minHeight() != other.m_box->minHeight()
+            || m_box->maxHeight() != other.m_box->maxHeight())
+            return true;
 
-    if (RuntimeEnabledFeatures::cssCompositingEnabled() && (rareNonInheritedData->m_effectiveBlendMode != other->rareNonInheritedData->m_effectiveBlendMode
-        || rareNonInheritedData->m_isolation != other->rareNonInheritedData->m_isolation))
-        return StyleDifferenceRepaintLayer;
+        if (m_box->verticalAlign() != other.m_box->verticalAlign())
+            return true;
 
-    if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
-        // Don't return early here; instead take note of the type of change,
-        // and deal with it when looking at compositing.
-        changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
+        if (m_box->boxSizing() != other.m_box->boxSizing())
+            return true;
     }
 
-    if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get()
-        && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) {
-        // Don't return early here; instead take note of the type of change,
-        // and deal with it when looking at compositing.
-        changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
+    if (noninherited_flags.verticalAlign != other.noninherited_flags.verticalAlign
+        || noninherited_flags.position != other.noninherited_flags.position)
+        return true;
+
+    if (surround.get() != other.surround.get()) {
+        if (surround->padding != other.surround->padding)
+            return true;
     }
 
-    if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
-        || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
-        return StyleDifferenceRepaintLayer;
-
-    if (inherited_flags._visibility != other->inherited_flags._visibility
-        || inherited_flags.m_printColorAdjust != other->inherited_flags.m_printColorAdjust
-        || inherited_flags._insideLink != other->inherited_flags._insideLink
-        || surround->border != other->surround->border
-        || *m_background.get() != *other->m_background.get()
-        || rareInheritedData->userModify != other->rareInheritedData->userModify
-        || rareInheritedData->userSelect != other->rareInheritedData->userSelect
-        || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
-        || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
-        || rareNonInheritedData->m_objectFit != other->rareNonInheritedData->m_objectFit
-        || rareNonInheritedData->m_objectPosition != other->rareNonInheritedData->m_objectPosition
-        || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
-        return StyleDifferenceRepaint;
-
-        // FIXME: The current spec is being reworked to remove dependencies between exclusions and affected
-        // content. There's a proposal to use floats instead. In that case, wrap-shape should actually relayout
-        // the parent container. For sure, I will have to revisit this code, but for now I've added this in order
-        // to avoid having diff() == StyleDifferenceEqual where wrap-shapes actually differ.
-        // Tracking bug: https://bugs.webkit.org/show_bug.cgi?id=62991
-        if (rareNonInheritedData->m_shapeOutside != other->rareNonInheritedData->m_shapeOutside)
-            return StyleDifferenceRepaint;
-
-        if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath)
-            return StyleDifferenceRepaint;
-
-    if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
-        if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
-            || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
-            || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
-            || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
-            || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY
-            || hasWillChangeCompositingHint() != other->hasWillChangeCompositingHint()
-            || hasWillChangeGpuRasterizationHint() != other->hasWillChangeGpuRasterizationHint())
-            return StyleDifferenceRecompositeLayer;
+    if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+        if (rareNonInheritedData->m_alignContent != other.rareNonInheritedData->m_alignContent
+            || rareNonInheritedData->m_alignItems != other.rareNonInheritedData->m_alignItems
+            || rareNonInheritedData->m_alignSelf != other.rareNonInheritedData->m_alignSelf)
+            return true;
     }
 
-    if (inherited->color != other->inherited->color
-        || inherited_flags._text_decorations != other->inherited_flags._text_decorations
-        || visual->textDecoration != other->visual->textDecoration
-        || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle
-        || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor
-        || rareInheritedData->textFillColor() != other->rareInheritedData->textFillColor()
-        || rareInheritedData->textStrokeColor() != other->rareInheritedData->textStrokeColor()
-        || rareInheritedData->textEmphasisColor() != other->rareInheritedData->textEmphasisColor()
-        || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill)
-        return StyleDifferenceRepaintIfTextOrColorChange;
+    return false;
+}
 
-    // Cursors are not checked, since they will be set appropriately in response to mouse events,
-    // so they don't need to cause any repaint or layout.
+bool RenderStyle::diffNeedsPaintInvalidationLayer(const RenderStyle& other) const
+{
+    if (position() != StaticPosition && (visual->clip != other.visual->clip || visual->hasAutoClip != other.visual->hasAutoClip))
+        return true;
 
-    // Animations don't need to be checked either.  We always set the new style on the RenderObject, so we will get a chance to fire off
-    // the resulting transition properly.
-    return StyleDifferenceEqual;
+    if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+        if (RuntimeEnabledFeatures::cssCompositingEnabled()
+            && (rareNonInheritedData->m_effectiveBlendMode != other.rareNonInheritedData->m_effectiveBlendMode
+                || rareNonInheritedData->m_isolation != other.rareNonInheritedData->m_isolation))
+            return true;
+
+        if (rareNonInheritedData->m_mask != other.rareNonInheritedData->m_mask
+            || rareNonInheritedData->m_maskBoxImage != other.rareNonInheritedData->m_maskBoxImage)
+            return true;
+    }
+
+    return false;
 }
 
-void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
+bool RenderStyle::diffNeedsPaintInvalidationObject(const RenderStyle& other) const
 {
-    StyleVisualData* data = visual.access();
-    data->clip.m_top = top;
-    data->clip.m_right = right;
-    data->clip.m_bottom = bottom;
-    data->clip.m_left = left;
+    if (inherited_flags._visibility != other.inherited_flags._visibility
+        || inherited_flags.m_printColorAdjust != other.inherited_flags.m_printColorAdjust
+        || inherited_flags._insideLink != other.inherited_flags._insideLink
+        || !surround->border.visuallyEqual(other.surround->border)
+        || !m_background->visuallyEqual(*other.m_background))
+        return true;
+
+    if (rareInheritedData.get() != other.rareInheritedData.get()) {
+        if (rareInheritedData->userModify != other.rareInheritedData->userModify
+            || rareInheritedData->userSelect != other.rareInheritedData->userSelect
+            || rareInheritedData->m_imageRendering != other.rareInheritedData->m_imageRendering)
+            return true;
+    }
+
+    if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+        if (rareNonInheritedData->userDrag != other.rareNonInheritedData->userDrag
+            || rareNonInheritedData->m_objectFit != other.rareNonInheritedData->m_objectFit
+            || rareNonInheritedData->m_objectPosition != other.rareNonInheritedData->m_objectPosition
+            || !rareNonInheritedData->shapeOutsideDataEquivalent(*other.rareNonInheritedData.get())
+            || !rareNonInheritedData->clipPathDataEquivalent(*other.rareNonInheritedData.get()))
+            return true;
+    }
+
+    return false;
+}
+
+void RenderStyle::updatePropertySpecificDifferences(const RenderStyle& other, StyleDifference& diff) const
+{
+    // StyleAdjuster has ensured that zIndex is non-auto only if it's applicable.
+    if (m_box->zIndex() != other.m_box->zIndex() || m_box->hasAutoZIndex() != other.m_box->hasAutoZIndex())
+        diff.setZIndexChanged();
+
+    if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+        if (!transformDataEquivalent(other))
+            diff.setTransformChanged();
+
+        if (rareNonInheritedData->opacity != other.rareNonInheritedData->opacity)
+            diff.setOpacityChanged();
+
+        if (rareNonInheritedData->m_filter != other.rareNonInheritedData->m_filter)
+            diff.setFilterChanged();
+    }
+
+    if (!diff.needsPaintInvalidation()) {
+        if (inherited->color != other.inherited->color
+            || inherited_flags.m_textUnderline != other.inherited_flags.m_textUnderline
+            || visual->textDecoration != other.visual->textDecoration) {
+            diff.setTextOrColorChanged();
+        } else if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+            if (rareNonInheritedData->m_textDecorationStyle != other.rareNonInheritedData->m_textDecorationStyle
+                || rareNonInheritedData->m_textDecorationColor != other.rareNonInheritedData->m_textDecorationColor)
+                diff.setTextOrColorChanged();
+        } else if (rareInheritedData.get() != other.rareInheritedData.get()) {
+            if (rareInheritedData->textFillColor() != other.rareInheritedData->textFillColor()
+                || rareInheritedData->textStrokeColor() != other.rareInheritedData->textStrokeColor()
+                || rareInheritedData->textEmphasisColor() != other.rareInheritedData->textEmphasisColor()
+                || rareInheritedData->textEmphasisFill != other.rareInheritedData->textEmphasisFill
+                || rareInheritedData->appliedTextDecorations != other.rareInheritedData->appliedTextDecorations)
+                diff.setTextOrColorChanged();
+        }
+    }
 }
 
 void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
@@ -705,8 +738,6 @@ void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
 
 void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
 {
-    if (QuotesData::equals(rareInheritedData->quotes.get(), q.get()))
-        return;
     rareInheritedData.access()->quotes = q;
 }
 
@@ -765,7 +796,7 @@ void RenderStyle::setContent(const String& string, bool add)
         if (lastContent) {
             // We attempt to merge with the last ContentData if possible.
             if (lastContent->isText()) {
-                TextContentData* textContent = static_cast<TextContentData*>(lastContent);
+                TextContentData* textContent = toTextContentData(lastContent);
                 textContent->setText(textContent->text() + string);
             } else
                 lastContent->setNext(ContentData::create(string));
@@ -800,14 +831,14 @@ void RenderStyle::setContent(QuoteType quote, bool add)
     rareNonInheritedData.access()->m_content = ContentData::create(quote);
 }
 
-blink::WebBlendMode RenderStyle::blendMode() const
+WebBlendMode RenderStyle::blendMode() const
 {
     if (RuntimeEnabledFeatures::cssCompositingEnabled())
-        return static_cast<blink::WebBlendMode>(rareNonInheritedData->m_effectiveBlendMode);
-    return blink::WebBlendModeNormal;
+        return static_cast<WebBlendMode>(rareNonInheritedData->m_effectiveBlendMode);
+    return WebBlendModeNormal;
 }
 
-void RenderStyle::setBlendMode(blink::WebBlendMode v)
+void RenderStyle::setBlendMode(WebBlendMode v)
 {
     if (RuntimeEnabledFeatures::cssCompositingEnabled())
         rareNonInheritedData.access()->m_effectiveBlendMode = v;
@@ -816,7 +847,7 @@ void RenderStyle::setBlendMode(blink::WebBlendMode v)
 bool RenderStyle::hasBlendMode() const
 {
     if (RuntimeEnabledFeatures::cssCompositingEnabled())
-        return static_cast<blink::WebBlendMode>(rareNonInheritedData->m_effectiveBlendMode) != blink::WebBlendModeNormal;
+        return static_cast<WebBlendMode>(rareNonInheritedData->m_effectiveBlendMode) != WebBlendModeNormal;
     return false;
 }
 
@@ -845,31 +876,12 @@ bool RenderStyle::hasWillChangeCompositingHint() const
     for (size_t i = 0; i < rareNonInheritedData->m_willChange->m_properties.size(); ++i) {
         switch (rareNonInheritedData->m_willChange->m_properties[i]) {
         case CSSPropertyOpacity:
+        case CSSPropertyTransform:
         case CSSPropertyWebkitTransform:
-        case CSSPropertyLeft:
         case CSSPropertyTop:
-        case CSSPropertyRight:
+        case CSSPropertyLeft:
         case CSSPropertyBottom:
-        case CSSPropertyWebkitFilter:
-            return true;
-        default:
-            break;
-        }
-    }
-    return false;
-}
-
-bool RenderStyle::hasWillChangeGpuRasterizationHint() const
-{
-    if (willChangeContents())
-        return true;
-
-    for (size_t i = 0; i < rareNonInheritedData->m_willChange->m_properties.size(); ++i) {
-        switch (rareNonInheritedData->m_willChange->m_properties[i]) {
-        case CSSPropertyWidth:
-        case CSSPropertyHeight:
-        case CSSPropertyBackgroundColor:
-        case CSSPropertyBackgroundPosition:
+        case CSSPropertyRight:
             return true;
         default:
             break;
@@ -1012,14 +1024,14 @@ RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect,
     return roundedRect;
 }
 
-static bool allLayersAreFixed(const FillLayer* layer)
+static bool allLayersAreFixed(const FillLayer& layer)
 {
-    bool allFixed = true;
-
-    for (const FillLayer* currLayer = layer; currLayer; currLayer = currLayer->next())
-        allFixed &= (currLayer->image() && currLayer->attachment() == FixedBackgroundAttachment);
+    for (const FillLayer* currLayer = &layer; currLayer; currLayer = currLayer->next()) {
+        if (!currLayer->image() || currLayer->attachment() != FixedBackgroundAttachment)
+            return false;
+    }
 
-    return layer && allFixed;
+    return true;
 }
 
 bool RenderStyle::hasEntirelyFixedBackground() const
@@ -1100,89 +1112,18 @@ const AtomicString& RenderStyle::textEmphasisMarkString() const
     return nullAtom;
 }
 
-void RenderStyle::adjustAnimations()
-{
-    CSSAnimationDataList* animationList = rareNonInheritedData->m_animations.get();
-    if (!animationList)
-        return;
-
-    // Get rid of empty animations and anything beyond them
-    for (size_t i = 0; i < animationList->size(); ++i) {
-        if (animationList->animation(i)->isEmpty()) {
-            animationList->resize(i);
-            break;
-        }
-    }
-
-    if (animationList->isEmpty()) {
-        clearAnimations();
-        return;
-    }
-
-    // Repeat patterns into layers that don't have some properties set.
-    animationList->fillUnsetProperties();
-}
-
-void RenderStyle::adjustTransitions()
-{
-    CSSAnimationDataList* transitionList = rareNonInheritedData->m_transitions.get();
-    if (!transitionList)
-        return;
-
-    // Get rid of empty transitions and anything beyond them
-    for (size_t i = 0; i < transitionList->size(); ++i) {
-        if (transitionList->animation(i)->isEmpty()) {
-            transitionList->resize(i);
-            break;
-        }
-    }
-
-    if (transitionList->isEmpty()) {
-        clearTransitions();
-        return;
-    }
-
-    // Repeat patterns into layers that don't have some properties set.
-    transitionList->fillUnsetProperties();
-
-    // Make sure there are no duplicate properties. This is an O(n^2) algorithm
-    // but the lists tend to be very short, so it is probably ok
-    for (size_t i = 0; i < transitionList->size(); ++i) {
-        for (size_t j = i+1; j < transitionList->size(); ++j) {
-            if (transitionList->animation(i)->property() == transitionList->animation(j)->property()) {
-                // toss i
-                transitionList->remove(i);
-                j = i;
-            }
-        }
-    }
-}
-
-CSSAnimationDataList* RenderStyle::accessAnimations()
+CSSAnimationData& RenderStyle::accessAnimations()
 {
     if (!rareNonInheritedData.access()->m_animations)
-        rareNonInheritedData.access()->m_animations = adoptPtrWillBeNoop(new CSSAnimationDataList());
-    return rareNonInheritedData->m_animations.get();
+        rareNonInheritedData.access()->m_animations = CSSAnimationData::create();
+    return *rareNonInheritedData->m_animations;
 }
 
-CSSAnimationDataList* RenderStyle::accessTransitions()
+CSSTransitionData& RenderStyle::accessTransitions()
 {
     if (!rareNonInheritedData.access()->m_transitions)
-        rareNonInheritedData.access()->m_transitions = adoptPtrWillBeNoop(new CSSAnimationDataList());
-    return rareNonInheritedData->m_transitions.get();
-}
-
-const CSSAnimationData* RenderStyle::transitionForProperty(CSSPropertyID property) const
-{
-    if (transitions()) {
-        for (size_t i = 0; i < transitions()->size(); ++i) {
-            const CSSAnimationData* p = transitions()->animation(i);
-            if (p->animationMode() == CSSAnimationData::AnimateAll || p->property() == property) {
-                return p;
-            }
-        }
-    }
-    return 0;
+        rareNonInheritedData.access()->m_transitions = CSSTransitionData::create();
+    return *rareNonInheritedData->m_transitions;
 }
 
 const Font& RenderStyle::font() const { return inherited->font; }
@@ -1192,6 +1133,33 @@ float RenderStyle::specifiedFontSize() const { return fontDescription().specifie
 float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
 int RenderStyle::fontSize() const { return fontDescription().computedPixelSize(); }
 FontWeight RenderStyle::fontWeight() const { return fontDescription().weight(); }
+FontStretch RenderStyle::fontStretch() const { return fontDescription().stretch(); }
+
+TextDecoration RenderStyle::textDecorationsInEffect() const
+{
+    int decorations = 0;
+
+    const Vector<AppliedTextDecoration>& applied = appliedTextDecorations();
+
+    for (size_t i = 0; i < applied.size(); ++i)
+        decorations |= applied[i].line();
+
+    return static_cast<TextDecoration>(decorations);
+}
+
+const Vector<AppliedTextDecoration>& RenderStyle::appliedTextDecorations() const
+{
+    if (!inherited_flags.m_textUnderline && !rareInheritedData->appliedTextDecorations) {
+        DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, empty, ());
+        return empty;
+    }
+    if (inherited_flags.m_textUnderline) {
+        DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, underline, (1, AppliedTextDecoration(TextDecorationUnderline)));
+        return underline;
+    }
+
+    return rareInheritedData->appliedTextDecorations->vector();
+}
 
 float RenderStyle::wordSpacing() const { return fontDescription().wordSpacing(); }
 float RenderStyle::letterSpacing() const { return fontDescription().letterSpacing(); }
@@ -1219,7 +1187,8 @@ Length RenderStyle::lineHeight() const
 
     return lh;
 }
-void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
+
+void RenderStyle::setLineHeight(const Length& specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
 
 int RenderStyle::computedLineHeight() const
 {
@@ -1262,7 +1231,7 @@ void RenderStyle::setFontSize(float size)
     if (!std::isfinite(size) || size < 0)
         size = 0;
     else
-        size = min(maximumAllowedFontSize, size);
+        size = std::min(maximumAllowedFontSize, size);
 
     FontSelector* currentFontSelector = font().fontSelector();
     FontDescription desc(fontDescription());
@@ -1272,7 +1241,7 @@ void RenderStyle::setFontSize(float size)
     float multiplier = textAutosizingMultiplier();
     if (multiplier > 1) {
         float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size, multiplier);
-        desc.setComputedSize(min(maximumAllowedFontSize, autosizedFontSize));
+        desc.setComputedSize(std::min(maximumAllowedFontSize, autosizedFontSize));
     }
 
     setFontDescription(desc);
@@ -1288,6 +1257,66 @@ void RenderStyle::setFontWeight(FontWeight weight)
     font().update(currentFontSelector);
 }
 
+void RenderStyle::addAppliedTextDecoration(const AppliedTextDecoration& decoration)
+{
+    RefPtr<AppliedTextDecorationList>& list = rareInheritedData.access()->appliedTextDecorations;
+
+    if (!list)
+        list = AppliedTextDecorationList::create();
+    else if (!list->hasOneRef())
+        list = list->copy();
+
+    if (inherited_flags.m_textUnderline) {
+        inherited_flags.m_textUnderline = false;
+        list->append(AppliedTextDecoration(TextDecorationUnderline));
+    }
+
+    list->append(decoration);
+}
+
+void RenderStyle::applyTextDecorations()
+{
+    if (textDecoration() == TextDecorationNone)
+        return;
+
+    TextDecorationStyle style = textDecorationStyle();
+    StyleColor styleColor = visitedDependentDecorationStyleColor();
+
+    int decorations = textDecoration();
+
+    if (decorations & TextDecorationUnderline) {
+        // To save memory, we don't use AppliedTextDecoration objects in the
+        // common case of a single simple underline.
+        AppliedTextDecoration underline(TextDecorationUnderline, style, styleColor);
+
+        if (!rareInheritedData->appliedTextDecorations && underline.isSimpleUnderline())
+            inherited_flags.m_textUnderline = true;
+        else
+            addAppliedTextDecoration(underline);
+    }
+    if (decorations & TextDecorationOverline)
+        addAppliedTextDecoration(AppliedTextDecoration(TextDecorationOverline, style, styleColor));
+    if (decorations & TextDecorationLineThrough)
+        addAppliedTextDecoration(AppliedTextDecoration(TextDecorationLineThrough, style, styleColor));
+}
+
+void RenderStyle::clearAppliedTextDecorations()
+{
+    inherited_flags.m_textUnderline = false;
+
+    if (rareInheritedData->appliedTextDecorations)
+        rareInheritedData.access()->appliedTextDecorations = nullptr;
+}
+
+void RenderStyle::setFontStretch(FontStretch stretch)
+{
+    FontSelector* currentFontSelector = font().fontSelector();
+    FontDescription desc(fontDescription());
+    desc.setStretch(stretch);
+    setFontDescription(desc);
+    font().update(currentFontSelector);
+}
+
 void RenderStyle::getShadowExtent(const ShadowList* shadowList, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
 {
     top = 0;
@@ -1302,10 +1331,10 @@ void RenderStyle::getShadowExtent(const ShadowList* shadowList, LayoutUnit &top,
             continue;
         float blurAndSpread = shadow.blur() + shadow.spread();
 
-        top = min<LayoutUnit>(top, shadow.y() - blurAndSpread);
-        right = max<LayoutUnit>(right, shadow.x() + blurAndSpread);
-        bottom = max<LayoutUnit>(bottom, shadow.y() + blurAndSpread);
-        left = min<LayoutUnit>(left, shadow.x() - blurAndSpread);
+        top = std::min<LayoutUnit>(top, shadow.y() - blurAndSpread);
+        right = std::max<LayoutUnit>(right, shadow.x() + blurAndSpread);
+        bottom = std::max<LayoutUnit>(bottom, shadow.y() + blurAndSpread);
+        left = std::min<LayoutUnit>(left, shadow.x() - blurAndSpread);
     }
 }
 
@@ -1322,10 +1351,10 @@ LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowList* shadowList)
         if (shadow.style() == Normal)
             continue;
         float blurAndSpread = shadow.blur() + shadow.spread();
-        top = max<LayoutUnit>(top, shadow.y() + blurAndSpread);
-        right = min<LayoutUnit>(right, shadow.x() - blurAndSpread);
-        bottom = min<LayoutUnit>(bottom, shadow.y() - blurAndSpread);
-        left = max<LayoutUnit>(left, shadow.x() + blurAndSpread);
+        top = std::max<LayoutUnit>(top, shadow.y() + blurAndSpread);
+        right = std::min<LayoutUnit>(right, shadow.x() - blurAndSpread);
+        bottom = std::min<LayoutUnit>(bottom, shadow.y() - blurAndSpread);
+        left = std::max<LayoutUnit>(left, shadow.x() + blurAndSpread);
     }
 
     return LayoutBoxExtent(top, right, bottom, left);
@@ -1343,8 +1372,8 @@ void RenderStyle::getShadowHorizontalExtent(const ShadowList* shadowList, Layout
             continue;
         float blurAndSpread = shadow.blur() + shadow.spread();
 
-        left = min<LayoutUnit>(left, shadow.x() - blurAndSpread);
-        right = max<LayoutUnit>(right, shadow.x() + blurAndSpread);
+        left = std::min<LayoutUnit>(left, shadow.x() - blurAndSpread);
+        right = std::max<LayoutUnit>(right, shadow.x() + blurAndSpread);
     }
 }
 
@@ -1360,15 +1389,34 @@ void RenderStyle::getShadowVerticalExtent(const ShadowList* shadowList, LayoutUn
             continue;
         float blurAndSpread = shadow.blur() + shadow.spread();
 
-        top = min<LayoutUnit>(top, shadow.y() - blurAndSpread);
-        bottom = max<LayoutUnit>(bottom, shadow.y() + blurAndSpread);
+        top = std::min<LayoutUnit>(top, shadow.y() - blurAndSpread);
+        bottom = std::max<LayoutUnit>(bottom, shadow.y() + blurAndSpread);
     }
 }
 
-StyleColor RenderStyle::visitedDependentDecorationColor() const
+StyleColor RenderStyle::visitedDependentDecorationStyleColor() const
 {
-    // Text decoration color fallback is handled in RenderObject::decorationColor.
-    return insideLink() == InsideVisitedLink ? visitedLinkTextDecorationColor() : textDecorationColor();
+    bool isVisited = insideLink() == InsideVisitedLink;
+
+    StyleColor styleColor = isVisited ? visitedLinkTextDecorationColor() : textDecorationColor();
+
+    if (!styleColor.isCurrentColor())
+        return styleColor;
+
+    if (textStrokeWidth()) {
+        // Prefer stroke color if possible, but not if it's fully transparent.
+        StyleColor textStrokeStyleColor = isVisited ? visitedLinkTextStrokeColor() : textStrokeColor();
+        if (!textStrokeStyleColor.isCurrentColor() && textStrokeStyleColor.color().alpha())
+            return textStrokeStyleColor;
+    }
+
+    return isVisited ? visitedLinkTextFillColor() : textFillColor();
+}
+
+Color RenderStyle::visitedDependentDecorationColor() const
+{
+    bool isVisited = insideLink() == InsideVisitedLink;
+    return visitedDependentDecorationStyleColor().resolve(isVisited ? visitedLinkColor() : color());
 }
 
 Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
@@ -1552,7 +1600,7 @@ unsigned short RenderStyle::borderEndWidth() const
     return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
 }
 
-void RenderStyle::setMarginStart(Length margin)
+void RenderStyle::setMarginStart(const Length& margin)
 {
     if (isHorizontalWritingMode()) {
         if (isLeftToRightDirection())
@@ -1567,7 +1615,7 @@ void RenderStyle::setMarginStart(Length margin)
     }
 }
 
-void RenderStyle::setMarginEnd(Length margin)
+void RenderStyle::setMarginEnd(const Length& margin)
 {
     if (isHorizontalWritingMode()) {
         if (isLeftToRightDirection())
@@ -1614,7 +1662,7 @@ void RenderStyle::setBorderImageSource(PassRefPtr<StyleImage> image)
     surround.access()->border.m_image.setImage(image);
 }
 
-void RenderStyle::setBorderImageSlices(LengthBox slices)
+void RenderStyle::setBorderImageSlices(const LengthBox& slices)
 {
     if (surround->border.m_image.imageSlices() == slices)
         return;
@@ -1667,4 +1715,54 @@ float calcBorderRadiiConstraintScaleFor(const FloatRect& rect, const FloatRounde
     return factor;
 }
 
-} // namespace WebCore
+bool RenderStyle::borderObscuresBackground() const
+{
+    if (!hasBorder())
+        return false;
+
+    // Bail if we have any border-image for now. We could look at the image alpha to improve this.
+    if (borderImage().image())
+        return false;
+
+    BorderEdge edges[4];
+    getBorderEdgeInfo(edges);
+
+    for (int i = BSTop; i <= BSLeft; ++i) {
+        const BorderEdge& currEdge = edges[i];
+        if (!currEdge.obscuresBackground())
+            return false;
+    }
+
+    return true;
+}
+
+void RenderStyle::getBorderEdgeInfo(BorderEdge edges[], bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+{
+    bool horizontal = isHorizontalWritingMode();
+
+    edges[BSTop] = BorderEdge(borderTopWidth(),
+        visitedDependentColor(CSSPropertyBorderTopColor),
+        borderTopStyle(),
+        borderTopIsTransparent(),
+        horizontal || includeLogicalLeftEdge);
+
+    edges[BSRight] = BorderEdge(borderRightWidth(),
+        visitedDependentColor(CSSPropertyBorderRightColor),
+        borderRightStyle(),
+        borderRightIsTransparent(),
+        !horizontal || includeLogicalRightEdge);
+
+    edges[BSBottom] = BorderEdge(borderBottomWidth(),
+        visitedDependentColor(CSSPropertyBorderBottomColor),
+        borderBottomStyle(),
+        borderBottomIsTransparent(),
+        horizontal || includeLogicalRightEdge);
+
+    edges[BSLeft] = BorderEdge(borderLeftWidth(),
+        visitedDependentColor(CSSPropertyBorderLeftColor),
+        borderLeftStyle(),
+        borderLeftIsTransparent(),
+        !horizontal || includeLogicalLeftEdge);
+}
+
+} // namespace blink