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 |