Index: third_party/WebKit/Source/core/layout/LayoutBlock.cpp |
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp |
index ae0385bc3e257924da6719ff2fe449ecf36bc649..8e907b7b6e0e01bdf42e667f94ce7161892d94fd 100644 |
--- a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp |
+++ b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp |
@@ -98,15 +98,13 @@ static_assert(sizeof(LayoutBlock) == sizeof(SameSizeAsLayoutBlock), "LayoutBlock |
// the middle of recomputing the style so we can't rely on any of its |
// information), which is why it's easier to just update it for every layout. |
static TrackedDescendantsMap* gPositionedDescendantsMap = nullptr; |
+static TrackedContainerMap* gPositionedContainerMap = nullptr; |
// This map keeps track of the descendants whose 'height' is percentage associated |
// with a containing block. Like |gPositionedDescendantsMap|, it is also recomputed |
// for every layout (see the comment above about why). |
static TrackedDescendantsMap* gPercentHeightDescendantsMap = nullptr; |
-static TrackedContainerMap* gPositionedContainerMap = nullptr; |
-static TrackedContainerMap* gPercentHeightContainerMap = nullptr; |
- |
struct ScrollInfo { |
ScrollInfo() : autoHorizontalScrollBarChanged(false), autoVerticalScrollBarChanged(false) {} |
DoubleSize scrollOffset; |
@@ -135,34 +133,31 @@ LayoutBlock::LayoutBlock(ContainerNode* node) |
, m_hasOnlySelfCollapsingChildren(false) |
, m_descendantsWithFloatsMarkedForLayout(false) |
, m_needsRecalcLogicalWidthAfterLayoutChildren(false) |
+ , m_hasPositionedObjects(false) |
+ , m_hasPercentHeightDescendants(false) |
{ |
// LayoutBlockFlow calls setChildrenInline(true). |
// By default, subclasses do not have inline children. |
} |
-static void removeBlockFromDescendantAndContainerMaps(LayoutBlock* block, TrackedDescendantsMap*& descendantMap, TrackedContainerMap*& containerMap) |
+void LayoutBlock::removeFromGlobalMaps() |
{ |
- if (OwnPtr<TrackedLayoutBoxListHashSet> descendantSet = descendantMap->take(block)) { |
- for (auto& descendant : *descendantSet) { |
- TrackedContainerMap::iterator it = containerMap->find(descendant); |
- ASSERT(it != containerMap->end()); |
- if (it == containerMap->end()) |
- continue; |
- HashSet<LayoutBlock*>* containerSet = it->value.get(); |
- ASSERT(containerSet->contains(block)); |
- containerSet->remove(block); |
- if (containerSet->isEmpty()) |
- containerMap->remove(it); |
+ if (hasPositionedObjects()) { |
+ OwnPtr<TrackedLayoutBoxListHashSet> descendants = gPositionedDescendantsMap->take(this); |
+ ASSERT(!descendants->isEmpty()); |
+ for (LayoutBox* descendant : *descendants) { |
+ ASSERT(gPositionedContainerMap->get(descendant) == this); |
+ gPositionedContainerMap->remove(descendant); |
+ } |
+ } |
+ if (hasPercentHeightDescendants()) { |
+ OwnPtr<TrackedLayoutBoxListHashSet> descendants = gPercentHeightDescendantsMap->take(this); |
+ ASSERT(!descendants->isEmpty()); |
+ for (LayoutBox* descendant : *descendants) { |
+ ASSERT(descendant->percentHeightContainer() == this); |
+ descendant->setPercentHeightContainer(nullptr); |
} |
} |
-} |
- |
-void LayoutBlock::removeFromGlobalMaps() |
-{ |
- if (gPercentHeightDescendantsMap) |
- removeBlockFromDescendantAndContainerMaps(this, gPercentHeightDescendantsMap, gPercentHeightContainerMap); |
- if (gPositionedDescendantsMap) |
- removeBlockFromDescendantAndContainerMaps(this, gPositionedDescendantsMap, gPositionedContainerMap); |
} |
LayoutBlock::~LayoutBlock() |
@@ -1397,79 +1392,60 @@ void LayoutBlock::setSelectionState(SelectionState state) |
inlineBoxWrapper()->root().setHasSelectedChildren(state != SelectionNone); |
} |
-void LayoutBlock::insertIntoTrackedLayoutBoxMaps(LayoutBox* descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap) |
+TrackedLayoutBoxListHashSet* LayoutBlock::positionedObjectsInternal() const |
+{ |
+ return gPositionedDescendantsMap ? gPositionedDescendantsMap->get(this) : nullptr; |
+} |
+ |
+void LayoutBlock::insertPositionedObject(LayoutBox* o) |
{ |
- if (!descendantsMap) { |
- descendantsMap = new TrackedDescendantsMap; |
- containerMap = new TrackedContainerMap; |
+ ASSERT(!isAnonymousBlock()); |
+ ASSERT(o->containingBlock() == this); |
+ |
+ if (gPositionedContainerMap) { |
+ auto containerMapIt = gPositionedContainerMap->find(o); |
+ if (containerMapIt != gPositionedContainerMap->end()) { |
+ if (containerMapIt->value == this) { |
+ ASSERT(hasPositionedObjects() && positionedObjects()->contains(o)); |
+ return; |
+ } |
+ removePositionedObject(o); |
+ } |
+ } else { |
+ gPositionedContainerMap = new TrackedContainerMap; |
} |
+ gPositionedContainerMap->set(o, this); |
- TrackedLayoutBoxListHashSet* descendantSet = descendantsMap->get(this); |
+ if (!gPositionedDescendantsMap) |
+ gPositionedDescendantsMap = new TrackedDescendantsMap; |
+ TrackedLayoutBoxListHashSet* descendantSet = gPositionedDescendantsMap->get(this); |
if (!descendantSet) { |
descendantSet = new TrackedLayoutBoxListHashSet; |
- descendantsMap->set(this, adoptPtr(descendantSet)); |
- } |
- bool added = descendantSet->add(descendant).isNewEntry; |
- if (!added) { |
- ASSERT(containerMap->get(descendant)); |
- ASSERT(containerMap->get(descendant)->contains(this)); |
- return; |
+ gPositionedDescendantsMap->set(this, adoptPtr(descendantSet)); |
} |
+ descendantSet->add(o); |
- HashSet<LayoutBlock*>* containerSet = containerMap->get(descendant); |
- if (!containerSet) { |
- containerSet = new HashSet<LayoutBlock*>; |
- containerMap->set(descendant, adoptPtr(containerSet)); |
- } |
- ASSERT(!containerSet->contains(this)); |
- containerSet->add(this); |
+ m_hasPositionedObjects = true; |
} |
-void LayoutBlock::removeFromTrackedLayoutBoxMaps(LayoutBox* descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap) |
+void LayoutBlock::removePositionedObject(LayoutBox* o) |
{ |
- if (!descendantsMap) |
+ if (!gPositionedContainerMap) |
return; |
- OwnPtr<HashSet<LayoutBlock*>> containerSet = containerMap->take(descendant); |
- if (!containerSet) |
+ LayoutBlock* container = gPositionedContainerMap->take(o); |
+ if (!container) |
return; |
- for (auto* container : *containerSet) { |
- // FIXME: Disabling this assert temporarily until we fix the layout |
- // bugs associated with positioned objects not properly cleared from |
- // their ancestor chain before being moved. See webkit bug 93766. |
- // ASSERT(descendant->isDescendantOf(container)); |
- |
- TrackedDescendantsMap::iterator descendantsMapIterator = descendantsMap->find(container); |
- ASSERT(descendantsMapIterator != descendantsMap->end()); |
- if (descendantsMapIterator == descendantsMap->end()) |
- continue; |
- TrackedLayoutBoxListHashSet* descendantSet = descendantsMapIterator->value.get(); |
- ASSERT(descendantSet->contains(descendant)); |
- descendantSet->remove(descendant); |
- if (descendantSet->isEmpty()) |
- descendantsMap->remove(descendantsMapIterator); |
+ TrackedLayoutBoxListHashSet* positionedDescendants = gPositionedDescendantsMap->get(container); |
+ ASSERT(positionedDescendants && positionedDescendants->contains(o)); |
+ positionedDescendants->remove(o); |
+ if (positionedDescendants->isEmpty()) { |
+ gPositionedDescendantsMap->remove(container); |
+ container->m_hasPositionedObjects = false; |
} |
} |
-TrackedLayoutBoxListHashSet* LayoutBlock::positionedObjects() const |
-{ |
- if (gPositionedDescendantsMap) |
- return gPositionedDescendantsMap->get(this); |
- return nullptr; |
-} |
- |
-void LayoutBlock::insertPositionedObject(LayoutBox* o) |
-{ |
- ASSERT(!isAnonymousBlock()); |
- insertIntoTrackedLayoutBoxMaps(o, gPositionedDescendantsMap, gPositionedContainerMap); |
-} |
- |
-void LayoutBlock::removePositionedObject(LayoutBox* o) |
-{ |
- removeFromTrackedLayoutBoxMaps(o, gPositionedDescendantsMap, gPositionedContainerMap); |
-} |
- |
void LayoutBlock::removePositionedObjects(LayoutBlock* o, ContainingBlockState containingBlockState) |
{ |
TrackedLayoutBoxListHashSet* positionedDescendants = positionedObjects(); |
@@ -1506,45 +1482,60 @@ void LayoutBlock::removePositionedObjects(LayoutBlock* o, ContainingBlockState c |
} |
} |
- for (unsigned i = 0; i < deadObjects.size(); i++) |
- removePositionedObject(deadObjects.at(i)); |
+ for (auto object : deadObjects) { |
+ ASSERT(gPositionedContainerMap->get(object) == this); |
+ positionedDescendants->remove(object); |
+ gPositionedContainerMap->remove(object); |
+ } |
+ if (positionedDescendants->isEmpty()) { |
+ gPositionedDescendantsMap->remove(this); |
+ m_hasPositionedObjects = false; |
+ } |
} |
void LayoutBlock::addPercentHeightDescendant(LayoutBox* descendant) |
{ |
- insertIntoTrackedLayoutBoxMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap); |
-} |
+ if (descendant->percentHeightContainer()) { |
+ if (descendant->percentHeightContainer() == this) { |
+ ASSERT(hasPercentHeightDescendant(descendant)); |
+ return; |
+ } |
+ descendant->removeFromPercentHeightContainer(); |
+ } |
+ descendant->setPercentHeightContainer(this); |
-void LayoutBlock::removePercentHeightDescendant(LayoutBox* descendant) |
-{ |
- removeFromTrackedLayoutBoxMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap); |
-} |
+ if (!gPercentHeightDescendantsMap) |
+ gPercentHeightDescendantsMap = new TrackedDescendantsMap; |
+ TrackedLayoutBoxListHashSet* descendantSet = gPercentHeightDescendantsMap->get(this); |
+ if (!descendantSet) { |
+ descendantSet = new TrackedLayoutBoxListHashSet; |
+ gPercentHeightDescendantsMap->set(this, adoptPtr(descendantSet)); |
+ } |
+ descendantSet->add(descendant); |
-TrackedLayoutBoxListHashSet* LayoutBlock::percentHeightDescendants() const |
-{ |
- return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this) : 0; |
+ m_hasPercentHeightDescendants = true; |
} |
-bool LayoutBlock::hasPercentHeightContainerMap() |
+void LayoutBlock::removePercentHeightDescendant(LayoutBox* descendant) |
{ |
- return gPercentHeightContainerMap; |
+ if (TrackedLayoutBoxListHashSet* descendants = percentHeightDescendants()) { |
+ descendants->remove(descendant); |
+ descendant->setPercentHeightContainer(nullptr); |
+ if (descendants->isEmpty()) { |
+ gPercentHeightDescendantsMap->remove(this); |
+ m_hasPercentHeightDescendants = false; |
+ } |
+ } |
} |
-bool LayoutBlock::hasPercentHeightDescendant(LayoutBox* descendant) |
+TrackedLayoutBoxListHashSet* LayoutBlock::percentHeightDescendantsInternal() const |
{ |
- // We don't null check gPercentHeightContainerMap since the caller |
- // already ensures this and we need to call this function on every |
- // descendant in clearPercentHeightDescendantsFrom(). |
- ASSERT(gPercentHeightContainerMap); |
- return gPercentHeightContainerMap->contains(descendant); |
+ return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this) : nullptr; |
} |
void LayoutBlock::dirtyForLayoutFromPercentageHeightDescendants(SubtreeLayoutScope& layoutScope) |
{ |
- if (!gPercentHeightDescendantsMap) |
- return; |
- |
- TrackedLayoutBoxListHashSet* descendants = gPercentHeightDescendantsMap->get(this); |
+ TrackedLayoutBoxListHashSet* descendants = percentHeightDescendants(); |
if (!descendants) |
return; |
@@ -1562,35 +1553,6 @@ void LayoutBlock::dirtyForLayoutFromPercentageHeightDescendants(SubtreeLayoutSco |
} |
} |
-void LayoutBlock::removePercentHeightDescendantIfNeeded(LayoutBox* descendant) |
-{ |
- // We query the map directly, rather than looking at style's |
- // logicalHeight()/logicalMinHeight()/logicalMaxHeight() since those |
- // can change with writing mode/directional changes. |
- if (!hasPercentHeightContainerMap()) |
- return; |
- |
- if (!hasPercentHeightDescendant(descendant)) |
- return; |
- |
- removePercentHeightDescendant(descendant); |
-} |
- |
-void LayoutBlock::clearPercentHeightDescendantsFrom(LayoutBox* parent) |
-{ |
- ASSERT(gPercentHeightContainerMap); |
- for (LayoutObject* curr = parent->slowFirstChild(); curr; curr = curr->nextInPreOrder(parent)) { |
- if (!curr->isBox()) |
- continue; |
- |
- LayoutBox* box = toLayoutBox(curr); |
- if (!hasPercentHeightDescendant(box)) |
- continue; |
- |
- removePercentHeightDescendant(box); |
- } |
-} |
- |
LayoutUnit LayoutBlock::textIndentOffset() const |
{ |
LayoutUnit cw = 0; |