Commit 7647e23c authored by bjonesbe@adobe.com's avatar bjonesbe@adobe.com

Refactor ShapeOutsideInfo so it isn't mutated for each line

Encapsulate the per line state into a ShapeOutsideDeltas object.
updateDeltasForContainingBlockLine has been renamed to
computeDeltasForContainingBlockLine, and it returns an instance of the
ShapeOutsideDeltas object for that line.  This object is cached, but
none of the functionality of ShapeOutsideInfo is dependant on any line
specific data anymore.

Review URL: https://codereview.chromium.org/460103002

git-svn-id: svn://svn.chromium.org/blink/trunk@180483 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent f8e38eab
...@@ -120,7 +120,7 @@ public: ...@@ -120,7 +120,7 @@ public:
LayoutUnit offset() const { return m_offset; } LayoutUnit offset() const { return m_offset; }
protected: protected:
virtual bool updateOffsetIfNeeded(const FloatingObject*) = 0; virtual bool updateOffsetIfNeeded(const FloatingObject&) = 0;
const RenderBlockFlow* m_renderer; const RenderBlockFlow* m_renderer;
int m_lineTop; int m_lineTop;
...@@ -142,7 +142,7 @@ public: ...@@ -142,7 +142,7 @@ public:
LayoutUnit heightRemaining() const; LayoutUnit heightRemaining() const;
protected: protected:
virtual bool updateOffsetIfNeeded(const FloatingObject*) OVERRIDE FINAL; virtual bool updateOffsetIfNeeded(const FloatingObject&) OVERRIDE FINAL;
}; };
template <FloatingObject::Type FloatTypeValue> template <FloatingObject::Type FloatTypeValue>
...@@ -156,7 +156,7 @@ public: ...@@ -156,7 +156,7 @@ public:
virtual ~ComputeFloatOffsetForLineLayoutAdapter() { } virtual ~ComputeFloatOffsetForLineLayoutAdapter() { }
protected: protected:
virtual bool updateOffsetIfNeeded(const FloatingObject*) OVERRIDE FINAL; virtual bool updateOffsetIfNeeded(const FloatingObject&) OVERRIDE FINAL;
}; };
...@@ -436,9 +436,9 @@ inline static bool rangesIntersect(int floatTop, int floatBottom, int objectTop, ...@@ -436,9 +436,9 @@ inline static bool rangesIntersect(int floatTop, int floatBottom, int objectTop,
} }
template<> template<>
inline bool ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatLeft>::updateOffsetIfNeeded(const FloatingObject* floatingObject) inline bool ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatLeft>::updateOffsetIfNeeded(const FloatingObject& floatingObject)
{ {
LayoutUnit logicalRight = m_renderer->logicalRightForFloat(floatingObject); LayoutUnit logicalRight = m_renderer->logicalRightForFloat(&floatingObject);
if (logicalRight > m_offset) { if (logicalRight > m_offset) {
m_offset = logicalRight; m_offset = logicalRight;
return true; return true;
...@@ -447,9 +447,9 @@ inline bool ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatLeft>:: ...@@ -447,9 +447,9 @@ inline bool ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatLeft>::
} }
template<> template<>
inline bool ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatRight>::updateOffsetIfNeeded(const FloatingObject* floatingObject) inline bool ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatRight>::updateOffsetIfNeeded(const FloatingObject& floatingObject)
{ {
LayoutUnit logicalLeft = m_renderer->logicalLeftForFloat(floatingObject); LayoutUnit logicalLeft = m_renderer->logicalLeftForFloat(&floatingObject);
if (logicalLeft < m_offset) { if (logicalLeft < m_offset) {
m_offset = logicalLeft; m_offset = logicalLeft;
return true; return true;
...@@ -475,31 +475,21 @@ inline void ComputeFloatOffsetAdapter<FloatTypeValue>::collectIfNeeded(const Int ...@@ -475,31 +475,21 @@ inline void ComputeFloatOffsetAdapter<FloatTypeValue>::collectIfNeeded(const Int
ASSERT(interval.low() == m_renderer->pixelSnappedLogicalTopForFloat(floatingObject)); ASSERT(interval.low() == m_renderer->pixelSnappedLogicalTopForFloat(floatingObject));
ASSERT(interval.high() == m_renderer->pixelSnappedLogicalBottomForFloat(floatingObject)); ASSERT(interval.high() == m_renderer->pixelSnappedLogicalBottomForFloat(floatingObject));
bool floatIsNewExtreme = updateOffsetIfNeeded(floatingObject); bool floatIsNewExtreme = updateOffsetIfNeeded(*floatingObject);
if (floatIsNewExtreme) if (floatIsNewExtreme)
m_outermostFloat = floatingObject; m_outermostFloat = floatingObject;
} }
static inline ShapeOutsideInfo* shapeInfoForFloat(const FloatingObject& floatingObject, const RenderBlockFlow& containingBlock, LayoutUnit lineTop, LayoutUnit lineBottom)
{
if (ShapeOutsideInfo* shapeOutside = floatingObject.renderer()->shapeOutsideInfo()) {
shapeOutside->updateDeltasForContainingBlockLine(containingBlock, floatingObject, lineTop, lineBottom - lineTop);
return shapeOutside;
}
return 0;
}
template<> template<>
inline bool ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatLeft>::updateOffsetIfNeeded(const FloatingObject* floatingObject) inline bool ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatLeft>::updateOffsetIfNeeded(const FloatingObject& floatingObject)
{ {
ASSERT(floatingObject); LayoutUnit logicalRight = m_renderer->logicalRightForFloat(&floatingObject);
LayoutUnit logicalRight = m_renderer->logicalRightForFloat(floatingObject); if (ShapeOutsideInfo* shapeOutside = floatingObject.renderer()->shapeOutsideInfo()) {
if (ShapeOutsideInfo* shapeOutside = shapeInfoForFloat(*floatingObject, *m_renderer, m_lineTop, m_lineBottom)) { ShapeOutsideDeltas shapeDeltas = shapeOutside->computeDeltasForContainingBlockLine(*m_renderer, floatingObject, m_lineTop, m_lineBottom - m_lineTop);
if (!shapeOutside->lineOverlapsShape()) if (!shapeDeltas.lineOverlapsShape())
return false; return false;
logicalRight += shapeOutside->rightMarginBoxDelta(); logicalRight += shapeDeltas.rightMarginBoxDelta();
} }
if (logicalRight > m_offset) { if (logicalRight > m_offset) {
m_offset = logicalRight; m_offset = logicalRight;
...@@ -510,15 +500,15 @@ inline bool ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatLeft>::u ...@@ -510,15 +500,15 @@ inline bool ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatLeft>::u
} }
template<> template<>
inline bool ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatRight>::updateOffsetIfNeeded(const FloatingObject* floatingObject) inline bool ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatRight>::updateOffsetIfNeeded(const FloatingObject& floatingObject)
{ {
ASSERT(floatingObject); LayoutUnit logicalLeft = m_renderer->logicalLeftForFloat(&floatingObject);
LayoutUnit logicalLeft = m_renderer->logicalLeftForFloat(floatingObject); if (ShapeOutsideInfo* shapeOutside = floatingObject.renderer()->shapeOutsideInfo()) {
if (ShapeOutsideInfo* shapeOutside = shapeInfoForFloat(*floatingObject, *m_renderer, m_lineTop, m_lineBottom)) { ShapeOutsideDeltas shapeDeltas = shapeOutside->computeDeltasForContainingBlockLine(*m_renderer, floatingObject, m_lineTop, m_lineBottom - m_lineTop);
if (!shapeOutside->lineOverlapsShape()) if (!shapeDeltas.lineOverlapsShape())
return false; return false;
logicalLeft += shapeOutside->leftMarginBoxDelta(); logicalLeft += shapeDeltas.leftMarginBoxDelta();
} }
if (logicalLeft < m_offset) { if (logicalLeft < m_offset) {
m_offset = logicalLeft; m_offset = logicalLeft;
......
...@@ -66,17 +66,17 @@ void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject* newFloat ...@@ -66,17 +66,17 @@ void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject* newFloat
if (height < m_block.logicalTopForFloat(newFloat) || height >= m_block.logicalBottomForFloat(newFloat)) if (height < m_block.logicalTopForFloat(newFloat) || height >= m_block.logicalBottomForFloat(newFloat))
return; return;
ShapeOutsideInfo* shapeOutsideInfo = newFloat->renderer()->shapeOutsideInfo(); ShapeOutsideDeltas shapeDeltas;
if (shapeOutsideInfo) { if (ShapeOutsideInfo* shapeOutsideInfo = newFloat->renderer()->shapeOutsideInfo()) {
LayoutUnit lineHeight = m_block.lineHeight(m_isFirstLine, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); LayoutUnit lineHeight = m_block.lineHeight(m_isFirstLine, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
shapeOutsideInfo->updateDeltasForContainingBlockLine(m_block, *newFloat, m_block.logicalHeight(), lineHeight); shapeDeltas = shapeOutsideInfo->computeDeltasForContainingBlockLine(m_block, *newFloat, m_block.logicalHeight(), lineHeight);
} }
if (newFloat->type() == FloatingObject::FloatLeft) { if (newFloat->type() == FloatingObject::FloatLeft) {
float newLeft = m_block.logicalRightForFloat(newFloat).toFloat(); float newLeft = m_block.logicalRightForFloat(newFloat).toFloat();
if (shapeOutsideInfo) { if (shapeDeltas.isValid()) {
if (shapeOutsideInfo->lineOverlapsShape()) if (shapeDeltas.lineOverlapsShape())
newLeft += shapeOutsideInfo->rightMarginBoxDelta(); newLeft += shapeDeltas.rightMarginBoxDelta();
else // Per the CSS Shapes spec, If the line doesn't overlap the shape, then ignore this shape for this line. else // Per the CSS Shapes spec, If the line doesn't overlap the shape, then ignore this shape for this line.
newLeft = m_left; newLeft = m_left;
} }
...@@ -85,9 +85,9 @@ void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject* newFloat ...@@ -85,9 +85,9 @@ void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject* newFloat
m_left = std::max<float>(m_left, newLeft); m_left = std::max<float>(m_left, newLeft);
} else { } else {
float newRight = m_block.logicalLeftForFloat(newFloat).toFloat(); float newRight = m_block.logicalLeftForFloat(newFloat).toFloat();
if (shapeOutsideInfo) { if (shapeDeltas.isValid()) {
if (shapeOutsideInfo->lineOverlapsShape()) if (shapeDeltas.lineOverlapsShape())
newRight += shapeOutsideInfo->leftMarginBoxDelta(); newRight += shapeDeltas.leftMarginBoxDelta();
else // Per the CSS Shapes spec, If the line doesn't overlap the shape, then ignore this shape for this line. else // Per the CSS Shapes spec, If the line doesn't overlap the shape, then ignore this shape for this line.
newRight = m_right; newRight = m_right;
} }
......
...@@ -274,42 +274,40 @@ bool ShapeOutsideInfo::isEnabledFor(const RenderBox& box) ...@@ -274,42 +274,40 @@ bool ShapeOutsideInfo::isEnabledFor(const RenderBox& box)
return false; return false;
} }
void ShapeOutsideInfo::updateDeltasForContainingBlockLine(const RenderBlockFlow& containingBlock, const FloatingObject& floatingObject, LayoutUnit lineTop, LayoutUnit lineHeight) ShapeOutsideDeltas ShapeOutsideInfo::computeDeltasForContainingBlockLine(const RenderBlockFlow& containingBlock, const FloatingObject& floatingObject, LayoutUnit lineTop, LayoutUnit lineHeight)
{ {
ASSERT(lineHeight >= 0); ASSERT(lineHeight >= 0);
LayoutUnit borderBoxTop = containingBlock.logicalTopForFloat(&floatingObject) + containingBlock.marginBeforeForChild(&m_renderer); LayoutUnit borderBoxTop = containingBlock.logicalTopForFloat(&floatingObject) + containingBlock.marginBeforeForChild(&m_renderer);
LayoutUnit borderBoxLineTop = lineTop - borderBoxTop; LayoutUnit borderBoxLineTop = lineTop - borderBoxTop;
if (isShapeDirty() || m_borderBoxLineTop != borderBoxLineTop || m_lineHeight != lineHeight) { if (isShapeDirty() || !m_shapeOutsideDeltas.isForLine(borderBoxLineTop, lineHeight)) {
m_borderBoxLineTop = borderBoxLineTop; LayoutUnit referenceBoxLineTop = borderBoxLineTop - logicalTopOffset();
m_referenceBoxLineTop = borderBoxLineTop - logicalTopOffset();
m_lineHeight = lineHeight;
LayoutUnit floatMarginBoxWidth = containingBlock.logicalWidthForFloat(&floatingObject); LayoutUnit floatMarginBoxWidth = containingBlock.logicalWidthForFloat(&floatingObject);
if (lineOverlapsShapeBounds()) { if (computedShape().lineOverlapsShapeMarginBounds(referenceBoxLineTop, lineHeight)) {
LineSegment segment = computedShape().getExcludedInterval((borderBoxLineTop - logicalTopOffset()), std::min(lineHeight, shapeLogicalBottom() - borderBoxLineTop)); LineSegment segment = computedShape().getExcludedInterval((borderBoxLineTop - logicalTopOffset()), std::min(lineHeight, shapeLogicalBottom() - borderBoxLineTop));
if (segment.isValid) { if (segment.isValid) {
LayoutUnit logicalLeftMargin = containingBlock.style()->isLeftToRightDirection() ? containingBlock.marginStartForChild(&m_renderer) : containingBlock.marginEndForChild(&m_renderer); LayoutUnit logicalLeftMargin = containingBlock.style()->isLeftToRightDirection() ? containingBlock.marginStartForChild(&m_renderer) : containingBlock.marginEndForChild(&m_renderer);
LayoutUnit rawLeftMarginBoxDelta = segment.logicalLeft + logicalLeftOffset() + logicalLeftMargin; LayoutUnit rawLeftMarginBoxDelta = segment.logicalLeft + logicalLeftOffset() + logicalLeftMargin;
m_leftMarginBoxDelta = clampToLayoutUnit(rawLeftMarginBoxDelta, LayoutUnit(), floatMarginBoxWidth); LayoutUnit leftMarginBoxDelta = clampTo<LayoutUnit>(rawLeftMarginBoxDelta, LayoutUnit(), floatMarginBoxWidth);
LayoutUnit logicalRightMargin = containingBlock.style()->isLeftToRightDirection() ? containingBlock.marginEndForChild(&m_renderer) : containingBlock.marginStartForChild(&m_renderer); LayoutUnit logicalRightMargin = containingBlock.style()->isLeftToRightDirection() ? containingBlock.marginEndForChild(&m_renderer) : containingBlock.marginStartForChild(&m_renderer);
LayoutUnit rawRightMarginBoxDelta = segment.logicalRight + logicalLeftOffset() - containingBlock.logicalWidthForChild(&m_renderer) - logicalRightMargin; LayoutUnit rawRightMarginBoxDelta = segment.logicalRight + logicalLeftOffset() - containingBlock.logicalWidthForChild(&m_renderer) - logicalRightMargin;
m_rightMarginBoxDelta = clampToLayoutUnit(rawRightMarginBoxDelta, -floatMarginBoxWidth, LayoutUnit()); LayoutUnit rightMarginBoxDelta = clampTo<LayoutUnit>(rawRightMarginBoxDelta, -floatMarginBoxWidth, LayoutUnit());
m_lineOverlapsShape = true;
return; m_shapeOutsideDeltas = ShapeOutsideDeltas(leftMarginBoxDelta, rightMarginBoxDelta, true, borderBoxLineTop, lineHeight);
return m_shapeOutsideDeltas;
} }
} }
// Lines that do not overlap the shape should act as if the float // Lines that do not overlap the shape should act as if the float
// wasn't there for layout purposes. So we set the deltas to remove the // wasn't there for layout purposes. So we set the deltas to remove the
// entire width of the float. // entire width of the float.
m_leftMarginBoxDelta = floatMarginBoxWidth; m_shapeOutsideDeltas = ShapeOutsideDeltas(floatMarginBoxWidth, -floatMarginBoxWidth, false, borderBoxLineTop, lineHeight);
m_rightMarginBoxDelta = -floatMarginBoxWidth;
m_lineOverlapsShape = false;
} }
return m_shapeOutsideDeltas;
} }
LayoutRect ShapeOutsideInfo::computedShapePhysicalBoundingBox() const LayoutRect ShapeOutsideInfo::computedShapePhysicalBoundingBox() const
......
...@@ -43,6 +43,43 @@ class RenderBlockFlow; ...@@ -43,6 +43,43 @@ class RenderBlockFlow;
class RenderBox; class RenderBox;
class FloatingObject; class FloatingObject;
class ShapeOutsideDeltas FINAL {
public:
ShapeOutsideDeltas()
: m_lineOverlapsShape(false)
, m_isValid(false)
{
}
ShapeOutsideDeltas(LayoutUnit leftMarginBoxDelta, LayoutUnit rightMarginBoxDelta, bool lineOverlapsShape, LayoutUnit borderBoxLineTop, LayoutUnit lineHeight)
: m_leftMarginBoxDelta(leftMarginBoxDelta)
, m_rightMarginBoxDelta(rightMarginBoxDelta)
, m_borderBoxLineTop(borderBoxLineTop)
, m_lineHeight(lineHeight)
, m_lineOverlapsShape(lineOverlapsShape)
, m_isValid(true)
{
}
bool isForLine(LayoutUnit borderBoxLineTop, LayoutUnit lineHeight)
{
return m_isValid && m_borderBoxLineTop == borderBoxLineTop && m_lineHeight == lineHeight;
}
bool isValid() { return m_isValid; }
LayoutUnit leftMarginBoxDelta() { ASSERT(m_isValid); return m_leftMarginBoxDelta; }
LayoutUnit rightMarginBoxDelta() { ASSERT(m_isValid); return m_rightMarginBoxDelta; }
bool lineOverlapsShape() { ASSERT(m_isValid); return m_lineOverlapsShape; }
private:
LayoutUnit m_leftMarginBoxDelta;
LayoutUnit m_rightMarginBoxDelta;
LayoutUnit m_borderBoxLineTop;
LayoutUnit m_lineHeight;
bool m_lineOverlapsShape : 1;
bool m_isValid : 1;
};
class ShapeOutsideInfo FINAL { class ShapeOutsideInfo FINAL {
WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_FAST_ALLOCATED;
public: public:
...@@ -55,21 +92,10 @@ public: ...@@ -55,21 +92,10 @@ public:
LayoutUnit shapeLogicalWidth() const { return computedShape().shapeMarginLogicalBoundingBox().width(); } LayoutUnit shapeLogicalWidth() const { return computedShape().shapeMarginLogicalBoundingBox().width(); }
LayoutUnit shapeLogicalHeight() const { return computedShape().shapeMarginLogicalBoundingBox().height(); } LayoutUnit shapeLogicalHeight() const { return computedShape().shapeMarginLogicalBoundingBox().height(); }
LayoutUnit logicalLineTop() const { return m_referenceBoxLineTop + logicalTopOffset(); }
LayoutUnit logicalLineBottom() const { return m_referenceBoxLineTop + m_lineHeight + logicalTopOffset(); }
LayoutUnit leftMarginBoxDelta() const { return m_leftMarginBoxDelta; }
LayoutUnit rightMarginBoxDelta() const { return m_rightMarginBoxDelta; }
bool lineOverlapsShape() const { return m_lineOverlapsShape; }
static PassOwnPtr<ShapeOutsideInfo> createInfo(const RenderBox& renderer) { return adoptPtr(new ShapeOutsideInfo(renderer)); } static PassOwnPtr<ShapeOutsideInfo> createInfo(const RenderBox& renderer) { return adoptPtr(new ShapeOutsideInfo(renderer)); }
static bool isEnabledFor(const RenderBox&); static bool isEnabledFor(const RenderBox&);
void updateDeltasForContainingBlockLine(const RenderBlockFlow&, const FloatingObject&, LayoutUnit lineTop, LayoutUnit lineHeight);
bool lineOverlapsShapeBounds() const ShapeOutsideDeltas computeDeltasForContainingBlockLine(const RenderBlockFlow&, const FloatingObject&, LayoutUnit lineTop, LayoutUnit lineHeight);
{
return computedShape().lineOverlapsShapeMarginBounds(m_referenceBoxLineTop, m_lineHeight);
}
static ShapeOutsideInfo& ensureInfo(const RenderBox& key) static ShapeOutsideInfo& ensureInfo(const RenderBox& key)
{ {
...@@ -94,7 +120,6 @@ public: ...@@ -94,7 +120,6 @@ public:
protected: protected:
ShapeOutsideInfo(const RenderBox& renderer) ShapeOutsideInfo(const RenderBox& renderer)
: m_renderer(renderer) : m_renderer(renderer)
, m_lineOverlapsShape(false)
{ } { }
private: private:
...@@ -110,16 +135,10 @@ private: ...@@ -110,16 +135,10 @@ private:
return staticInfoMap; return staticInfoMap;
} }
LayoutUnit m_referenceBoxLineTop;
LayoutUnit m_lineHeight;
const RenderBox& m_renderer; const RenderBox& m_renderer;
mutable OwnPtr<Shape> m_shape; mutable OwnPtr<Shape> m_shape;
LayoutSize m_referenceBoxLogicalSize; LayoutSize m_referenceBoxLogicalSize;
LayoutUnit m_leftMarginBoxDelta; ShapeOutsideDeltas m_shapeOutsideDeltas;
LayoutUnit m_rightMarginBoxDelta;
LayoutUnit m_borderBoxLineTop;
bool m_lineOverlapsShape;
}; };
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment