StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle& other) const { // 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 diff; if (diffNeedsFullLayout(other)) { diff.setNeedsFullLayout(); } else if (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(); } updatePropertySpecificDifferences(other, diff); // 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. return diff; }
void RenderLayerModelObject::styleWillChange(StyleDifference diff, const RenderStyle& newStyle) { s_wasFloating = isFloating(); // If our z-index changes value or our visibility changes, // we need to dirty our stacking context's z-order list. RenderStyle* oldStyle = style(); if (oldStyle) { // Do a repaint with the old style first through RenderLayerRepainter. // RenderObject::styleWillChange takes care of repainting objects without RenderLayers. if (parent() && diff.needsRepaintLayer()) { layer()->repainter().repaintIncludingNonCompositingDescendants(); if (oldStyle->hasClip() != newStyle.hasClip() || oldStyle->clip() != newStyle.clip()) layer()->clipper().clearClipRectsIncludingDescendants(); } else if (diff.needsFullLayout()) { if (hasLayer()) { if (!layer()->hasCompositedLayerMapping() && oldStyle->position() != newStyle.position()) layer()->repainter().repaintIncludingNonCompositingDescendants(); } else if (newStyle.hasTransform() || newStyle.opacity() < 1 || newStyle.hasFilter()) { // If we don't have a layer yet, but we are going to get one because of transform or opacity, // then we need to repaint the old position of the object. paintInvalidationForWholeRenderer(); } } } RenderObject::styleWillChange(diff, newStyle); }
void RenderSVGResourceContainer::registerResource() { SVGDocumentExtensions& extensions = svgExtensionsFromElement(element()); if (!extensions.hasPendingResource(m_id)) { extensions.addResource(m_id, this); return; } OwnPtr<SVGDocumentExtensions::SVGPendingElements> clients(extensions.removePendingResource(m_id)); // Cache us with the new id. extensions.addResource(m_id, this); // Update cached resources of pending clients. const SVGDocumentExtensions::SVGPendingElements::const_iterator end = clients->end(); for (SVGDocumentExtensions::SVGPendingElements::const_iterator it = clients->begin(); it != end; ++it) { ASSERT((*it)->hasPendingResources()); extensions.clearHasPendingResourcesIfPossible(*it); RenderObject* renderer = (*it)->renderer(); if (!renderer) continue; StyleDifference diff; diff.setNeedsFullLayout(); SVGResourcesCache::clientStyleChanged(renderer, diff, renderer->style()); renderer->setNeedsLayoutAndFullPaintInvalidation(); } }
void LayoutSVGRoot::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle) { if (diff.needsFullLayout()) setNeedsBoundariesUpdate(); if (diff.needsPaintInvalidation()) { // Box decorations may have appeared/disappeared - recompute status. m_hasBoxDecorationBackground = calculateHasBoxDecorations(); } LayoutReplaced::styleDidChange(diff, oldStyle); SVGResourcesCache::clientStyleChanged(this, diff, styleRef()); }
void RenderSVGRoot::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { if (diff.needsFullLayout()) setNeedsBoundariesUpdate(); if (diff.needsRepaint()) { // Box decorations may have appeared/disappeared - recompute status. m_hasBoxDecorations = calculateHasBoxDecorations(); } RenderReplaced::styleDidChange(diff, oldStyle); SVGResourcesCache::clientStyleChanged(this, diff, style()); }
StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const { StyleDifference styleDifference; if (diffNeedsLayoutAndPaintInvalidation(other)) { styleDifference.setNeedsFullLayout(); styleDifference.setNeedsPaintInvalidationObject(); } else if (diffNeedsPaintInvalidation(other)) { styleDifference.setNeedsPaintInvalidationObject(); } return styleDifference; }
StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const { StyleDifference styleDifference; if (diffNeedsLayoutAndRepaint(other)) { styleDifference.setNeedsFullLayout(); styleDifference.setNeedsRepaintObject(); } else if (diffNeedsRepaint(other)) { styleDifference.setNeedsRepaintObject(); } return styleDifference; }
void LayoutTableRow::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle) { ASSERT(style()->display() == TABLE_ROW); LayoutBox::styleDidChange(diff, oldStyle); propagateStyleToAnonymousChildren(); if (section() && oldStyle && style()->logicalHeight() != oldStyle->logicalHeight()) section()->rowLogicalHeightChanged(this); // If border was changed, notify table. if (parent()) { LayoutTable* table = this->table(); if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border()) table->invalidateCollapsedBorders(); if (table && oldStyle && diff.needsFullLayout() && needsLayout() && table->collapseBorders() && borderWidthChanged(oldStyle, style())) { // If the border width changes on a row, we need to make sure the cells in the row know to lay out again. // This only happens when borders are collapsed, since they end up affecting the border sides of the cell // itself. for (LayoutBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) { if (!childBox->isTableCell()) continue; childBox->setChildNeedsLayout(); } } } }
void LayoutSVGInline::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle) { if (diff.needsFullLayout()) setNeedsBoundariesUpdate(); LayoutInline::styleDidChange(diff, oldStyle); SVGResourcesCache::clientStyleChanged(this, diff, styleRef()); }
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(); } }
void LayoutSVGBlock::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle) { if (diff.needsFullLayout()) { setNeedsBoundariesUpdate(); if (diff.transformChanged()) setNeedsTransformUpdate(); } if (isBlendingAllowed()) { bool hasBlendModeChanged = (oldStyle && oldStyle->hasBlendMode()) == !style()->hasBlendMode(); if (parent() && hasBlendModeChanged) parent()->descendantIsolationRequirementsChanged(style()->hasBlendMode() ? DescendantIsolationRequired : DescendantIsolationNeedsUpdate); } LayoutBlock::styleDidChange(diff, oldStyle); SVGResourcesCache::clientStyleChanged(this, diff, styleRef()); }
void RenderSVGBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { if (diff.needsFullLayout()) setNeedsBoundariesUpdate(); RenderBlock::styleDidChange(diff, oldStyle); SVGResourcesCache::clientStyleChanged(this, diff, style()); }
void LayoutScrollbarPart::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle) { LayoutBlock::styleDidChange(diff, oldStyle); setInline(false); clearPositionedState(); setFloating(false); setHasOverflowClip(false); if (oldStyle && m_scrollbar && m_part != NoPart && (diff.needsPaintInvalidation() || diff.needsLayout())) m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part); }
void LayoutSVGResourceContainer::registerResource() { SVGDocumentExtensions& extensions = svgExtensionsFromElement(element()); if (!extensions.hasPendingResource(m_id)) { extensions.addResource(m_id, this); return; } SVGDocumentExtensions::SVGPendingElements* clients(extensions.removePendingResource(m_id)); // Cache us with the new id. extensions.addResource(m_id, this); // Update cached resources of pending clients. for (const auto& pendingClient : *clients) { ASSERT(pendingClient->hasPendingResources()); extensions.clearHasPendingResourcesIfPossible(pendingClient); LayoutObject* layoutObject = pendingClient->layoutObject(); if (!layoutObject) continue; const ComputedStyle& style = layoutObject->styleRef(); // If the client has a layer (is a non-SVGElement) we need to signal // invalidation in the same way as is done in markAllResourceClientsForInvalidation above. if (layoutObject->hasLayer() && resourceType() == FilterResourceType) { if (style.hasFilter()) toLayoutBoxModelObject(layoutObject)->layer()->filterNeedsPaintInvalidation(); // If this is the SVG root, we could have both 'filter' and // '-webkit-filter' applied, so we need to do the invalidation // below as well, unless we can optimistically determine that // 'filter' does not apply to the element in question. if (!layoutObject->isSVGRoot() || !style.svgStyle().hasFilter()) continue; } StyleDifference diff; diff.setNeedsFullLayout(); SVGResourcesCache::clientStyleChanged(layoutObject, diff, style); layoutObject->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::SvgResourceInvalidated); } }
void SVGInlineTextBoxPainter::paintText(const PaintInfo& paintInfo, const ComputedStyle& style, const ComputedStyle& selectionStyle, const SVGTextFragment& fragment, LayoutSVGResourceMode resourceMode, bool shouldPaintSelection) { int startPosition = 0; int endPosition = 0; if (shouldPaintSelection) { m_svgInlineTextBox.selectionStartEnd(startPosition, endPosition); shouldPaintSelection = m_svgInlineTextBox.mapStartEndPositionsIntoFragmentCoordinates(fragment, startPosition, endPosition); } // Fast path if there is no selection, just draw the whole chunk part using the regular style TextRun textRun = m_svgInlineTextBox.constructTextRun(style, fragment); if (!shouldPaintSelection || startPosition >= endPosition) { paintTextWithShadows(paintInfo, style, textRun, fragment, 0, fragment.length, resourceMode); return; } // Eventually draw text using regular style until the start position of the selection bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; if (startPosition > 0 && !paintSelectedTextOnly) paintTextWithShadows(paintInfo, style, textRun, fragment, 0, startPosition, resourceMode); // Draw text using selection style from the start to the end position of the selection if (style != selectionStyle) { StyleDifference diff; diff.setNeedsPaintInvalidationObject(); SVGResourcesCache::clientStyleChanged(&m_svgInlineTextBox.parent()->layoutObject(), diff, selectionStyle); } paintTextWithShadows(paintInfo, selectionStyle, textRun, fragment, startPosition, endPosition, resourceMode); if (style != selectionStyle) { StyleDifference diff; diff.setNeedsPaintInvalidationObject(); SVGResourcesCache::clientStyleChanged(&m_svgInlineTextBox.parent()->layoutObject(), diff, style); } // Eventually draw text using regular style from the end position of the selection to the end of the current chunk part if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnly) paintTextWithShadows(paintInfo, style, textRun, fragment, endPosition, fragment.length, resourceMode); }
void RenderSVGModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { if (diff.needsFullLayout()) { setNeedsBoundariesUpdate(); if (style()->hasTransform()) setNeedsTransformUpdate(); } RenderObject::styleDidChange(diff, oldStyle); SVGResourcesCache::clientStyleChanged(this, diff, style()); }
void RenderLayerModelObject::styleWillChange(StyleDifference diff, const RenderStyle& newStyle) { if (RenderStyle* oldStyle = style()) { if (parent() && diff.needsPaintInvalidationLayer()) { if (oldStyle->hasAutoClip() != newStyle.hasAutoClip() || oldStyle->clip() != newStyle.clip()) layer()->clipper().clearClipRectsIncludingDescendants(); } } RenderObject::styleWillChange(diff, newStyle); }
void SVGResourcesCache::clientStyleChanged(LayoutObject* layoutObject, StyleDifference diff, const ComputedStyle& newStyle) { ASSERT(layoutObject); ASSERT(layoutObject->node()); ASSERT(layoutObject->node()->isSVGElement()); if (!diff.hasDifference() || !layoutObject->parent()) return; // In this case the proper SVGFE*Element will decide whether the modified CSS properties require a relayout or paintInvalidation. if (layoutObject->isSVGResourceFilterPrimitive() && !diff.needsLayout()) return; // Dynamic changes of CSS properties like 'clip-path' may require us to recompute the associated resources for a layoutObject. // FIXME: Avoid passing in a useless StyleDifference, but instead compare oldStyle/newStyle to see which resources changed // to be able to selectively rebuild individual resources, instead of all of them. if (layoutObjectCanHaveResources(layoutObject)) { SVGResourcesCache* cache = resourcesCacheFromLayoutObject(layoutObject); cache->removeResourcesFromLayoutObject(layoutObject); cache->addResourcesFromLayoutObject(layoutObject, newStyle); } LayoutSVGResourceContainer::markForLayoutAndParentResourceInvalidation(layoutObject, false); }
void LayoutSVGRect::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle) { if (diff.needsFullLayout() && oldStyle) { const SVGComputedStyle& oldSvgStyle = oldStyle->svgStyle(); const SVGComputedStyle& svgStyle = style()->svgStyle(); if (oldSvgStyle.rx() != svgStyle.rx() || oldSvgStyle.ry() != svgStyle.ry() || oldSvgStyle.vectorEffect() != svgStyle.vectorEffect() || definitelyHasSimpleStroke(oldSvgStyle) != definitelyHasSimpleStroke(svgStyle)) setNeedsShapeUpdate(); } // Superclass will take care of calling clientStyleChanged. LayoutSVGShape::styleDidChange(diff, oldStyle); }
void RenderSVGGradientStop::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderObject::styleDidChange(diff, oldStyle); if (!diff.hasDifference()) return; // <stop> elements should only be allowed to make renderers under gradient elements // but I can imagine a few cases we might not be catching, so let's not crash if our parent isn't a gradient. SVGGradientElement* gradient = gradientElement(); if (!gradient) return; RenderObject* renderer = gradient->renderer(); if (!renderer) return; RenderSVGResourceContainer* container = toRenderSVGResourceContainer(renderer); container->removeAllClientsFromCache(); }
void LayoutSVGInlineText::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle) { LayoutText::styleDidChange(diff, oldStyle); updateScaledFont(); bool newPreserves = style() ? style()->whiteSpace() == PRE : false; bool oldPreserves = oldStyle ? oldStyle->whiteSpace() == PRE : false; if (oldPreserves != newPreserves) { setText(originalText(), true); return; } if (!diff.needsFullLayout()) return; // The text metrics may be influenced by style changes. if (LayoutSVGText* textLayoutObject = LayoutSVGText::locateLayoutSVGTextAncestor(this)) textLayoutObject->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::StyleChange); }
void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { m_desiredInnerEditorLogicalHeight = -1; RenderTextControl::styleDidChange(diff, oldStyle); // We may have set the width and the height in the old style in layout(). // Reset them now to avoid getting a spurious layout hint. Element* viewPort = editingViewPortElement(); if (RenderObject* viewPortRenderer = viewPort ? viewPort->renderer() : 0) { viewPortRenderer->style()->setHeight(Length()); viewPortRenderer->style()->setWidth(Length()); } Element* container = containerElement(); if (RenderObject* containerRenderer = container ? container->renderer() : 0) { containerRenderer->style()->setHeight(Length()); containerRenderer->style()->setWidth(Length()); } RenderObject* innerEditorRenderer = innerEditorElement()->renderer(); if (innerEditorRenderer && diff.needsFullLayout()) innerEditorRenderer->setNeedsLayoutAndFullPaintInvalidation(); if (HTMLElement* placeholder = inputElement()->placeholderElement()) placeholder->setInlineStyleProperty(CSSPropertyTextOverflow, textShouldBeTruncated() ? CSSValueEllipsis : CSSValueClip); setHasOverflowClip(false); }