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:
LayoutUnit offset() const { return m_offset; }
protected:
virtual bool updateOffsetIfNeeded(const FloatingObject*) = 0;
virtual bool updateOffsetIfNeeded(const FloatingObject&) = 0;
const RenderBlockFlow* m_renderer;
int m_lineTop;
......@@ -142,7 +142,7 @@ public:
LayoutUnit heightRemaining() const;
protected:
virtual bool updateOffsetIfNeeded(const FloatingObject*) OVERRIDE FINAL;
virtual bool updateOffsetIfNeeded(const FloatingObject&) OVERRIDE FINAL;
};
template <FloatingObject::Type FloatTypeValue>
......@@ -156,7 +156,7 @@ public:
virtual ~ComputeFloatOffsetForLineLayoutAdapter() { }
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,
}
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) {
m_offset = logicalRight;
return true;
......@@ -447,9 +447,9 @@ inline bool ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatLeft>::
}
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) {
m_offset = logicalLeft;
return true;
......@@ -475,31 +475,21 @@ inline void ComputeFloatOffsetAdapter<FloatTypeValue>::collectIfNeeded(const Int
ASSERT(interval.low() == m_renderer->pixelSnappedLogicalTopForFloat(floatingObject));
ASSERT(interval.high() == m_renderer->pixelSnappedLogicalBottomForFloat(floatingObject));
bool floatIsNewExtreme = updateOffsetIfNeeded(floatingObject);
bool floatIsNewExtreme = updateOffsetIfNeeded(*floatingObject);
if (floatIsNewExtreme)
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<>
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);
if (ShapeOutsideInfo* shapeOutside = shapeInfoForFloat(*floatingObject, *m_renderer, m_lineTop, m_lineBottom)) {
if (!shapeOutside->lineOverlapsShape())
LayoutUnit logicalRight = m_renderer->logicalRightForFloat(&floatingObject);
if (ShapeOutsideInfo* shapeOutside = floatingObject.renderer()->shapeOutsideInfo()) {
ShapeOutsideDeltas shapeDeltas = shapeOutside->computeDeltasForContainingBlockLine(*m_renderer, floatingObject, m_lineTop, m_lineBottom - m_lineTop);
if (!shapeDeltas.lineOverlapsShape())
return false;
logicalRight += shapeOutside->rightMarginBoxDelta();
logicalRight += shapeDeltas.rightMarginBoxDelta();
}
if (logicalRight > m_offset) {
m_offset = logicalRight;
......@@ -510,15 +500,15 @@ inline bool ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatLeft>::u
}
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);
if (ShapeOutsideInfo* shapeOutside = shapeInfoForFloat(*floatingObject, *m_renderer, m_lineTop, m_lineBottom)) {
if (!shapeOutside->lineOverlapsShape())
LayoutUnit logicalLeft = m_renderer->logicalLeftForFloat(&floatingObject);
if (ShapeOutsideInfo* shapeOutside = floatingObject.renderer()->shapeOutsideInfo()) {
ShapeOutsideDeltas shapeDeltas = shapeOutside->computeDeltasForContainingBlockLine(*m_renderer, floatingObject, m_lineTop, m_lineBottom - m_lineTop);
if (!shapeDeltas.lineOverlapsShape())
return false;
logicalLeft += shapeOutside->leftMarginBoxDelta();
logicalLeft += shapeDeltas.leftMarginBoxDelta();
}
if (logicalLeft < m_offset) {
m_offset = logicalLeft;
......
......@@ -66,17 +66,17 @@ void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject* newFloat
if (height < m_block.logicalTopForFloat(newFloat) || height >= m_block.logicalBottomForFloat(newFloat))
return;
ShapeOutsideInfo* shapeOutsideInfo = newFloat->renderer()->shapeOutsideInfo();
if (shapeOutsideInfo) {
ShapeOutsideDeltas shapeDeltas;
if (ShapeOutsideInfo* shapeOutsideInfo = newFloat->renderer()->shapeOutsideInfo()) {
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) {
float newLeft = m_block.logicalRightForFloat(newFloat).toFloat();
if (shapeOutsideInfo) {
if (shapeOutsideInfo->lineOverlapsShape())
newLeft += shapeOutsideInfo->rightMarginBoxDelta();
if (shapeDeltas.isValid()) {
if (shapeDeltas.lineOverlapsShape())
newLeft += shapeDeltas.rightMarginBoxDelta();
else // Per the CSS Shapes spec, If the line doesn't overlap the shape, then ignore this shape for this line.
newLeft = m_left;
}
......@@ -85,9 +85,9 @@ void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject* newFloat
m_left = std::max<float>(m_left, newLeft);
} else {
float newRight = m_block.logicalLeftForFloat(newFloat).toFloat();
if (shapeOutsideInfo) {
if (shapeOutsideInfo->lineOverlapsShape())
newRight += shapeOutsideInfo->leftMarginBoxDelta();
if (shapeDeltas.isValid()) {
if (shapeDeltas.lineOverlapsShape())
newRight += shapeDeltas.leftMarginBoxDelta();
else // Per the CSS Shapes spec, If the line doesn't overlap the shape, then ignore this shape for this line.
newRight = m_right;
}
......
......@@ -274,42 +274,40 @@ bool ShapeOutsideInfo::isEnabledFor(const RenderBox& box)
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);
LayoutUnit borderBoxTop = containingBlock.logicalTopForFloat(&floatingObject) + containingBlock.marginBeforeForChild(&m_renderer);
LayoutUnit borderBoxLineTop = lineTop - borderBoxTop;
if (isShapeDirty() || m_borderBoxLineTop != borderBoxLineTop || m_lineHeight != lineHeight) {
m_borderBoxLineTop = borderBoxLineTop;
m_referenceBoxLineTop = borderBoxLineTop - logicalTopOffset();
m_lineHeight = lineHeight;
if (isShapeDirty() || !m_shapeOutsideDeltas.isForLine(borderBoxLineTop, lineHeight)) {
LayoutUnit referenceBoxLineTop = borderBoxLineTop - logicalTopOffset();
LayoutUnit floatMarginBoxWidth = containingBlock.logicalWidthForFloat(&floatingObject);
if (lineOverlapsShapeBounds()) {
if (computedShape().lineOverlapsShapeMarginBounds(referenceBoxLineTop, lineHeight)) {
LineSegment segment = computedShape().getExcludedInterval((borderBoxLineTop - logicalTopOffset()), std::min(lineHeight, shapeLogicalBottom() - borderBoxLineTop));
if (segment.isValid) {
LayoutUnit logicalLeftMargin = containingBlock.style()->isLeftToRightDirection() ? containingBlock.marginStartForChild(&m_renderer) : containingBlock.marginEndForChild(&m_renderer);
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 rawRightMarginBoxDelta = segment.logicalRight + logicalLeftOffset() - containingBlock.logicalWidthForChild(&m_renderer) - logicalRightMargin;
m_rightMarginBoxDelta = clampToLayoutUnit(rawRightMarginBoxDelta, -floatMarginBoxWidth, LayoutUnit());
m_lineOverlapsShape = true;
return;
LayoutUnit rightMarginBoxDelta = clampTo<LayoutUnit>(rawRightMarginBoxDelta, -floatMarginBoxWidth, LayoutUnit());
m_shapeOutsideDeltas = ShapeOutsideDeltas(leftMarginBoxDelta, rightMarginBoxDelta, true, borderBoxLineTop, lineHeight);
return m_shapeOutsideDeltas;
}
}
// 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
// entire width of the float.
m_leftMarginBoxDelta = floatMarginBoxWidth;
m_rightMarginBoxDelta = -floatMarginBoxWidth;
m_lineOverlapsShape = false;
m_shapeOutsideDeltas = ShapeOutsideDeltas(floatMarginBoxWidth, -floatMarginBoxWidth, false, borderBoxLineTop, lineHeight);
}
return m_shapeOutsideDeltas;
}
LayoutRect ShapeOutsideInfo::computedShapePhysicalBoundingBox() const
......
......@@ -43,6 +43,43 @@ class RenderBlockFlow;
class RenderBox;
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 {
WTF_MAKE_FAST_ALLOCATED;
public:
......@@ -55,21 +92,10 @@ public:
LayoutUnit shapeLogicalWidth() const { return computedShape().shapeMarginLogicalBoundingBox().width(); }
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 bool isEnabledFor(const RenderBox&);
void updateDeltasForContainingBlockLine(const RenderBlockFlow&, const FloatingObject&, LayoutUnit lineTop, LayoutUnit lineHeight);
bool lineOverlapsShapeBounds() const
{
return computedShape().lineOverlapsShapeMarginBounds(m_referenceBoxLineTop, m_lineHeight);
}
ShapeOutsideDeltas computeDeltasForContainingBlockLine(const RenderBlockFlow&, const FloatingObject&, LayoutUnit lineTop, LayoutUnit lineHeight);
static ShapeOutsideInfo& ensureInfo(const RenderBox& key)
{
......@@ -94,7 +120,6 @@ public:
protected:
ShapeOutsideInfo(const RenderBox& renderer)
: m_renderer(renderer)
, m_lineOverlapsShape(false)
{ }
private:
......@@ -110,16 +135,10 @@ private:
return staticInfoMap;
}
LayoutUnit m_referenceBoxLineTop;
LayoutUnit m_lineHeight;
const RenderBox& m_renderer;
mutable OwnPtr<Shape> m_shape;
LayoutSize m_referenceBoxLogicalSize;
LayoutUnit m_leftMarginBoxDelta;
LayoutUnit m_rightMarginBoxDelta;
LayoutUnit m_borderBoxLineTop;
bool m_lineOverlapsShape;
ShapeOutsideDeltas m_shapeOutsideDeltas;
};
}
......
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