| 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;
|
|
|