2009-01-12 Simon Fraser <simon.fraser@apple.com>

        Reviewed by Dan Bernstein

        https://bugs.webkit.org/show_bug.cgi?id=23220

        Merge layoutDelta into LayoutState. This requires that we
        push even when layoutState is disabled, so that layoutDelta
        can still be stored.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@39834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent ae3794de
2009-01-12 Simon Fraser <simon.fraser@apple.com>
Reviewed by Dan Bernstein
https://bugs.webkit.org/show_bug.cgi?id=23220
Merge layoutDelta into LayoutState. This requires that we
push even when layoutState is disabled, so that layoutDelta
can still be stored.
* rendering/LayoutState.cpp:
(WebCore::LayoutState::LayoutState):
* rendering/LayoutState.h:
(WebCore::LayoutState::LayoutState):
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::layoutBlock):
(WebCore::RenderBlock::layoutBlockChildren):
(WebCore::RenderBlock::layoutOnlyPositionedObjects):
* rendering/RenderBox.cpp:
(WebCore::RenderBox::localToAbsolute):
(WebCore::RenderBox::absoluteToLocal):
(WebCore::RenderBox::computeAbsoluteRepaintRect):
* rendering/RenderFlexibleBox.cpp:
(WebCore::RenderFlexibleBox::layoutBlock):
* rendering/RenderFlow.cpp:
(WebCore::RenderFlow::absoluteClippedOverflowRect):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::updateLayerPositions):
* rendering/RenderTableCell.cpp:
(WebCore::RenderTableCell::computeAbsoluteRepaintRect):
(WebCore::RenderTableCell::localToAbsolute):
* rendering/RenderView.cpp:
(WebCore::RenderView::pushLayoutState):
* rendering/RenderView.h:
(WebCore::RenderView::layoutDelta):
(WebCore::RenderView::addLayoutDelta):
(WebCore::RenderView::doingFullRepaint):
(WebCore::RenderView::pushLayoutState):
(WebCore::RenderView::popLayoutState):
(WebCore::RenderView::layoutStateEnabled):
(WebCore::RenderView::layoutState):
(WebCore::LayoutStateMaintainer::LayoutStateMaintainer):
(WebCore::LayoutStateMaintainer::push):
(WebCore::LayoutStateMaintainer::pop):
* rendering/bidi.cpp:
(WebCore::RenderBlock::layoutInlineChildren):
2009-01-12 Julien Chaffraix <jchaffraix@pleyo.com>
Reviewed by Holger Freyther.
......@@ -33,10 +33,12 @@
namespace WebCore {
LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize& offset)
: m_next(prev)
#ifndef NDEBUG
, m_renderer(renderer)
#endif
{
ASSERT(prev);
m_next = prev;
ASSERT(m_next);
bool fixed = renderer->isPositioned() && renderer->style()->position() == FixedPosition;
if (fixed) {
......@@ -72,16 +74,22 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize&
layer->subtractScrolledContentOffset(x, y);
m_offset = IntSize(x, y);
}
m_layoutDelta = m_next->m_layoutDelta;
// FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
}
LayoutState::LayoutState(RenderObject* root)
: m_clipped(false)
, m_next(0)
#ifndef NDEBUG
, m_renderer(root)
#endif
{
RenderObject* container = root->container();
FloatPoint absContentPoint = container->localToAbsoluteForContent(FloatPoint(), false, true);
m_offset = IntSize(absContentPoint.x(), absContentPoint.y());
m_next = 0;
}
#ifndef NDEBUG
......
......@@ -41,6 +41,9 @@ public:
LayoutState()
: m_clipped(false)
, m_next(0)
#ifndef NDEBUG
, m_renderer(0)
#endif
{
}
......@@ -62,8 +65,14 @@ private:
public:
bool m_clipped;
IntRect m_clipRect;
IntSize m_offset;
IntSize m_offset; // x/y offset from container.
IntSize m_layoutDelta; // Transient offset from the final position of the object
// used to ensure that repaints happen in the correct place.
// This is a total delta accumulated from the root.
LayoutState* m_next;
#ifndef NDEBUG
RenderObject* m_renderer;
#endif
};
} // namespace WebCore
......
......@@ -595,7 +595,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
oldOutlineBox = absoluteOutlineBounds();
}
LayoutStateMaintainer statePusher(view(), this, IntSize(xPos(), yPos()), !m_hasColumns && !hasTransform() && !hasReflection());
LayoutStateMaintainer statePusher(view(), this, IntSize(xPos(), yPos()), m_hasColumns || hasTransform() || hasReflection());
int oldWidth = m_width;
int oldColumnWidth = desiredColumnWidth();
......@@ -1302,7 +1302,9 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
// Cache our old rect so that we can dirty the proper repaint rects if the child moves.
IntRect oldRect(child->xPos(), child->yPos() , child->width(), child->height());
#ifndef NDEBUG
IntSize oldLayoutDelta = view()->layoutDelta();
#endif
// Go ahead and position the child as though it didn't collapse with the top.
view()->addLayoutDelta(IntSize(0, child->yPos() - yPosEstimate));
child->setPos(child->xPos(), yPosEstimate);
......@@ -1377,6 +1379,7 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
if (!childHadLayout && child->checkForRepaintDuringLayout())
child->repaint();
ASSERT(oldLayoutDelta == view()->layoutDelta());
child = child->nextSibling();
}
......@@ -1390,7 +1393,7 @@ bool RenderBlock::layoutOnlyPositionedObjects()
if (!posChildNeedsLayout() || normalChildNeedsLayout() || selfNeedsLayout())
return false;
LayoutStateMaintainer statePusher(view(), this, IntSize(xPos(), yPos()), !m_hasColumns && !hasTransform() && !hasReflection());
LayoutStateMaintainer statePusher(view(), this, IntSize(xPos(), yPos()), m_hasColumns || hasTransform() || hasReflection());
if (needsPositionedMovementLayout()) {
tryLayoutDoingPositionedMovementOnly();
......
......@@ -996,7 +996,8 @@ IntSize RenderBox::offsetForPositionedInContainer(RenderObject* container) const
FloatPoint RenderBox::localToAbsolute(FloatPoint localPoint, bool fixed, bool useTransforms) const
{
if (RenderView* v = view()) {
if (LayoutState* layoutState = v->layoutState()) {
if (v->layoutStateEnabled()) {
LayoutState* layoutState = v->layoutState();
IntSize offset = layoutState->m_offset;
offset.expand(m_x, m_y);
localPoint += offset;
......@@ -1027,7 +1028,7 @@ FloatPoint RenderBox::localToAbsolute(FloatPoint localPoint, bool fixed, bool us
FloatPoint RenderBox::absoluteToLocal(FloatPoint containerPoint, bool fixed, bool useTransforms) const
{
// We don't expect absoluteToLocal() to be called during layout (yet)
ASSERT(!view() || !view()->layoutState());
ASSERT(!view() || !view()->layoutStateEnabled());
if (style()->position() == FixedPosition)
fixed = true;
......@@ -1188,7 +1189,8 @@ IntRect RenderBox::absoluteClippedOverflowRect()
void RenderBox::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
{
if (RenderView* v = view()) {
if (LayoutState* layoutState = v->layoutState()) {
if (v->layoutStateEnabled()) {
LayoutState* layoutState = v->layoutState();
if (style()->position() == RelativePosition && m_layer)
rect.move(m_layer->relativePositionOffset());
......
......@@ -220,7 +220,7 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
oldOutlineBox = absoluteOutlineBounds();
}
LayoutStateMaintainer statePusher(view(), this, IntSize(m_x, m_y), !hasTransform() && !hasReflection());
LayoutStateMaintainer statePusher(view(), this, IntSize(m_x, m_y), hasTransform() || hasReflection());
int previousWidth = m_width;
int previousHeight = m_height;
......
......@@ -484,7 +484,7 @@ IntRect RenderFlow::absoluteClippedOverflowRect()
{
if (isInlineFlow()) {
// Only compacts and run-ins are allowed in here during layout.
ASSERT(!view() || !view()->layoutState() || isCompact() || isRunIn());
ASSERT(!view() || !view()->layoutStateEnabled() || isCompact() || isRunIn());
if (!firstLineBox() && !continuation())
return IntRect();
......
......@@ -229,7 +229,7 @@ void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
ASSERT(view);
// FIXME: Optimize using LayoutState and remove the disableLayoutState() call
// from updateScrollInfoAfterLayout().
ASSERT(!view->layoutState());
ASSERT(!view->layoutStateEnabled());
IntRect newRect = m_object->absoluteClippedOverflowRect();
IntRect newOutlineBox = m_object->absoluteOutlineBounds();
......
......@@ -191,7 +191,7 @@ void RenderTableCell::computeAbsoluteRepaintRect(IntRect& r, bool fixed)
{
r.setY(r.y() + m_topExtra);
RenderView* v = view();
if ((!v || !v->layoutState()) && parent())
if ((!v || !v->layoutStateEnabled()) && parent())
r.move(-parent()->xPos(), -parent()->yPos()); // Rows are in the same coordinate space, so don't add their offset in.
RenderBlock::computeAbsoluteRepaintRect(r, fixed);
}
......@@ -199,7 +199,7 @@ void RenderTableCell::computeAbsoluteRepaintRect(IntRect& r, bool fixed)
FloatPoint RenderTableCell::localToAbsolute(FloatPoint localPoint, bool fixed, bool useTransforms) const
{
RenderView* v = view();
if ((!v || !v->layoutState()) && parent()) {
if ((!v || !v->layoutStateEnabled()) && parent()) {
// Rows are in the same coordinate space, so don't add their offset in.
localPoint.move(-parent()->xPos(), -parent()->yPos());
}
......
......@@ -601,7 +601,7 @@ void RenderView::setBestTruncatedAt(int y, RenderObject* forRenderer, bool force
void RenderView::pushLayoutState(RenderObject* root)
{
ASSERT(!m_frameView->needsFullRepaint());
ASSERT(!doingFullRepaint());
ASSERT(m_layoutStateDisableCount == 0);
ASSERT(m_layoutState == 0);
......
......@@ -101,14 +101,25 @@ public:
void removeWidget(RenderObject*);
// layoutDelta is used transiently during layout to store how far an object has moved from its
// last layout location, in order to repaint correctly
const IntSize& layoutDelta() const { return m_layoutDelta; }
void addLayoutDelta(const IntSize& delta) { m_layoutDelta += delta; }
// last layout location, in order to repaint correctly.
// If we're doing a full repaint m_layoutState will be 0, but in that case layoutDelta doesn't matter.
IntSize layoutDelta() const
{
return m_layoutState ? m_layoutState->m_layoutDelta : IntSize();
}
void addLayoutDelta(const IntSize& delta)
{
if (m_layoutState)
m_layoutState->m_layoutDelta += delta;
}
bool doingFullRepaint() const { return m_frameView->needsFullRepaint(); }
void pushLayoutState(RenderBox* renderer, const IntSize& offset)
{
if (m_layoutStateDisableCount || m_frameView->needsFullRepaint())
if (doingFullRepaint())
return;
// We push LayoutState even if layoutState is disabled because it stores layoutDelta too.
m_layoutState = new (renderArena()) LayoutState(m_layoutState, renderer, offset);
}
......@@ -116,18 +127,21 @@ public:
void popLayoutState()
{
if (m_layoutStateDisableCount || m_frameView->needsFullRepaint())
if (doingFullRepaint())
return;
LayoutState* state = m_layoutState;
m_layoutState = state->m_next;
state->destroy(renderArena());
}
LayoutState* layoutState() const { return m_layoutStateDisableCount ? 0 : m_layoutState; }
// Returns true if layoutState should be used for its cached offset and clip.
bool layoutStateEnabled() const { return m_layoutStateDisableCount == 0 && m_layoutState; }
LayoutState* layoutState() const { return m_layoutState; }
// Suspends the LayoutState optimization. Used under transforms that cannot be represented by
// LayoutState (common in SVG) and when manipulating the render tree during layout in ways
// that can trigger repaint of a non-child (e.g. when a list item moves its list marker around).
// Note that even when disabled, LayoutState is still used to store layoutDelta.
void disableLayoutState() { m_layoutStateDisableCount++; }
void enableLayoutState() { ASSERT(m_layoutStateDisableCount > 0); m_layoutStateDisableCount--; }
......@@ -158,7 +172,6 @@ private:
int m_bestTruncatedAt;
int m_truncatorWidth;
bool m_forcedPageBreak;
IntSize m_layoutDelta;
LayoutState* m_layoutState;
unsigned m_layoutStateDisableCount;
};
......@@ -167,9 +180,9 @@ private:
class LayoutStateMaintainer : Noncopyable {
public:
// ctor to push now
LayoutStateMaintainer(RenderView* view, RenderBox* root, IntSize offset, bool shouldPush = true)
LayoutStateMaintainer(RenderView* view, RenderBox* root, IntSize offset, bool disableState = false)
: m_view(view)
, m_shouldPushPop(shouldPush)
, m_disabled(disableState)
, m_didStart(false)
, m_didEnd(false)
{
......@@ -179,7 +192,7 @@ public:
// ctor to maybe push later
LayoutStateMaintainer(RenderView* view)
: m_view(view)
, m_shouldPushPop(true)
, m_disabled(false)
, m_didStart(false)
, m_didEnd(false)
{
......@@ -190,33 +203,32 @@ public:
ASSERT(m_didStart == m_didEnd); // if this fires, it means that someone did a push(), but forgot to pop().
}
void push(RenderBox* root, IntSize offset)
{
ASSERT(!m_didStart);
// We push state even if disabled, because we still need to store layoutDelta
m_view->pushLayoutState(root, offset);
if (m_disabled)
m_view->disableLayoutState();
m_didStart = true;
}
void pop()
{
if (m_didStart) {
ASSERT(!m_didEnd);
if (m_shouldPushPop)
m_view->popLayoutState();
else
m_view->popLayoutState();
if (m_disabled)
m_view->enableLayoutState();
m_didEnd = true;
}
}
void push(RenderBox* root, IntSize offset)
{
ASSERT(!m_didStart);
if (m_shouldPushPop)
m_view->pushLayoutState(root, offset);
else
m_view->disableLayoutState();
m_didStart = true;
}
bool didPush() const { return m_didStart; }
private:
RenderView* m_view;
bool m_shouldPushPop : 1; // true if we should push/pop, rather than disable/enable
bool m_disabled : 1; // true if the offset and clip part of layoutState is disabled
bool m_didStart : 1; // true if we did a push or disable
bool m_didEnd : 1; // true if we popped or re-enabled
};
......
......@@ -867,14 +867,13 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
if (fullLayout && !selfNeedsLayout()) {
setNeedsLayout(true, false); // Mark ourselves as needing a full layout. This way we'll repaint like
// we're supposed to.
if (!document()->view()->needsFullRepaint() && m_layer) {
RenderView* v = view();
if (v && !v->doingFullRepaint() && m_layer) {
// Because we waited until we were already inside layout to discover
// that the block really needed a full layout, we missed our chance to repaint the layer
// before layout started. Luckily the layer has cached the repaint rect for its original
// position and size, and so we can use that to make a repaint happen now.
RenderView* c = view();
if (c && !c->printing())
c->repaintViewRectangle(m_layer->repaintRect());
v->repaintViewRectangle(m_layer->repaintRect());
}
}
......
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