summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering')
-rwxr-xr-xSource/WebCore/rendering/RenderBlock.cpp10
-rw-r--r--Source/WebCore/rendering/RenderBox.cpp49
-rw-r--r--Source/WebCore/rendering/RenderBox.h3
-rw-r--r--Source/WebCore/rendering/RenderBoxModelObject.cpp51
-rw-r--r--Source/WebCore/rendering/RenderBoxModelObject.h4
-rw-r--r--Source/WebCore/rendering/RenderFlexibleBox.cpp34
-rw-r--r--Source/WebCore/rendering/RenderFlexibleBox.h6
-rw-r--r--Source/WebCore/rendering/RenderGeometryMap.cpp270
-rw-r--r--Source/WebCore/rendering/RenderGeometryMap.h85
-rw-r--r--Source/WebCore/rendering/RenderInline.cpp39
-rw-r--r--Source/WebCore/rendering/RenderInline.h3
-rw-r--r--Source/WebCore/rendering/RenderLayer.cpp136
-rw-r--r--Source/WebCore/rendering/RenderLayer.h108
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.cpp15
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.h2
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.cpp62
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.h7
-rw-r--r--Source/WebCore/rendering/RenderMediaControlsChromium.cpp49
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnBlock.cpp18
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnBlock.h8
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp4
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnFlowThread.h3
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnSet.h2
-rwxr-xr-xSource/WebCore/rendering/RenderObject.cpp56
-rw-r--r--Source/WebCore/rendering/RenderObject.h12
-rw-r--r--Source/WebCore/rendering/RenderTableCell.cpp4
-rw-r--r--Source/WebCore/rendering/RenderTableCell.h2
-rw-r--r--Source/WebCore/rendering/RenderTableSection.cpp2
-rw-r--r--Source/WebCore/rendering/RenderTreeAsText.cpp2
-rw-r--r--Source/WebCore/rendering/RenderView.cpp26
-rw-r--r--Source/WebCore/rendering/RenderView.h1
-rw-r--r--Source/WebCore/rendering/RenderingAllInOne.cpp2
-rw-r--r--Source/WebCore/rendering/style/RenderStyleConstants.h4
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGBlock.cpp6
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGBlock.h1
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGContainer.cpp13
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGContainer.h2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp5
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGForeignObject.h1
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInline.cpp15
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInline.h4
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGModelObject.cpp11
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGModelObject.h2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGRoot.cpp17
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGRoot.h5
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGText.cpp9
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGText.h1
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderSupport.cpp18
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderSupport.h2
-rw-r--r--Source/WebCore/rendering/svg/SVGResourcesCache.cpp28
-rw-r--r--Source/WebCore/rendering/svg/SVGResourcesCache.h14
52 files changed, 939 insertions, 296 deletions
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp
index 15867e1c6..e6a73d9a4 100755
--- a/Source/WebCore/rendering/RenderBlock.cpp
+++ b/Source/WebCore/rendering/RenderBlock.cpp
@@ -2015,16 +2015,6 @@ LayoutUnit RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo
logicalTop = min(logicalTop, nextPageLogicalTop(beforeCollapseLogicalTop));
setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop));
}
-
- // If we have collapsed into a previous sibling and so reduced the height of the parent, ensure any floats that now
- // overhang from the previous sibling are added to our parent
- RenderObject* prev = child->previousSibling();
- if (prev && prev->isRenderBlock()) {
- RenderBlock* block = toRenderBlock(prev);
- if (block->m_floatingObjects && block->lowestFloatLogicalBottom() > logicalTop)
- addOverhangingFloats(block, false);
- }
-
return logicalTop;
}
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp
index 565e3c96b..04ff3dbe3 100644
--- a/Source/WebCore/rendering/RenderBox.cpp
+++ b/Source/WebCore/rendering/RenderBox.cpp
@@ -44,6 +44,7 @@
#include "RenderBoxRegionInfo.h"
#include "RenderFlexibleBox.h"
#include "RenderFlowThread.h"
+#include "RenderGeometryMap.h"
#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderPart.h"
@@ -437,6 +438,7 @@ void RenderBox::updateLayerTransform()
IntRect RenderBox::absoluteContentBox() const
{
+ // This is wrong with transforms and flipped writing modes.
IntRect rect = pixelSnappedIntRect(contentBoxRect());
FloatPoint absPos = localToAbsolute(FloatPoint());
rect.move(absPos.x(), absPos.y());
@@ -1315,6 +1317,46 @@ void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool
o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, DoNotApplyContainerFlip, wasFixed);
}
+const RenderObject* RenderBox::pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+ ASSERT(ancestorToStopAt != this);
+
+ bool ancestorSkipped;
+ RenderObject* container = this->container(ancestorToStopAt, &ancestorSkipped);
+ if (!container)
+ return 0;
+
+ bool isFixedPos = style()->position() == FixedPosition;
+ bool hasTransform = hasLayer() && layer()->transform();
+
+ LayoutSize adjustmentForSkippedAncestor;
+ if (ancestorSkipped) {
+ // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
+ // to just subtract the delta between the ancestor and o.
+ adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(container);
+ }
+
+ bool offsetDependsOnPoint = false;
+ LayoutSize containerOffset = offsetFromContainer(container, LayoutPoint(), &offsetDependsOnPoint);
+
+ if (container->isRenderFlowThread())
+ offsetDependsOnPoint = true;
+
+ bool preserve3D = container->style()->preserves3D() || style()->preserves3D();
+ if (shouldUseTransformFromContainer(container)) {
+ TransformationMatrix t;
+ getTransformFromContainer(container, containerOffset, t);
+ t.translateRight(adjustmentForSkippedAncestor.width(), adjustmentForSkippedAncestor.height());
+
+ geometryMap.push(this, t, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform);
+ } else {
+ containerOffset += adjustmentForSkippedAncestor;
+ geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform);
+ }
+
+ return ancestorSkipped ? ancestorToStopAt : container;
+}
+
void RenderBox::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const
{
// We don't expect absoluteToLocal() to be called during layout (yet)
@@ -1332,7 +1374,7 @@ void RenderBox::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, Transfor
RenderBoxModelObject::mapAbsoluteToLocalPoint(fixed, useTransforms, transformState);
}
-LayoutSize RenderBox::offsetFromContainer(RenderObject* o, const LayoutPoint& point) const
+LayoutSize RenderBox::offsetFromContainer(RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
{
ASSERT(o == container());
@@ -1350,6 +1392,9 @@ LayoutSize RenderBox::offsetFromContainer(RenderObject* o, const LayoutPoint& po
offset = toLayoutSize(block->flipForWritingModeIncludingColumns(toLayoutPoint(offset)));
o->adjustForColumns(offset, columnPoint);
offset = block->flipForWritingMode(offset);
+
+ if (offsetDependsOnPoint)
+ *offsetDependsOnPoint = true;
} else
offset += topLeftLocationOffset();
}
@@ -3766,7 +3811,7 @@ LayoutRect RenderBox::layoutOverflowRectForPropagation(RenderStyle* parentStyle)
rect = layer()->currentTransform().mapRect(rect);
if (isRelPositioned())
- rect.move(relativePositionOffsetX(), relativePositionOffsetY());
+ rect.move(relativePositionOffset());
// Now we need to flip back.
flipForWritingMode(rect);
diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h
index 9ff60e672..c3696ab8d 100644
--- a/Source/WebCore/rendering/RenderBox.h
+++ b/Source/WebCore/rendering/RenderBox.h
@@ -276,7 +276,7 @@ public:
void setOverrideWidth(LayoutUnit);
void clearOverrideSize();
- virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&) const;
+ virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
LayoutUnit computeBorderBoxLogicalWidth(LayoutUnit width) const;
LayoutUnit computeBorderBoxLogicalHeight(LayoutUnit height) const;
@@ -519,6 +519,7 @@ protected:
virtual bool shouldComputeSizeAsReplaced() const { return isReplaced() && !isInlineBlockOrInlineTable(); }
virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
+ virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject*, RenderGeometryMap&) const;
virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const;
void paintRootBoxFillLayers(const PaintInfo&);
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.cpp b/Source/WebCore/rendering/RenderBoxModelObject.cpp
index f5b6500e5..1625f075b 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.cpp
+++ b/Source/WebCore/rendering/RenderBoxModelObject.cpp
@@ -345,10 +345,6 @@ void RenderBoxModelObject::destroyLayer()
void RenderBoxModelObject::willBeDestroyed()
{
- // This must be done before we destroy the RenderObject.
- if (m_layer)
- m_layer->clearClipRects();
-
// A continuation of this RenderObject should be destroyed at subclasses.
ASSERT(!continuation());
@@ -463,48 +459,41 @@ void RenderBoxModelObject::updateBoxModelInfoFromStyle()
setHorizontalWritingMode(styleToUse->isHorizontalWritingMode());
}
-enum RelPosAxis { RelPosX, RelPosY };
-
-static LayoutUnit accumulateRelativePositionOffsets(const RenderObject* child, RelPosAxis axis)
+static LayoutSize accumulateRelativePositionOffsets(const RenderObject* child)
{
if (!child->isAnonymousBlock() || !child->isRelPositioned())
- return 0;
- LayoutUnit offset = ZERO_LAYOUT_UNIT;
+ return LayoutSize();
+ LayoutSize offset;
RenderObject* p = toRenderBlock(child)->inlineElementContinuation();
while (p && p->isRenderInline()) {
- if (p->isRelPositioned())
- offset += (axis == RelPosX) ? toRenderInline(p)->relativePositionOffsetX() : toRenderInline(p)->relativePositionOffsetY();
+ if (p->isRelPositioned()) {
+ RenderInline* renderInline = toRenderInline(p);
+ offset += renderInline->relativePositionOffset();
+ }
p = p->parent();
}
return offset;
}
-LayoutUnit RenderBoxModelObject::relativePositionOffsetX() const
+LayoutSize RenderBoxModelObject::relativePositionOffset() const
{
- LayoutUnit offset = accumulateRelativePositionOffsets(this, RelPosX);
+ LayoutSize offset = accumulateRelativePositionOffsets(this);
+
+ RenderBlock* containingBlock = this->containingBlock();
// Objects that shrink to avoid floats normally use available line width when computing containing block width. However
// in the case of relative positioning using percentages, we can't do this. The offset should always be resolved using the
// available width of the containing block. Therefore we don't use containingBlockLogicalWidthForContent() here, but instead explicitly
// call availableWidth on our containing block.
if (!style()->left().isAuto()) {
- RenderBlock* cb = containingBlock();
- if (!style()->right().isAuto() && !cb->style()->isLeftToRightDirection())
- return -valueForLength(style()->right(), cb->availableWidth(), view());
- return offset + valueForLength(style()->left(), cb->availableWidth(), view());
- }
- if (!style()->right().isAuto()) {
- RenderBlock* cb = containingBlock();
- return offset + -valueForLength(style()->right(), cb->availableWidth(), view());
+ if (!style()->right().isAuto() && !containingBlock->style()->isLeftToRightDirection())
+ offset.setWidth(-valueForLength(style()->right(), containingBlock->availableWidth(), view()));
+ else
+ offset.expand(valueForLength(style()->left(), containingBlock->availableWidth(), view()), 0);
+ } else if (!style()->right().isAuto()) {
+ offset.expand(-valueForLength(style()->right(), containingBlock->availableWidth(), view()), 0);
}
- return offset;
-}
-LayoutUnit RenderBoxModelObject::relativePositionOffsetY() const
-{
- LayoutUnit offset = accumulateRelativePositionOffsets(this, RelPosY);
-
- RenderBlock* containingBlock = this->containingBlock();
// If the containing block of a relatively positioned element does not
// specify a height, a percentage top or bottom offset should be resolved as
// auto. An exception to this is if the containing block has the WinIE quirk
@@ -515,13 +504,13 @@ LayoutUnit RenderBoxModelObject::relativePositionOffsetY() const
&& (!containingBlock->style()->height().isAuto()
|| !style()->top().isPercent()
|| containingBlock->stretchesToViewport()))
- return offset + valueForLength(style()->top(), containingBlock->availableHeight(), view());
+ offset.expand(0, valueForLength(style()->top(), containingBlock->availableHeight(), view()));
- if (!style()->bottom().isAuto()
+ else if (!style()->bottom().isAuto()
&& (!containingBlock->style()->height().isAuto()
|| !style()->bottom().isPercent()
|| containingBlock->stretchesToViewport()))
- return offset + -valueForLength(style()->bottom(), containingBlock->availableHeight(), view());
+ offset.expand(0, -valueForLength(style()->bottom(), containingBlock->availableHeight(), view()));
return offset;
}
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.h b/Source/WebCore/rendering/RenderBoxModelObject.h
index b145e6f71..5e2f26b5b 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.h
+++ b/Source/WebCore/rendering/RenderBoxModelObject.h
@@ -58,9 +58,7 @@ public:
RenderBoxModelObject(Node*);
virtual ~RenderBoxModelObject();
- LayoutUnit relativePositionOffsetX() const;
- LayoutUnit relativePositionOffsetY() const;
- LayoutSize relativePositionOffset() const { return LayoutSize(relativePositionOffsetX(), relativePositionOffsetY()); }
+ LayoutSize relativePositionOffset() const;
LayoutSize relativePositionLogicalOffset() const { return style()->isHorizontalWritingMode() ? relativePositionOffset() : relativePositionOffset().transposedSize(); }
// IE extensions. Used to calculate offsetWidth/Height. Overridden by inlines (RenderFlow)
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp
index 2feab4f75..8f0997b85 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.cpp
+++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp
@@ -35,6 +35,7 @@
#include "RenderLayer.h"
#include "RenderView.h"
#include <limits>
+#include <wtf/MathExtras.h>
namespace WebCore {
@@ -593,7 +594,7 @@ LayoutUnit RenderFlexibleBox::preferredMainAxisContentExtentForChild(RenderBox*
LayoutUnit mainAxisExtent = hasOrthogonalFlow(child) ? child->logicalHeight() : child->maxPreferredLogicalWidth();
return mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child);
}
- return minimumValueForLength(mainAxisLength, mainAxisContentExtent(), view());
+ return std::max(LayoutUnit(0), minimumValueForLength(mainAxisLength, mainAxisContentExtent(), view()));
}
LayoutUnit RenderFlexibleBox::computeAvailableFreeSpace(LayoutUnit preferredMainAxisExtent)
@@ -624,17 +625,17 @@ void RenderFlexibleBox::layoutFlexItems(FlexOrderIterator& iterator, WTF::Vector
OrderedFlexItemList orderedChildren;
LayoutUnit preferredMainAxisExtent;
float totalPositiveFlexibility;
- float totalNegativeFlexibility;
+ float totalWeightedNegativeFlexibility;
LayoutUnit minMaxAppliedMainAxisExtent;
LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore();
- while (computeNextFlexLine(iterator, orderedChildren, preferredMainAxisExtent, totalPositiveFlexibility, totalNegativeFlexibility, minMaxAppliedMainAxisExtent)) {
+ while (computeNextFlexLine(iterator, orderedChildren, preferredMainAxisExtent, totalPositiveFlexibility, totalWeightedNegativeFlexibility, minMaxAppliedMainAxisExtent)) {
LayoutUnit availableFreeSpace = computeAvailableFreeSpace(preferredMainAxisExtent);
FlexSign flexSign = (minMaxAppliedMainAxisExtent < preferredMainAxisExtent + availableFreeSpace) ? PositiveFlexibility : NegativeFlexibility;
InflexibleFlexItemSize inflexibleItems;
WTF::Vector<LayoutUnit> childSizes;
- while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, totalPositiveFlexibility, totalNegativeFlexibility, inflexibleItems, childSizes)) {
- ASSERT(totalPositiveFlexibility >= 0 && totalNegativeFlexibility >= 0);
+ while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, totalPositiveFlexibility, totalWeightedNegativeFlexibility, inflexibleItems, childSizes)) {
+ ASSERT(totalPositiveFlexibility >= 0 && totalWeightedNegativeFlexibility >= 0);
ASSERT(inflexibleItems.size() > 0);
}
@@ -800,11 +801,11 @@ LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox* child, Layo
return childSize;
}
-bool RenderFlexibleBox::computeNextFlexLine(FlexOrderIterator& iterator, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalNegativeFlexibility, LayoutUnit& minMaxAppliedMainAxisExtent)
+bool RenderFlexibleBox::computeNextFlexLine(FlexOrderIterator& iterator, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, LayoutUnit& minMaxAppliedMainAxisExtent)
{
orderedChildren.clear();
preferredMainAxisExtent = 0;
- totalPositiveFlexibility = totalNegativeFlexibility = 0;
+ totalPositiveFlexibility = totalWeightedNegativeFlexibility = 0;
minMaxAppliedMainAxisExtent = 0;
if (!iterator.currentChild())
@@ -828,7 +829,7 @@ bool RenderFlexibleBox::computeNextFlexLine(FlexOrderIterator& iterator, Ordered
orderedChildren.append(child);
preferredMainAxisExtent += childMainAxisMarginBoxExtent;
totalPositiveFlexibility += child->style()->positiveFlex();
- totalNegativeFlexibility += child->style()->negativeFlex();
+ totalWeightedNegativeFlexibility += child->style()->negativeFlex() * childMainAxisExtent;
LayoutUnit childMinMaxAppliedMainAxisExtent = adjustChildSizeForMinAndMax(child, childMainAxisExtent, flexboxAvailableContentExtent);
minMaxAppliedMainAxisExtent += childMinMaxAppliedMainAxisExtent - childMainAxisExtent + childMainAxisMarginBoxExtent;
@@ -836,20 +837,21 @@ bool RenderFlexibleBox::computeNextFlexLine(FlexOrderIterator& iterator, Ordered
return true;
}
-void RenderFlexibleBox::freezeViolations(const WTF::Vector<Violation>& violations, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems)
+void RenderFlexibleBox::freezeViolations(const WTF::Vector<Violation>& violations, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems)
{
for (size_t i = 0; i < violations.size(); ++i) {
RenderBox* child = violations[i].child;
LayoutUnit childSize = violations[i].childSize;
- availableFreeSpace -= childSize - preferredMainAxisContentExtentForChild(child);
+ LayoutUnit preferredChildSize = preferredMainAxisContentExtentForChild(child);
+ availableFreeSpace -= childSize - preferredChildSize;
totalPositiveFlexibility -= child->style()->positiveFlex();
- totalNegativeFlexibility -= child->style()->negativeFlex();
+ totalWeightedNegativeFlexibility -= child->style()->negativeFlex() * preferredChildSize;
inflexibleItems.set(child, childSize);
}
}
// Returns true if we successfully ran the algorithm and sized the flex items.
-bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems, WTF::Vector<LayoutUnit>& childSizes)
+bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems, WTF::Vector<LayoutUnit>& childSizes)
{
childSizes.clear();
LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent();
@@ -869,10 +871,10 @@ bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedF
else {
LayoutUnit preferredChildSize = preferredMainAxisContentExtentForChild(child);
LayoutUnit childSize = preferredChildSize;
- if (availableFreeSpace > 0 && totalPositiveFlexibility > 0 && flexSign == PositiveFlexibility)
+ if (availableFreeSpace > 0 && totalPositiveFlexibility > 0 && flexSign == PositiveFlexibility && isfinite(totalPositiveFlexibility))
childSize += lroundf(availableFreeSpace * child->style()->positiveFlex() / totalPositiveFlexibility);
- else if (availableFreeSpace < 0 && totalNegativeFlexibility > 0 && flexSign == NegativeFlexibility)
- childSize += lroundf(availableFreeSpace * child->style()->negativeFlex() / totalNegativeFlexibility);
+ else if (availableFreeSpace < 0 && totalWeightedNegativeFlexibility > 0 && flexSign == NegativeFlexibility && isfinite(totalWeightedNegativeFlexibility))
+ childSize += lroundf(availableFreeSpace * child->style()->negativeFlex() * preferredChildSize / totalWeightedNegativeFlexibility);
LayoutUnit adjustedChildSize = adjustChildSizeForMinAndMax(child, childSize, flexboxAvailableContentExtent);
childSizes.append(adjustedChildSize);
@@ -888,7 +890,7 @@ bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedF
}
if (totalViolation)
- freezeViolations(totalViolation < 0 ? maxViolations : minViolations, availableFreeSpace, totalPositiveFlexibility, totalNegativeFlexibility, inflexibleItems);
+ freezeViolations(totalViolation < 0 ? maxViolations : minViolations, availableFreeSpace, totalPositiveFlexibility, totalWeightedNegativeFlexibility, inflexibleItems);
else
availableFreeSpace -= usedFreeSpace;
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.h b/Source/WebCore/rendering/RenderFlexibleBox.h
index 8383a46b8..ae61d631f 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.h
+++ b/Source/WebCore/rendering/RenderFlexibleBox.h
@@ -113,11 +113,11 @@ private:
void computeMainAxisPreferredSizes(bool relayoutChildren, FlexOrderHashSet&);
LayoutUnit lineBreakLength();
LayoutUnit adjustChildSizeForMinAndMax(RenderBox*, LayoutUnit childSize, LayoutUnit flexboxAvailableContentExtent);
- bool computeNextFlexLine(FlexOrderIterator&, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalNegativeFlexibility, LayoutUnit& minMaxAppliedMainAxisExtent);
+ bool computeNextFlexLine(FlexOrderIterator&, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, LayoutUnit& minMaxAppliedMainAxisExtent);
LayoutUnit computeAvailableFreeSpace(LayoutUnit preferredMainAxisExtent);
- bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize&, WTF::Vector<LayoutUnit>& childSizes);
- void freezeViolations(const WTF::Vector<Violation>&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize&);
+ bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, InflexibleFlexItemSize&, WTF::Vector<LayoutUnit>& childSizes);
+ void freezeViolations(const WTF::Vector<Violation>&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, InflexibleFlexItemSize&);
void setLogicalOverrideSize(RenderBox* child, LayoutUnit childPreferredSize);
void prepareChildForPositionedLayout(RenderBox* child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset);
diff --git a/Source/WebCore/rendering/RenderGeometryMap.cpp b/Source/WebCore/rendering/RenderGeometryMap.cpp
new file mode 100644
index 000000000..65f189bb1
--- /dev/null
+++ b/Source/WebCore/rendering/RenderGeometryMap.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderGeometryMap.h"
+
+#include "RenderView.h"
+#include "TransformState.h"
+
+namespace WebCore {
+
+
+// Stores data about how to map from one renderer to its container.
+class RenderGeometryMapStep {
+ WTF_MAKE_NONCOPYABLE(RenderGeometryMapStep);
+public:
+ RenderGeometryMapStep(const RenderObject* renderer, bool accumulatingTransform, bool isNonUniform, bool isFixedPosition, bool hasTransform)
+ : m_renderer(renderer)
+ , m_accumulatingTransform(accumulatingTransform)
+ , m_isNonUniform(isNonUniform)
+ , m_isFixedPosition(isFixedPosition)
+ , m_hasTransform(hasTransform)
+ {
+ }
+
+ FloatPoint mapPoint(const FloatPoint& p) const
+ {
+ if (!m_transform)
+ return p + m_offset;
+
+ return m_transform->mapPoint(p);
+ }
+
+ FloatQuad mapQuad(const FloatQuad& quad) const
+ {
+ if (!m_transform) {
+ FloatQuad q = quad;
+ q.move(m_offset);
+ return q;
+ }
+
+ return m_transform->mapQuad(quad);
+ }
+
+ const RenderObject* m_renderer;
+ LayoutSize m_offset;
+ OwnPtr<TransformationMatrix> m_transform; // Includes offset if non-null.
+ bool m_accumulatingTransform;
+ bool m_isNonUniform; // Mapping depends on the input point, e.g. because of CSS columns.
+ bool m_isFixedPosition;
+ bool m_hasTransform;
+};
+
+
+RenderGeometryMap::RenderGeometryMap()
+ : m_insertionPosition(notFound)
+ , m_nonUniformStepsCount(0)
+ , m_transformedStepsCount(0)
+ , m_fixedStepsCount(0)
+{
+}
+
+RenderGeometryMap::~RenderGeometryMap()
+{
+}
+
+FloatPoint RenderGeometryMap::absolutePoint(const FloatPoint& p) const
+{
+ FloatPoint result;
+
+ if (!hasFixedPositionStep() && !hasTransformStep() && !hasNonUniformStep())
+ result = p + m_accumulatedOffset;
+ else {
+ TransformState transformState(TransformState::ApplyTransformDirection, p);
+ mapToAbsolute(transformState);
+ result = transformState.lastPlanarPoint();
+ }
+
+#if !ASSERT_DISABLED
+ FloatPoint rendererMappedResult = m_mapping.last()->m_renderer->localToAbsolute(p, false, true);
+ ASSERT(rendererMappedResult == result);
+#endif
+
+ return result;
+}
+
+FloatRect RenderGeometryMap::absoluteRect(const FloatRect& rect) const
+{
+ FloatRect result;
+
+ if (!hasFixedPositionStep() && !hasTransformStep() && !hasNonUniformStep()) {
+ result = rect;
+ result.move(m_accumulatedOffset);
+ } else {
+ TransformState transformState(TransformState::ApplyTransformDirection, rect.center(), rect);
+ mapToAbsolute(transformState);
+ result = transformState.lastPlanarQuad().boundingBox();
+ }
+
+#if !ASSERT_DISABLED
+ FloatRect rendererMappedResult = m_mapping.last()->m_renderer->localToAbsoluteQuad(rect).boundingBox();
+ // Inspector creates renderers with negative width <https://bugs.webkit.org/show_bug.cgi?id=87194>.
+ // Taking FloatQuad bounds avoids spurious assertions because of that.
+ ASSERT(enclosingIntRect(rendererMappedResult) == enclosingIntRect(FloatQuad(result).boundingBox()));
+#endif
+
+ return result;
+}
+
+void RenderGeometryMap::mapToAbsolute(TransformState& transformState) const
+{
+ // If the mapping includes something like columns, we have to go via renderers.
+ if (hasNonUniformStep()) {
+ bool fixed = false;
+ m_mapping.last()->m_renderer->mapLocalToContainer(0, fixed, true, transformState, RenderObject::ApplyContainerFlip);
+ return;
+ }
+
+ bool inFixed = false;
+
+ for (int i = m_mapping.size() - 1; i >= 0; --i) {
+ const RenderGeometryMapStep* currStep = m_mapping[i].get();
+
+ if (currStep->m_hasTransform) {
+ // If this box has a transform, it acts as a fixed position container for fixed descendants,
+ // and may itself also be fixed position. So propagate 'fixed' up only if this box is fixed position.
+ inFixed &= currStep->m_isFixedPosition;
+ } else
+ inFixed |= currStep->m_isFixedPosition;
+
+ if (!i) {
+ if (currStep->m_transform)
+ transformState.applyTransform(*currStep->m_transform.get());
+
+ // The root gets special treatment for fixed position
+ if (inFixed)
+ transformState.move(currStep->m_offset.width(), currStep->m_offset.height());
+ } else {
+ TransformState::TransformAccumulation accumulate = currStep->m_accumulatingTransform ? TransformState::AccumulateTransform : TransformState::FlattenTransform;
+ if (currStep->m_transform)
+ transformState.applyTransform(*currStep->m_transform.get(), accumulate);
+ else
+ transformState.move(currStep->m_offset.width(), currStep->m_offset.height(), accumulate);
+ }
+ }
+
+ transformState.flatten();
+}
+
+void RenderGeometryMap::pushMappingsToAncestor(const RenderObject* renderer, const RenderBoxModelObject* ancestor)
+{
+ const RenderObject* currRenderer = renderer;
+
+ // We need to push mappings in reverse order here, so do insertions rather than appends.
+ m_insertionPosition = m_mapping.size();
+
+ do {
+ currRenderer = currRenderer->pushMappingToContainer(ancestor, *this);
+ } while (currRenderer && currRenderer != ancestor);
+
+ m_insertionPosition = notFound;
+}
+
+void RenderGeometryMap::push(const RenderObject* renderer, const LayoutSize& offsetFromContainer, bool accumulatingTransform, bool isNonUniform, bool isFixedPosition, bool hasTransform)
+{
+ ASSERT(m_insertionPosition != notFound);
+
+ OwnPtr<RenderGeometryMapStep> step = adoptPtr(new RenderGeometryMapStep(renderer, accumulatingTransform, isNonUniform, isFixedPosition, hasTransform));
+ step->m_offset = offsetFromContainer;
+
+ stepInserted(*step.get());
+ m_mapping.insert(m_insertionPosition, step.release());
+}
+
+void RenderGeometryMap::push(const RenderObject* renderer, const TransformationMatrix& t, bool accumulatingTransform, bool isNonUniform, bool isFixedPosition, bool hasTransform)
+{
+ ASSERT(m_insertionPosition != notFound);
+
+ OwnPtr<RenderGeometryMapStep> step = adoptPtr(new RenderGeometryMapStep(renderer, accumulatingTransform, isNonUniform, isFixedPosition, hasTransform));
+ step->m_transform = adoptPtr(new TransformationMatrix(t));
+
+ stepInserted(*step.get());
+ m_mapping.insert(m_insertionPosition, step.release());
+}
+
+void RenderGeometryMap::pushView(const RenderView* view, const LayoutSize& scrollOffset, const TransformationMatrix* t)
+{
+ ASSERT(m_insertionPosition != notFound);
+
+ OwnPtr<RenderGeometryMapStep> step = adoptPtr(new RenderGeometryMapStep(view, false, false, false, t));
+ step->m_offset = scrollOffset;
+ if (t)
+ step->m_transform = adoptPtr(new TransformationMatrix(*t));
+
+ ASSERT(!m_mapping.size()); // The view should always be the first thing pushed.
+ stepInserted(*step.get());
+ m_mapping.insert(m_insertionPosition, step.release());
+}
+
+void RenderGeometryMap::popMappingsToAncestor(const RenderBoxModelObject* ancestor)
+{
+ ASSERT(m_mapping.size());
+
+ while (m_mapping.size() && m_mapping.last()->m_renderer != ancestor) {
+ stepRemoved(*m_mapping.last().get());
+ m_mapping.removeLast();
+ }
+}
+
+void RenderGeometryMap::stepInserted(const RenderGeometryMapStep& step)
+{
+ // Offset on the first step is the RenderView's offset, which is only applied when we have fixed-position.s
+ if (m_mapping.size())
+ m_accumulatedOffset += step.m_offset;
+
+ if (step.m_isNonUniform)
+ ++m_nonUniformStepsCount;
+
+ if (step.m_transform)
+ ++m_transformedStepsCount;
+
+ if (step.m_isFixedPosition)
+ ++m_fixedStepsCount;
+}
+
+void RenderGeometryMap::stepRemoved(const RenderGeometryMapStep& step)
+{
+ // Offset on the first step is the RenderView's offset, which is only applied when we have fixed-position.s
+ if (m_mapping.size() > 1)
+ m_accumulatedOffset -= step.m_offset;
+
+ if (step.m_isNonUniform) {
+ ASSERT(m_nonUniformStepsCount);
+ --m_nonUniformStepsCount;
+ }
+
+ if (step.m_transform) {
+ ASSERT(m_transformedStepsCount);
+ --m_transformedStepsCount;
+ }
+
+ if (step.m_isFixedPosition) {
+ ASSERT(m_fixedStepsCount);
+ --m_fixedStepsCount;
+ }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderGeometryMap.h b/Source/WebCore/rendering/RenderGeometryMap.h
new file mode 100644
index 000000000..6a6120333
--- /dev/null
+++ b/Source/WebCore/rendering/RenderGeometryMap.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RenderGeometryMap_h
+#define RenderGeometryMap_h
+
+#include "FloatPoint.h"
+#include "FloatQuad.h"
+#include "IntSize.h"
+#include "RenderObject.h"
+#include "TransformationMatrix.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class RenderGeometryMapStep;
+
+// Can be used while walking the Renderer tree to cache data about offsets and transforms.
+class RenderGeometryMap {
+public:
+ RenderGeometryMap();
+ ~RenderGeometryMap();
+
+ FloatPoint absolutePoint(const FloatPoint&) const;
+ FloatRect absoluteRect(const FloatRect&) const;
+
+ // Called by code walking the renderer or layer trees.
+ void pushMappingsToAncestor(const RenderObject*, const RenderBoxModelObject* ancestor);
+ void popMappingsToAncestor(const RenderBoxModelObject*);
+
+ // The following methods should only be called by renderers inside a call to pushMappingsToAncestor().
+
+ // Push geometry info between this renderer and some ancestor. The ancestor must be its container() or some
+ // stacking context between the renderer and its container.
+ void push(const RenderObject*, const LayoutSize&, bool accumulatingTransform = false, bool isNonUniform = false, bool isFixedPosition = false, bool hasTransform = false);
+ void push(const RenderObject*, const TransformationMatrix&, bool accumulatingTransform = false, bool isNonUniform = false, bool isFixedPosition = false, bool hasTransform = false);
+
+ // RenderView gets special treatment, because it applies the scroll offset only for elements inside in fixed position.
+ void pushView(const RenderView*, const LayoutSize& scrollOffset, const TransformationMatrix* = 0);
+
+private:
+ void mapToAbsolute(TransformState&) const;
+
+ void stepInserted(const RenderGeometryMapStep&);
+ void stepRemoved(const RenderGeometryMapStep&);
+
+ bool hasNonUniformStep() const { return m_nonUniformStepsCount; }
+ bool hasTransformStep() const { return m_transformedStepsCount; }
+ bool hasFixedPositionStep() const { return m_fixedStepsCount; }
+
+ typedef Vector<OwnPtr<RenderGeometryMapStep> > RenderGeometryMapSteps; // FIXME: inline capacity?
+
+ size_t m_insertionPosition;
+ int m_nonUniformStepsCount;
+ int m_transformedStepsCount;
+ int m_fixedStepsCount;
+ RenderGeometryMapSteps m_mapping;
+ LayoutSize m_accumulatedOffset;
+};
+
+} // namespace WebCore
+
+#endif // RenderGeometryMap_h
diff --git a/Source/WebCore/rendering/RenderInline.cpp b/Source/WebCore/rendering/RenderInline.cpp
index 0c88749f7..b8928161e 100644
--- a/Source/WebCore/rendering/RenderInline.cpp
+++ b/Source/WebCore/rendering/RenderInline.cpp
@@ -32,6 +32,7 @@
#include "RenderArena.h"
#include "RenderBlock.h"
#include "RenderFlowThread.h"
+#include "RenderGeometryMap.h"
#include "RenderLayer.h"
#include "RenderTheme.h"
#include "RenderView.h"
@@ -1065,7 +1066,7 @@ void RenderInline::computeRectForRepaint(RenderBoxModelObject* repaintContainer,
o->computeRectForRepaint(repaintContainer, rect, fixed);
}
-LayoutSize RenderInline::offsetFromContainer(RenderObject* container, const LayoutPoint& point) const
+LayoutSize RenderInline::offsetFromContainer(RenderObject* container, const LayoutPoint& point, bool* offsetDependsOnPoint) const
{
ASSERT(container == this->container());
@@ -1078,6 +1079,9 @@ LayoutSize RenderInline::offsetFromContainer(RenderObject* container, const Layo
if (container->hasOverflowClip())
offset -= toRenderBox(container)->scrolledContentOffset();
+ if (offsetDependsOnPoint)
+ *offsetDependsOnPoint = container->hasColumns() || (container->isBox() && container->style()->isFlippedBlocksWritingMode());
+
return offset;
}
@@ -1129,6 +1133,39 @@ void RenderInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b
o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, applyContainerFlip, wasFixed);
}
+const RenderObject* RenderInline::pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+ ASSERT(ancestorToStopAt != this);
+
+ bool ancestorSkipped;
+ RenderObject* container = this->container(ancestorToStopAt, &ancestorSkipped);
+ if (!container)
+ return 0;
+
+ LayoutSize adjustmentForSkippedAncestor;
+ if (ancestorSkipped) {
+ // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
+ // to just subtract the delta between the ancestor and o.
+ adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(container);
+ }
+
+ bool offsetDependsOnPoint = false;
+ LayoutSize containerOffset = offsetFromContainer(container, LayoutPoint(), &offsetDependsOnPoint);
+
+ bool preserve3D = container->style()->preserves3D() || style()->preserves3D();
+ if (shouldUseTransformFromContainer(container)) {
+ TransformationMatrix t;
+ getTransformFromContainer(container, containerOffset, t);
+ t.translateRight(adjustmentForSkippedAncestor.width(), adjustmentForSkippedAncestor.height()); // FIXME: right?
+ geometryMap.push(this, t, preserve3D, offsetDependsOnPoint);
+ } else {
+ containerOffset += adjustmentForSkippedAncestor;
+ geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint);
+ }
+
+ return ancestorSkipped ? ancestorToStopAt : container;
+}
+
void RenderInline::updateDragState(bool dragOn)
{
RenderBoxModelObject::updateDragState(dragOn);
diff --git a/Source/WebCore/rendering/RenderInline.h b/Source/WebCore/rendering/RenderInline.h
index 2363f0b0a..4187f3187 100644
--- a/Source/WebCore/rendering/RenderInline.h
+++ b/Source/WebCore/rendering/RenderInline.h
@@ -49,7 +49,7 @@ public:
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
- virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&) const;
+ virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
IntRect linesBoundingBox() const;
LayoutRect linesVisualOverflowBoundingBox() const;
@@ -134,6 +134,7 @@ private:
virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect&, bool fixed) const;
virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
+ virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const;
virtual VisiblePosition positionForPoint(const LayoutPoint&);
diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp
index 39afa3053..e0b56e7e5 100644
--- a/Source/WebCore/rendering/RenderLayer.cpp
+++ b/Source/WebCore/rendering/RenderLayer.cpp
@@ -125,25 +125,6 @@ using namespace HTMLNames;
const int MinimumWidthWhileResizing = 100;
const int MinimumHeightWhileResizing = 40;
-void* ClipRects::operator new(size_t sz, RenderArena* renderArena)
-{
- return renderArena->allocate(sz);
-}
-
-void ClipRects::operator delete(void* ptr, size_t sz)
-{
- // Stash size where destroy can find it.
- *(size_t *)ptr = sz;
-}
-
-void ClipRects::destroy(RenderArena* renderArena)
-{
- delete this;
-
- // Recover the size left there for us by operator delete and free the memory.
- renderArena->free(*(size_t *)this, this);
-}
-
RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
: m_inResizeMode(false)
, m_scrollDimensionsDirty(true)
@@ -180,10 +161,6 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
, m_posZOrderList(0)
, m_negZOrderList(0)
, m_normalFlowList(0)
- , m_clipRects(0)
-#ifndef NDEBUG
- , m_clipRectsRoot(0)
-#endif
, m_marquee(0)
, m_staticInlinePosition(0)
, m_staticBlockPosition(0)
@@ -252,9 +229,6 @@ RenderLayer::~RenderLayer()
clearBacking(true);
#endif
- // Make sure we have no lingering clip rects.
- ASSERT(!m_clipRects);
-
if (m_scrollCorner)
m_scrollCorner->destroy();
if (m_resizer)
@@ -534,6 +508,9 @@ void RenderLayer::updateTransform()
m_transform = adoptPtr(new TransformationMatrix);
else
m_transform.clear();
+
+ // Layers with transforms act as clip rects roots, so clear the cached clip rects here.
+ clearClipRectsIncludingDescendants();
}
if (hasTransform) {
@@ -1070,7 +1047,7 @@ void RenderLayer::setFilterBackendNeedsRepaintingInRect(const LayoutRect& rect,
}
#endif
-RenderLayer* RenderLayer::clippingRoot() const
+RenderLayer* RenderLayer::clippingRootForPainting() const
{
#if USE(ACCELERATED_COMPOSITING)
if (isComposited())
@@ -2935,7 +2912,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* context,
// Make sure the parent's clip rects have been calculated.
ClipRect clipRect = paintDirtyRect;
if (parent()) {
- clipRect = backgroundClipRect(rootLayer, region, paintFlags & PaintLayerTemporaryClipRects);
+ clipRect = backgroundClipRect(rootLayer, region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects);
clipRect.intersect(paintDirtyRect);
// Push the parent coordinate space's clip.
@@ -3044,7 +3021,7 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
#endif
if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
- calculateRects(rootLayer, region, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, localPaintFlags & PaintLayerTemporaryClipRects);
+ calculateRects(rootLayer, region, (localPaintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
paintOffset = toPoint(layerBounds.location() - renderBoxLocation());
}
@@ -3452,11 +3429,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
{
// The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
- bool useTemporaryClipRects = false;
-#if USE(ACCELERATED_COMPOSITING)
- useTemporaryClipRects = compositor()->inCompositingMode();
-#endif
- useTemporaryClipRects |= renderer()->view()->frameView()->containsScrollableAreaWithOverlayScrollbars();
+ bool useTemporaryClipRects = renderer()->view()->frameView()->containsScrollableAreaWithOverlayScrollbars();
LayoutRect hitTestArea = result.rectForPoint(hitTestPoint);
@@ -3464,7 +3437,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
if (transform() && !appliedTransform) {
// Make sure the parent's clip rects have been calculated.
if (parent()) {
- ClipRect clipRect = backgroundClipRect(rootLayer, result.region(), useTemporaryClipRects, IncludeOverlayScrollbarSize);
+ ClipRect clipRect = backgroundClipRect(rootLayer, result.region(), useTemporaryClipRects ? TemporaryClipRects : RootRelativeClipRects, IncludeOverlayScrollbarSize);
// Go ahead and test the enclosing clip now.
if (!clipRect.intersects(hitTestArea))
return 0;
@@ -3525,7 +3498,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
ClipRect bgRect;
ClipRect fgRect;
ClipRect outlineRect;
- calculateRects(rootLayer, result.region(), hitTestRect, layerBounds, bgRect, fgRect, outlineRect, useTemporaryClipRects, IncludeOverlayScrollbarSize);
+ calculateRects(rootLayer, result.region(), useTemporaryClipRects ? TemporaryClipRects : RootRelativeClipRects, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, IncludeOverlayScrollbarSize);
// The following are used for keeping track of the z-depth of the hit point of 3d-transformed
// descendants.
@@ -3796,10 +3769,11 @@ RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend
return 0;
}
-void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy)
+void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy)
{
- if (m_clipRects) {
- ASSERT(rootLayer == m_clipRectsRoot);
+ ASSERT(clipRectsType < NumCachedClipRectsTypes);
+ if (m_clipRectsCache && m_clipRectsCache->m_clipRects[clipRectsType]) {
+ ASSERT(rootLayer == m_clipRectsCache->m_clipRectsRoot[clipRectsType]);
return; // We have the correct cached value.
}
@@ -3807,29 +3781,34 @@ void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* re
// examine the parent. We want to cache clip rects with us as the root.
RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
if (parentLayer)
- parentLayer->updateClipRects(rootLayer, region, relevancy);
+ parentLayer->updateClipRects(rootLayer, region, clipRectsType, relevancy);
ClipRects clipRects;
- calculateClipRects(rootLayer, region, clipRects, true, relevancy);
+ calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy);
- if (parentLayer && parentLayer->clipRects() && clipRects == *parentLayer->clipRects())
- m_clipRects = parentLayer->clipRects();
+ if (!m_clipRectsCache)
+ m_clipRectsCache = adoptPtr(new ClipRectsCache);
+
+ if (parentLayer && parentLayer->clipRects(clipRectsType) && clipRects == *parentLayer->clipRects(clipRectsType))
+ m_clipRectsCache->m_clipRects[clipRectsType] = parentLayer->clipRects(clipRectsType);
else
- m_clipRects = new (renderer()->renderArena()) ClipRects(clipRects);
- m_clipRects->ref();
+ m_clipRectsCache->m_clipRects[clipRectsType] = ClipRects::create(clipRects);
+
+ m_clipRectsCache->m_clipRects[clipRectsType]->ref();
#ifndef NDEBUG
- m_clipRectsRoot = rootLayer;
+ m_clipRectsCache->m_clipRectsRoot[clipRectsType] = rootLayer;
#endif
}
-void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRects& clipRects,
- bool useCached, OverlayScrollbarSizeRelevancy relevancy) const
+void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy) const
{
if (!parent()) {
// The root layer's clip rect is always infinite.
clipRects.reset(PaintInfo::infiniteRect());
return;
}
+
+ bool useCached = clipRectsType != TemporaryClipRects;
// For transformed layers, the root layer was shifted to be us, so there is no need to
// examine the parent. We want to cache clip rects with us as the root.
@@ -3837,10 +3816,10 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion*
// Ensure that our parent's clip has been calculated so that we can examine the values.
if (parentLayer) {
- if (useCached && parentLayer->clipRects())
- clipRects = *parentLayer->clipRects();
+ if (useCached && parentLayer->clipRects(clipRectsType))
+ clipRects = *parentLayer->clipRects(clipRectsType);
else
- parentLayer->calculateClipRects(rootLayer, region, clipRects);
+ parentLayer->calculateClipRects(rootLayer, region, clipRectsType, clipRects);
} else
clipRects.reset(PaintInfo::infiniteRect());
@@ -3888,16 +3867,16 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion*
}
}
-void RenderLayer::parentClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRects& clipRects, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const
+void RenderLayer::parentClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy) const
{
ASSERT(parent());
- if (temporaryClipRects) {
- parent()->calculateClipRects(rootLayer, region, clipRects, false, relevancy);
+ if (clipRectsType == TemporaryClipRects) {
+ parent()->calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy);
return;
}
- parent()->updateClipRects(rootLayer, region, relevancy);
- clipRects = *parent()->clipRects();
+ parent()->updateClipRects(rootLayer, region, clipRectsType, relevancy);
+ clipRects = *parent()->clipRects(clipRectsType);
}
static inline ClipRect backgroundClipRectForPosition(const ClipRects& parentRects, EPosition position)
@@ -3911,11 +3890,11 @@ static inline ClipRect backgroundClipRectForPosition(const ClipRects& parentRect
return parentRects.overflowClipRect();
}
-ClipRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, RenderRegion* region, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const
+ClipRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy) const
{
ASSERT(parent());
ClipRects parentRects;
- parentClipRects(rootLayer, region, parentRects, temporaryClipRects, relevancy);
+ parentClipRects(rootLayer, region, clipRectsType, parentRects, relevancy);
ClipRect backgroundClipRect = backgroundClipRectForPosition(parentRects, renderer()->style()->position());
RenderView* view = renderer()->view();
ASSERT(view);
@@ -3927,12 +3906,11 @@ ClipRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, RenderReg
return backgroundClipRect;
}
-void RenderLayer::calculateRects(const RenderLayer* rootLayer, RenderRegion* region, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
- ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, bool temporaryClipRects,
- OverlayScrollbarSizeRelevancy relevancy) const
+void RenderLayer::calculateRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
+ ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, OverlayScrollbarSizeRelevancy relevancy) const
{
if (rootLayer != this && parent()) {
- backgroundRect = backgroundClipRect(rootLayer, region, temporaryClipRects, relevancy);
+ backgroundRect = backgroundClipRect(rootLayer, region, clipRectsType, relevancy);
backgroundRect.intersect(paintDirtyRect);
} else
backgroundRect = paintDirtyRect;
@@ -3985,10 +3963,10 @@ LayoutRect RenderLayer::childrenClipRect() const
// FIXME: border-radius not accounted for.
// FIXME: Regions not accounted for.
RenderView* renderView = renderer()->view();
- RenderLayer* clippingRootLayer = clippingRoot();
+ RenderLayer* clippingRootLayer = clippingRootForPainting();
LayoutRect layerBounds;
ClipRect backgroundRect, foregroundRect, outlineRect;
- calculateRects(clippingRootLayer, 0, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+ calculateRects(clippingRootLayer, 0, PaintingClipRects, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect.rect())).enclosingBoundingBox();
}
@@ -3997,10 +3975,10 @@ LayoutRect RenderLayer::selfClipRect() const
// FIXME: border-radius not accounted for.
// FIXME: Regions not accounted for.
RenderView* renderView = renderer()->view();
- RenderLayer* clippingRootLayer = clippingRoot();
+ RenderLayer* clippingRootLayer = clippingRootForPainting();
LayoutRect layerBounds;
ClipRect backgroundRect, foregroundRect, outlineRect;
- calculateRects(clippingRootLayer, 0, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+ calculateRects(clippingRootLayer, 0, PaintingClipRects, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect.rect())).enclosingBoundingBox();
}
@@ -4008,10 +3986,10 @@ LayoutRect RenderLayer::localClipRect() const
{
// FIXME: border-radius not accounted for.
// FIXME: Regions not accounted for.
- RenderLayer* clippingRootLayer = clippingRoot();
+ RenderLayer* clippingRootLayer = clippingRootForPainting();
LayoutRect layerBounds;
ClipRect backgroundRect, foregroundRect, outlineRect;
- calculateRects(clippingRootLayer, 0, PaintInfo::infiniteRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+ calculateRects(clippingRootLayer, 0, PaintingClipRects, PaintInfo::infiniteRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
LayoutRect clipRect = backgroundRect.rect();
if (clipRect == PaintInfo::infiniteRect())
@@ -4259,25 +4237,25 @@ IntRect RenderLayer::calculateLayerBounds(const RenderLayer* layer, const Render
return pixelSnappedIntRect(unionBounds);
}
-void RenderLayer::clearClipRectsIncludingDescendants()
+void RenderLayer::clearClipRectsIncludingDescendants(ClipRectsType typeToClear)
{
- if (!m_clipRects)
+ // FIXME: it's not clear how this layer not having clip rects guarantees that no descendants have any.
+ if (!m_clipRectsCache)
return;
- clearClipRects();
+ clearClipRects(typeToClear);
for (RenderLayer* l = firstChild(); l; l = l->nextSibling())
- l->clearClipRectsIncludingDescendants();
+ l->clearClipRectsIncludingDescendants(typeToClear);
}
-void RenderLayer::clearClipRects()
+void RenderLayer::clearClipRects(ClipRectsType typeToClear)
{
- if (m_clipRects) {
- m_clipRects->deref(renderer()->renderArena());
- m_clipRects = 0;
-#ifndef NDEBUG
- m_clipRectsRoot = 0;
-#endif
+ if (typeToClear == AllClipRectTypes)
+ m_clipRectsCache = nullptr;
+ else {
+ ASSERT(typeToClear < NumCachedClipRectsTypes);
+ m_clipRectsCache->m_clipRects[typeToClear] = nullptr;
}
}
diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h
index 860a37290..ad23af708 100644
--- a/Source/WebCore/rendering/RenderLayer.h
+++ b/Source/WebCore/rendering/RenderLayer.h
@@ -129,27 +129,19 @@ inline ClipRect intersection(const ClipRect& a, const ClipRect& b)
class ClipRects {
public:
- ClipRects()
- : m_refCnt(0)
- , m_fixed(false)
+ static PassRefPtr<ClipRects> create()
{
+ return adoptRef(new ClipRects);
}
- ClipRects(const LayoutRect& r)
- : m_overflowClipRect(r)
- , m_fixedClipRect(r)
- , m_posClipRect(r)
- , m_refCnt(0)
- , m_fixed(false)
+ static PassRefPtr<ClipRects> create(const ClipRects& other)
{
+ return adoptRef(new ClipRects(other));
}
- ClipRects(const ClipRects& other)
- : m_overflowClipRect(other.overflowClipRect())
- , m_fixedClipRect(other.fixedClipRect())
- , m_posClipRect(other.posClipRect())
- , m_refCnt(0)
- , m_fixed(other.fixed())
+ ClipRects()
+ : m_refCnt(0)
+ , m_fixed(false)
{
}
@@ -174,15 +166,11 @@ public:
void setFixed(bool fixed) { m_fixed = fixed; }
void ref() { m_refCnt++; }
- void deref(RenderArena* renderArena) { if (--m_refCnt == 0) destroy(renderArena); }
-
- void destroy(RenderArena*);
-
- // Overloaded new operator.
- void* operator new(size_t, RenderArena*);
-
- // Overridden to prevent the normal delete from being called.
- void operator delete(void*, size_t);
+ void deref()
+ {
+ if (!--m_refCnt)
+ delete this;
+ }
bool operator==(const ClipRects& other) const
{
@@ -202,10 +190,24 @@ public:
}
private:
- // The normal operator new is disallowed on all render objects.
- void* operator new(size_t) throw();
+ ClipRects(const LayoutRect& r)
+ : m_overflowClipRect(r)
+ , m_fixedClipRect(r)
+ , m_posClipRect(r)
+ , m_refCnt(0)
+ , m_fixed(false)
+ {
+ }
+
+ ClipRects(const ClipRects& other)
+ : m_overflowClipRect(other.overflowClipRect())
+ , m_fixedClipRect(other.fixedClipRect())
+ , m_posClipRect(other.posClipRect())
+ , m_refCnt(0)
+ , m_fixed(other.fixed())
+ {
+ }
-private:
ClipRect m_overflowClipRect;
ClipRect m_fixedClipRect;
ClipRect m_posClipRect;
@@ -213,6 +215,30 @@ private:
bool m_fixed : 1;
};
+enum ClipRectsType {
+ PaintingClipRects, // Relative to painting ancestor. Used for painting.
+ RootRelativeClipRects, // Relative to the ancestor treated as the root (e.g. transformed layer). Used for hit testing.
+ AbsoluteClipRects, // Relative to the RenderView's layer. Used for compositing overlap testing.
+ NumCachedClipRectsTypes,
+ AllClipRectTypes,
+ TemporaryClipRects
+};
+
+struct ClipRectsCache {
+ ClipRectsCache()
+ {
+#ifndef NDEBUG
+ for (int i = 0; i < NumCachedClipRectsTypes; ++i)
+ m_clipRectsRoot[i] = 0;
+#endif
+ }
+
+ RefPtr<ClipRects> m_clipRects[NumCachedClipRectsTypes];
+#ifndef NDEBUG
+ const RenderLayer* m_clipRectsRoot[NumCachedClipRectsTypes];
+#endif
+};
+
class RenderLayer : public ScrollableArea {
public:
friend class RenderReplica;
@@ -371,8 +397,8 @@ public:
const LayoutSize& relativePositionOffset() const { return m_relativeOffset; }
- void clearClipRectsIncludingDescendants();
- void clearClipRects();
+ void clearClipRectsIncludingDescendants(ClipRectsType typeToClear = AllClipRectTypes);
+ void clearClipRects(ClipRectsType typeToClear = AllClipRectTypes);
void addBlockSelectionGapsBounds(const LayoutRect&);
void clearBlockSelectionGapsBounds();
@@ -423,7 +449,7 @@ public:
RenderLayer* enclosingScrollableLayer() const;
// The layer relative to which clipping rects for this layer are computed.
- RenderLayer* clippingRoot() const;
+ RenderLayer* clippingRootForPainting() const;
#if USE(ACCELERATED_COMPOSITING)
// Enclosing compositing layer; if includeSelf is true, may return this.
@@ -472,16 +498,17 @@ public:
// This method figures out our layerBounds in coordinates relative to
// |rootLayer}. It also computes our background and foreground clip rects
// for painting/event handling.
- void calculateRects(const RenderLayer* rootLayer, RenderRegion*, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
+ void calculateRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect,
- bool temporaryClipRects = false, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+ OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
// Compute and cache clip rects computed with the given layer as the root
- void updateClipRects(const RenderLayer* rootLayer, RenderRegion*, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize);
+ void updateClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize);
// Compute and return the clip rects. If useCached is true, will used previously computed clip rects on ancestors
// (rather than computing them all from scratch up the parent chain).
- void calculateClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRects&, bool useCached = false, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
- ClipRects* clipRects() const { return m_clipRects; }
+ void calculateClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, ClipRects&, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+
+ ClipRects* clipRects(ClipRectsType type) const { ASSERT(type < NumCachedClipRectsTypes); return m_clipRectsCache ? m_clipRectsCache->m_clipRects[type].get() : 0; }
LayoutRect childrenClipRect() const; // Returns the foreground clip rect of the layer in the document's coordinate space.
LayoutRect selfClipRect() const; // Returns the background clip rect of the layer in the document's coordinate space.
@@ -767,8 +794,8 @@ private:
void updateOrRemoveFilterEffect();
#endif
- void parentClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRects&, bool temporaryClipRects = false, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
- ClipRect backgroundClipRect(const RenderLayer* rootLayer, RenderRegion*, bool temporaryClipRects, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+ void parentClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, ClipRects&, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+ ClipRect backgroundClipRect(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
LayoutRect paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior);
RenderLayer* enclosingTransformedAncestor() const;
@@ -905,11 +932,8 @@ protected:
// overflow layers, but that may change in the future.
Vector<RenderLayer*>* m_normalFlowList;
- ClipRects* m_clipRects; // Cached clip rects used when painting and hit testing.
-#ifndef NDEBUG
- const RenderLayer* m_clipRectsRoot; // Root layer used to compute clip rects.
-#endif
-
+ OwnPtr<ClipRectsCache> m_clipRectsCache;
+
IntPoint m_cachedOverlayScrollbarOffset;
RenderMarquee* m_marquee; // Used by layers with overflow:marquee
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index ee39912a9..1085eabc0 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -267,7 +267,7 @@ void RenderLayerBacking::updateCompositedBounds()
LayoutRect clippingBounds = view->unscaledDocumentRect();
if (m_owningLayer != rootLayer)
- clippingBounds.intersect(m_owningLayer->backgroundClipRect(rootLayer, 0, true).rect()); // FIXME: Incorrect for CSS regions.
+ clippingBounds.intersect(m_owningLayer->backgroundClipRect(rootLayer, 0, AbsoluteClipRects).rect()); // FIXME: Incorrect for CSS regions.
LayoutPoint delta;
m_owningLayer->convertToLayerCoords(rootLayer, delta);
@@ -465,7 +465,7 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
// Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
// layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
// for a compositing layer, rootLayer is the layer itself.
- IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(compAncestor, 0, true).rect()); // FIXME: Incorrect for CSS regions.
+ IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(compAncestor, 0, TemporaryClipRects).rect()); // FIXME: Incorrect for CSS regions.
ASSERT(parentClipRect != PaintInfo::infiniteRect());
m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation));
m_ancestorClippingLayer->setSize(parentClipRect.size());
@@ -1112,6 +1112,17 @@ bool RenderLayerBacking::paintsIntoWindow() const
return false;
}
+void RenderLayerBacking::setRequiresOwnBackingStore(bool flag)
+{
+ if (flag == m_requiresOwnBackingStore)
+ return;
+
+ // This affects the answer to paintsIntoCompositedAncestor(), which in turn affects
+ // cached clip rects, so when it changes we have to clear clip rects on descendants.
+ m_owningLayer->clearClipRectsIncludingDescendants(PaintingClipRects);
+ m_requiresOwnBackingStore = flag;
+}
+
void RenderLayerBacking::setContentsNeedDisplay()
{
ASSERT(!paintsIntoCompositedAncestor());
diff --git a/Source/WebCore/rendering/RenderLayerBacking.h b/Source/WebCore/rendering/RenderLayerBacking.h
index a6a03ac77..d8718858e 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.h
+++ b/Source/WebCore/rendering/RenderLayerBacking.h
@@ -101,7 +101,7 @@ public:
// paints into some ancestor layer.
bool paintsIntoCompositedAncestor() const { return !m_requiresOwnBackingStore; }
- void setRequiresOwnBackingStore(bool flag) { m_requiresOwnBackingStore = flag; }
+ void setRequiresOwnBackingStore(bool);
void setContentsNeedDisplay();
// r is in the coordinate space of the layer's render object
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index c402b593d..2a9d2ab07 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -45,6 +45,7 @@
#include "RenderApplet.h"
#include "RenderEmbeddedObject.h"
#include "RenderFullScreen.h"
+#include "RenderGeometryMap.h"
#include "RenderIFrame.h"
#include "RenderLayerBacking.h"
#include "RenderReplica.h"
@@ -54,6 +55,7 @@
#include "ScrollingCoordinator.h"
#include "Settings.h"
#include "TiledBacking.h"
+#include "TransformState.h"
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
#include "HTMLMediaElement.h"
@@ -398,9 +400,10 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
bool layersChanged = false;
if (m_compositingConsultsOverlap) {
OverlapMap overlapTestRequestMap;
- computeCompositingRequirements(updateRoot, &overlapTestRequestMap, compState, layersChanged);
+ RenderGeometryMap geometryMap;
+ computeCompositingRequirements(0, updateRoot, &geometryMap, &overlapTestRequestMap, compState, layersChanged);
} else
- computeCompositingRequirements(updateRoot, 0, compState, layersChanged);
+ computeCompositingRequirements(0, updateRoot, 0, 0, compState, layersChanged);
needHierarchyUpdate |= layersChanged;
}
@@ -537,6 +540,9 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR
if (innerCompositor && innerCompositor->inCompositingMode())
innerCompositor->updateRootLayerAttachment();
}
+
+ if (layerChanged)
+ layer->clearClipRectsIncludingDescendants(PaintingClipRects);
return layerChanged;
}
@@ -624,33 +630,37 @@ RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const Rend
return 0;
}
-void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer* layer, IntRect& layerBounds, bool& boundsComputed)
+void RenderLayerCompositor::addToOverlapMap(RenderGeometryMap& geometryMap, OverlapMap& overlapMap, RenderLayer* layer, IntRect& layerBounds, bool& boundsComputed)
{
if (layer->isRootLayer())
return;
if (!boundsComputed) {
- layerBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox();
+ layerBounds = enclosingIntRect(geometryMap.absoluteRect(layer->localBoundingBox()));
// Empty rects never intersect, but we need them to for the purposes of overlap testing.
if (layerBounds.isEmpty())
layerBounds.setSize(IntSize(1, 1));
boundsComputed = true;
}
- IntRect clipRect = pixelSnappedIntRect(layer->backgroundClipRect(rootRenderLayer(), 0, true).rect()); // FIXME: Incorrect for CSS regions.
+ IntRect clipRect = pixelSnappedIntRect(layer->backgroundClipRect(rootRenderLayer(), 0, AbsoluteClipRects).rect()); // FIXME: Incorrect for CSS regions.
clipRect.scale(pageScaleFactor());
clipRect.intersect(layerBounds);
overlapMap.add(layer, clipRect);
}
-void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, RenderLayer* layer)
+void RenderLayerCompositor::addToOverlapMapRecursive(RenderGeometryMap& geometryMap, OverlapMap& overlapMap, RenderLayer* layer, RenderLayer* ancestorLayer)
{
if (!canBeComposited(layer) || overlapMap.contains(layer))
return;
+ // A null ancestorLayer is an indication that 'layer' has already been pushed.
+ if (ancestorLayer)
+ geometryMap.pushMappingsToAncestor(layer->renderer(), ancestorLayer->renderer());
+
IntRect bounds;
bool haveComputedBounds = false;
- addToOverlapMap(overlapMap, layer, bounds, haveComputedBounds);
+ addToOverlapMap(geometryMap, overlapMap, layer, bounds, haveComputedBounds);
#if !ASSERT_DISABLED
LayerListMutationDetector mutationChecker(layer);
@@ -661,7 +671,7 @@ void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, Ren
size_t listSize = negZOrderList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = negZOrderList->at(i);
- addToOverlapMapRecursive(overlapMap, curLayer);
+ addToOverlapMapRecursive(geometryMap, overlapMap, curLayer, layer);
}
}
}
@@ -670,7 +680,7 @@ void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, Ren
size_t listSize = normalFlowList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = normalFlowList->at(i);
- addToOverlapMapRecursive(overlapMap, curLayer);
+ addToOverlapMapRecursive(geometryMap, overlapMap, curLayer, layer);
}
}
@@ -679,10 +689,13 @@ void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, Ren
size_t listSize = posZOrderList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = posZOrderList->at(i);
- addToOverlapMapRecursive(overlapMap, curLayer);
+ addToOverlapMapRecursive(geometryMap, overlapMap, curLayer, layer);
}
}
}
+
+ if (ancestorLayer)
+ geometryMap.popMappingsToAncestor(ancestorLayer->renderer());
}
// Recurse through the layers in z-index and overflow order (which is equivalent to painting order)
@@ -694,11 +707,14 @@ void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, Ren
// must be compositing so that its contents render over that child.
// This implies that its positive z-index children must also be compositing.
//
-void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, OverlapMap* overlapMap, CompositingState& compositingState, bool& layersChanged)
+void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer* layer, RenderGeometryMap* geometryMap, OverlapMap* overlapMap, CompositingState& compositingState, bool& layersChanged)
{
- layer->updateLayerPosition();
layer->updateLayerListsIfNeeded();
-
+
+ // Should geometryMap be part of the overlap map?
+ if (geometryMap)
+ geometryMap->pushMappingsToAncestor(layer->renderer(), ancestorLayer ? ancestorLayer->renderer() : 0);
+
// Clear the flag
layer->setHasCompositingDescendant(false);
@@ -708,7 +724,8 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
IntRect absBounds;
if (overlapMap && !overlapMap->isEmpty() && compositingState.m_testingOverlap) {
// If we're testing for overlap, we only need to composite if we overlap something that is already composited.
- absBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox();
+ absBounds = enclosingIntRect(geometryMap->absoluteRect(layer->localBoundingBox()));
+
// Empty rects never intersect, but we need them to for the purposes of overlap testing.
if (absBounds.isEmpty())
absBounds.setSize(IntSize(1, 1));
@@ -757,7 +774,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
size_t listSize = negZOrderList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = negZOrderList->at(i);
- computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged);
+ computeCompositingRequirements(layer, curLayer, geometryMap, overlapMap, childState, layersChanged);
// If we have to make a layer for this child, make one now so we can have a contents layer
// (since we need to ensure that the -ve z-order child renders underneath our contents).
@@ -777,7 +794,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
size_t listSize = normalFlowList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = normalFlowList->at(i);
- computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged);
+ computeCompositingRequirements(layer, curLayer, geometryMap, overlapMap, childState, layersChanged);
}
}
@@ -786,7 +803,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
size_t listSize = posZOrderList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = posZOrderList->at(i);
- computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged);
+ computeCompositingRequirements(layer, curLayer, geometryMap, overlapMap, childState, layersChanged);
}
}
}
@@ -803,7 +820,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
// the overlap map. Layers that do not composite will draw into their
// compositing ancestor's backing, and so are still considered for overlap.
if (overlapMap && childState.m_compositingAncestor && !childState.m_compositingAncestor->isRootLayer())
- addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds);
+ addToOverlapMap(*geometryMap, *overlapMap, layer, absBounds, haveComputedBounds);
// If we have a software transform, and we have layers under us, we need to also
// be composited. Also, if we have opacity < 1, then we need to be a layer so that
@@ -813,7 +830,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
childState.m_compositingAncestor = layer;
if (overlapMap) {
overlapMap->pushCompositingContainer();
- addToOverlapMapRecursive(*overlapMap, layer);
+ addToOverlapMapRecursive(*geometryMap, *overlapMap, layer);
}
willBeComposited = true;
}
@@ -842,7 +859,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
childState.m_compositingAncestor = layer;
if (overlapMap) {
overlapMap->pushCompositingContainer();
- addToOverlapMapRecursive(*overlapMap, layer);
+ addToOverlapMapRecursive(*geometryMap, *overlapMap, layer);
}
willBeComposited = true;
}
@@ -873,6 +890,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
if (layer->reflectionLayer() && updateLayerCompositingState(layer->reflectionLayer(), CompositingChangeRepaintNow))
layersChanged = true;
+
+ if (geometryMap)
+ geometryMap->popMappingsToAncestor(ancestorLayer ? ancestorLayer->renderer() : 0);
}
void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer)
@@ -1536,7 +1556,7 @@ bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const
if (!computeClipRoot || computeClipRoot == layer)
return false;
- return layer->backgroundClipRect(computeClipRoot, 0, true).rect() != PaintInfo::infiniteRect(); // FIXME: Incorrect for CSS regions.
+ return layer->backgroundClipRect(computeClipRoot, 0, TemporaryClipRects).rect() != PaintInfo::infiniteRect(); // FIXME: Incorrect for CSS regions.
}
// Return true if the given layer is a stacking context and has compositing child
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h
index e294b5866..273849352 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.h
+++ b/Source/WebCore/rendering/RenderLayerCompositor.h
@@ -34,6 +34,7 @@ namespace WebCore {
class GraphicsLayer;
class RenderEmbeddedObject;
+class RenderGeometryMap;
class RenderPart;
class ScrollingCoordinator;
#if ENABLE(VIDEO)
@@ -238,13 +239,13 @@ private:
// Repaint the given rect (which is layer's coords), and regions of child layers that intersect that rect.
void recursiveRepaintLayerRect(RenderLayer*, const IntRect&);
- void addToOverlapMap(OverlapMap&, RenderLayer*, IntRect& layerBounds, bool& boundsComputed);
- void addToOverlapMapRecursive(OverlapMap&, RenderLayer*);
+ void addToOverlapMap(RenderGeometryMap&, OverlapMap&, RenderLayer*, IntRect& layerBounds, bool& boundsComputed);
+ void addToOverlapMapRecursive(RenderGeometryMap&, OverlapMap&, RenderLayer*, RenderLayer* ancestorLayer = 0);
void updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>*);
// Returns true if any layer's compositing changed
- void computeCompositingRequirements(RenderLayer*, OverlapMap*, struct CompositingState&, bool& layersChanged);
+ void computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer*, RenderGeometryMap*, OverlapMap*, struct CompositingState&, bool& layersChanged);
// Recurses down the tree, parenting descendant compositing layers and collecting an array of child layers for the current compositing layer.
void rebuildCompositingLayerTree(RenderLayer*, Vector<GraphicsLayer*>& childGraphicsLayersOfEnclosingLayer, int depth);
diff --git a/Source/WebCore/rendering/RenderMediaControlsChromium.cpp b/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
index c28049c2b..72e12c881 100644
--- a/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
+++ b/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
@@ -127,37 +127,37 @@ static bool paintMediaSlider(RenderObject* object, const PaintInfo& paintInfo, c
context->drawRect(rect);
context->restore();
- // Draw the buffered ranges.
- // FIXME: Draw multiple ranges if there are multiple buffered ranges. http://webkit.org/b/85925
+ // Draw the buffered range. Since the element may have multiple buffered ranges and it'd be
+ // distracting/'busy' to show all of them, show only the buffered range containing the current play head.
IntRect bufferedRect = rect;
bufferedRect.inflate(-style->borderLeftWidth());
- double bufferedWidth = 0.0;
RefPtr<TimeRanges> bufferedTimeRanges = mediaElement->buffered();
- if (bufferedTimeRanges->length() > 0) {
- // Account for the width of the slider thumb.
- Image* mediaSliderThumb = getMediaSliderThumb();
- double thumbWidth = mediaSliderThumb->width() / 2.0 + 1.0;
- double rectWidth = bufferedRect.width() - thumbWidth;
- if (rectWidth < 0.0)
- rectWidth = 0.0;
- // Preserve old behavior pending resolution of UI design of multiple ranges (see FIXME above).
- // http://webkit.org/b/85926
- double fakePercentLoaded = 0;
- float duration = mediaElement->duration();
- if (duration && !isinf(duration))
- fakePercentLoaded = bufferedTimeRanges->end(bufferedTimeRanges->length() - 1, ASSERT_NO_EXCEPTION) / duration;
- bufferedWidth = rectWidth * fakePercentLoaded + thumbWidth;
- }
- bufferedRect.setWidth(bufferedWidth);
+ float duration = mediaElement->duration();
+ float currentTime = mediaElement->currentTime();
+ if (isnan(duration) || isinf(duration) || !duration || isnan(currentTime))
+ return true;
+
+ for (unsigned i = 0; i < bufferedTimeRanges->length(); ++i) {
+ float start = bufferedTimeRanges->start(i, ASSERT_NO_EXCEPTION);
+ float end = bufferedTimeRanges->end(i, ASSERT_NO_EXCEPTION);
+ if (isnan(start) || isnan(end) || start > currentTime || end < currentTime)
+ continue;
+ float startFraction = start / duration;
+ float endFraction = end / duration;
+ float widthFraction = endFraction - startFraction;
+ bufferedRect.move(startFraction * bufferedRect.width(), 0);
+ bufferedRect.setWidth(widthFraction * bufferedRect.width());
+
+ // Don't bother drawing an empty area.
+ if (bufferedRect.isEmpty())
+ return true;
- // Don't bother drawing an empty area.
- if (!bufferedRect.isEmpty()) {
IntPoint sliderTopLeft = bufferedRect.location();
- IntPoint sliderTopRight = sliderTopLeft;
- sliderTopRight.move(0, bufferedRect.height());
+ IntPoint sliderBottomLeft = sliderTopLeft;
+ sliderBottomLeft.move(0, bufferedRect.height());
- RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderTopRight);
+ RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderBottomLeft);
Color startColor = object->style()->visitedDependentColor(CSSPropertyColor);
gradient->addColorStop(0.0, startColor);
gradient->addColorStop(1.0, Color(startColor.red() / 2, startColor.green() / 2, startColor.blue() / 2, startColor.alpha()));
@@ -167,6 +167,7 @@ static bool paintMediaSlider(RenderObject* object, const PaintInfo& paintInfo, c
context->setFillGradient(gradient);
context->fillRect(bufferedRect);
context->restore();
+ return true;
}
return true;
diff --git a/Source/WebCore/rendering/RenderMultiColumnBlock.cpp b/Source/WebCore/rendering/RenderMultiColumnBlock.cpp
index d29055e68..d7f43ff50 100644
--- a/Source/WebCore/rendering/RenderMultiColumnBlock.cpp
+++ b/Source/WebCore/rendering/RenderMultiColumnBlock.cpp
@@ -25,6 +25,7 @@
#include "config.h"
#include "RenderMultiColumnBlock.h"
+#include "RenderMultiColumnFlowThread.h"
using namespace std;
@@ -32,6 +33,7 @@ namespace WebCore {
RenderMultiColumnBlock::RenderMultiColumnBlock(Node* node)
: RenderBlock(node)
+ , m_flowThread(0)
, m_columnCount(1)
, m_columnWidth(0)
{
@@ -73,6 +75,22 @@ bool RenderMultiColumnBlock::recomputeLogicalWidth()
return relayoutChildren;
}
+void RenderMultiColumnBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+ if (!m_flowThread) {
+ m_flowThread = new (renderArena()) RenderMultiColumnFlowThread(document());
+ m_flowThread->setStyle(RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK));
+ RenderBlock::addChild(m_flowThread); // Always put the flow thread at the end.
+ }
+
+ // Column sets are siblings of the flow thread. All children designed to be in the columns, however, are part
+ // of the flow thread itself.
+ if (newChild->isRenderMultiColumnSet())
+ RenderBlock::addChild(newChild, beforeChild);
+ else
+ m_flowThread->addChild(newChild, beforeChild);
+}
+
const char* RenderMultiColumnBlock::renderName() const
{
if (isFloating())
diff --git a/Source/WebCore/rendering/RenderMultiColumnBlock.h b/Source/WebCore/rendering/RenderMultiColumnBlock.h
index 2ab642146..833c9bf71 100644
--- a/Source/WebCore/rendering/RenderMultiColumnBlock.h
+++ b/Source/WebCore/rendering/RenderMultiColumnBlock.h
@@ -31,6 +31,8 @@
namespace WebCore {
+class RenderMultiColumnFlowThread;
+
class RenderMultiColumnBlock : public RenderBlock {
public:
RenderMultiColumnBlock(Node*);
@@ -41,7 +43,13 @@ private:
virtual bool recomputeLogicalWidth();
void computeColumnCountAndWidth();
+ virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
+
+ RenderMultiColumnFlowThread* flowThread() const { return m_flowThread; }
+
private:
+ RenderMultiColumnFlowThread* m_flowThread;
+
unsigned m_columnCount; // The default column count/width that are based off our containing block width. These values represent only the default,
LayoutUnit m_columnWidth; // since a multi-column block that is split across variable width pages or regions will have different column counts and widths in each.
// These values will be cached (eventually) for multi-column blocks.
diff --git a/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp b/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp
index e90ef4e3c..e553c5401 100644
--- a/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp
+++ b/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp
@@ -33,6 +33,10 @@ RenderMultiColumnFlowThread::RenderMultiColumnFlowThread(Node* node)
{
}
+RenderMultiColumnFlowThread::~RenderMultiColumnFlowThread()
+{
+}
+
const char* RenderMultiColumnFlowThread::renderName() const
{
return "RenderMultiColumnFlowThread";
diff --git a/Source/WebCore/rendering/RenderMultiColumnFlowThread.h b/Source/WebCore/rendering/RenderMultiColumnFlowThread.h
index f4a0a0420..6f236d1f4 100644
--- a/Source/WebCore/rendering/RenderMultiColumnFlowThread.h
+++ b/Source/WebCore/rendering/RenderMultiColumnFlowThread.h
@@ -34,7 +34,8 @@ namespace WebCore {
class RenderMultiColumnFlowThread : public RenderFlowThread {
public:
RenderMultiColumnFlowThread(Node*);
-
+ ~RenderMultiColumnFlowThread();
+
private:
virtual const char* renderName() const OVERRIDE;
};
diff --git a/Source/WebCore/rendering/RenderMultiColumnSet.h b/Source/WebCore/rendering/RenderMultiColumnSet.h
index c5794c8df..f345a8ed3 100644
--- a/Source/WebCore/rendering/RenderMultiColumnSet.h
+++ b/Source/WebCore/rendering/RenderMultiColumnSet.h
@@ -45,6 +45,8 @@ class RenderMultiColumnSet : public RenderRegionSet {
public:
RenderMultiColumnSet(Node*, RenderFlowThread*);
+ virtual bool isRenderMultiColumnSet() const OVERRIDE { return true; }
+
private:
virtual const char* renderName() const;
};
diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp
index 4eb16b835..1cd6d36dc 100755
--- a/Source/WebCore/rendering/RenderObject.cpp
+++ b/Source/WebCore/rendering/RenderObject.cpp
@@ -46,6 +46,7 @@
#include "RenderCounter.h"
#include "RenderDeprecatedFlexibleBox.h"
#include "RenderFlexibleBox.h"
+#include "RenderGeometryMap.h"
#include "RenderImage.h"
#include "RenderImageResourceStyleImage.h"
#include "RenderInline.h"
@@ -188,9 +189,11 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style)
case BOX:
case INLINE_BOX:
return new (arena) RenderDeprecatedFlexibleBox(node);
+#if ENABLE(CSS3_FLEXBOX)
case FLEX:
case INLINE_FLEX:
return new (arena) RenderFlexibleBox(node);
+#endif
}
return 0;
@@ -219,7 +222,6 @@ RenderObject::RenderObject(Node* node)
RenderObject::~RenderObject()
{
- ASSERT(!node() || documentBeingDestroyed() || !frame()->view() || frame()->view()->layoutRoot() != this);
#ifndef NDEBUG
ASSERT(!m_hasAXObject);
renderObjectCounter.decrement();
@@ -593,14 +595,26 @@ RenderBlock* RenderObject::firstLineBlock() const
static inline bool objectIsRelayoutBoundary(const RenderObject* object)
{
- // FIXME: In future it may be possible to broaden this condition in order to improve performance.
- // Table cells are excluded because even when their CSS height is fixed, their height()
- // may depend on their contents.
- return object->isTextControl()
+ // FIXME: In future it may be possible to broaden these conditions in order to improve performance.
+ if (object->isTextControl())
+ return true;
+
#if ENABLE(SVG)
- || object->isSVGRoot()
+ if (object->isSVGRoot())
+ return true;
#endif
- || (object->hasOverflowClip() && !object->style()->width().isIntrinsicOrAuto() && !object->style()->height().isIntrinsicOrAuto() && !object->style()->height().isPercent() && !object->isTableCell());
+
+ if (!object->hasOverflowClip())
+ return false;
+
+ if (object->style()->width().isIntrinsicOrAuto() || object->style()->height().isIntrinsicOrAuto() || object->style()->height().isPercent())
+ return false;
+
+ // Table parts can't be relayout roots since the table is responsible for layouting all the parts.
+ if (object->isTablePart())
+ return false;
+
+ return true;
}
void RenderObject::markContainingBlocksForLayout(bool scheduleRelayout, RenderObject* newRoot)
@@ -2031,6 +2045,7 @@ void RenderObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b
if (!o)
return;
+ // FIXME: this should call offsetFromContainer to share code, but I'm not sure it's ever called.
LayoutPoint centerPoint = roundedLayoutPoint(transformState.mappedPoint());
if (o->isBox() && o->style()->isFlippedBlocksWritingMode())
transformState.move(toRenderBox(o)->flipForWritingModeIncludingColumns(roundedLayoutPoint(transformState.mappedPoint())) - centerPoint);
@@ -2046,6 +2061,24 @@ void RenderObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b
o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, DoNotApplyContainerFlip, wasFixed);
}
+const RenderObject* RenderObject::pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+ ASSERT_UNUSED(ancestorToStopAt, ancestorToStopAt != this);
+
+ RenderObject* container = parent();
+ if (!container)
+ return 0;
+
+ // FIXME: this should call offsetFromContainer to share code, but I'm not sure it's ever called.
+ LayoutSize offset;
+ if (container->hasOverflowClip())
+ offset = -toRenderBox(container)->scrolledContentOffset();
+
+ geometryMap.push(this, offset, hasColumns());
+
+ return container;
+}
+
void RenderObject::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const
{
RenderObject* o = parent();
@@ -2114,7 +2147,7 @@ FloatPoint RenderObject::localToContainerPoint(const FloatPoint& localPoint, Ren
return transformState.lastPlanarPoint();
}
-LayoutSize RenderObject::offsetFromContainer(RenderObject* o, const LayoutPoint& point) const
+LayoutSize RenderObject::offsetFromContainer(RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
{
ASSERT(o == container());
@@ -2125,6 +2158,9 @@ LayoutSize RenderObject::offsetFromContainer(RenderObject* o, const LayoutPoint&
if (o->hasOverflowClip())
offset -= toRenderBox(o)->scrolledContentOffset();
+ if (offsetDependsOnPoint)
+ *offsetDependsOnPoint = hasColumns();
+
return offset;
}
@@ -2200,7 +2236,7 @@ bool RenderObject::hasOutlineAnnotation() const
return node() && node()->isLink() && document()->printing();
}
-RenderObject* RenderObject::container(RenderBoxModelObject* repaintContainer, bool* repaintContainerSkipped) const
+RenderObject* RenderObject::container(const RenderBoxModelObject* repaintContainer, bool* repaintContainerSkipped) const
{
if (repaintContainerSkipped)
*repaintContainerSkipped = false;
@@ -2260,7 +2296,7 @@ bool RenderObject::isSelectionBorder() const
inline void RenderObject::clearLayoutRootIfNeeded() const
{
- if (node() && !documentBeingDestroyed() && frame()) {
+ if (!documentBeingDestroyed() && frame()) {
if (FrameView* view = frame()->view()) {
if (view->layoutRoot() == this) {
ASSERT_NOT_REACHED();
diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h
index f1032a534..ed90aac22 100644
--- a/Source/WebCore/rendering/RenderObject.h
+++ b/Source/WebCore/rendering/RenderObject.h
@@ -60,6 +60,7 @@ class RenderBoxModelObject;
class RenderInline;
class RenderBlock;
class RenderFlowThread;
+class RenderGeometryMap;
class RenderLayer;
class RenderTable;
class RenderTheme;
@@ -360,6 +361,9 @@ public:
virtual bool isRenderFlowThread() const { return false; }
virtual bool isRenderNamedFlowThread() const { return false; }
+
+ virtual bool isRenderMultiColumnSet() const { return false; }
+
virtual bool isRenderScrollbarPart() const { return false; }
bool canHaveRegionStyle() const { return isRenderBlock() && !isAnonymous() && !isRenderFlowThread(); }
@@ -583,7 +587,7 @@ public:
// Returns the object containing this one. Can be different from parent for positioned elements.
// If repaintContainer and repaintContainerSkipped are not null, on return *repaintContainerSkipped
// is true if the renderer returned is an ancestor of repaintContainer.
- RenderObject* container(RenderBoxModelObject* repaintContainer = 0, bool* repaintContainerSkipped = 0) const;
+ RenderObject* container(const RenderBoxModelObject* repaintContainer = 0, bool* repaintContainerSkipped = 0) const;
virtual RenderObject* hoverAncestor() const { return parent(); }
@@ -684,7 +688,7 @@ public:
// Return the offset from the container() renderer (excluding transforms). In multi-column layout,
// different offsets apply at different points, so return the offset that applies to the given point.
- virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&) const;
+ virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
// Return the offset from an object up the container() chain. Asserts that none of the intermediate objects have transforms.
LayoutSize offsetFromAncestorContainer(RenderObject*) const;
@@ -881,6 +885,10 @@ public:
virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const;
+ // Pushes state onto RenderGeometryMap about how to map coordinates from this renderer to its container, or ancestorToStopAt (whichever is encountered first).
+ // Returns the renderer which was mapped to (container or ancestorToStopAt).
+ virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const;
+
bool shouldUseTransformFromContainer(const RenderObject* container) const;
void getTransformFromContainer(const RenderObject* container, const LayoutSize& offsetInContainer, TransformationMatrix&) const;
diff --git a/Source/WebCore/rendering/RenderTableCell.cpp b/Source/WebCore/rendering/RenderTableCell.cpp
index 10720c2b8..99ec92d7d 100644
--- a/Source/WebCore/rendering/RenderTableCell.cpp
+++ b/Source/WebCore/rendering/RenderTableCell.cpp
@@ -240,11 +240,11 @@ void RenderTableCell::setOverrideHeightFromRowHeight(LayoutUnit rowHeight)
RenderBlock::setOverrideHeight(max<LayoutUnit>(0, rowHeight - borderBefore() - paddingBefore() - borderAfter() - paddingAfter()));
}
-LayoutSize RenderTableCell::offsetFromContainer(RenderObject* o, const LayoutPoint& point) const
+LayoutSize RenderTableCell::offsetFromContainer(RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
{
ASSERT(o == container());
- LayoutSize offset = RenderBlock::offsetFromContainer(o, point);
+ LayoutSize offset = RenderBlock::offsetFromContainer(o, point, offsetDependsOnPoint);
if (parent())
offset.expand(-parentBox()->x(), -parentBox()->y());
diff --git a/Source/WebCore/rendering/RenderTableCell.h b/Source/WebCore/rendering/RenderTableCell.h
index dac8a7606..2a5820e9e 100644
--- a/Source/WebCore/rendering/RenderTableCell.h
+++ b/Source/WebCore/rendering/RenderTableCell.h
@@ -152,7 +152,7 @@ private:
virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const OVERRIDE;
- virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&) const;
+ virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const;
virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect&, bool fixed = false) const;
diff --git a/Source/WebCore/rendering/RenderTableSection.cpp b/Source/WebCore/rendering/RenderTableSection.cpp
index 7f44a75a0..db25e8149 100644
--- a/Source/WebCore/rendering/RenderTableSection.cpp
+++ b/Source/WebCore/rendering/RenderTableSection.cpp
@@ -403,6 +403,8 @@ int RenderTableSection::calcRowLogicalHeight()
void RenderTableSection::layout()
{
ASSERT(needsLayout());
+ ASSERT(!needsCellRecalc());
+ ASSERT(!table()->needsSectionRecalc());
LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
for (RenderObject* child = children()->firstChild(); child; child = child->nextSibling()) {
diff --git a/Source/WebCore/rendering/RenderTreeAsText.cpp b/Source/WebCore/rendering/RenderTreeAsText.cpp
index 51fc41745..39319ca1f 100644
--- a/Source/WebCore/rendering/RenderTreeAsText.cpp
+++ b/Source/WebCore/rendering/RenderTreeAsText.cpp
@@ -718,7 +718,7 @@ static void writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLaye
// Calculate the clip rects we should use.
LayoutRect layerBounds;
ClipRect damageRect, clipRectToApply, outlineRect;
- l->calculateRects(rootLayer, 0, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, true);
+ l->calculateRects(rootLayer, 0, TemporaryClipRects, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
// Ensure our lists are up-to-date.
l->updateLayerListsIfNeeded();
diff --git a/Source/WebCore/rendering/RenderView.cpp b/Source/WebCore/rendering/RenderView.cpp
index 8633104e3..aadb9b9b5 100644
--- a/Source/WebCore/rendering/RenderView.cpp
+++ b/Source/WebCore/rendering/RenderView.cpp
@@ -32,6 +32,7 @@
#include "HTMLFrameOwnerElement.h"
#include "HitTestResult.h"
#include "Page.h"
+#include "RenderGeometryMap.h"
#include "RenderLayer.h"
#include "RenderNamedFlowThread.h"
#include "RenderSelectionInfo.h"
@@ -167,6 +168,27 @@ void RenderView::mapLocalToContainer(RenderBoxModelObject* repaintContainer, boo
transformState.move(m_frameView->scrollOffsetForFixedPosition());
}
+const RenderObject* RenderView::pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+ // If a container was specified, and was not 0 or the RenderView,
+ // then we should have found it by now.
+ ASSERT_ARG(ancestorToStopAt, !ancestorToStopAt || ancestorToStopAt == this);
+
+ LayoutSize scrollOffset;
+
+ if (m_frameView)
+ scrollOffset = m_frameView->scrollOffsetForFixedPosition();
+
+ if (!ancestorToStopAt && shouldUseTransformFromContainer(0)) {
+ TransformationMatrix t;
+ getTransformFromContainer(0, LayoutSize(), t);
+ geometryMap.pushView(this, scrollOffset, &t);
+ } else
+ geometryMap.pushView(this, scrollOffset);
+
+ return 0;
+}
+
void RenderView::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const
{
if (fixed && m_frameView)
@@ -733,10 +755,10 @@ LayoutRect RenderView::backgroundRect(RenderBox* backgroundRenderer) const
IntRect RenderView::documentRect() const
{
- IntRect overflowRect(unscaledDocumentRect());
+ FloatRect overflowRect(unscaledDocumentRect());
if (hasTransform())
overflowRect = layer()->currentTransform().mapRect(overflowRect);
- return overflowRect;
+ return IntRect(overflowRect);
}
int RenderView::viewHeight() const
diff --git a/Source/WebCore/rendering/RenderView.h b/Source/WebCore/rendering/RenderView.h
index 4ac061f72..e6a5722d8 100644
--- a/Source/WebCore/rendering/RenderView.h
+++ b/Source/WebCore/rendering/RenderView.h
@@ -188,6 +188,7 @@ public:
protected:
virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
+ virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const;
virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const;
virtual bool requiresColumns(int desiredColumnCount) const OVERRIDE;
diff --git a/Source/WebCore/rendering/RenderingAllInOne.cpp b/Source/WebCore/rendering/RenderingAllInOne.cpp
index ff8e0731e..d17bd313a 100644
--- a/Source/WebCore/rendering/RenderingAllInOne.cpp
+++ b/Source/WebCore/rendering/RenderingAllInOne.cpp
@@ -75,6 +75,8 @@
#include "RenderMenuList.cpp"
#include "RenderMeter.cpp"
#include "RenderMultiColumnBlock.cpp"
+#include "RenderMultiColumnFlowThread.cpp"
+#include "RenderMultiColumnSet.cpp"
#include "RenderObject.cpp"
#include "RenderObjectChildList.cpp"
#include "RenderPart.cpp"
diff --git a/Source/WebCore/rendering/style/RenderStyleConstants.h b/Source/WebCore/rendering/style/RenderStyleConstants.h
index ba7677b10..55c739a07 100644
--- a/Source/WebCore/rendering/style/RenderStyleConstants.h
+++ b/Source/WebCore/rendering/style/RenderStyleConstants.h
@@ -409,8 +409,10 @@ enum EDisplay {
TABLE, INLINE_TABLE, TABLE_ROW_GROUP,
TABLE_HEADER_GROUP, TABLE_FOOTER_GROUP, TABLE_ROW,
TABLE_COLUMN_GROUP, TABLE_COLUMN, TABLE_CELL,
- TABLE_CAPTION, BOX, INLINE_BOX,
+ TABLE_CAPTION, BOX, INLINE_BOX,
+#if ENABLE(CSS3_FLEXBOX)
FLEX, INLINE_FLEX,
+#endif
GRID, INLINE_GRID,
NONE
};
diff --git a/Source/WebCore/rendering/svg/RenderSVGBlock.cpp b/Source/WebCore/rendering/svg/RenderSVGBlock.cpp
index cf44efff1..c4f9a284d 100644
--- a/Source/WebCore/rendering/svg/RenderSVGBlock.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGBlock.cpp
@@ -104,12 +104,6 @@ void RenderSVGBlock::styleDidChange(StyleDifference diff, const RenderStyle* old
SVGResourcesCache::clientStyleChanged(this, diff, style());
}
-void RenderSVGBlock::updateFromElement()
-{
- RenderBlock::updateFromElement();
- SVGResourcesCache::clientUpdatedFromElement(this, style());
-}
-
}
#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGBlock.h b/Source/WebCore/rendering/svg/RenderSVGBlock.h
index 9ef55a919..7f5b78532 100644
--- a/Source/WebCore/rendering/svg/RenderSVGBlock.h
+++ b/Source/WebCore/rendering/svg/RenderSVGBlock.h
@@ -45,7 +45,6 @@ private:
virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
- virtual void updateFromElement();
};
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp
index a1fd8321d..7b2866113 100644
--- a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp
@@ -87,6 +87,19 @@ void RenderSVGContainer::layout()
setNeedsLayout(false);
}
+void RenderSVGContainer::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+ RenderSVGModelObject::addChild(child, beforeChild);
+ SVGResourcesCache::clientWasAddedToTree(child, child->style());
+}
+
+void RenderSVGContainer::removeChild(RenderObject* child)
+{
+ SVGResourcesCache::clientWillBeRemovedFromTree(child);
+ RenderSVGModelObject::removeChild(child);
+}
+
+
bool RenderSVGContainer::selfWillPaint()
{
SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.h b/Source/WebCore/rendering/svg/RenderSVGContainer.h
index 5be036638..335732b84 100644
--- a/Source/WebCore/rendering/svg/RenderSVGContainer.h
+++ b/Source/WebCore/rendering/svg/RenderSVGContainer.h
@@ -53,6 +53,8 @@ protected:
virtual void layout();
+ virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
+ virtual void removeChild(RenderObject*) OVERRIDE;
virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint&);
virtual FloatRect objectBoundingBox() const { return m_objectBoundingBox; }
diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
index 2918fe3a9..074944066 100644
--- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
@@ -193,6 +193,11 @@ void RenderSVGForeignObject::mapLocalToContainer(RenderBoxModelObject* repaintCo
SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
}
+const RenderObject* RenderSVGForeignObject::pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+ return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
+}
+
}
#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
index 4a1a8ac25..8fe0864c1 100644
--- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
+++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
@@ -55,6 +55,7 @@ public:
virtual bool isSVGForeignObject() const { return true; }
virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
+ virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const;
virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
private:
diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.cpp b/Source/WebCore/rendering/svg/RenderSVGInline.cpp
index bb1a367ac..057bfda00 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInline.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGInline.cpp
@@ -84,6 +84,11 @@ void RenderSVGInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer
SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
}
+const RenderObject* RenderSVGInline::pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+ return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
+}
+
void RenderSVGInline::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
{
const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this);
@@ -114,21 +119,19 @@ void RenderSVGInline::styleDidChange(StyleDifference diff, const RenderStyle* ol
SVGResourcesCache::clientStyleChanged(this, diff, style());
}
-void RenderSVGInline::updateFromElement()
-{
- RenderInline::updateFromElement();
- SVGResourcesCache::clientUpdatedFromElement(this, style());
-}
-
void RenderSVGInline::addChild(RenderObject* child, RenderObject* beforeChild)
{
RenderInline::addChild(child, beforeChild);
+ SVGResourcesCache::clientWasAddedToTree(child, child->style());
+
if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
textRenderer->subtreeChildWasAdded(child);
}
void RenderSVGInline::removeChild(RenderObject* child)
{
+ SVGResourcesCache::clientWillBeRemovedFromTree(child);
+
RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this);
if (!textRenderer) {
RenderInline::removeChild(child);
diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.h b/Source/WebCore/rendering/svg/RenderSVGInline.h
index 172062196..533a99aa6 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInline.h
+++ b/Source/WebCore/rendering/svg/RenderSVGInline.h
@@ -48,6 +48,7 @@ public:
virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const;
virtual void computeFloatRectForRepaint(RenderBoxModelObject* repaintContainer, FloatRect&, bool fixed = false) const;
virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
+ virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const;
virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
private:
@@ -56,9 +57,8 @@ private:
virtual void willBeDestroyed();
virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
- virtual void updateFromElement();
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+ virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
virtual void removeChild(RenderObject*) OVERRIDE;
};
diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
index 48fd7d879..c1c27b09a 100644
--- a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
@@ -60,6 +60,11 @@ void RenderSVGModelObject::mapLocalToContainer(RenderBoxModelObject* repaintCont
SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
}
+const RenderObject* RenderSVGModelObject::pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+ return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
+}
+
// Copied from RenderBox, this method likely requires further refactoring to work easily for both SVG and CSS Box Model content.
// FIXME: This may also need to move into SVGRenderSupport as the RenderBox version depends
// on borderBoundingBox() which SVG RenderBox subclases (like SVGRenderBlock) do not implement.
@@ -106,12 +111,6 @@ void RenderSVGModelObject::styleDidChange(StyleDifference diff, const RenderStyl
SVGResourcesCache::clientStyleChanged(this, diff, style());
}
-void RenderSVGModelObject::updateFromElement()
-{
- RenderObject::updateFromElement();
- SVGResourcesCache::clientUpdatedFromElement(this, style());
-}
-
bool RenderSVGModelObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint&, const LayoutPoint&, HitTestAction)
{
ASSERT_NOT_REACHED();
diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.h b/Source/WebCore/rendering/svg/RenderSVGModelObject.h
index b9692fe1d..d82600f57 100644
--- a/Source/WebCore/rendering/svg/RenderSVGModelObject.h
+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.h
@@ -59,9 +59,9 @@ public:
virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
+ virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const;
virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
- virtual void updateFromElement();
static bool checkIntersection(RenderObject*, const FloatRect&);
static bool checkEnclosure(RenderObject*, const FloatRect&);
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp
index 3dba672dd..80760fd48 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp
@@ -165,7 +165,7 @@ void RenderSVGResourceContainer::registerResource()
RenderObject* renderer = (*it)->renderer();
if (!renderer)
continue;
- SVGResourcesCache::clientUpdatedFromElement(renderer, renderer->style());
+ SVGResourcesCache::clientStyleChanged(renderer, StyleDifferenceLayout, renderer->style());
renderer->setNeedsLayout(true);
}
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
index 941185f55..663245333 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
@@ -326,10 +326,16 @@ void RenderSVGRoot::styleDidChange(StyleDifference diff, const RenderStyle* oldS
SVGResourcesCache::clientStyleChanged(this, diff, style());
}
-void RenderSVGRoot::updateFromElement()
+void RenderSVGRoot::addChild(RenderObject* child, RenderObject* beforeChild)
{
- RenderReplaced::updateFromElement();
- SVGResourcesCache::clientUpdatedFromElement(this, style());
+ RenderReplaced::addChild(child, beforeChild);
+ SVGResourcesCache::clientWasAddedToTree(child, child->style());
+}
+
+void RenderSVGRoot::removeChild(RenderObject* child)
+{
+ SVGResourcesCache::clientWillBeRemovedFromTree(child);
+ RenderReplaced::removeChild(child);
}
// RenderBox methods will expect coordinates w/o any transforms in coordinates
@@ -391,6 +397,11 @@ void RenderSVGRoot::mapLocalToContainer(RenderBoxModelObject* repaintContainer,
RenderReplaced::mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, ApplyContainerFlip, wasFixed);
}
+const RenderObject* RenderSVGRoot::pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+ return RenderReplaced::pushMappingToContainer(ancestorToStopAt, geometryMap);
+}
+
void RenderSVGRoot::updateCachedBoundaries()
{
m_objectBoundingBox = FloatRect();
diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.h b/Source/WebCore/rendering/svg/RenderSVGRoot.h
index c334afbe6..6fb569468 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRoot.h
+++ b/Source/WebCore/rendering/svg/RenderSVGRoot.h
@@ -78,7 +78,8 @@ private:
virtual void willBeDestroyed();
virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
- virtual void updateFromElement();
+ virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
+ virtual void removeChild(RenderObject*) OVERRIDE;
virtual const AffineTransform& localToParentTransform() const;
@@ -95,6 +96,8 @@ private:
virtual void computeFloatRectForRepaint(RenderBoxModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const;
virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
+ virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const;
+
virtual bool canBeSelectionLeaf() const { return false; }
virtual bool canHaveChildren() const { return true; }
diff --git a/Source/WebCore/rendering/svg/RenderSVGText.cpp b/Source/WebCore/rendering/svg/RenderSVGText.cpp
index d918453c5..a2cae7dbb 100644
--- a/Source/WebCore/rendering/svg/RenderSVGText.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGText.cpp
@@ -115,6 +115,11 @@ void RenderSVGText::mapLocalToContainer(RenderBoxModelObject* repaintContainer,
SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
}
+const RenderObject* RenderSVGText::pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+ return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
+}
+
static inline void collectLayoutAttributes(RenderObject* text, Vector<SVGTextLayoutAttributes*>& attributes)
{
for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) {
@@ -524,11 +529,15 @@ FloatRect RenderSVGText::repaintRectInLocalCoordinates() const
void RenderSVGText::addChild(RenderObject* child, RenderObject* beforeChild)
{
RenderSVGBlock::addChild(child, beforeChild);
+
+ SVGResourcesCache::clientWasAddedToTree(child, child->style());
subtreeChildWasAdded(child);
}
void RenderSVGText::removeChild(RenderObject* child)
{
+ SVGResourcesCache::clientWillBeRemovedFromTree(child);
+
Vector<SVGTextLayoutAttributes*, 2> affectedAttributes;
FontCachePurgePreventer fontCachePurgePreventer;
subtreeChildWillBeRemoved(child, affectedAttributes);
diff --git a/Source/WebCore/rendering/svg/RenderSVGText.h b/Source/WebCore/rendering/svg/RenderSVGText.h
index 56723f6c1..af950c341 100644
--- a/Source/WebCore/rendering/svg/RenderSVGText.h
+++ b/Source/WebCore/rendering/svg/RenderSVGText.h
@@ -76,6 +76,7 @@ private:
virtual void computeFloatRectForRepaint(RenderBoxModelObject* repaintContainer, FloatRect&, bool fixed = false) const;
virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
+ virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const;
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
virtual void removeChild(RenderObject*) OVERRIDE;
virtual void willBeDestroyed() OVERRIDE;
diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
index ddc7c9155..177ce9c44 100644
--- a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
+++ b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
@@ -28,6 +28,7 @@
#include "SVGRenderSupport.h"
#include "NodeRenderStyle.h"
+#include "RenderGeometryMap.h"
#include "RenderLayer.h"
#include "RenderSVGResource.h"
#include "RenderSVGResourceClipper.h"
@@ -85,6 +86,23 @@ void SVGRenderSupport::mapLocalToContainer(const RenderObject* object, RenderBox
parent->mapLocalToContainer(repaintContainer, false, true, transformState, RenderObject::DoNotApplyContainerFlip, wasFixed);
}
+const RenderObject* SVGRenderSupport::pushMappingToContainer(const RenderObject* object, const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap)
+{
+ ASSERT_UNUSED(ancestorToStopAt, ancestorToStopAt != object);
+
+ RenderObject* parent = object->parent();
+
+ // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform
+ // to map an element from SVG viewport coordinates to CSS box coordinates.
+ // RenderSVGRoot's mapLocalToContainer method expects CSS box coordinates.
+ if (parent->isSVGRoot())
+ geometryMap.push(object, TransformationMatrix(toRenderSVGRoot(parent)->localToBorderBoxTransform()));
+ else
+ geometryMap.push(object, LayoutSize());
+
+ return parent;
+}
+
// Update a bounding box taking into account the validity of the other bounding box.
static inline void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox)
{
diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.h b/Source/WebCore/rendering/svg/SVGRenderSupport.h
index e25b12f06..fa960f05e 100644
--- a/Source/WebCore/rendering/svg/SVGRenderSupport.h
+++ b/Source/WebCore/rendering/svg/SVGRenderSupport.h
@@ -34,6 +34,7 @@ class FloatPoint;
class FloatRect;
class ImageBuffer;
class RenderBoxModelObject;
+class RenderGeometryMap;
class RenderObject;
class RenderStyle;
class RenderSVGRoot;
@@ -64,6 +65,7 @@ public:
static LayoutRect clippedOverflowRectForRepaint(const RenderObject*, RenderBoxModelObject* repaintContainer);
static void computeFloatRectForRepaint(const RenderObject*, RenderBoxModelObject* repaintContainer, FloatRect&, bool fixed);
static void mapLocalToContainer(const RenderObject*, RenderBoxModelObject* repaintContainer, TransformState&, bool* wasFixed = 0);
+ static const RenderObject* pushMappingToContainer(const RenderObject*, const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&);
// Shared between SVG renderers and resources.
static void applyStrokeStyleToContext(GraphicsContext*, const RenderStyle*, const RenderObject*);
diff --git a/Source/WebCore/rendering/svg/SVGResourcesCache.cpp b/Source/WebCore/rendering/svg/SVGResourcesCache.cpp
index 1715f6c04..87531ed3e 100644
--- a/Source/WebCore/rendering/svg/SVGResourcesCache.cpp
+++ b/Source/WebCore/rendering/svg/SVGResourcesCache.cpp
@@ -128,24 +128,44 @@ void SVGResourcesCache::clientLayoutChanged(RenderObject* object)
void SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifference diff, const RenderStyle* newStyle)
{
ASSERT(renderer);
- if (diff == StyleDifferenceEqual)
+ if (diff == StyleDifferenceEqual || !renderer->parent())
return;
// In this case the proper SVGFE*Element will decide whether the modified CSS properties require a relayout or repaint.
if (renderer->isSVGResourceFilterPrimitive() && diff == StyleDifferenceRepaint)
return;
- clientUpdatedFromElement(renderer, newStyle);
+ // Dynamic changes of CSS properties like 'clip-path' may require us to recompute the associated resources for a renderer.
+ // FIXME: Avoid passing in a useless StyleDifference, but instead compare oldStyle/newStyle to see which resources changed
+ // to be able to selectively rebuild individual resources, instead of all of them.
+ SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
+ cache->removeResourcesFromRenderObject(renderer);
+ cache->addResourcesFromRenderObject(renderer, newStyle);
+
+ RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
}
-void SVGResourcesCache::clientUpdatedFromElement(RenderObject* renderer, const RenderStyle* newStyle)
+static inline bool rendererCanHaveResources(RenderObject* renderer)
{
ASSERT(renderer);
ASSERT(renderer->parent());
+ return renderer->node() && !renderer->isSVGInlineText();
+}
+void SVGResourcesCache::clientWasAddedToTree(RenderObject* renderer, const RenderStyle* newStyle)
+{
+ if (!rendererCanHaveResources(renderer))
+ return;
SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
- cache->removeResourcesFromRenderObject(renderer);
cache->addResourcesFromRenderObject(renderer, newStyle);
+}
+
+void SVGResourcesCache::clientWillBeRemovedFromTree(RenderObject* renderer)
+{
+ if (!rendererCanHaveResources(renderer))
+ return;
+ SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
+ cache->removeResourcesFromRenderObject(renderer);
RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
}
diff --git a/Source/WebCore/rendering/svg/SVGResourcesCache.h b/Source/WebCore/rendering/svg/SVGResourcesCache.h
index 72e526a67..633fcd73d 100644
--- a/Source/WebCore/rendering/svg/SVGResourcesCache.h
+++ b/Source/WebCore/rendering/svg/SVGResourcesCache.h
@@ -37,10 +37,14 @@ public:
SVGResourcesCache();
~SVGResourcesCache();
- void addResourcesFromRenderObject(RenderObject*, const RenderStyle*);
- void removeResourcesFromRenderObject(RenderObject*);
static SVGResources* cachedResourcesForRenderObject(const RenderObject*);
+ // Called from all SVG renderers addChild() methods.
+ static void clientWasAddedToTree(RenderObject*, const RenderStyle* newStyle);
+
+ // Called from all SVG renderers removeChild() methods.
+ static void clientWillBeRemovedFromTree(RenderObject*);
+
// Called from all SVG renderers destroy() methods - except for RenderSVGResourceContainer.
static void clientDestroyed(RenderObject*);
@@ -50,13 +54,13 @@ public:
// Called from all SVG renderers styleDidChange() methods.
static void clientStyleChanged(RenderObject*, StyleDifference, const RenderStyle* newStyle);
- // Called from all SVG renderers updateFromElement() methods.
- static void clientUpdatedFromElement(RenderObject*, const RenderStyle* newStyle);
-
// Called from RenderSVGResourceContainer::willBeDestroyed().
static void resourceDestroyed(RenderSVGResourceContainer*);
private:
+ void addResourcesFromRenderObject(RenderObject*, const RenderStyle*);
+ void removeResourcesFromRenderObject(RenderObject*);
+
HashMap<const RenderObject*, SVGResources*> m_cache;
};