Commit 2ddd9396 authored by hyatt@apple.com's avatar hyatt@apple.com

2008-04-14 David Hyatt <hyatt@apple.com>

        Add a new optimized layout path for positioned objects that move.  Also avoid always marking the <html>
        object for layout when it has a percentage height, since the RenderView already does that when its size
        changes.

        Reviewed by mjs

        * rendering/RenderBlock.cpp:
        (WebCore::RenderBlock::layoutBlockChildren):
        (WebCore::RenderBlock::layoutPositionedObjects):
        * rendering/RenderBox.h:
        (WebCore::RenderBox::layoutDoingPositionedMovementOnly):
        * rendering/RenderObject.cpp:
        (WebCore::RenderObject::RenderObject):
        (WebCore::RenderObject::setNeedsLayout):
        (WebCore::RenderObject::setChildNeedsLayout):
        (WebCore::RenderObject::setNeedsPositionedMovementLayout):
        (WebCore::RenderObject::setStyle):
        * rendering/RenderObject.h:
        (WebCore::RenderObject::needsLayout):
        (WebCore::RenderObject::needsPositionedMovementLayoutOnly):
        (WebCore::RenderObject::layoutDoingPositionedMovementOnly):
        * rendering/RenderStyle.cpp:
        (WebCore::positionedObjectMoved):
        (WebCore::RenderStyle::diff):
        * rendering/RenderStyle.h:
        (WebCore::RenderStyle::):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@31876 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent d80993b1
2008-04-14 David Hyatt <hyatt@apple.com>
Add a new optimized layout path for positioned objects that move. Also avoid always marking the <html>
object for layout when it has a percentage height, since the RenderView already does that when its size
changes.
Reviewed by mjs
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::layoutBlockChildren):
(WebCore::RenderBlock::layoutPositionedObjects):
* rendering/RenderBox.h:
(WebCore::RenderBox::layoutDoingPositionedMovementOnly):
* rendering/RenderObject.cpp:
(WebCore::RenderObject::RenderObject):
(WebCore::RenderObject::setNeedsLayout):
(WebCore::RenderObject::setChildNeedsLayout):
(WebCore::RenderObject::setNeedsPositionedMovementLayout):
(WebCore::RenderObject::setStyle):
* rendering/RenderObject.h:
(WebCore::RenderObject::needsLayout):
(WebCore::RenderObject::needsPositionedMovementLayoutOnly):
(WebCore::RenderObject::layoutDoingPositionedMovementOnly):
* rendering/RenderStyle.cpp:
(WebCore::positionedObjectMoved):
(WebCore::RenderStyle::diff):
* rendering/RenderStyle.h:
(WebCore::RenderStyle::):
2008-04-14 David Hyatt <hyatt@apple.com>
Add support for gradients in the CSS content property.
......@@ -1172,7 +1172,7 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
// Make sure we layout children if they need it.
// FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into
// an auto value. Add a method to determine this, so that we can avoid the relayout.
if (relayoutChildren || (child->style()->height().isPercent() || child->style()->minHeight().isPercent() || child->style()->maxHeight().isPercent()))
if (relayoutChildren || ((child->style()->height().isPercent() || child->style()->minHeight().isPercent() || child->style()->maxHeight().isPercent()) && !isRenderView()))
child->setChildNeedsLayout(true, false);
// If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths.
......@@ -1330,8 +1330,12 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
// If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths.
if (relayoutChildren && (r->style()->paddingLeft().isPercent() || r->style()->paddingRight().isPercent()))
r->setPrefWidthsDirty(true, false);
r->layoutIfNeeded();
// We don't have to do a full layout. We just have to update our position.
if (r->needsPositionedMovementLayoutOnly())
r->layoutDoingPositionedMovementOnly();
else
r->layoutIfNeeded();
}
}
}
......
......@@ -156,6 +156,14 @@ public:
virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
virtual void imageChanged(CachedImage*);
// Called when a positioned object moves but doesn't change size. A simplified layout is done
// that just updates the object's position.
virtual void layoutDoingPositionedMovementOnly() {
calcWidth();
calcHeight();
setNeedsLayout(false);
}
protected:
void paintBackground(const PaintInfo&, const Color&, const BackgroundLayer*, int clipY, int clipHeight, int tx, int ty, int width, int height);
void paintBackgrounds(const PaintInfo&, const Color&, const BackgroundLayer*, int clipY, int clipHeight, int tx, int ty, int width, int height);
......
......@@ -178,6 +178,7 @@ RenderObject::RenderObject(Node* node)
#endif
, m_verticalPosition(PositionUndefined)
, m_needsLayout(false)
, m_needsPositionedMovementLayout(false)
, m_normalChildNeedsLayout(false)
, m_posChildNeedsLayout(false)
, m_prefWidthsDirty(false)
......@@ -699,6 +700,7 @@ void RenderObject::setNeedsLayout(bool b, bool markParents)
} else {
m_posChildNeedsLayout = false;
m_normalChildNeedsLayout = false;
m_needsPositionedMovementLayout = false;
}
}
......@@ -712,6 +714,18 @@ void RenderObject::setChildNeedsLayout(bool b, bool markParents)
} else {
m_posChildNeedsLayout = false;
m_normalChildNeedsLayout = false;
m_needsPositionedMovementLayout = false;
}
}
void RenderObject::setNeedsPositionedMovementLayout()
{
bool alreadyNeededLayout = needsLayout();
m_needsPositionedMovementLayout = true;
if (!alreadyNeededLayout) {
markContainingBlocksForLayout();
if (hasLayer())
layer()->setNeedsFullRepaint();
}
}
......@@ -2211,7 +2225,7 @@ void RenderObject::setStyle(RenderStyle* style)
&& parent() && (parent()->isBlockFlow() || parent()->isInlineFlow());
// reset style flags
if (d == RenderStyle::Layout) {
if (d == RenderStyle::Layout || d == RenderStyle::LayoutPositionedMovementOnly) {
m_floating = false;
m_positioned = false;
m_relPositioned = false;
......@@ -2256,6 +2270,8 @@ void RenderObject::setStyle(RenderStyle* style)
// need to relayout.
if (d == RenderStyle::Layout && m_parent)
setNeedsLayoutAndPrefWidthsRecalc();
else if (d == RenderStyle::LayoutPositionedMovementOnly && m_parent && !isText())
setNeedsPositionedMovementLayout();
else if (m_parent && !isText() && (d == RenderStyle::RepaintLayer || d == RenderStyle::Repaint))
// Do a repaint with the new style now, e.g., for example if we go from
// not having an outline to having an outline.
......
......@@ -336,11 +336,12 @@ public:
bool hasHorizontalBordersPaddingOrMargin() const { return hasHorizontalBordersOrPadding() || marginLeft() != 0 || marginRight() != 0; }
bool hasHorizontalBordersOrPadding() const { return borderLeft() != 0 || borderRight() != 0 || paddingLeft() != 0 || paddingRight() != 0; }
bool needsLayout() const { return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout; }
bool needsLayout() const { return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout || m_needsPositionedMovementLayout; }
bool selfNeedsLayout() const { return m_needsLayout; }
bool needsPositionedMovementLayoutOnly() const { return m_needsPositionedMovementLayout && !m_needsLayout && !m_normalChildNeedsLayout && !m_posChildNeedsLayout; }
bool posChildNeedsLayout() const { return m_posChildNeedsLayout; }
bool normalChildNeedsLayout() const { return m_normalChildNeedsLayout; }
bool prefWidthsDirty() const { return m_prefWidthsDirty; }
bool isSelectionBorder() const;
......@@ -392,7 +393,7 @@ public:
void markContainingBlocksForLayout(bool scheduleRelayout = true, RenderObject* newRoot = 0);
void setNeedsLayout(bool b, bool markParents = true);
void setChildNeedsLayout(bool b, bool markParents = true);
void setNeedsPositionedMovementLayout();
void setPrefWidthsDirty(bool, bool markParents = true);
void invalidateContainerPrefWidths();
......@@ -496,6 +497,10 @@ public:
/* This function performs a layout only if one is needed. */
void layoutIfNeeded() { if (needsLayout()) layout(); }
// Called when a positioned object moves but doesn't change size. A simplified layout is done
// that just updates the object's position.
virtual void layoutDoingPositionedMovementOnly() {};
// used for element state updates that cannot be fixed with a
// repaint and do not need a relayout
virtual void updateFromElement() { }
......@@ -907,6 +912,7 @@ private:
mutable short m_verticalPosition : 15;
bool m_needsLayout : 1;
bool m_needsPositionedMovementLayout :1;
bool m_normalChildNeedsLayout : 1;
bool m_posChildNeedsLayout : 1;
bool m_prefWidthsDirty : 1;
......
......@@ -1232,6 +1232,29 @@ bool RenderStyle::inheritedNotEqual(RenderStyle* other) const
rareInheritedData != other->rareInheritedData;
}
bool positionedObjectMoved(const LengthBox& a, const LengthBox& b)
{
// If any unit types are different, then we can't guarantee
// that this was just a movement.
if (a.left.type() != b.left.type() ||
a.right.type() != b.right.type() ||
a.top.type() != b.top.type() ||
a.bottom.type() != b.bottom.type())
return false;
// Only one unit can be non-auto in the horizontal direction and
// in the vertical direction. Otherwise the adjustment of values
// is changing the size of the box.
if (!a.left.isIntrinsicOrAuto() && !a.right.isIntrinsicOrAuto())
return false;
if (!a.top.isIntrinsicOrAuto() && !a.bottom.isIntrinsicOrAuto())
return false;
// One of the units is fixed or percent in both directions and stayed
// that way in the new style. Therefore all we are doing is moving.
return true;
}
/*
compares two styles. The result gives an idea of the action that
needs to be taken when replacing the old style with a new one.
......@@ -1398,8 +1421,12 @@ RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
// Make sure these left/top/right/bottom checks stay below all layout checks and above
// all visible checks.
if (other->position() != StaticPosition) {
if (position() != StaticPosition) {
if (surround->offset != other->surround->offset) {
// Optimize for the case where a positioned layer is moving but not changing size.
if (position() == AbsolutePosition && positionedObjectMoved(surround->offset, other->surround->offset))
return LayoutPositionedMovementOnly;
// FIXME: We will need to do a bit of work in RenderObject/Box::setStyle before we
// can stop doing a layout when relative positioned objects move. In particular, we'll need
// to update scrolling positions and figure out how to do a repaint properly of the updated layer.
......@@ -1407,8 +1434,7 @@ RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
// return RepaintLayer;
//else
return Layout;
}
else if (box->z_index != other->box->z_index || box->z_auto != other->box->z_auto ||
} else if (box->z_index != other->box->z_index || box->z_auto != other->box->z_auto ||
visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip)
return RepaintLayer;
}
......
......@@ -2244,7 +2244,7 @@ public:
// (2) Repaint - The object just needs to be repainted.
// (3) RepaintLayer - The layer and its descendant layers needs to be repainted.
// (4) Layout - A layout is required.
enum Diff { Equal, Repaint, RepaintLayer, Layout };
enum Diff { Equal, Repaint, RepaintLayer, LayoutPositionedMovementOnly, Layout };
Diff diff( const RenderStyle *other ) const;
bool isDisplayReplacedType() {
......
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