| Index: Source/core/layout/LayoutBoxModelObject.cpp
|
| diff --git a/Source/core/layout/LayoutBoxModelObject.cpp b/Source/core/layout/LayoutBoxModelObject.cpp
|
| index cadd46946bfa2b7d2cba8f771cac23b5cbbb07d7..59d0499b13228e5d1c8ba14ff79f4de31473a946 100644
|
| --- a/Source/core/layout/LayoutBoxModelObject.cpp
|
| +++ b/Source/core/layout/LayoutBoxModelObject.cpp
|
| @@ -60,6 +60,8 @@ namespace blink {
|
| typedef HashMap<const LayoutBoxModelObject*, LayoutBoxModelObject*> ContinuationMap;
|
| static ContinuationMap* continuationMap = nullptr;
|
|
|
| +bool LayoutBoxModelObject::s_wasFloating = false;
|
| +
|
| void LayoutBoxModelObject::setSelectionState(SelectionState state)
|
| {
|
| if (state == SelectionInside && selectionState() != SelectionNone)
|
| @@ -93,12 +95,15 @@ bool LayoutBoxModelObject::hasAcceleratedCompositing() const
|
| }
|
|
|
| LayoutBoxModelObject::LayoutBoxModelObject(ContainerNode* node)
|
| - : LayoutLayerModelObject(node)
|
| + : LayoutObject(node)
|
| {
|
| }
|
|
|
| LayoutBoxModelObject::~LayoutBoxModelObject()
|
| {
|
| + // Our layer should have been destroyed and cleared by now
|
| + ASSERT(!hasLayer());
|
| + ASSERT(!m_layer);
|
| }
|
|
|
| void LayoutBoxModelObject::willBeDestroyed()
|
| @@ -108,9 +113,200 @@ void LayoutBoxModelObject::willBeDestroyed()
|
| // A continuation of this LayoutObject should be destroyed at subclasses.
|
| ASSERT(!continuation());
|
|
|
| - LayoutLayerModelObject::willBeDestroyed();
|
| + if (isPositioned()) {
|
| + // Don't use this->view() because the document's renderView has been set to 0 during destruction.
|
| + if (LocalFrame* frame = this->frame()) {
|
| + if (FrameView* frameView = frame->view()) {
|
| + if (style()->hasViewportConstrainedPosition())
|
| + frameView->removeViewportConstrainedObject(this);
|
| + }
|
| + }
|
| + }
|
| +
|
| + LayoutObject::willBeDestroyed();
|
| +
|
| + destroyLayer();
|
| +}
|
| +
|
| +void LayoutBoxModelObject::styleWillChange(StyleDifference diff, const LayoutStyle& newStyle)
|
| +{
|
| + s_wasFloating = isFloating();
|
| +
|
| + if (const LayoutStyle* oldStyle = style()) {
|
| + if (parent() && diff.needsPaintInvalidationLayer()) {
|
| + if (oldStyle->hasAutoClip() != newStyle.hasAutoClip()
|
| + || oldStyle->clip() != newStyle.clip())
|
| + layer()->clipper().clearClipRectsIncludingDescendants();
|
| + }
|
| + }
|
| +
|
| + LayoutObject::styleWillChange(diff, newStyle);
|
| +}
|
| +
|
| +void LayoutBoxModelObject::styleDidChange(StyleDifference diff, const LayoutStyle* oldStyle)
|
| +{
|
| + bool hadTransform = hasTransformRelatedProperty();
|
| + bool hadLayer = hasLayer();
|
| + bool layerWasSelfPainting = hadLayer && layer()->isSelfPaintingLayer();
|
| +
|
| + LayoutObject::styleDidChange(diff, oldStyle);
|
| + updateFromStyle();
|
| +
|
| + LayerType type = layerTypeRequired();
|
| + if (type != NoLayer) {
|
| + if (!layer() && layerCreationAllowedForSubtree()) {
|
| + if (s_wasFloating && isFloating())
|
| + setChildNeedsLayout();
|
| + createLayer(type);
|
| + if (parent() && !needsLayout()) {
|
| + // FIXME: We should call a specialized version of this function.
|
| + layer()->updateLayerPositionsAfterLayout();
|
| + }
|
| + }
|
| + } else if (layer() && layer()->parent()) {
|
| + setHasTransformRelatedProperty(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit.
|
| + setHasReflection(false);
|
| + layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
|
| + if (s_wasFloating && isFloating())
|
| + setChildNeedsLayout();
|
| + if (hadTransform)
|
| + setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
|
| + }
|
| +
|
| + if (layer()) {
|
| + // FIXME: Ideally we shouldn't need this setter but we can't easily infer an overflow-only layer
|
| + // from the style.
|
| + layer()->setLayerType(type);
|
| +
|
| + layer()->styleChanged(diff, oldStyle);
|
| + if (hadLayer && layer()->isSelfPaintingLayer() != layerWasSelfPainting)
|
| + setChildNeedsLayout();
|
| + }
|
| +
|
| + if (FrameView *frameView = view()->frameView()) {
|
| + bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosition();
|
| + bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition();
|
| + if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) {
|
| + if (newStyleIsViewportConstained && layer())
|
| + frameView->addViewportConstrainedObject(this);
|
| + else
|
| + frameView->removeViewportConstrainedObject(this);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void LayoutBoxModelObject::createLayer(LayerType type)
|
| +{
|
| + ASSERT(!m_layer);
|
| + m_layer = adoptPtr(new Layer(this, type));
|
| + setHasLayer(true);
|
| + m_layer->insertOnlyThisLayer();
|
| +}
|
| +
|
| +void LayoutBoxModelObject::destroyLayer()
|
| +{
|
| + setHasLayer(false);
|
| + m_layer = nullptr;
|
| +}
|
| +
|
| +bool LayoutBoxModelObject::hasSelfPaintingLayer() const
|
| +{
|
| + return m_layer && m_layer->isSelfPaintingLayer();
|
| +}
|
| +
|
| +LayerScrollableArea* LayoutBoxModelObject::scrollableArea() const
|
| +{
|
| + return m_layer ? m_layer->scrollableArea() : 0;
|
| +}
|
| +
|
| +void LayoutBoxModelObject::addLayerHitTestRects(LayerHitTestRects& rects, const Layer* currentLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const
|
| +{
|
| + if (hasLayer()) {
|
| + if (isRenderView()) {
|
| + // RenderView is handled with a special fast-path, but it needs to know the current layer.
|
| + LayoutObject::addLayerHitTestRects(rects, layer(), LayoutPoint(), LayoutRect());
|
| + } else {
|
| + // Since a LayoutObject never lives outside it's container Layer, we can switch
|
| + // to marking entire layers instead. This may sometimes mark more than necessary (when
|
| + // a layer is made of disjoint objects) but in practice is a significant performance
|
| + // savings.
|
| + layer()->addLayerHitTestRects(rects);
|
| + }
|
| + } else {
|
| + LayoutObject::addLayerHitTestRects(rects, currentLayer, layerOffset, containerRect);
|
| + }
|
| +}
|
| +
|
| +void LayoutBoxModelObject::invalidateTreeIfNeeded(const PaintInvalidationState& paintInvalidationState)
|
| +{
|
| + ASSERT(!needsLayout());
|
| +
|
| + if (!shouldCheckForPaintInvalidation(paintInvalidationState))
|
| + return;
|
| +
|
| + bool establishesNewPaintInvalidationContainer = isPaintInvalidationContainer();
|
| + const LayoutBoxModelObject& newPaintInvalidationContainer = *adjustCompositedContainerForSpecialAncestors(establishesNewPaintInvalidationContainer ? this : &paintInvalidationState.paintInvalidationContainer());
|
| + // FIXME: This assert should be re-enabled when we move paint invalidation to after compositing update. crbug.com/360286
|
| + // ASSERT(&newPaintInvalidationContainer == containerForPaintInvalidation());
|
| +
|
| + PaintInvalidationReason reason = invalidatePaintIfNeeded(paintInvalidationState, newPaintInvalidationContainer);
|
| + clearPaintInvalidationState(paintInvalidationState);
|
| +
|
| + PaintInvalidationState childTreeWalkState(paintInvalidationState, *this, newPaintInvalidationContainer);
|
| + if (reason == PaintInvalidationLocationChange)
|
| + childTreeWalkState.setForceCheckForPaintInvalidation();
|
| + invalidatePaintOfSubtreesIfNeeded(childTreeWalkState);
|
| +}
|
| +
|
| +void LayoutBoxModelObject::setBackingNeedsPaintInvalidationInRect(const LayoutRect& r, PaintInvalidationReason invalidationReason) const
|
| +{
|
| + // https://bugs.webkit.org/show_bug.cgi?id=61159 describes an unreproducible crash here,
|
| + // so assert but check that the layer is composited.
|
| + ASSERT(compositingState() != NotComposited);
|
| +
|
| + // FIXME: generalize accessors to backing GraphicsLayers so that this code is squashing-agnostic.
|
| + if (layer()->groupedMapping()) {
|
| + LayoutRect paintInvalidationRect = r;
|
| + if (GraphicsLayer* squashingLayer = layer()->groupedMapping()->squashingLayer()) {
|
| + // Note: the subpixel accumulation of layer() does not need to be added here. It is already taken into account.
|
| + squashingLayer->setNeedsDisplayInRect(pixelSnappedIntRect(paintInvalidationRect), invalidationReason);
|
| + }
|
| + } else {
|
| + layer()->compositedLayerMapping()->setContentsNeedDisplayInRect(r, invalidationReason);
|
| + }
|
| }
|
|
|
| +void LayoutBoxModelObject::addChildFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint& additionalOffset) const
|
| +{
|
| + for (LayoutObject* current = slowFirstChild(); current; current = current->nextSibling()) {
|
| + if (current->isText() || current->isListMarker())
|
| + continue;
|
| +
|
| + if (!current->isBox()) {
|
| + current->addFocusRingRects(rects, additionalOffset);
|
| + continue;
|
| + }
|
| +
|
| + RenderBox* box = toRenderBox(current);
|
| + if (!box->hasLayer()) {
|
| + box->addFocusRingRects(rects, additionalOffset + box->locationOffset());
|
| + continue;
|
| + }
|
| +
|
| + Vector<LayoutRect> layerFocusRingRects;
|
| + box->addFocusRingRects(layerFocusRingRects, LayoutPoint());
|
| + for (size_t i = 0; i < layerFocusRingRects.size(); ++i) {
|
| + FloatQuad quadInBox = box->localToContainerQuad(FloatQuad(layerFocusRingRects[i]), this);
|
| + LayoutRect rect = LayoutRect(quadInBox.boundingBox());
|
| + if (!rect.isEmpty()) {
|
| + rect.moveBy(additionalOffset);
|
| + rects.append(rect);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| bool LayoutBoxModelObject::calculateHasBoxDecorations() const
|
| {
|
| const LayoutStyle& styleToUse = styleRef();
|
| @@ -119,8 +315,6 @@ bool LayoutBoxModelObject::calculateHasBoxDecorations() const
|
|
|
| void LayoutBoxModelObject::updateFromStyle()
|
| {
|
| - LayoutLayerModelObject::updateFromStyle();
|
| -
|
| const LayoutStyle& styleToUse = styleRef();
|
| setHasBoxDecorationBackground(calculateHasBoxDecorations());
|
| setInline(styleToUse.isDisplayInlineType());
|
| @@ -481,7 +675,7 @@ void LayoutBoxModelObject::setContinuation(LayoutBoxModelObject* continuation)
|
|
|
| void LayoutBoxModelObject::computeLayerHitTestRects(LayerHitTestRects& rects) const
|
| {
|
| - LayoutLayerModelObject::computeLayerHitTestRects(rects);
|
| + LayoutObject::computeLayerHitTestRects(rects);
|
|
|
| // If there is a continuation then we need to consult it here, since this is
|
| // the root of the tree walk and it wouldn't otherwise get picked up.
|
| @@ -587,7 +781,7 @@ void LayoutBoxModelObject::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, Tra
|
| }
|
| }
|
|
|
| -const LayoutObject* LayoutBoxModelObject::pushMappingToContainer(const LayoutLayerModelObject* ancestorToStopAt, LayoutGeometryMap& geometryMap) const
|
| +const LayoutObject* LayoutBoxModelObject::pushMappingToContainer(const LayoutBoxModelObject* ancestorToStopAt, LayoutGeometryMap& geometryMap) const
|
| {
|
| ASSERT(ancestorToStopAt != this);
|
|
|
|
|