#include "HTMLNames.h"
#include "core/dom/Document.h"
#include "core/editing/htmlediting.h"
+#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLElement.h"
#include "core/html/HTMLFrameElementBase.h"
#include "core/html/HTMLFrameOwnerElement.h"
-#include "core/html/HTMLHtmlElement.h"
-#include "core/html/HTMLTextAreaElement.h"
-#include "core/frame/Frame.h"
-#include "core/frame/FrameView.h"
#include "core/page/AutoscrollController.h"
#include "core/page/EventHandler.h"
#include "core/page/Page.h"
-#include "core/platform/graphics/GraphicsContextStateSaver.h"
#include "core/rendering/HitTestResult.h"
#include "core/rendering/PaintInfo.h"
-#include "core/rendering/RenderBoxRegionInfo.h"
+#include "core/rendering/RenderDeprecatedFlexibleBox.h"
#include "core/rendering/RenderFlexibleBox.h"
-#include "core/rendering/RenderFlowThread.h"
#include "core/rendering/RenderGeometryMap.h"
#include "core/rendering/RenderGrid.h"
#include "core/rendering/RenderInline.h"
#include "core/rendering/RenderLayer.h"
-#include "core/rendering/RenderLayerCompositor.h"
+#include "core/rendering/RenderListBox.h"
#include "core/rendering/RenderListMarker.h"
-#include "core/rendering/RenderRegion.h"
#include "core/rendering/RenderTableCell.h"
#include "core/rendering/RenderTheme.h"
#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
+#include "platform/LengthFunctions.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/geometry/TransformState.h"
+#include "platform/graphics/GraphicsContextStateSaver.h"
using namespace std;
// Used by flexible boxes when flexing this element and by table cells.
typedef WTF::HashMap<const RenderBox*, LayoutUnit> OverrideSizeMap;
-static OverrideSizeMap* gOverrideHeightMap = 0;
-static OverrideSizeMap* gOverrideWidthMap = 0;
// Used by grid elements to properly size their grid items.
+// FIXME: Move these into RenderBoxRareData.
static OverrideSizeMap* gOverrideContainingBlockLogicalHeightMap = 0;
static OverrideSizeMap* gOverrideContainingBlockLogicalWidthMap = 0;
static const int autoscrollBeltSize = 20;
static const unsigned backgroundObscurationTestMaxDepth = 4;
-bool RenderBox::s_hadOverflowClip = false;
-
static bool skipBodyBackground(const RenderBox* bodyElementRenderer)
{
ASSERT(bodyElementRenderer->isBody());
RenderBox::RenderBox(ContainerNode* node)
: RenderBoxModelObject(node)
+ , m_intrinsicContentLogicalHeight(-1)
, m_minPreferredLogicalWidth(-1)
, m_maxPreferredLogicalWidth(-1)
- , m_intrinsicContentLogicalHeight(-1)
- , m_inlineBoxWrapper(0)
{
setIsBox();
}
-RenderBox::~RenderBox()
-{
-}
-
-LayoutRect RenderBox::borderBoxRectInRegion(RenderRegion* region, RenderBoxRegionInfoFlags cacheFlag) const
-{
- if (!region)
- return borderBoxRect();
-
- // Compute the logical width and placement in this region.
- RenderBoxRegionInfo* boxInfo = renderBoxRegionInfo(region, cacheFlag);
- if (!boxInfo)
- return borderBoxRect();
-
- // We have cached insets.
- LayoutUnit logicalWidth = boxInfo->logicalWidth();
- LayoutUnit logicalLeft = boxInfo->logicalLeft();
-
- // Now apply the parent inset since it is cumulative whenever anything in the containing block chain shifts.
- // FIXME: Doesn't work right with perpendicular writing modes.
- const RenderBlock* currentBox = containingBlock();
- RenderBoxRegionInfo* currentBoxInfo = currentBox->renderBoxRegionInfo(region);
- while (currentBoxInfo && currentBoxInfo->isShifted()) {
- if (currentBox->style()->direction() == LTR)
- logicalLeft += currentBoxInfo->logicalLeft();
- else
- logicalLeft -= (currentBox->logicalWidth() - currentBoxInfo->logicalWidth()) - currentBoxInfo->logicalLeft();
- currentBox = currentBox->containingBlock();
- region = currentBox->clampToStartAndEndRegions(region);
- currentBoxInfo = currentBox->renderBoxRegionInfo(region);
- }
-
- if (cacheFlag == DoNotCacheRenderBoxRegionInfo)
- delete boxInfo;
-
- if (isHorizontalWritingMode())
- return LayoutRect(logicalLeft, 0, logicalWidth, height());
- return LayoutRect(0, logicalLeft, width(), logicalWidth);
-}
-
-void RenderBox::clearRenderBoxRegionInfo()
-{
- if (isRenderFlowThread())
- return;
-
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (flowThread)
- flowThread->removeRenderBoxRegionInfo(this);
-}
-
void RenderBox::willBeDestroyed()
{
clearOverrideSize();
RenderBlock::removePercentHeightDescendantIfNeeded(this);
- ShapeOutsideInfo::removeInfo(this);
+ ShapeOutsideInfo::removeInfo(*this);
RenderBoxModelObject::willBeDestroyed();
}
RenderBlock::removePositionedObject(this);
}
-void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
{
- s_hadOverflowClip = hasOverflowClip();
-
RenderStyle* oldStyle = style();
if (oldStyle) {
// The background of the root element or the body element could propagate up to
// the canvas. Just dirty the entire canvas when our style changes substantially.
- if (diff >= StyleDifferenceRepaint && node() &&
- (isHTMLHtmlElement(node()) || node()->hasTagName(bodyTag))) {
+ if ((diff.needsRepaint() || diff.needsLayout()) && node()
+ && (isHTMLHtmlElement(*node()) || isHTMLBodyElement(*node()))) {
view()->repaint();
- if (oldStyle->hasEntirelyFixedBackground() != newStyle->hasEntirelyFixedBackground())
- view()->compositor()->rootFixedBackgroundsChanged();
+ if (oldStyle->hasEntirelyFixedBackground() != newStyle.hasEntirelyFixedBackground())
+ view()->compositor()->setNeedsUpdateFixedBackground();
}
// When a layout hint happens and an object's position style changes, we have to do a layout
// to dirty the render tree using the old position value now.
- if (diff == StyleDifferenceLayout && parent() && oldStyle->position() != newStyle->position()) {
+ if (diff.needsFullLayout() && parent() && oldStyle->position() != newStyle.position()) {
markContainingBlocksForLayout();
if (oldStyle->position() == StaticPosition)
repaint();
- else if (newStyle->hasOutOfFlowPosition())
+ else if (newStyle.hasOutOfFlowPosition())
parent()->setChildNeedsLayout();
- if (isFloating() && !isOutOfFlowPositioned() && newStyle->hasOutOfFlowPosition())
+ if (isFloating() && !isOutOfFlowPositioned() && newStyle.hasOutOfFlowPosition())
removeFloatingOrPositionedChildFromBlockLists();
}
- } else if (newStyle && isBody())
+ // FIXME: This branch runs when !oldStyle, which means that layout was never called
+ // so what's the point in invalidating the whole view that we never painted?
+ } else if (isBody())
view()->repaint();
RenderBoxModelObject::styleWillChange(diff, newStyle);
}
// Our opaqueness might have changed without triggering layout.
- if (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintIfTextOrColorChange || diff == StyleDifferenceRepaintLayer) {
+ if (diff.needsRepaint()) {
RenderObject* parentToInvalidate = parent();
for (unsigned i = 0; i < backgroundObscurationTestMaxDepth && parentToInvalidate; ++i) {
parentToInvalidate->invalidateBackgroundObscurationStatus();
}
}
- if (isRoot() || isBody())
+ if (isDocumentElement() || isBody())
document().view()->recalculateScrollbarOverlayStyle();
updateShapeOutsideInfoAfterStyleChange(*style(), oldStyle);
Length shapeMargin = style.shapeMargin();
Length oldShapeMargin = oldStyle ? oldStyle->shapeMargin() : RenderStyle::initialShapeMargin();
+ float shapeImageThreshold = style.shapeImageThreshold();
+ float oldShapeImageThreshold = oldStyle ? oldStyle->shapeImageThreshold() : RenderStyle::initialShapeImageThreshold();
+
// FIXME: A future optimization would do a deep comparison for equality. (bug 100811)
- if (shapeOutside == oldShapeOutside && shapeMargin == oldShapeMargin)
+ if (shapeOutside == oldShapeOutside && shapeMargin == oldShapeMargin && shapeImageThreshold == oldShapeImageThreshold)
return;
if (!shapeOutside)
- ShapeOutsideInfo::removeInfo(this);
+ ShapeOutsideInfo::removeInfo(*this);
else
- ShapeOutsideInfo::ensureInfo(this)->dirtyShapeSize();
+ ShapeOutsideInfo::ensureInfo(*this).markShapeAsDirty();
if (shapeOutside || shapeOutside != oldShapeOutside)
markShapeOutsideDependentsForLayout();
RenderBoxModelObject::updateFromStyle();
RenderStyle* styleToUse = style();
- bool isRootObject = isRoot();
+ bool isRootObject = isDocumentElement();
bool isViewObject = isRenderView();
// The root and the RenderView always paint their backgrounds/borders.
setFloating(!isOutOfFlowPositioned() && styleToUse->isFloating());
- // We also handle <body> and <html>, whose overflow applies to the viewport.
- if (styleToUse->overflowX() != OVISIBLE && !isRootObject && isRenderBlock()) {
- bool boxHasOverflowClip = true;
- if (isBody()) {
- // Overflow on the body can propagate to the viewport under the following conditions.
- // (1) The root element is <html>.
- // (2) We are the primary <body> (can be checked by looking at document.body).
- // (3) The root element has visible overflow.
- if (isHTMLHtmlElement(document().documentElement())
- && document().body() == node()
- && document().documentElement()->renderer()->style()->overflowX() == OVISIBLE)
- boxHasOverflowClip = false;
+ bool boxHasOverflowClip = false;
+ if (!styleToUse->isOverflowVisible() && isRenderBlock() && !isViewObject) {
+ // If overflow has been propagated to the viewport, it has no effect here.
+ if (node() != document().viewportDefiningElement()) {
+ boxHasOverflowClip = true;
+ if (!hasOverflowClip()) {
+ // If we are getting an overflow clip, preemptively erase any overflowing content.
+ // FIXME: This should probably consult RenderOverflow.
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ repaint();
+ }
}
+ }
- // Check for overflow clip.
- // It's sufficient to just check one direction, since it's illegal to have visible on only one overflow value.
- if (boxHasOverflowClip) {
- if (!s_hadOverflowClip)
- // Erase the overflow
- repaint();
- setHasOverflowClip();
- }
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && (boxHasOverflowClip != hasOverflowClip())) {
+ // FIXME: This shouldn't be required if we tracked the visual overflow
+ // generated by positioned children or self painting layers. crbug.com/345403
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling())
+ child->setShouldDoFullRepaintIfSelfPaintingLayer(true);
}
+ setHasOverflowClip(boxHasOverflowClip);
+
setHasTransform(styleToUse->hasTransformRelatedProperty());
setHasReflection(styleToUse->boxReflect());
}
return;
}
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
+ LayoutStateMaintainer statePusher(*this, locationOffset());
while (child) {
child->layoutIfNeeded();
ASSERT(!child->needsLayout());
child = child->nextSibling();
}
- statePusher.pop();
invalidateBackgroundObscurationStatus();
clearNeedsLayout();
}
return snapSizeToPixel(offsetHeight(), y() + clientTop());
}
-bool RenderBox::canDetermineWidthWithoutLayout() const
-{
- // FIXME: This optimization is incorrect as written.
- // We need to be able to opt-in to this behavior only when
- // it's guarentted correct.
- // Until then disabling this optimization to be safe.
- return false;
-
- // FIXME: There are likely many subclasses of RenderBlockFlow which
- // cannot determine their layout just from style!
- // Perhaps we should create a "PlainRenderBlockFlow"
- // and move this optimization there?
- if (!isRenderBlockFlow()
- // Flexbox items can be expanded beyond their width.
- || isFlexItemIncludingDeprecated()
- // Table Layout controls cell size and can expand beyond width.
- || isTableCell())
- return false;
-
- RenderStyle* style = this->style();
- return style->width().isFixed()
- && style->minWidth().isFixed()
- && (style->maxWidth().isUndefined() || style->maxWidth().isFixed())
- && style->paddingLeft().isFixed()
- && style->paddingRight().isFixed()
- && style->boxSizing() == CONTENT_BOX;
-}
-
-LayoutUnit RenderBox::fixedOffsetWidth() const
-{
- ASSERT(canDetermineWidthWithoutLayout());
-
- RenderStyle* style = this->style();
-
- LayoutUnit width = std::max(LayoutUnit(style->minWidth().value()), LayoutUnit(style->width().value()));
- if (style->maxWidth().isFixed())
- width = std::min(LayoutUnit(style->maxWidth().value()), width);
-
- LayoutUnit borderLeft = style->borderLeft().nonZero() ? style->borderLeft().width() : 0;
- LayoutUnit borderRight = style->borderRight().nonZero() ? style->borderRight().width() : 0;
-
- return width + borderLeft + borderRight + style->paddingLeft().value() + style->paddingRight().value();
-}
-
int RenderBox::scrollWidth() const
{
if (hasOverflowClip())
void RenderBox::setScrollLeft(int newLeft)
{
+ // This doesn't hit in any tests, but since the equivalent code in setScrollTop
+ // does, presumably this code does as well.
+ DisableCompositingQueryAsserts disabler;
+
if (hasOverflowClip())
layer()->scrollableArea()->scrollToXOffset(newLeft, ScrollOffsetClamped);
}
void RenderBox::setScrollTop(int newTop)
{
+ // Hits in compositing/overflow/do-not-assert-on-invisible-composited-layers.html
+ DisableCompositingQueryAsserts disabler;
+
if (hasOverflowClip())
layer()->scrollableArea()->scrollToYOffset(newTop, ScrollOffsetClamped);
}
void RenderBox::scrollToOffset(const IntSize& offset)
{
ASSERT(hasOverflowClip());
+
+ // This doesn't hit in any tests, but since the equivalent code in setScrollTop
+ // does, presumably this code does as well.
+ DisableCompositingQueryAsserts disabler;
layer()->scrollableArea()->scrollToOffset(offset, ScrollOffsetClamped);
}
void RenderBox::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
{
+ // Presumably the same issue as in setScrollTop. See crbug.com/343132.
+ DisableCompositingQueryAsserts disabler;
+
RenderBox* parentBox = 0;
LayoutRect newRect = rect;
if (ownerElement && ownerElement->renderer()) {
HTMLFrameElementBase* frameElementBase = 0;
- if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))
+ if (isHTMLFrameElement(*ownerElement) || isHTMLIFrameElement(*ownerElement))
frameElementBase = toHTMLFrameElementBase(ownerElement);
if (frameElementAndViewPermitScroll(frameElementBase, frameView)) {
void RenderBox::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
{
- quads.append(localToAbsoluteQuad(FloatRect(0, 0, width(), height()), 0 /* mode */, wasFixed));
+ quads.append(localToAbsoluteQuad(FloatRect(0, 0, width().toFloat(), height().toFloat()), 0 /* mode */, wasFixed));
}
void RenderBox::updateLayerTransform()
layer()->updateTransform();
}
-LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb, RenderRegion* region) const
+LayoutUnit RenderBox::constrainLogicalWidthByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb) const
{
RenderStyle* styleToUse = style();
if (!styleToUse->logicalMaxWidth().isUndefined())
- logicalWidth = min(logicalWidth, computeLogicalWidthInRegionUsing(MaxSize, styleToUse->logicalMaxWidth(), availableWidth, cb, region));
- return max(logicalWidth, computeLogicalWidthInRegionUsing(MinSize, styleToUse->logicalMinWidth(), availableWidth, cb, region));
+ logicalWidth = min(logicalWidth, computeLogicalWidthUsing(MaxSize, styleToUse->logicalMaxWidth(), availableWidth, cb));
+ return max(logicalWidth, computeLogicalWidthUsing(MinSize, styleToUse->logicalMinWidth(), availableWidth, cb));
}
LayoutUnit RenderBox::constrainLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const
return localToAbsoluteQuad(FloatRect(rect));
}
-LayoutRect RenderBox::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap) const
-{
- LayoutRect box = borderBoundingBox();
- adjustRectForOutlineAndShadow(box);
-
- if (repaintContainer != this) {
- FloatQuad containerRelativeQuad;
- if (geometryMap)
- containerRelativeQuad = geometryMap->mapToContainer(box, repaintContainer);
- else
- containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer);
-
- box = containerRelativeQuad.enclosingBoundingBox();
- }
-
- // FIXME: layoutDelta needs to be applied in parts before/after transforms and
- // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
- box.move(view()->layoutDelta());
-
- return box;
-}
-
void RenderBox::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*)
{
if (!size().isEmpty())
rects.append(LayoutRect(layerOffset, size()));
}
-LayoutRect RenderBox::reflectionBox() const
-{
- LayoutRect result;
- if (!style()->boxReflect())
- return result;
- LayoutRect box = borderBoxRect();
- result = box;
- switch (style()->boxReflect()->direction()) {
- case ReflectionBelow:
- result.move(0, box.height() + reflectionOffset());
- break;
- case ReflectionAbove:
- result.move(0, -box.height() - reflectionOffset());
- break;
- case ReflectionLeft:
- result.move(-box.width() - reflectionOffset(), 0);
- break;
- case ReflectionRight:
- result.move(box.width() + reflectionOffset(), 0);
- break;
- }
- return result;
-}
-
int RenderBox::reflectionOffset() const
{
if (!style()->boxReflect())
return 0;
- RenderView* renderView = view();
if (style()->boxReflect()->direction() == ReflectionLeft || style()->boxReflect()->direction() == ReflectionRight)
- return valueForLength(style()->boxReflect()->offset(), borderBoxRect().width(), renderView);
- return valueForLength(style()->boxReflect()->offset(), borderBoxRect().height(), renderView);
+ return valueForLength(style()->boxReflect()->offset(), borderBoxRect().width());
+ return valueForLength(style()->boxReflect()->offset(), borderBoxRect().height());
}
LayoutRect RenderBox::reflectedRect(const LayoutRect& r) const
return 0;
}
-bool RenderBox::scrollImpl(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
+bool RenderBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float delta)
{
- RenderLayer* layer = this->layer();
- return layer && layer->scrollableArea() && layer->scrollableArea()->scroll(direction, granularity, multiplier);
-}
+ // Presumably the same issue as in setScrollTop. See crbug.com/343132.
+ DisableCompositingQueryAsserts disabler;
-bool RenderBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
-{
- if (scrollImpl(direction, granularity, multiplier)) {
- if (stopNode)
- *stopNode = node();
- return true;
- }
+ // Logical scroll is a higher level concept, all directions by here must be physical
+ ASSERT(!isLogical(direction));
- if (stopNode && *stopNode && *stopNode == node())
- return true;
-
- RenderBlock* b = containingBlock();
- if (b && !b->isRenderView())
- return b->scroll(direction, granularity, multiplier, stopNode);
- return false;
-}
-
-bool RenderBox::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
-{
- if (scrollImpl(logicalToPhysical(direction, isHorizontalWritingMode(), style()->isFlippedBlocksWritingMode()),
- granularity, multiplier)) {
- if (stopNode)
- *stopNode = node();
- return true;
- }
-
- if (stopNode && *stopNode && *stopNode == node())
- return true;
+ if (!layer() || !layer()->scrollableArea())
+ return false;
- RenderBlock* b = containingBlock();
- if (b && !b->isRenderView())
- return b->logicalScroll(direction, granularity, multiplier, stopNode);
- return false;
+ return layer()->scrollableArea()->scroll(direction, granularity, delta);
}
bool RenderBox::canBeScrolledAndHasScrollableArea() const
void RenderBox::autoscroll(const IntPoint& position)
{
- Frame* frame = this->frame();
+ LocalFrame* frame = this->frame();
if (!frame)
return;
void RenderBox::panScroll(const IntPoint& sourcePoint)
{
- Frame* frame = this->frame();
+ LocalFrame* frame = this->frame();
if (!frame)
return;
if (RenderBox* scrollableBox = enclosingScrollableBox())
scrollableBox->scrollByRecursively(remainingScrollOffset, clamp);
- Frame* frame = this->frame();
+ LocalFrame* frame = this->frame();
if (frame && frame->page())
frame->page()->autoscrollController().updateAutoscrollRenderer();
}
void RenderBox::applyCachedClipAndScrollOffsetForRepaint(LayoutRect& paintRect) const
{
+ flipForWritingMode(paintRect);
paintRect.move(-scrolledContentOffset()); // For overflow:auto/scroll/hidden.
// Do not clip scroll layer contents to reduce the number of repaints while scrolling.
- if (usesCompositedScrolling())
+ if (usesCompositedScrolling()) {
+ flipForWritingMode(paintRect);
return;
+ }
// height() is inaccurate if we're in the middle of a layout of this RenderBox, so use the
// layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
// anyway if its size does change.
LayoutRect clipRect(LayoutPoint(), cachedSizeForOverflowClip());
paintRect = intersection(paintRect, clipRect);
+ flipForWritingMode(paintRect);
}
void RenderBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
{
if (preferredLogicalWidthsDirty()) {
#ifndef NDEBUG
- SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox*>(this));
+ SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox&>(*this));
#endif
const_cast<RenderBox*>(this)->computePreferredLogicalWidths();
}
{
if (preferredLogicalWidthsDirty()) {
#ifndef NDEBUG
- SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox*>(this));
+ SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox&>(*this));
#endif
const_cast<RenderBox*>(this)->computePreferredLogicalWidths();
}
bool RenderBox::hasOverrideHeight() const
{
- return gOverrideHeightMap && gOverrideHeightMap->contains(this);
+ return m_rareData && m_rareData->m_overrideLogicalContentHeight != -1;
}
bool RenderBox::hasOverrideWidth() const
{
- return gOverrideWidthMap && gOverrideWidthMap->contains(this);
+ return m_rareData && m_rareData->m_overrideLogicalContentWidth != -1;
}
void RenderBox::setOverrideLogicalContentHeight(LayoutUnit height)
{
- if (!gOverrideHeightMap)
- gOverrideHeightMap = new OverrideSizeMap();
- gOverrideHeightMap->set(this, height);
+ ASSERT(height >= 0);
+ ensureRareData().m_overrideLogicalContentHeight = height;
}
void RenderBox::setOverrideLogicalContentWidth(LayoutUnit width)
{
- if (!gOverrideWidthMap)
- gOverrideWidthMap = new OverrideSizeMap();
- gOverrideWidthMap->set(this, width);
+ ASSERT(width >= 0);
+ ensureRareData().m_overrideLogicalContentWidth = width;
}
void RenderBox::clearOverrideLogicalContentHeight()
{
- if (gOverrideHeightMap)
- gOverrideHeightMap->remove(this);
+ if (m_rareData)
+ m_rareData->m_overrideLogicalContentHeight = -1;
}
void RenderBox::clearOverrideLogicalContentWidth()
{
- if (gOverrideWidthMap)
- gOverrideWidthMap->remove(this);
+ if (m_rareData)
+ m_rareData->m_overrideLogicalContentWidth = -1;
}
void RenderBox::clearOverrideSize()
LayoutUnit RenderBox::overrideLogicalContentWidth() const
{
ASSERT(hasOverrideWidth());
- return gOverrideWidthMap->get(this);
+ return m_rareData->m_overrideLogicalContentWidth;
}
LayoutUnit RenderBox::overrideLogicalContentHeight() const
{
ASSERT(hasOverrideHeight());
- return gOverrideHeightMap->get(this);
+ return m_rareData->m_overrideLogicalContentHeight;
}
LayoutUnit RenderBox::overrideContainingBlockContentLogicalWidth() const
// Check our bounds next. For this purpose always assume that we can only be hit in the
// foreground phase (which is true for replaced elements like images).
- LayoutRect boundsRect = borderBoxRectInRegion(locationInContainer.region());
+ LayoutRect boundsRect = borderBoxRect();
boundsRect.moveBy(adjustedLocation);
if (visibleToHitTestRequest(request) && action == HitTestForeground && locationInContainer.intersects(boundsRect)) {
updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
if (!style->hasAppearance() && borderObscuresBackground() && backgroundHasOpaqueTopLayer())
return BackgroundBleedBackgroundOverBorder;
- return BackgroundBleedUseTransparencyLayer;
+ return BackgroundBleedClipBackground;
}
void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
if (!paintInfo.shouldPaintWithinRoot(this))
return;
- LayoutRect paintRect = borderBoxRectInRegion(paintInfo.renderRegion);
+ LayoutRect paintRect = borderBoxRect();
paintRect.moveBy(paintOffset);
paintBoxDecorationsWithRect(paintInfo, paintOffset, paintRect);
}
paintBoxShadow(paintInfo, paintRect, style(), Normal);
GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
- if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) {
- // To avoid the background color bleeding out behind the border, we'll render background and border
- // into a transparency layer, and then clip that in one go (which requires setting up the clip before
- // beginning the layer).
- RoundedRect border = style()->getRoundedBorderFor(paintRect, view());
+ if (bleedAvoidance == BackgroundBleedClipBackground) {
stateSaver.save();
+ RoundedRect border = style()->getRoundedBorderFor(paintRect);
paintInfo.context->clipRoundedRect(border);
- paintInfo.context->beginTransparencyLayer(1);
}
paintBackgroundWithBorderAndBoxShadow(paintInfo, paintRect, bleedAvoidance);
-
- if (bleedAvoidance == BackgroundBleedUseTransparencyLayer)
- paintInfo.context->endLayer();
}
void RenderBox::paintBackgroundWithBorderAndBoxShadow(PaintInfo& paintInfo, const LayoutRect& paintRect, BackgroundBleedAvoidance bleedAvoidance)
paintBoxShadow(paintInfo, paintRect, style(), Inset);
// The theme will tell us whether or not we should also paint the CSS border.
- if (bleedAvoidance != BackgroundBleedBackgroundOverBorder && (!style()->hasAppearance() || (!themePainted && RenderTheme::theme().paintBorderOnly(this, paintInfo, snappedPaintRect))) && style()->hasBorder())
+ if (bleedAvoidance != BackgroundBleedBackgroundOverBorder && (!style()->hasAppearance() || (!themePainted && RenderTheme::theme().paintBorderOnly(this, paintInfo, snappedPaintRect))) && style()->hasBorder() && !(isTable() && toRenderTable(this)->collapseBorders()))
paintBorder(paintInfo, paintRect, style(), bleedAvoidance);
}
void RenderBox::paintBackground(const PaintInfo& paintInfo, const LayoutRect& paintRect, BackgroundBleedAvoidance bleedAvoidance)
{
- if (isRoot()) {
+ if (isDocumentElement()) {
paintRootBoxFillLayers(paintInfo);
return;
}
paintFillLayers(paintInfo, resolveColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect, bleedAvoidance);
}
-LayoutRect RenderBox::backgroundPaintedExtent() const
+bool RenderBox::getBackgroundPaintedExtent(LayoutRect& paintedExtent) const
{
ASSERT(hasBackground());
LayoutRect backgroundRect = pixelSnappedIntRect(borderBoxRect());
Color backgroundColor = resolveColor(CSSPropertyBackgroundColor);
- if (backgroundColor.isValid() && backgroundColor.alpha())
- return backgroundRect;
- if (!style()->backgroundLayers()->image() || style()->backgroundLayers()->next())
- return backgroundRect;
+ if (backgroundColor.alpha()) {
+ paintedExtent = backgroundRect;
+ return true;
+ }
+
+ if (!style()->backgroundLayers()->image() || style()->backgroundLayers()->next()) {
+ paintedExtent = backgroundRect;
+ return true;
+ }
+
BackgroundImageGeometry geometry;
- const_cast<RenderBox*>(this)->calculateBackgroundImageGeometry(style()->backgroundLayers(), backgroundRect, geometry);
- return geometry.destRect();
+ calculateBackgroundImageGeometry(0, style()->backgroundLayers(), backgroundRect, geometry);
+ if (geometry.hasNonLocalGeometry())
+ return false;
+ paintedExtent = geometry.destRect();
+ return true;
}
bool RenderBox::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
return false;
Color backgroundColor = resolveColor(CSSPropertyBackgroundColor);
- if (!backgroundColor.isValid() || backgroundColor.hasAlpha())
+ if (backgroundColor.hasAlpha())
return false;
// If the element has appearance, it might be painted by theme.
return false;
if (childLayer->hasTransform() || childLayer->isTransparent() || childLayer->hasFilter())
return false;
+ if (childBox->hasOverflowClip() && childStyle->hasBorderRadius())
+ return false;
}
return true;
}
if (!hasBackground())
return false;
// Table and root background painting is special.
- if (isTable() || isRoot())
+ if (isTable() || isDocumentElement())
return false;
// FIXME: box-shadow is painted while background painting.
if (style()->boxShadow())
return false;
- LayoutRect backgroundRect = backgroundPaintedExtent();
+ LayoutRect backgroundRect;
+ if (!getBackgroundPaintedExtent(backgroundRect))
+ return false;
return foregroundIsKnownToBeOpaqueInRect(backgroundRect, backgroundObscurationTestMaxDepth);
}
if (hasOverflowClip() && fillLayer->attachment() == LocalBackgroundAttachment)
return false;
- if (fillLayer->hasOpaqueImage(this) && fillLayer->hasRepeatXY() && fillLayer->image()->canRender(this, style()->effectiveZoom()))
+ if (fillLayer->hasOpaqueImage(this) && fillLayer->hasRepeatXY() && fillLayer->image()->canRender(*this, style()->effectiveZoom()))
return true;
// If there is only one layer and no image, check whether the background color is opaque
if (!fillLayer->next() && !fillLayer->hasImage()) {
Color bgColor = resolveColor(CSSPropertyBackgroundColor);
- if (bgColor.isValid() && bgColor.alpha() == 255)
+ if (bgColor.alpha() == 255)
return true;
}
}
if (allMaskImagesLoaded) {
- paintFillLayers(paintInfo, Color(), style()->maskLayers(), paintRect, BackgroundBleedNone, compositeOp);
+ paintFillLayers(paintInfo, Color::transparent, style()->maskLayers(), paintRect, BackgroundBleedNone, compositeOp);
paintNinePieceImage(paintInfo.context, paintRect, style(), style()->maskBoxImage(), compositeOp);
}
paintInfo.context->endLayer();
}
-LayoutRect RenderBox::maskClipRect()
-{
- const NinePieceImage& maskBoxImage = style()->maskBoxImage();
- if (maskBoxImage.image()) {
- LayoutRect borderImageRect = borderBoxRect();
-
- // Apply outsets to the border box.
- borderImageRect.expand(style()->maskBoxImageOutsets());
- return borderImageRect;
- }
-
- LayoutRect result;
- LayoutRect borderBox = borderBoxRect();
- for (const FillLayer* maskLayer = style()->maskLayers(); maskLayer; maskLayer = maskLayer->next()) {
- if (maskLayer->image()) {
- BackgroundImageGeometry geometry;
- calculateBackgroundImageGeometry(maskLayer, borderBox, geometry);
- result.unite(geometry.destRect());
- }
- }
- return result;
-}
-
void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect,
BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
{
// the layer recursion into paintFillLayerExtended, or to compute the layer geometry here
// and pass it down.
- if (!shouldDrawBackgroundInSeparateBuffer && curLayer->blendMode() != BlendModeNormal)
+ if (!shouldDrawBackgroundInSeparateBuffer && curLayer->blendMode() != blink::WebBlendModeNormal)
shouldDrawBackgroundInSeparateBuffer = true;
// The clipOccludesNextLayers condition must be evaluated first to avoid short-circuiting.
- if (curLayer->clipOccludesNextLayers(curLayer == fillLayer) && curLayer->hasOpaqueImage(this) && curLayer->image()->canRender(this, style()->effectiveZoom()) && curLayer->hasRepeatXY() && curLayer->blendMode() == BlendModeNormal && !boxShadowShouldBeAppliedToBackground(bleedAvoidance))
+ if (curLayer->clipOccludesNextLayers(curLayer == fillLayer) && curLayer->hasOpaqueImage(this) && curLayer->image()->canRender(*this, style()->effectiveZoom()) && curLayer->hasRepeatXY() && curLayer->blendMode() == blink::WebBlendModeNormal && !boxShadowShouldBeAppliedToBackground(bleedAvoidance))
break;
curLayer = curLayer->next();
}
if (!parent())
return;
+ AllowRepaintScope scoper(frameView());
+
if ((style()->borderImage().image() && style()->borderImage().image()->data() == image) ||
(style()->maskBoxImage().image() && style()->maskBoxImage().image()->data() == image)) {
repaint();
return;
}
+ ShapeValue* shapeOutsideValue = style()->shapeOutside();
+ if (!frameView()->isInPerformLayout() && isFloating() && shapeOutsideValue && shapeOutsideValue->image() && shapeOutsideValue->image()->data() == image) {
+ ShapeOutsideInfo::ensureInfo(*this).markShapeAsDirty();
+ markShapeOutsideDependentsForLayout();
+ }
+
bool didFullRepaint = repaintLayerRectsForImage(image, style()->backgroundLayers(), true);
if (!didFullRepaint)
repaintLayerRectsForImage(image, style()->maskLayers(), false);
-
if (hasLayer() && layer()->hasCompositedMask() && layersUseImage(image, style()->maskLayers()))
layer()->contentChanged(MaskImageChanged);
}
RenderBox* layerRenderer = 0;
for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
- if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(this, style()->effectiveZoom())) {
- // Now that we know this image is being used, compute the renderer and the rect
- // if we haven't already
+ if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(*this, style()->effectiveZoom())) {
+ // Now that we know this image is being used, compute the renderer and the rect if we haven't already.
if (!layerRenderer) {
- bool drawingRootBackground = drawingBackground && (isRoot() || (isBody() && !document().documentElement()->renderer()->hasBackground()));
+ bool drawingRootBackground = drawingBackground && (isDocumentElement() || (isBody() && !document().documentElement()->renderer()->hasBackground()));
if (drawingRootBackground) {
layerRenderer = view();
}
BackgroundImageGeometry geometry;
- layerRenderer->calculateBackgroundImageGeometry(curLayer, rendererRect, geometry);
+ layerRenderer->calculateBackgroundImageGeometry(0, curLayer, rendererRect, geometry);
+ if (geometry.hasNonLocalGeometry()) {
+ // Rather than incur the costs of computing the paintContainer for renderers with fixed backgrounds
+ // in order to get the right destRect, just repaint the entire renderer.
+ layerRenderer->repaint();
+ return true;
+ }
+
layerRenderer->repaintRectangle(geometry.destRect());
if (geometry.destRect() == rendererRect)
return true;
return false;
}
+void RenderBox::repaintTreeAfterLayout()
+{
+ // FIXME: Currently only using this logic for RenderBox and its ilk. Ideally, RenderBlockFlows with
+ // inline children should track a dirty rect in local coordinates for dirty lines instead of repainting
+ // the world.
+ // FIXME: We should still be recursing through inline's children, as they can have boxes, but we don't
+ // appear to have tests for this?
+ // FIXME: SVG should probably also go through this unified repaint system.
+
+ ASSERT(RuntimeEnabledFeatures::repaintAfterLayoutEnabled());
+ ASSERT(!needsLayout());
+
+ if (!shouldCheckForInvalidationAfterLayout())
+ return;
+
+ const LayoutRect oldRepaintRect = previousRepaintRect();
+ const LayoutPoint oldPositionFromRepaintContainer = previousPositionFromRepaintContainer();
+ const RenderLayerModelObject* repaintContainer = containerForRepaint();
+ setPreviousRepaintRect(clippedOverflowRectForRepaint(repaintContainer));
+ setPreviousPositionFromRepaintContainer(positionFromRepaintContainer(repaintContainer));
+
+ // If we are set to do a full repaint that means the RenderView will be
+ // invalidated. We can then skip issuing of invalidations for the child
+ // renderers as they'll be covered by the RenderView.
+ if (view()->doingFullRepaint() && this != view()) {
+ LayoutStateMaintainer statePusher(*this, isTableRow() ? LayoutSize() : locationOffset());
+ RenderObject::repaintTreeAfterLayout();
+ return;
+ }
+
+ if ((onlyNeededPositionedMovementLayout() && compositingState() != PaintsIntoOwnBacking)
+ || (shouldDoFullRepaintIfSelfPaintingLayer()
+ && hasLayer()
+ && layer()->isSelfPaintingLayer())) {
+ setShouldDoFullRepaintAfterLayout(true);
+ }
+
+ const LayoutRect& newRepaintRect = previousRepaintRect();
+ const LayoutPoint& newPositionFromRepaintContainer = previousPositionFromRepaintContainer();
+ bool didFullRepaint = repaintAfterLayoutIfNeeded(containerForRepaint(),
+ shouldDoFullRepaintAfterLayout(), oldRepaintRect, oldPositionFromRepaintContainer, &newRepaintRect, &newPositionFromRepaintContainer);
+
+ if (!didFullRepaint)
+ repaintOverflowIfNeeded();
+
+ // Repaint any scrollbars if there is a scrollable area for this renderer.
+ if (enclosingLayer()) {
+ if (RenderLayerScrollableArea* area = enclosingLayer()->scrollableArea()) {
+ if (area->hasVerticalBarDamage())
+ repaintRectangle(area->verticalBarDamage());
+ if (area->hasHorizontalBarDamage())
+ repaintRectangle(area->horizontalBarDamage());
+ area->resetScrollbarDamage();
+ }
+ }
+
+ // FIXME: This concept of a tree walking state for fast lookups should be generalized away from
+ // just layout.
+ // FIXME: Table rows shouldn't be special-cased.
+ LayoutStateMaintainer statePusher(*this, isTableRow() ? LayoutSize() : locationOffset());
+ RenderObject::repaintTreeAfterLayout();
+}
+
bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumulatedOffset, ContentsClipBehavior contentsClipBehavior)
{
if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseSelfOutline || paintInfo.phase == PaintPhaseMask)
if (!isControlClip && !isOverflowClip)
return false;
- LayoutRect clipRect = isControlClip ? controlClipRect(accumulatedOffset) : overflowClipRect(accumulatedOffset, paintInfo.renderRegion);
+ LayoutRect clipRect = isControlClip ? controlClipRect(accumulatedOffset) : overflowClipRect(accumulatedOffset);
RoundedRect clipRoundedRect(0, 0, 0, 0);
bool hasBorderRadius = style()->hasBorderRadius();
if (hasBorderRadius)
if (contentsVisualOverflow.isEmpty())
return false;
- // FIXME: Get rid of this slop from here and elsewhere.
- // Instead, properly include the outline in visual overflow.
- if (RenderView* view = this->view())
- contentsVisualOverflow.inflate(view->maximalOutlineSize());
-
LayoutRect conservativeClipRect = clipRect;
if (hasBorderRadius)
conservativeClipRect.intersect(clipRoundedRect.radiusCenterRect());
paintInfo.phase = originalPhase;
}
-LayoutRect RenderBox::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy)
+LayoutRect RenderBox::overflowClipRect(const LayoutPoint& location, OverlayScrollbarSizeRelevancy relevancy)
{
// FIXME: When overflow-clip (CSS3) is implemented, we'll obtain the property
// here.
- LayoutRect clipRect = borderBoxRectInRegion(region);
+ LayoutRect clipRect = borderBoxRect();
clipRect.setLocation(location + clipRect.location() + LayoutSize(borderLeft(), borderTop()));
clipRect.setSize(clipRect.size() - LayoutSize(borderLeft() + borderRight(), borderTop() + borderBottom()));
return clipRect;
}
-LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region)
+LayoutRect RenderBox::clipRect(const LayoutPoint& location)
{
- LayoutRect borderBoxRect = borderBoxRectInRegion(region);
+ LayoutRect borderBoxRect = this->borderBoxRect();
LayoutRect clipRect = LayoutRect(borderBoxRect.location() + location, borderBoxRect.size());
- RenderView* renderView = view();
if (!style()->clipLeft().isAuto()) {
- LayoutUnit c = valueForLength(style()->clipLeft(), borderBoxRect.width(), renderView);
+ LayoutUnit c = valueForLength(style()->clipLeft(), borderBoxRect.width());
clipRect.move(c, 0);
clipRect.contract(c, 0);
}
- // We don't use the region-specific border box's width and height since clip offsets are (stupidly) specified
- // from the left and top edges. Therefore it's better to avoid constraining to smaller widths and heights.
-
if (!style()->clipRight().isAuto())
- clipRect.contract(width() - valueForLength(style()->clipRight(), width(), renderView), 0);
+ clipRect.contract(width() - valueForLength(style()->clipRight(), width()), 0);
if (!style()->clipTop().isAuto()) {
- LayoutUnit c = valueForLength(style()->clipTop(), borderBoxRect.height(), renderView);
+ LayoutUnit c = valueForLength(style()->clipTop(), borderBoxRect.height());
clipRect.move(0, c);
clipRect.contract(0, c);
}
if (!style()->clipBottom().isAuto())
- clipRect.contract(0, height() - valueForLength(style()->clipBottom(), height(), renderView));
+ clipRect.contract(0, height() - valueForLength(style()->clipBottom(), height()));
return clipRect;
}
-LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion* region) const
+LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlockFlow* cb) const
{
- RenderRegion* containingBlockRegion = 0;
LayoutUnit logicalTopPosition = logicalTop();
- if (region) {
- LayoutUnit offsetFromLogicalTopOfRegion = region ? region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage() : LayoutUnit();
- logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
- containingBlockRegion = cb->clampToStartAndEndRegions(region);
- }
-
- LayoutUnit result = cb->availableLogicalWidthForLine(logicalTopPosition, false, containingBlockRegion) - childMarginStart - childMarginEnd;
+ LayoutUnit result = cb->availableLogicalWidthForLine(logicalTopPosition, false) - childMarginStart - childMarginEnd;
// We need to see if margins on either the start side or the end side can contain the floats in question. If they can,
// then just using the line width is inaccurate. In the case where a float completely fits, we don't need to use the line
// doesn't fit, we can use the line offset, but we need to grow it by the margin to reflect the fact that the margin was
// "consumed" by the float. Negative margins aren't consumed by the float, and so we ignore them.
if (childMarginStart > 0) {
- LayoutUnit startContentSide = cb->startOffsetForContent(containingBlockRegion);
+ LayoutUnit startContentSide = cb->startOffsetForContent();
LayoutUnit startContentSideWithMargin = startContentSide + childMarginStart;
- LayoutUnit startOffset = cb->startOffsetForLine(logicalTopPosition, false, containingBlockRegion);
+ LayoutUnit startOffset = cb->startOffsetForLine(logicalTopPosition, false);
if (startOffset > startContentSideWithMargin)
result += childMarginStart;
else
}
if (childMarginEnd > 0) {
- LayoutUnit endContentSide = cb->endOffsetForContent(containingBlockRegion);
+ LayoutUnit endContentSide = cb->endOffsetForContent();
LayoutUnit endContentSideWithMargin = endContentSide + childMarginEnd;
- LayoutUnit endOffset = cb->endOffsetForLine(logicalTopPosition, false, containingBlockRegion);
+ LayoutUnit endOffset = cb->endOffsetForLine(logicalTopPosition, false);
if (endOffset > endContentSideWithMargin)
result += childMarginEnd;
else
return cb->availableLogicalHeight(heightType);
}
-LayoutUnit RenderBox::containingBlockLogicalWidthForContentInRegion(RenderRegion* region) const
+LayoutUnit RenderBox::containingBlockAvailableLineWidth() const
{
- if (!region)
- return containingBlockLogicalWidthForContent();
-
RenderBlock* cb = containingBlock();
- RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region);
- // FIXME: It's unclear if a region's content should use the containing block's override logical width.
- // If it should, the following line should call containingBlockLogicalWidthForContent.
- LayoutUnit result = cb->availableLogicalWidth();
- RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(containingBlockRegion);
- if (!boxInfo)
- return result;
- return max<LayoutUnit>(0, result - (cb->logicalWidth() - boxInfo->logicalWidth()));
-}
-
-LayoutUnit RenderBox::containingBlockAvailableLineWidthInRegion(RenderRegion* region) const
-{
- RenderBlock* cb = containingBlock();
- RenderRegion* containingBlockRegion = 0;
- LayoutUnit logicalTopPosition = logicalTop();
- if (region) {
- LayoutUnit offsetFromLogicalTopOfRegion = region ? region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage() : LayoutUnit();
- logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
- containingBlockRegion = cb->clampToStartAndEndRegions(region);
- }
- return cb->availableLogicalWidthForLine(logicalTopPosition, false, containingBlockRegion, availableLogicalHeight(IncludeMarginBorderPadding));
+ if (cb->isRenderBlockFlow())
+ return toRenderBlockFlow(cb)->availableLogicalWidthForLine(logicalTop(), false, availableLogicalHeight(IncludeMarginBorderPadding));
+ return 0;
}
LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const
return;
if (RenderView* v = view()) {
- if (v->layoutStateEnabled() && !repaintContainer) {
+ if (v->canUseLayoutStateForContainer(repaintContainer)) {
LayoutState* layoutState = v->layoutState();
- LayoutSize offset = layoutState->m_paintOffset + locationOffset();
+ LayoutSize offset = layoutState->paintOffset() + locationOffset();
if (style()->hasInFlowPosition() && layer())
offset += layer()->offsetForInFlowPosition();
transformState.move(offset);
LayoutSize RenderBox::offsetFromContainer(RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
{
- // A region "has" boxes inside it without being their container.
- // FIXME: change container() / containingBlock() to count for boxes being positioned relative to the region, not the
- // FlowThread. This requires a separate patch as a simple test with such a change in container() causes 129 out of
- // 337 regions tests to fail.
- ASSERT(o == container() || o->isRenderRegion());
+ ASSERT(o == container());
LayoutSize offset;
if (isInFlowPositioned())
offset += toSize(columnRect.location());
LayoutPoint columnPoint = block->flipForWritingModeIncludingColumns(point + offset);
offset = toLayoutSize(block->flipForWritingModeIncludingColumns(toLayoutPoint(offset)));
- o->adjustForColumns(offset, columnPoint);
+ offset += o->columnOffset(columnPoint);
offset = block->flipForWritingMode(offset);
if (offsetDependsOnPoint)
*offsetDependsOnPoint = true;
- } else
+ } else {
offset += topLeftLocationOffset();
+ if (o->isRenderFlowThread()) {
+ // So far the point has been in flow thread coordinates (i.e. as if everything in
+ // the fragmentation context lived in one tall single column). Convert it to a
+ // visual point now.
+ LayoutPoint pointInContainer = point + offset;
+ offset += o->columnOffset(pointInContainer);
+ if (offsetDependsOnPoint)
+ *offsetDependsOnPoint = true;
+ }
+ }
}
if (o->hasOverflowClip())
offset -= toRenderBox(o)->scrolledContentOffset();
if (style()->position() == AbsolutePosition && o->isInFlowPositioned() && o->isRenderInline())
- offset += toRenderInline(o)->offsetForInFlowPositionedInline(this);
-
- if (offsetDependsOnPoint)
- *offsetDependsOnPoint |= o->isRenderFlowThread();
+ offset += toRenderInline(o)->offsetForInFlowPositionedInline(*this);
return offset;
}
InlineBox* RenderBox::createInlineBox()
{
- return new InlineBox(this);
+ return new InlineBox(*this);
}
void RenderBox::dirtyLineBoxes(bool fullLayout)
{
- if (m_inlineBoxWrapper) {
+ if (inlineBoxWrapper()) {
if (fullLayout) {
- m_inlineBoxWrapper->destroy();
- m_inlineBoxWrapper = 0;
- } else
- m_inlineBoxWrapper->dirtyLineBoxes();
+ inlineBoxWrapper()->destroy();
+ ASSERT(m_rareData);
+ m_rareData->m_inlineBoxWrapper = 0;
+ } else {
+ inlineBoxWrapper()->dirtyLineBoxes();
+ }
}
}
// 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.
- RootInlineBox* root = box->root();
- root->block()->setStaticInlinePositionForChild(this, root->lineTopWithLeading(), LayoutUnit::fromFloatRound(box->logicalLeft()));
+ RootInlineBox& root = box->root();
+ root.block().setStaticInlinePositionForChild(this, root.lineTopWithLeading(), LayoutUnit::fromFloatRound(box->logicalLeft()));
if (style()->hasStaticInlinePosition(box->isHorizontal()))
setChildNeedsLayout(MarkOnlyThis); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
} else {
}
// Nuke the box.
- box->remove();
+ box->remove(DontMarkLineBoxes);
box->destroy();
} else if (isReplaced()) {
setLocation(roundedLayoutPoint(box->topLeft()));
void RenderBox::deleteLineBoxWrapper()
{
- if (m_inlineBoxWrapper) {
+ if (inlineBoxWrapper()) {
if (!documentBeingDestroyed())
- m_inlineBoxWrapper->remove();
- m_inlineBoxWrapper->destroy();
- m_inlineBoxWrapper = 0;
+ inlineBoxWrapper()->remove();
+ inlineBoxWrapper()->destroy();
+ ASSERT(m_rareData);
+ m_rareData->m_inlineBoxWrapper = 0;
}
}
LayoutRect r = visualOverflowRect();
RenderView* v = view();
- if (v) {
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && v) {
// FIXME: layoutDelta needs to be applied in parts before/after transforms and
// repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
r.move(v->layoutDelta());
}
- if (style()) {
- // We have to use maximalOutlineSize() because a child might have an outline
- // that projects outside of our overflowRect.
- if (v) {
- ASSERT(style()->outlineSize() <= v->maximalOutlineSize());
- r.inflate(v->maximalOutlineSize());
- }
- }
-
computeRectForRepaint(repaintContainer, r);
return r;
}
RenderStyle* styleToUse = style();
if (RenderView* v = view()) {
// LayoutState is only valid for root-relative, non-fixed position repainting
- if (v->layoutStateEnabled() && !repaintContainer && styleToUse->position() != FixedPosition) {
+ if (v->canUseLayoutStateForContainer(repaintContainer) && styleToUse->position() != FixedPosition) {
LayoutState* layoutState = v->layoutState();
if (layer() && layer()->transform())
rect.move(layer()->offsetForInFlowPosition());
rect.moveBy(location());
- rect.move(layoutState->m_paintOffset);
- if (layoutState->m_clipped)
- rect.intersect(layoutState->m_clipRect);
+ rect.move(layoutState->paintOffset());
+ if (layoutState->isClipped())
+ rect.intersect(layoutState->clipRect());
return;
}
}
fixed = true;
if (position == AbsolutePosition && o->isInFlowPositioned() && o->isRenderInline()) {
- topLeft += toRenderInline(o)->offsetForInFlowPositionedInline(this);
+ topLeft += toRenderInline(o)->offsetForInFlowPositionedInline(*this);
} else if (styleToUse->hasInFlowPosition() && 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
void RenderBox::updateLogicalWidth()
{
LogicalExtentComputedValues computedValues;
- computeLogicalWidthInRegion(computedValues);
+ computeLogicalWidth(computedValues);
setLogicalWidth(computedValues.m_extent);
setLogicalLeft(computedValues.m_position);
ASSERT(renderer);
Node* parentNode = renderer->generatingNode();
ASSERT(parentNode);
- ASSERT(parentNode->hasTagName(olTag) || parentNode->hasTagName(ulTag));
+ ASSERT(isHTMLOListElement(parentNode) || isHTMLUListElement(parentNode));
ASSERT(renderer->style()->textAutosizingMultiplier() != 1);
#endif
float maxWidth = 0;
if (!itemChild->isListMarker())
continue;
RenderBox* itemMarker = toRenderBox(itemChild);
- // FIXME: canDetermineWidthWithoutLayout expects us to use fixedOffsetWidth, which this code
- // does not do! This check is likely wrong.
- if (!itemMarker->canDetermineWidthWithoutLayout() && itemMarker->needsLayout()) {
- // Make sure to compute the autosized width.
+ // Make sure to compute the autosized width.
+ if (itemMarker->needsLayout())
itemMarker->layout();
- }
maxWidth = max<float>(maxWidth, toRenderListMarker(itemMarker)->logicalWidth().toFloat());
break;
}
return maxWidth;
}
-void RenderBox::computeLogicalWidthInRegion(LogicalExtentComputedValues& computedValues, RenderRegion* region) const
+void RenderBox::computeLogicalWidth(LogicalExtentComputedValues& computedValues) const
{
computedValues.m_extent = logicalWidth();
computedValues.m_position = logicalLeft();
if (isOutOfFlowPositioned()) {
// FIXME: This calculation is not patched for block-flow yet.
// https://bugs.webkit.org/show_bug.cgi?id=46500
- computePositionedLogicalWidth(computedValues, region);
+ computePositionedLogicalWidth(computedValues);
return;
}
Length logicalWidthLength = treatAsReplaced ? Length(computeReplacedLogicalWidth(), Fixed) : styleToUse->logicalWidth();
RenderBlock* cb = containingBlock();
- LayoutUnit containerLogicalWidth = max<LayoutUnit>(0, containingBlockLogicalWidthForContentInRegion(region));
+ LayoutUnit containerLogicalWidth = max<LayoutUnit>(0, containingBlockLogicalWidthForContent());
bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
if (isInline() && !isInlineBlockOrInlineTable()) {
// just calculate margins
- RenderView* renderView = view();
- computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView);
- computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView);
+ computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth);
+ computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth);
if (treatAsReplaced)
- computedValues.m_extent = max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth());
+ computedValues.m_extent = max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth());
return;
}
LayoutUnit containerWidthInInlineDirection = containerLogicalWidth;
if (hasPerpendicularContainingBlock)
containerWidthInInlineDirection = perpendicularContainingBlockLogicalHeight();
- LayoutUnit preferredWidth = computeLogicalWidthInRegionUsing(MainOrPreferredSize, styleToUse->logicalWidth(), containerWidthInInlineDirection, cb, region);
- computedValues.m_extent = constrainLogicalWidthInRegionByMinMax(preferredWidth, containerWidthInInlineDirection, cb, region);
+ LayoutUnit preferredWidth = computeLogicalWidthUsing(MainOrPreferredSize, styleToUse->logicalWidth(), containerWidthInInlineDirection, cb);
+ computedValues.m_extent = constrainLogicalWidthByMinMax(preferredWidth, containerWidthInInlineDirection, cb);
}
// Margin calculations.
if (hasPerpendicularContainingBlock || isFloating() || isInline()) {
- RenderView* renderView = view();
- computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView);
- computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView);
+ computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth);
+ computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth);
} else {
- LayoutUnit containerLogicalWidthForAutoMargins = containerLogicalWidth;
- if (avoidsFloats() && cb->containsFloats())
- containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(region);
bool hasInvertedDirection = cb->style()->isLeftToRightDirection() != style()->isLeftToRightDirection();
- computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, computedValues.m_extent,
+ computeInlineDirectionMargins(cb, containerLogicalWidth, computedValues.m_extent,
hasInvertedDirection ? computedValues.m_margins.m_end : computedValues.m_margins.m_start,
hasInvertedDirection ? computedValues.m_margins.m_start : computedValues.m_margins.m_end);
}
if (styleToUse->textAutosizingMultiplier() != 1 && styleToUse->marginStart().type() == Fixed) {
Node* parentNode = generatingNode();
- if (parentNode && (parentNode->hasTagName(olTag) || parentNode->hasTagName(ulTag))) {
+ if (parentNode && (isHTMLOListElement(*parentNode) || isHTMLUListElement(*parentNode))) {
// Make sure the markers in a list are properly positioned (i.e. not chopped off) when autosized.
const float adjustedMargin = (1 - 1.0 / styleToUse->textAutosizingMultiplier()) * getMaxWidthListMarker(this);
bool hasInvertedDirection = cb->style()->isLeftToRightDirection() != style()->isLeftToRightDirection();
LayoutUnit RenderBox::fillAvailableMeasure(LayoutUnit availableLogicalWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const
{
- RenderView* renderView = view();
- marginStart = minimumValueForLength(style()->marginStart(), availableLogicalWidth, renderView);
- marginEnd = minimumValueForLength(style()->marginEnd(), availableLogicalWidth, renderView);
+ marginStart = minimumValueForLength(style()->marginStart(), availableLogicalWidth);
+ marginEnd = minimumValueForLength(style()->marginEnd(), availableLogicalWidth);
return availableLogicalWidth - marginStart - marginEnd;
}
return 0;
}
-LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(SizeType widthType, Length logicalWidth, LayoutUnit availableLogicalWidth,
- const RenderBlock* cb, RenderRegion* region) const
+LayoutUnit RenderBox::computeLogicalWidthUsing(SizeType widthType, Length logicalWidth, LayoutUnit availableLogicalWidth, const RenderBlock* cb) const
{
if (!logicalWidth.isIntrinsicOrAuto()) {
// FIXME: If the containing block flow is perpendicular to our direction we need to use the available logical height instead.
- return adjustBorderBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, availableLogicalWidth, view()));
+ return adjustBorderBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, availableLogicalWidth));
}
if (logicalWidth.isIntrinsic())
LayoutUnit logicalWidthResult = fillAvailableMeasure(availableLogicalWidth, marginStart, marginEnd);
if (shrinkToAvoidFloats() && cb->containsFloats())
- logicalWidthResult = min(logicalWidthResult, shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, region));
+ logicalWidthResult = min(logicalWidthResult, shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, toRenderBlockFlow(cb)));
- if (widthType == MainOrPreferredSize && sizesLogicalWidthToFitContent(widthType))
+ if (widthType == MainOrPreferredSize && sizesLogicalWidthToFitContent(logicalWidth))
return max(minPreferredLogicalWidth(), min(maxPreferredLogicalWidth(), logicalWidthResult));
return logicalWidthResult;
}
ASSERT(parent->style()->isColumnFlexDirection());
if (flexitem->style()->marginStart().isAuto() || flexitem->style()->marginEnd().isAuto())
return false;
- return flexitem->style()->alignSelf() == AlignStretch || (flexitem->style()->alignSelf() == AlignAuto && parent->style()->alignItems() == AlignStretch);
+ return flexitem->style()->alignSelf() == ItemPositionStretch || (flexitem->style()->alignSelf() == ItemPositionAuto && parent->style()->alignItems() == ItemPositionStretch);
}
static bool isStretchingColumnFlexItem(const RenderObject* flexitem)
return false;
}
-bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const
+bool RenderBox::sizesLogicalWidthToFitContent(const Length& logicalWidth) const
{
// Marquees in WinIE are like a mixture of blocks and inline-blocks. They size as though they're blocks,
// but they allow text to sit on the same line as the marquee.
if (isFloating() || (isInlineBlockOrInlineTable() && !isMarquee()))
return true;
- // This code may look a bit strange. Basically width:intrinsic should clamp the size when testing both
- // min-width and width. max-width is only clamped if it is also intrinsic.
- Length logicalWidth = (widthType == MaxSize) ? style()->logicalMaxWidth() : style()->logicalWidth();
if (logicalWidth.type() == Intrinsic)
return true;
// stretching column flexbox.
// FIXME: Think about block-flow here.
// https://bugs.webkit.org/show_bug.cgi?id=46473
- if (logicalWidth.type() == Auto && !isStretchingColumnFlexItem(this) && autoWidthShouldFitContent())
+ if (logicalWidth.isAuto() && !isStretchingColumnFlexItem(this) && autoWidthShouldFitContent())
return true;
if (isHorizontalWritingMode() != containingBlock()->isHorizontalWritingMode())
bool RenderBox::autoWidthShouldFitContent() const
{
- if (node() && (node()->hasTagName(inputTag) || node()->hasTagName(selectTag) || node()->hasTagName(buttonTag)
- || isHTMLTextAreaElement(node()) || node()->hasTagName(legendTag)))
- return true;
-
- return false;
+ return node() && (isHTMLInputElement(*node()) || isHTMLSelectElement(*node()) || isHTMLButtonElement(*node())
+ || isHTMLTextAreaElement(*node()) || (isHTMLLegendElement(*node()) && !style()->hasOutOfFlowPosition()));
}
void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const
const RenderStyle* containingBlockStyle = containingBlock->style();
Length marginStartLength = style()->marginStartUsing(containingBlockStyle);
Length marginEndLength = style()->marginEndUsing(containingBlockStyle);
- RenderView* renderView = view();
if (isFloating() || isInline()) {
// Inline blocks/tables and floats don't have their margins increased.
- marginStart = minimumValueForLength(marginStartLength, containerWidth, renderView);
- marginEnd = minimumValueForLength(marginEndLength, containerWidth, renderView);
+ marginStart = minimumValueForLength(marginStartLength, containerWidth);
+ marginEnd = minimumValueForLength(marginEndLength, containerWidth);
return;
}
marginEndLength.setValue(0);
}
+ LayoutUnit availableWidth = containerWidth;
+ if (avoidsFloats() && containingBlock->containsFloats())
+ availableWidth = containingBlockAvailableLineWidth();
+
// Case One: The object is being centered in the containing block's available logical width.
- if ((marginStartLength.isAuto() && marginEndLength.isAuto() && childWidth < containerWidth)
+ if ((marginStartLength.isAuto() && marginEndLength.isAuto() && childWidth < availableWidth)
|| (!marginStartLength.isAuto() && !marginEndLength.isAuto() && containingBlock->style()->textAlign() == WEBKIT_CENTER)) {
// Other browsers center the margin box for align=center elements so we match them here.
- LayoutUnit marginStartWidth = minimumValueForLength(marginStartLength, containerWidth, renderView);
- LayoutUnit marginEndWidth = minimumValueForLength(marginEndLength, containerWidth, renderView);
- LayoutUnit centeredMarginBoxStart = max<LayoutUnit>(0, (containerWidth - childWidth - marginStartWidth - marginEndWidth) / 2);
+ LayoutUnit marginStartWidth = minimumValueForLength(marginStartLength, containerWidth);
+ LayoutUnit marginEndWidth = minimumValueForLength(marginEndLength, containerWidth);
+ LayoutUnit centeredMarginBoxStart = max<LayoutUnit>(0, (availableWidth - childWidth - marginStartWidth - marginEndWidth) / 2);
marginStart = centeredMarginBoxStart + marginStartWidth;
- marginEnd = containerWidth - childWidth - marginStart + marginEndWidth;
+ marginEnd = availableWidth - childWidth - marginStart + marginEndWidth;
return;
}
// Case Two: The object is being pushed to the start of the containing block's available logical width.
- if (marginEndLength.isAuto() && childWidth < containerWidth) {
- marginStart = valueForLength(marginStartLength, containerWidth, renderView);
- marginEnd = containerWidth - childWidth - marginStart;
+ if (marginEndLength.isAuto() && childWidth < availableWidth) {
+ marginStart = valueForLength(marginStartLength, containerWidth);
+ marginEnd = availableWidth - childWidth - marginStart;
return;
}
// Case Three: The object is being pushed to the end of the containing block's available logical width.
bool pushToEndFromTextAlign = !marginEndLength.isAuto() && ((!containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_LEFT)
|| (containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_RIGHT));
- if ((marginStartLength.isAuto() && childWidth < containerWidth) || pushToEndFromTextAlign) {
- marginEnd = valueForLength(marginEndLength, containerWidth, renderView);
- marginStart = containerWidth - childWidth - marginEnd;
+ if ((marginStartLength.isAuto() && childWidth < availableWidth) || pushToEndFromTextAlign) {
+ marginEnd = valueForLength(marginEndLength, containerWidth);
+ marginStart = availableWidth - childWidth - marginEnd;
return;
}
// Case Four: Either no auto margins, or our width is >= the container width (css2.1, 10.3.3). In that case
// auto margins will just turn into 0.
- marginStart = minimumValueForLength(marginStartLength, containerWidth, renderView);
- marginEnd = minimumValueForLength(marginEndLength, containerWidth, renderView);
-}
-
-RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, RenderBoxRegionInfoFlags cacheFlag) const
-{
- // Make sure nobody is trying to call this with a null region.
- if (!region)
- return 0;
-
- // If we have computed our width in this region already, it will be cached, and we can
- // just return it.
- RenderBoxRegionInfo* boxInfo = region->renderBoxRegionInfo(this);
- if (boxInfo && cacheFlag == CacheRenderBoxRegionInfo)
- return boxInfo;
-
- // No cached value was found, so we have to compute our insets in this region.
- // FIXME: For now we limit this computation to normal RenderBlocks. Future patches will expand
- // support to cover all boxes.
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (isRenderFlowThread() || !flowThread || !canHaveBoxInfoInRegion() || flowThread->style()->writingMode() != style()->writingMode())
- return 0;
-
- LogicalExtentComputedValues computedValues;
- computeLogicalWidthInRegion(computedValues, region);
-
- // Now determine the insets based off where this object is supposed to be positioned.
- RenderBlock* cb = containingBlock();
- RenderRegion* clampedContainingBlockRegion = cb->clampToStartAndEndRegions(region);
- RenderBoxRegionInfo* containingBlockInfo = cb->renderBoxRegionInfo(clampedContainingBlockRegion);
- LayoutUnit containingBlockLogicalWidth = cb->logicalWidth();
- LayoutUnit containingBlockLogicalWidthInRegion = containingBlockInfo ? containingBlockInfo->logicalWidth() : containingBlockLogicalWidth;
-
- LayoutUnit marginStartInRegion = computedValues.m_margins.m_start;
- LayoutUnit startMarginDelta = marginStartInRegion - marginStart();
- LayoutUnit logicalWidthInRegion = computedValues.m_extent;
- LayoutUnit logicalLeftInRegion = computedValues.m_position;
- LayoutUnit widthDelta = logicalWidthInRegion - logicalWidth();
- LayoutUnit logicalLeftDelta = isOutOfFlowPositioned() ? logicalLeftInRegion - logicalLeft() : startMarginDelta;
- LayoutUnit logicalRightInRegion = containingBlockLogicalWidthInRegion - (logicalLeftInRegion + logicalWidthInRegion);
- LayoutUnit oldLogicalRight = containingBlockLogicalWidth - (logicalLeft() + logicalWidth());
- LayoutUnit logicalRightDelta = isOutOfFlowPositioned() ? logicalRightInRegion - oldLogicalRight : startMarginDelta;
-
- LayoutUnit logicalLeftOffset = 0;
-
- if (!isOutOfFlowPositioned() && avoidsFloats() && cb->containsFloats()) {
- LayoutUnit startPositionDelta = cb->computeStartPositionDeltaForChildAvoidingFloats(this, marginStartInRegion, region);
- if (cb->style()->isLeftToRightDirection())
- logicalLeftDelta += startPositionDelta;
- else
- logicalRightDelta += startPositionDelta;
- }
-
- if (cb->style()->isLeftToRightDirection())
- logicalLeftOffset += logicalLeftDelta;
- else
- logicalLeftOffset -= (widthDelta + logicalRightDelta);
-
- LayoutUnit logicalRightOffset = logicalWidth() - (logicalLeftOffset + logicalWidthInRegion);
- bool isShifted = (containingBlockInfo && containingBlockInfo->isShifted())
- || (style()->isLeftToRightDirection() && logicalLeftOffset)
- || (!style()->isLeftToRightDirection() && logicalRightOffset);
-
- // FIXME: Although it's unlikely, these boxes can go outside our bounds, and so we will need to incorporate them into overflow.
- if (cacheFlag == CacheRenderBoxRegionInfo)
- return region->setRenderBoxRegionInfo(this, logicalLeftOffset, logicalWidthInRegion, isShifted);
- return new RenderBoxRegionInfo(logicalLeftOffset, logicalWidthInRegion, isShifted);
+ marginStart = minimumValueForLength(marginStartLength, containerWidth);
+ marginEnd = minimumValueForLength(marginEndLength, containerWidth);
}
static bool shouldFlipBeforeAfterMargins(const RenderStyle* containingBlockStyle, const RenderStyle* childStyle)
// Block children of horizontal flexible boxes fill the height of the box.
// FIXME: Account for block-flow in flexible boxes.
// https://bugs.webkit.org/show_bug.cgi?id=46418
- if (h.isAuto() && parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
- && parent()->isStretchingChildren()) {
+ if (h.isAuto() && inHorizontalBox && toRenderDeprecatedFlexibleBox(parent())->isStretchingChildren()) {
h = Length(parentBox()->contentLogicalHeight() - marginBefore() - marginAfter() - borderAndPaddingLogicalHeight(), Fixed);
checkMinMaxHeight = false;
}
if (hasPerpendicularContainingBlock) {
bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb->style(), style());
computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), heightResult,
- shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
- shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
+ shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
+ shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
}
}
// height since we don't set a height in RenderView when we're printing. So without this quirk, the
// height has nothing to be a percentage of, and it ends up being 0. That is bad.
bool paginatedContentNeedsBaseHeight = document().printing() && h.isPercent()
- && (isRoot() || (isBody() && document().documentElement()->renderer()->style()->logicalHeight().isPercent())) && !isInline();
+ && (isDocumentElement() || (isBody() && document().documentElement()->renderer()->style()->logicalHeight().isPercent())) && !isInline();
if (stretchesToViewport() || paginatedContentNeedsBaseHeight) {
LayoutUnit margins = collapsedMarginBefore() + collapsedMarginAfter();
LayoutUnit visibleHeight = viewLogicalHeightForPercentages();
- if (isRoot())
+ if (isDocumentElement())
computedValues.m_extent = max(computedValues.m_extent, visibleHeight - margins);
else {
LayoutUnit marginsBordersPadding = margins + parentBox()->marginBefore() + parentBox()->marginAfter() + parentBox()->borderAndPaddingLogicalHeight();
return height.value();
if (height.isPercent())
return computePercentageLogicalHeight(height);
- if (height.isViewportPercentage())
- return valueForLength(height, 0, view());
return -1;
}
bool RenderBox::skipContainingBlockForPercentHeightCalculation(const RenderBox* containingBlock) const
{
+ // Flow threads for multicol or paged overflow should be skipped. They are invisible to the DOM,
+ // and percent heights of children should be resolved against the multicol or paged container.
+ if (containingBlock->isRenderFlowThread())
+ return true;
+
// For quirks mode and anonymous blocks, we skip auto-height containingBlocks when computing percentages.
// For standards mode, we treat the percentage as auto if it has an auto-height containing block.
if (!document().inQuirksMode() && !containingBlock->isAnonymousBlock())
const RenderBox* containingBlockChild = this;
LayoutUnit rootMarginBorderPaddingHeight = 0;
while (!cb->isRenderView() && skipContainingBlockForPercentHeightCalculation(cb)) {
- if (cb->isBody() || cb->isRoot())
+ if (cb->isBody() || cb->isDocumentElement())
rootMarginBorderPaddingHeight += cb->marginBefore() + cb->marginAfter() + cb->borderAndPaddingLogicalHeight();
skippedAutoHeightContainingBlock = true;
containingBlockChild = cb;
cb = cb->containingBlock();
- cb->addPercentHeightDescendant(const_cast<RenderBox*>(this));
}
+ cb->addPercentHeightDescendant(const_cast<RenderBox*>(this));
RenderStyle* cbstyle = cb->style();
LayoutUnit contentBoxHeight = cb->constrainContentBoxLogicalHeightByMinMax(contentBoxHeightWithScrollbar - cb->scrollbarLogicalHeight(), -1);
availableHeight = max<LayoutUnit>(0, contentBoxHeight);
}
- } else if (cbstyle->logicalHeight().isViewportPercentage()) {
- LayoutUnit heightWithScrollbar = valueForLength(cbstyle->logicalHeight(), 0, view());
- if (heightWithScrollbar != -1) {
- LayoutUnit contentBoxHeightWithScrollbar = cb->adjustContentBoxLogicalHeightForBoxSizing(heightWithScrollbar);
- // We need to adjust for min/max height because this method does not
- // handle the min/max of the current block, its caller does. So the
- // return value from the recursive call will not have been adjusted
- // yet.
- LayoutUnit contentBoxHeight = cb->constrainContentBoxLogicalHeightByMinMax(contentBoxHeightWithScrollbar - cb->scrollbarLogicalHeight(), -1);
- availableHeight = max<LayoutUnit>(0, contentBoxHeight);
- }
} else if (isOutOfFlowPositionedWithSpecifiedHeight) {
// Don't allow this to affect the block' height() member variable, since this
// can get called while the block is still laying out its kids.
LayoutUnit availableLogicalWidth = 0;
return computeIntrinsicLogicalWidthUsing(logicalWidth, availableLogicalWidth, borderAndPaddingLogicalWidth()) - borderAndPaddingLogicalWidth();
}
- case ViewportPercentageWidth:
- case ViewportPercentageHeight:
- case ViewportPercentageMin:
- case ViewportPercentageMax:
- return adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, 0, view()));
case FitContent:
case FillAvailable:
case Percent:
return computeIntrinsicLogicalWidthUsing(logicalWidth, cw, borderAndPaddingLogicalWidth()) - borderAndPaddingLogicalWidth();
if (cw > 0 || (!cw && (containerLogicalWidth.isFixed() || containerLogicalWidth.isPercent())))
return adjustContentBoxLogicalWidthForBoxSizing(minimumValueForLength(logicalWidth, cw));
+ return 0;
}
- // fall through
case Intrinsic:
case MinIntrinsic:
case Auto:
- case Relative:
- case ExtendToZoom:
case Undefined:
return intrinsicLogicalWidth();
+ case ExtendToZoom:
+ case DeviceWidth:
+ case DeviceHeight:
+ break;
}
ASSERT_NOT_REACHED();
case Calculated:
{
RenderObject* cb = isOutOfFlowPositioned() ? container() : containingBlock();
- while (cb->isAnonymous()) {
+ while (cb->isAnonymous())
cb = cb->containingBlock();
+ if (cb->isRenderBlock())
toRenderBlock(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this));
- }
// FIXME: This calculation is not patched for block-flow yet.
// https://bugs.webkit.org/show_bug.cgi?id=46500
}
return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeight, availableHeight));
}
- case ViewportPercentageWidth:
- case ViewportPercentageHeight:
- case ViewportPercentageMin:
- case ViewportPercentageMax:
- return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeight, 0, view()));
case MinContent:
case MaxContent:
case FitContent:
// Margins are calculated with respect to the logical width of
// the containing block (8.3)
LayoutUnit cw = containingBlockLogicalWidthForContent();
- RenderView* renderView = view();
RenderStyle* containingBlockStyle = containingBlock->style();
- marginBefore = minimumValueForLength(style()->marginBeforeUsing(containingBlockStyle), cw, renderView);
- marginAfter = minimumValueForLength(style()->marginAfterUsing(containingBlockStyle), cw, renderView);
+ marginBefore = minimumValueForLength(style()->marginBeforeUsing(containingBlockStyle), cw);
+ marginAfter = minimumValueForLength(style()->marginAfterUsing(containingBlockStyle), cw);
}
void RenderBox::computeAndSetBlockDirectionMargins(const RenderBlock* containingBlock)
containingBlock->setMarginAfterForChild(this, marginAfter);
}
-LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* region, bool checkForPerpendicularWritingMode) const
+LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode) const
{
if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
return containingBlockLogicalHeightForPositioned(containingBlock, false);
// Use viewport as container for top-level fixed-position elements.
if (style()->position() == FixedPosition && containingBlock->isRenderView()) {
- const RenderView* view = static_cast<const RenderView*>(containingBlock);
+ const RenderView* view = toRenderView(containingBlock);
if (FrameView* frameView = view->frameView()) {
LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
return containingBlock->isHorizontalWritingMode() ? viewportRect.width() : viewportRect.height();
}
}
- if (containingBlock->isBox()) {
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (!flowThread)
- return toRenderBox(containingBlock)->clientLogicalWidth();
-
- const RenderBlock* cb = toRenderBlock(containingBlock);
- RenderBoxRegionInfo* boxInfo = 0;
- if (!region) {
- if (containingBlock->isRenderFlowThread() && !checkForPerpendicularWritingMode)
- return toRenderFlowThread(containingBlock)->contentLogicalWidthOfFirstRegion();
- if (isWritingModeRoot()) {
- LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage();
- RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
- if (cbRegion) {
- cbRegion = cb->clampToStartAndEndRegions(cbRegion);
- boxInfo = cb->renderBoxRegionInfo(cbRegion);
- }
- }
- } else if (region && flowThread->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode()) {
- RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region);
- boxInfo = cb->renderBoxRegionInfo(containingBlockRegion);
- }
- return (boxInfo) ? max<LayoutUnit>(0, cb->clientLogicalWidth() - (cb->logicalWidth() - boxInfo->logicalWidth())) : cb->clientLogicalWidth();
- }
+ if (containingBlock->isBox())
+ return toRenderBox(containingBlock)->clientLogicalWidth();
ASSERT(containingBlock->isRenderInline() && containingBlock->isInFlowPositioned());
LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode) const
{
if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
- return containingBlockLogicalWidthForPositioned(containingBlock, 0, false);
+ return containingBlockLogicalWidthForPositioned(containingBlock, false);
// Use viewport as container for top-level fixed-position elements.
if (style()->position() == FixedPosition && containingBlock->isRenderView()) {
- const RenderView* view = static_cast<const RenderView*>(containingBlock);
+ const RenderView* view = toRenderView(containingBlock);
if (FrameView* frameView = view->frameView()) {
LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
return containingBlock->isHorizontalWritingMode() ? viewportRect.height() : viewportRect.width();
}
if (containingBlock->isBox()) {
- const RenderBlock* cb = toRenderBlock(containingBlock);
- LayoutUnit result = cb->clientLogicalHeight();
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (flowThread && containingBlock->isRenderFlowThread() && flowThread->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode())
- return toRenderFlowThread(containingBlock)->contentLogicalHeightOfFirstRegion();
- return result;
+ const RenderBlock* cb = containingBlock->isRenderBlock() ?
+ toRenderBlock(containingBlock) : containingBlock->containingBlock();
+ return cb->clientLogicalHeight();
}
ASSERT(containingBlock->isRenderInline() && containingBlock->isInFlowPositioned());
return heightResult;
}
-static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRight, const RenderBox* child, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth, RenderRegion* region)
+static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRight, const RenderBox* child, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth)
{
if (!logicalLeft.isAuto() || !logicalRight.isAuto())
return;
staticPosition += toRenderBox(curr)->logicalLeft();
if (toRenderBox(curr)->isRelPositioned())
staticPosition += toRenderBox(curr)->relativePositionOffset().width();
- if (region && curr->isRenderBlock()) {
- const RenderBlock* cb = toRenderBlock(curr);
- region = cb->clampToStartAndEndRegions(region);
- RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region);
- if (boxInfo)
- staticPosition += boxInfo->logicalLeft();
- }
} else if (curr->isInline()) {
if (curr->isRelPositioned()) {
if (!curr->style()->logicalLeft().isAuto())
}
if (curr == enclosingBox)
staticPosition -= enclosingBox->logicalWidth();
- if (region && curr->isRenderBlock()) {
- const RenderBlock* cb = toRenderBlock(curr);
- region = cb->clampToStartAndEndRegions(region);
- RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region);
- if (boxInfo) {
- if (curr != containerBlock)
- staticPosition -= cb->logicalWidth() - (boxInfo->logicalLeft() + boxInfo->logicalWidth());
- if (curr == enclosingBox)
- staticPosition += enclosingBox->logicalWidth() - boxInfo->logicalWidth();
- }
- }
} else if (curr->isInline()) {
if (curr->isRelPositioned()) {
if (!curr->style()->logicalLeft().isAuto())
}
}
-void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& computedValues, RenderRegion* region) const
+void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& computedValues) const
{
if (isReplaced()) {
- // FIXME: Positioned replaced elements inside a flow thread are not working properly
- // with variable width regions (see https://bugs.webkit.org/show_bug.cgi?id=69896 ).
computePositionedLogicalWidthReplaced(computedValues);
return;
}
// relative positioned inline.
const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
- const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, region);
+ const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock);
// Use the container block's direction except when calculating the static distance
// This conforms with the reference results for abspos-replaced-width-margin-000.htm
// see FIXME 1
// Calculate the static distance if needed.
- computeInlineStaticDistance(logicalLeftLength, logicalRightLength, this, containerBlock, containerLogicalWidth, region);
+ computeInlineStaticDistance(logicalLeftLength, logicalRightLength, this, containerBlock, containerLogicalWidth);
// Calculate constraint equation values for 'width' case.
computePositionedLogicalWidthUsing(style()->logicalWidth(), containerBlock, containerDirection,
}
computedValues.m_extent += bordersPlusPadding;
-
- // Adjust logicalLeft if we need to for the flipped version of our writing mode in regions.
- // FIXME: Add support for other types of objects as containerBlock, not only RenderBlock.
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (flowThread && !region && isWritingModeRoot() && isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode() && containerBlock->isRenderBlock()) {
- ASSERT(containerBlock->canHaveBoxInfoInRegion());
- LayoutUnit logicalLeftPos = computedValues.m_position;
- const RenderBlock* cb = toRenderBlock(containerBlock);
- LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage();
- RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
- if (cbRegion) {
- cbRegion = cb->clampToStartAndEndRegions(cbRegion);
- RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion);
- if (boxInfo) {
- logicalLeftPos += boxInfo->logicalLeft();
- computedValues.m_position = logicalLeftPos;
- }
- }
- }
}
static void computeLogicalLeftPositionedOffset(LayoutUnit& logicalLeftPos, const RenderBox* child, LayoutUnit logicalWidthValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth)
if (containerBlock->isHorizontalWritingMode() != child->isHorizontalWritingMode() && containerBlock->style()->isFlippedBlocksWritingMode()) {
logicalLeftPos = containerLogicalWidth - logicalWidthValue - logicalLeftPos;
logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderRight() : containerBlock->borderBottom());
- } else
+ } else {
logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderLeft() : containerBlock->borderTop());
+ }
}
void RenderBox::shrinkToFitWidth(const LayoutUnit availableSpace, const LayoutUnit logicalLeftValue, const LayoutUnit bordersPlusPadding, LogicalExtentComputedValues& computedValues) const
LayoutUnit logicalLeftValue = 0;
- const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, false);
+ const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, false);
bool logicalWidthIsAuto = logicalWidth.isIntrinsicOrAuto();
bool logicalLeftIsAuto = logicalLeft.isAuto();
bool logicalRightIsAuto = logicalRight.isAuto();
- RenderView* renderView = view();
LayoutUnit& marginLogicalLeftValue = style()->isLeftToRightDirection() ? computedValues.m_margins.m_start : computedValues.m_margins.m_end;
LayoutUnit& marginLogicalRightValue = style()->isLeftToRightDirection() ? computedValues.m_margins.m_end : computedValues.m_margins.m_start;
if (!logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
// NOTE: It is not necessary to solve for 'right' in the over constrained
// case because the value is not used for any further calculations.
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
- computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth, renderView));
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
+ computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth));
- const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth, renderView) + bordersPlusPadding);
+ const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth) + bordersPlusPadding);
// Margins are now the only unknown
if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
}
} else if (marginLogicalLeft.isAuto()) {
// Solve for left margin
- marginLogicalRightValue = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
+ marginLogicalRightValue = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
marginLogicalLeftValue = availableSpace - marginLogicalRightValue;
} else if (marginLogicalRight.isAuto()) {
// Solve for right margin
- marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
+ marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
marginLogicalRightValue = availableSpace - marginLogicalLeftValue;
} else {
// Over-constrained, solve for left if direction is RTL
- marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
- marginLogicalRightValue = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
+ marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
+ marginLogicalRightValue = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
// Use the containing block's direction rather than the parent block's
// per CSS 2.1 reference test abspos-non-replaced-width-margin-000.
// because the value is not used for any further calculations.
// Calculate margins, 'auto' margins are ignored.
- marginLogicalLeftValue = minimumValueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
- marginLogicalRightValue = minimumValueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
+ marginLogicalLeftValue = minimumValueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
+ marginLogicalRightValue = minimumValueForLength(marginLogicalRight, containerRelativeLogicalWidth);
const LayoutUnit availableSpace = containerLogicalWidth - (marginLogicalLeftValue + marginLogicalRightValue + bordersPlusPadding);
// Use rule/case that applies.
if (logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
// RULE 1: (use shrink-to-fit for width, and solve of left)
- LayoutUnit logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+ LayoutUnit logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
// FIXME: would it be better to have shrink-to-fit in one step?
LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
logicalLeftValue = availableSpace - (computedValues.m_extent + logicalRightValue);
} else if (!logicalLeftIsAuto && logicalWidthIsAuto && logicalRightIsAuto) {
// RULE 3: (use shrink-to-fit for width, and no need solve of right)
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
shrinkToFitWidth(availableSpace, logicalLeftValue, bordersPlusPadding, computedValues);
} else if (logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
// RULE 4: (solve for left)
- computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth, renderView));
- logicalLeftValue = availableSpace - (computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth, renderView));
+ computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth));
+ logicalLeftValue = availableSpace - (computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth));
} else if (!logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
// RULE 5: (solve for width)
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
if (autoWidthShouldFitContent())
shrinkToFitWidth(availableSpace, logicalLeftValue, bordersPlusPadding, computedValues);
else
- computedValues.m_extent = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth, renderView));
+ computedValues.m_extent = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth));
} else if (!logicalLeftIsAuto && !logicalWidthIsAuto && logicalRightIsAuto) {
// RULE 6: (no need solve for right)
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
- computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth, renderView));
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
+ computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth));
}
}
// Set final height value.
computedValues.m_extent += bordersPlusPadding;
-
- // Adjust logicalTop if we need to for perpendicular writing modes in regions.
- // FIXME: Add support for other types of objects as containerBlock, not only RenderBlock.
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (flowThread && isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode() && containerBlock->isRenderBlock()) {
- ASSERT(containerBlock->canHaveBoxInfoInRegion());
- LayoutUnit logicalTopPos = computedValues.m_position;
- const RenderBlock* cb = toRenderBlock(containerBlock);
- LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage() - logicalLeft();
- RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
- if (cbRegion) {
- cbRegion = cb->clampToStartAndEndRegions(cbRegion);
- RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion);
- if (boxInfo) {
- logicalTopPos += boxInfo->logicalLeft();
- computedValues.m_position = logicalTopPos;
- }
- }
- }
}
static void computeLogicalTopPositionedOffset(LayoutUnit& logicalTopPos, const RenderBox* child, LayoutUnit logicalHeightValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalHeight)
LayoutUnit logicalHeightValue;
LayoutUnit contentLogicalHeight = logicalHeight - bordersPlusPadding;
- const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, false);
+ const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, false);
LayoutUnit logicalTopValue = 0;
bool logicalHeightIsAuto = logicalHeightLength.isAuto();
bool logicalTopIsAuto = logicalTop.isAuto();
bool logicalBottomIsAuto = logicalBottom.isAuto();
- RenderView* renderView = view();
LayoutUnit resolvedLogicalHeight;
// Height is never unsolved for tables.
if (logicalHeightLength.isIntrinsic())
resolvedLogicalHeight = computeIntrinsicLogicalContentHeightUsing(logicalHeightLength, contentLogicalHeight, bordersPlusPadding);
else
- resolvedLogicalHeight = adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeightLength, containerLogicalHeight, renderView));
+ resolvedLogicalHeight = adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeightLength, containerLogicalHeight));
}
if (!logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
// case because the value is not used for any further calculations.
logicalHeightValue = resolvedLogicalHeight;
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
- const LayoutUnit availableSpace = containerLogicalHeight - (logicalTopValue + logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView) + bordersPlusPadding);
+ const LayoutUnit availableSpace = containerLogicalHeight - (logicalTopValue + logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight) + bordersPlusPadding);
// Margins are now the only unknown
if (marginBefore.isAuto() && marginAfter.isAuto()) {
computedValues.m_margins.m_after = availableSpace - computedValues.m_margins.m_before; // account for odd valued differences
} else if (marginBefore.isAuto()) {
// Solve for top margin
- computedValues.m_margins.m_after = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
+ computedValues.m_margins.m_after = valueForLength(marginAfter, containerRelativeLogicalWidth);
computedValues.m_margins.m_before = availableSpace - computedValues.m_margins.m_after;
} else if (marginAfter.isAuto()) {
// Solve for bottom margin
- computedValues.m_margins.m_before = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
+ computedValues.m_margins.m_before = valueForLength(marginBefore, containerRelativeLogicalWidth);
computedValues.m_margins.m_after = availableSpace - computedValues.m_margins.m_before;
} else {
// Over-constrained, (no need solve for bottom)
- computedValues.m_margins.m_before = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
- computedValues.m_margins.m_after = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
+ computedValues.m_margins.m_before = valueForLength(marginBefore, containerRelativeLogicalWidth);
+ computedValues.m_margins.m_after = valueForLength(marginAfter, containerRelativeLogicalWidth);
}
} else {
/*--------------------------------------------------------------------*\
// because the value is not used for any further calculations.
// Calculate margins, 'auto' margins are ignored.
- computedValues.m_margins.m_before = minimumValueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
- computedValues.m_margins.m_after = minimumValueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
+ computedValues.m_margins.m_before = minimumValueForLength(marginBefore, containerRelativeLogicalWidth);
+ computedValues.m_margins.m_after = minimumValueForLength(marginAfter, containerRelativeLogicalWidth);
const LayoutUnit availableSpace = containerLogicalHeight - (computedValues.m_margins.m_before + computedValues.m_margins.m_after + bordersPlusPadding);
if (logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
// RULE 1: (height is content based, solve of top)
logicalHeightValue = contentLogicalHeight;
- logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView));
+ logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight));
} else if (!logicalTopIsAuto && logicalHeightIsAuto && logicalBottomIsAuto) {
// RULE 3: (height is content based, no need solve of bottom)
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
logicalHeightValue = contentLogicalHeight;
} else if (logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
// RULE 4: (solve of top)
logicalHeightValue = resolvedLogicalHeight;
- logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView));
+ logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight));
} else if (!logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
// RULE 5: (solve of height)
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
- logicalHeightValue = max<LayoutUnit>(0, availableSpace - (logicalTopValue + valueForLength(logicalBottom, containerLogicalHeight, renderView)));
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
+ logicalHeightValue = max<LayoutUnit>(0, availableSpace - (logicalTopValue + valueForLength(logicalBottom, containerLogicalHeight)));
} else if (!logicalTopIsAuto && !logicalHeightIsAuto && logicalBottomIsAuto) {
// RULE 6: (no need solve of bottom)
logicalHeightValue = resolvedLogicalHeight;
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
}
}
computedValues.m_extent = logicalHeightValue;
const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock);
- const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, false);
+ const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, false);
// To match WinIE, in quirks mode use the parent's 'direction' property
// instead of the the container block's.
* else if 'direction' is 'rtl', set 'right' to the static position.
\*-----------------------------------------------------------------------*/
// see FIXME 1
- computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, containerLogicalWidth, 0); // FIXME: Pass the region.
+ computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, containerLogicalWidth);
/*-----------------------------------------------------------------------*\
* 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left'
\*-----------------------------------------------------------------------*/
LayoutUnit logicalLeftValue = 0;
LayoutUnit logicalRightValue = 0;
- RenderView* renderView = view();
if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
// 'left' and 'right' cannot be 'auto' due to step 3
ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
- logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
LayoutUnit difference = availableSpace - (logicalLeftValue + logicalRightValue);
if (difference > 0) {
* that value.
\*-----------------------------------------------------------------------*/
} else if (logicalLeft.isAuto()) {
- marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
- marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
- logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+ marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
+ marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
// Solve for 'left'
logicalLeftValue = availableSpace - (logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias);
} else if (logicalRight.isAuto()) {
- marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
- marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
+ marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
// Solve for 'right'
logicalRightValue = availableSpace - (logicalLeftValue + marginLogicalLeftAlias + marginLogicalRightAlias);
} else if (marginLogicalLeft.isAuto()) {
- marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
- logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+ marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
// Solve for 'margin-left'
marginLogicalLeftAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalRightAlias);
} else if (marginLogicalRight.isAuto()) {
- marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
- logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+ marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
// Solve for 'margin-right'
marginLogicalRightAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias);
} else {
// Nothing is 'auto', just calculate the values.
- marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
- marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
- logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
+ marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
// If the containing block is right-to-left, then push the left position as far to the right as possible
if (containerDirection == RTL) {
int totalLogicalWidth = computedValues.m_extent + logicalLeftValue + logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias;
const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock);
- const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, false);
+ const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, false);
// Variables to solve.
Length marginBefore = style()->marginBefore();
Length logicalTop = style()->logicalTop();
Length logicalBottom = style()->logicalBottom();
- RenderView* renderView = view();
/*-----------------------------------------------------------------------*\
* 1. The used value of 'height' is determined as for inline replaced
// 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined.
ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto()));
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
- logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
+ logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);
LayoutUnit difference = availableSpace - (logicalTopValue + logicalBottomValue);
// NOTE: This may result in negative values.
* for that value.
\*-----------------------------------------------------------------------*/
} else if (logicalTop.isAuto()) {
- marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
- marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
- logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
+ marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth);
+ marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth);
+ logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);
// Solve for 'top'
logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias + marginAfterAlias);
} else if (logicalBottom.isAuto()) {
- marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
- marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth);
+ marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
// Solve for 'bottom'
// NOTE: It is not necessary to solve for 'bottom' because we don't ever
// use the value.
} else if (marginBefore.isAuto()) {
- marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
- logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
+ marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
+ logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);
// Solve for 'margin-top'
marginBeforeAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginAfterAlias);
} else if (marginAfter.isAuto()) {
- marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
- logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
+ marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
+ logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);
// Solve for 'margin-bottom'
marginAfterAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginBeforeAlias);
} else {
// Nothing is 'auto', just calculate the values.
- marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
- marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth);
+ marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
// NOTE: It is not necessary to solve for 'bottom' because we don't ever
// use the value.
}
rect.move(LayoutSize(width() - caretWidth, 0));
if (box) {
- RootInlineBox* rootBox = box->root();
- LayoutUnit top = rootBox->lineTop();
+ RootInlineBox& rootBox = box->root();
+ LayoutUnit top = rootBox.lineTop();
rect.setY(top);
- rect.setHeight(rootBox->lineBottom() - top);
+ rect.setHeight(rootBox.lineBottom() - top);
}
// If height of box is smaller than font height, use the latter one,
// FIXME: Border/padding should be added for all elements but this workaround
// is needed because we use offsets inside an "atomic" element to represent
// positions before and after the element in deprecated editing offsets.
- if (node() && !(editingIgnoresContent(node()) || isTableElement(node()))) {
+ if (node() && !(editingIgnoresContent(node()) || isRenderedTable(node()))) {
rect.setX(rect.x() + borderLeft() + paddingLeft());
rect.setY(rect.y() + paddingTop() + borderTop());
}
bool RenderBox::avoidsFloats() const
{
- return isReplaced() || hasOverflowClip() || isHR() || isLegend() || isWritingModeRoot() || isFlexItemIncludingDeprecated();
+ // CSS2.1: "The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting
+ // context .. must not overlap the margin box of any floats in the same block formatting context."
+ // FIXME: The inclusion of horizontal rule and legend elements here isn't covered by any spec.
+ return isReplaced() || isHR() || isLegend() || isTable() || (!isFloatingOrOutOfFlowPositioned() && createsBlockFormattingContext());
+}
+
+bool RenderBox::createsBlockFormattingContext() const
+{
+ return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() || hasOverflowClip() || isFlexItemIncludingDeprecated()
+ || style()->specifiesColumns() || isRenderFlowThread() || isTableCell() || isTableCaption() || isFieldset() || isWritingModeRoot() || isDocumentElement() || style()->columnSpan();
+}
+
+void RenderBox::markForPaginationRelayoutIfNeeded(SubtreeLayoutScope& layoutScope)
+{
+ ASSERT(!needsLayout());
+ // If fragmentation height has changed, we need to lay out. No need to enter the renderer if it
+ // is childless, though.
+ if (view()->layoutState()->pageLogicalHeightChanged() && firstChild())
+ layoutScope.setChildNeedsLayout(this);
}
void RenderBox::addVisualEffectOverflow()
{
- if (!style()->boxShadow() && !style()->hasBorderImageOutsets())
+ if (!style()->boxShadow() && !style()->hasBorderImageOutsets() && !style()->hasOutline())
return;
bool isFlipped = style()->isFlippedBlocksWritingMode();
overflowMaxY = max(overflowMaxY, borderBox.maxY() + ((!isFlipped || !isHorizontal) ? borderOutsets.bottom() : borderOutsets.top()));
}
- // Add in the final overflow with shadows and outsets combined.
+ if (style()->hasOutline()) {
+ LayoutUnit outlineSize = style()->outlineSize();
+
+ overflowMinX = min(overflowMinX, borderBox.x() - outlineSize);
+ overflowMaxX = max(overflowMaxX, borderBox.maxX() + outlineSize);
+ overflowMinY = min(overflowMinY, borderBox.y() - outlineSize);
+ overflowMaxY = max(overflowMaxY, borderBox.maxY() + outlineSize);
+ }
+
+ // Add in the final overflow with shadows, outsets and outline combined.
LayoutRect visualEffectOverflow(overflowMinX, overflowMinY, overflowMaxX - overflowMinX, overflowMaxY - overflowMinY);
addVisualOverflow(visualEffectOverflow);
}
hasTopOverflow = true;
}
- if (hasColumns() && style()->columnProgression() == ReverseColumnProgression) {
- if (isHorizontalWritingMode() ^ !style()->hasInlineColumnAxis())
- hasLeftOverflow = !hasLeftOverflow;
- else
- hasTopOverflow = !hasTopOverflow;
- }
-
if (!hasTopOverflow)
overflowRect.shiftYEdgeTo(max(overflowRect.y(), clientBox.y()));
else
return;
}
- if (!m_overflow)
- m_overflow = adoptPtr(new RenderOverflow(clientBoxRect(), borderBoxRect()));
+ if (!m_overflow) {
+ LayoutRect clientBox = clientBoxRect();
+ if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+ clientBox.move(-verticalScrollbarWidth(), 0);
+ m_overflow = adoptPtr(new RenderOverflow(clientBox, borderBoxRect()));
+ }
m_overflow->addContentsVisualOverflow(rect);
}
return percentageLogicalHeightIsResolvableFromBlock(cb->containingBlock(), cb->isOutOfFlowPositioned());
if (cb->isRenderView() || inQuirksMode || isOutOfFlowPositionedWithSpecifiedHeight)
return true;
- if (cb->isRoot() && isOutOfFlowPositioned) {
+ if (cb->isDocumentElement() && isOutOfFlowPositioned) {
// Match the positioned objects behavior, which is that positioned objects will fill their viewport
// always. Note we could only hit this case by recurring into computePercentageLogicalHeight on a positioned containing block.
return true;
{
// Only propagate interior layout overflow if we don't clip it.
LayoutRect rect = borderBoxRect();
+ // We want to include the margin, but only when it adds height. Quirky margins don't contribute height
+ // nor do the margins of self-collapsing blocks.
+ if (!style()->hasMarginAfterQuirk() && !isSelfCollapsingBlock())
+ rect.expand(isHorizontalWritingMode() ? LayoutSize(LayoutUnit(), marginAfter()) : LayoutSize(marginAfter(), LayoutUnit()));
+
if (!hasOverflowClip())
rect.unite(layoutOverflowRect());
LayoutRect RenderBox::noOverflowRect() const
{
- // Because of the special coodinate system used for overflow rectangles and many other
+ // Because of the special coordinate system used for overflow rectangles and many other
// rectangles (not quite logical, not quite physical), we need to flip the block progression
// coordinate in vertical-rl and horizontal-bt writing modes. In other words, the rectangle
// returned is physical, except for the block direction progression coordinate (y in horizontal
// writing modes, x in vertical writing modes), which is always "logical top". Apart from the
// flipping, this method does the same as clientBoxRect().
- LayoutUnit left = borderLeft();
+ const int scrollBarWidth = verticalScrollbarWidth();
+ const int scrollBarHeight = horizontalScrollbarHeight();
+ LayoutUnit left = borderLeft() + (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft() ? scrollBarWidth : 0);
LayoutUnit top = borderTop();
LayoutUnit right = borderRight();
LayoutUnit bottom = borderBottom();
// FIXME: when the above mentioned bug is fixed, it should hopefully be possible to call
// clientBoxRect() or paddingBoxRect() in this method, rather than fiddling with the edges on
// our own.
- rect.contract(verticalScrollbarWidth(), horizontalScrollbarHeight());
+ if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+ rect.contract(0, scrollBarHeight);
+ else
+ rect.contract(scrollBarWidth, scrollBarHeight);
return rect;
}
return LayoutSize(rect.x(), rect.y());
}
-bool RenderBox::hasRelativeDimensions() const
-{
- // FIXME: This should probably include viewport percentage heights as well.
- return style()->height().isPercent() || style()->width().isPercent()
- || style()->maxHeight().isPercent() || style()->maxWidth().isPercent()
- || style()->minHeight().isPercent() || style()->minWidth().isPercent();
-}
-
bool RenderBox::hasRelativeLogicalHeight() const
{
return style()->logicalHeight().isPercent()
|| style()->logicalMinHeight().isPercent()
- || style()->logicalMaxHeight().isPercent()
- || style()->logicalHeight().isViewportPercentage()
- || style()->logicalMinHeight().isViewportPercentage()
- || style()->logicalMaxHeight().isViewportPercentage();
+ || style()->logicalMaxHeight().isPercent();
}
static void markBoxForRelayoutAfterSplit(RenderBox* box)