Index: Source/core/rendering/style/RenderStyle.cpp |
diff --git a/Source/core/rendering/style/RenderStyle.cpp b/Source/core/rendering/style/RenderStyle.cpp |
index 8accb94d73609b0186a0da53fcf963a1286545f0..0d0e226896a254b53e12a639b798e7f003349b87 100644 |
--- a/Source/core/rendering/style/RenderStyle.cpp |
+++ b/Source/core/rendering/style/RenderStyle.cpp |
@@ -366,21 +366,73 @@ 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.needsRepaintLayer() || !diff.needsFullLayout()) && diffNeedsLayoutAndRepaintLayer(other)) { |
+ diff.setNeedsFullLayout(); |
+ diff.setNeedsRepaintLayer(); |
+ } |
+ |
+ if ((!diff.needsRepaint() || !diff.needsFullLayout()) && diffNeedsLayoutAndRepaintSelf(other)) { |
+ diff.setNeedsFullLayout(); |
+ diff.setNeedsRepaintSelf(); |
+ } |
+ |
+ if (!diff.needsFullLayout() && diffNeedsLayoutOnly(other)) |
+ diff.setNeedsFullLayout(); |
+ |
+ 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 ((position() == AbsolutePosition || position() == FixedPosition) |
+ && positionedObjectMovedOnly(surround->offset, other.surround->offset, m_box->width())) { |
+ diff.setNeedsPositionedMovementLayout(); |
+ } else { |
+ // 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). |
+ diff.setNeedsFullLayout(); |
+ diff.setNeedsRepaintSelf(); |
+ } |
} |
+ if (!diff.needsRepaintLayer() && diffNeedsRepaintLayerOnly(other)) |
+ diff.setNeedsRepaintLayer(); |
+ |
+ if (!diff.needsRepaint() && diffNeedsRepaintOnly(other)) |
+ diff.setNeedsRepaintSelf(); |
+ |
+ addContextSensitiveDiffFlags(other, diff); |
+ |
+ if (diff.noChange() && diffNeedsRecompositeLayerOnly(other)) |
+ diff.setNeedsRecompositeLayer(); |
+ |
+ // 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. |
+ |
+ // 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::diffNeedsLayoutAndRepaintLayer(const RenderStyle& other) const |
+{ |
+ if (position() != other.position()) |
+ return true; |
+ |
+ return false; |
+} |
+ |
+bool RenderStyle::diffNeedsLayoutAndRepaintSelf(const RenderStyle& other) const |
+{ |
if (m_box.get() != other.m_box.get()) { |
if (m_box->width() != other.m_box->width() |
|| m_box->minWidth() != other.m_box->minWidth() |
@@ -388,28 +440,28 @@ StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle& other, un |
|| m_box->height() != other.m_box->height() |
|| m_box->minHeight() != other.m_box->minHeight() |
|| m_box->maxHeight() != other.m_box->maxHeight()) |
- return StyleDifferenceLayout; |
+ return true; |
if (m_box->verticalAlign() != other.m_box->verticalAlign()) |
- return StyleDifferenceLayout; |
+ return true; |
if (m_box->boxSizing() != other.m_box->boxSizing()) |
- return StyleDifferenceLayout; |
+ return true; |
} |
if (surround.get() != other.surround.get()) { |
if (surround->margin != other.surround->margin) |
- return StyleDifferenceLayout; |
+ return true; |
if (surround->padding != other.surround->padding) |
- return StyleDifferenceLayout; |
+ return true; |
// 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; |
+ return true; |
} |
if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) { |
@@ -430,38 +482,32 @@ StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle& other, un |
|| rareNonInheritedData->m_gridItem.get() != other.rareNonInheritedData->m_gridItem.get() |
|| rareNonInheritedData->m_textCombine != other.rareNonInheritedData->m_textCombine |
|| rareNonInheritedData->hasFilters() != other.rareNonInheritedData->hasFilters()) |
- return StyleDifferenceLayout; |
+ return true; |
if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other.rareNonInheritedData->m_deprecatedFlexibleBox.get() |
&& *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other.rareNonInheritedData->m_deprecatedFlexibleBox.get()) |
- return StyleDifferenceLayout; |
+ return true; |
if (rareNonInheritedData->m_flexibleBox.get() != other.rareNonInheritedData->m_flexibleBox.get() |
&& *rareNonInheritedData->m_flexibleBox.get() != *other.rareNonInheritedData->m_flexibleBox.get()) |
- return StyleDifferenceLayout; |
+ return true; |
// FIXME: We should add an optimized form of layout that just recomputes visual overflow. |
if (!rareNonInheritedData->shadowDataEquivalent(*other.rareNonInheritedData.get())) |
- return StyleDifferenceLayout; |
+ return true; |
if (!rareNonInheritedData->reflectionDataEquivalent(*other.rareNonInheritedData.get())) |
- return StyleDifferenceLayout; |
+ return true; |
if (rareNonInheritedData->m_multiCol.get() != other.rareNonInheritedData->m_multiCol.get() |
&& *rareNonInheritedData->m_multiCol.get() != *other.rareNonInheritedData->m_multiCol.get()) |
- return StyleDifferenceLayout; |
- |
- 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; |
- } |
+ 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(); |
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. |
@@ -471,7 +517,7 @@ StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle& other, un |
// 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; |
} |
} |
@@ -500,24 +546,24 @@ StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle& other, un |
|| rareInheritedData->m_lineBoxContain != other.rareInheritedData->m_lineBoxContain |
|| rareInheritedData->listStyleImage != other.rareInheritedData->listStyleImage |
|| rareInheritedData->textStrokeWidth != other.rareInheritedData->textStrokeWidth) |
- return StyleDifferenceLayout; |
+ return true; |
if (!rareInheritedData->shadowDataEquivalent(*other.rareInheritedData.get())) |
- return StyleDifferenceLayout; |
+ return true; |
if (rareInheritedData->quotes.get() != other.rareInheritedData->quotes.get()) |
- return StyleDifferenceLayout; |
+ return true; |
} |
if (visual->m_textAutosizingMultiplier != other.visual->m_textAutosizingMultiplier) |
- return StyleDifferenceLayout; |
+ 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; |
+ return true; |
} |
if (inherited_flags._box_direction != other.inherited_flags._box_direction |
@@ -527,7 +573,7 @@ StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle& other, un |
|| 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; |
+ return true; |
if (noninherited_flags._overflowX != other.noninherited_flags._overflowX |
|| noninherited_flags._overflowY != other.noninherited_flags._overflowY |
@@ -537,14 +583,14 @@ StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle& other, un |
|| 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; |
+ 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._table_layout != other.noninherited_flags._table_layout) |
- return StyleDifferenceLayout; |
+ return true; |
// In the collapsing border model, 'hidden' suppresses other borders, while 'none' |
// does not, so these style differences can be width differences. |
@@ -557,74 +603,51 @@ StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle& other, un |
|| (borderLeftStyle() == BNONE && other.borderLeftStyle() == BHIDDEN) |
|| (borderRightStyle() == BHIDDEN && other.borderRightStyle() == BNONE) |
|| (borderRightStyle() == BNONE && other.borderRightStyle() == BHIDDEN))) |
- return StyleDifferenceLayout; |
+ 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 StyleDifferenceLayout; |
+ return true; |
} |
if ((visibility() == COLLAPSE) != (other.visibility() == COLLAPSE)) |
- return StyleDifferenceLayout; |
+ return true; |
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; |
+ // Movement of non-static-positioned object is special cased in RenderStyle::visualInvalidationDiff(). |
- // 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; |
- } |
+ return false; |
+} |
- StyleDifference repaintDifference = repaintOnlyDiff(other, changedContextSensitiveProperties); |
- ASSERT(repaintDifference <= StyleDifferenceRepaintLayer); |
- return repaintDifference; |
+bool RenderStyle::diffNeedsLayoutOnly(const RenderStyle& other) const |
+{ |
+ // FIXME: Examine cases in needsFullLayoutAndRepaintLayer() and needsFullLayoutAndRepaintSelf() |
+ // and move cases that don't need repaint into this method. |
+ return false; |
} |
-StyleDifference RenderStyle::repaintOnlyDiff(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const |
+bool RenderStyle::diffNeedsRepaintLayerOnly(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 (position() != StaticPosition && (visual->clip != other.visual->clip || visual->hasClip != other.visual->hasClip)) |
+ return true; |
if (RuntimeEnabledFeatures::cssCompositingEnabled() && (rareNonInheritedData->m_effectiveBlendMode != other.rareNonInheritedData->m_effectiveBlendMode |
|| rareNonInheritedData->m_isolation != other.rareNonInheritedData->m_isolation)) |
- return StyleDifferenceRepaintLayer; |
- |
- 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 (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; |
- } |
+ return true; |
if (rareNonInheritedData->m_mask != other.rareNonInheritedData->m_mask |
|| rareNonInheritedData->m_maskBoxImage != other.rareNonInheritedData->m_maskBoxImage) |
- return StyleDifferenceRepaintLayer; |
+ return true; |
+ return false; |
+} |
+ |
+bool RenderStyle::diffNeedsRepaintOnly(const RenderStyle& other) const |
+{ |
if (inherited_flags._visibility != other.inherited_flags._visibility |
|| inherited_flags.m_printColorAdjust != other.inherited_flags.m_printColorAdjust |
|| inherited_flags._insideLink != other.inherited_flags._insideLink |
@@ -637,14 +660,19 @@ StyleDifference RenderStyle::repaintOnlyDiff(const RenderStyle& other, unsigned& |
|| rareNonInheritedData->m_objectFit != other.rareNonInheritedData->m_objectFit |
|| rareNonInheritedData->m_objectPosition != other.rareNonInheritedData->m_objectPosition |
|| rareInheritedData->m_imageRendering != other.rareInheritedData->m_imageRendering) |
- return StyleDifferenceRepaint; |
+ return true; |
+ |
+ if (rareNonInheritedData->m_shapeOutside != other.rareNonInheritedData->m_shapeOutside) |
+ return true; |
- if (rareNonInheritedData->m_shapeOutside != other.rareNonInheritedData->m_shapeOutside) |
- return StyleDifferenceRepaint; |
+ if (rareNonInheritedData->m_clipPath != other.rareNonInheritedData->m_clipPath) |
+ return true; |
- if (rareNonInheritedData->m_clipPath != other.rareNonInheritedData->m_clipPath) |
- return StyleDifferenceRepaint; |
+ return false; |
+} |
+bool RenderStyle::diffNeedsRecompositeLayerOnly(const RenderStyle& other) const |
+{ |
if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) { |
if (rareNonInheritedData->m_transformStyle3D != other.rareNonInheritedData->m_transformStyle3D |
|| rareNonInheritedData->m_backfaceVisibility != other.rareNonInheritedData->m_backfaceVisibility |
@@ -653,26 +681,41 @@ StyleDifference RenderStyle::repaintOnlyDiff(const RenderStyle& other, unsigned& |
|| rareNonInheritedData->m_perspectiveOriginY != other.rareNonInheritedData->m_perspectiveOriginY |
|| hasWillChangeCompositingHint() != other.hasWillChangeCompositingHint() |
|| hasWillChangeGpuRasterizationHint() != other.hasWillChangeGpuRasterizationHint()) |
- return StyleDifferenceRecompositeLayer; |
+ 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) |
- changedContextSensitiveProperties |= ContextSensitivePropertyTextOrColor; |
+ 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. |
+void RenderStyle::addContextSensitiveDiffFlags(const RenderStyle& other, StyleDifference& diff) const |
+{ |
+ if (position() != StaticPosition && (m_box->zIndex() != other.m_box->zIndex() || m_box->hasAutoZIndex() != other.m_box->hasAutoZIndex())) |
+ diff.setZIndexChanged(); |
- // 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 (!transformDataEquivalent(other)) |
+ diff.setTransformChanged(); |
+ |
+ if (rareNonInheritedData->opacity != other.rareNonInheritedData->opacity) |
+ diff.setOpacityChanged(); |
+ |
+ if (rareNonInheritedData->m_filter.get() != other.rareNonInheritedData->m_filter.get() |
+ && *rareNonInheritedData->m_filter.get() != *other.rareNonInheritedData->m_filter.get()) |
+ diff.setFilterChanged(); |
+ } |
+ |
+ if (!diff.needsRepaint()) { |
+ 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) |
+ diff.setTextOrColorChanged(); |
+ } |
} |
void RenderStyle::setClip(Length top, Length right, Length bottom, Length left) |