Index: third_party/WebKit/WebCore/rendering/RenderBox.cpp |
=================================================================== |
--- third_party/WebKit/WebCore/rendering/RenderBox.cpp (revision 9383) |
+++ third_party/WebKit/WebCore/rendering/RenderBox.cpp (working copy) |
@@ -61,6 +61,7 @@ |
typedef WTF::HashMap<const RenderBox*, int> OverrideSizeMap; |
static OverrideSizeMap* gOverrideSizeMap = 0; |
+bool RenderBox::s_wasFloating = false; |
bool RenderBox::s_hadOverflowClip = false; |
RenderBox::RenderBox(Node* node) |
@@ -71,6 +72,7 @@ |
, m_marginBottom(0) |
, m_minPrefWidth(-1) |
, m_maxPrefWidth(-1) |
+ , m_layer(0) |
, m_inlineBoxWrapper(0) |
{ |
setIsBox(); |
@@ -88,6 +90,10 @@ |
if (hasOverrideSize()) |
gOverrideSizeMap->remove(this); |
+ // This must be done before we destroy the RenderObject. |
+ if (m_layer) |
+ m_layer->clearClipRects(); |
+ |
if (style() && (style()->height().isPercent() || style()->minHeight().isPercent() || style()->maxHeight().isPercent())) |
RenderBlock::removePercentHeightDescendant(this); |
@@ -123,6 +129,7 @@ |
void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) |
{ |
+ s_wasFloating = isFloating(); |
s_hadOverflowClip = hasOverflowClip(); |
if (style()) { |
@@ -189,35 +196,16 @@ |
void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) |
{ |
+ // We need to ensure that view->maximalOutlineSize() is valid for any repaints that happen |
+ // during the style change (it's used by clippedOverflowRectForRepaint()). |
+ if (style()->outlineWidth() > 0 && style()->outlineSize() > maximalOutlineSize(PaintPhaseOutline)) |
+ toRenderView(document()->renderer())->setMaximalOutlineSize(style()->outlineSize()); |
+ |
RenderBoxModelObject::styleDidChange(diff, oldStyle); |
if (needsLayout() && oldStyle && (oldStyle->height().isPercent() || oldStyle->minHeight().isPercent() || oldStyle->maxHeight().isPercent())) |
RenderBlock::removePercentHeightDescendant(this); |
- // If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the |
- // new zoomed coordinate space. |
- if (hasOverflowClip() && oldStyle && style() && oldStyle->effectiveZoom() != style()->effectiveZoom()) { |
- int left = scrollLeft(); |
- if (left) { |
- left = (left / oldStyle->effectiveZoom()) * style()->effectiveZoom(); |
- setScrollLeft(left); |
- } |
- int top = scrollTop(); |
- if (top) { |
- top = (top / oldStyle->effectiveZoom()) * style()->effectiveZoom(); |
- setScrollTop(top); |
- } |
- } |
- |
- // Set the text color if we're the body. |
- if (isBody()) |
- document()->setTextColor(style()->color()); |
-} |
- |
-void RenderBox::updateBoxModelInfoFromStyle() |
-{ |
- RenderBoxModelObject::updateBoxModelInfoFromStyle(); |
- |
bool isRootObject = isRoot(); |
bool isViewObject = isRenderView(); |
@@ -225,9 +213,24 @@ |
if (isRootObject || isViewObject) |
setHasBoxDecorations(true); |
- setPositioned(style()->position() == AbsolutePosition || style()->position() == FixedPosition); |
- setFloating(!isPositioned() && style()->isFloating()); |
+ setInline(style()->isDisplayInlineType()); |
+ switch (style()->position()) { |
+ case AbsolutePosition: |
+ case FixedPosition: |
+ setPositioned(true); |
+ break; |
+ default: |
+ setPositioned(false); |
+ |
+ if (style()->isFloating()) |
+ setFloating(true); |
+ |
+ if (style()->position() == RelativePosition) |
+ setRelPositioned(true); |
+ break; |
+ } |
+ |
// We also handle <body> and <html>, whose overflow applies to the viewport. |
if (style()->overflowX() != OVISIBLE && !isRootObject && (isRenderBlock() || isTableRow() || isTableSection())) { |
bool boxHasOverflowClip = true; |
@@ -252,8 +255,54 @@ |
} |
} |
- setHasTransform(style()->hasTransform()); |
+ // FIXME: we should make transforms really work on inline flows eventually. |
+ if (!isInline() || isReplaced()) |
+ setHasTransform(style()->hasTransform()); |
setHasReflection(style()->boxReflect()); |
+ |
+ if (requiresLayer()) { |
+ if (!m_layer) { |
+ if (s_wasFloating && isFloating()) |
+ setChildNeedsLayout(true); |
+ m_layer = new (renderArena()) RenderLayer(this); |
+ setHasLayer(true); |
+ m_layer->insertOnlyThisLayer(); |
+ if (parent() && !needsLayout() && containingBlock()) |
+ m_layer->updateLayerPositions(); |
+ } |
+ } else if (m_layer && !isRootObject && !isViewObject) { |
+ ASSERT(m_layer->parent()); |
+ RenderLayer* layer = m_layer; |
+ m_layer = 0; |
+ setHasLayer(false); |
+ setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit. |
+ setHasReflection(false); |
+ layer->removeOnlyThisLayer(); |
+ if (s_wasFloating && isFloating()) |
+ setChildNeedsLayout(true); |
+ } |
+ |
+ // If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the |
+ // new zoomed coordinate space. |
+ if (hasOverflowClip() && oldStyle && style() && oldStyle->effectiveZoom() != style()->effectiveZoom()) { |
+ int left = scrollLeft(); |
+ if (left) { |
+ left = (left / oldStyle->effectiveZoom()) * style()->effectiveZoom(); |
+ setScrollLeft(left); |
+ } |
+ int top = scrollTop(); |
+ if (top) { |
+ top = (top / oldStyle->effectiveZoom()) * style()->effectiveZoom(); |
+ setScrollTop(top); |
+ } |
+ } |
+ |
+ if (m_layer) |
+ m_layer->styleChanged(diff, oldStyle); |
+ |
+ // Set the text color if we're the body. |
+ if (isBody()) |
+ document()->setTextColor(style()->color()); |
} |
void RenderBox::layout() |
@@ -375,37 +424,37 @@ |
int RenderBox::scrollWidth() const |
{ |
if (hasOverflowClip()) |
- return layer()->scrollWidth(); |
+ return m_layer->scrollWidth(); |
return overflowWidth(); |
} |
int RenderBox::scrollHeight() const |
{ |
if (hasOverflowClip()) |
- return layer()->scrollHeight(); |
+ return m_layer->scrollHeight(); |
return overflowHeight(); |
} |
int RenderBox::scrollLeft() const |
{ |
- return hasOverflowClip() ? layer()->scrollXOffset() : 0; |
+ return hasOverflowClip() ? m_layer->scrollXOffset() : 0; |
} |
int RenderBox::scrollTop() const |
{ |
- return hasOverflowClip() ? layer()->scrollYOffset() : 0; |
+ return hasOverflowClip() ? m_layer->scrollYOffset() : 0; |
} |
void RenderBox::setScrollLeft(int newLeft) |
{ |
if (hasOverflowClip()) |
- layer()->scrollToXOffset(newLeft); |
+ m_layer->scrollToXOffset(newLeft); |
} |
void RenderBox::setScrollTop(int newTop) |
{ |
if (hasOverflowClip()) |
- layer()->scrollToYOffset(newTop); |
+ m_layer->scrollToYOffset(newTop); |
} |
int RenderBox::paddingTop(bool) const |
@@ -469,7 +518,7 @@ |
} |
-IntRect RenderBox::outlineBoundsForRepaint(RenderBoxModelObject* /*repaintContainer*/) const |
+IntRect RenderBox::outlineBoundsForRepaint(RenderBox* /*repaintContainer*/) const |
{ |
IntRect box = borderBoundingBox(); |
adjustRectForOutlineAndShadow(box); |
@@ -1272,9 +1321,9 @@ |
int clipHeight = height() - bTop - borderBottom(); |
// Subtract out scrollbars if we have them. |
- if (layer()) { |
- clipWidth -= layer()->verticalScrollbarWidth(); |
- clipHeight -= layer()->horizontalScrollbarHeight(); |
+ if (m_layer) { |
+ clipWidth -= m_layer->verticalScrollbarWidth(); |
+ clipHeight -= m_layer->horizontalScrollbarHeight(); |
} |
return IntRect(clipX, clipY, clipWidth, clipHeight); |
@@ -1326,8 +1375,8 @@ |
IntSize offset = layoutState->m_offset; |
offset.expand(x(), y()); |
localPoint += offset; |
- if (style()->position() == RelativePosition && layer()) |
- localPoint += layer()->relativePositionOffset(); |
+ if (style()->position() == RelativePosition && m_layer) |
+ localPoint += m_layer->relativePositionOffset(); |
return localPoint; |
} |
} |
@@ -1337,9 +1386,9 @@ |
RenderObject* o = container(); |
if (o) { |
- if (useTransforms && layer() && layer()->transform()) { |
+ if (useTransforms && m_layer && m_layer->transform()) { |
fixed = false; // Elements with transforms act as a containing block for fixed position descendants |
- localPoint = layer()->transform()->mapPoint(localPoint); |
+ localPoint = m_layer->transform()->mapPoint(localPoint); |
} |
localPoint += offsetFromContainer(o); |
@@ -1358,22 +1407,22 @@ |
if (style()->position() == FixedPosition) |
fixed = true; |
- if (useTransforms && layer() && layer()->transform()) |
+ if (useTransforms && m_layer && m_layer->transform()) |
fixed = false; |
RenderObject* o = container(); |
if (o) { |
FloatPoint localPoint = o->absoluteToLocal(containerPoint, fixed, useTransforms); |
localPoint -= offsetFromContainer(o); |
- if (useTransforms && layer() && layer()->transform()) |
- localPoint = layer()->transform()->inverse().mapPoint(localPoint); |
+ if (useTransforms && m_layer && m_layer->transform()) |
+ localPoint = m_layer->transform()->inverse().mapPoint(localPoint); |
return localPoint; |
} |
return FloatPoint(); |
} |
-FloatQuad RenderBox::localToContainerQuad(const FloatQuad& localQuad, RenderBoxModelObject* repaintContainer, bool fixed) const |
+FloatQuad RenderBox::localToContainerQuad(const FloatQuad& localQuad, RenderBox* repaintContainer, bool fixed) const |
{ |
if (repaintContainer == this) |
return localQuad; |
@@ -1384,9 +1433,9 @@ |
RenderObject* o = container(); |
if (o) { |
FloatQuad quad = localQuad; |
- if (layer() && layer()->transform()) { |
+ if (m_layer && m_layer->transform()) { |
fixed = false; // Elements with transforms act as a containing block for fixed position descendants |
- quad = layer()->transform()->mapQuad(quad); |
+ quad = m_layer->transform()->mapQuad(quad); |
} |
quad += offsetFromContainer(o); |
return o->localToContainerQuad(quad, repaintContainer, fixed); |
@@ -1439,18 +1488,18 @@ |
if (isPositioned()) { |
// Cache the x position only if we were an INLINE type originally. |
bool wasInline = style()->isOriginalDisplayInlineType(); |
- if (wasInline && style()->hasStaticX()) { |
+ if (wasInline && hasStaticX()) { |
// The value is cached in the xPos of the box. We only need this value if |
// our object was inline originally, since otherwise it would have ended up underneath |
// the inlines. |
- layer()->setStaticX(box->xPos()); |
+ setStaticX(box->xPos()); |
setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly. |
- } else if (!wasInline && style()->hasStaticY()) { |
+ } else if (!wasInline && hasStaticY()) { |
// Our object was a block originally, so we make our normal flow position be |
// just below the line box (as though all the inlines that came before us got |
// wrapped in an anonymous block, which is what would have happened had we been |
// in flow). This value was cached in the yPos() of the box. |
- layer()->setStaticY(box->yPos()); |
+ setStaticY(box->yPos()); |
setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly. |
} |
@@ -1473,7 +1522,7 @@ |
} |
} |
-IntRect RenderBox::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) |
+IntRect RenderBox::clippedOverflowRectForRepaint(RenderBox* repaintContainer) |
{ |
if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) |
return IntRect(); |
@@ -1503,14 +1552,14 @@ |
return r; |
} |
-void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed) |
+void RenderBox::computeRectForRepaint(RenderBox* repaintContainer, IntRect& rect, bool fixed) |
{ |
if (RenderView* v = view()) { |
// LayoutState is only valid for root-relative repainting |
if (v->layoutStateEnabled() && !repaintContainer) { |
LayoutState* layoutState = v->layoutState(); |
- if (style()->position() == RelativePosition && layer()) |
- rect.move(layer()->relativePositionOffset()); |
+ if (style()->position() == RelativePosition && m_layer) |
+ rect.move(m_layer->relativePositionOffset()); |
rect.move(x(), y()); |
rect.move(layoutState->m_offset); |
@@ -1548,9 +1597,9 @@ |
// We are now in our parent container's coordinate space. Apply our transform to obtain a bounding box |
// in the parent's coordinate space that encloses us. |
- if (layer() && layer()->transform()) { |
+ if (m_layer && m_layer->transform()) { |
fixed = false; |
- rect = layer()->transform()->mapRect(rect); |
+ rect = m_layer->transform()->mapRect(rect); |
// FIXME: this clobbers topLeft adjustment done for multicol above |
topLeft = rect.location(); |
topLeft.move(x(), y()); |
@@ -1558,12 +1607,12 @@ |
if (style()->position() == AbsolutePosition && o->isRelPositioned() && o->isRenderInline()) |
topLeft += toRenderInline(o)->relativePositionedInlineOffset(this); |
- else if (style()->position() == RelativePosition && layer()) { |
+ else if (style()->position() == RelativePosition && m_layer) { |
// Apply the relative position offset when invalidating a rectangle. The layer |
// is translated, but the render box isn't, so we need to do this to get the |
// right dirty rect. Since this is called from RenderObject::setStyle, the relative position |
// flag on the RenderObject has been cleared, so use the one on the style(). |
- topLeft += layer()->relativePositionOffset(); |
+ topLeft += m_layer->relativePositionOffset(); |
} |
// FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout, |
@@ -1605,6 +1654,30 @@ |
} |
} |
+int RenderBox::relativePositionOffsetX() const |
+{ |
+ if (!style()->left().isAuto()) { |
+ if (!style()->right().isAuto() && containingBlock()->style()->direction() == RTL) |
+ return -style()->right().calcValue(containingBlockWidth()); |
+ return style()->left().calcValue(containingBlockWidth()); |
+ } |
+ if (!style()->right().isAuto()) |
+ return -style()->right().calcValue(containingBlockWidth()); |
+ return 0; |
+} |
+ |
+int RenderBox::relativePositionOffsetY() const |
+{ |
+ if (!style()->top().isAuto()) { |
+ if (!style()->top().isPercent() || containingBlock()->style()->height().isFixed()) |
+ return style()->top().calcValue(containingBlockHeight()); |
+ } else if (!style()->bottom().isAuto()) { |
+ if (!style()->bottom().isPercent() || containingBlock()->style()->height().isFixed()) |
+ return -style()->bottom().calcValue(containingBlockHeight()); |
+ } |
+ return 0; |
+} |
+ |
void RenderBox::calcWidth() |
{ |
if (isPositioned()) { |
@@ -2047,7 +2120,7 @@ |
return calcContentBoxHeight(h.calcValue(containingBlock()->availableHeight())); |
if (isRenderBlock() && isPositioned() && style()->height().isAuto() && !(style()->top().isAuto() || style()->bottom().isAuto())) { |
- RenderBlock* block = const_cast<RenderBlock*>(toRenderBlock(this)); |
+ RenderBlock* block = const_cast<RenderBlock*>(static_cast<const RenderBlock*>(this)); |
int oldHeight = block->height(); |
block->calcHeight(); |
int newHeight = block->calcContentBoxHeight(block->contentHeight()); |
@@ -2074,6 +2147,33 @@ |
m_marginBottom = style()->marginBottom().calcMinValue(cw); |
} |
+int RenderBox::staticX() const |
+{ |
+ return m_layer ? m_layer->staticX() : 0; |
+} |
+ |
+int RenderBox::staticY() const |
+{ |
+ return m_layer ? m_layer->staticY() : 0; |
+} |
+ |
+void RenderBox::setStaticX(int staticX) |
+{ |
+ ASSERT(isPositioned() || isRelPositioned()); |
+ m_layer->setStaticX(staticX); |
+} |
+ |
+void RenderBox::setStaticY(int staticY) |
+{ |
+ ASSERT(isPositioned() || isRelPositioned()); |
+ |
+ if (staticY == m_layer->staticY()) |
+ return; |
+ |
+ m_layer->setStaticY(staticY); |
+ setChildNeedsLayout(true, false); |
+} |
+ |
int RenderBox::containingBlockWidthForPositioned(const RenderObject* containingBlock) const |
{ |
if (containingBlock->isRenderInline()) { |
@@ -2195,14 +2295,14 @@ |
if (left.isAuto() && right.isAuto()) { |
if (containerDirection == LTR) { |
// 'staticX' should already have been set through layout of the parent. |
- int staticPosition = layer()->staticX() - containerBlock->borderLeft(); |
+ int staticPosition = staticX() - containerBlock->borderLeft(); |
for (RenderBox* po = parentBox(); po && po != containerBlock; po = po->parentBox()) |
staticPosition += po->x(); |
left.setValue(Fixed, staticPosition); |
} else { |
RenderBox* po = parentBox(); |
// 'staticX' should already have been set through layout of the parent. |
- int staticPosition = layer()->staticX() + containerWidth + containerBlock->borderRight() - po->width(); |
+ int staticPosition = staticX() + containerWidth + containerBlock->borderRight() - po->width(); |
for (; po && po != containerBlock; po = po->parentBox()) |
staticPosition -= po->x(); |
right.setValue(Fixed, staticPosition); |
@@ -2490,7 +2590,7 @@ |
// Calculate the static distance if needed. |
if (top.isAuto() && bottom.isAuto()) { |
// staticY should already have been set through layout of the parent() |
- int staticTop = layer()->staticY() - containerBlock->borderTop(); |
+ int staticTop = staticY() - containerBlock->borderTop(); |
for (RenderBox* po = parentBox(); po && po != containerBlock; po = po->parentBox()) { |
if (!po->isTableRow()) |
staticTop += po->y(); |
@@ -2717,14 +2817,14 @@ |
// see FIXME 1 |
if (containerDirection == LTR) { |
// 'staticX' should already have been set through layout of the parent. |
- int staticPosition = layer()->staticX() - containerBlock->borderLeft(); |
+ int staticPosition = staticX() - containerBlock->borderLeft(); |
for (RenderBox* po = parentBox(); po && po != containerBlock; po = po->parentBox()) |
staticPosition += po->x(); |
left.setValue(Fixed, staticPosition); |
} else { |
RenderBox* po = parentBox(); |
// 'staticX' should already have been set through layout of the parent. |
- int staticPosition = layer()->staticX() + containerWidth + containerBlock->borderRight() - po->width(); |
+ int staticPosition = staticX() + containerWidth + containerBlock->borderRight() - po->width(); |
for (; po && po != containerBlock; po = po->parentBox()) |
staticPosition -= po->x(); |
right.setValue(Fixed, staticPosition); |
@@ -2883,7 +2983,7 @@ |
// see FIXME 2 |
if (top.isAuto() && bottom.isAuto()) { |
// staticY should already have been set through layout of the parent(). |
- int staticTop = layer()->staticY() - containerBlock->borderTop(); |
+ int staticTop = staticY() - containerBlock->borderTop(); |
for (RenderBox* po = parentBox(); po && po != containerBlock; po = po->parentBox()) { |
if (!po->isTableRow()) |
staticTop += po->y(); |