| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) | 4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) |
| 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) | 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) |
| 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
| 7 * Copyright (C) 2010 Google Inc. All rights reserved. | 7 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 8 * | 8 * |
| 9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
| 10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 // The HashMap for storing continuation pointers. | 53 // The HashMap for storing continuation pointers. |
| 54 // An inline can be split with blocks occuring in between the inline content. | 54 // An inline can be split with blocks occuring in between the inline content. |
| 55 // When this occurs we need a pointer to the next object. We can basically be | 55 // When this occurs we need a pointer to the next object. We can basically be |
| 56 // split into a sequence of inlines and blocks. The continuation will either be | 56 // split into a sequence of inlines and blocks. The continuation will either be |
| 57 // an anonymous block (that houses other blocks) or it will be an inline flow. | 57 // an anonymous block (that houses other blocks) or it will be an inline flow. |
| 58 // <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as | 58 // <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as |
| 59 // its continuation but the <b> will just have an inline as its continuation. | 59 // its continuation but the <b> will just have an inline as its continuation. |
| 60 typedef HashMap<const LayoutBoxModelObject*, LayoutBoxModelObject*> Continuation
Map; | 60 typedef HashMap<const LayoutBoxModelObject*, LayoutBoxModelObject*> Continuation
Map; |
| 61 static ContinuationMap* continuationMap = nullptr; | 61 static ContinuationMap* continuationMap = nullptr; |
| 62 | 62 |
| 63 bool LayoutBoxModelObject::s_wasFloating = false; |
| 64 |
| 63 void LayoutBoxModelObject::setSelectionState(SelectionState state) | 65 void LayoutBoxModelObject::setSelectionState(SelectionState state) |
| 64 { | 66 { |
| 65 if (state == SelectionInside && selectionState() != SelectionNone) | 67 if (state == SelectionInside && selectionState() != SelectionNone) |
| 66 return; | 68 return; |
| 67 | 69 |
| 68 if ((state == SelectionStart && selectionState() == SelectionEnd) | 70 if ((state == SelectionStart && selectionState() == SelectionEnd) |
| 69 || (state == SelectionEnd && selectionState() == SelectionStart)) | 71 || (state == SelectionEnd && selectionState() == SelectionStart)) |
| 70 LayoutObject::setSelectionState(SelectionBoth); | 72 LayoutObject::setSelectionState(SelectionBoth); |
| 71 else | 73 else |
| 72 LayoutObject::setSelectionState(state); | 74 LayoutObject::setSelectionState(state); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 86 | 88 |
| 87 layer()->contentChanged(changeType); | 89 layer()->contentChanged(changeType); |
| 88 } | 90 } |
| 89 | 91 |
| 90 bool LayoutBoxModelObject::hasAcceleratedCompositing() const | 92 bool LayoutBoxModelObject::hasAcceleratedCompositing() const |
| 91 { | 93 { |
| 92 return view()->compositor()->hasAcceleratedCompositing(); | 94 return view()->compositor()->hasAcceleratedCompositing(); |
| 93 } | 95 } |
| 94 | 96 |
| 95 LayoutBoxModelObject::LayoutBoxModelObject(ContainerNode* node) | 97 LayoutBoxModelObject::LayoutBoxModelObject(ContainerNode* node) |
| 96 : LayoutLayerModelObject(node) | 98 : LayoutObject(node) |
| 97 { | 99 { |
| 98 } | 100 } |
| 99 | 101 |
| 100 LayoutBoxModelObject::~LayoutBoxModelObject() | 102 LayoutBoxModelObject::~LayoutBoxModelObject() |
| 101 { | 103 { |
| 104 // Our layer should have been destroyed and cleared by now |
| 105 ASSERT(!hasLayer()); |
| 106 ASSERT(!m_layer); |
| 102 } | 107 } |
| 103 | 108 |
| 104 void LayoutBoxModelObject::willBeDestroyed() | 109 void LayoutBoxModelObject::willBeDestroyed() |
| 105 { | 110 { |
| 106 ImageQualityController::remove(this); | 111 ImageQualityController::remove(this); |
| 107 | 112 |
| 108 // A continuation of this LayoutObject should be destroyed at subclasses. | 113 // A continuation of this LayoutObject should be destroyed at subclasses. |
| 109 ASSERT(!continuation()); | 114 ASSERT(!continuation()); |
| 110 | 115 |
| 111 LayoutLayerModelObject::willBeDestroyed(); | 116 if (isPositioned()) { |
| 112 } | 117 // Don't use this->view() because the document's renderView has been set
to 0 during destruction. |
| 118 if (LocalFrame* frame = this->frame()) { |
| 119 if (FrameView* frameView = frame->view()) { |
| 120 if (style()->hasViewportConstrainedPosition()) |
| 121 frameView->removeViewportConstrainedObject(this); |
| 122 } |
| 123 } |
| 124 } |
| 125 |
| 126 LayoutObject::willBeDestroyed(); |
| 127 |
| 128 destroyLayer(); |
| 129 } |
| 130 |
| 131 void LayoutBoxModelObject::styleWillChange(StyleDifference diff, const LayoutSty
le& newStyle) |
| 132 { |
| 133 s_wasFloating = isFloating(); |
| 134 |
| 135 if (const LayoutStyle* oldStyle = style()) { |
| 136 if (parent() && diff.needsPaintInvalidationLayer()) { |
| 137 if (oldStyle->hasAutoClip() != newStyle.hasAutoClip() |
| 138 || oldStyle->clip() != newStyle.clip()) |
| 139 layer()->clipper().clearClipRectsIncludingDescendants(); |
| 140 } |
| 141 } |
| 142 |
| 143 LayoutObject::styleWillChange(diff, newStyle); |
| 144 } |
| 145 |
| 146 void LayoutBoxModelObject::styleDidChange(StyleDifference diff, const LayoutStyl
e* oldStyle) |
| 147 { |
| 148 bool hadTransform = hasTransformRelatedProperty(); |
| 149 bool hadLayer = hasLayer(); |
| 150 bool layerWasSelfPainting = hadLayer && layer()->isSelfPaintingLayer(); |
| 151 |
| 152 LayoutObject::styleDidChange(diff, oldStyle); |
| 153 updateFromStyle(); |
| 154 |
| 155 LayerType type = layerTypeRequired(); |
| 156 if (type != NoLayer) { |
| 157 if (!layer() && layerCreationAllowedForSubtree()) { |
| 158 if (s_wasFloating && isFloating()) |
| 159 setChildNeedsLayout(); |
| 160 createLayer(type); |
| 161 if (parent() && !needsLayout()) { |
| 162 // FIXME: We should call a specialized version of this function. |
| 163 layer()->updateLayerPositionsAfterLayout(); |
| 164 } |
| 165 } |
| 166 } else if (layer() && layer()->parent()) { |
| 167 setHasTransformRelatedProperty(false); // Either a transform wasn't spec
ified or the object doesn't support transforms, so just null out the bit. |
| 168 setHasReflection(false); |
| 169 layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_l
ayer |
| 170 if (s_wasFloating && isFloating()) |
| 171 setChildNeedsLayout(); |
| 172 if (hadTransform) |
| 173 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); |
| 174 } |
| 175 |
| 176 if (layer()) { |
| 177 // FIXME: Ideally we shouldn't need this setter but we can't easily infe
r an overflow-only layer |
| 178 // from the style. |
| 179 layer()->setLayerType(type); |
| 180 |
| 181 layer()->styleChanged(diff, oldStyle); |
| 182 if (hadLayer && layer()->isSelfPaintingLayer() != layerWasSelfPainting) |
| 183 setChildNeedsLayout(); |
| 184 } |
| 185 |
| 186 if (FrameView *frameView = view()->frameView()) { |
| 187 bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosit
ion(); |
| 188 bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportCo
nstrainedPosition(); |
| 189 if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) { |
| 190 if (newStyleIsViewportConstained && layer()) |
| 191 frameView->addViewportConstrainedObject(this); |
| 192 else |
| 193 frameView->removeViewportConstrainedObject(this); |
| 194 } |
| 195 } |
| 196 } |
| 197 |
| 198 void LayoutBoxModelObject::createLayer(LayerType type) |
| 199 { |
| 200 ASSERT(!m_layer); |
| 201 m_layer = adoptPtr(new Layer(this, type)); |
| 202 setHasLayer(true); |
| 203 m_layer->insertOnlyThisLayer(); |
| 204 } |
| 205 |
| 206 void LayoutBoxModelObject::destroyLayer() |
| 207 { |
| 208 setHasLayer(false); |
| 209 m_layer = nullptr; |
| 210 } |
| 211 |
| 212 bool LayoutBoxModelObject::hasSelfPaintingLayer() const |
| 213 { |
| 214 return m_layer && m_layer->isSelfPaintingLayer(); |
| 215 } |
| 216 |
| 217 LayerScrollableArea* LayoutBoxModelObject::scrollableArea() const |
| 218 { |
| 219 return m_layer ? m_layer->scrollableArea() : 0; |
| 220 } |
| 221 |
| 222 void LayoutBoxModelObject::addLayerHitTestRects(LayerHitTestRects& rects, const
Layer* currentLayer, const LayoutPoint& layerOffset, const LayoutRect& container
Rect) const |
| 223 { |
| 224 if (hasLayer()) { |
| 225 if (isRenderView()) { |
| 226 // RenderView is handled with a special fast-path, but it needs to k
now the current layer. |
| 227 LayoutObject::addLayerHitTestRects(rects, layer(), LayoutPoint(), La
youtRect()); |
| 228 } else { |
| 229 // Since a LayoutObject never lives outside it's container Layer, we
can switch |
| 230 // to marking entire layers instead. This may sometimes mark more th
an necessary (when |
| 231 // a layer is made of disjoint objects) but in practice is a signifi
cant performance |
| 232 // savings. |
| 233 layer()->addLayerHitTestRects(rects); |
| 234 } |
| 235 } else { |
| 236 LayoutObject::addLayerHitTestRects(rects, currentLayer, layerOffset, con
tainerRect); |
| 237 } |
| 238 } |
| 239 |
| 240 void LayoutBoxModelObject::invalidateTreeIfNeeded(const PaintInvalidationState&
paintInvalidationState) |
| 241 { |
| 242 ASSERT(!needsLayout()); |
| 243 |
| 244 if (!shouldCheckForPaintInvalidation(paintInvalidationState)) |
| 245 return; |
| 246 |
| 247 bool establishesNewPaintInvalidationContainer = isPaintInvalidationContainer
(); |
| 248 const LayoutBoxModelObject& newPaintInvalidationContainer = *adjustComposite
dContainerForSpecialAncestors(establishesNewPaintInvalidationContainer ? this :
&paintInvalidationState.paintInvalidationContainer()); |
| 249 // FIXME: This assert should be re-enabled when we move paint invalidation t
o after compositing update. crbug.com/360286 |
| 250 // ASSERT(&newPaintInvalidationContainer == containerForPaintInvalidation())
; |
| 251 |
| 252 PaintInvalidationReason reason = invalidatePaintIfNeeded(paintInvalidationSt
ate, newPaintInvalidationContainer); |
| 253 clearPaintInvalidationState(paintInvalidationState); |
| 254 |
| 255 PaintInvalidationState childTreeWalkState(paintInvalidationState, *this, new
PaintInvalidationContainer); |
| 256 if (reason == PaintInvalidationLocationChange) |
| 257 childTreeWalkState.setForceCheckForPaintInvalidation(); |
| 258 invalidatePaintOfSubtreesIfNeeded(childTreeWalkState); |
| 259 } |
| 260 |
| 261 void LayoutBoxModelObject::setBackingNeedsPaintInvalidationInRect(const LayoutRe
ct& r, PaintInvalidationReason invalidationReason) const |
| 262 { |
| 263 // https://bugs.webkit.org/show_bug.cgi?id=61159 describes an unreproducible
crash here, |
| 264 // so assert but check that the layer is composited. |
| 265 ASSERT(compositingState() != NotComposited); |
| 266 |
| 267 // FIXME: generalize accessors to backing GraphicsLayers so that this code i
s squashing-agnostic. |
| 268 if (layer()->groupedMapping()) { |
| 269 LayoutRect paintInvalidationRect = r; |
| 270 if (GraphicsLayer* squashingLayer = layer()->groupedMapping()->squashing
Layer()) { |
| 271 // Note: the subpixel accumulation of layer() does not need to be ad
ded here. It is already taken into account. |
| 272 squashingLayer->setNeedsDisplayInRect(pixelSnappedIntRect(paintInval
idationRect), invalidationReason); |
| 273 } |
| 274 } else { |
| 275 layer()->compositedLayerMapping()->setContentsNeedDisplayInRect(r, inval
idationReason); |
| 276 } |
| 277 } |
| 278 |
| 279 void LayoutBoxModelObject::addChildFocusRingRects(Vector<LayoutRect>& rects, con
st LayoutPoint& additionalOffset) const |
| 280 { |
| 281 for (LayoutObject* current = slowFirstChild(); current; current = current->n
extSibling()) { |
| 282 if (current->isText() || current->isListMarker()) |
| 283 continue; |
| 284 |
| 285 if (!current->isBox()) { |
| 286 current->addFocusRingRects(rects, additionalOffset); |
| 287 continue; |
| 288 } |
| 289 |
| 290 RenderBox* box = toRenderBox(current); |
| 291 if (!box->hasLayer()) { |
| 292 box->addFocusRingRects(rects, additionalOffset + box->locationOffset
()); |
| 293 continue; |
| 294 } |
| 295 |
| 296 Vector<LayoutRect> layerFocusRingRects; |
| 297 box->addFocusRingRects(layerFocusRingRects, LayoutPoint()); |
| 298 for (size_t i = 0; i < layerFocusRingRects.size(); ++i) { |
| 299 FloatQuad quadInBox = box->localToContainerQuad(FloatQuad(layerFocus
RingRects[i]), this); |
| 300 LayoutRect rect = LayoutRect(quadInBox.boundingBox()); |
| 301 if (!rect.isEmpty()) { |
| 302 rect.moveBy(additionalOffset); |
| 303 rects.append(rect); |
| 304 } |
| 305 } |
| 306 } |
| 307 } |
| 308 |
| 113 | 309 |
| 114 bool LayoutBoxModelObject::calculateHasBoxDecorations() const | 310 bool LayoutBoxModelObject::calculateHasBoxDecorations() const |
| 115 { | 311 { |
| 116 const LayoutStyle& styleToUse = styleRef(); | 312 const LayoutStyle& styleToUse = styleRef(); |
| 117 return hasBackground() || styleToUse.hasBorder() || styleToUse.hasAppearance
() || styleToUse.boxShadow(); | 313 return hasBackground() || styleToUse.hasBorder() || styleToUse.hasAppearance
() || styleToUse.boxShadow(); |
| 118 } | 314 } |
| 119 | 315 |
| 120 void LayoutBoxModelObject::updateFromStyle() | 316 void LayoutBoxModelObject::updateFromStyle() |
| 121 { | 317 { |
| 122 LayoutLayerModelObject::updateFromStyle(); | |
| 123 | |
| 124 const LayoutStyle& styleToUse = styleRef(); | 318 const LayoutStyle& styleToUse = styleRef(); |
| 125 setHasBoxDecorationBackground(calculateHasBoxDecorations()); | 319 setHasBoxDecorationBackground(calculateHasBoxDecorations()); |
| 126 setInline(styleToUse.isDisplayInlineType()); | 320 setInline(styleToUse.isDisplayInlineType()); |
| 127 setPositionState(styleToUse.position()); | 321 setPositionState(styleToUse.position()); |
| 128 setHorizontalWritingMode(styleToUse.isHorizontalWritingMode()); | 322 setHorizontalWritingMode(styleToUse.isHorizontalWritingMode()); |
| 129 } | 323 } |
| 130 | 324 |
| 131 static LayoutSize accumulateInFlowPositionOffsets(const LayoutObject* child) | 325 static LayoutSize accumulateInFlowPositionOffsets(const LayoutObject* child) |
| 132 { | 326 { |
| 133 if (!child->isAnonymousBlock() || !child->isRelPositioned()) | 327 if (!child->isAnonymousBlock() || !child->isRelPositioned()) |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 continuationMap = new ContinuationMap; | 668 continuationMap = new ContinuationMap; |
| 475 continuationMap->set(this, continuation); | 669 continuationMap->set(this, continuation); |
| 476 } else { | 670 } else { |
| 477 if (continuationMap) | 671 if (continuationMap) |
| 478 continuationMap->remove(this); | 672 continuationMap->remove(this); |
| 479 } | 673 } |
| 480 } | 674 } |
| 481 | 675 |
| 482 void LayoutBoxModelObject::computeLayerHitTestRects(LayerHitTestRects& rects) co
nst | 676 void LayoutBoxModelObject::computeLayerHitTestRects(LayerHitTestRects& rects) co
nst |
| 483 { | 677 { |
| 484 LayoutLayerModelObject::computeLayerHitTestRects(rects); | 678 LayoutObject::computeLayerHitTestRects(rects); |
| 485 | 679 |
| 486 // If there is a continuation then we need to consult it here, since this is | 680 // If there is a continuation then we need to consult it here, since this is |
| 487 // the root of the tree walk and it wouldn't otherwise get picked up. | 681 // the root of the tree walk and it wouldn't otherwise get picked up. |
| 488 // Continuations should always be siblings in the tree, so any others should | 682 // Continuations should always be siblings in the tree, so any others should |
| 489 // get picked up already by the tree walk. | 683 // get picked up already by the tree walk. |
| 490 if (continuation()) | 684 if (continuation()) |
| 491 continuation()->computeLayerHitTestRects(rects); | 685 continuation()->computeLayerHitTestRects(rects); |
| 492 } | 686 } |
| 493 | 687 |
| 494 LayoutRect LayoutBoxModelObject::localCaretRectForEmptyElement(LayoutUnit width,
LayoutUnit textIndentOffset) | 688 LayoutRect LayoutBoxModelObject::localCaretRectForEmptyElement(LayoutUnit width,
LayoutUnit textIndentOffset) |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || styl
e()->preserves3D()); | 774 bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || styl
e()->preserves3D()); |
| 581 if (mode & UseTransforms && shouldUseTransformFromContainer(o)) { | 775 if (mode & UseTransforms && shouldUseTransformFromContainer(o)) { |
| 582 TransformationMatrix t; | 776 TransformationMatrix t; |
| 583 getTransformFromContainer(o, containerOffset, t); | 777 getTransformFromContainer(o, containerOffset, t); |
| 584 transformState.applyTransform(t, preserve3D ? TransformState::Accumulate
Transform : TransformState::FlattenTransform); | 778 transformState.applyTransform(t, preserve3D ? TransformState::Accumulate
Transform : TransformState::FlattenTransform); |
| 585 } else { | 779 } else { |
| 586 transformState.move(containerOffset.width(), containerOffset.height(), p
reserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransfo
rm); | 780 transformState.move(containerOffset.width(), containerOffset.height(), p
reserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransfo
rm); |
| 587 } | 781 } |
| 588 } | 782 } |
| 589 | 783 |
| 590 const LayoutObject* LayoutBoxModelObject::pushMappingToContainer(const LayoutLay
erModelObject* ancestorToStopAt, LayoutGeometryMap& geometryMap) const | 784 const LayoutObject* LayoutBoxModelObject::pushMappingToContainer(const LayoutBox
ModelObject* ancestorToStopAt, LayoutGeometryMap& geometryMap) const |
| 591 { | 785 { |
| 592 ASSERT(ancestorToStopAt != this); | 786 ASSERT(ancestorToStopAt != this); |
| 593 | 787 |
| 594 bool ancestorSkipped; | 788 bool ancestorSkipped; |
| 595 LayoutObject* container = this->container(ancestorToStopAt, &ancestorSkipped
); | 789 LayoutObject* container = this->container(ancestorToStopAt, &ancestorSkipped
); |
| 596 if (!container) | 790 if (!container) |
| 597 return 0; | 791 return 0; |
| 598 | 792 |
| 599 bool isInline = isRenderInline(); | 793 bool isInline = isRenderInline(); |
| 600 bool isFixedPos = !isInline && style()->position() == FixedPosition; | 794 bool isFixedPos = !isInline && style()->position() == FixedPosition; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent()); | 850 ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent()); |
| 657 for (LayoutObject* child = startChild; child && child != endChild; ) { | 851 for (LayoutObject* child = startChild; child && child != endChild; ) { |
| 658 // Save our next sibling as moveChildTo will clear it. | 852 // Save our next sibling as moveChildTo will clear it. |
| 659 LayoutObject* nextSibling = child->nextSibling(); | 853 LayoutObject* nextSibling = child->nextSibling(); |
| 660 moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert); | 854 moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert); |
| 661 child = nextSibling; | 855 child = nextSibling; |
| 662 } | 856 } |
| 663 } | 857 } |
| 664 | 858 |
| 665 } // namespace blink | 859 } // namespace blink |
| OLD | NEW |