#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;
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();
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)
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) {
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());
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)
void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
{
- if (QuotesData::equals(rareInheritedData->quotes.get(), q.get()))
- return;
rareInheritedData.access()->quotes = q;
}
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));
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;
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;
}
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;
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
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; }
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(); }
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
{
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());
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);
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;
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);
}
}
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);
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);
}
}
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
return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
}
-void RenderStyle::setMarginStart(Length margin)
+void RenderStyle::setMarginStart(const Length& margin)
{
if (isHorizontalWritingMode()) {
if (isLeftToRightDirection())
}
}
-void RenderStyle::setMarginEnd(Length margin)
+void RenderStyle::setMarginEnd(const Length& margin)
{
if (isHorizontalWritingMode()) {
if (isLeftToRightDirection())
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;
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