/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "config.h" #include "core/rendering/RenderBox.h" #include #include #include "HTMLNames.h" #include "core/dom/Document.h" #include "core/editing/htmlediting.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/rendering/HitTestResult.h" #include "core/rendering/LayoutRectRecorder.h" #include "core/rendering/PaintInfo.h" #include "core/rendering/RenderBoxRegionInfo.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/RenderListMarker.h" #include "core/rendering/RenderRegion.h" #include "core/rendering/RenderTableCell.h" #include "core/rendering/RenderTheme.h" #include "core/rendering/RenderView.h" #include "platform/geometry/FloatQuad.h" #include "platform/geometry/TransformState.h" #include "platform/graphics/GraphicsContextStateSaver.h" using namespace std; namespace WebCore { using namespace HTMLNames; // Used by flexible boxes when flexing this element and by table cells. typedef WTF::HashMap OverrideSizeMap; static OverrideSizeMap* gOverrideHeightMap = 0; static OverrideSizeMap* gOverrideWidthMap = 0; // Used by grid elements to properly size their grid items. static OverrideSizeMap* gOverrideContainingBlockLogicalHeightMap = 0; static OverrideSizeMap* gOverrideContainingBlockLogicalWidthMap = 0; // Size of border belt for autoscroll. When mouse pointer in border belt, // autoscroll is started. static const int autoscrollBeltSize = 20; static const unsigned backgroundObscurationTestMaxDepth = 4; static bool skipBodyBackground(const RenderBox* bodyElementRenderer) { ASSERT(bodyElementRenderer->isBody()); // The only paints its background if the root element has defined a background independent of the body, // or if the 's parent is not the document element's renderer (e.g. inside SVG foreignObject). RenderObject* documentElementRenderer = bodyElementRenderer->document().documentElement()->renderer(); return documentElementRenderer && !documentElementRenderer->hasBackground() && (documentElementRenderer == bodyElementRenderer->parent()); } RenderBox::RenderBox(ContainerNode* node) : RenderBoxModelObject(node) , 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(); clearContainingBlockOverrideSize(); RenderBlock::removePercentHeightDescendantIfNeeded(this); ShapeOutsideInfo::removeInfo(this); RenderBoxModelObject::willBeDestroyed(); } void RenderBox::removeFloatingOrPositionedChildFromBlockLists() { ASSERT(isFloatingOrOutOfFlowPositioned()); if (documentBeingDestroyed()) return; if (isFloating()) { RenderBlockFlow* parentBlockFlow = 0; for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) { if (curr->isRenderBlockFlow()) { RenderBlockFlow* currBlockFlow = toRenderBlockFlow(curr); if (!parentBlockFlow || currBlockFlow->containsFloat(this)) parentBlockFlow = currBlockFlow; } } if (parentBlockFlow) { parentBlockFlow->markSiblingsWithFloatsForLayout(this); parentBlockFlow->markAllDescendantsWithFloatsForLayout(this, false); } } if (isOutOfFlowPositioned()) RenderBlock::removePositionedObject(this); } void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) { 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))) { view()->repaint(); if (oldStyle->hasEntirelyFixedBackground() != newStyle->hasEntirelyFixedBackground()) view()->compositor()->rootFixedBackgroundsChanged(); } // 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()) { markContainingBlocksForLayout(); if (oldStyle->position() == StaticPosition) repaint(); else if (newStyle->hasOutOfFlowPosition()) parent()->setChildNeedsLayout(); if (isFloating() && !isOutOfFlowPositioned() && newStyle->hasOutOfFlowPosition()) removeFloatingOrPositionedChildFromBlockLists(); } } else if (newStyle && isBody()) view()->repaint(); RenderBoxModelObject::styleWillChange(diff, newStyle); } void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { // Horizontal writing mode definition is updated in RenderBoxModelObject::updateFromStyle, // (as part of the RenderBoxModelObject::styleDidChange call below). So, we can safely cache the horizontal // writing mode value before style change here. bool oldHorizontalWritingMode = isHorizontalWritingMode(); RenderBoxModelObject::styleDidChange(diff, oldStyle); RenderStyle* newStyle = style(); if (needsLayout() && oldStyle) { RenderBlock::removePercentHeightDescendantIfNeeded(this); // Normally we can do optimized positioning layout for absolute/fixed positioned objects. There is one special case, however, which is // when the positioned object's margin-before is changed. In this case the parent has to get a layout in order to run margin collapsing // to determine the new static position. if (isOutOfFlowPositioned() && newStyle->hasStaticBlockPosition(isHorizontalWritingMode()) && oldStyle->marginBefore() != newStyle->marginBefore() && parent() && !parent()->normalChildNeedsLayout()) parent()->setChildNeedsLayout(); } if (RenderBlock::hasPercentHeightContainerMap() && firstChild() && oldHorizontalWritingMode != isHorizontalWritingMode()) RenderBlock::clearPercentHeightDescendantsFrom(this); // If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the // new zoomed coordinate space. if (hasOverflowClip() && oldStyle && newStyle && oldStyle->effectiveZoom() != newStyle->effectiveZoom() && layer()) { if (int left = layer()->scrollableArea()->scrollXOffset()) { left = (left / oldStyle->effectiveZoom()) * newStyle->effectiveZoom(); layer()->scrollableArea()->scrollToXOffset(left); } if (int top = layer()->scrollableArea()->scrollYOffset()) { top = (top / oldStyle->effectiveZoom()) * newStyle->effectiveZoom(); layer()->scrollableArea()->scrollToYOffset(top); } } // Our opaqueness might have changed without triggering layout. if (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintIfTextOrColorChange || diff == StyleDifferenceRepaintLayer) { RenderObject* parentToInvalidate = parent(); for (unsigned i = 0; i < backgroundObscurationTestMaxDepth && parentToInvalidate; ++i) { parentToInvalidate->invalidateBackgroundObscurationStatus(); parentToInvalidate = parentToInvalidate->parent(); } } if (isRoot() || isBody()) document().view()->recalculateScrollbarOverlayStyle(); updateShapeOutsideInfoAfterStyleChange(*style(), oldStyle); updateGridPositionAfterStyleChange(oldStyle); } void RenderBox::updateShapeOutsideInfoAfterStyleChange(const RenderStyle& style, const RenderStyle* oldStyle) { const ShapeValue* shapeOutside = style.shapeOutside(); const ShapeValue* oldShapeOutside = oldStyle ? oldStyle->shapeOutside() : RenderStyle::initialShapeOutside(); 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 && shapeImageThreshold == oldShapeImageThreshold) return; if (!shapeOutside) ShapeOutsideInfo::removeInfo(this); else ShapeOutsideInfo::ensureInfo(this)->dirtyShapeSize(); if (shapeOutside || shapeOutside != oldShapeOutside) markShapeOutsideDependentsForLayout(); } void RenderBox::updateGridPositionAfterStyleChange(const RenderStyle* oldStyle) { if (!oldStyle || !parent() || !parent()->isRenderGrid()) return; if (oldStyle->gridColumnStart() == style()->gridColumnStart() && oldStyle->gridColumnEnd() == style()->gridColumnEnd() && oldStyle->gridRowStart() == style()->gridRowStart() && oldStyle->gridRowEnd() == style()->gridRowEnd() && oldStyle->order() == style()->order() && oldStyle->hasOutOfFlowPosition() == style()->hasOutOfFlowPosition()) return; // It should be possible to not dirty the grid in some cases (like moving an explicitly placed grid item). // For now, it's more simple to just always recompute the grid. toRenderGrid(parent())->dirtyGrid(); } void RenderBox::updateFromStyle() { RenderBoxModelObject::updateFromStyle(); RenderStyle* styleToUse = style(); bool isRootObject = isRoot(); bool isViewObject = isRenderView(); // The root and the RenderView always paint their backgrounds/borders. if (isRootObject || isViewObject) setHasBoxDecorations(true); setFloating(!isOutOfFlowPositioned() && styleToUse->isFloating()); // We also handle and , 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 . // (2) We are the primary (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; } // 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 we are getting an overflow clip, preemptively erase any overflowing content. // FIXME: This should probably consult RenderOverflow. if (!hasOverflowClip()) repaint(); setHasOverflowClip(true); } } else { setHasOverflowClip(false); } setHasTransform(styleToUse->hasTransformRelatedProperty()); setHasReflection(styleToUse->boxReflect()); } void RenderBox::layout() { ASSERT(needsLayout()); LayoutRectRecorder recorder(*this); RenderObject* child = firstChild(); if (!child) { clearNeedsLayout(); return; } LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode()); while (child) { child->layoutIfNeeded(); ASSERT(!child->needsLayout()); child = child->nextSibling(); } statePusher.pop(); invalidateBackgroundObscurationStatus(); clearNeedsLayout(); } // More IE extensions. clientWidth and clientHeight represent the interior of an object // excluding border and scrollbar. LayoutUnit RenderBox::clientWidth() const { return width() - borderLeft() - borderRight() - verticalScrollbarWidth(); } LayoutUnit RenderBox::clientHeight() const { return height() - borderTop() - borderBottom() - horizontalScrollbarHeight(); } int RenderBox::pixelSnappedClientWidth() const { return snapSizeToPixel(clientWidth(), x() + clientLeft()); } int RenderBox::pixelSnappedClientHeight() const { return snapSizeToPixel(clientHeight(), y() + clientTop()); } int RenderBox::pixelSnappedOffsetWidth() const { return snapSizeToPixel(offsetWidth(), x() + clientLeft()); } int RenderBox::pixelSnappedOffsetHeight() const { 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()) return layer()->scrollableArea()->scrollWidth(); // For objects with visible overflow, this matches IE. // FIXME: Need to work right with writing modes. if (style()->isLeftToRightDirection()) return snapSizeToPixel(max(clientWidth(), layoutOverflowRect().maxX() - borderLeft()), x() + clientLeft()); return clientWidth() - min(0, layoutOverflowRect().x() - borderLeft()); } int RenderBox::scrollHeight() const { if (hasOverflowClip()) return layer()->scrollableArea()->scrollHeight(); // For objects with visible overflow, this matches IE. // FIXME: Need to work right with writing modes. return snapSizeToPixel(max(clientHeight(), layoutOverflowRect().maxY() - borderTop()), y() + clientTop()); } int RenderBox::scrollLeft() const { return hasOverflowClip() ? layer()->scrollableArea()->scrollXOffset() : 0; } int RenderBox::scrollTop() const { return hasOverflowClip() ? layer()->scrollableArea()->scrollYOffset() : 0; } void RenderBox::setScrollLeft(int newLeft) { if (hasOverflowClip()) layer()->scrollableArea()->scrollToXOffset(newLeft, ScrollOffsetClamped); } void RenderBox::setScrollTop(int newTop) { if (hasOverflowClip()) layer()->scrollableArea()->scrollToYOffset(newTop, ScrollOffsetClamped); } void RenderBox::scrollToOffset(const IntSize& offset) { ASSERT(hasOverflowClip()); layer()->scrollableArea()->scrollToOffset(offset, ScrollOffsetClamped); } static inline bool frameElementAndViewPermitScroll(HTMLFrameElementBase* frameElementBase, FrameView* frameView) { // If scrollbars aren't explicitly forbidden, permit scrolling. if (frameElementBase && frameElementBase->scrollingMode() != ScrollbarAlwaysOff) return true; // If scrollbars are forbidden, user initiated scrolls should obviously be ignored. if (frameView->wasScrolledByUser()) return false; // Forbid autoscrolls when scrollbars are off, but permits other programmatic scrolls, // like navigation to an anchor. Page* page = frameView->frame().page(); if (!page) return false; return !page->autoscrollController().autoscrollInProgress(); } void RenderBox::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY) { RenderBox* parentBox = 0; LayoutRect newRect = rect; bool restrictedByLineClamp = false; if (parent()) { parentBox = parent()->enclosingBox(); restrictedByLineClamp = !parent()->style()->lineClamp().isNone(); } if (hasOverflowClip() && !restrictedByLineClamp) { // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property. // This will prevent us from revealing text hidden by the slider in Safari RSS. newRect = layer()->scrollableArea()->exposeRect(rect, alignX, alignY); } else if (!parentBox && canBeProgramaticallyScrolled()) { if (FrameView* frameView = this->frameView()) { Element* ownerElement = document().ownerElement(); if (ownerElement && ownerElement->renderer()) { HTMLFrameElementBase* frameElementBase = 0; if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag)) frameElementBase = toHTMLFrameElementBase(ownerElement); if (frameElementAndViewPermitScroll(frameElementBase, frameView)) { LayoutRect viewRect = frameView->visibleContentRect(); LayoutRect exposeRect = ScrollAlignment::getRectToExpose(viewRect, rect, alignX, alignY); int xOffset = roundToInt(exposeRect.x()); int yOffset = roundToInt(exposeRect.y()); // Adjust offsets if they're outside of the allowable range. xOffset = max(0, min(frameView->contentsWidth(), xOffset)); yOffset = max(0, min(frameView->contentsHeight(), yOffset)); frameView->setScrollPosition(IntPoint(xOffset, yOffset)); if (frameView->safeToPropagateScrollToParent()) { parentBox = ownerElement->renderer()->enclosingBox(); // FIXME: This doesn't correctly convert the rect to // absolute coordinates in the parent. newRect.setX(rect.x() - frameView->scrollX() + frameView->x()); newRect.setY(rect.y() - frameView->scrollY() + frameView->y()); } else { parentBox = 0; } } } else { LayoutRect viewRect = frameView->visibleContentRect(); LayoutRect r = ScrollAlignment::getRectToExpose(viewRect, rect, alignX, alignY); frameView->setScrollPosition(roundedIntPoint(r.location())); } } } if (frame()->page()->autoscrollController().autoscrollInProgress()) parentBox = enclosingScrollableBox(); if (parentBox) parentBox->scrollRectToVisible(newRect, alignX, alignY); } void RenderBox::absoluteRects(Vector& rects, const LayoutPoint& accumulatedOffset) const { rects.append(pixelSnappedIntRect(accumulatedOffset, size())); } void RenderBox::absoluteQuads(Vector& quads, bool* wasFixed) const { quads.append(localToAbsoluteQuad(FloatRect(0, 0, width(), height()), 0 /* mode */, wasFixed)); } void RenderBox::updateLayerTransform() { // Transform-origin depends on box size, so we need to update the layer transform after layout. if (hasLayer()) layer()->updateTransform(); } LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb, RenderRegion* region) 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)); } LayoutUnit RenderBox::constrainLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const { RenderStyle* styleToUse = style(); if (!styleToUse->logicalMaxHeight().isUndefined()) { LayoutUnit maxH = computeLogicalHeightUsing(styleToUse->logicalMaxHeight(), intrinsicContentHeight); if (maxH != -1) logicalHeight = min(logicalHeight, maxH); } return max(logicalHeight, computeLogicalHeightUsing(styleToUse->logicalMinHeight(), intrinsicContentHeight)); } LayoutUnit RenderBox::constrainContentBoxLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const { RenderStyle* styleToUse = style(); if (!styleToUse->logicalMaxHeight().isUndefined()) { LayoutUnit maxH = computeContentLogicalHeight(styleToUse->logicalMaxHeight(), intrinsicContentHeight); if (maxH != -1) logicalHeight = min(logicalHeight, maxH); } return max(logicalHeight, computeContentLogicalHeight(styleToUse->logicalMinHeight(), intrinsicContentHeight)); } IntRect RenderBox::absoluteContentBox() const { // This is wrong with transforms and flipped writing modes. IntRect rect = pixelSnappedIntRect(contentBoxRect()); FloatPoint absPos = localToAbsolute(); rect.move(absPos.x(), absPos.y()); return rect; } FloatQuad RenderBox::absoluteContentQuad() const { LayoutRect rect = contentBoxRect(); 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& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*) { if (!size().isEmpty()) rects.append(pixelSnappedIntRect(additionalOffset, size())); } bool RenderBox::canResize() const { // We need a special case for