RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const { int leftWidth = (includeLogicalLeftEdge) ? borderLeftWidth() : 0; int rightWidth = (includeLogicalRightEdge) ? borderRightWidth() : 0; int topWidth = borderTopWidth(); int bottomWidth = borderBottomWidth(); return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge); }
/* compares two styles. The result gives an idea of the action that needs to be taken when replacing the old style with a new one. CbLayout: The containing block of the object needs a relayout. Layout: the RenderObject needs a relayout after the style change Visible: The change is visible, but no relayout is needed NonVisible: The object does need neither repaint nor relayout after the change. ### TODO: A lot can be optimised here based on the display type, lots of optimisations are unimplemented, and currently result in the worst case result causing a relayout of the containing block. */ RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const { #if ENABLE(SVG) // This is horribly inefficient. Eventually we'll have to integrate // this more directly by calling: Diff svgDiff = svgStyle->diff(other) // and then checking svgDiff and returning from the appropriate places below. if (m_svgStyle != other->m_svgStyle) return Layout; #endif if (box->width != other->box->width || box->min_width != other->box->min_width || box->max_width != other->box->max_width || box->height != other->box->height || box->min_height != other->box->min_height || box->max_height != other->box->max_height) return Layout; if (box->vertical_align != other->box->vertical_align || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align) return Layout; if (box->boxSizing != other->box->boxSizing) return Layout; if (surround->margin != other->surround->margin) return Layout; if (surround->padding != other->surround->padding) return Layout; if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) { if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance || rareNonInheritedData->marginTopCollapse != other->rareNonInheritedData->marginTopCollapse || rareNonInheritedData->marginBottomCollapse != other->rareNonInheritedData->marginBottomCollapse || rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp || rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow) return Layout; if (rareNonInheritedData->flexibleBox.get() != other->rareNonInheritedData->flexibleBox.get() && *rareNonInheritedData->flexibleBox.get() != *other->rareNonInheritedData->flexibleBox.get()) return Layout; if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get())) return Layout; if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get())) return Layout; if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get() && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get()) return Layout; if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get() && *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) return Layout; #if ENABLE(DASHBOARD_SUPPORT) // If regions change, trigger a relayout to re-calc regions. if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions) return Layout; #endif } if (rareInheritedData.get() != other->rareInheritedData.get()) { if (rareInheritedData->highlight != other->rareInheritedData->highlight || rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust || rareInheritedData->wordBreak != other->rareInheritedData->wordBreak || rareInheritedData->wordWrap != other->rareInheritedData->wordWrap || rareInheritedData->nbspMode != other->rareInheritedData->nbspMode || rareInheritedData->khtmlLineBreak != other->rareInheritedData->khtmlLineBreak || rareInheritedData->textSecurity != other->rareInheritedData->textSecurity) return Layout; if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get())) return Layout; if (textStrokeWidth() != other->textStrokeWidth()) return Layout; } if (inherited->indent != other->inherited->indent || inherited->line_height != other->inherited->line_height || inherited->list_style_image != other->inherited->list_style_image || inherited->font != other->inherited->font || inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing || inherited->vertical_border_spacing != other->inherited->vertical_border_spacing || inherited_flags._box_direction != other->inherited_flags._box_direction || inherited_flags._visuallyOrdered != other->inherited_flags._visuallyOrdered || inherited_flags._htmlHacks != other->inherited_flags._htmlHacks || noninherited_flags._position != other->noninherited_flags._position || noninherited_flags._floating != other->noninherited_flags._floating || noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay) return Layout; if (((int)noninherited_flags._effectiveDisplay) >= TABLE) { 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 Layout; // 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 Layout; } 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 Layout; } if (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 || noninherited_flags._clear != other->noninherited_flags._clear) return Layout; // Overflow returns a layout hint. if (noninherited_flags._overflowX != other->noninherited_flags._overflowX || noninherited_flags._overflowY != other->noninherited_flags._overflowY) return Layout; // 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 Layout; // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree. const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get(); const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get(); if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB))) return Layout; if (visual->counterIncrement != other->visual->counterIncrement || visual->counterReset != other->visual->counterReset) return Layout; if (inherited->m_effectiveZoom != other->inherited->m_effectiveZoom) return Layout; // Make sure these left/top/right/bottom checks stay below all layout checks and above // all visible checks. if (position() != StaticPosition) { if (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)) return LayoutPositionedMovementOnly; // FIXME: We will need to do a bit of work in RenderObject/Box::setStyle before we // can stop doing a layout when relative positioned objects move. In particular, we'll need // to update scrolling positions and figure out how to do a repaint properly of the updated layer. //if (other->position() == RelativePosition) // return RepaintLayer; //else return Layout; } else if (box->z_index != other->box->z_index || box->z_auto != other->box->z_auto || visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip) return RepaintLayer; } if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity || rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage) return RepaintLayer; if (inherited->color != other->inherited->color || inherited_flags._visibility != other->inherited_flags._visibility || inherited_flags._text_decorations != other->inherited_flags._text_decorations || inherited_flags._force_backgrounds_to_white != other->inherited_flags._force_backgrounds_to_white || surround->border != other->surround->border || *background.get() != *other->background.get() || visual->textDecoration != other->visual->textDecoration || rareInheritedData->userModify != other->rareInheritedData->userModify || rareInheritedData->userSelect != other->rareInheritedData->userSelect || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor) return Repaint; // Cursors are not checked, since they will be set appropriately in response to mouse events, // so they don't need to cause any repaint or layout. // Animations don't need to be checked either. We always set the new style on the RenderObject, so we will get a chance to fire off // the resulting transition properly. return Equal; }
bool RenderStyle::diffNeedsFullLayout(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->textOverflow != other.rareNonInheritedData->textOverflow || rareNonInheritedData->m_wrapFlow != other.rareNonInheritedData->m_wrapFlow || rareNonInheritedData->m_wrapThrough != other.rareNonInheritedData->m_wrapThrough || 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) return true; if (rareNonInheritedData->m_flexibleBox.get() != other.rareNonInheritedData->m_flexibleBox.get() && *rareNonInheritedData->m_flexibleBox.get() != *other.rareNonInheritedData->m_flexibleBox.get()) return true; // FIXME: We should add an optimized form of layout that just recomputes visual overflow. if (!rareNonInheritedData->shadowDataEquivalent(*other.rareNonInheritedData.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(); if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB))) 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()) { // 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 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->wordBreak != other.rareInheritedData->wordBreak || rareInheritedData->overflowWrap != other.rareInheritedData->overflowWrap || rareInheritedData->lineBreak != other.rareInheritedData->lineBreak || 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->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->textStrokeWidth != other.rareInheritedData->textStrokeWidth) return true; if (!rareInheritedData->shadowDataEquivalent(*other.rareInheritedData.get())) 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 true; } if (inherited_flags.m_rtlOrdering != other.inherited_flags.m_rtlOrdering || inherited_flags._text_align != other.inherited_flags._text_align || inherited_flags._direction != other.inherited_flags._direction || inherited_flags._white_space != other.inherited_flags._white_space) return true; if (noninherited_flags.overflowX != other.noninherited_flags.overflowX || noninherited_flags.overflowY != other.noninherited_flags.overflowY || noninherited_flags.unicodeBidi != other.noninherited_flags.unicodeBidi || noninherited_flags.position != other.noninherited_flags.position || noninherited_flags.originalDisplay != other.noninherited_flags.originalDisplay) return true; if (!m_background->outline().visuallyEqual(other.m_background->outline())) { // FIXME: We only really need to recompute the overflow but we don't have an optimized layout for it. return true; } 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 (noninherited_flags.verticalAlign != other.noninherited_flags.verticalAlign) return true; if (surround.get() != other.surround.get()) { if (surround->margin != other.surround->margin) return true; if (surround->padding != other.surround->padding) return true; } // Movement of non-static-positioned object is special cased in RenderStyle::visualInvalidationDiff(). return false; }