summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering')
-rw-r--r--Source/WebCore/rendering/AutoTableLayout.cpp32
-rw-r--r--Source/WebCore/rendering/AutoTableLayout.h8
-rw-r--r--Source/WebCore/rendering/InlineIterator.h2
-rw-r--r--Source/WebCore/rendering/LogicalSelectionOffsetCaches.h11
-rw-r--r--Source/WebCore/rendering/RenderBlock.cpp373
-rw-r--r--Source/WebCore/rendering/RenderBlock.h14
-rw-r--r--Source/WebCore/rendering/RenderBlockFlow.cpp26
-rw-r--r--Source/WebCore/rendering/RenderBlockFlow.h4
-rw-r--r--Source/WebCore/rendering/RenderBlockLineLayout.cpp4
-rw-r--r--Source/WebCore/rendering/RenderBox.cpp46
-rw-r--r--Source/WebCore/rendering/RenderBox.h2
-rw-r--r--Source/WebCore/rendering/RenderFlexibleBox.cpp112
-rw-r--r--Source/WebCore/rendering/RenderFlexibleBox.h19
-rw-r--r--Source/WebCore/rendering/RenderHTMLCanvas.cpp13
-rw-r--r--Source/WebCore/rendering/RenderImage.cpp30
-rw-r--r--Source/WebCore/rendering/RenderInline.cpp5
-rw-r--r--Source/WebCore/rendering/RenderLayer.cpp33
-rw-r--r--Source/WebCore/rendering/RenderObject.cpp3
-rw-r--r--Source/WebCore/rendering/RenderReplaced.cpp38
-rw-r--r--Source/WebCore/rendering/RenderReplaced.h1
-rw-r--r--Source/WebCore/rendering/RenderTable.cpp7
-rw-r--r--Source/WebCore/rendering/RenderTableCell.cpp16
-rw-r--r--Source/WebCore/rendering/RenderTableCell.h2
-rw-r--r--Source/WebCore/rendering/RenderTableSection.cpp12
-rw-r--r--Source/WebCore/rendering/TableLayout.h2
-rw-r--r--Source/WebCore/rendering/line/BreakingContext.h6
-rw-r--r--Source/WebCore/rendering/line/LineWidth.cpp13
-rw-r--r--Source/WebCore/rendering/line/LineWidth.h28
-rw-r--r--Source/WebCore/rendering/style/RenderStyle.cpp1
-rw-r--r--Source/WebCore/rendering/style/RenderStyle.h8
-rw-r--r--Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp3
-rw-r--r--Source/WebCore/rendering/style/StyleRareNonInheritedData.h2
-rw-r--r--Source/WebCore/rendering/style/StyleScrollSnapPoints.cpp4
-rw-r--r--Source/WebCore/rendering/style/WillChangeData.cpp26
-rw-r--r--Source/WebCore/rendering/style/WillChangeData.h2
35 files changed, 566 insertions, 342 deletions
diff --git a/Source/WebCore/rendering/AutoTableLayout.cpp b/Source/WebCore/rendering/AutoTableLayout.cpp
index 3b93a5118..27330f7b0 100644
--- a/Source/WebCore/rendering/AutoTableLayout.cpp
+++ b/Source/WebCore/rendering/AutoTableLayout.cpp
@@ -181,9 +181,27 @@ void AutoTableLayout::fullRecalc()
recalcColumn(i);
}
+static bool shouldScaleColumnsForParent(const RenderTable& table)
+{
+ RenderBlock* containingBlock = table.containingBlock();
+ while (containingBlock && !is<RenderView>(containingBlock)) {
+ // It doesn't matter if our table is auto or fixed: auto means we don't
+ // scale. Fixed doesn't care if we do or not because it doesn't depend
+ // on the cell contents' preferred widths.
+ if (is<RenderTableCell>(containingBlock))
+ return false;
+ containingBlock = containingBlock->containingBlock();
+ }
+ return true;
+}
+
// FIXME: This needs to be adapted for vertical writing modes.
-static bool shouldScaleColumns(RenderTable* table)
+static bool shouldScaleColumnsForSelf(RenderTable* table)
{
+ // Normally, scale all columns to satisfy this from CSS2.2:
+ // "A percentage value for a column width is relative to the table width.
+ // If the table has 'width: auto', a percentage represents a constraint on the column's width"
+
// A special case. If this table is not fixed width and contained inside
// a cell, then don't bloat the maxwidth by examining percentage growth.
bool scale = true;
@@ -220,7 +238,7 @@ void AutoTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, Layout
maxWidth = 0;
float maxPercent = 0;
float maxNonPercent = 0;
- bool scaleColumns = shouldScaleColumns(m_table);
+ bool scaleColumnsForSelf = shouldScaleColumnsForSelf(m_table);
// We substitute 0 percent by (epsilon / percentScaleFactor) percent in two places below to avoid division by zero.
// FIXME: Handle the 0% cases properly.
@@ -230,7 +248,7 @@ void AutoTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, Layout
for (size_t i = 0; i < m_layoutStruct.size(); ++i) {
minWidth += m_layoutStruct[i].effectiveMinLogicalWidth;
maxWidth += m_layoutStruct[i].effectiveMaxLogicalWidth;
- if (scaleColumns) {
+ if (scaleColumnsForSelf) {
if (m_layoutStruct[i].effectiveLogicalWidth.isPercent()) {
float percent = std::min(m_layoutStruct[i].effectiveLogicalWidth.percent(), remainingPercent);
float logicalWidth = m_layoutStruct[i].effectiveMaxLogicalWidth * 100 / std::max(percent, epsilon);
@@ -241,10 +259,12 @@ void AutoTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, Layout
}
}
- if (scaleColumns) {
+ if (scaleColumnsForSelf) {
maxNonPercent = maxNonPercent * 100 / std::max(remainingPercent, epsilon);
- maxWidth = std::max(maxWidth, LayoutUnit(std::min<float>(maxNonPercent, tableMaxWidth)));
- maxWidth = std::max(maxWidth, LayoutUnit(std::min<float>(maxPercent, tableMaxWidth)));
+ m_scaledWidthFromPercentColumns = LayoutUnit(std::min<float>(maxNonPercent, tableMaxWidth));
+ m_scaledWidthFromPercentColumns = std::max(m_scaledWidthFromPercentColumns, LayoutUnit(std::min<float>(maxPercent, tableMaxWidth)));
+ if (m_scaledWidthFromPercentColumns > maxWidth && shouldScaleColumnsForParent(*m_table))
+ maxWidth = m_scaledWidthFromPercentColumns;
}
maxWidth = std::max(maxWidth, LayoutUnit(spanMaxLogicalWidth));
diff --git a/Source/WebCore/rendering/AutoTableLayout.h b/Source/WebCore/rendering/AutoTableLayout.h
index ce108ad90..f73f62cf8 100644
--- a/Source/WebCore/rendering/AutoTableLayout.h
+++ b/Source/WebCore/rendering/AutoTableLayout.h
@@ -36,9 +36,10 @@ public:
explicit AutoTableLayout(RenderTable*);
virtual ~AutoTableLayout();
- virtual void computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) override;
- virtual void applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const override;
- virtual void layout() override;
+ void computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) override;
+ LayoutUnit scaledWidthFromPercentColumns() const override { return m_scaledWidthFromPercentColumns; }
+ void applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const override;
+ void layout() override;
private:
void fullRecalc();
@@ -63,6 +64,7 @@ private:
Vector<RenderTableCell*, 4> m_spanCells;
bool m_hasPercent : 1;
mutable bool m_effectiveLogicalWidthDirty : 1;
+ LayoutUnit m_scaledWidthFromPercentColumns;
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/InlineIterator.h b/Source/WebCore/rendering/InlineIterator.h
index 0c8fb3827..4dc5b4f21 100644
--- a/Source/WebCore/rendering/InlineIterator.h
+++ b/Source/WebCore/rendering/InlineIterator.h
@@ -492,7 +492,7 @@ static inline unsigned numberOfIsolateAncestors(const InlineIterator& iter)
// of BidiResolver which knows nothing about RenderObjects.
static inline void addPlaceholderRunForIsolatedInline(InlineBidiResolver& resolver, RenderObject& obj, unsigned pos, RenderElement& root)
{
- BidiRun* isolatedRun = new BidiRun(pos, 0, obj, resolver.context(), resolver.dir());
+ BidiRun* isolatedRun = new BidiRun(pos, pos, obj, resolver.context(), resolver.dir());
resolver.runs().addRun(isolatedRun);
// FIXME: isolatedRuns() could be a hash of object->run and then we could cheaply
// ASSERT here that we didn't create multiple objects for the same inline.
diff --git a/Source/WebCore/rendering/LogicalSelectionOffsetCaches.h b/Source/WebCore/rendering/LogicalSelectionOffsetCaches.h
index aefe10738..cb48a3642 100644
--- a/Source/WebCore/rendering/LogicalSelectionOffsetCaches.h
+++ b/Source/WebCore/rendering/LogicalSelectionOffsetCaches.h
@@ -38,7 +38,8 @@ public:
void setBlock(RenderBlock* block, const LogicalSelectionOffsetCaches* cache, bool parentCacheHasFloatsOrFlowThreads = false)
{
m_block = block;
- m_hasFloatsOrFlowThreads = parentCacheHasFloatsOrFlowThreads || m_hasFloatsOrFlowThreads || m_block->containsFloats() || m_block->flowThreadContainingBlock();
+ bool blockHasFloatsOrFlowThreads = m_block ? (m_block->containsFloats() || m_block->flowThreadContainingBlock()) : false;
+ m_hasFloatsOrFlowThreads = parentCacheHasFloatsOrFlowThreads || m_hasFloatsOrFlowThreads || blockHasFloatsOrFlowThreads;
m_cache = cache;
m_cachedLogicalLeftSelectionOffset = false;
m_cachedLogicalRightSelectionOffset = false;
@@ -49,9 +50,9 @@ public:
ASSERT(m_cache);
if (m_hasFloatsOrFlowThreads || !m_cachedLogicalLeftSelectionOffset) {
m_cachedLogicalLeftSelectionOffset = true;
- m_logicalLeftSelectionOffset = m_block->logicalLeftSelectionOffset(rootBlock, position, *m_cache);
+ m_logicalLeftSelectionOffset = m_block ? m_block->logicalLeftSelectionOffset(rootBlock, position, *m_cache) : LayoutUnit::fromPixel(0);
} else
- ASSERT(m_logicalLeftSelectionOffset == m_block->logicalLeftSelectionOffset(rootBlock, position, *m_cache));
+ ASSERT(m_logicalLeftSelectionOffset == (m_block ? m_block->logicalLeftSelectionOffset(rootBlock, position, *m_cache) : LayoutUnit::fromPixel(0)));
return m_logicalLeftSelectionOffset;
}
@@ -60,9 +61,9 @@ public:
ASSERT(m_cache);
if (m_hasFloatsOrFlowThreads || !m_cachedLogicalRightSelectionOffset) {
m_cachedLogicalRightSelectionOffset = true;
- m_logicalRightSelectionOffset = m_block->logicalRightSelectionOffset(rootBlock, position, *m_cache);
+ m_logicalRightSelectionOffset = m_block ? m_block->logicalRightSelectionOffset(rootBlock, position, *m_cache) : LayoutUnit::fromPixel(0);
} else
- ASSERT(m_logicalRightSelectionOffset == m_block->logicalRightSelectionOffset(rootBlock, position, *m_cache));
+ ASSERT(m_logicalRightSelectionOffset == (m_block ? m_block->logicalRightSelectionOffset(rootBlock, position, *m_cache) : LayoutUnit::fromPixel(0)));
return m_logicalRightSelectionOffset;
}
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp
index 3ffdef97d..bf1a78a7f 100644
--- a/Source/WebCore/rendering/RenderBlock.cpp
+++ b/Source/WebCore/rendering/RenderBlock.cpp
@@ -92,11 +92,136 @@ struct SameSizeAsRenderBlock : public RenderBox {
COMPILE_ASSERT(sizeof(RenderBlock) == sizeof(SameSizeAsRenderBlock), RenderBlock_should_stay_small);
-static TrackedDescendantsMap* gPositionedDescendantsMap;
-static TrackedDescendantsMap* gPercentHeightDescendantsMap;
+typedef HashMap<const RenderBlock*, std::unique_ptr<TrackedRendererListHashSet>> TrackedDescendantsMap;
+typedef HashMap<const RenderBox*, std::unique_ptr<HashSet<const RenderBlock*>>> TrackedContainerMap;
-static TrackedContainerMap* gPositionedContainerMap;
-static TrackedContainerMap* gPercentHeightContainerMap;
+static TrackedDescendantsMap* percentHeightDescendantsMap;
+static TrackedContainerMap* percentHeightContainerMap;
+
+static void insertIntoTrackedRendererMaps(const RenderBlock& container, RenderBox& descendant)
+{
+ if (!percentHeightDescendantsMap) {
+ percentHeightDescendantsMap = new TrackedDescendantsMap;
+ percentHeightContainerMap = new TrackedContainerMap;
+ }
+
+ auto& descendantSet = percentHeightDescendantsMap->ensure(&container, [] {
+ return std::make_unique<TrackedRendererListHashSet>();
+ }).iterator->value;
+
+ bool added = descendantSet->add(&descendant).isNewEntry;
+ if (!added) {
+ ASSERT(percentHeightContainerMap->get(&descendant));
+ ASSERT(percentHeightContainerMap->get(&descendant)->contains(&container));
+ return;
+ }
+
+ auto& containerSet = percentHeightContainerMap->ensure(&descendant, [] {
+ return std::make_unique<HashSet<const RenderBlock*>>();
+ }).iterator->value;
+
+ ASSERT(!containerSet->contains(&container));
+ containerSet->add(&container);
+}
+
+static void removeFromTrackedRendererMaps(RenderBox& descendant)
+{
+ if (!percentHeightDescendantsMap)
+ return;
+
+ std::unique_ptr<HashSet<const RenderBlock*>> containerSet = percentHeightContainerMap->take(&descendant);
+ if (!containerSet)
+ 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));
+ auto descendantsMapIterator = percentHeightDescendantsMap->find(container);
+ ASSERT(descendantsMapIterator != percentHeightDescendantsMap->end());
+ if (descendantsMapIterator == percentHeightDescendantsMap->end())
+ continue;
+ auto& descendantSet = descendantsMapIterator->value;
+ ASSERT(descendantSet->contains(&descendant));
+ descendantSet->remove(&descendant);
+ if (descendantSet->isEmpty())
+ percentHeightDescendantsMap->remove(descendantsMapIterator);
+ }
+}
+
+class PositionedDescendantsMap {
+public:
+ enum class MoveDescendantToEnd { No, Yes };
+ void addDescendant(const RenderBlock& containingBlock, RenderBox& positionedDescendant, MoveDescendantToEnd moveDescendantToEnd)
+ {
+ // Protect against double insert where a descendant would end up with multiple containing blocks.
+ auto* previousContainingBlock = m_containerMap.get(&positionedDescendant);
+ if (previousContainingBlock && previousContainingBlock != &containingBlock) {
+ if (auto* descendants = m_descendantsMap.get(previousContainingBlock))
+ descendants->remove(&positionedDescendant);
+ }
+
+ auto& descendants = m_descendantsMap.ensure(&containingBlock, [] {
+ return std::make_unique<TrackedRendererListHashSet>();
+ }).iterator->value;
+
+ bool isNewEntry = moveDescendantToEnd == MoveDescendantToEnd::Yes ? descendants->appendOrMoveToLast(&positionedDescendant).isNewEntry
+ : descendants->add(&positionedDescendant).isNewEntry;
+ if (!isNewEntry) {
+ ASSERT(m_containerMap.contains(&positionedDescendant));
+ return;
+ }
+ m_containerMap.set(&positionedDescendant, &containingBlock);
+ }
+
+ void removeDescendant(const RenderBox& positionedDescendant)
+ {
+ auto* containingBlock = m_containerMap.take(&positionedDescendant);
+ if (!containingBlock)
+ return;
+
+ auto descendantsIterator = m_descendantsMap.find(containingBlock);
+ ASSERT(descendantsIterator != m_descendantsMap.end());
+ if (descendantsIterator == m_descendantsMap.end())
+ return;
+
+ auto& descendants = descendantsIterator->value;
+ ASSERT(descendants->contains(const_cast<RenderBox*>(&positionedDescendant)));
+
+ descendants->remove(const_cast<RenderBox*>(&positionedDescendant));
+ if (descendants->isEmpty())
+ m_descendantsMap.remove(descendantsIterator);
+ }
+
+ void removeContainingBlock(const RenderBlock& containingBlock)
+ {
+ auto descendants = m_descendantsMap.take(&containingBlock);
+ if (!descendants)
+ return;
+
+ for (auto* renderer : *descendants)
+ m_containerMap.remove(renderer);
+ }
+
+ TrackedRendererListHashSet* positionedRenderers(const RenderBlock& containingBlock) const
+ {
+ return m_descendantsMap.get(&containingBlock);
+ }
+
+private:
+ using DescendantsMap = HashMap<const RenderBlock*, std::unique_ptr<TrackedRendererListHashSet>>;
+ using ContainerMap = HashMap<const RenderBox*, const RenderBlock*>;
+
+ DescendantsMap m_descendantsMap;
+ ContainerMap m_containerMap;
+};
+
+static PositionedDescendantsMap& positionedDescendantsMap()
+{
+ static NeverDestroyed<PositionedDescendantsMap> mapForPositionedDescendants;
+ return mapForPositionedDescendants;
+}
typedef HashMap<RenderBlock*, std::unique_ptr<ListHashSet<RenderInline*>>> ContinuationOutlineTableMap;
@@ -192,21 +317,24 @@ RenderBlock::RenderBlock(Document& document, Ref<RenderStyle>&& style, BaseTypeF
{
}
-static void removeBlockFromDescendantAndContainerMaps(RenderBlock* block, TrackedDescendantsMap*& descendantMap, TrackedContainerMap*& containerMap)
+static void removeBlockFromPercentageDescendantAndContainerMaps(RenderBlock* block)
{
- if (std::unique_ptr<TrackedRendererListHashSet> descendantSet = descendantMap->take(block)) {
- TrackedRendererListHashSet::iterator end = descendantSet->end();
- for (TrackedRendererListHashSet::iterator descendant = descendantSet->begin(); descendant != end; ++descendant) {
- TrackedContainerMap::iterator it = containerMap->find(*descendant);
- ASSERT(it != containerMap->end());
- if (it == containerMap->end())
- continue;
- HashSet<RenderBlock*>* containerSet = it->value.get();
- ASSERT(containerSet->contains(block));
- containerSet->remove(block);
- if (containerSet->isEmpty())
- containerMap->remove(it);
- }
+ if (!percentHeightDescendantsMap)
+ return;
+ std::unique_ptr<TrackedRendererListHashSet> descendantSet = percentHeightDescendantsMap->take(block);
+ if (!descendantSet)
+ return;
+
+ for (auto* descendant : *descendantSet) {
+ auto it = percentHeightContainerMap->find(descendant);
+ ASSERT(it != percentHeightContainerMap->end());
+ if (it == percentHeightContainerMap->end())
+ continue;
+ auto* containerSet = it->value.get();
+ ASSERT(containerSet->contains(block));
+ containerSet->remove(block);
+ if (containerSet->isEmpty())
+ percentHeightContainerMap->remove(it);
}
}
@@ -216,10 +344,8 @@ RenderBlock::~RenderBlock()
if (gRareDataMap)
gRareDataMap->remove(this);
- if (gPercentHeightDescendantsMap)
- removeBlockFromDescendantAndContainerMaps(this, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
- if (gPositionedDescendantsMap)
- removeBlockFromDescendantAndContainerMaps(this, gPositionedDescendantsMap, gPositionedContainerMap);
+ removeBlockFromPercentageDescendantAndContainerMaps(this);
+ positionedDescendantsMap().removeContainingBlock(*this);
}
void RenderBlock::willBeDestroyed()
@@ -244,14 +370,20 @@ void RenderBlock::removePositionedObjectsIfNeeded(const RenderStyle& oldStyle, c
if (oldStyle.position() == newStyle.position() && hadTransform == willHaveTransform)
return;
- // We are no longer a containing block.
+ // We are no longer the containing block for fixed descendants.
+ if (hadTransform && !willHaveTransform) {
+ // Our positioned descendants will be inserted into a new containing block's positioned objects list during the next layout.
+ removePositionedObjects(nullptr, NewContainingBlock);
+ return;
+ }
+
+ // We are no longer the containing block for absolute positioned descendants.
if (newStyle.position() == StaticPosition && !willHaveTransform) {
- // Clear our positioned objects list. Our absolutely positioned descendants will be
- // inserted into our containing block's positioned objects list during layout.
+ // Our positioned descendants will be inserted into a new containing block's positioned objects list during the next layout.
removePositionedObjects(nullptr, NewContainingBlock);
return;
}
-
+
// We are a new containing block.
if (oldStyle.position() == StaticPosition && !hadTransform) {
// Remove our absolutely positioned descendants from their current containing block.
@@ -1157,10 +1289,10 @@ void RenderBlock::updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, R
void RenderBlock::dirtyForLayoutFromPercentageHeightDescendants()
{
- if (!gPercentHeightDescendantsMap)
+ if (!percentHeightDescendantsMap)
return;
- TrackedRendererListHashSet* descendants = gPercentHeightDescendantsMap->get(this);
+ TrackedRendererListHashSet* descendants = percentHeightDescendantsMap->get(this);
if (!descendants)
return;
@@ -1264,34 +1396,33 @@ bool RenderBlock::simplifiedLayout()
return true;
}
-void RenderBlock::markFixedPositionObjectForLayoutIfNeeded(RenderObject& child)
+void RenderBlock::markFixedPositionObjectForLayoutIfNeeded(RenderBox& positionedChild)
{
- if (child.style().position() != FixedPosition)
+ if (positionedChild.style().position() != FixedPosition)
return;
- bool hasStaticBlockPosition = child.style().hasStaticBlockPosition(isHorizontalWritingMode());
- bool hasStaticInlinePosition = child.style().hasStaticInlinePosition(isHorizontalWritingMode());
+ bool hasStaticBlockPosition = positionedChild.style().hasStaticBlockPosition(isHorizontalWritingMode());
+ bool hasStaticInlinePosition = positionedChild.style().hasStaticInlinePosition(isHorizontalWritingMode());
if (!hasStaticBlockPosition && !hasStaticInlinePosition)
return;
- auto o = child.parent();
- while (o && !is<RenderView>(*o) && o->style().position() != AbsolutePosition)
- o = o->parent();
- if (o->style().position() != AbsolutePosition)
+ auto* parent = positionedChild.parent();
+ while (parent && !is<RenderView>(*parent) && parent->style().position() != AbsolutePosition)
+ parent = parent->parent();
+ if (!parent || parent->style().position() != AbsolutePosition)
return;
- auto& box = downcast<RenderBox>(child);
if (hasStaticInlinePosition) {
LogicalExtentComputedValues computedValues;
- box.computeLogicalWidthInRegion(computedValues);
+ positionedChild.computeLogicalWidthInRegion(computedValues);
LayoutUnit newLeft = computedValues.m_position;
- if (newLeft != box.logicalLeft())
- box.setChildNeedsLayout(MarkOnlyThis);
+ if (newLeft != positionedChild.logicalLeft())
+ positionedChild.setChildNeedsLayout(MarkOnlyThis);
} else if (hasStaticBlockPosition) {
- LayoutUnit oldTop = box.logicalTop();
- box.updateLogicalHeight();
- if (box.logicalTop() != oldTop)
- box.setChildNeedsLayout(MarkOnlyThis);
+ LayoutUnit oldTop = positionedChild.logicalTop();
+ positionedChild.updateLogicalHeight();
+ if (positionedChild.logicalTop() != oldTop)
+ positionedChild.setChildNeedsLayout(MarkOnlyThis);
}
}
@@ -2049,6 +2180,8 @@ LayoutUnit RenderBlock::logicalLeftSelectionOffset(RenderBlock& rootBlock, Layou
ASSERT(currentCache);
auto info = currentCache->containingBlockInfo(*cb);
cb = info.block();
+ if (!cb)
+ break;
currentCache = info.cache();
}
return logicalLeft;
@@ -2071,6 +2204,8 @@ LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock& rootBlock, Layo
ASSERT(currentCache);
auto info = currentCache->containingBlockInfo(*cb);
cb = info.block();
+ if (!cb)
+ break;
currentCache = info.cache();
}
return logicalRight;
@@ -2108,148 +2243,79 @@ RenderBlock* RenderBlock::blockBeforeWithinSelectionRoot(LayoutSize& offset) con
return beforeBlock;
}
-void RenderBlock::insertIntoTrackedRendererMaps(RenderBox& descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap, bool forceNewEntry)
-{
- if (!descendantsMap) {
- descendantsMap = new TrackedDescendantsMap;
- containerMap = new TrackedContainerMap;
- }
-
- TrackedRendererListHashSet* descendantSet = descendantsMap->get(this);
- if (!descendantSet) {
- descendantSet = new TrackedRendererListHashSet;
- descendantsMap->set(this, std::unique_ptr<TrackedRendererListHashSet>(descendantSet));
- }
-
- if (forceNewEntry) {
- descendantSet->remove(&descendant);
- containerMap->remove(&descendant);
- }
-
- bool added = descendantSet->add(&descendant).isNewEntry;
- if (!added) {
- ASSERT(containerMap->get(&descendant));
- ASSERT(containerMap->get(&descendant)->contains(this));
- return;
- }
-
- HashSet<RenderBlock*>* containerSet = containerMap->get(&descendant);
- if (!containerSet) {
- containerSet = new HashSet<RenderBlock*>;
- containerMap->set(&descendant, std::unique_ptr<HashSet<RenderBlock*>>(containerSet));
- }
- ASSERT(!containerSet->contains(this));
- containerSet->add(this);
-}
-
-void RenderBlock::removeFromTrackedRendererMaps(RenderBox& descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap)
-{
- if (!descendantsMap)
- return;
-
- std::unique_ptr<HashSet<RenderBlock*>> containerSet = containerMap->take(&descendant);
- if (!containerSet)
- return;
-
- for (auto it = containerSet->begin(), end = containerSet->end(); it != end; ++it) {
- RenderBlock* container = *it;
-
- // 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;
- TrackedRendererListHashSet* descendantSet = descendantsMapIterator->value.get();
- ASSERT(descendantSet->contains(&descendant));
- descendantSet->remove(&descendant);
- if (descendantSet->isEmpty())
- descendantsMap->remove(descendantsMapIterator);
- }
-}
-
TrackedRendererListHashSet* RenderBlock::positionedObjects() const
{
- if (gPositionedDescendantsMap)
- return gPositionedDescendantsMap->get(this);
- return nullptr;
+ return positionedDescendantsMap().positionedRenderers(*this);
}
-void RenderBlock::insertPositionedObject(RenderBox& o)
+void RenderBlock::insertPositionedObject(RenderBox& positioned)
{
ASSERT(!isAnonymousBlock());
- if (o.isRenderFlowThread())
+ if (positioned.isRenderFlowThread())
return;
-
- insertIntoTrackedRendererMaps(o, gPositionedDescendantsMap, gPositionedContainerMap, isRenderView());
+
+ positionedDescendantsMap().addDescendant(*this, positioned, isRenderView() ? PositionedDescendantsMap::MoveDescendantToEnd::Yes
+ : PositionedDescendantsMap::MoveDescendantToEnd::No);
}
-void RenderBlock::removePositionedObject(RenderBox& o)
+void RenderBlock::removePositionedObject(const RenderBox& rendererToRemove)
{
- removeFromTrackedRendererMaps(o, gPositionedDescendantsMap, gPositionedContainerMap);
+ positionedDescendantsMap().removeDescendant(rendererToRemove);
}
-void RenderBlock::removePositionedObjects(RenderBlock* o, ContainingBlockState containingBlockState)
+void RenderBlock::removePositionedObjects(const RenderBlock* newContainingBlockCandidate, ContainingBlockState containingBlockState)
{
- TrackedRendererListHashSet* positionedDescendants = positionedObjects();
+ auto* positionedDescendants = positionedObjects();
if (!positionedDescendants)
return;
- Vector<RenderBox*, 16> deadObjects;
-
- for (auto it = positionedDescendants->begin(), end = positionedDescendants->end(); it != end; ++it) {
- RenderBox* r = *it;
- if (!o || r->isDescendantOf(o)) {
- if (containingBlockState == NewContainingBlock)
- r->setChildNeedsLayout(MarkOnlyThis);
-
- // It is parent blocks job to add positioned child to positioned objects list of its containing block
- // Parent layout needs to be invalidated to ensure this happens.
- RenderElement* p = r->parent();
- while (p && !p->isRenderBlock())
- p = p->parent();
- if (p)
- p->setChildNeedsLayout();
-
- deadObjects.append(r);
- }
+ Vector<RenderBox*, 16> renderersToRemove;
+ for (auto* renderer : *positionedDescendants) {
+ if (newContainingBlockCandidate && !renderer->isDescendantOf(newContainingBlockCandidate))
+ continue;
+ renderersToRemove.append(renderer);
+ if (containingBlockState == NewContainingBlock)
+ renderer->setChildNeedsLayout(MarkOnlyThis);
+ // It is the parent block's job to add positioned children to positioned objects list of its containing block.
+ // Dirty the parent to ensure this happens.
+ auto* parent = renderer->parent();
+ while (parent && !parent->isRenderBlock())
+ parent = parent->parent();
+ if (parent)
+ parent->setChildNeedsLayout();
}
-
- for (unsigned i = 0; i < deadObjects.size(); i++)
- removePositionedObject(*deadObjects.at(i));
+ for (auto* renderer : renderersToRemove)
+ removePositionedObject(*renderer);
}
void RenderBlock::addPercentHeightDescendant(RenderBox& descendant)
{
- insertIntoTrackedRendererMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
+ insertIntoTrackedRendererMaps(*this, descendant);
}
void RenderBlock::removePercentHeightDescendant(RenderBox& descendant)
{
- removeFromTrackedRendererMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
+ removeFromTrackedRendererMaps(descendant);
}
TrackedRendererListHashSet* RenderBlock::percentHeightDescendants() const
{
- return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this) : 0;
+ return percentHeightDescendantsMap ? percentHeightDescendantsMap->get(this) : nullptr;
}
bool RenderBlock::hasPercentHeightContainerMap()
{
- return gPercentHeightContainerMap;
+ return percentHeightContainerMap;
}
bool RenderBlock::hasPercentHeightDescendant(RenderBox& descendant)
{
- // We don't null check gPercentHeightContainerMap since the caller
+ // We don't null check percentHeightContainerMap since the caller
// already ensures this and we need to call this function on every
// descendant in clearPercentHeightDescendantsFrom().
- ASSERT(gPercentHeightContainerMap);
- return gPercentHeightContainerMap->contains(&descendant);
+ ASSERT(percentHeightContainerMap);
+ return percentHeightContainerMap->contains(&descendant);
}
void RenderBlock::removePercentHeightDescendantIfNeeded(RenderBox& descendant)
@@ -2268,7 +2334,7 @@ void RenderBlock::removePercentHeightDescendantIfNeeded(RenderBox& descendant)
void RenderBlock::clearPercentHeightDescendantsFrom(RenderBox& parent)
{
- ASSERT(gPercentHeightContainerMap);
+ ASSERT(percentHeightContainerMap);
for (RenderObject* child = parent.firstChild(); child; child = child->nextInPreOrder(&parent)) {
if (!is<RenderBox>(*child))
continue;
@@ -3768,17 +3834,12 @@ RenderBlock* RenderBlock::createAnonymousWithParentRendererAndDisplay(const Rend
#ifndef NDEBUG
void RenderBlock::checkPositionedObjectsNeedLayout()
{
- if (!gPositionedDescendantsMap)
- return;
-
- TrackedRendererListHashSet* positionedDescendantSet = positionedObjects();
- if (!positionedDescendantSet)
+ auto* positionedDescendants = positionedObjects();
+ if (!positionedDescendants)
return;
- for (auto it = positionedDescendantSet->begin(), end = positionedDescendantSet->end(); it != end; ++it) {
- RenderBox* currBox = *it;
- ASSERT(!currBox->needsLayout());
- }
+ for (auto* renderer : *positionedDescendants)
+ ASSERT(!renderer->needsLayout());
}
#endif
diff --git a/Source/WebCore/rendering/RenderBlock.h b/Source/WebCore/rendering/RenderBlock.h
index bb618e486..49468c586 100644
--- a/Source/WebCore/rendering/RenderBlock.h
+++ b/Source/WebCore/rendering/RenderBlock.h
@@ -42,8 +42,6 @@ struct BidiRun;
struct PaintInfo;
typedef WTF::ListHashSet<RenderBox*> TrackedRendererListHashSet;
-typedef WTF::HashMap<const RenderBlock*, std::unique_ptr<TrackedRendererListHashSet>> TrackedDescendantsMap;
-typedef WTF::HashMap<const RenderBox*, std::unique_ptr<HashSet<RenderBlock*>>> TrackedContainerMap;
enum CaretType { CursorCaret, DragCaret };
enum ContainingBlockState { NewContainingBlock, SameContainingBlock };
@@ -83,8 +81,8 @@ public:
virtual void invalidateLineLayoutPath() { }
void insertPositionedObject(RenderBox&);
- static void removePositionedObject(RenderBox&);
- void removePositionedObjects(RenderBlock*, ContainingBlockState = SameContainingBlock);
+ static void removePositionedObject(const RenderBox&);
+ void removePositionedObjects(const RenderBlock*, ContainingBlockState = SameContainingBlock);
TrackedRendererListHashSet* positionedObjects() const;
bool hasPositionedObjects() const
@@ -316,7 +314,7 @@ protected:
void layoutPositionedObjects(bool relayoutChildren, bool fixedPositionObjectsOnly = false);
virtual void layoutPositionedObject(RenderBox&, bool relayoutChildren, bool fixedPositionObjectsOnly);
- void markFixedPositionObjectForLayoutIfNeeded(RenderObject& child);
+ void markFixedPositionObjectForLayoutIfNeeded(RenderBox& child);
LayoutUnit marginIntrinsicLogicalWidthForChild(RenderBox&) const;
@@ -417,12 +415,6 @@ private:
virtual bool isSelfCollapsingBlock() const override;
virtual bool childrenPreventSelfCollapsing() const;
- // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
- virtual bool hasLines() const { return false; }
-
- void insertIntoTrackedRendererMaps(RenderBox& descendant, TrackedDescendantsMap*&, TrackedContainerMap*&, bool forceNewEntry = false);
- static void removeFromTrackedRendererMaps(RenderBox& descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
-
void createFirstLetterRenderer(RenderElement* firstLetterBlock, RenderText* currentTextChild);
void updateFirstLetterStyle(RenderElement* firstLetterBlock, RenderObject* firstLetterContainer);
diff --git a/Source/WebCore/rendering/RenderBlockFlow.cpp b/Source/WebCore/rendering/RenderBlockFlow.cpp
index 33bce4025..53ff0b6c7 100644
--- a/Source/WebCore/rendering/RenderBlockFlow.cpp
+++ b/Source/WebCore/rendering/RenderBlockFlow.cpp
@@ -1648,7 +1648,15 @@ static inline bool needsAppleMailPaginationQuirk(RootInlineBox& lineBox)
return false;
}
-
+
+static void clearShouldBreakAtLineToAvoidWidowIfNeeded(RenderBlockFlow& blockFlow)
+{
+ if (!blockFlow.shouldBreakAtLineToAvoidWidow())
+ return;
+ blockFlow.clearShouldBreakAtLineToAvoidWidow();
+ blockFlow.setDidBreakAtLineToAvoidWidow();
+}
+
void RenderBlockFlow::adjustLinePositionForPagination(RootInlineBox* lineBox, LayoutUnit& delta, bool& overflowsRegion, RenderFlowThread* flowThread)
{
// FIXME: Ignore anonymous inline blocks. Handle the delta already having been set because of
@@ -1702,8 +1710,11 @@ void RenderBlockFlow::adjustLinePositionForPagination(RootInlineBox* lineBox, La
logicalBottom = intMinForLayoutUnit;
lineBox->computeReplacedAndTextLineTopAndBottom(logicalOffset, logicalBottom);
lineHeight = logicalBottom - logicalOffset;
- if (logicalOffset == intMaxForLayoutUnit || lineHeight > pageLogicalHeight)
- return; // Give up. We're genuinely too big even after excluding blank space and overflow.
+ if (logicalOffset == intMaxForLayoutUnit || lineHeight > pageLogicalHeight) {
+ // Give up. We're genuinely too big even after excluding blank space and overflow.
+ clearShouldBreakAtLineToAvoidWidowIfNeeded(*this);
+ return;
+ }
pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset);
}
@@ -1712,10 +1723,8 @@ void RenderBlockFlow::adjustLinePositionForPagination(RootInlineBox* lineBox, La
int lineIndex = lineCount(lineBox);
if (remainingLogicalHeight < lineHeight || (shouldBreakAtLineToAvoidWidow() && lineBreakToAvoidWidow() == lineIndex)) {
- if (shouldBreakAtLineToAvoidWidow() && lineBreakToAvoidWidow() == lineIndex) {
- clearShouldBreakAtLineToAvoidWidow();
- setDidBreakAtLineToAvoidWidow();
- }
+ if (lineBreakToAvoidWidow() == lineIndex)
+ clearShouldBreakAtLineToAvoidWidowIfNeeded(*this);
// If we have a non-uniform page height, then we have to shift further possibly.
if (!hasUniformPageLogicalHeight && !pushToNextPageWithMinimumLogicalHeight(remainingLogicalHeight, logicalOffset, lineHeight))
return;
@@ -3528,7 +3537,8 @@ bool RenderBlockFlow::relayoutForPagination(LayoutStateMaintainer& statePusher)
bool RenderBlockFlow::hasLines() const
{
- ASSERT(childrenInline());
+ if (!childrenInline())
+ return false;
if (auto simpleLineLayout = this->simpleLineLayout())
return simpleLineLayout->lineCount();
diff --git a/Source/WebCore/rendering/RenderBlockFlow.h b/Source/WebCore/rendering/RenderBlockFlow.h
index 3b9d81268..84766c45b 100644
--- a/Source/WebCore/rendering/RenderBlockFlow.h
+++ b/Source/WebCore/rendering/RenderBlockFlow.h
@@ -345,8 +345,8 @@ public:
RootInlineBox* firstRootBox() const { return downcast<RootInlineBox>(m_lineBoxes.firstLineBox()); }
RootInlineBox* lastRootBox() const { return downcast<RootInlineBox>(m_lineBoxes.lastLineBox()); }
- virtual bool hasLines() const override final;
- virtual void invalidateLineLayoutPath() override final;
+ bool hasLines() const;
+ void invalidateLineLayoutPath() final;
enum LineLayoutPath { UndeterminedPath = 0, SimpleLinesPath, LineBoxesPath, ForceLineBoxesPath };
LineLayoutPath lineLayoutPath() const { return static_cast<LineLayoutPath>(renderBlockFlowLineLayoutPath()); }
diff --git a/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
index 451de09c9..d67c38daa 100644
--- a/Source/WebCore/rendering/RenderBlockLineLayout.cpp
+++ b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
@@ -2250,6 +2250,10 @@ void RenderBlockFlow::marginCollapseLinesFromStart(LineLayoutState& layoutState,
if (!stopLine->hasAnonymousInlineBlock())
return;
+ // We already handled top of block with startLine.
+ if (stopLine == firstRootBox())
+ return;
+
// Re-run margin collapsing on the block sequence that stopLine is a part of.
// First go backwards to get the entire sequence.
RootInlineBox* prev = stopLine;
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp
index c437851c0..e4809d288 100644
--- a/Source/WebCore/rendering/RenderBox.cpp
+++ b/Source/WebCore/rendering/RenderBox.cpp
@@ -120,18 +120,12 @@ static bool skipBodyBackground(const RenderBox* bodyElementRenderer)
RenderBox::RenderBox(Element& element, Ref<RenderStyle>&& style, BaseTypeFlags baseTypeFlags)
: RenderBoxModelObject(element, WTFMove(style), baseTypeFlags)
- , m_minPreferredLogicalWidth(-1)
- , m_maxPreferredLogicalWidth(-1)
- , m_inlineBoxWrapper(nullptr)
{
setIsBox();
}
RenderBox::RenderBox(Document& document, Ref<RenderStyle>&& style, BaseTypeFlags baseTypeFlags)
: RenderBoxModelObject(document, WTFMove(style), baseTypeFlags)
- , m_minPreferredLogicalWidth(-1)
- , m_maxPreferredLogicalWidth(-1)
- , m_inlineBoxWrapper(nullptr)
{
setIsBox();
}
@@ -516,17 +510,19 @@ void RenderBox::updateFromStyle()
boxHasOverflowClip = false;
}
}
-
// Check for overflow clip.
// It's sufficient to just check one direction, since it's illegal to have visible on only one overflow value.
if (boxHasOverflowClip) {
- if (!s_hadOverflowClip)
- // Erase the overflow
- repaint();
+ if (!s_hadOverflowClip && hasRenderOverflow()) {
+ // Erase the overflow.
+ // Overflow changes have to result in immediate repaints of the entire layout overflow area because
+ // repaints issued by removal of descendants get clipped using the updated style when they shouldn't.
+ repaintRectangle(visualOverflowRect());
+ repaintRectangle(layoutOverflowRect());
+ }
setHasOverflowClip();
}
}
-
setHasTransformRelatedProperty(styleToUse.hasTransformRelatedProperty());
setHasReflection(styleToUse.boxReflect());
}
@@ -2121,13 +2117,14 @@ std::unique_ptr<InlineElementBox> RenderBox::createInlineBox()
void RenderBox::dirtyLineBoxes(bool fullLayout)
{
- if (m_inlineBoxWrapper) {
- if (fullLayout) {
- delete m_inlineBoxWrapper;
- m_inlineBoxWrapper = nullptr;
- } else
- m_inlineBoxWrapper->dirtyLineBoxes();
- }
+ if (!m_inlineBoxWrapper)
+ return;
+
+ if (fullLayout) {
+ delete m_inlineBoxWrapper;
+ m_inlineBoxWrapper = nullptr;
+ } else
+ m_inlineBoxWrapper->dirtyLineBoxes();
}
void RenderBox::positionLineBox(InlineElementBox& box)
@@ -2163,12 +2160,13 @@ void RenderBox::positionLineBox(InlineElementBox& box)
void RenderBox::deleteLineBoxWrapper()
{
- if (m_inlineBoxWrapper) {
- if (!documentBeingDestroyed())
- m_inlineBoxWrapper->removeFromParent();
- delete m_inlineBoxWrapper;
- m_inlineBoxWrapper = nullptr;
- }
+ if (!m_inlineBoxWrapper)
+ return;
+
+ if (!documentBeingDestroyed())
+ m_inlineBoxWrapper->removeFromParent();
+ delete m_inlineBoxWrapper;
+ m_inlineBoxWrapper = nullptr;
}
LayoutRect RenderBox::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h
index 508ba3d28..8e63a2c82 100644
--- a/Source/WebCore/rendering/RenderBox.h
+++ b/Source/WebCore/rendering/RenderBox.h
@@ -740,7 +740,7 @@ protected:
LayoutUnit m_maxPreferredLogicalWidth;
// For inline replaced elements, the inline box that owns us.
- InlineElementBox* m_inlineBoxWrapper;
+ InlineElementBox* m_inlineBoxWrapper { nullptr };
// Our overflow information.
RefPtr<RenderOverflow> m_overflow;
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp
index 98e9f2d06..5b0a83de7 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.cpp
+++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp
@@ -363,7 +363,7 @@ LayoutUnit RenderFlexibleBox::clientLogicalBottomAfterRepositioning()
return std::max(clientLogicalBottom(), maxChildLogicalBottom);
}
-bool RenderFlexibleBox::hasOrthogonalFlow(RenderBox& child) const
+bool RenderFlexibleBox::hasOrthogonalFlow(const RenderBox& child) const
{
// FIXME: If the child is a flexbox, then we need to check isHorizontalFlow.
return isHorizontalFlow() != child.isHorizontalWritingMode();
@@ -450,14 +450,14 @@ LayoutUnit RenderFlexibleBox::mainAxisContentExtent(LayoutUnit contentLogicalHei
return contentLogicalWidth();
}
-Optional<LayoutUnit> RenderFlexibleBox::computeMainAxisExtentForChild(RenderBox& child, SizeType sizeType, const Length& size)
+Optional<LayoutUnit> RenderFlexibleBox::computeMainAxisExtentForChild(const RenderBox& child, SizeType sizeType, const Length& size)
{
// FIXME: This is wrong for orthogonal flows. It should use the flexbox's writing-mode, not the child's in order
// to figure out the logical height/width.
if (isColumnFlow()) {
// We don't have to check for "auto" here - computeContentLogicalHeight will just return Nullopt for that case anyway.
if (size.isIntrinsic())
- child.layoutIfNeeded();
+ const_cast<RenderBox&>(child).layoutIfNeeded(); // FIXME: Should not need to do a layout here.
return child.computeContentLogicalHeight(sizeType, size, child.logicalHeight() - child.borderAndPaddingLogicalHeight());
}
// FIXME: Figure out how this should work for regions and pass in the appropriate values.
@@ -648,15 +648,14 @@ LayoutUnit RenderFlexibleBox::mainAxisBorderAndPaddingExtentForChild(RenderBox&
{
return isHorizontalFlow() ? child.horizontalBorderAndPaddingExtent() : child.verticalBorderAndPaddingExtent();
}
-
-bool RenderFlexibleBox::mainAxisExtentIsDefinite() const
-{
- return isColumnFlow() ? hasDefiniteLogicalHeight() : hasDefiniteLogicalWidth();
-}
-
-bool RenderFlexibleBox::mainAxisLengthIsIndefinite(const Length& flexBasis) const
+
+bool RenderFlexibleBox::mainAxisLengthIsDefinite(const RenderBox& child, const Length& flexBasis) const
{
- return flexBasis.isAuto() || (flexBasis.isPercentOrCalculated() && !mainAxisExtentIsDefinite());
+ if (flexBasis.isAuto())
+ return false;
+ if (flexBasis.isPercentOrCalculated())
+ return isColumnFlow() ? bool(child.computePercentageLogicalHeight(flexBasis)) : hasDefiniteLogicalWidth();
+ return true;
}
LayoutUnit RenderFlexibleBox::mainAxisScrollbarExtentForChild(RenderBox& child) const
@@ -855,7 +854,72 @@ void RenderFlexibleBox::prepareOrderIteratorAndMargins()
}
}
-LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox& child, LayoutUnit childSize)
+bool RenderFlexibleBox::crossAxisLengthIsDefinite(const RenderBox& child, const Length& length) const
+{
+ if (length.isAuto())
+ return false;
+ if (length.isPercentOrCalculated())
+ return hasOrthogonalFlow(child) ? hasDefiniteLogicalWidth() : bool(child.computePercentageLogicalHeight(length));
+ return length.isFixed();
+}
+
+
+Optional<LayoutUnit> RenderFlexibleBox::computeMainSizeFromAspectRatioUsing(const RenderBox& child, Length crossSizeLength) const
+{
+ ASSERT(child.hasAspectRatio());
+ ASSERT(child.intrinsicSize().height() > 0);
+
+ Optional<LayoutUnit> crossSize;
+ if (crossSizeLength.isFixed())
+ crossSize = LayoutUnit(crossSizeLength.value());
+ else {
+ ASSERT(crossSizeLength.isPercentOrCalculated());
+ crossSize = hasOrthogonalFlow(child) ?
+ adjustBorderBoxLogicalWidthForBoxSizing(valueForLength(crossSizeLength, contentWidth())) :
+ child.computePercentageLogicalHeight(crossSizeLength);
+ }
+
+ if (!crossSize)
+ return crossSize;
+
+ const LayoutSize& childIntrinsicSize = child.intrinsicSize();
+ double ratio = childIntrinsicSize.width().toFloat() / childIntrinsicSize.height().toFloat();
+ if (isHorizontalFlow())
+ return LayoutUnit(crossSize.value() * ratio);
+ return LayoutUnit(crossSize.value() / ratio);
+}
+
+LayoutUnit RenderFlexibleBox::adjustChildSizeForAspectRatioCrossAxisMinAndMax(const RenderBox& child, LayoutUnit childSize)
+{
+ Length crossMin = isHorizontalFlow() ? child.style().minHeight() : child.style().minWidth();
+ Length crossMax = isHorizontalFlow() ? child.style().maxHeight() : child.style().maxWidth();
+
+ if (crossAxisLengthIsDefinite(child, crossMax)) {
+ Optional<LayoutUnit> maxValue = computeMainSizeFromAspectRatioUsing(child, crossMax);
+ if (maxValue)
+ childSize = std::min(maxValue.value(), childSize);
+ }
+
+ if (crossAxisLengthIsDefinite(child, crossMin)) {
+ Optional<LayoutUnit> minValue = computeMainSizeFromAspectRatioUsing(child, crossMin);
+ if (minValue)
+ childSize = std::max(minValue.value(), childSize);
+ }
+
+ return childSize;
+}
+
+bool RenderFlexibleBox::useChildAspectRatio(const RenderBox& child) const
+{
+ if (!child.hasAspectRatio())
+ return false;
+ if (!child.intrinsicSize().height())
+ return false;
+ Length crossSize = isHorizontalFlow() ? child.style().height() : child.style().width();
+ return crossAxisLengthIsDefinite(child, crossSize);
+}
+
+LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(const RenderBox& child, LayoutUnit childSize)
{
Length max = isHorizontalFlow() ? child.style().maxWidth() : child.style().maxHeight();
Optional<LayoutUnit> maxExtent = Nullopt;
@@ -863,26 +927,36 @@ LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox& child, Layo
maxExtent = computeMainAxisExtentForChild(child, MaxSize, max);
childSize = std::min(childSize, maxExtent.valueOr(childSize));
}
-
+
Length min = isHorizontalFlow() ? child.style().minWidth() : child.style().minHeight();
if (min.isSpecifiedOrIntrinsic())
return std::max(childSize, computeMainAxisExtentForChild(child, MinSize, min).valueOr(childSize));
-
- if (!isFlexibleBoxImpl() && min.isAuto() && mainAxisOverflowForChild(child) == OVISIBLE) {
+
+ if (!isFlexibleBoxImpl() && min.isAuto() && mainAxisOverflowForChild(child) == OVISIBLE && !(isColumnFlow() && is<RenderFlexibleBox>(child))) {
// This is the implementation of CSS flexbox section 4.5 which defines the minimum size of "pure" flex
// items. For any other item the value should be 0, this also includes RenderFlexibleBox's derived clases
// (RenderButton, RenderFullScreen...) because that's just an implementation detail.
+ // FIXME: For now we don't handle nested column flexboxes. Need to implement better intrinsic
+ // size handling from the flex box spec first (4.5).
LayoutUnit contentSize = computeMainAxisExtentForChild(child, MinSize, Length(MinContent)).value();
ASSERT(contentSize >= 0);
+ if (child.hasAspectRatio() && child.intrinsicSize().height() > 0)
+ contentSize = adjustChildSizeForAspectRatioCrossAxisMinAndMax(child, contentSize);
contentSize = std::min(contentSize, maxExtent.valueOr(contentSize));
-
+
Length mainSize = isHorizontalFlow() ? child.style().width() : child.style().height();
- if (!mainAxisLengthIsIndefinite(mainSize)) {
+ if (mainAxisLengthIsDefinite(child, mainSize)) {
LayoutUnit resolvedMainSize = computeMainAxisExtentForChild(child, MainOrPreferredSize, mainSize).value();
ASSERT(resolvedMainSize >= 0);
LayoutUnit specifiedSize = std::min(resolvedMainSize, maxExtent.valueOr(resolvedMainSize));
-
return std::max(childSize, std::min(specifiedSize, contentSize));
+ } else if (useChildAspectRatio(child)) {
+ Length crossSizeLength = isHorizontalFlow() ? child.style().height() : child.style().width();
+ Optional<LayoutUnit> transferredSize = computeMainSizeFromAspectRatioUsing(child, crossSizeLength);
+ if (transferredSize) {
+ transferredSize = adjustChildSizeForAspectRatioCrossAxisMinAndMax(child, transferredSize.value());
+ return std::max(childSize, std::min(transferredSize.value(), contentSize));
+ }
}
return std::max(childSize, contentSize);
}
@@ -1085,7 +1159,7 @@ void RenderFlexibleBox::resetAutoMarginsAndLogicalTopInCrossAxis(RenderBox& chil
child.updateLogicalHeight();
}
-EOverflow RenderFlexibleBox::mainAxisOverflowForChild(RenderBox& child) const
+EOverflow RenderFlexibleBox::mainAxisOverflowForChild(const RenderBox& child) const
{
if (isHorizontalFlow())
return child.style().overflowX();
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.h b/Source/WebCore/rendering/RenderFlexibleBox.h
index 9bae316aa..f2e5d1760 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.h
+++ b/Source/WebCore/rendering/RenderFlexibleBox.h
@@ -85,8 +85,8 @@ private:
// Use an inline capacity of 8, since flexbox containers usually have less than 8 children.
typedef Vector<LayoutRect, 8> ChildFrameRects;
- virtual bool isFlexibleBox() const override final { return true; }
- bool hasOrthogonalFlow(RenderBox& child) const;
+ bool isFlexibleBox() const final { return true; }
+ bool hasOrthogonalFlow(const RenderBox& child) const;
bool isColumnFlow() const;
bool isLeftToRightFlow() const;
bool isMultiline() const;
@@ -98,7 +98,7 @@ private:
LayoutUnit mainAxisExtent() const;
LayoutUnit crossAxisContentExtent() const;
LayoutUnit mainAxisContentExtent(LayoutUnit contentLogicalHeight);
- Optional<LayoutUnit> computeMainAxisExtentForChild(RenderBox& child, SizeType, const Length& size);
+ Optional<LayoutUnit> computeMainAxisExtentForChild(const RenderBox& child, SizeType, const Length& size);
WritingMode transformedWritingMode() const;
LayoutUnit flowAwareBorderStart() const;
LayoutUnit flowAwareBorderEnd() const;
@@ -122,7 +122,7 @@ private:
LayoutUnit mainAxisBorderAndPaddingExtentForChild(RenderBox& child) const;
LayoutUnit mainAxisScrollbarExtentForChild(RenderBox& child) const;
LayoutUnit preferredMainAxisContentExtentForChild(RenderBox& child, bool hasInfiniteLineLength);
- EOverflow mainAxisOverflowForChild(RenderBox&) const;
+ EOverflow mainAxisOverflowForChild(const RenderBox&) const;
void layoutFlexItems(bool relayoutChildren, Vector<LineContext>&);
LayoutUnit autoMarginOffsetInMainAxis(const OrderedFlexItemList&, LayoutUnit& availableFreeSpace);
@@ -139,7 +139,8 @@ private:
LayoutUnit computeChildMarginValue(const Length& margin);
void prepareOrderIteratorAndMargins();
- LayoutUnit adjustChildSizeForMinAndMax(RenderBox&, LayoutUnit childSize);
+ LayoutUnit adjustChildSizeForMinAndMax(const RenderBox&, LayoutUnit childSize);
+ LayoutUnit adjustChildSizeForAspectRatioCrossAxisMinAndMax(const RenderBox&, LayoutUnit childSize);
bool computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, double& totalFlexGrow, double& totalWeightedFlexShrink, LayoutUnit& minMaxAppliedMainAxisExtent, bool& hasInfiniteLineLength);
bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize&, Vector<LayoutUnit>& childSizes, bool hasInfiniteLineLength);
@@ -158,9 +159,11 @@ private:
void flipForRightToLeftColumn();
void flipForWrapReverse(const Vector<LineContext>&, LayoutUnit crossAxisStartEdge);
- bool mainAxisExtentIsDefinite() const;
- bool mainAxisLengthIsIndefinite(const Length& flexBasis) const;
-
+ bool mainAxisLengthIsDefinite(const RenderBox&, const Length&) const;
+ bool crossAxisLengthIsDefinite(const RenderBox&, const Length&) const;
+ bool useChildAspectRatio(const RenderBox&) const;
+ Optional<LayoutUnit> computeMainSizeFromAspectRatioUsing(const RenderBox& child, Length crossSizeLength) const;
+
virtual bool isFlexibleBoxImpl() const { return false; };
mutable OrderIterator m_orderIterator;
diff --git a/Source/WebCore/rendering/RenderHTMLCanvas.cpp b/Source/WebCore/rendering/RenderHTMLCanvas.cpp
index f2de75d52..199f903b4 100644
--- a/Source/WebCore/rendering/RenderHTMLCanvas.cpp
+++ b/Source/WebCore/rendering/RenderHTMLCanvas.cpp
@@ -101,18 +101,7 @@ void RenderHTMLCanvas::canvasSizeChanged()
if (!parent())
return;
-
- if (!preferredLogicalWidthsDirty())
- setPreferredLogicalWidthsDirty(true);
-
- LayoutSize oldSize = size();
- updateLogicalWidth();
- updateLogicalHeight();
- if (oldSize == size())
- return;
-
- if (!selfNeedsLayout())
- setNeedsLayout();
+ setNeedsLayoutIfNeededAfterIntrinsicSizeChange();
}
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderImage.cpp b/Source/WebCore/rendering/RenderImage.cpp
index d8ee8150b..00d907829 100644
--- a/Source/WebCore/rendering/RenderImage.cpp
+++ b/Source/WebCore/rendering/RenderImage.cpp
@@ -294,29 +294,8 @@ void RenderImage::repaintOrMarkForLayout(ImageSizeChangeType imageSizeChange, co
bool imageSourceHasChangedSize = oldIntrinsicSize != newIntrinsicSize || imageSizeChange != ImageSizeChangeNone;
- if (imageSourceHasChangedSize) {
- setPreferredLogicalWidthsDirty(true);
-
- // If the actual area occupied by the image has changed and it is not constrained by style then a layout is required.
- bool imageSizeIsConstrained = style().logicalWidth().isSpecified() && style().logicalHeight().isSpecified();
-
- // FIXME: We only need to recompute the containing block's preferred size
- // if the containing block's size depends on the image's size (i.e., the container uses shrink-to-fit sizing).
- // There's no easy way to detect that shrink-to-fit is needed, always force a layout.
- bool containingBlockNeedsToRecomputePreferredSize =
- style().logicalWidth().isPercentOrCalculated()
- || style().logicalMaxWidth().isPercentOrCalculated()
- || style().logicalMinWidth().isPercentOrCalculated();
-
- bool layoutSizeDependsOnIntrinsicSize = style().aspectRatioType() == AspectRatioFromIntrinsic;
-
- if (!imageSizeIsConstrained || containingBlockNeedsToRecomputePreferredSize || layoutSizeDependsOnIntrinsicSize) {
- // FIXME: It's not clear that triggering a layout guarantees a repaint in all cases.
- // But many callers do depend on this code causing a layout.
- setNeedsLayout();
- return;
- }
- }
+ if (imageSourceHasChangedSize && setNeedsLayoutIfNeededAfterIntrinsicSizeChange())
+ return;
if (everHadLayout() && !selfNeedsLayout()) {
// The inner content rectangle is calculated during layout, but may need an update now
@@ -574,6 +553,11 @@ bool RenderImage::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect,
ObjectFit objectFit = style().objectFit();
if (objectFit != ObjectFitFill && objectFit != ObjectFitCover)
return false;
+
+ LengthPoint objectPosition = style().objectPosition();
+ if (objectPosition != RenderStyle::initialObjectPosition())
+ return false;
+
// Check for image with alpha.
return imageResource().cachedImage() && imageResource().cachedImage()->currentFrameKnownToBeOpaque(this);
}
diff --git a/Source/WebCore/rendering/RenderInline.cpp b/Source/WebCore/rendering/RenderInline.cpp
index 3125c62f6..749099044 100644
--- a/Source/WebCore/rendering/RenderInline.cpp
+++ b/Source/WebCore/rendering/RenderInline.cpp
@@ -1206,7 +1206,7 @@ LayoutRect RenderInline::linesVisualOverflowBoundingBoxInRegion(const RenderRegi
LayoutRect RenderInline::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
{
// Only first-letter renderers are allowed in here during layout. They mutate the tree triggering repaints.
- ASSERT(!view().layoutStateEnabled() || style().styleType() == FIRST_LETTER);
+ ASSERT(!view().layoutStateEnabled() || style().styleType() == FIRST_LETTER || hasSelfPaintingLayer());
if (!firstLineBoxIncludingCulling() && !continuation())
return LayoutRect();
@@ -1807,8 +1807,7 @@ void RenderInline::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
if (!container)
container = this;
- region.clip = region.bounds;
- container->computeAbsoluteRepaintRect(region.clip);
+ region.clip = container->computeAbsoluteRepaintRect(region.bounds);
if (region.clip.height() < 0) {
region.clip.setHeight(0);
region.clip.setWidth(0);
diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp
index d0cba5316..dae97f749 100644
--- a/Source/WebCore/rendering/RenderLayer.cpp
+++ b/Source/WebCore/rendering/RenderLayer.cpp
@@ -1805,15 +1805,15 @@ void RenderLayer::beginTransparencyLayers(GraphicsContext& context, const LayerP
context.clip(pixelSnappedClipRect);
#if ENABLE(CSS_COMPOSITING)
- // RenderSVGRoot takes care of its blend mode.
- if (!renderer().isSVGRoot() && hasBlendMode())
+ bool usesCompositeOperation = hasBlendMode() && !(renderer().isSVGRoot() && parent() && parent()->isRootLayer());
+ if (usesCompositeOperation)
context.setCompositeOperation(context.compositeOperation(), blendMode());
#endif
context.beginTransparencyLayer(renderer().opacity());
#if ENABLE(CSS_COMPOSITING)
- if (!renderer().isSVGRoot() && hasBlendMode())
+ if (usesCompositeOperation)
context.setCompositeOperation(context.compositeOperation(), BlendModeNormal);
#endif
@@ -6423,6 +6423,19 @@ void RenderLayer::repaintIncludingNonCompositingDescendants(RenderLayerModelObje
}
}
+static bool mayCreateGraphicalGroup(const RenderElement& renderer)
+{
+ bool createsGraphicalGroup = renderer.hasClipPath()
+ || renderer.hasFilter()
+ || renderer.hasBackdropFilter()
+#if ENABLE(CSS_COMPOSITING)
+ || renderer.hasBlendMode()
+#endif
+ || renderer.isTransparent()
+ || renderer.hasMask();
+ return createsGraphicalGroup || (renderer.style().willChange() && renderer.style().willChange()->canCreateGraphicalGroup());
+}
+
bool RenderLayer::shouldBeNormalFlowOnly() const
{
return (renderer().hasOverflowClip()
@@ -6434,20 +6447,14 @@ bool RenderLayer::shouldBeNormalFlowOnly() const
|| renderer().isRenderIFrame()
|| (renderer().style().specifiesColumns() && !isRootLayer())
|| renderer().isInFlowRenderFlowThread())
- && !renderer().isPositioned()
&& !renderer().hasTransformRelatedProperty()
- && !renderer().hasClipPath()
- && !renderer().hasFilter()
- && !renderer().hasBackdropFilter()
+ && !renderer().isPositioned()
+ && !needsCompositedScrolling()
+ && !renderer().style().hasFlowFrom()
#if PLATFORM(IOS)
&& !hasAcceleratedTouchScrolling()
#endif
-#if ENABLE(CSS_COMPOSITING)
- && !renderer().hasBlendMode()
-#endif
- && !isTransparent()
- && !needsCompositedScrolling()
- && !renderer().style().hasFlowFrom();
+ && !mayCreateGraphicalGroup(renderer());
}
bool RenderLayer::shouldBeSelfPaintingLayer() const
diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp
index edb4f3398..df2cd277d 100644
--- a/Source/WebCore/rendering/RenderObject.cpp
+++ b/Source/WebCore/rendering/RenderObject.cpp
@@ -1924,8 +1924,7 @@ void RenderObject::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
h - styleRegion.offset.top().value() - styleRegion.offset.bottom().value());
region.type = styleRegion.type;
- region.clip = region.bounds;
- computeAbsoluteRepaintRect(region.clip);
+ region.clip = computeAbsoluteRepaintRect(region.bounds);
if (region.clip.height() < 0) {
region.clip.setHeight(0);
region.clip.setWidth(0);
diff --git a/Source/WebCore/rendering/RenderReplaced.cpp b/Source/WebCore/rendering/RenderReplaced.cpp
index a818ad0fa..6b36b13e3 100644
--- a/Source/WebCore/rendering/RenderReplaced.cpp
+++ b/Source/WebCore/rendering/RenderReplaced.cpp
@@ -287,6 +287,31 @@ bool RenderReplaced::hasReplacedLogicalHeight() const
return false;
}
+bool RenderReplaced::setNeedsLayoutIfNeededAfterIntrinsicSizeChange()
+{
+ setPreferredLogicalWidthsDirty(true);
+
+ // If the actual area occupied by the image has changed and it is not constrained by style then a layout is required.
+ bool imageSizeIsConstrained = style().logicalWidth().isSpecified() && style().logicalHeight().isSpecified();
+
+ // FIXME: We only need to recompute the containing block's preferred size
+ // if the containing block's size depends on the image's size (i.e., the container uses shrink-to-fit sizing).
+ // There's no easy way to detect that shrink-to-fit is needed, always force a layout.
+ bool containingBlockNeedsToRecomputePreferredSize =
+ style().logicalWidth().isPercentOrCalculated()
+ || style().logicalMaxWidth().isPercentOrCalculated()
+ || style().logicalMinWidth().isPercentOrCalculated();
+
+ bool layoutSizeDependsOnIntrinsicSize = style().aspectRatioType() == AspectRatioFromIntrinsic;
+
+ if (!imageSizeIsConstrained || containingBlockNeedsToRecomputePreferredSize || layoutSizeDependsOnIntrinsicSize) {
+ setNeedsLayout();
+ return true;
+ }
+
+ return false;
+}
+
void RenderReplaced::computeAspectRatioInformationForRenderBox(RenderBox* contentRenderer, FloatSize& constrainedSize, double& intrinsicRatio) const
{
FloatSize intrinsicSize;
@@ -338,8 +363,6 @@ LayoutRect RenderReplaced::replacedContentRect(const LayoutSize& intrinsicSize)
return contentRect;
ObjectFit objectFit = style().objectFit();
- if (objectFit == ObjectFitFill)
- return contentRect;
LayoutRect finalRect = contentRect;
switch (objectFit) {
@@ -354,13 +377,14 @@ LayoutRect RenderReplaced::replacedContentRect(const LayoutSize& intrinsicSize)
finalRect.setSize(intrinsicSize);
break;
case ObjectFitFill:
- ASSERT_NOT_REACHED();
+ break;
}
- // FIXME: This is where object-position should be taken into account, but since it's not
- // implemented yet, assume the initial value of "50% 50%".
- LayoutUnit xOffset = (contentRect.width() - finalRect.width()) / 2;
- LayoutUnit yOffset = (contentRect.height() - finalRect.height()) / 2;
+ LengthPoint objectPosition = style().objectPosition();
+
+ LayoutUnit xOffset = minimumValueForLength(objectPosition.x(), contentRect.width() - finalRect.width());
+ LayoutUnit yOffset = minimumValueForLength(objectPosition.y(), contentRect.height() - finalRect.height());
+
finalRect.move(xOffset, yOffset);
return finalRect;
diff --git a/Source/WebCore/rendering/RenderReplaced.h b/Source/WebCore/rendering/RenderReplaced.h
index 9f7dfc571..72dbb81d1 100644
--- a/Source/WebCore/rendering/RenderReplaced.h
+++ b/Source/WebCore/rendering/RenderReplaced.h
@@ -37,6 +37,7 @@ public:
bool hasReplacedLogicalWidth() const;
bool hasReplacedLogicalHeight() const;
+ bool setNeedsLayoutIfNeededAfterIntrinsicSizeChange();
protected:
RenderReplaced(Element&, Ref<RenderStyle>&&);
diff --git a/Source/WebCore/rendering/RenderTable.cpp b/Source/WebCore/rendering/RenderTable.cpp
index 05325314a..b3be2de98 100644
--- a/Source/WebCore/rendering/RenderTable.cpp
+++ b/Source/WebCore/rendering/RenderTable.cpp
@@ -300,6 +300,13 @@ void RenderTable::updateLogicalWidth()
// Ensure we aren't bigger than our available width.
setLogicalWidth(std::min(availableContentLogicalWidth, maxPreferredLogicalWidth()));
+ LayoutUnit maxWidth = maxPreferredLogicalWidth();
+ // scaledWidthFromPercentColumns depends on m_layoutStruct in TableLayoutAlgorithmAuto, which
+ // maxPreferredLogicalWidth fills in. So scaledWidthFromPercentColumns has to be called after
+ // maxPreferredLogicalWidth.
+ LayoutUnit scaledWidth = m_tableLayout->scaledWidthFromPercentColumns() + bordersPaddingAndSpacingInRowDirection();
+ maxWidth = std::max(scaledWidth, maxWidth);
+ setLogicalWidth(std::min(availableContentLogicalWidth, maxWidth));
}
// Ensure we aren't smaller than our min preferred width.
diff --git a/Source/WebCore/rendering/RenderTableCell.cpp b/Source/WebCore/rendering/RenderTableCell.cpp
index efd90c18c..35e5e0b88 100644
--- a/Source/WebCore/rendering/RenderTableCell.cpp
+++ b/Source/WebCore/rendering/RenderTableCell.cpp
@@ -404,6 +404,13 @@ LayoutUnit RenderTableCell::cellBaselinePosition() const
return firstLineBaseline().valueOr(borderAndPaddingBefore() + contentLogicalHeight());
}
+static inline void markCellDirtyWhenCollapsedBorderChanges(RenderTableCell* cell)
+{
+ if (!cell)
+ return;
+ cell->setNeedsLayoutAndPrefWidthsRecalc();
+}
+
void RenderTableCell::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
ASSERT(style().display() == TABLE_CELL);
@@ -422,8 +429,15 @@ void RenderTableCell::styleDidChange(StyleDifference diff, const RenderStyle* ol
// If border was changed, notify table.
RenderTable* table = this->table();
- if (table && oldStyle && oldStyle->border() != style().border())
+ if (table && oldStyle && oldStyle->border() != style().border()) {
table->invalidateCollapsedBorders(this);
+ if (table->collapseBorders() && diff == StyleDifferenceLayout) {
+ markCellDirtyWhenCollapsedBorderChanges(table->cellBelow(this));
+ markCellDirtyWhenCollapsedBorderChanges(table->cellAbove(this));
+ markCellDirtyWhenCollapsedBorderChanges(table->cellBefore(this));
+ markCellDirtyWhenCollapsedBorderChanges(table->cellAfter(this));
+ }
+ }
}
// The following rules apply for resolving conflicts and figuring out which border
diff --git a/Source/WebCore/rendering/RenderTableCell.h b/Source/WebCore/rendering/RenderTableCell.h
index bd69f09e3..17a0171a0 100644
--- a/Source/WebCore/rendering/RenderTableCell.h
+++ b/Source/WebCore/rendering/RenderTableCell.h
@@ -284,6 +284,8 @@ inline LayoutUnit RenderTableCell::logicalHeightForRowSizing() const
{
// FIXME: This function does too much work, and is very hot during table layout!
LayoutUnit adjustedLogicalHeight = logicalHeight() - (intrinsicPaddingBefore() + intrinsicPaddingAfter());
+ if (!style().logicalHeight().isSpecified())
+ return adjustedLogicalHeight;
LayoutUnit styleLogicalHeight = valueForLength(style().logicalHeight(), 0);
// In strict mode, box-sizing: content-box do the right thing and actually add in the border and padding.
// Call computedCSSPadding* directly to avoid including implicitPadding.
diff --git a/Source/WebCore/rendering/RenderTableSection.cpp b/Source/WebCore/rendering/RenderTableSection.cpp
index 1907657e9..7f9100b6e 100644
--- a/Source/WebCore/rendering/RenderTableSection.cpp
+++ b/Source/WebCore/rendering/RenderTableSection.cpp
@@ -251,6 +251,15 @@ void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row)
cell->setCol(table()->effColToCol(col));
}
+static LayoutUnit resolveLogicalHeightForRow(const Length& rowLogicalHeight)
+{
+ if (rowLogicalHeight.isFixed())
+ return rowLogicalHeight.value();
+ if (rowLogicalHeight.isCalculated())
+ return rowLogicalHeight.nonNanCalculatedValue(0);
+ return 0;
+}
+
LayoutUnit RenderTableSection::calcRowLogicalHeight()
{
#ifndef NDEBUG
@@ -278,7 +287,7 @@ LayoutUnit RenderTableSection::calcRowLogicalHeight()
LayoutUnit baselineDescent = 0;
// Our base size is the biggest logical height from our cells' styles (excluding row spanning cells).
- m_rowPos[r + 1] = std::max(m_rowPos[r] + minimumValueForLength(m_grid[r].logicalHeight, 0), LayoutUnit::fromPixel(0));
+ m_rowPos[r + 1] = std::max(m_rowPos[r] + resolveLogicalHeightForRow(m_grid[r].logicalHeight), LayoutUnit::fromPixel(0));
Row& row = m_grid[r].row;
unsigned totalCols = row.size();
@@ -372,6 +381,7 @@ void RenderTableSection::layout()
ASSERT(!needsCellRecalc());
ASSERT(!table()->needsSectionRecalc());
+ m_forceSlowPaintPathWithOverflowingCell = false;
// addChild may over-grow m_grid but we don't want to throw away the memory too early as addChild
// can be called in a loop (e.g during parsing). Doing it now ensures we have a stable-enough structure.
m_grid.shrinkToFit();
diff --git a/Source/WebCore/rendering/TableLayout.h b/Source/WebCore/rendering/TableLayout.h
index 23169aa65..6c0b32d24 100644
--- a/Source/WebCore/rendering/TableLayout.h
+++ b/Source/WebCore/rendering/TableLayout.h
@@ -21,6 +21,7 @@
#ifndef TableLayout_h
#define TableLayout_h
+#include "LayoutUnit.h"
#include <wtf/FastMalloc.h>
#include <wtf/Noncopyable.h>
@@ -39,6 +40,7 @@ public:
virtual ~TableLayout() { }
virtual void computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) = 0;
+ virtual LayoutUnit scaledWidthFromPercentColumns() const { return LayoutUnit(0); }
virtual void applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const = 0;
virtual void layout() = 0;
diff --git a/Source/WebCore/rendering/line/BreakingContext.h b/Source/WebCore/rendering/line/BreakingContext.h
index c1f947689..799d2c063 100644
--- a/Source/WebCore/rendering/line/BreakingContext.h
+++ b/Source/WebCore/rendering/line/BreakingContext.h
@@ -559,9 +559,9 @@ inline void BreakingContext::handleReplaced()
m_ignoringSpaces = true;
}
if (downcast<RenderListMarker>(*m_current.renderer()).isInside())
- m_width.addUncommittedReplacedWidth(replacedLogicalWidth);
+ m_width.addUncommittedWidth(replacedLogicalWidth);
} else
- m_width.addUncommittedReplacedWidth(replacedLogicalWidth);
+ m_width.addUncommittedWidth(replacedLogicalWidth);
if (is<RenderRubyRun>(*m_current.renderer())) {
m_width.applyOverhang(downcast<RenderRubyRun>(m_current.renderer()), m_lastObject, m_nextObject);
downcast<RenderRubyRun>(m_current.renderer())->updatePriorContextFromCachedBreakIterator(m_renderTextInfo.lineBreakIterator);
@@ -747,7 +747,7 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
float charWidth = 0;
bool breakNBSP = m_autoWrap && m_currentStyle->nbspMode() == SPACE;
// Auto-wrapping text should wrap in the middle of a word only if it could not wrap before the word,
- // which is only possible if the word is the first thing on the line, that is, if |w| is zero.
+ // which is only possible if the word is the first thing on the line.
bool breakWords = m_currentStyle->breakWords() && ((m_autoWrap && !m_width.hasCommitted()) || m_currWS == PRE);
bool midWordBreak = false;
bool breakAll = m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWrap;
diff --git a/Source/WebCore/rendering/line/LineWidth.cpp b/Source/WebCore/rendering/line/LineWidth.cpp
index f3b12b3ef..71e05cb23 100644
--- a/Source/WebCore/rendering/line/LineWidth.cpp
+++ b/Source/WebCore/rendering/line/LineWidth.cpp
@@ -37,14 +37,6 @@ namespace WebCore {
LineWidth::LineWidth(RenderBlockFlow& block, bool isFirstLine, IndentTextOrNot shouldIndentText)
: m_block(block)
- , m_uncommittedWidth(0)
- , m_committedWidth(0)
- , m_overhangWidth(0)
- , m_trailingWhitespaceWidth(0)
- , m_trailingCollapsedWhitespaceWidth(0)
- , m_left(0)
- , m_right(0)
- , m_availableWidth(0)
, m_isFirstLine(isFirstLine)
, m_shouldIndentText(shouldIndentText)
{
@@ -136,10 +128,7 @@ void LineWidth::commit()
{
m_committedWidth += m_uncommittedWidth;
m_uncommittedWidth = 0;
- if (m_hasUncommittedReplaced) {
- m_hasCommittedReplaced = true;
- m_hasUncommittedReplaced = false;
- }
+ m_hasCommitted = true;
}
void LineWidth::applyOverhang(RenderRubyRun* rubyRun, RenderObject* startRenderer, RenderObject* endRenderer)
diff --git a/Source/WebCore/rendering/line/LineWidth.h b/Source/WebCore/rendering/line/LineWidth.h
index 949d2c392..370b3a0f8 100644
--- a/Source/WebCore/rendering/line/LineWidth.h
+++ b/Source/WebCore/rendering/line/LineWidth.h
@@ -59,7 +59,7 @@ public:
float availableWidth() const { return m_availableWidth; }
float logicalLeftOffset() const { return m_left; }
- bool hasCommitted() const { return m_committedWidth > 0 || m_hasCommittedReplaced; }
+ bool hasCommitted() const { return m_hasCommitted; }
void updateAvailableWidth(LayoutUnit minimumHeight = 0);
void shrinkAvailableWidthForNewFloatIfNeeded(const FloatingObject&);
@@ -67,11 +67,6 @@ public:
{
m_uncommittedWidth += delta;
}
- void addUncommittedReplacedWidth(float delta)
- {
- addUncommittedWidth(delta);
- m_hasUncommittedReplaced = true;
- }
void commit();
void applyOverhang(RenderRubyRun*, RenderObject* startRenderer, RenderObject* endRenderer);
void fitBelowFloats(bool isFirstLine = false);
@@ -87,17 +82,16 @@ private:
#endif
RenderBlockFlow& m_block;
- float m_uncommittedWidth;
- float m_committedWidth;
- float m_overhangWidth; // The amount by which |m_availableWidth| has been inflated to account for possible contraction due to ruby overhang.
- float m_trailingWhitespaceWidth;
- float m_trailingCollapsedWhitespaceWidth;
- float m_left;
- float m_right;
- float m_availableWidth;
- bool m_isFirstLine;
- bool m_hasUncommittedReplaced { false };
- bool m_hasCommittedReplaced { false };
+ float m_uncommittedWidth { 0 };
+ float m_committedWidth { 0 };
+ float m_overhangWidth { 0 }; // The amount by which |m_availableWidth| has been inflated to account for possible contraction due to ruby overhang.
+ float m_trailingWhitespaceWidth { 0 };
+ float m_trailingCollapsedWhitespaceWidth { 0 };
+ float m_left { 0 };
+ float m_right { 0 };
+ float m_availableWidth { 0 };
+ bool m_isFirstLine { true };
+ bool m_hasCommitted { false };
IndentTextOrNot m_shouldIndentText;
};
diff --git a/Source/WebCore/rendering/style/RenderStyle.cpp b/Source/WebCore/rendering/style/RenderStyle.cpp
index ebd4c9142..39c43ee15 100644
--- a/Source/WebCore/rendering/style/RenderStyle.cpp
+++ b/Source/WebCore/rendering/style/RenderStyle.cpp
@@ -811,6 +811,7 @@ bool RenderStyle::changeRequiresRepaint(const RenderStyle& other, unsigned& chan
|| rareNonInheritedData->userDrag != other.rareNonInheritedData->userDrag
|| rareNonInheritedData->m_borderFit != other.rareNonInheritedData->m_borderFit
|| rareNonInheritedData->m_objectFit != other.rareNonInheritedData->m_objectFit
+ || rareNonInheritedData->m_objectPosition != other.rareNonInheritedData->m_objectPosition
|| rareInheritedData->m_imageRendering != other.rareInheritedData->m_imageRendering)
return true;
diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h
index 559df8182..7f84a0754 100644
--- a/Source/WebCore/rendering/style/RenderStyle.h
+++ b/Source/WebCore/rendering/style/RenderStyle.h
@@ -40,6 +40,7 @@
#include "Length.h"
#include "LengthBox.h"
#include "LengthFunctions.h"
+#include "LengthPoint.h"
#include "LengthSize.h"
#include "LineClampValue.h"
#include "NinePieceImage.h"
@@ -1035,8 +1036,9 @@ public:
TextOrientation textOrientation() const { return static_cast<TextOrientation>(rareInheritedData->m_textOrientation); }
ObjectFit objectFit() const { return static_cast<ObjectFit>(rareNonInheritedData->m_objectFit); }
-
- // Return true if any transform related property (currently transform, transformStyle3D or perspective)
+ LengthPoint objectPosition() const { return rareNonInheritedData->m_objectPosition; }
+
+ // Return true if any transform related property (currently transform, transformStyle3D or perspective)
// indicates that we are transforming
bool hasTransformRelatedProperty() const { return hasTransform() || preserves3D() || hasPerspective(); }
@@ -1606,6 +1608,7 @@ public:
bool setTextOrientation(TextOrientation);
void setObjectFit(ObjectFit fit) { SET_VAR(rareNonInheritedData, m_objectFit, fit); }
+ void setObjectPosition(const LengthPoint& position) { SET_VAR(rareNonInheritedData, m_objectPosition, position); }
void setRubyPosition(RubyPosition position) { SET_VAR(rareInheritedData, m_rubyPosition, position); }
@@ -1896,6 +1899,7 @@ public:
static TextOrientation initialTextOrientation() { return TextOrientation::
Mixed; }
static ObjectFit initialObjectFit() { return ObjectFitFill; }
+ static LengthPoint initialObjectPosition() { return LengthPoint(Length(50.0f, Percent), Length(50.0f, Percent)); }
static EEmptyCell initialEmptyCells() { return SHOW; }
static EListStylePosition initialListStylePosition() { return OUTSIDE; }
static EListStyleType initialListStyleType() { return Disc; }
diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
index 24ae59cf2..120bd5f5a 100644
--- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
+++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
@@ -63,6 +63,7 @@ StyleRareNonInheritedData::StyleRareNonInheritedData()
#endif
, m_willChange(RenderStyle::initialWillChange())
, m_mask(FillLayer(MaskFillLayer))
+ , m_objectPosition(RenderStyle::initialObjectPosition())
#if ENABLE(CSS_SHAPES)
, m_shapeOutside(RenderStyle::initialShapeOutside())
, m_shapeMargin(RenderStyle::initialShapeMargin())
@@ -149,6 +150,7 @@ inline StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonIn
, m_mask(o.m_mask)
, m_maskBoxImage(o.m_maskBoxImage)
, m_pageSize(o.m_pageSize)
+ , m_objectPosition(o.m_objectPosition)
#if ENABLE(CSS_SHAPES)
, m_shapeOutside(o.m_shapeOutside)
, m_shapeMargin(o.m_shapeMargin)
@@ -253,6 +255,7 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
&& m_mask == o.m_mask
&& m_maskBoxImage == o.m_maskBoxImage
&& m_pageSize == o.m_pageSize
+ && m_objectPosition == o.m_objectPosition
#if ENABLE(CSS_SHAPES)
&& arePointingToEqualData(m_shapeOutside, o.m_shapeOutside)
&& m_shapeMargin == o.m_shapeMargin
diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
index 9b1b2ad53..069b92878 100644
--- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
+++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
@@ -32,6 +32,7 @@
#include "CursorData.h"
#include "DataRef.h"
#include "FillLayer.h"
+#include "LengthPoint.h"
#include "LineClampValue.h"
#include "NinePieceImage.h"
#include "ShapeValue.h"
@@ -154,6 +155,7 @@ public:
NinePieceImage m_maskBoxImage;
LengthSize m_pageSize;
+ LengthPoint m_objectPosition;
#if ENABLE(CSS_SHAPES)
RefPtr<ShapeValue> m_shapeOutside;
diff --git a/Source/WebCore/rendering/style/StyleScrollSnapPoints.cpp b/Source/WebCore/rendering/style/StyleScrollSnapPoints.cpp
index 8d8858f84..854c3e25f 100644
--- a/Source/WebCore/rendering/style/StyleScrollSnapPoints.cpp
+++ b/Source/WebCore/rendering/style/StyleScrollSnapPoints.cpp
@@ -31,8 +31,8 @@
namespace WebCore {
ScrollSnapPoints::ScrollSnapPoints()
- : repeatOffset(100, Percent)
- , hasRepeat(true)
+ : repeatOffset(0, Fixed)
+ , hasRepeat(false)
, usesElements(false)
{
}
diff --git a/Source/WebCore/rendering/style/WillChangeData.cpp b/Source/WebCore/rendering/style/WillChangeData.cpp
index 77d4aa871..cff2e7cd3 100644
--- a/Source/WebCore/rendering/style/WillChangeData.cpp
+++ b/Source/WebCore/rendering/style/WillChangeData.cpp
@@ -99,6 +99,30 @@ static bool propertyCreatesStackingContext(CSSPropertyID property)
}
}
+static bool propertyCreatesGraphicalGroup(CSSPropertyID property)
+{
+ switch (property) {
+ case CSSPropertyClipPath:
+ case CSSPropertyWebkitClipPath:
+ case CSSPropertyMask:
+ case CSSPropertyOpacity:
+#if ENABLE(CSS_COMPOSITING)
+ case CSSPropertyMixBlendMode:
+ case CSSPropertyIsolation:
+#endif
+ case CSSPropertyFilter:
+#if ENABLE(FILTERS_LEVEL_2)
+ case CSSPropertyWebkitBackdropFilter:
+#endif
+ case CSSPropertyWebkitMask:
+ case CSSPropertyWebkitMaskImage:
+ case CSSPropertyWebkitMaskBoxImage:
+ return true;
+ default:
+ return false;
+ }
+}
+
static bool propertyTriggersCompositing(CSSPropertyID property)
{
switch (property) {
@@ -137,6 +161,8 @@ void WillChangeData::addFeature(Feature feature, CSSPropertyID propertyID)
m_canTriggerCompositingOnInline |= propertyTriggersCompositing(propertyID);
m_canTriggerCompositing |= m_canTriggerCompositingOnInline | propertyTriggersCompositingOnBoxesOnly(propertyID);
+
+ m_canCreateGraphicalGroup |= propertyCreatesGraphicalGroup(propertyID);
}
WillChangeData::FeaturePropertyPair WillChangeData::featureAt(size_t index) const
diff --git a/Source/WebCore/rendering/style/WillChangeData.h b/Source/WebCore/rendering/style/WillChangeData.h
index 49e76089d..6bab28da6 100644
--- a/Source/WebCore/rendering/style/WillChangeData.h
+++ b/Source/WebCore/rendering/style/WillChangeData.h
@@ -57,6 +57,7 @@ public:
bool canCreateStackingContext() const { return m_canCreateStackingContext; }
bool canTriggerCompositing() const { return m_canTriggerCompositing; }
bool canTriggerCompositingOnInline() const { return m_canTriggerCompositingOnInline; }
+ bool canCreateGraphicalGroup() const { return m_canCreateGraphicalGroup; }
enum Feature {
ScrollPosition,
@@ -124,6 +125,7 @@ private:
bool m_canCreateStackingContext { false };
bool m_canTriggerCompositing { false };
bool m_canTriggerCompositingOnInline { false };
+ bool m_canCreateGraphicalGroup { false };
};