#include "platform/LengthFunctions.h"
#include "platform/fonts/Font.h"
#include "platform/fonts/FontSelector.h"
+#include "platform/geometry/FloatRoundedRect.h"
#include "wtf/MathExtras.h"
using namespace std;
rareNonInheritedData.access()->m_marquee.init();
rareNonInheritedData.access()->m_multiCol.init();
rareNonInheritedData.access()->m_transform.init();
+ rareNonInheritedData.access()->m_willChange.init();
rareNonInheritedData.access()->m_filter.init();
rareNonInheritedData.access()->m_grid.init();
rareNonInheritedData.access()->m_gridItem.init();
{
}
-static StyleRecalcChange comparePseudoStyles(const RenderStyle* oldStyle, const RenderStyle* newStyle)
+static StyleRecalcChange diffPseudoStyles(const RenderStyle* oldStyle, const RenderStyle* newStyle)
{
// If the pseudoStyles have changed, we want any StyleRecalcChange that is not NoChange
// because setStyle will do the right thing with anything else.
return NoChange;
}
-StyleRecalcChange RenderStyle::compare(const RenderStyle* oldStyle, const RenderStyle* newStyle)
+StyleRecalcChange RenderStyle::stylePropagationDiff(const RenderStyle* oldStyle, const RenderStyle* newStyle)
{
if ((!oldStyle && newStyle) || (oldStyle && !newStyle))
return Reattach;
if (oldStyle->display() != newStyle->display()
|| oldStyle->hasPseudoStyle(FIRST_LETTER) != newStyle->hasPseudoStyle(FIRST_LETTER)
|| oldStyle->columnSpan() != newStyle->columnSpan()
- || oldStyle->specifiesAutoColumns() != newStyle->specifiesAutoColumns()
|| !oldStyle->contentDataEquivalent(newStyle)
- || oldStyle->hasTextCombine() != newStyle->hasTextCombine()
- || oldStyle->flowThread() != newStyle->flowThread()
- || oldStyle->regionThread() != newStyle->regionThread())
+ || oldStyle->hasTextCombine() != newStyle->hasTextCombine())
return Reattach;
if (*oldStyle == *newStyle)
- return comparePseudoStyles(oldStyle, newStyle);
+ return diffPseudoStyles(oldStyle, newStyle);
if (oldStyle->inheritedNotEqual(newStyle)
|| oldStyle->hasExplicitlyInheritedProperties()
&& rareInheritedData.get() == other->rareInheritedData.get();
}
-static bool positionedObjectMoved(const LengthBox& a, const LengthBox& b, const Length& width)
+static bool positionedObjectMovedOnly(const LengthBox& a, const LengthBox& b, const Length& width)
{
// If any unit types are different, then we can't guarantee
// that this was just a movement.
return false;
if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
return false;
- // If our width is auto and left or right is specified then this
+ // If our width is auto and left or right is specified and changed then this
// is not just a movement - we need to resize to our container.
- if ((!a.left().isIntrinsicOrAuto() || !a.right().isIntrinsicOrAuto()) && width.isIntrinsicOrAuto())
+ if (width.isIntrinsicOrAuto()
+ && ((!a.left().isIntrinsicOrAuto() && a.left() != b.left())
+ || (!a.right().isIntrinsicOrAuto() && a.right() != b.right())))
return false;
// One of the units is fixed or percent in both directions and stayed
return true;
}
-StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
+StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle& other, unsigned& changedContextSensitiveProperties) 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() && diffNeedsFullLayout(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();
+ }
}
- 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 (diffNeedsRepaintLayer(other))
+ diff.setNeedsRepaintLayer();
+ else if (diffNeedsRepaintObject(other))
+ diff.setNeedsRepaintObject();
+
+ changedContextSensitiveProperties = computeChangedContextSensitiveProperties(other, diff);
+
+ if (diff.hasNoChange() && diffNeedsRecompositeLayer(other))
+ diff.setNeedsRecompositeLayer();
- if (m_box->verticalAlign() != other->m_box->verticalAlign())
- 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 repaint or layout.
- if (m_box->boxSizing() != other->m_box->boxSizing())
- return StyleDifferenceLayout;
+ // 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::diffNeedsFullLayout(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()
+ || 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 (m_box->verticalAlign() != other.m_box->verticalAlign())
+ return true;
+
+ if (m_box->boxSizing() != other.m_box->boxSizing())
+ return true;
}
- if (surround.get() != other->surround.get()) {
- if (surround->margin != other->surround->margin)
- return StyleDifferenceLayout;
+ if (surround.get() != other.surround.get()) {
+ if (surround->margin != other.surround->margin)
+ return true;
- if (surround->padding != other->surround->padding)
- return StyleDifferenceLayout;
+ if (surround->padding != other.surround->padding)
+ 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;
+ 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_regionFragment != other->rareNonInheritedData->m_regionFragment
- || 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_shapeInside != other->rareNonInheritedData->m_shapeInside
- || 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_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 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->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
- return StyleDifferenceLayout;
+ if (rareNonInheritedData->m_flexibleBox.get() != other.rareNonInheritedData->m_flexibleBox.get()
+ && *rareNonInheritedData->m_flexibleBox.get() != *other.rareNonInheritedData->m_flexibleBox.get())
+ return true;
- if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get()
- && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.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_transform.get() != other->rareNonInheritedData->m_transform.get()
- && *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
- // 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->reflectionDataEquivalent(*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 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->m_lineGrid != other->rareInheritedData->m_lineGrid
- || rareInheritedData->m_lineSnap != other->rareInheritedData->m_lineSnap
- || rareInheritedData->m_lineAlign != other->rareInheritedData->m_lineAlign
- || 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 (visual->m_textAutosizingMultiplier != other.visual->m_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 (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._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 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;
+ 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 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;
+ && ((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 StyleDifferenceLayout;
+ 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;
-
- // 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;
+ if ((visibility() == COLLAPSE) != (other.visibility() == COLLAPSE))
+ return true;
- // 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 && positionedObjectMoved(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;
+ 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 true;
}
- return repaintOnlyDiff(other, changedContextSensitiveProperties);
+ // Movement of non-static-positioned object is special cased in RenderStyle::visualInvalidationDiff().
+
+ return false;
}
-StyleDifference RenderStyle::repaintOnlyDiff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
+bool RenderStyle::diffNeedsRepaintLayer(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.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->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_mask != other.rareNonInheritedData->m_mask
+ || rareNonInheritedData->m_maskBoxImage != other.rareNonInheritedData->m_maskBoxImage)
+ 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;
+ return false;
+}
+
+bool RenderStyle::diffNeedsRepaintObject(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
+ || !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->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)
- return StyleDifferenceRecompositeLayer;
+ if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+ if (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
+ || rareNonInheritedData->m_shapeOutside != other.rareNonInheritedData->m_shapeOutside
+ || rareNonInheritedData->m_clipPath != other.rareNonInheritedData->m_clipPath)
+ 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::diffNeedsRecompositeLayer(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
+ || rareNonInheritedData->m_perspective != other.rareNonInheritedData->m_perspective
+ || rareNonInheritedData->m_perspectiveOriginX != other.rareNonInheritedData->m_perspectiveOriginX
+ || rareNonInheritedData->m_perspectiveOriginY != other.rareNonInheritedData->m_perspectiveOriginY
+ || hasWillChangeCompositingHint() != other.hasWillChangeCompositingHint())
+ 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;
+ return false;
+}
+
+unsigned RenderStyle::computeChangedContextSensitiveProperties(const RenderStyle& other, StyleDifference diff) const
+{
+ unsigned changedContextSensitiveProperties = ContextSensitivePropertyNone;
+
+ // 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())
+ changedContextSensitiveProperties |= ContextSensitivePropertyZIndex;
+
+ if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+ if (!transformDataEquivalent(other))
+ changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
+
+ if (rareNonInheritedData->opacity != other.rareNonInheritedData->opacity)
+ changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
+
+ if (rareNonInheritedData->m_filter != other.rareNonInheritedData->m_filter)
+ changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
+ }
+
+ if (!diff.needsRepaint()) {
+ if (inherited->color != other.inherited->color
+ || inherited_flags._text_decorations != other.inherited_flags._text_decorations
+ || visual->textDecoration != other.visual->textDecoration) {
+ changedContextSensitiveProperties |= ContextSensitivePropertyTextOrColor;
+ } else if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+ if (rareNonInheritedData->m_textDecorationStyle != other.rareNonInheritedData->m_textDecorationStyle
+ || rareNonInheritedData->m_textDecorationColor != other.rareNonInheritedData->m_textDecorationColor)
+ changedContextSensitiveProperties |= ContextSensitivePropertyTextOrColor;
+ } 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)
+ changedContextSensitiveProperties |= ContextSensitivePropertyTextOrColor;
+ }
+ }
+
+ return changedContextSensitiveProperties;
}
void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
{
- if (QuotesData::equals(rareInheritedData->quotes.get(), q.get()))
- return;
rareInheritedData.access()->quotes = q;
}
void RenderStyle::clearCursorList()
{
if (rareInheritedData->cursorData)
- rareInheritedData.access()->cursorData = 0;
+ rareInheritedData.access()->cursorData = nullptr;
}
void RenderStyle::addCallbackSelector(const String& selector)
return false;
}
+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:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation> >& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
{
// transform-origin brackets the transform with translate operations.
valueForLength(border.bottomRight().height(), size.height())));
}
-static float calcConstraintScaleFor(const IntRect& rect, const RoundedRect::Radii& radii)
-{
- // Constrain corner radii using CSS3 rules:
- // http://www.w3.org/TR/css3-background/#the-border-radius
-
- float factor = 1;
- unsigned radiiSum;
-
- // top
- radiiSum = static_cast<unsigned>(radii.topLeft().width()) + static_cast<unsigned>(radii.topRight().width()); // Casts to avoid integer overflow.
- if (radiiSum > static_cast<unsigned>(rect.width()))
- factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
-
- // bottom
- radiiSum = static_cast<unsigned>(radii.bottomLeft().width()) + static_cast<unsigned>(radii.bottomRight().width());
- if (radiiSum > static_cast<unsigned>(rect.width()))
- factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
-
- // left
- radiiSum = static_cast<unsigned>(radii.topLeft().height()) + static_cast<unsigned>(radii.bottomLeft().height());
- if (radiiSum > static_cast<unsigned>(rect.height()))
- factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
-
- // right
- radiiSum = static_cast<unsigned>(radii.topRight().height()) + static_cast<unsigned>(radii.bottomRight().height());
- if (radiiSum > static_cast<unsigned>(rect.height()))
- factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
-
- ASSERT(factor <= 1);
- return factor;
-}
-
StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); }
void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v)
{
RoundedRect roundedRect(snappedBorderRect);
if (hasBorderRadius()) {
RoundedRect::Radii radii = calcRadiiFor(surround->border, snappedBorderRect.size());
- radii.scale(calcConstraintScaleFor(snappedBorderRect, radii));
+ radii.scale(calcBorderRadiiConstraintScaleFor(borderRect, radii));
roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
}
return roundedRect;
CSSAnimationDataList* RenderStyle::accessAnimations()
{
if (!rareNonInheritedData.access()->m_animations)
- rareNonInheritedData.access()->m_animations = adoptPtr(new CSSAnimationDataList());
+ rareNonInheritedData.access()->m_animations = adoptPtrWillBeNoop(new CSSAnimationDataList());
return rareNonInheritedData->m_animations.get();
}
CSSAnimationDataList* RenderStyle::accessTransitions()
{
if (!rareNonInheritedData.access()->m_transitions)
- rareNonInheritedData.access()->m_transitions = adoptPtr(new CSSAnimationDataList());
+ 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;
-}
-
const Font& RenderStyle::font() const { return inherited->font; }
const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); }
const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); }
float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); }
float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
-int RenderStyle::fontSize() const { return inherited->font.pixelSize(); }
+int RenderStyle::fontSize() const { return fontDescription().computedPixelSize(); }
+FontWeight RenderStyle::fontWeight() const { return fontDescription().weight(); }
-float RenderStyle::wordSpacing() const { return inherited->font.wordSpacing(); }
-float RenderStyle::letterSpacing() const { return inherited->font.letterSpacing(); }
+float RenderStyle::wordSpacing() const { return fontDescription().wordSpacing(); }
+float RenderStyle::letterSpacing() const { return fontDescription().letterSpacing(); }
bool RenderStyle::setFontDescription(const FontDescription& v)
{
if (inherited->font.fontDescription() != v) {
- inherited.access()->font = Font(v, inherited->font.letterSpacing(), inherited->font.wordSpacing());
+ inherited.access()->font = Font(v);
return true;
}
return false;
}
-Length RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
+const Length& RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
Length RenderStyle::lineHeight() const
{
const Length& lh = inherited->line_height;
return lh.value();
}
-void RenderStyle::setWordSpacing(float v) { inherited.access()->font.setWordSpacing(v); }
-void RenderStyle::setLetterSpacing(float v) { inherited.access()->font.setLetterSpacing(v); }
+void RenderStyle::setWordSpacing(float wordSpacing)
+{
+ FontSelector* currentFontSelector = font().fontSelector();
+ FontDescription desc(fontDescription());
+ desc.setWordSpacing(wordSpacing);
+ setFontDescription(desc);
+ font().update(currentFontSelector);
+}
+
+void RenderStyle::setLetterSpacing(float letterSpacing)
+{
+ FontSelector* currentFontSelector = font().fontSelector();
+ FontDescription desc(fontDescription());
+ desc.setLetterSpacing(letterSpacing);
+ setFontDescription(desc);
+ font().update(currentFontSelector);
+}
void RenderStyle::setFontSize(float size)
{
font().update(currentFontSelector);
}
+void RenderStyle::setFontWeight(FontWeight weight)
+{
+ FontSelector* currentFontSelector = font().fontSelector();
+ FontDescription desc(fontDescription());
+ desc.setWeight(weight);
+ setFontDescription(desc);
+ font().update(currentFontSelector);
+}
+
void RenderStyle::getShadowExtent(const ShadowList* shadowList, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
{
top = 0;
surround.access()->border.m_image.setOutset(outset);
}
+float calcBorderRadiiConstraintScaleFor(const FloatRect& rect, const FloatRoundedRect::Radii& radii)
+{
+ // Constrain corner radii using CSS3 rules:
+ // http://www.w3.org/TR/css3-background/#the-border-radius
+
+ float factor = 1;
+ float radiiSum;
+
+ // top
+ radiiSum = radii.topLeft().width() + radii.topRight().width(); // Casts to avoid integer overflow.
+ if (radiiSum > rect.width())
+ factor = std::min(rect.width() / radiiSum, factor);
+
+ // bottom
+ radiiSum = radii.bottomLeft().width() + radii.bottomRight().width();
+ if (radiiSum > rect.width())
+ factor = std::min(rect.width() / radiiSum, factor);
+
+ // left
+ radiiSum = radii.topLeft().height() + radii.bottomLeft().height();
+ if (radiiSum > rect.height())
+ factor = std::min(rect.height() / radiiSum, factor);
+
+ // right
+ radiiSum = radii.topRight().height() + radii.bottomRight().height();
+ if (radiiSum > rect.height())
+ factor = std::min(rect.height() / radiiSum, factor);
+
+ ASSERT(factor <= 1);
+ return factor;
+}
+
} // namespace WebCore