Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2005 Allan Sandfeld Jensen (kde (at) carewolf.com)
      5  *           (C) 2005, 2006 Samuel Weinig (sam.weinig (at) gmail.com)
      6  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
      7  * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
      8  *
      9  * This library is free software; you can redistribute it and/or
     10  * modify it under the terms of the GNU Library General Public
     11  * License as published by the Free Software Foundation; either
     12  * version 2 of the License, or (at your option) any later version.
     13  *
     14  * This library is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     17  * Library General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU Library General Public License
     20  * along with this library; see the file COPYING.LIB.  If not, write to
     21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     22  * Boston, MA 02110-1301, USA.
     23  *
     24  */
     25 
     26 #include "config.h"
     27 #include "core/rendering/RenderBox.h"
     28 
     29 #include <math.h>
     30 #include <algorithm>
     31 #include "HTMLNames.h"
     32 #include "core/dom/Document.h"
     33 #include "core/editing/htmlediting.h"
     34 #include "core/html/HTMLElement.h"
     35 #include "core/html/HTMLFrameElementBase.h"
     36 #include "core/html/HTMLFrameOwnerElement.h"
     37 #include "core/html/HTMLHtmlElement.h"
     38 #include "core/html/HTMLTextAreaElement.h"
     39 #include "core/frame/Frame.h"
     40 #include "core/frame/FrameView.h"
     41 #include "core/page/AutoscrollController.h"
     42 #include "core/page/EventHandler.h"
     43 #include "core/page/Page.h"
     44 #include "core/rendering/HitTestResult.h"
     45 #include "core/rendering/LayoutRectRecorder.h"
     46 #include "core/rendering/PaintInfo.h"
     47 #include "core/rendering/RenderBoxRegionInfo.h"
     48 #include "core/rendering/RenderFlexibleBox.h"
     49 #include "core/rendering/RenderFlowThread.h"
     50 #include "core/rendering/RenderGeometryMap.h"
     51 #include "core/rendering/RenderGrid.h"
     52 #include "core/rendering/RenderInline.h"
     53 #include "core/rendering/RenderLayer.h"
     54 #include "core/rendering/RenderLayerCompositor.h"
     55 #include "core/rendering/RenderListMarker.h"
     56 #include "core/rendering/RenderRegion.h"
     57 #include "core/rendering/RenderTableCell.h"
     58 #include "core/rendering/RenderTheme.h"
     59 #include "core/rendering/RenderView.h"
     60 #include "platform/geometry/FloatQuad.h"
     61 #include "platform/geometry/TransformState.h"
     62 #include "platform/graphics/GraphicsContextStateSaver.h"
     63 
     64 using namespace std;
     65 
     66 namespace WebCore {
     67 
     68 using namespace HTMLNames;
     69 
     70 // Used by flexible boxes when flexing this element and by table cells.
     71 typedef WTF::HashMap<const RenderBox*, LayoutUnit> OverrideSizeMap;
     72 static OverrideSizeMap* gOverrideHeightMap = 0;
     73 static OverrideSizeMap* gOverrideWidthMap = 0;
     74 
     75 // Used by grid elements to properly size their grid items.
     76 static OverrideSizeMap* gOverrideContainingBlockLogicalHeightMap = 0;
     77 static OverrideSizeMap* gOverrideContainingBlockLogicalWidthMap = 0;
     78 
     79 
     80 // Size of border belt for autoscroll. When mouse pointer in border belt,
     81 // autoscroll is started.
     82 static const int autoscrollBeltSize = 20;
     83 static const unsigned backgroundObscurationTestMaxDepth = 4;
     84 
     85 static bool skipBodyBackground(const RenderBox* bodyElementRenderer)
     86 {
     87     ASSERT(bodyElementRenderer->isBody());
     88     // The <body> only paints its background if the root element has defined a background independent of the body,
     89     // or if the <body>'s parent is not the document element's renderer (e.g. inside SVG foreignObject).
     90     RenderObject* documentElementRenderer = bodyElementRenderer->document().documentElement()->renderer();
     91     return documentElementRenderer
     92         && !documentElementRenderer->hasBackground()
     93         && (documentElementRenderer == bodyElementRenderer->parent());
     94 }
     95 
     96 RenderBox::RenderBox(ContainerNode* node)
     97     : RenderBoxModelObject(node)
     98     , m_minPreferredLogicalWidth(-1)
     99     , m_maxPreferredLogicalWidth(-1)
    100     , m_intrinsicContentLogicalHeight(-1)
    101     , m_inlineBoxWrapper(0)
    102 {
    103     setIsBox();
    104 }
    105 
    106 RenderBox::~RenderBox()
    107 {
    108 }
    109 
    110 LayoutRect RenderBox::borderBoxRectInRegion(RenderRegion* region, RenderBoxRegionInfoFlags cacheFlag) const
    111 {
    112     if (!region)
    113         return borderBoxRect();
    114 
    115     // Compute the logical width and placement in this region.
    116     RenderBoxRegionInfo* boxInfo = renderBoxRegionInfo(region, cacheFlag);
    117     if (!boxInfo)
    118         return borderBoxRect();
    119 
    120     // We have cached insets.
    121     LayoutUnit logicalWidth = boxInfo->logicalWidth();
    122     LayoutUnit logicalLeft = boxInfo->logicalLeft();
    123 
    124     // Now apply the parent inset since it is cumulative whenever anything in the containing block chain shifts.
    125     // FIXME: Doesn't work right with perpendicular writing modes.
    126     const RenderBlock* currentBox = containingBlock();
    127     RenderBoxRegionInfo* currentBoxInfo = currentBox->renderBoxRegionInfo(region);
    128     while (currentBoxInfo && currentBoxInfo->isShifted()) {
    129         if (currentBox->style()->direction() == LTR)
    130             logicalLeft += currentBoxInfo->logicalLeft();
    131         else
    132             logicalLeft -= (currentBox->logicalWidth() - currentBoxInfo->logicalWidth()) - currentBoxInfo->logicalLeft();
    133         currentBox = currentBox->containingBlock();
    134         region = currentBox->clampToStartAndEndRegions(region);
    135         currentBoxInfo = currentBox->renderBoxRegionInfo(region);
    136     }
    137 
    138     if (cacheFlag == DoNotCacheRenderBoxRegionInfo)
    139         delete boxInfo;
    140 
    141     if (isHorizontalWritingMode())
    142         return LayoutRect(logicalLeft, 0, logicalWidth, height());
    143     return LayoutRect(0, logicalLeft, width(), logicalWidth);
    144 }
    145 
    146 void RenderBox::clearRenderBoxRegionInfo()
    147 {
    148     if (isRenderFlowThread())
    149         return;
    150 
    151     RenderFlowThread* flowThread = flowThreadContainingBlock();
    152     if (flowThread)
    153         flowThread->removeRenderBoxRegionInfo(this);
    154 }
    155 
    156 void RenderBox::willBeDestroyed()
    157 {
    158     clearOverrideSize();
    159     clearContainingBlockOverrideSize();
    160 
    161     RenderBlock::removePercentHeightDescendantIfNeeded(this);
    162 
    163     ShapeOutsideInfo::removeInfo(this);
    164 
    165     RenderBoxModelObject::willBeDestroyed();
    166 }
    167 
    168 void RenderBox::removeFloatingOrPositionedChildFromBlockLists()
    169 {
    170     ASSERT(isFloatingOrOutOfFlowPositioned());
    171 
    172     if (documentBeingDestroyed())
    173         return;
    174 
    175     if (isFloating()) {
    176         RenderBlockFlow* parentBlockFlow = 0;
    177         for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) {
    178             if (curr->isRenderBlockFlow()) {
    179                 RenderBlockFlow* currBlockFlow = toRenderBlockFlow(curr);
    180                 if (!parentBlockFlow || currBlockFlow->containsFloat(this))
    181                     parentBlockFlow = currBlockFlow;
    182             }
    183         }
    184 
    185         if (parentBlockFlow) {
    186             parentBlockFlow->markSiblingsWithFloatsForLayout(this);
    187             parentBlockFlow->markAllDescendantsWithFloatsForLayout(this, false);
    188         }
    189     }
    190 
    191     if (isOutOfFlowPositioned())
    192         RenderBlock::removePositionedObject(this);
    193 }
    194 
    195 void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
    196 {
    197     RenderStyle* oldStyle = style();
    198     if (oldStyle) {
    199         // The background of the root element or the body element could propagate up to
    200         // the canvas.  Just dirty the entire canvas when our style changes substantially.
    201         if (diff >= StyleDifferenceRepaint && node() &&
    202             (isHTMLHtmlElement(node()) || node()->hasTagName(bodyTag))) {
    203             view()->repaint();
    204 
    205             if (oldStyle->hasEntirelyFixedBackground() != newStyle->hasEntirelyFixedBackground())
    206                 view()->compositor()->rootFixedBackgroundsChanged();
    207         }
    208 
    209         // When a layout hint happens and an object's position style changes, we have to do a layout
    210         // to dirty the render tree using the old position value now.
    211         if (diff == StyleDifferenceLayout && parent() && oldStyle->position() != newStyle->position()) {
    212             markContainingBlocksForLayout();
    213             if (oldStyle->position() == StaticPosition)
    214                 repaint();
    215             else if (newStyle->hasOutOfFlowPosition())
    216                 parent()->setChildNeedsLayout();
    217             if (isFloating() && !isOutOfFlowPositioned() && newStyle->hasOutOfFlowPosition())
    218                 removeFloatingOrPositionedChildFromBlockLists();
    219         }
    220     } else if (newStyle && isBody())
    221         view()->repaint();
    222 
    223     RenderBoxModelObject::styleWillChange(diff, newStyle);
    224 }
    225 
    226 void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
    227 {
    228     // Horizontal writing mode definition is updated in RenderBoxModelObject::updateFromStyle,
    229     // (as part of the RenderBoxModelObject::styleDidChange call below). So, we can safely cache the horizontal
    230     // writing mode value before style change here.
    231     bool oldHorizontalWritingMode = isHorizontalWritingMode();
    232 
    233     RenderBoxModelObject::styleDidChange(diff, oldStyle);
    234 
    235     RenderStyle* newStyle = style();
    236     if (needsLayout() && oldStyle) {
    237         RenderBlock::removePercentHeightDescendantIfNeeded(this);
    238 
    239         // Normally we can do optimized positioning layout for absolute/fixed positioned objects. There is one special case, however, which is
    240         // 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
    241         // to determine the new static position.
    242         if (isOutOfFlowPositioned() && newStyle->hasStaticBlockPosition(isHorizontalWritingMode()) && oldStyle->marginBefore() != newStyle->marginBefore()
    243             && parent() && !parent()->normalChildNeedsLayout())
    244             parent()->setChildNeedsLayout();
    245     }
    246 
    247     if (RenderBlock::hasPercentHeightContainerMap() && firstChild()
    248         && oldHorizontalWritingMode != isHorizontalWritingMode())
    249         RenderBlock::clearPercentHeightDescendantsFrom(this);
    250 
    251     // If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the
    252     // new zoomed coordinate space.
    253     if (hasOverflowClip() && oldStyle && newStyle && oldStyle->effectiveZoom() != newStyle->effectiveZoom() && layer()) {
    254         if (int left = layer()->scrollableArea()->scrollXOffset()) {
    255             left = (left / oldStyle->effectiveZoom()) * newStyle->effectiveZoom();
    256             layer()->scrollableArea()->scrollToXOffset(left);
    257         }
    258         if (int top = layer()->scrollableArea()->scrollYOffset()) {
    259             top = (top / oldStyle->effectiveZoom()) * newStyle->effectiveZoom();
    260             layer()->scrollableArea()->scrollToYOffset(top);
    261         }
    262     }
    263 
    264     // Our opaqueness might have changed without triggering layout.
    265     if (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintIfTextOrColorChange || diff == StyleDifferenceRepaintLayer) {
    266         RenderObject* parentToInvalidate = parent();
    267         for (unsigned i = 0; i < backgroundObscurationTestMaxDepth && parentToInvalidate; ++i) {
    268             parentToInvalidate->invalidateBackgroundObscurationStatus();
    269             parentToInvalidate = parentToInvalidate->parent();
    270         }
    271     }
    272 
    273     if (isRoot() || isBody())
    274         document().view()->recalculateScrollbarOverlayStyle();
    275 
    276     updateShapeOutsideInfoAfterStyleChange(*style(), oldStyle);
    277     updateGridPositionAfterStyleChange(oldStyle);
    278 }
    279 
    280 void RenderBox::updateShapeOutsideInfoAfterStyleChange(const RenderStyle& style, const RenderStyle* oldStyle)
    281 {
    282     const ShapeValue* shapeOutside = style.shapeOutside();
    283     const ShapeValue* oldShapeOutside = oldStyle ? oldStyle->shapeOutside() : RenderStyle::initialShapeOutside();
    284 
    285     Length shapeMargin = style.shapeMargin();
    286     Length oldShapeMargin = oldStyle ? oldStyle->shapeMargin() : RenderStyle::initialShapeMargin();
    287 
    288     float shapeImageThreshold = style.shapeImageThreshold();
    289     float oldShapeImageThreshold = oldStyle ? oldStyle->shapeImageThreshold() : RenderStyle::initialShapeImageThreshold();
    290 
    291     // FIXME: A future optimization would do a deep comparison for equality. (bug 100811)
    292     if (shapeOutside == oldShapeOutside && shapeMargin == oldShapeMargin && shapeImageThreshold == oldShapeImageThreshold)
    293         return;
    294 
    295     if (!shapeOutside)
    296         ShapeOutsideInfo::removeInfo(this);
    297     else
    298         ShapeOutsideInfo::ensureInfo(this)->dirtyShapeSize();
    299 
    300     if (shapeOutside || shapeOutside != oldShapeOutside)
    301         markShapeOutsideDependentsForLayout();
    302 }
    303 
    304 void RenderBox::updateGridPositionAfterStyleChange(const RenderStyle* oldStyle)
    305 {
    306     if (!oldStyle || !parent() || !parent()->isRenderGrid())
    307         return;
    308 
    309     if (oldStyle->gridColumnStart() == style()->gridColumnStart()
    310         && oldStyle->gridColumnEnd() == style()->gridColumnEnd()
    311         && oldStyle->gridRowStart() == style()->gridRowStart()
    312         && oldStyle->gridRowEnd() == style()->gridRowEnd()
    313         && oldStyle->order() == style()->order()
    314         && oldStyle->hasOutOfFlowPosition() == style()->hasOutOfFlowPosition())
    315         return;
    316 
    317     // It should be possible to not dirty the grid in some cases (like moving an explicitly placed grid item).
    318     // For now, it's more simple to just always recompute the grid.
    319     toRenderGrid(parent())->dirtyGrid();
    320 }
    321 
    322 void RenderBox::updateFromStyle()
    323 {
    324     RenderBoxModelObject::updateFromStyle();
    325 
    326     RenderStyle* styleToUse = style();
    327     bool isRootObject = isRoot();
    328     bool isViewObject = isRenderView();
    329 
    330     // The root and the RenderView always paint their backgrounds/borders.
    331     if (isRootObject || isViewObject)
    332         setHasBoxDecorations(true);
    333 
    334     setFloating(!isOutOfFlowPositioned() && styleToUse->isFloating());
    335 
    336     bool boxHasOverflowClip = false;
    337     // We also handle <body> and <html>, whose overflow applies to the viewport.
    338     // It's sufficient to just check one direction, since it's illegal to have visible on only one overflow value.
    339     if (styleToUse->overflowX() != OVISIBLE && !isRootObject && isRenderBlock()) {
    340         // Overflow on the body can propagate to the viewport under the following conditions.
    341         // (1) The root element is <html>.
    342         // (2) We are the primary <body> (can be checked by looking at document.body).
    343         // (3) The root element has visible overflow.
    344         if (isBody() && isHTMLHtmlElement(document().documentElement())
    345             && document().body() == node()
    346             && document().documentElement()->renderer()->style()->overflowX() == OVISIBLE) {
    347             boxHasOverflowClip = false;
    348         } else {
    349             boxHasOverflowClip = true;
    350             if (!hasOverflowClip()) {
    351                 // If we are getting an overflow clip, preemptively erase any overflowing content.
    352                 // FIXME: This should probably consult RenderOverflow.
    353                 repaint();
    354             }
    355         }
    356     }
    357     setHasOverflowClip(boxHasOverflowClip);
    358 
    359     setHasTransform(styleToUse->hasTransformRelatedProperty());
    360     setHasReflection(styleToUse->boxReflect());
    361 }
    362 
    363 void RenderBox::layout()
    364 {
    365     ASSERT(needsLayout());
    366 
    367     LayoutRectRecorder recorder(*this);
    368 
    369     RenderObject* child = firstChild();
    370     if (!child) {
    371         clearNeedsLayout();
    372         return;
    373     }
    374 
    375     LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
    376     while (child) {
    377         child->layoutIfNeeded();
    378         ASSERT(!child->needsLayout());
    379         child = child->nextSibling();
    380     }
    381     statePusher.pop();
    382     invalidateBackgroundObscurationStatus();
    383     clearNeedsLayout();
    384 }
    385 
    386 // More IE extensions.  clientWidth and clientHeight represent the interior of an object
    387 // excluding border and scrollbar.
    388 LayoutUnit RenderBox::clientWidth() const
    389 {
    390     return width() - borderLeft() - borderRight() - verticalScrollbarWidth();
    391 }
    392 
    393 LayoutUnit RenderBox::clientHeight() const
    394 {
    395     return height() - borderTop() - borderBottom() - horizontalScrollbarHeight();
    396 }
    397 
    398 int RenderBox::pixelSnappedClientWidth() const
    399 {
    400     return snapSizeToPixel(clientWidth(), x() + clientLeft());
    401 }
    402 
    403 int RenderBox::pixelSnappedClientHeight() const
    404 {
    405     return snapSizeToPixel(clientHeight(), y() + clientTop());
    406 }
    407 
    408 int RenderBox::pixelSnappedOffsetWidth() const
    409 {
    410     return snapSizeToPixel(offsetWidth(), x() + clientLeft());
    411 }
    412 
    413 int RenderBox::pixelSnappedOffsetHeight() const
    414 {
    415     return snapSizeToPixel(offsetHeight(), y() + clientTop());
    416 }
    417 
    418 bool RenderBox::canDetermineWidthWithoutLayout() const
    419 {
    420     // FIXME: This optimization is incorrect as written.
    421     // We need to be able to opt-in to this behavior only when
    422     // it's guarentted correct.
    423     // Until then disabling this optimization to be safe.
    424     return false;
    425 
    426     // FIXME: There are likely many subclasses of RenderBlockFlow which
    427     // cannot determine their layout just from style!
    428     // Perhaps we should create a "PlainRenderBlockFlow"
    429     // and move this optimization there?
    430     if (!isRenderBlockFlow()
    431         // Flexbox items can be expanded beyond their width.
    432         || isFlexItemIncludingDeprecated()
    433         // Table Layout controls cell size and can expand beyond width.
    434         || isTableCell())
    435         return false;
    436 
    437     RenderStyle* style = this->style();
    438     return style->width().isFixed()
    439         && style->minWidth().isFixed()
    440         && (style->maxWidth().isUndefined() || style->maxWidth().isFixed())
    441         && style->paddingLeft().isFixed()
    442         && style->paddingRight().isFixed()
    443         && style->boxSizing() == CONTENT_BOX;
    444 }
    445 
    446 LayoutUnit RenderBox::fixedOffsetWidth() const
    447 {
    448     ASSERT(canDetermineWidthWithoutLayout());
    449 
    450     RenderStyle* style = this->style();
    451 
    452     LayoutUnit width = std::max(LayoutUnit(style->minWidth().value()), LayoutUnit(style->width().value()));
    453     if (style->maxWidth().isFixed())
    454         width = std::min(LayoutUnit(style->maxWidth().value()), width);
    455 
    456     LayoutUnit borderLeft = style->borderLeft().nonZero() ? style->borderLeft().width() : 0;
    457     LayoutUnit borderRight = style->borderRight().nonZero() ? style->borderRight().width() : 0;
    458 
    459     return width + borderLeft + borderRight + style->paddingLeft().value() + style->paddingRight().value();
    460 }
    461 
    462 int RenderBox::scrollWidth() const
    463 {
    464     if (hasOverflowClip())
    465         return layer()->scrollableArea()->scrollWidth();
    466     // For objects with visible overflow, this matches IE.
    467     // FIXME: Need to work right with writing modes.
    468     if (style()->isLeftToRightDirection())
    469         return snapSizeToPixel(max(clientWidth(), layoutOverflowRect().maxX() - borderLeft()), x() + clientLeft());
    470     return clientWidth() - min<LayoutUnit>(0, layoutOverflowRect().x() - borderLeft());
    471 }
    472 
    473 int RenderBox::scrollHeight() const
    474 {
    475     if (hasOverflowClip())
    476         return layer()->scrollableArea()->scrollHeight();
    477     // For objects with visible overflow, this matches IE.
    478     // FIXME: Need to work right with writing modes.
    479     return snapSizeToPixel(max(clientHeight(), layoutOverflowRect().maxY() - borderTop()), y() + clientTop());
    480 }
    481 
    482 int RenderBox::scrollLeft() const
    483 {
    484     return hasOverflowClip() ? layer()->scrollableArea()->scrollXOffset() : 0;
    485 }
    486 
    487 int RenderBox::scrollTop() const
    488 {
    489     return hasOverflowClip() ? layer()->scrollableArea()->scrollYOffset() : 0;
    490 }
    491 
    492 void RenderBox::setScrollLeft(int newLeft)
    493 {
    494     if (hasOverflowClip())
    495         layer()->scrollableArea()->scrollToXOffset(newLeft, ScrollOffsetClamped);
    496 }
    497 
    498 void RenderBox::setScrollTop(int newTop)
    499 {
    500     if (hasOverflowClip())
    501         layer()->scrollableArea()->scrollToYOffset(newTop, ScrollOffsetClamped);
    502 }
    503 
    504 void RenderBox::scrollToOffset(const IntSize& offset)
    505 {
    506     ASSERT(hasOverflowClip());
    507     layer()->scrollableArea()->scrollToOffset(offset, ScrollOffsetClamped);
    508 }
    509 
    510 static inline bool frameElementAndViewPermitScroll(HTMLFrameElementBase* frameElementBase, FrameView* frameView)
    511 {
    512     // If scrollbars aren't explicitly forbidden, permit scrolling.
    513     if (frameElementBase && frameElementBase->scrollingMode() != ScrollbarAlwaysOff)
    514         return true;
    515 
    516     // If scrollbars are forbidden, user initiated scrolls should obviously be ignored.
    517     if (frameView->wasScrolledByUser())
    518         return false;
    519 
    520     // Forbid autoscrolls when scrollbars are off, but permits other programmatic scrolls,
    521     // like navigation to an anchor.
    522     Page* page = frameView->frame().page();
    523     if (!page)
    524         return false;
    525     return !page->autoscrollController().autoscrollInProgress();
    526 }
    527 
    528 void RenderBox::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
    529 {
    530     RenderBox* parentBox = 0;
    531     LayoutRect newRect = rect;
    532 
    533     bool restrictedByLineClamp = false;
    534     if (parent()) {
    535         parentBox = parent()->enclosingBox();
    536         restrictedByLineClamp = !parent()->style()->lineClamp().isNone();
    537     }
    538 
    539     if (hasOverflowClip() && !restrictedByLineClamp) {
    540         // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property.
    541         // This will prevent us from revealing text hidden by the slider in Safari RSS.
    542         newRect = layer()->scrollableArea()->exposeRect(rect, alignX, alignY);
    543     } else if (!parentBox && canBeProgramaticallyScrolled()) {
    544         if (FrameView* frameView = this->frameView()) {
    545             Element* ownerElement = document().ownerElement();
    546 
    547             if (ownerElement && ownerElement->renderer()) {
    548                 HTMLFrameElementBase* frameElementBase = 0;
    549 
    550                 if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))
    551                     frameElementBase = toHTMLFrameElementBase(ownerElement);
    552 
    553                 if (frameElementAndViewPermitScroll(frameElementBase, frameView)) {
    554                     LayoutRect viewRect = frameView->visibleContentRect();
    555                     LayoutRect exposeRect = ScrollAlignment::getRectToExpose(viewRect, rect, alignX, alignY);
    556 
    557                     int xOffset = roundToInt(exposeRect.x());
    558                     int yOffset = roundToInt(exposeRect.y());
    559                     // Adjust offsets if they're outside of the allowable range.
    560                     xOffset = max(0, min(frameView->contentsWidth(), xOffset));
    561                     yOffset = max(0, min(frameView->contentsHeight(), yOffset));
    562 
    563                     frameView->setScrollPosition(IntPoint(xOffset, yOffset));
    564                     if (frameView->safeToPropagateScrollToParent()) {
    565                         parentBox = ownerElement->renderer()->enclosingBox();
    566                         // FIXME: This doesn't correctly convert the rect to
    567                         // absolute coordinates in the parent.
    568                         newRect.setX(rect.x() - frameView->scrollX() + frameView->x());
    569                         newRect.setY(rect.y() - frameView->scrollY() + frameView->y());
    570                     } else {
    571                         parentBox = 0;
    572                     }
    573                 }
    574             } else {
    575                 LayoutRect viewRect = frameView->visibleContentRect();
    576                 LayoutRect r = ScrollAlignment::getRectToExpose(viewRect, rect, alignX, alignY);
    577                 frameView->setScrollPosition(roundedIntPoint(r.location()));
    578             }
    579         }
    580     }
    581 
    582     if (frame()->page()->autoscrollController().autoscrollInProgress())
    583         parentBox = enclosingScrollableBox();
    584 
    585     if (parentBox)
    586         parentBox->scrollRectToVisible(newRect, alignX, alignY);
    587 }
    588 
    589 void RenderBox::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
    590 {
    591     rects.append(pixelSnappedIntRect(accumulatedOffset, size()));
    592 }
    593 
    594 void RenderBox::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
    595 {
    596     quads.append(localToAbsoluteQuad(FloatRect(0, 0, width(), height()), 0 /* mode */, wasFixed));
    597 }
    598 
    599 void RenderBox::updateLayerTransform()
    600 {
    601     // Transform-origin depends on box size, so we need to update the layer transform after layout.
    602     if (hasLayer())
    603         layer()->updateTransform();
    604 }
    605 
    606 LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb, RenderRegion* region) const
    607 {
    608     RenderStyle* styleToUse = style();
    609     if (!styleToUse->logicalMaxWidth().isUndefined())
    610         logicalWidth = min(logicalWidth, computeLogicalWidthInRegionUsing(MaxSize, styleToUse->logicalMaxWidth(), availableWidth, cb, region));
    611     return max(logicalWidth, computeLogicalWidthInRegionUsing(MinSize, styleToUse->logicalMinWidth(), availableWidth, cb, region));
    612 }
    613 
    614 LayoutUnit RenderBox::constrainLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const
    615 {
    616     RenderStyle* styleToUse = style();
    617     if (!styleToUse->logicalMaxHeight().isUndefined()) {
    618         LayoutUnit maxH = computeLogicalHeightUsing(styleToUse->logicalMaxHeight(), intrinsicContentHeight);
    619         if (maxH != -1)
    620             logicalHeight = min(logicalHeight, maxH);
    621     }
    622     return max(logicalHeight, computeLogicalHeightUsing(styleToUse->logicalMinHeight(), intrinsicContentHeight));
    623 }
    624 
    625 LayoutUnit RenderBox::constrainContentBoxLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const
    626 {
    627     RenderStyle* styleToUse = style();
    628     if (!styleToUse->logicalMaxHeight().isUndefined()) {
    629         LayoutUnit maxH = computeContentLogicalHeight(styleToUse->logicalMaxHeight(), intrinsicContentHeight);
    630         if (maxH != -1)
    631             logicalHeight = min(logicalHeight, maxH);
    632     }
    633     return max(logicalHeight, computeContentLogicalHeight(styleToUse->logicalMinHeight(), intrinsicContentHeight));
    634 }
    635 
    636 IntRect RenderBox::absoluteContentBox() const
    637 {
    638     // This is wrong with transforms and flipped writing modes.
    639     IntRect rect = pixelSnappedIntRect(contentBoxRect());
    640     FloatPoint absPos = localToAbsolute();
    641     rect.move(absPos.x(), absPos.y());
    642     return rect;
    643 }
    644 
    645 FloatQuad RenderBox::absoluteContentQuad() const
    646 {
    647     LayoutRect rect = contentBoxRect();
    648     return localToAbsoluteQuad(FloatRect(rect));
    649 }
    650 
    651 LayoutRect RenderBox::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap) const
    652 {
    653     LayoutRect box = borderBoundingBox();
    654     adjustRectForOutlineAndShadow(box);
    655 
    656     if (repaintContainer != this) {
    657         FloatQuad containerRelativeQuad;
    658         if (geometryMap)
    659             containerRelativeQuad = geometryMap->mapToContainer(box, repaintContainer);
    660         else
    661             containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer);
    662 
    663         box = containerRelativeQuad.enclosingBoundingBox();
    664     }
    665 
    666     // FIXME: layoutDelta needs to be applied in parts before/after transforms and
    667     // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
    668     box.move(view()->layoutDelta());
    669 
    670     return box;
    671 }
    672 
    673 void RenderBox::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*)
    674 {
    675     if (!size().isEmpty())
    676         rects.append(pixelSnappedIntRect(additionalOffset, size()));
    677 }
    678 
    679 bool RenderBox::canResize() const
    680 {
    681     // We need a special case for <iframe> because they never have
    682     // hasOverflowClip(). However, they do "implicitly" clip their contents, so
    683     // we want to allow resizing them also.
    684     return (hasOverflowClip() || isRenderIFrame()) && style()->resize() != RESIZE_NONE;
    685 }
    686 
    687 void RenderBox::addLayerHitTestRects(LayerHitTestRects& layerRects, const RenderLayer* currentLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const
    688 {
    689     LayoutPoint adjustedLayerOffset = layerOffset + locationOffset();
    690     RenderBoxModelObject::addLayerHitTestRects(layerRects, currentLayer, adjustedLayerOffset, containerRect);
    691 }
    692 
    693 void RenderBox::computeSelfHitTestRects(Vector<LayoutRect>& rects, const LayoutPoint& layerOffset) const
    694 {
    695     if (!size().isEmpty())
    696         rects.append(LayoutRect(layerOffset, size()));
    697 }
    698 
    699 LayoutRect RenderBox::reflectionBox() const
    700 {
    701     LayoutRect result;
    702     if (!style()->boxReflect())
    703         return result;
    704     LayoutRect box = borderBoxRect();
    705     result = box;
    706     switch (style()->boxReflect()->direction()) {
    707         case ReflectionBelow:
    708             result.move(0, box.height() + reflectionOffset());
    709             break;
    710         case ReflectionAbove:
    711             result.move(0, -box.height() - reflectionOffset());
    712             break;
    713         case ReflectionLeft:
    714             result.move(-box.width() - reflectionOffset(), 0);
    715             break;
    716         case ReflectionRight:
    717             result.move(box.width() + reflectionOffset(), 0);
    718             break;
    719     }
    720     return result;
    721 }
    722 
    723 int RenderBox::reflectionOffset() const
    724 {
    725     if (!style()->boxReflect())
    726         return 0;
    727     RenderView* renderView = view();
    728     if (style()->boxReflect()->direction() == ReflectionLeft || style()->boxReflect()->direction() == ReflectionRight)
    729         return valueForLength(style()->boxReflect()->offset(), borderBoxRect().width(), renderView);
    730     return valueForLength(style()->boxReflect()->offset(), borderBoxRect().height(), renderView);
    731 }
    732 
    733 LayoutRect RenderBox::reflectedRect(const LayoutRect& r) const
    734 {
    735     if (!style()->boxReflect())
    736         return LayoutRect();
    737 
    738     LayoutRect box = borderBoxRect();
    739     LayoutRect result = r;
    740     switch (style()->boxReflect()->direction()) {
    741         case ReflectionBelow:
    742             result.setY(box.maxY() + reflectionOffset() + (box.maxY() - r.maxY()));
    743             break;
    744         case ReflectionAbove:
    745             result.setY(box.y() - reflectionOffset() - box.height() + (box.maxY() - r.maxY()));
    746             break;
    747         case ReflectionLeft:
    748             result.setX(box.x() - reflectionOffset() - box.width() + (box.maxX() - r.maxX()));
    749             break;
    750         case ReflectionRight:
    751             result.setX(box.maxX() + reflectionOffset() + (box.maxX() - r.maxX()));
    752             break;
    753     }
    754     return result;
    755 }
    756 
    757 int RenderBox::verticalScrollbarWidth() const
    758 {
    759     if (!hasOverflowClip() || style()->overflowY() == OOVERLAY)
    760         return 0;
    761 
    762     return layer()->scrollableArea()->verticalScrollbarWidth();
    763 }
    764 
    765 int RenderBox::horizontalScrollbarHeight() const
    766 {
    767     if (!hasOverflowClip() || style()->overflowX() == OOVERLAY)
    768         return 0;
    769 
    770     return layer()->scrollableArea()->horizontalScrollbarHeight();
    771 }
    772 
    773 int RenderBox::instrinsicScrollbarLogicalWidth() const
    774 {
    775     if (!hasOverflowClip())
    776         return 0;
    777 
    778     if (isHorizontalWritingMode() && style()->overflowY() == OSCROLL) {
    779         ASSERT(layer()->scrollableArea() && layer()->scrollableArea()->hasVerticalScrollbar());
    780         return verticalScrollbarWidth();
    781     }
    782 
    783     if (!isHorizontalWritingMode() && style()->overflowX() == OSCROLL) {
    784         ASSERT(layer()->scrollableArea() && layer()->scrollableArea()->hasHorizontalScrollbar());
    785         return horizontalScrollbarHeight();
    786     }
    787 
    788     return 0;
    789 }
    790 
    791 bool RenderBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
    792 {
    793     // Logical scroll is a higher level concept, all directions by here must be physical
    794     ASSERT(!isLogical(direction));
    795 
    796     if (!layer() || !layer()->scrollableArea())
    797         return false;
    798 
    799     return layer()->scrollableArea()->scroll(direction, granularity, multiplier);
    800 }
    801 
    802 bool RenderBox::canBeScrolledAndHasScrollableArea() const
    803 {
    804     return canBeProgramaticallyScrolled() && (scrollHeight() != clientHeight() || scrollWidth() != clientWidth());
    805 }
    806 
    807 bool RenderBox::canBeProgramaticallyScrolled() const
    808 {
    809     Node* node = this->node();
    810     if (node && node->isDocumentNode())
    811         return true;
    812 
    813     if (!hasOverflowClip())
    814         return false;
    815 
    816     bool hasScrollableOverflow = hasScrollableOverflowX() || hasScrollableOverflowY();
    817     if (scrollsOverflow() && hasScrollableOverflow)
    818         return true;
    819 
    820     return node && node->rendererIsEditable();
    821 }
    822 
    823 bool RenderBox::usesCompositedScrolling() const
    824 {
    825     return hasOverflowClip() && hasLayer() && layer()->scrollableArea()->usesCompositedScrolling();
    826 }
    827 
    828 void RenderBox::autoscroll(const IntPoint& position)
    829 {
    830     Frame* frame = this->frame();
    831     if (!frame)
    832         return;
    833 
    834     FrameView* frameView = frame->view();
    835     if (!frameView)
    836         return;
    837 
    838     IntPoint currentDocumentPosition = frameView->windowToContents(position);
    839     scrollRectToVisible(LayoutRect(currentDocumentPosition, LayoutSize(1, 1)), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
    840 }
    841 
    842 bool RenderBox::autoscrollInProgress() const
    843 {
    844     return frame() && frame()->page() && frame()->page()->autoscrollController().autoscrollInProgress(this);
    845 }
    846 
    847 // There are two kinds of renderer that can autoscroll.
    848 bool RenderBox::canAutoscroll() const
    849 {
    850     if (node() && node()->isDocumentNode())
    851         return view()->frameView()->isScrollable();
    852 
    853     // Check for a box that can be scrolled in its own right.
    854     return canBeScrolledAndHasScrollableArea();
    855 }
    856 
    857 // If specified point is in border belt, returned offset denotes direction of
    858 // scrolling.
    859 IntSize RenderBox::calculateAutoscrollDirection(const IntPoint& windowPoint) const
    860 {
    861     if (!frame())
    862         return IntSize();
    863 
    864     FrameView* frameView = frame()->view();
    865     if (!frameView)
    866         return IntSize();
    867 
    868     IntRect box(absoluteBoundingBoxRect());
    869     box.move(view()->frameView()->scrollOffset());
    870     IntRect windowBox = view()->frameView()->contentsToWindow(box);
    871 
    872     IntPoint windowAutoscrollPoint = windowPoint;
    873 
    874     if (windowAutoscrollPoint.x() < windowBox.x() + autoscrollBeltSize)
    875         windowAutoscrollPoint.move(-autoscrollBeltSize, 0);
    876     else if (windowAutoscrollPoint.x() > windowBox.maxX() - autoscrollBeltSize)
    877         windowAutoscrollPoint.move(autoscrollBeltSize, 0);
    878 
    879     if (windowAutoscrollPoint.y() < windowBox.y() + autoscrollBeltSize)
    880         windowAutoscrollPoint.move(0, -autoscrollBeltSize);
    881     else if (windowAutoscrollPoint.y() > windowBox.maxY() - autoscrollBeltSize)
    882         windowAutoscrollPoint.move(0, autoscrollBeltSize);
    883 
    884     return windowAutoscrollPoint - windowPoint;
    885 }
    886 
    887 RenderBox* RenderBox::findAutoscrollable(RenderObject* renderer)
    888 {
    889     while (renderer && !(renderer->isBox() && toRenderBox(renderer)->canAutoscroll())) {
    890         if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document().ownerElement())
    891             renderer = renderer->document().ownerElement()->renderer();
    892         else
    893             renderer = renderer->parent();
    894     }
    895 
    896     return renderer && renderer->isBox() ? toRenderBox(renderer) : 0;
    897 }
    898 
    899 static inline int adjustedScrollDelta(int beginningDelta)
    900 {
    901     // This implemention matches Firefox's.
    902     // http://mxr.mozilla.org/firefox/source/toolkit/content/widgets/browser.xml#856.
    903     const int speedReducer = 12;
    904 
    905     int adjustedDelta = beginningDelta / speedReducer;
    906     if (adjustedDelta > 1)
    907         adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(adjustedDelta))) - 1;
    908     else if (adjustedDelta < -1)
    909         adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(-adjustedDelta))) + 1;
    910 
    911     return adjustedDelta;
    912 }
    913 
    914 static inline IntSize adjustedScrollDelta(const IntSize& delta)
    915 {
    916     return IntSize(adjustedScrollDelta(delta.width()), adjustedScrollDelta(delta.height()));
    917 }
    918 
    919 void RenderBox::panScroll(const IntPoint& sourcePoint)
    920 {
    921     Frame* frame = this->frame();
    922     if (!frame)
    923         return;
    924 
    925     IntPoint lastKnownMousePosition = frame->eventHandler().lastKnownMousePosition();
    926 
    927     // We need to check if the last known mouse position is out of the window. When the mouse is out of the window, the position is incoherent
    928     static IntPoint previousMousePosition;
    929     if (lastKnownMousePosition.x() < 0 || lastKnownMousePosition.y() < 0)
    930         lastKnownMousePosition = previousMousePosition;
    931     else
    932         previousMousePosition = lastKnownMousePosition;
    933 
    934     IntSize delta = lastKnownMousePosition - sourcePoint;
    935 
    936     if (abs(delta.width()) <= ScrollView::noPanScrollRadius) // at the center we let the space for the icon
    937         delta.setWidth(0);
    938     if (abs(delta.height()) <= ScrollView::noPanScrollRadius)
    939         delta.setHeight(0);
    940 
    941     scrollByRecursively(adjustedScrollDelta(delta), ScrollOffsetClamped);
    942 }
    943 
    944 void RenderBox::scrollByRecursively(const IntSize& delta, ScrollOffsetClamping clamp)
    945 {
    946     if (delta.isZero())
    947         return;
    948 
    949     bool restrictedByLineClamp = false;
    950     if (parent())
    951         restrictedByLineClamp = !parent()->style()->lineClamp().isNone();
    952 
    953     if (hasOverflowClip() && !restrictedByLineClamp) {
    954         IntSize newScrollOffset = layer()->scrollableArea()->adjustedScrollOffset() + delta;
    955         layer()->scrollableArea()->scrollToOffset(newScrollOffset, clamp);
    956 
    957         // If this layer can't do the scroll we ask the next layer up that can scroll to try
    958         IntSize remainingScrollOffset = newScrollOffset - layer()->scrollableArea()->adjustedScrollOffset();
    959         if (!remainingScrollOffset.isZero() && parent()) {
    960             if (RenderBox* scrollableBox = enclosingScrollableBox())
    961                 scrollableBox->scrollByRecursively(remainingScrollOffset, clamp);
    962 
    963             Frame* frame = this->frame();
    964             if (frame && frame->page())
    965                 frame->page()->autoscrollController().updateAutoscrollRenderer();
    966         }
    967     } else if (view()->frameView()) {
    968         // If we are here, we were called on a renderer that can be programmatically scrolled, but doesn't
    969         // have an overflow clip. Which means that it is a document node that can be scrolled.
    970         view()->frameView()->scrollBy(delta);
    971 
    972         // FIXME: If we didn't scroll the whole way, do we want to try looking at the frames ownerElement?
    973         // https://bugs.webkit.org/show_bug.cgi?id=28237
    974     }
    975 }
    976 
    977 bool RenderBox::needsPreferredWidthsRecalculation() const
    978 {
    979     return style()->paddingStart().isPercent() || style()->paddingEnd().isPercent();
    980 }
    981 
    982 IntSize RenderBox::scrolledContentOffset() const
    983 {
    984     ASSERT(hasOverflowClip());
    985     ASSERT(hasLayer());
    986     return layer()->scrollableArea()->scrollOffset();
    987 }
    988 
    989 LayoutSize RenderBox::cachedSizeForOverflowClip() const
    990 {
    991     ASSERT(hasOverflowClip());
    992     ASSERT(hasLayer());
    993     return layer()->size();
    994 }
    995 
    996 void RenderBox::applyCachedClipAndScrollOffsetForRepaint(LayoutRect& paintRect) const
    997 {
    998     paintRect.move(-scrolledContentOffset()); // For overflow:auto/scroll/hidden.
    999 
   1000     // Do not clip scroll layer contents to reduce the number of repaints while scrolling.
   1001     if (usesCompositedScrolling())
   1002         return;
   1003 
   1004     // height() is inaccurate if we're in the middle of a layout of this RenderBox, so use the
   1005     // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
   1006     // anyway if its size does change.
   1007     LayoutRect clipRect(LayoutPoint(), cachedSizeForOverflowClip());
   1008     paintRect = intersection(paintRect, clipRect);
   1009 }
   1010 
   1011 void RenderBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
   1012 {
   1013     minLogicalWidth = minPreferredLogicalWidth() - borderAndPaddingLogicalWidth();
   1014     maxLogicalWidth = maxPreferredLogicalWidth() - borderAndPaddingLogicalWidth();
   1015 }
   1016 
   1017 LayoutUnit RenderBox::minPreferredLogicalWidth() const
   1018 {
   1019     if (preferredLogicalWidthsDirty()) {
   1020 #ifndef NDEBUG
   1021         SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox*>(this));
   1022 #endif
   1023         const_cast<RenderBox*>(this)->computePreferredLogicalWidths();
   1024     }
   1025 
   1026     return m_minPreferredLogicalWidth;
   1027 }
   1028 
   1029 LayoutUnit RenderBox::maxPreferredLogicalWidth() const
   1030 {
   1031     if (preferredLogicalWidthsDirty()) {
   1032 #ifndef NDEBUG
   1033         SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox*>(this));
   1034 #endif
   1035         const_cast<RenderBox*>(this)->computePreferredLogicalWidths();
   1036     }
   1037 
   1038     return m_maxPreferredLogicalWidth;
   1039 }
   1040 
   1041 bool RenderBox::hasOverrideHeight() const
   1042 {
   1043     return gOverrideHeightMap && gOverrideHeightMap->contains(this);
   1044 }
   1045 
   1046 bool RenderBox::hasOverrideWidth() const
   1047 {
   1048     return gOverrideWidthMap && gOverrideWidthMap->contains(this);
   1049 }
   1050 
   1051 void RenderBox::setOverrideLogicalContentHeight(LayoutUnit height)
   1052 {
   1053     if (!gOverrideHeightMap)
   1054         gOverrideHeightMap = new OverrideSizeMap();
   1055     gOverrideHeightMap->set(this, height);
   1056 }
   1057 
   1058 void RenderBox::setOverrideLogicalContentWidth(LayoutUnit width)
   1059 {
   1060     if (!gOverrideWidthMap)
   1061         gOverrideWidthMap = new OverrideSizeMap();
   1062     gOverrideWidthMap->set(this, width);
   1063 }
   1064 
   1065 void RenderBox::clearOverrideLogicalContentHeight()
   1066 {
   1067     if (gOverrideHeightMap)
   1068         gOverrideHeightMap->remove(this);
   1069 }
   1070 
   1071 void RenderBox::clearOverrideLogicalContentWidth()
   1072 {
   1073     if (gOverrideWidthMap)
   1074         gOverrideWidthMap->remove(this);
   1075 }
   1076 
   1077 void RenderBox::clearOverrideSize()
   1078 {
   1079     clearOverrideLogicalContentHeight();
   1080     clearOverrideLogicalContentWidth();
   1081 }
   1082 
   1083 LayoutUnit RenderBox::overrideLogicalContentWidth() const
   1084 {
   1085     ASSERT(hasOverrideWidth());
   1086     return gOverrideWidthMap->get(this);
   1087 }
   1088 
   1089 LayoutUnit RenderBox::overrideLogicalContentHeight() const
   1090 {
   1091     ASSERT(hasOverrideHeight());
   1092     return gOverrideHeightMap->get(this);
   1093 }
   1094 
   1095 LayoutUnit RenderBox::overrideContainingBlockContentLogicalWidth() const
   1096 {
   1097     ASSERT(hasOverrideContainingBlockLogicalWidth());
   1098     return gOverrideContainingBlockLogicalWidthMap->get(this);
   1099 }
   1100 
   1101 LayoutUnit RenderBox::overrideContainingBlockContentLogicalHeight() const
   1102 {
   1103     ASSERT(hasOverrideContainingBlockLogicalHeight());
   1104     return gOverrideContainingBlockLogicalHeightMap->get(this);
   1105 }
   1106 
   1107 bool RenderBox::hasOverrideContainingBlockLogicalWidth() const
   1108 {
   1109     return gOverrideContainingBlockLogicalWidthMap && gOverrideContainingBlockLogicalWidthMap->contains(this);
   1110 }
   1111 
   1112 bool RenderBox::hasOverrideContainingBlockLogicalHeight() const
   1113 {
   1114     return gOverrideContainingBlockLogicalHeightMap && gOverrideContainingBlockLogicalHeightMap->contains(this);
   1115 }
   1116 
   1117 void RenderBox::setOverrideContainingBlockContentLogicalWidth(LayoutUnit logicalWidth)
   1118 {
   1119     if (!gOverrideContainingBlockLogicalWidthMap)
   1120         gOverrideContainingBlockLogicalWidthMap = new OverrideSizeMap;
   1121     gOverrideContainingBlockLogicalWidthMap->set(this, logicalWidth);
   1122 }
   1123 
   1124 void RenderBox::setOverrideContainingBlockContentLogicalHeight(LayoutUnit logicalHeight)
   1125 {
   1126     if (!gOverrideContainingBlockLogicalHeightMap)
   1127         gOverrideContainingBlockLogicalHeightMap = new OverrideSizeMap;
   1128     gOverrideContainingBlockLogicalHeightMap->set(this, logicalHeight);
   1129 }
   1130 
   1131 void RenderBox::clearContainingBlockOverrideSize()
   1132 {
   1133     if (gOverrideContainingBlockLogicalWidthMap)
   1134         gOverrideContainingBlockLogicalWidthMap->remove(this);
   1135     clearOverrideContainingBlockContentLogicalHeight();
   1136 }
   1137 
   1138 void RenderBox::clearOverrideContainingBlockContentLogicalHeight()
   1139 {
   1140     if (gOverrideContainingBlockLogicalHeightMap)
   1141         gOverrideContainingBlockLogicalHeightMap->remove(this);
   1142 }
   1143 
   1144 LayoutUnit RenderBox::adjustBorderBoxLogicalWidthForBoxSizing(LayoutUnit width) const
   1145 {
   1146     LayoutUnit bordersPlusPadding = borderAndPaddingLogicalWidth();
   1147     if (style()->boxSizing() == CONTENT_BOX)
   1148         return width + bordersPlusPadding;
   1149     return max(width, bordersPlusPadding);
   1150 }
   1151 
   1152 LayoutUnit RenderBox::adjustBorderBoxLogicalHeightForBoxSizing(LayoutUnit height) const
   1153 {
   1154     LayoutUnit bordersPlusPadding = borderAndPaddingLogicalHeight();
   1155     if (style()->boxSizing() == CONTENT_BOX)
   1156         return height + bordersPlusPadding;
   1157     return max(height, bordersPlusPadding);
   1158 }
   1159 
   1160 LayoutUnit RenderBox::adjustContentBoxLogicalWidthForBoxSizing(LayoutUnit width) const
   1161 {
   1162     if (style()->boxSizing() == BORDER_BOX)
   1163         width -= borderAndPaddingLogicalWidth();
   1164     return max<LayoutUnit>(0, width);
   1165 }
   1166 
   1167 LayoutUnit RenderBox::adjustContentBoxLogicalHeightForBoxSizing(LayoutUnit height) const
   1168 {
   1169     if (style()->boxSizing() == BORDER_BOX)
   1170         height -= borderAndPaddingLogicalHeight();
   1171     return max<LayoutUnit>(0, height);
   1172 }
   1173 
   1174 // Hit Testing
   1175 bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
   1176 {
   1177     LayoutPoint adjustedLocation = accumulatedOffset + location();
   1178 
   1179     // Check kids first.
   1180     for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
   1181         if (!child->hasLayer() && child->nodeAtPoint(request, result, locationInContainer, adjustedLocation, action)) {
   1182             updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
   1183             return true;
   1184         }
   1185     }
   1186 
   1187     // Check our bounds next. For this purpose always assume that we can only be hit in the
   1188     // foreground phase (which is true for replaced elements like images).
   1189     LayoutRect boundsRect = borderBoxRectInRegion(locationInContainer.region());
   1190     boundsRect.moveBy(adjustedLocation);
   1191     if (visibleToHitTestRequest(request) && action == HitTestForeground && locationInContainer.intersects(boundsRect)) {
   1192         updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
   1193         if (!result.addNodeToRectBasedTestResult(node(), request, locationInContainer, boundsRect))
   1194             return true;
   1195     }
   1196 
   1197     return false;
   1198 }
   1199 
   1200 // --------------------- painting stuff -------------------------------
   1201 
   1202 void RenderBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
   1203 {
   1204     LayoutPoint adjustedPaintOffset = paintOffset + location();
   1205     // default implementation. Just pass paint through to the children
   1206     PaintInfo childInfo(paintInfo);
   1207     childInfo.updatePaintingRootForChildren(this);
   1208     for (RenderObject* child = firstChild(); child; child = child->nextSibling())
   1209         child->paint(childInfo, adjustedPaintOffset);
   1210 }
   1211 
   1212 void RenderBox::paintRootBoxFillLayers(const PaintInfo& paintInfo)
   1213 {
   1214     if (paintInfo.skipRootBackground())
   1215         return;
   1216 
   1217     RenderObject* rootBackgroundRenderer = rendererForRootBackground();
   1218 
   1219     const FillLayer* bgLayer = rootBackgroundRenderer->style()->backgroundLayers();
   1220     Color bgColor = rootBackgroundRenderer->resolveColor(CSSPropertyBackgroundColor);
   1221 
   1222     paintFillLayers(paintInfo, bgColor, bgLayer, view()->backgroundRect(this), BackgroundBleedNone, CompositeSourceOver, rootBackgroundRenderer);
   1223 }
   1224 
   1225 BackgroundBleedAvoidance RenderBox::determineBackgroundBleedAvoidance(GraphicsContext* context) const
   1226 {
   1227     if (context->paintingDisabled())
   1228         return BackgroundBleedNone;
   1229 
   1230     const RenderStyle* style = this->style();
   1231 
   1232     if (!style->hasBackground() || !style->hasBorder() || !style->hasBorderRadius() || borderImageIsLoadedAndCanBeRendered())
   1233         return BackgroundBleedNone;
   1234 
   1235     AffineTransform ctm = context->getCTM();
   1236     FloatSize contextScaling(static_cast<float>(ctm.xScale()), static_cast<float>(ctm.yScale()));
   1237 
   1238     // Because RoundedRect uses IntRect internally the inset applied by the
   1239     // BackgroundBleedShrinkBackground strategy cannot be less than one integer
   1240     // layout coordinate, even with subpixel layout enabled. To take that into
   1241     // account, we clamp the contextScaling to 1.0 for the following test so
   1242     // that borderObscuresBackgroundEdge can only return true if the border
   1243     // widths are greater than 2 in both layout coordinates and screen
   1244     // coordinates.
   1245     // This precaution will become obsolete if RoundedRect is ever promoted to
   1246     // a sub-pixel representation.
   1247     if (contextScaling.width() > 1)
   1248         contextScaling.setWidth(1);
   1249     if (contextScaling.height() > 1)
   1250         contextScaling.setHeight(1);
   1251 
   1252     if (borderObscuresBackgroundEdge(contextScaling))
   1253         return BackgroundBleedShrinkBackground;
   1254     if (!style->hasAppearance() && borderObscuresBackground() && backgroundHasOpaqueTopLayer())
   1255         return BackgroundBleedBackgroundOverBorder;
   1256 
   1257     return BackgroundBleedUseTransparencyLayer;
   1258 }
   1259 
   1260 void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
   1261 {
   1262     if (!paintInfo.shouldPaintWithinRoot(this))
   1263         return;
   1264 
   1265     LayoutRect paintRect = borderBoxRectInRegion(paintInfo.renderRegion);
   1266     paintRect.moveBy(paintOffset);
   1267     paintBoxDecorationsWithRect(paintInfo, paintOffset, paintRect);
   1268 }
   1269 
   1270 void RenderBox::paintBoxDecorationsWithRect(PaintInfo& paintInfo, const LayoutPoint& paintOffset, const LayoutRect& paintRect)
   1271 {
   1272     BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context);
   1273 
   1274     // FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have
   1275     // custom shadows of their own.
   1276     if (!boxShadowShouldBeAppliedToBackground(bleedAvoidance))
   1277         paintBoxShadow(paintInfo, paintRect, style(), Normal);
   1278 
   1279     GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
   1280     if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) {
   1281         // To avoid the background color bleeding out behind the border, we'll render background and border
   1282         // into a transparency layer, and then clip that in one go (which requires setting up the clip before
   1283         // beginning the layer).
   1284         RoundedRect border = style()->getRoundedBorderFor(paintRect, view());
   1285         stateSaver.save();
   1286         paintInfo.context->clipRoundedRect(border);
   1287         paintInfo.context->beginTransparencyLayer(1);
   1288     }
   1289 
   1290     paintBackgroundWithBorderAndBoxShadow(paintInfo, paintRect, bleedAvoidance);
   1291 
   1292     if (bleedAvoidance == BackgroundBleedUseTransparencyLayer)
   1293         paintInfo.context->endLayer();
   1294 }
   1295 
   1296 void RenderBox::paintBackgroundWithBorderAndBoxShadow(PaintInfo& paintInfo, const LayoutRect& paintRect, BackgroundBleedAvoidance bleedAvoidance)
   1297 {
   1298     // If we have a native theme appearance, paint that before painting our background.
   1299     // The theme will tell us whether or not we should also paint the CSS background.
   1300     IntRect snappedPaintRect(pixelSnappedIntRect(paintRect));
   1301     bool themePainted = style()->hasAppearance() && !RenderTheme::theme().paint(this, paintInfo, snappedPaintRect);
   1302     if (!themePainted) {
   1303         if (bleedAvoidance == BackgroundBleedBackgroundOverBorder)
   1304             paintBorder(paintInfo, paintRect, style(), bleedAvoidance);
   1305 
   1306         paintBackground(paintInfo, paintRect, bleedAvoidance);
   1307 
   1308         if (style()->hasAppearance())
   1309             RenderTheme::theme().paintDecorations(this, paintInfo, snappedPaintRect);
   1310     }
   1311     paintBoxShadow(paintInfo, paintRect, style(), Inset);
   1312 
   1313     // The theme will tell us whether or not we should also paint the CSS border.
   1314     if (bleedAvoidance != BackgroundBleedBackgroundOverBorder && (!style()->hasAppearance() || (!themePainted && RenderTheme::theme().paintBorderOnly(this, paintInfo, snappedPaintRect))) && style()->hasBorder() && !(isTable() && toRenderTable(this)->collapseBorders()))
   1315         paintBorder(paintInfo, paintRect, style(), bleedAvoidance);
   1316 }
   1317 
   1318 void RenderBox::paintBackground(const PaintInfo& paintInfo, const LayoutRect& paintRect, BackgroundBleedAvoidance bleedAvoidance)
   1319 {
   1320     if (isRoot()) {
   1321         paintRootBoxFillLayers(paintInfo);
   1322         return;
   1323     }
   1324     if (isBody() && skipBodyBackground(this))
   1325         return;
   1326     if (backgroundIsKnownToBeObscured())
   1327         return;
   1328     paintFillLayers(paintInfo, resolveColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect, bleedAvoidance);
   1329 }
   1330 
   1331 LayoutRect RenderBox::backgroundPaintedExtent() const
   1332 {
   1333     ASSERT(hasBackground());
   1334     LayoutRect backgroundRect = pixelSnappedIntRect(borderBoxRect());
   1335 
   1336     Color backgroundColor = resolveColor(CSSPropertyBackgroundColor);
   1337     if (backgroundColor.isValid() && backgroundColor.alpha())
   1338         return backgroundRect;
   1339     if (!style()->backgroundLayers()->image() || style()->backgroundLayers()->next())
   1340         return backgroundRect;
   1341     BackgroundImageGeometry geometry;
   1342     const_cast<RenderBox*>(this)->calculateBackgroundImageGeometry(style()->backgroundLayers(), backgroundRect, geometry);
   1343     return geometry.destRect();
   1344 }
   1345 
   1346 bool RenderBox::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
   1347 {
   1348     if (isBody() && skipBodyBackground(this))
   1349         return false;
   1350 
   1351     Color backgroundColor = resolveColor(CSSPropertyBackgroundColor);
   1352     if (!backgroundColor.isValid() || backgroundColor.hasAlpha())
   1353         return false;
   1354 
   1355     // If the element has appearance, it might be painted by theme.
   1356     // We cannot be sure if theme paints the background opaque.
   1357     // In this case it is safe to not assume opaqueness.
   1358     // FIXME: May be ask theme if it paints opaque.
   1359     if (style()->hasAppearance())
   1360         return false;
   1361     // FIXME: Check the opaqueness of background images.
   1362 
   1363     // FIXME: Use rounded rect if border radius is present.
   1364     if (style()->hasBorderRadius())
   1365         return false;
   1366     // FIXME: The background color clip is defined by the last layer.
   1367     if (style()->backgroundLayers()->next())
   1368         return false;
   1369     LayoutRect backgroundRect;
   1370     switch (style()->backgroundClip()) {
   1371     case BorderFillBox:
   1372         backgroundRect = borderBoxRect();
   1373         break;
   1374     case PaddingFillBox:
   1375         backgroundRect = paddingBoxRect();
   1376         break;
   1377     case ContentFillBox:
   1378         backgroundRect = contentBoxRect();
   1379         break;
   1380     default:
   1381         break;
   1382     }
   1383     return backgroundRect.contains(localRect);
   1384 }
   1385 
   1386 static bool isCandidateForOpaquenessTest(RenderBox* childBox)
   1387 {
   1388     RenderStyle* childStyle = childBox->style();
   1389     if (childStyle->position() != StaticPosition && childBox->containingBlock() != childBox->parent())
   1390         return false;
   1391     if (childStyle->visibility() != VISIBLE || childStyle->shapeOutside())
   1392         return false;
   1393     if (!childBox->width() || !childBox->height())
   1394         return false;
   1395     if (RenderLayer* childLayer = childBox->layer()) {
   1396         // FIXME: perhaps this could be less conservative?
   1397         if (childLayer->compositingState() != NotComposited)
   1398             return false;
   1399         // FIXME: Deal with z-index.
   1400         if (!childStyle->hasAutoZIndex())
   1401             return false;
   1402         if (childLayer->hasTransform() || childLayer->isTransparent() || childLayer->hasFilter())
   1403             return false;
   1404         if (childBox->hasOverflowClip() && childStyle->hasBorderRadius())
   1405             return false;
   1406     }
   1407     return true;
   1408 }
   1409 
   1410 bool RenderBox::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const
   1411 {
   1412     if (!maxDepthToTest)
   1413         return false;
   1414     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
   1415         if (!child->isBox())
   1416             continue;
   1417         RenderBox* childBox = toRenderBox(child);
   1418         if (!isCandidateForOpaquenessTest(childBox))
   1419             continue;
   1420         LayoutPoint childLocation = childBox->location();
   1421         if (childBox->isRelPositioned())
   1422             childLocation.move(childBox->relativePositionOffset());
   1423         LayoutRect childLocalRect = localRect;
   1424         childLocalRect.moveBy(-childLocation);
   1425         if (childLocalRect.y() < 0 || childLocalRect.x() < 0) {
   1426             // If there is unobscured area above/left of a static positioned box then the rect is probably not covered.
   1427             if (childBox->style()->position() == StaticPosition)
   1428                 return false;
   1429             continue;
   1430         }
   1431         if (childLocalRect.maxY() > childBox->height() || childLocalRect.maxX() > childBox->width())
   1432             continue;
   1433         if (childBox->backgroundIsKnownToBeOpaqueInRect(childLocalRect))
   1434             return true;
   1435         if (childBox->foregroundIsKnownToBeOpaqueInRect(childLocalRect, maxDepthToTest - 1))
   1436             return true;
   1437     }
   1438     return false;
   1439 }
   1440 
   1441 bool RenderBox::computeBackgroundIsKnownToBeObscured()
   1442 {
   1443     // Test to see if the children trivially obscure the background.
   1444     // FIXME: This test can be much more comprehensive.
   1445     if (!hasBackground())
   1446         return false;
   1447     // Table and root background painting is special.
   1448     if (isTable() || isRoot())
   1449         return false;
   1450     // FIXME: box-shadow is painted while background painting.
   1451     if (style()->boxShadow())
   1452         return false;
   1453     LayoutRect backgroundRect = backgroundPaintedExtent();
   1454     return foregroundIsKnownToBeOpaqueInRect(backgroundRect, backgroundObscurationTestMaxDepth);
   1455 }
   1456 
   1457 bool RenderBox::backgroundHasOpaqueTopLayer() const
   1458 {
   1459     const FillLayer* fillLayer = style()->backgroundLayers();
   1460     if (!fillLayer || fillLayer->clip() != BorderFillBox)
   1461         return false;
   1462 
   1463     // Clipped with local scrolling
   1464     if (hasOverflowClip() && fillLayer->attachment() == LocalBackgroundAttachment)
   1465         return false;
   1466 
   1467     if (fillLayer->hasOpaqueImage(this) && fillLayer->hasRepeatXY() && fillLayer->image()->canRender(this, style()->effectiveZoom()))
   1468         return true;
   1469 
   1470     // If there is only one layer and no image, check whether the background color is opaque
   1471     if (!fillLayer->next() && !fillLayer->hasImage()) {
   1472         Color bgColor = resolveColor(CSSPropertyBackgroundColor);
   1473         if (bgColor.isValid() && bgColor.alpha() == 255)
   1474             return true;
   1475     }
   1476 
   1477     return false;
   1478 }
   1479 
   1480 void RenderBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
   1481 {
   1482     if (!paintInfo.shouldPaintWithinRoot(this) || style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask || paintInfo.context->paintingDisabled())
   1483         return;
   1484 
   1485     LayoutRect paintRect = LayoutRect(paintOffset, size());
   1486     paintMaskImages(paintInfo, paintRect);
   1487 }
   1488 
   1489 void RenderBox::paintClippingMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
   1490 {
   1491     if (!paintInfo.shouldPaintWithinRoot(this) || style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseClippingMask || paintInfo.context->paintingDisabled())
   1492         return;
   1493 
   1494     if (!layer() || layer()->compositingState() != PaintsIntoOwnBacking)
   1495         return;
   1496 
   1497     // We should never have this state in this function. A layer with a mask
   1498     // should have always created its own backing if it became composited.
   1499     ASSERT(layer()->compositingState() != HasOwnBackingButPaintsIntoAncestor);
   1500 
   1501     LayoutRect paintRect = LayoutRect(paintOffset, size());
   1502     paintInfo.context->fillRect(pixelSnappedIntRect(paintRect), Color::black);
   1503 }
   1504 
   1505 void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& paintRect)
   1506 {
   1507     // Figure out if we need to push a transparency layer to render our mask.
   1508     bool pushTransparencyLayer = false;
   1509     bool compositedMask = hasLayer() && layer()->hasCompositedMask();
   1510     bool flattenCompositingLayers = view()->frameView() && view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
   1511     CompositeOperator compositeOp = CompositeSourceOver;
   1512 
   1513     bool allMaskImagesLoaded = true;
   1514 
   1515     if (!compositedMask || flattenCompositingLayers) {
   1516         pushTransparencyLayer = true;
   1517         StyleImage* maskBoxImage = style()->maskBoxImage().image();
   1518         const FillLayer* maskLayers = style()->maskLayers();
   1519 
   1520         // Don't render a masked element until all the mask images have loaded, to prevent a flash of unmasked content.
   1521         if (maskBoxImage)
   1522             allMaskImagesLoaded &= maskBoxImage->isLoaded();
   1523 
   1524         if (maskLayers)
   1525             allMaskImagesLoaded &= maskLayers->imagesAreLoaded();
   1526 
   1527         paintInfo.context->setCompositeOperation(CompositeDestinationIn);
   1528         paintInfo.context->beginTransparencyLayer(1);
   1529         compositeOp = CompositeSourceOver;
   1530     }
   1531 
   1532     if (allMaskImagesLoaded) {
   1533         paintFillLayers(paintInfo, Color(), style()->maskLayers(), paintRect, BackgroundBleedNone, compositeOp);
   1534         paintNinePieceImage(paintInfo.context, paintRect, style(), style()->maskBoxImage(), compositeOp);
   1535     }
   1536 
   1537     if (pushTransparencyLayer)
   1538         paintInfo.context->endLayer();
   1539 }
   1540 
   1541 LayoutRect RenderBox::maskClipRect()
   1542 {
   1543     const NinePieceImage& maskBoxImage = style()->maskBoxImage();
   1544     if (maskBoxImage.image()) {
   1545         LayoutRect borderImageRect = borderBoxRect();
   1546 
   1547         // Apply outsets to the border box.
   1548         borderImageRect.expand(style()->maskBoxImageOutsets());
   1549         return borderImageRect;
   1550     }
   1551 
   1552     LayoutRect result;
   1553     LayoutRect borderBox = borderBoxRect();
   1554     for (const FillLayer* maskLayer = style()->maskLayers(); maskLayer; maskLayer = maskLayer->next()) {
   1555         if (maskLayer->image()) {
   1556             BackgroundImageGeometry geometry;
   1557             calculateBackgroundImageGeometry(maskLayer, borderBox, geometry);
   1558             result.unite(geometry.destRect());
   1559         }
   1560     }
   1561     return result;
   1562 }
   1563 
   1564 void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect,
   1565     BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
   1566 {
   1567     Vector<const FillLayer*, 8> layers;
   1568     const FillLayer* curLayer = fillLayer;
   1569     bool shouldDrawBackgroundInSeparateBuffer = false;
   1570     while (curLayer) {
   1571         layers.append(curLayer);
   1572         // Stop traversal when an opaque layer is encountered.
   1573         // FIXME : It would be possible for the following occlusion culling test to be more aggressive
   1574         // on layers with no repeat by testing whether the image covers the layout rect.
   1575         // Testing that here would imply duplicating a lot of calculations that are currently done in
   1576         // RenderBoxModelObject::paintFillLayerExtended. A more efficient solution might be to move
   1577         // the layer recursion into paintFillLayerExtended, or to compute the layer geometry here
   1578         // and pass it down.
   1579 
   1580         if (!shouldDrawBackgroundInSeparateBuffer && curLayer->blendMode() != blink::WebBlendModeNormal)
   1581             shouldDrawBackgroundInSeparateBuffer = true;
   1582 
   1583         // The clipOccludesNextLayers condition must be evaluated first to avoid short-circuiting.
   1584         if (curLayer->clipOccludesNextLayers(curLayer == fillLayer) && curLayer->hasOpaqueImage(this) && curLayer->image()->canRender(this, style()->effectiveZoom()) && curLayer->hasRepeatXY() && curLayer->blendMode() == blink::WebBlendModeNormal && !boxShadowShouldBeAppliedToBackground(bleedAvoidance))
   1585             break;
   1586         curLayer = curLayer->next();
   1587     }
   1588 
   1589     GraphicsContext* context = paintInfo.context;
   1590     if (!context)
   1591         shouldDrawBackgroundInSeparateBuffer = false;
   1592     if (shouldDrawBackgroundInSeparateBuffer)
   1593         context->beginTransparencyLayer(1);
   1594 
   1595     Vector<const FillLayer*>::const_reverse_iterator topLayer = layers.rend();
   1596     for (Vector<const FillLayer*>::const_reverse_iterator it = layers.rbegin(); it != topLayer; ++it)
   1597         paintFillLayer(paintInfo, c, *it, rect, bleedAvoidance, op, backgroundObject);
   1598 
   1599     if (shouldDrawBackgroundInSeparateBuffer)
   1600         context->endLayer();
   1601 }
   1602 
   1603 void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect,
   1604     BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
   1605 {
   1606     paintFillLayerExtended(paintInfo, c, fillLayer, rect, bleedAvoidance, 0, LayoutSize(), op, backgroundObject);
   1607 }
   1608 
   1609 static bool layersUseImage(WrappedImagePtr image, const FillLayer* layers)
   1610 {
   1611     for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
   1612         if (curLayer->image() && image == curLayer->image()->data())
   1613             return true;
   1614     }
   1615 
   1616     return false;
   1617 }
   1618 
   1619 void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*)
   1620 {
   1621     if (!parent())
   1622         return;
   1623 
   1624     if ((style()->borderImage().image() && style()->borderImage().image()->data() == image) ||
   1625         (style()->maskBoxImage().image() && style()->maskBoxImage().image()->data() == image)) {
   1626         repaint();
   1627         return;
   1628     }
   1629 
   1630     bool didFullRepaint = repaintLayerRectsForImage(image, style()->backgroundLayers(), true);
   1631     if (!didFullRepaint)
   1632         repaintLayerRectsForImage(image, style()->maskLayers(), false);
   1633 
   1634 
   1635     if (hasLayer() && layer()->hasCompositedMask() && layersUseImage(image, style()->maskLayers()))
   1636         layer()->contentChanged(MaskImageChanged);
   1637 }
   1638 
   1639 bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer* layers, bool drawingBackground)
   1640 {
   1641     LayoutRect rendererRect;
   1642     RenderBox* layerRenderer = 0;
   1643 
   1644     for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
   1645         if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(this, style()->effectiveZoom())) {
   1646             // Now that we know this image is being used, compute the renderer and the rect
   1647             // if we haven't already
   1648             if (!layerRenderer) {
   1649                 bool drawingRootBackground = drawingBackground && (isRoot() || (isBody() && !document().documentElement()->renderer()->hasBackground()));
   1650                 if (drawingRootBackground) {
   1651                     layerRenderer = view();
   1652 
   1653                     LayoutUnit rw;
   1654                     LayoutUnit rh;
   1655 
   1656                     if (FrameView* frameView = toRenderView(layerRenderer)->frameView()) {
   1657                         rw = frameView->contentsWidth();
   1658                         rh = frameView->contentsHeight();
   1659                     } else {
   1660                         rw = layerRenderer->width();
   1661                         rh = layerRenderer->height();
   1662                     }
   1663                     rendererRect = LayoutRect(-layerRenderer->marginLeft(),
   1664                         -layerRenderer->marginTop(),
   1665                         max(layerRenderer->width() + layerRenderer->marginWidth() + layerRenderer->borderLeft() + layerRenderer->borderRight(), rw),
   1666                         max(layerRenderer->height() + layerRenderer->marginHeight() + layerRenderer->borderTop() + layerRenderer->borderBottom(), rh));
   1667                 } else {
   1668                     layerRenderer = this;
   1669                     rendererRect = borderBoxRect();
   1670                 }
   1671             }
   1672 
   1673             BackgroundImageGeometry geometry;
   1674             layerRenderer->calculateBackgroundImageGeometry(curLayer, rendererRect, geometry);
   1675             layerRenderer->repaintRectangle(geometry.destRect());
   1676             if (geometry.destRect() == rendererRect)
   1677                 return true;
   1678         }
   1679     }
   1680     return false;
   1681 }
   1682 
   1683 bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumulatedOffset, ContentsClipBehavior contentsClipBehavior)
   1684 {
   1685     if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseSelfOutline || paintInfo.phase == PaintPhaseMask)
   1686         return false;
   1687 
   1688     bool isControlClip = hasControlClip();
   1689     bool isOverflowClip = hasOverflowClip() && !layer()->isSelfPaintingLayer();
   1690 
   1691     if (!isControlClip && !isOverflowClip)
   1692         return false;
   1693 
   1694     LayoutRect clipRect = isControlClip ? controlClipRect(accumulatedOffset) : overflowClipRect(accumulatedOffset, paintInfo.renderRegion);
   1695     RoundedRect clipRoundedRect(0, 0, 0, 0);
   1696     bool hasBorderRadius = style()->hasBorderRadius();
   1697     if (hasBorderRadius)
   1698         clipRoundedRect = style()->getRoundedInnerBorderFor(LayoutRect(accumulatedOffset, size()));
   1699 
   1700     if (contentsClipBehavior == SkipContentsClipIfPossible) {
   1701         LayoutRect contentsVisualOverflow = contentsVisualOverflowRect();
   1702         if (contentsVisualOverflow.isEmpty())
   1703             return false;
   1704 
   1705         // FIXME: Get rid of this slop from here and elsewhere.
   1706         // Instead, properly include the outline in visual overflow.
   1707         if (RenderView* view = this->view())
   1708             contentsVisualOverflow.inflate(view->maximalOutlineSize());
   1709 
   1710         LayoutRect conservativeClipRect = clipRect;
   1711         if (hasBorderRadius)
   1712             conservativeClipRect.intersect(clipRoundedRect.radiusCenterRect());
   1713         conservativeClipRect.moveBy(-accumulatedOffset);
   1714         if (hasLayer())
   1715             conservativeClipRect.move(scrolledContentOffset());
   1716         if (conservativeClipRect.contains(contentsVisualOverflow))
   1717             return false;
   1718     }
   1719 
   1720     if (paintInfo.phase == PaintPhaseOutline)
   1721         paintInfo.phase = PaintPhaseChildOutlines;
   1722     else if (paintInfo.phase == PaintPhaseChildBlockBackground) {
   1723         paintInfo.phase = PaintPhaseBlockBackground;
   1724         paintObject(paintInfo, accumulatedOffset);
   1725         paintInfo.phase = PaintPhaseChildBlockBackgrounds;
   1726     }
   1727     paintInfo.context->save();
   1728     if (hasBorderRadius)
   1729         paintInfo.context->clipRoundedRect(clipRoundedRect);
   1730     paintInfo.context->clip(pixelSnappedIntRect(clipRect));
   1731     return true;
   1732 }
   1733 
   1734 void RenderBox::popContentsClip(PaintInfo& paintInfo, PaintPhase originalPhase, const LayoutPoint& accumulatedOffset)
   1735 {
   1736     ASSERT(hasControlClip() || (hasOverflowClip() && !layer()->isSelfPaintingLayer()));
   1737 
   1738     paintInfo.context->restore();
   1739     if (originalPhase == PaintPhaseOutline) {
   1740         paintInfo.phase = PaintPhaseSelfOutline;
   1741         paintObject(paintInfo, accumulatedOffset);
   1742         paintInfo.phase = originalPhase;
   1743     } else if (originalPhase == PaintPhaseChildBlockBackground)
   1744         paintInfo.phase = originalPhase;
   1745 }
   1746 
   1747 LayoutRect RenderBox::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy)
   1748 {
   1749     // FIXME: When overflow-clip (CSS3) is implemented, we'll obtain the property
   1750     // here.
   1751     LayoutRect clipRect = borderBoxRectInRegion(region);
   1752     clipRect.setLocation(location + clipRect.location() + LayoutSize(borderLeft(), borderTop()));
   1753     clipRect.setSize(clipRect.size() - LayoutSize(borderLeft() + borderRight(), borderTop() + borderBottom()));
   1754 
   1755     if (!hasOverflowClip())
   1756         return clipRect;
   1757 
   1758     // Subtract out scrollbars if we have them.
   1759     if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
   1760         clipRect.move(layer()->scrollableArea()->verticalScrollbarWidth(relevancy), 0);
   1761     clipRect.contract(layer()->scrollableArea()->verticalScrollbarWidth(relevancy), layer()->scrollableArea()->horizontalScrollbarHeight(relevancy));
   1762 
   1763     return clipRect;
   1764 }
   1765 
   1766 LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region)
   1767 {
   1768     LayoutRect borderBoxRect = borderBoxRectInRegion(region);
   1769     LayoutRect clipRect = LayoutRect(borderBoxRect.location() + location, borderBoxRect.size());
   1770     RenderView* renderView = view();
   1771 
   1772     if (!style()->clipLeft().isAuto()) {
   1773         LayoutUnit c = valueForLength(style()->clipLeft(), borderBoxRect.width(), renderView);
   1774         clipRect.move(c, 0);
   1775         clipRect.contract(c, 0);
   1776     }
   1777 
   1778     // We don't use the region-specific border box's width and height since clip offsets are (stupidly) specified
   1779     // from the left and top edges. Therefore it's better to avoid constraining to smaller widths and heights.
   1780 
   1781     if (!style()->clipRight().isAuto())
   1782         clipRect.contract(width() - valueForLength(style()->clipRight(), width(), renderView), 0);
   1783 
   1784     if (!style()->clipTop().isAuto()) {
   1785         LayoutUnit c = valueForLength(style()->clipTop(), borderBoxRect.height(), renderView);
   1786         clipRect.move(0, c);
   1787         clipRect.contract(0, c);
   1788     }
   1789 
   1790     if (!style()->clipBottom().isAuto())
   1791         clipRect.contract(0, height() - valueForLength(style()->clipBottom(), height(), renderView));
   1792 
   1793     return clipRect;
   1794 }
   1795 
   1796 LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlockFlow* cb, RenderRegion* region) const
   1797 {
   1798     RenderRegion* containingBlockRegion = 0;
   1799     LayoutUnit logicalTopPosition = logicalTop();
   1800     if (region) {
   1801         LayoutUnit offsetFromLogicalTopOfRegion = region ? region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage() : LayoutUnit();
   1802         logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
   1803         containingBlockRegion = cb->clampToStartAndEndRegions(region);
   1804     }
   1805 
   1806     LayoutUnit result = cb->availableLogicalWidthForLineInRegion(logicalTopPosition, false, containingBlockRegion) - childMarginStart - childMarginEnd;
   1807 
   1808     // We need to see if margins on either the start side or the end side can contain the floats in question. If they can,
   1809     // then just using the line width is inaccurate. In the case where a float completely fits, we don't need to use the line
   1810     // offset at all, but can instead push all the way to the content edge of the containing block. In the case where the float
   1811     // 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
   1812     // "consumed" by the float. Negative margins aren't consumed by the float, and so we ignore them.
   1813     if (childMarginStart > 0) {
   1814         LayoutUnit startContentSide = cb->startOffsetForContent(containingBlockRegion);
   1815         LayoutUnit startContentSideWithMargin = startContentSide + childMarginStart;
   1816         LayoutUnit startOffset = cb->startOffsetForLineInRegion(logicalTopPosition, false, containingBlockRegion);
   1817         if (startOffset > startContentSideWithMargin)
   1818             result += childMarginStart;
   1819         else
   1820             result += startOffset - startContentSide;
   1821     }
   1822 
   1823     if (childMarginEnd > 0) {
   1824         LayoutUnit endContentSide = cb->endOffsetForContent(containingBlockRegion);
   1825         LayoutUnit endContentSideWithMargin = endContentSide + childMarginEnd;
   1826         LayoutUnit endOffset = cb->endOffsetForLineInRegion(logicalTopPosition, false, containingBlockRegion);
   1827         if (endOffset > endContentSideWithMargin)
   1828             result += childMarginEnd;
   1829         else
   1830             result += endOffset - endContentSide;
   1831     }
   1832 
   1833     return result;
   1834 }
   1835 
   1836 LayoutUnit RenderBox::containingBlockLogicalWidthForContent() const
   1837 {
   1838     if (hasOverrideContainingBlockLogicalWidth())
   1839         return overrideContainingBlockContentLogicalWidth();
   1840 
   1841     RenderBlock* cb = containingBlock();
   1842     return cb->availableLogicalWidth();
   1843 }
   1844 
   1845 LayoutUnit RenderBox::containingBlockLogicalHeightForContent(AvailableLogicalHeightType heightType) const
   1846 {
   1847     if (hasOverrideContainingBlockLogicalHeight())
   1848         return overrideContainingBlockContentLogicalHeight();
   1849 
   1850     RenderBlock* cb = containingBlock();
   1851     return cb->availableLogicalHeight(heightType);
   1852 }
   1853 
   1854 LayoutUnit RenderBox::containingBlockLogicalWidthForContentInRegion(RenderRegion* region) const
   1855 {
   1856     if (!region)
   1857         return containingBlockLogicalWidthForContent();
   1858 
   1859     RenderBlock* cb = containingBlock();
   1860     RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region);
   1861     // FIXME: It's unclear if a region's content should use the containing block's override logical width.
   1862     // If it should, the following line should call containingBlockLogicalWidthForContent.
   1863     LayoutUnit result = cb->availableLogicalWidth();
   1864     RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(containingBlockRegion);
   1865     if (!boxInfo)
   1866         return result;
   1867     return max<LayoutUnit>(0, result - (cb->logicalWidth() - boxInfo->logicalWidth()));
   1868 }
   1869 
   1870 LayoutUnit RenderBox::containingBlockAvailableLineWidthInRegion(RenderRegion* region) const
   1871 {
   1872     RenderBlock* cb = containingBlock();
   1873     RenderRegion* containingBlockRegion = 0;
   1874     LayoutUnit logicalTopPosition = logicalTop();
   1875     if (region) {
   1876         LayoutUnit offsetFromLogicalTopOfRegion = region ? region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage() : LayoutUnit();
   1877         logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
   1878         containingBlockRegion = cb->clampToStartAndEndRegions(region);
   1879     }
   1880     return cb->availableLogicalWidthForLineInRegion(logicalTopPosition, false, containingBlockRegion, availableLogicalHeight(IncludeMarginBorderPadding));
   1881 }
   1882 
   1883 LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const
   1884 {
   1885     if (hasOverrideContainingBlockLogicalHeight())
   1886         return overrideContainingBlockContentLogicalHeight();
   1887 
   1888     RenderBlock* cb = containingBlock();
   1889     if (cb->hasOverrideHeight())
   1890         return cb->overrideLogicalContentHeight();
   1891 
   1892     RenderStyle* containingBlockStyle = cb->style();
   1893     Length logicalHeightLength = containingBlockStyle->logicalHeight();
   1894 
   1895     // FIXME: For now just support fixed heights.  Eventually should support percentage heights as well.
   1896     if (!logicalHeightLength.isFixed()) {
   1897         LayoutUnit fillFallbackExtent = containingBlockStyle->isHorizontalWritingMode() ? view()->frameView()->visibleHeight() : view()->frameView()->visibleWidth();
   1898         LayoutUnit fillAvailableExtent = containingBlock()->availableLogicalHeight(ExcludeMarginBorderPadding);
   1899         return min(fillAvailableExtent, fillFallbackExtent);
   1900     }
   1901 
   1902     // Use the content box logical height as specified by the style.
   1903     return cb->adjustContentBoxLogicalHeightForBoxSizing(logicalHeightLength.value());
   1904 }
   1905 
   1906 void RenderBox::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
   1907 {
   1908     if (repaintContainer == this)
   1909         return;
   1910 
   1911     if (RenderView* v = view()) {
   1912         if (v->layoutStateEnabled() && !repaintContainer) {
   1913             LayoutState* layoutState = v->layoutState();
   1914             LayoutSize offset = layoutState->m_paintOffset + locationOffset();
   1915             if (style()->hasInFlowPosition() && layer())
   1916                 offset += layer()->offsetForInFlowPosition();
   1917             transformState.move(offset);
   1918             return;
   1919         }
   1920     }
   1921 
   1922     bool containerSkipped;
   1923     RenderObject* o = container(repaintContainer, &containerSkipped);
   1924     if (!o)
   1925         return;
   1926 
   1927     bool isFixedPos = style()->position() == FixedPosition;
   1928     bool hasTransform = hasLayer() && layer()->transform();
   1929     // If this box has a transform, it acts as a fixed position container for fixed descendants,
   1930     // and may itself also be fixed position. So propagate 'fixed' up only if this box is fixed position.
   1931     if (hasTransform && !isFixedPos)
   1932         mode &= ~IsFixed;
   1933     else if (isFixedPos)
   1934         mode |= IsFixed;
   1935 
   1936     if (wasFixed)
   1937         *wasFixed = mode & IsFixed;
   1938 
   1939     LayoutSize containerOffset = offsetFromContainer(o, roundedLayoutPoint(transformState.mappedPoint()));
   1940 
   1941     bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || style()->preserves3D());
   1942     if (mode & UseTransforms && shouldUseTransformFromContainer(o)) {
   1943         TransformationMatrix t;
   1944         getTransformFromContainer(o, containerOffset, t);
   1945         transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
   1946     } else
   1947         transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
   1948 
   1949     if (containerSkipped) {
   1950         // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
   1951         // to just subtract the delta between the repaintContainer and o.
   1952         LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
   1953         transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
   1954         return;
   1955     }
   1956 
   1957     mode &= ~ApplyContainerFlip;
   1958 
   1959     o->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
   1960 }
   1961 
   1962 void RenderBox::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
   1963 {
   1964     // We don't expect to be called during layout.
   1965     ASSERT(!view() || !view()->layoutStateEnabled());
   1966 
   1967     bool isFixedPos = style()->position() == FixedPosition;
   1968     bool hasTransform = hasLayer() && layer()->transform();
   1969     if (hasTransform && !isFixedPos) {
   1970         // If this box has a transform, it acts as a fixed position container for fixed descendants,
   1971         // and may itself also be fixed position. So propagate 'fixed' up only if this box is fixed position.
   1972         mode &= ~IsFixed;
   1973     } else if (isFixedPos)
   1974         mode |= IsFixed;
   1975 
   1976     RenderBoxModelObject::mapAbsoluteToLocalPoint(mode, transformState);
   1977 }
   1978 
   1979 LayoutSize RenderBox::offsetFromContainer(RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
   1980 {
   1981     // A region "has" boxes inside it without being their container.
   1982     // FIXME: change container() / containingBlock() to count for boxes being positioned relative to the region, not the
   1983     // FlowThread. This requires a separate patch as a simple test with such a change in container() causes 129 out of
   1984     // 337 regions tests to fail.
   1985     ASSERT(o == container() || o->isRenderRegion());
   1986 
   1987     LayoutSize offset;
   1988     if (isInFlowPositioned())
   1989         offset += offsetForInFlowPosition();
   1990 
   1991     if (!isInline() || isReplaced()) {
   1992         if (!style()->hasOutOfFlowPosition() && o->hasColumns()) {
   1993             RenderBlock* block = toRenderBlock(o);
   1994             LayoutRect columnRect(frameRect());
   1995             block->adjustStartEdgeForWritingModeIncludingColumns(columnRect);
   1996             offset += toSize(columnRect.location());
   1997             LayoutPoint columnPoint = block->flipForWritingModeIncludingColumns(point + offset);
   1998             offset = toLayoutSize(block->flipForWritingModeIncludingColumns(toLayoutPoint(offset)));
   1999             o->adjustForColumns(offset, columnPoint);
   2000             offset = block->flipForWritingMode(offset);
   2001 
   2002             if (offsetDependsOnPoint)
   2003                 *offsetDependsOnPoint = true;
   2004         } else
   2005             offset += topLeftLocationOffset();
   2006     }
   2007 
   2008     if (o->hasOverflowClip())
   2009         offset -= toRenderBox(o)->scrolledContentOffset();
   2010 
   2011     if (style()->position() == AbsolutePosition && o->isInFlowPositioned() && o->isRenderInline())
   2012         offset += toRenderInline(o)->offsetForInFlowPositionedInline(this);
   2013 
   2014     if (offsetDependsOnPoint)
   2015         *offsetDependsOnPoint |= o->isRenderFlowThread();
   2016 
   2017     return offset;
   2018 }
   2019 
   2020 InlineBox* RenderBox::createInlineBox()
   2021 {
   2022     return new InlineBox(this);
   2023 }
   2024 
   2025 void RenderBox::dirtyLineBoxes(bool fullLayout)
   2026 {
   2027     if (m_inlineBoxWrapper) {
   2028         if (fullLayout) {
   2029             m_inlineBoxWrapper->destroy();
   2030             m_inlineBoxWrapper = 0;
   2031         } else
   2032             m_inlineBoxWrapper->dirtyLineBoxes();
   2033     }
   2034 }
   2035 
   2036 void RenderBox::positionLineBox(InlineBox* box)
   2037 {
   2038     if (isOutOfFlowPositioned()) {
   2039         // Cache the x position only if we were an INLINE type originally.
   2040         bool wasInline = style()->isOriginalDisplayInlineType();
   2041         if (wasInline) {
   2042             // The value is cached in the xPos of the box.  We only need this value if
   2043             // our object was inline originally, since otherwise it would have ended up underneath
   2044             // the inlines.
   2045             RootInlineBox* root = box->root();
   2046             root->block()->setStaticInlinePositionForChild(this, root->lineTopWithLeading(), LayoutUnit::fromFloatRound(box->logicalLeft()));
   2047             if (style()->hasStaticInlinePosition(box->isHorizontal()))
   2048                 setChildNeedsLayout(MarkOnlyThis); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
   2049         } else {
   2050             // Our object was a block originally, so we make our normal flow position be
   2051             // just below the line box (as though all the inlines that came before us got
   2052             // wrapped in an anonymous block, which is what would have happened had we been
   2053             // in flow).  This value was cached in the y() of the box.
   2054             layer()->setStaticBlockPosition(box->logicalTop());
   2055             if (style()->hasStaticBlockPosition(box->isHorizontal()))
   2056                 setChildNeedsLayout(MarkOnlyThis); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
   2057         }
   2058 
   2059         // Nuke the box.
   2060         box->remove();
   2061         box->destroy();
   2062     } else if (isReplaced()) {
   2063         setLocation(roundedLayoutPoint(box->topLeft()));
   2064         setInlineBoxWrapper(box);
   2065     }
   2066 }
   2067 
   2068 void RenderBox::deleteLineBoxWrapper()
   2069 {
   2070     if (m_inlineBoxWrapper) {
   2071         if (!documentBeingDestroyed())
   2072             m_inlineBoxWrapper->remove();
   2073         m_inlineBoxWrapper->destroy();
   2074         m_inlineBoxWrapper = 0;
   2075     }
   2076 }
   2077 
   2078 LayoutRect RenderBox::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
   2079 {
   2080     if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
   2081         return LayoutRect();
   2082 
   2083     LayoutRect r = visualOverflowRect();
   2084 
   2085     RenderView* v = view();
   2086     if (v) {
   2087         // FIXME: layoutDelta needs to be applied in parts before/after transforms and
   2088         // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
   2089         r.move(v->layoutDelta());
   2090     }
   2091 
   2092     if (style()) {
   2093         // We have to use maximalOutlineSize() because a child might have an outline
   2094         // that projects outside of our overflowRect.
   2095         if (v) {
   2096             ASSERT(style()->outlineSize() <= v->maximalOutlineSize());
   2097             r.inflate(v->maximalOutlineSize());
   2098         }
   2099     }
   2100 
   2101     computeRectForRepaint(repaintContainer, r);
   2102     return r;
   2103 }
   2104 
   2105 void RenderBox::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
   2106 {
   2107     // The rect we compute at each step is shifted by our x/y offset in the parent container's coordinate space.
   2108     // Only when we cross a writing mode boundary will we have to possibly flipForWritingMode (to convert into a more appropriate
   2109     // offset corner for the enclosing container).  This allows for a fully RL or BT document to repaint
   2110     // properly even during layout, since the rect remains flipped all the way until the end.
   2111     //
   2112     // RenderView::computeRectForRepaint then converts the rect to physical coordinates.  We also convert to
   2113     // physical when we hit a repaintContainer boundary.  Therefore the final rect returned is always in the
   2114     // physical coordinate space of the repaintContainer.
   2115     RenderStyle* styleToUse = style();
   2116     if (RenderView* v = view()) {
   2117         // LayoutState is only valid for root-relative, non-fixed position repainting
   2118         if (v->layoutStateEnabled() && !repaintContainer && styleToUse->position() != FixedPosition) {
   2119             LayoutState* layoutState = v->layoutState();
   2120 
   2121             if (layer() && layer()->transform())
   2122                 rect = layer()->transform()->mapRect(pixelSnappedIntRect(rect));
   2123 
   2124             // We can't trust the bits on RenderObject, because this might be called while re-resolving style.
   2125             if (styleToUse->hasInFlowPosition() && layer())
   2126                 rect.move(layer()->offsetForInFlowPosition());
   2127 
   2128             rect.moveBy(location());
   2129             rect.move(layoutState->m_paintOffset);
   2130             if (layoutState->m_clipped)
   2131                 rect.intersect(layoutState->m_clipRect);
   2132             return;
   2133         }
   2134     }
   2135 
   2136     if (hasReflection())
   2137         rect.unite(reflectedRect(rect));
   2138 
   2139     if (repaintContainer == this) {
   2140         if (repaintContainer->style()->isFlippedBlocksWritingMode())
   2141             flipForWritingMode(rect);
   2142         return;
   2143     }
   2144 
   2145     bool containerSkipped;
   2146     RenderObject* o = container(repaintContainer, &containerSkipped);
   2147     if (!o)
   2148         return;
   2149 
   2150     if (isWritingModeRoot() && !isOutOfFlowPositioned())
   2151         flipForWritingMode(rect);
   2152 
   2153     LayoutPoint topLeft = rect.location();
   2154     topLeft.move(locationOffset());
   2155 
   2156     EPosition position = styleToUse->position();
   2157 
   2158     // We are now in our parent container's coordinate space.  Apply our transform to obtain a bounding box
   2159     // in the parent's coordinate space that encloses us.
   2160     if (hasLayer() && layer()->transform()) {
   2161         fixed = position == FixedPosition;
   2162         rect = layer()->transform()->mapRect(pixelSnappedIntRect(rect));
   2163         topLeft = rect.location();
   2164         topLeft.move(locationOffset());
   2165     } else if (position == FixedPosition)
   2166         fixed = true;
   2167 
   2168     if (position == AbsolutePosition && o->isInFlowPositioned() && o->isRenderInline()) {
   2169         topLeft += toRenderInline(o)->offsetForInFlowPositionedInline(this);
   2170     } else if (styleToUse->hasInFlowPosition() && layer()) {
   2171         // Apply the relative position offset when invalidating a rectangle.  The layer
   2172         // is translated, but the render box isn't, so we need to do this to get the
   2173         // right dirty rect.  Since this is called from RenderObject::setStyle, the relative position
   2174         // flag on the RenderObject has been cleared, so use the one on the style().
   2175         topLeft += layer()->offsetForInFlowPosition();
   2176     }
   2177 
   2178     if (position != AbsolutePosition && position != FixedPosition && o->hasColumns() && o->isRenderBlockFlow()) {
   2179         LayoutRect repaintRect(topLeft, rect.size());
   2180         toRenderBlock(o)->adjustRectForColumns(repaintRect);
   2181         topLeft = repaintRect.location();
   2182         rect = repaintRect;
   2183     }
   2184 
   2185     // FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout,
   2186     // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer.
   2187     rect.setLocation(topLeft);
   2188     if (o->hasOverflowClip()) {
   2189         RenderBox* containerBox = toRenderBox(o);
   2190         containerBox->applyCachedClipAndScrollOffsetForRepaint(rect);
   2191         if (rect.isEmpty())
   2192             return;
   2193     }
   2194 
   2195     if (containerSkipped) {
   2196         // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
   2197         LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
   2198         rect.move(-containerOffset);
   2199         return;
   2200     }
   2201 
   2202     o->computeRectForRepaint(repaintContainer, rect, fixed);
   2203 }
   2204 
   2205 void RenderBox::repaintDuringLayoutIfMoved(const LayoutRect& oldRect)
   2206 {
   2207     if (oldRect.location() != m_frameRect.location()) {
   2208         LayoutRect newRect = m_frameRect;
   2209         // The child moved.  Invalidate the object's old and new positions.  We have to do this
   2210         // since the object may not have gotten a layout.
   2211         m_frameRect = oldRect;
   2212         repaint();
   2213         repaintOverhangingFloats(true);
   2214         m_frameRect = newRect;
   2215         repaint();
   2216         repaintOverhangingFloats(true);
   2217     }
   2218 }
   2219 
   2220 void RenderBox::repaintOverhangingFloats(bool)
   2221 {
   2222 }
   2223 
   2224 void RenderBox::updateLogicalWidth()
   2225 {
   2226     LogicalExtentComputedValues computedValues;
   2227     computeLogicalWidthInRegion(computedValues);
   2228 
   2229     setLogicalWidth(computedValues.m_extent);
   2230     setLogicalLeft(computedValues.m_position);
   2231     setMarginStart(computedValues.m_margins.m_start);
   2232     setMarginEnd(computedValues.m_margins.m_end);
   2233 }
   2234 
   2235 static float getMaxWidthListMarker(const RenderBox* renderer)
   2236 {
   2237 #ifndef NDEBUG
   2238     ASSERT(renderer);
   2239     Node* parentNode = renderer->generatingNode();
   2240     ASSERT(parentNode);
   2241     ASSERT(parentNode->hasTagName(olTag) || parentNode->hasTagName(ulTag));
   2242     ASSERT(renderer->style()->textAutosizingMultiplier() != 1);
   2243 #endif
   2244     float maxWidth = 0;
   2245     for (RenderObject* child = renderer->firstChild(); child; child = child->nextSibling()) {
   2246         if (!child->isListItem())
   2247             continue;
   2248 
   2249         RenderBox* listItem = toRenderBox(child);
   2250         for (RenderObject* itemChild = listItem->firstChild(); itemChild; itemChild = itemChild->nextSibling()) {
   2251             if (!itemChild->isListMarker())
   2252                 continue;
   2253             RenderBox* itemMarker = toRenderBox(itemChild);
   2254             // FIXME: canDetermineWidthWithoutLayout expects us to use fixedOffsetWidth, which this code
   2255             // does not do! This check is likely wrong.
   2256             if (!itemMarker->canDetermineWidthWithoutLayout() && itemMarker->needsLayout()) {
   2257                 // Make sure to compute the autosized width.
   2258                 itemMarker->layout();
   2259             }
   2260             maxWidth = max<float>(maxWidth, toRenderListMarker(itemMarker)->logicalWidth().toFloat());
   2261             break;
   2262         }
   2263     }
   2264     return maxWidth;
   2265 }
   2266 
   2267 void RenderBox::computeLogicalWidthInRegion(LogicalExtentComputedValues& computedValues, RenderRegion* region) const
   2268 {
   2269     computedValues.m_extent = logicalWidth();
   2270     computedValues.m_position = logicalLeft();
   2271     computedValues.m_margins.m_start = marginStart();
   2272     computedValues.m_margins.m_end = marginEnd();
   2273 
   2274     if (isOutOfFlowPositioned()) {
   2275         // FIXME: This calculation is not patched for block-flow yet.
   2276         // https://bugs.webkit.org/show_bug.cgi?id=46500
   2277         computePositionedLogicalWidth(computedValues, region);
   2278         return;
   2279     }
   2280 
   2281     // If layout is limited to a subtree, the subtree root's logical width does not change.
   2282     if (node() && view()->frameView() && view()->frameView()->layoutRoot(true) == this)
   2283         return;
   2284 
   2285     // The parent box is flexing us, so it has increased or decreased our
   2286     // width.  Use the width from the style context.
   2287     // FIXME: Account for block-flow in flexible boxes.
   2288     // https://bugs.webkit.org/show_bug.cgi?id=46418
   2289     if (hasOverrideWidth() && (style()->borderFit() == BorderFitLines || parent()->isFlexibleBoxIncludingDeprecated())) {
   2290         computedValues.m_extent = overrideLogicalContentWidth() + borderAndPaddingLogicalWidth();
   2291         return;
   2292     }
   2293 
   2294     // FIXME: Account for block-flow in flexible boxes.
   2295     // https://bugs.webkit.org/show_bug.cgi?id=46418
   2296     bool inVerticalBox = parent()->isDeprecatedFlexibleBox() && (parent()->style()->boxOrient() == VERTICAL);
   2297     bool stretching = (parent()->style()->boxAlign() == BSTRETCH);
   2298     bool treatAsReplaced = shouldComputeSizeAsReplaced() && (!inVerticalBox || !stretching);
   2299 
   2300     RenderStyle* styleToUse = style();
   2301     Length logicalWidthLength = treatAsReplaced ? Length(computeReplacedLogicalWidth(), Fixed) : styleToUse->logicalWidth();
   2302 
   2303     RenderBlock* cb = containingBlock();
   2304     LayoutUnit containerLogicalWidth = max<LayoutUnit>(0, containingBlockLogicalWidthForContentInRegion(region));
   2305     bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
   2306 
   2307     if (isInline() && !isInlineBlockOrInlineTable()) {
   2308         // just calculate margins
   2309         RenderView* renderView = view();
   2310         computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView);
   2311         computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView);
   2312         if (treatAsReplaced)
   2313             computedValues.m_extent = max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth());
   2314         return;
   2315     }
   2316 
   2317     // Width calculations
   2318     if (treatAsReplaced)
   2319         computedValues.m_extent = logicalWidthLength.value() + borderAndPaddingLogicalWidth();
   2320     else {
   2321         LayoutUnit containerWidthInInlineDirection = containerLogicalWidth;
   2322         if (hasPerpendicularContainingBlock)
   2323             containerWidthInInlineDirection = perpendicularContainingBlockLogicalHeight();
   2324         LayoutUnit preferredWidth = computeLogicalWidthInRegionUsing(MainOrPreferredSize, styleToUse->logicalWidth(), containerWidthInInlineDirection, cb, region);
   2325         computedValues.m_extent = constrainLogicalWidthInRegionByMinMax(preferredWidth, containerWidthInInlineDirection, cb, region);
   2326     }
   2327 
   2328     // Margin calculations.
   2329     if (hasPerpendicularContainingBlock || isFloating() || isInline()) {
   2330         RenderView* renderView = view();
   2331         computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView);
   2332         computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView);
   2333     } else {
   2334         LayoutUnit containerLogicalWidthForAutoMargins = containerLogicalWidth;
   2335         if (avoidsFloats() && cb->containsFloats())
   2336             containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(region);
   2337         bool hasInvertedDirection = cb->style()->isLeftToRightDirection() != style()->isLeftToRightDirection();
   2338         computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, computedValues.m_extent,
   2339             hasInvertedDirection ? computedValues.m_margins.m_end : computedValues.m_margins.m_start,
   2340             hasInvertedDirection ? computedValues.m_margins.m_start : computedValues.m_margins.m_end);
   2341     }
   2342 
   2343     if (!hasPerpendicularContainingBlock && containerLogicalWidth && containerLogicalWidth != (computedValues.m_extent + computedValues.m_margins.m_start + computedValues.m_margins.m_end)
   2344         && !isFloating() && !isInline() && !cb->isFlexibleBoxIncludingDeprecated() && !cb->isRenderGrid()) {
   2345         LayoutUnit newMargin = containerLogicalWidth - computedValues.m_extent - cb->marginStartForChild(this);
   2346         bool hasInvertedDirection = cb->style()->isLeftToRightDirection() != style()->isLeftToRightDirection();
   2347         if (hasInvertedDirection)
   2348             computedValues.m_margins.m_start = newMargin;
   2349         else
   2350             computedValues.m_margins.m_end = newMargin;
   2351     }
   2352 
   2353     if (styleToUse->textAutosizingMultiplier() != 1 && styleToUse->marginStart().type() == Fixed) {
   2354         Node* parentNode = generatingNode();
   2355         if (parentNode && (parentNode->hasTagName(olTag) || parentNode->hasTagName(ulTag))) {
   2356             // Make sure the markers in a list are properly positioned (i.e. not chopped off) when autosized.
   2357             const float adjustedMargin = (1 - 1.0 / styleToUse->textAutosizingMultiplier()) * getMaxWidthListMarker(this);
   2358             bool hasInvertedDirection = cb->style()->isLeftToRightDirection() != style()->isLeftToRightDirection();
   2359             if (hasInvertedDirection)
   2360                 computedValues.m_margins.m_end += adjustedMargin;
   2361             else
   2362                 computedValues.m_margins.m_start += adjustedMargin;
   2363         }
   2364     }
   2365 }
   2366 
   2367 LayoutUnit RenderBox::fillAvailableMeasure(LayoutUnit availableLogicalWidth) const
   2368 {
   2369     LayoutUnit marginStart = 0;
   2370     LayoutUnit marginEnd = 0;
   2371     return fillAvailableMeasure(availableLogicalWidth, marginStart, marginEnd);
   2372 }
   2373 
   2374 LayoutUnit RenderBox::fillAvailableMeasure(LayoutUnit availableLogicalWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const
   2375 {
   2376     RenderView* renderView = view();
   2377     marginStart = minimumValueForLength(style()->marginStart(), availableLogicalWidth, renderView);
   2378     marginEnd = minimumValueForLength(style()->marginEnd(), availableLogicalWidth, renderView);
   2379     return availableLogicalWidth - marginStart - marginEnd;
   2380 }
   2381 
   2382 LayoutUnit RenderBox::computeIntrinsicLogicalWidthUsing(Length logicalWidthLength, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const
   2383 {
   2384     if (logicalWidthLength.type() == FillAvailable)
   2385         return fillAvailableMeasure(availableLogicalWidth);
   2386 
   2387     LayoutUnit minLogicalWidth = 0;
   2388     LayoutUnit maxLogicalWidth = 0;
   2389     computeIntrinsicLogicalWidths(minLogicalWidth, maxLogicalWidth);
   2390 
   2391     if (logicalWidthLength.type() == MinContent)
   2392         return minLogicalWidth + borderAndPadding;
   2393 
   2394     if (logicalWidthLength.type() == MaxContent)
   2395         return maxLogicalWidth + borderAndPadding;
   2396 
   2397     if (logicalWidthLength.type() == FitContent) {
   2398         minLogicalWidth += borderAndPadding;
   2399         maxLogicalWidth += borderAndPadding;
   2400         return max(minLogicalWidth, min(maxLogicalWidth, fillAvailableMeasure(availableLogicalWidth)));
   2401     }
   2402 
   2403     ASSERT_NOT_REACHED();
   2404     return 0;
   2405 }
   2406 
   2407 LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(SizeType widthType, Length logicalWidth, LayoutUnit availableLogicalWidth,
   2408     const RenderBlock* cb, RenderRegion* region) const
   2409 {
   2410     if (!logicalWidth.isIntrinsicOrAuto()) {
   2411         // FIXME: If the containing block flow is perpendicular to our direction we need to use the available logical height instead.
   2412         return adjustBorderBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, availableLogicalWidth, view()));
   2413     }
   2414 
   2415     if (logicalWidth.isIntrinsic())
   2416         return computeIntrinsicLogicalWidthUsing(logicalWidth, availableLogicalWidth, borderAndPaddingLogicalWidth());
   2417 
   2418     LayoutUnit marginStart = 0;
   2419     LayoutUnit marginEnd = 0;
   2420     LayoutUnit logicalWidthResult = fillAvailableMeasure(availableLogicalWidth, marginStart, marginEnd);
   2421 
   2422     if (shrinkToAvoidFloats() && cb->containsFloats())
   2423         logicalWidthResult = min(logicalWidthResult, shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, toRenderBlockFlow(cb), region));
   2424 
   2425     if (widthType == MainOrPreferredSize && sizesLogicalWidthToFitContent(widthType))
   2426         return max(minPreferredLogicalWidth(), min(maxPreferredLogicalWidth(), logicalWidthResult));
   2427     return logicalWidthResult;
   2428 }
   2429 
   2430 static bool columnFlexItemHasStretchAlignment(const RenderObject* flexitem)
   2431 {
   2432     RenderObject* parent = flexitem->parent();
   2433     // auto margins mean we don't stretch. Note that this function will only be used for
   2434     // widths, so we don't have to check marginBefore/marginAfter.
   2435     ASSERT(parent->style()->isColumnFlexDirection());
   2436     if (flexitem->style()->marginStart().isAuto() || flexitem->style()->marginEnd().isAuto())
   2437         return false;
   2438     return flexitem->style()->alignSelf() == AlignStretch || (flexitem->style()->alignSelf() == AlignAuto && parent->style()->alignItems() == AlignStretch);
   2439 }
   2440 
   2441 static bool isStretchingColumnFlexItem(const RenderObject* flexitem)
   2442 {
   2443     RenderObject* parent = flexitem->parent();
   2444     if (parent->isDeprecatedFlexibleBox() && parent->style()->boxOrient() == VERTICAL && parent->style()->boxAlign() == BSTRETCH)
   2445         return true;
   2446 
   2447     // We don't stretch multiline flexboxes because they need to apply line spacing (align-content) first.
   2448     if (parent->isFlexibleBox() && parent->style()->flexWrap() == FlexNoWrap && parent->style()->isColumnFlexDirection() && columnFlexItemHasStretchAlignment(flexitem))
   2449         return true;
   2450     return false;
   2451 }
   2452 
   2453 bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const
   2454 {
   2455     // Marquees in WinIE are like a mixture of blocks and inline-blocks.  They size as though they're blocks,
   2456     // but they allow text to sit on the same line as the marquee.
   2457     if (isFloating() || (isInlineBlockOrInlineTable() && !isMarquee()))
   2458         return true;
   2459 
   2460     // This code may look a bit strange.  Basically width:intrinsic should clamp the size when testing both
   2461     // min-width and width.  max-width is only clamped if it is also intrinsic.
   2462     Length logicalWidth = (widthType == MaxSize) ? style()->logicalMaxWidth() : style()->logicalWidth();
   2463     if (logicalWidth.type() == Intrinsic)
   2464         return true;
   2465 
   2466     // Children of a horizontal marquee do not fill the container by default.
   2467     // FIXME: Need to deal with MAUTO value properly.  It could be vertical.
   2468     // FIXME: Think about block-flow here.  Need to find out how marquee direction relates to
   2469     // block-flow (as well as how marquee overflow should relate to block flow).
   2470     // https://bugs.webkit.org/show_bug.cgi?id=46472
   2471     if (parent()->isMarquee()) {
   2472         EMarqueeDirection dir = parent()->style()->marqueeDirection();
   2473         if (dir == MAUTO || dir == MFORWARD || dir == MBACKWARD || dir == MLEFT || dir == MRIGHT)
   2474             return true;
   2475     }
   2476 
   2477     // Flexible box items should shrink wrap, so we lay them out at their intrinsic widths.
   2478     // In the case of columns that have a stretch alignment, we go ahead and layout at the
   2479     // stretched size to avoid an extra layout when applying alignment.
   2480     if (parent()->isFlexibleBox()) {
   2481         // For multiline columns, we need to apply align-content first, so we can't stretch now.
   2482         if (!parent()->style()->isColumnFlexDirection() || parent()->style()->flexWrap() != FlexNoWrap)
   2483             return true;
   2484         if (!columnFlexItemHasStretchAlignment(this))
   2485             return true;
   2486     }
   2487 
   2488     // Flexible horizontal boxes lay out children at their intrinsic widths.  Also vertical boxes
   2489     // that don't stretch their kids lay out their children at their intrinsic widths.
   2490     // FIXME: Think about block-flow here.
   2491     // https://bugs.webkit.org/show_bug.cgi?id=46473
   2492     if (parent()->isDeprecatedFlexibleBox() && (parent()->style()->boxOrient() == HORIZONTAL || parent()->style()->boxAlign() != BSTRETCH))
   2493         return true;
   2494 
   2495     // Button, input, select, textarea, and legend treat width value of 'auto' as 'intrinsic' unless it's in a
   2496     // stretching column flexbox.
   2497     // FIXME: Think about block-flow here.
   2498     // https://bugs.webkit.org/show_bug.cgi?id=46473
   2499     if (logicalWidth.type() == Auto && !isStretchingColumnFlexItem(this) && autoWidthShouldFitContent())
   2500         return true;
   2501 
   2502     if (isHorizontalWritingMode() != containingBlock()->isHorizontalWritingMode())
   2503         return true;
   2504 
   2505     return false;
   2506 }
   2507 
   2508 bool RenderBox::autoWidthShouldFitContent() const
   2509 {
   2510     if (node() && (node()->hasTagName(inputTag) || node()->hasTagName(selectTag) || node()->hasTagName(buttonTag)
   2511         || isHTMLTextAreaElement(node()) || node()->hasTagName(legendTag)))
   2512         return true;
   2513 
   2514     return false;
   2515 }
   2516 
   2517 void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const
   2518 {
   2519     const RenderStyle* containingBlockStyle = containingBlock->style();
   2520     Length marginStartLength = style()->marginStartUsing(containingBlockStyle);
   2521     Length marginEndLength = style()->marginEndUsing(containingBlockStyle);
   2522     RenderView* renderView = view();
   2523 
   2524     if (isFloating() || isInline()) {
   2525         // Inline blocks/tables and floats don't have their margins increased.
   2526         marginStart = minimumValueForLength(marginStartLength, containerWidth, renderView);
   2527         marginEnd = minimumValueForLength(marginEndLength, containerWidth, renderView);
   2528         return;
   2529     }
   2530 
   2531     if (containingBlock->isFlexibleBox()) {
   2532         // We need to let flexbox handle the margin adjustment - otherwise, flexbox
   2533         // will think we're wider than we actually are and calculate line sizes wrong.
   2534         // See also http://dev.w3.org/csswg/css-flexbox/#auto-margins
   2535         if (marginStartLength.isAuto())
   2536             marginStartLength.setValue(0);
   2537         if (marginEndLength.isAuto())
   2538             marginEndLength.setValue(0);
   2539     }
   2540 
   2541     // Case One: The object is being centered in the containing block's available logical width.
   2542     if ((marginStartLength.isAuto() && marginEndLength.isAuto() && childWidth < containerWidth)
   2543         || (!marginStartLength.isAuto() && !marginEndLength.isAuto() && containingBlock->style()->textAlign() == WEBKIT_CENTER)) {
   2544         // Other browsers center the margin box for align=center elements so we match them here.
   2545         LayoutUnit marginStartWidth = minimumValueForLength(marginStartLength, containerWidth, renderView);
   2546         LayoutUnit marginEndWidth = minimumValueForLength(marginEndLength, containerWidth, renderView);
   2547         LayoutUnit centeredMarginBoxStart = max<LayoutUnit>(0, (containerWidth - childWidth - marginStartWidth - marginEndWidth) / 2);
   2548         marginStart = centeredMarginBoxStart + marginStartWidth;
   2549         marginEnd = containerWidth - childWidth - marginStart + marginEndWidth;
   2550         return;
   2551     }
   2552 
   2553     // Case Two: The object is being pushed to the start of the containing block's available logical width.
   2554     if (marginEndLength.isAuto() && childWidth < containerWidth) {
   2555         marginStart = valueForLength(marginStartLength, containerWidth, renderView);
   2556         marginEnd = containerWidth - childWidth - marginStart;
   2557         return;
   2558     }
   2559 
   2560     // Case Three: The object is being pushed to the end of the containing block's available logical width.
   2561     bool pushToEndFromTextAlign = !marginEndLength.isAuto() && ((!containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_LEFT)
   2562         || (containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_RIGHT));
   2563     if ((marginStartLength.isAuto() && childWidth < containerWidth) || pushToEndFromTextAlign) {
   2564         marginEnd = valueForLength(marginEndLength, containerWidth, renderView);
   2565         marginStart = containerWidth - childWidth - marginEnd;
   2566         return;
   2567     }
   2568 
   2569     // Case Four: Either no auto margins, or our width is >= the container width (css2.1, 10.3.3).  In that case
   2570     // auto margins will just turn into 0.
   2571     marginStart = minimumValueForLength(marginStartLength, containerWidth, renderView);
   2572     marginEnd = minimumValueForLength(marginEndLength, containerWidth, renderView);
   2573 }
   2574 
   2575 RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, RenderBoxRegionInfoFlags cacheFlag) const
   2576 {
   2577     // Make sure nobody is trying to call this with a null region.
   2578     if (!region)
   2579         return 0;
   2580 
   2581     // If we have computed our width in this region already, it will be cached, and we can
   2582     // just return it.
   2583     RenderBoxRegionInfo* boxInfo = region->renderBoxRegionInfo(this);
   2584     if (boxInfo && cacheFlag == CacheRenderBoxRegionInfo)
   2585         return boxInfo;
   2586 
   2587     // No cached value was found, so we have to compute our insets in this region.
   2588     // FIXME: For now we limit this computation to normal RenderBlocks. Future patches will expand
   2589     // support to cover all boxes.
   2590     RenderFlowThread* flowThread = flowThreadContainingBlock();
   2591     if (isRenderFlowThread() || !flowThread || !canHaveBoxInfoInRegion() || flowThread->style()->writingMode() != style()->writingMode())
   2592         return 0;
   2593 
   2594     LogicalExtentComputedValues computedValues;
   2595     computeLogicalWidthInRegion(computedValues, region);
   2596 
   2597     // Now determine the insets based off where this object is supposed to be positioned.
   2598     RenderBlock* cb = containingBlock();
   2599     RenderRegion* clampedContainingBlockRegion = cb->clampToStartAndEndRegions(region);
   2600     RenderBoxRegionInfo* containingBlockInfo = cb->renderBoxRegionInfo(clampedContainingBlockRegion);
   2601     LayoutUnit containingBlockLogicalWidth = cb->logicalWidth();
   2602     LayoutUnit containingBlockLogicalWidthInRegion = containingBlockInfo ? containingBlockInfo->logicalWidth() : containingBlockLogicalWidth;
   2603 
   2604     LayoutUnit marginStartInRegion = computedValues.m_margins.m_start;
   2605     LayoutUnit startMarginDelta = marginStartInRegion - marginStart();
   2606     LayoutUnit logicalWidthInRegion = computedValues.m_extent;
   2607     LayoutUnit logicalLeftInRegion = computedValues.m_position;
   2608     LayoutUnit widthDelta = logicalWidthInRegion - logicalWidth();
   2609     LayoutUnit logicalLeftDelta = isOutOfFlowPositioned() ? logicalLeftInRegion - logicalLeft() : startMarginDelta;
   2610     LayoutUnit logicalRightInRegion = containingBlockLogicalWidthInRegion - (logicalLeftInRegion + logicalWidthInRegion);
   2611     LayoutUnit oldLogicalRight = containingBlockLogicalWidth - (logicalLeft() + logicalWidth());
   2612     LayoutUnit logicalRightDelta = isOutOfFlowPositioned() ? logicalRightInRegion - oldLogicalRight : startMarginDelta;
   2613 
   2614     LayoutUnit logicalLeftOffset = 0;
   2615 
   2616     if (!isOutOfFlowPositioned() && avoidsFloats() && cb->containsFloats()) {
   2617         LayoutUnit startPositionDelta = cb->computeStartPositionDeltaForChildAvoidingFloats(this, marginStartInRegion, region);
   2618         if (cb->style()->isLeftToRightDirection())
   2619             logicalLeftDelta += startPositionDelta;
   2620         else
   2621             logicalRightDelta += startPositionDelta;
   2622     }
   2623 
   2624     if (cb->style()->isLeftToRightDirection())
   2625         logicalLeftOffset += logicalLeftDelta;
   2626     else
   2627         logicalLeftOffset -= (widthDelta + logicalRightDelta);
   2628 
   2629     LayoutUnit logicalRightOffset = logicalWidth() - (logicalLeftOffset + logicalWidthInRegion);
   2630     bool isShifted = (containingBlockInfo && containingBlockInfo->isShifted())
   2631             || (style()->isLeftToRightDirection() && logicalLeftOffset)
   2632             || (!style()->isLeftToRightDirection() && logicalRightOffset);
   2633 
   2634     // FIXME: Although it's unlikely, these boxes can go outside our bounds, and so we will need to incorporate them into overflow.
   2635     if (cacheFlag == CacheRenderBoxRegionInfo)
   2636         return region->setRenderBoxRegionInfo(this, logicalLeftOffset, logicalWidthInRegion, isShifted);
   2637     return new RenderBoxRegionInfo(logicalLeftOffset, logicalWidthInRegion, isShifted);
   2638 }
   2639 
   2640 static bool shouldFlipBeforeAfterMargins(const RenderStyle* containingBlockStyle, const RenderStyle* childStyle)
   2641 {
   2642     ASSERT(containingBlockStyle->isHorizontalWritingMode() != childStyle->isHorizontalWritingMode());
   2643     WritingMode childWritingMode = childStyle->writingMode();
   2644     bool shouldFlip = false;
   2645     switch (containingBlockStyle->writingMode()) {
   2646     case TopToBottomWritingMode:
   2647         shouldFlip = (childWritingMode == RightToLeftWritingMode);
   2648         break;
   2649     case BottomToTopWritingMode:
   2650         shouldFlip = (childWritingMode == RightToLeftWritingMode);
   2651         break;
   2652     case RightToLeftWritingMode:
   2653         shouldFlip = (childWritingMode == BottomToTopWritingMode);
   2654         break;
   2655     case LeftToRightWritingMode:
   2656         shouldFlip = (childWritingMode == BottomToTopWritingMode);
   2657         break;
   2658     }
   2659 
   2660     if (!containingBlockStyle->isLeftToRightDirection())
   2661         shouldFlip = !shouldFlip;
   2662 
   2663     return shouldFlip;
   2664 }
   2665 
   2666 void RenderBox::updateLogicalHeight()
   2667 {
   2668     m_intrinsicContentLogicalHeight = contentLogicalHeight();
   2669 
   2670     LogicalExtentComputedValues computedValues;
   2671     computeLogicalHeight(logicalHeight(), logicalTop(), computedValues);
   2672 
   2673     setLogicalHeight(computedValues.m_extent);
   2674     setLogicalTop(computedValues.m_position);
   2675     setMarginBefore(computedValues.m_margins.m_before);
   2676     setMarginAfter(computedValues.m_margins.m_after);
   2677 }
   2678 
   2679 void RenderBox::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
   2680 {
   2681     computedValues.m_extent = logicalHeight;
   2682     computedValues.m_position = logicalTop;
   2683 
   2684     // Cell height is managed by the table and inline non-replaced elements do not support a height property.
   2685     if (isTableCell() || (isInline() && !isReplaced()))
   2686         return;
   2687 
   2688     Length h;
   2689     if (isOutOfFlowPositioned())
   2690         computePositionedLogicalHeight(computedValues);
   2691     else {
   2692         RenderBlock* cb = containingBlock();
   2693         bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
   2694 
   2695         if (!hasPerpendicularContainingBlock) {
   2696             bool shouldFlipBeforeAfter = cb->style()->writingMode() != style()->writingMode();
   2697             computeBlockDirectionMargins(cb,
   2698                 shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
   2699                 shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
   2700         }
   2701 
   2702         // For tables, calculate margins only.
   2703         if (isTable()) {
   2704             if (hasPerpendicularContainingBlock) {
   2705                 bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb->style(), style());
   2706                 computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), computedValues.m_extent,
   2707                     shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
   2708                     shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
   2709             }
   2710             return;
   2711         }
   2712 
   2713         // FIXME: Account for block-flow in flexible boxes.
   2714         // https://bugs.webkit.org/show_bug.cgi?id=46418
   2715         bool inHorizontalBox = parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL;
   2716         bool stretching = parent()->style()->boxAlign() == BSTRETCH;
   2717         bool treatAsReplaced = shouldComputeSizeAsReplaced() && (!inHorizontalBox || !stretching);
   2718         bool checkMinMaxHeight = false;
   2719 
   2720         // The parent box is flexing us, so it has increased or decreased our height.  We have to
   2721         // grab our cached flexible height.
   2722         // FIXME: Account for block-flow in flexible boxes.
   2723         // https://bugs.webkit.org/show_bug.cgi?id=46418
   2724         if (hasOverrideHeight() && parent()->isFlexibleBoxIncludingDeprecated())
   2725             h = Length(overrideLogicalContentHeight(), Fixed);
   2726         else if (treatAsReplaced)
   2727             h = Length(computeReplacedLogicalHeight(), Fixed);
   2728         else {
   2729             h = style()->logicalHeight();
   2730             checkMinMaxHeight = true;
   2731         }
   2732 
   2733         // Block children of horizontal flexible boxes fill the height of the box.
   2734         // FIXME: Account for block-flow in flexible boxes.
   2735         // https://bugs.webkit.org/show_bug.cgi?id=46418
   2736         if (h.isAuto() && parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
   2737                 && parent()->isStretchingChildren()) {
   2738             h = Length(parentBox()->contentLogicalHeight() - marginBefore() - marginAfter() - borderAndPaddingLogicalHeight(), Fixed);
   2739             checkMinMaxHeight = false;
   2740         }
   2741 
   2742         LayoutUnit heightResult;
   2743         if (checkMinMaxHeight) {
   2744             heightResult = computeLogicalHeightUsing(style()->logicalHeight(), computedValues.m_extent - borderAndPaddingLogicalHeight());
   2745             if (heightResult == -1)
   2746                 heightResult = computedValues.m_extent;
   2747             heightResult = constrainLogicalHeightByMinMax(heightResult, computedValues.m_extent - borderAndPaddingLogicalHeight());
   2748         } else {
   2749             // The only times we don't check min/max height are when a fixed length has
   2750             // been given as an override.  Just use that.  The value has already been adjusted
   2751             // for box-sizing.
   2752             ASSERT(h.isFixed());
   2753             heightResult = h.value() + borderAndPaddingLogicalHeight();
   2754         }
   2755 
   2756         computedValues.m_extent = heightResult;
   2757 
   2758         if (hasPerpendicularContainingBlock) {
   2759             bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb->style(), style());
   2760             computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), heightResult,
   2761                     shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
   2762                     shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
   2763         }
   2764     }
   2765 
   2766     // WinIE quirk: The <html> block always fills the entire canvas in quirks mode.  The <body> always fills the
   2767     // <html> block in quirks mode.  Only apply this quirk if the block is normal flow and no height
   2768     // is specified. When we're printing, we also need this quirk if the body or root has a percentage
   2769     // height since we don't set a height in RenderView when we're printing. So without this quirk, the
   2770     // height has nothing to be a percentage of, and it ends up being 0. That is bad.
   2771     bool paginatedContentNeedsBaseHeight = document().printing() && h.isPercent()
   2772         && (isRoot() || (isBody() && document().documentElement()->renderer()->style()->logicalHeight().isPercent())) && !isInline();
   2773     if (stretchesToViewport() || paginatedContentNeedsBaseHeight) {
   2774         LayoutUnit margins = collapsedMarginBefore() + collapsedMarginAfter();
   2775         LayoutUnit visibleHeight = viewLogicalHeightForPercentages();
   2776         if (isRoot())
   2777             computedValues.m_extent = max(computedValues.m_extent, visibleHeight - margins);
   2778         else {
   2779             LayoutUnit marginsBordersPadding = margins + parentBox()->marginBefore() + parentBox()->marginAfter() + parentBox()->borderAndPaddingLogicalHeight();
   2780             computedValues.m_extent = max(computedValues.m_extent, visibleHeight - marginsBordersPadding);
   2781         }
   2782     }
   2783 }
   2784 
   2785 LayoutUnit RenderBox::viewLogicalHeightForPercentages() const
   2786 {
   2787     if (document().printing())
   2788         return static_cast<LayoutUnit>(view()->pageLogicalHeight());
   2789     return view()->viewLogicalHeight();
   2790 }
   2791 
   2792 LayoutUnit RenderBox::computeLogicalHeightUsing(const Length& height, LayoutUnit intrinsicContentHeight) const
   2793 {
   2794     LayoutUnit logicalHeight = computeContentAndScrollbarLogicalHeightUsing(height, intrinsicContentHeight);
   2795     if (logicalHeight != -1)
   2796         logicalHeight = adjustBorderBoxLogicalHeightForBoxSizing(logicalHeight);
   2797     return logicalHeight;
   2798 }
   2799 
   2800 LayoutUnit RenderBox::computeContentLogicalHeight(const Length& height, LayoutUnit intrinsicContentHeight) const
   2801 {
   2802     LayoutUnit heightIncludingScrollbar = computeContentAndScrollbarLogicalHeightUsing(height, intrinsicContentHeight);
   2803     if (heightIncludingScrollbar == -1)
   2804         return -1;
   2805     return std::max<LayoutUnit>(0, adjustContentBoxLogicalHeightForBoxSizing(heightIncludingScrollbar) - scrollbarLogicalHeight());
   2806 }
   2807 
   2808 LayoutUnit RenderBox::computeIntrinsicLogicalContentHeightUsing(Length logicalHeightLength, LayoutUnit intrinsicContentHeight, LayoutUnit borderAndPadding) const
   2809 {
   2810     // FIXME(cbiesinger): The css-sizing spec is considering changing what min-content/max-content should resolve to.
   2811     // If that happens, this code will have to change.
   2812     if (logicalHeightLength.isMinContent() || logicalHeightLength.isMaxContent() || logicalHeightLength.isFitContent()) {
   2813         if (isReplaced())
   2814             return intrinsicSize().height();
   2815         if (m_intrinsicContentLogicalHeight != -1)
   2816             return m_intrinsicContentLogicalHeight;
   2817         return intrinsicContentHeight;
   2818     }
   2819     if (logicalHeightLength.isFillAvailable())
   2820         return containingBlock()->availableLogicalHeight(ExcludeMarginBorderPadding) - borderAndPadding;
   2821     ASSERT_NOT_REACHED();
   2822     return 0;
   2823 }
   2824 
   2825 LayoutUnit RenderBox::computeContentAndScrollbarLogicalHeightUsing(const Length& height, LayoutUnit intrinsicContentHeight) const
   2826 {
   2827     // FIXME(cbiesinger): The css-sizing spec is considering changing what min-content/max-content should resolve to.
   2828     // If that happens, this code will have to change.
   2829     if (height.isIntrinsic()) {
   2830         if (intrinsicContentHeight == -1)
   2831             return -1; // Intrinsic height isn't available.
   2832         return computeIntrinsicLogicalContentHeightUsing(height, intrinsicContentHeight, borderAndPaddingLogicalHeight());
   2833     }
   2834     if (height.isFixed())
   2835         return height.value();
   2836     if (height.isPercent())
   2837         return computePercentageLogicalHeight(height);
   2838     if (height.isViewportPercentage())
   2839         return valueForLength(height, 0, view());
   2840     return -1;
   2841 }
   2842 
   2843 bool RenderBox::skipContainingBlockForPercentHeightCalculation(const RenderBox* containingBlock) const
   2844 {
   2845     // For quirks mode and anonymous blocks, we skip auto-height containingBlocks when computing percentages.
   2846     // For standards mode, we treat the percentage as auto if it has an auto-height containing block.
   2847     if (!document().inQuirksMode() && !containingBlock->isAnonymousBlock())
   2848         return false;
   2849     return !containingBlock->isTableCell() && !containingBlock->isOutOfFlowPositioned() && containingBlock->style()->logicalHeight().isAuto() && isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode();
   2850 }
   2851 
   2852 LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) const
   2853 {
   2854     LayoutUnit availableHeight = -1;
   2855 
   2856     bool skippedAutoHeightContainingBlock = false;
   2857     RenderBlock* cb = containingBlock();
   2858     const RenderBox* containingBlockChild = this;
   2859     LayoutUnit rootMarginBorderPaddingHeight = 0;
   2860     while (!cb->isRenderView() && skipContainingBlockForPercentHeightCalculation(cb)) {
   2861         if (cb->isBody() || cb->isRoot())
   2862             rootMarginBorderPaddingHeight += cb->marginBefore() + cb->marginAfter() + cb->borderAndPaddingLogicalHeight();
   2863         skippedAutoHeightContainingBlock = true;
   2864         containingBlockChild = cb;
   2865         cb = cb->containingBlock();
   2866         cb->addPercentHeightDescendant(const_cast<RenderBox*>(this));
   2867     }
   2868 
   2869     RenderStyle* cbstyle = cb->style();
   2870 
   2871     // A positioned element that specified both top/bottom or that specifies height should be treated as though it has a height
   2872     // explicitly specified that can be used for any percentage computations.
   2873     bool isOutOfFlowPositionedWithSpecifiedHeight = cb->isOutOfFlowPositioned() && (!cbstyle->logicalHeight().isAuto() || (!cbstyle->logicalTop().isAuto() && !cbstyle->logicalBottom().isAuto()));
   2874 
   2875     bool includeBorderPadding = isTable();
   2876 
   2877     if (isHorizontalWritingMode() != cb->isHorizontalWritingMode())
   2878         availableHeight = containingBlockChild->containingBlockLogicalWidthForContent();
   2879     else if (hasOverrideContainingBlockLogicalHeight())
   2880         availableHeight = overrideContainingBlockContentLogicalHeight();
   2881     else if (cb->isTableCell()) {
   2882         if (!skippedAutoHeightContainingBlock) {
   2883             // Table cells violate what the CSS spec says to do with heights. Basically we
   2884             // don't care if the cell specified a height or not. We just always make ourselves
   2885             // be a percentage of the cell's current content height.
   2886             if (!cb->hasOverrideHeight()) {
   2887                 // Normally we would let the cell size intrinsically, but scrolling overflow has to be
   2888                 // treated differently, since WinIE lets scrolled overflow regions shrink as needed.
   2889                 // While we can't get all cases right, we can at least detect when the cell has a specified
   2890                 // height or when the table has a specified height. In these cases we want to initially have
   2891                 // no size and allow the flexing of the table or the cell to its specified height to cause us
   2892                 // to grow to fill the space. This could end up being wrong in some cases, but it is
   2893                 // preferable to the alternative (sizing intrinsically and making the row end up too big).
   2894                 RenderTableCell* cell = toRenderTableCell(cb);
   2895                 if (scrollsOverflowY() && (!cell->style()->logicalHeight().isAuto() || !cell->table()->style()->logicalHeight().isAuto()))
   2896                     return 0;
   2897                 return -1;
   2898             }
   2899             availableHeight = cb->overrideLogicalContentHeight();
   2900             includeBorderPadding = true;
   2901         }
   2902     } else if (cbstyle->logicalHeight().isFixed()) {
   2903         LayoutUnit contentBoxHeight = cb->adjustContentBoxLogicalHeightForBoxSizing(cbstyle->logicalHeight().value());
   2904         availableHeight = max<LayoutUnit>(0, cb->constrainContentBoxLogicalHeightByMinMax(contentBoxHeight - cb->scrollbarLogicalHeight(), -1));
   2905     } else if (cbstyle->logicalHeight().isPercent() && !isOutOfFlowPositionedWithSpecifiedHeight) {
   2906         // We need to recur and compute the percentage height for our containing block.
   2907         LayoutUnit heightWithScrollbar = cb->computePercentageLogicalHeight(cbstyle->logicalHeight());
   2908         if (heightWithScrollbar != -1) {
   2909             LayoutUnit contentBoxHeightWithScrollbar = cb->adjustContentBoxLogicalHeightForBoxSizing(heightWithScrollbar);
   2910             // We need to adjust for min/max height because this method does not
   2911             // handle the min/max of the current block, its caller does. So the
   2912             // return value from the recursive call will not have been adjusted
   2913             // yet.
   2914             LayoutUnit contentBoxHeight = cb->constrainContentBoxLogicalHeightByMinMax(contentBoxHeightWithScrollbar - cb->scrollbarLogicalHeight(), -1);
   2915             availableHeight = max<LayoutUnit>(0, contentBoxHeight);
   2916         }
   2917     } else if (cbstyle->logicalHeight().isViewportPercentage()) {
   2918         LayoutUnit heightWithScrollbar = valueForLength(cbstyle->logicalHeight(), 0, view());
   2919         if (heightWithScrollbar != -1) {
   2920             LayoutUnit contentBoxHeightWithScrollbar = cb->adjustContentBoxLogicalHeightForBoxSizing(heightWithScrollbar);
   2921             // We need to adjust for min/max height because this method does not
   2922             // handle the min/max of the current block, its caller does. So the
   2923             // return value from the recursive call will not have been adjusted
   2924             // yet.
   2925             LayoutUnit contentBoxHeight = cb->constrainContentBoxLogicalHeightByMinMax(contentBoxHeightWithScrollbar - cb->scrollbarLogicalHeight(), -1);
   2926             availableHeight = max<LayoutUnit>(0, contentBoxHeight);
   2927         }
   2928     } else if (isOutOfFlowPositionedWithSpecifiedHeight) {
   2929         // Don't allow this to affect the block' height() member variable, since this
   2930         // can get called while the block is still laying out its kids.
   2931         LogicalExtentComputedValues computedValues;
   2932         cb->computeLogicalHeight(cb->logicalHeight(), 0, computedValues);
   2933         availableHeight = computedValues.m_extent - cb->borderAndPaddingLogicalHeight() - cb->scrollbarLogicalHeight();
   2934     } else if (cb->isRenderView())
   2935         availableHeight = viewLogicalHeightForPercentages();
   2936 
   2937     if (availableHeight == -1)
   2938         return availableHeight;
   2939 
   2940     availableHeight -= rootMarginBorderPaddingHeight;
   2941 
   2942     LayoutUnit result = valueForLength(height, availableHeight);
   2943     if (includeBorderPadding) {
   2944         // FIXME: Table cells should default to box-sizing: border-box so we can avoid this hack.
   2945         // It is necessary to use the border-box to match WinIE's broken
   2946         // box model. This is essential for sizing inside
   2947         // table cells using percentage heights.
   2948         result -= borderAndPaddingLogicalHeight();
   2949         return max<LayoutUnit>(0, result);
   2950     }
   2951     return result;
   2952 }
   2953 
   2954 LayoutUnit RenderBox::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const
   2955 {
   2956     return computeReplacedLogicalWidthRespectingMinMaxWidth(computeReplacedLogicalWidthUsing(style()->logicalWidth()), shouldComputePreferred);
   2957 }
   2958 
   2959 LayoutUnit RenderBox::computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit logicalWidth, ShouldComputePreferred shouldComputePreferred) const
   2960 {
   2961     LayoutUnit minLogicalWidth = (shouldComputePreferred == ComputePreferred && style()->logicalMinWidth().isPercent()) || style()->logicalMinWidth().isUndefined() ? logicalWidth : computeReplacedLogicalWidthUsing(style()->logicalMinWidth());
   2962     LayoutUnit maxLogicalWidth = (shouldComputePreferred == ComputePreferred && style()->logicalMaxWidth().isPercent()) || style()->logicalMaxWidth().isUndefined() ? logicalWidth : computeReplacedLogicalWidthUsing(style()->logicalMaxWidth());
   2963     return max(minLogicalWidth, min(logicalWidth, maxLogicalWidth));
   2964 }
   2965 
   2966 LayoutUnit RenderBox::computeReplacedLogicalWidthUsing(Length logicalWidth) const
   2967 {
   2968     switch (logicalWidth.type()) {
   2969         case Fixed:
   2970             return adjustContentBoxLogicalWidthForBoxSizing(logicalWidth.value());
   2971         case MinContent:
   2972         case MaxContent: {
   2973             // MinContent/MaxContent don't need the availableLogicalWidth argument.
   2974             LayoutUnit availableLogicalWidth = 0;
   2975             return computeIntrinsicLogicalWidthUsing(logicalWidth, availableLogicalWidth, borderAndPaddingLogicalWidth()) - borderAndPaddingLogicalWidth();
   2976         }
   2977         case ViewportPercentageWidth:
   2978         case ViewportPercentageHeight:
   2979         case ViewportPercentageMin:
   2980         case ViewportPercentageMax:
   2981             return adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, 0, view()));
   2982         case FitContent:
   2983         case FillAvailable:
   2984         case Percent:
   2985         case Calculated: {
   2986             // FIXME: containingBlockLogicalWidthForContent() is wrong if the replaced element's block-flow is perpendicular to the
   2987             // containing block's block-flow.
   2988             // https://bugs.webkit.org/show_bug.cgi?id=46496
   2989             const LayoutUnit cw = isOutOfFlowPositioned() ? containingBlockLogicalWidthForPositioned(toRenderBoxModelObject(container())) : containingBlockLogicalWidthForContent();
   2990             Length containerLogicalWidth = containingBlock()->style()->logicalWidth();
   2991             // FIXME: Handle cases when containing block width is calculated or viewport percent.
   2992             // https://bugs.webkit.org/show_bug.cgi?id=91071
   2993             if (logicalWidth.isIntrinsic())
   2994                 return computeIntrinsicLogicalWidthUsing(logicalWidth, cw, borderAndPaddingLogicalWidth()) - borderAndPaddingLogicalWidth();
   2995             if (cw > 0 || (!cw && (containerLogicalWidth.isFixed() || containerLogicalWidth.isPercent())))
   2996                 return adjustContentBoxLogicalWidthForBoxSizing(minimumValueForLength(logicalWidth, cw));
   2997         }
   2998         // fall through
   2999         case Intrinsic:
   3000         case MinIntrinsic:
   3001         case Auto:
   3002         case ExtendToZoom:
   3003         case Undefined:
   3004             return intrinsicLogicalWidth();
   3005     }
   3006 
   3007     ASSERT_NOT_REACHED();
   3008     return 0;
   3009 }
   3010 
   3011 LayoutUnit RenderBox::computeReplacedLogicalHeight() const
   3012 {
   3013     return computeReplacedLogicalHeightRespectingMinMaxHeight(computeReplacedLogicalHeightUsing(style()->logicalHeight()));
   3014 }
   3015 
   3016 LayoutUnit RenderBox::computeReplacedLogicalHeightRespectingMinMaxHeight(LayoutUnit logicalHeight) const
   3017 {
   3018     LayoutUnit minLogicalHeight = computeReplacedLogicalHeightUsing(style()->logicalMinHeight());
   3019     LayoutUnit maxLogicalHeight = style()->logicalMaxHeight().isUndefined() ? logicalHeight : computeReplacedLogicalHeightUsing(style()->logicalMaxHeight());
   3020     return max(minLogicalHeight, min(logicalHeight, maxLogicalHeight));
   3021 }
   3022 
   3023 LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(Length logicalHeight) const
   3024 {
   3025     switch (logicalHeight.type()) {
   3026         case Fixed:
   3027             return adjustContentBoxLogicalHeightForBoxSizing(logicalHeight.value());
   3028         case Percent:
   3029         case Calculated:
   3030         {
   3031             RenderObject* cb = isOutOfFlowPositioned() ? container() : containingBlock();
   3032             while (cb->isAnonymous()) {
   3033                 cb = cb->containingBlock();
   3034                 toRenderBlock(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this));
   3035             }
   3036 
   3037             // FIXME: This calculation is not patched for block-flow yet.
   3038             // https://bugs.webkit.org/show_bug.cgi?id=46500
   3039             if (cb->isOutOfFlowPositioned() && cb->style()->height().isAuto() && !(cb->style()->top().isAuto() || cb->style()->bottom().isAuto())) {
   3040                 ASSERT_WITH_SECURITY_IMPLICATION(cb->isRenderBlock());
   3041                 RenderBlock* block = toRenderBlock(cb);
   3042                 LogicalExtentComputedValues computedValues;
   3043                 block->computeLogicalHeight(block->logicalHeight(), 0, computedValues);
   3044                 LayoutUnit newContentHeight = computedValues.m_extent - block->borderAndPaddingLogicalHeight() - block->scrollbarLogicalHeight();
   3045                 LayoutUnit newHeight = block->adjustContentBoxLogicalHeightForBoxSizing(newContentHeight);
   3046                 return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeight, newHeight));
   3047             }
   3048 
   3049             // FIXME: availableLogicalHeight() is wrong if the replaced element's block-flow is perpendicular to the
   3050             // containing block's block-flow.
   3051             // https://bugs.webkit.org/show_bug.cgi?id=46496
   3052             LayoutUnit availableHeight;
   3053             if (isOutOfFlowPositioned())
   3054                 availableHeight = containingBlockLogicalHeightForPositioned(toRenderBoxModelObject(cb));
   3055             else {
   3056                 availableHeight = containingBlockLogicalHeightForContent(IncludeMarginBorderPadding);
   3057                 // It is necessary to use the border-box to match WinIE's broken
   3058                 // box model.  This is essential for sizing inside
   3059                 // table cells using percentage heights.
   3060                 // FIXME: This needs to be made block-flow-aware.  If the cell and image are perpendicular block-flows, this isn't right.
   3061                 // https://bugs.webkit.org/show_bug.cgi?id=46997
   3062                 while (cb && !cb->isRenderView() && (cb->style()->logicalHeight().isAuto() || cb->style()->logicalHeight().isPercent())) {
   3063                     if (cb->isTableCell()) {
   3064                         // Don't let table cells squeeze percent-height replaced elements
   3065                         // <http://bugs.webkit.org/show_bug.cgi?id=15359>
   3066                         availableHeight = max(availableHeight, intrinsicLogicalHeight());
   3067                         return valueForLength(logicalHeight, availableHeight - borderAndPaddingLogicalHeight());
   3068                     }
   3069                     toRenderBlock(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this));
   3070                     cb = cb->containingBlock();
   3071                 }
   3072             }
   3073             return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeight, availableHeight));
   3074         }
   3075         case ViewportPercentageWidth:
   3076         case ViewportPercentageHeight:
   3077         case ViewportPercentageMin:
   3078         case ViewportPercentageMax:
   3079             return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeight, 0, view()));
   3080         case MinContent:
   3081         case MaxContent:
   3082         case FitContent:
   3083         case FillAvailable:
   3084             return adjustContentBoxLogicalHeightForBoxSizing(computeIntrinsicLogicalContentHeightUsing(logicalHeight, intrinsicLogicalHeight(), borderAndPaddingHeight()));
   3085         default:
   3086             return intrinsicLogicalHeight();
   3087     }
   3088 }
   3089 
   3090 LayoutUnit RenderBox::availableLogicalHeight(AvailableLogicalHeightType heightType) const
   3091 {
   3092     return constrainLogicalHeightByMinMax(availableLogicalHeightUsing(style()->logicalHeight(), heightType), -1);
   3093 }
   3094 
   3095 LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h, AvailableLogicalHeightType heightType) const
   3096 {
   3097     if (isRenderView())
   3098         return isHorizontalWritingMode() ? toRenderView(this)->frameView()->visibleHeight() : toRenderView(this)->frameView()->visibleWidth();
   3099 
   3100     // We need to stop here, since we don't want to increase the height of the table
   3101     // artificially.  We're going to rely on this cell getting expanded to some new
   3102     // height, and then when we lay out again we'll use the calculation below.
   3103     if (isTableCell() && (h.isAuto() || h.isPercent())) {
   3104         if (hasOverrideHeight())
   3105             return overrideLogicalContentHeight();
   3106         return logicalHeight() - borderAndPaddingLogicalHeight();
   3107     }
   3108 
   3109     if (h.isPercent() && isOutOfFlowPositioned() && !isRenderFlowThread()) {
   3110         // FIXME: This is wrong if the containingBlock has a perpendicular writing mode.
   3111         LayoutUnit availableHeight = containingBlockLogicalHeightForPositioned(containingBlock());
   3112         return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(h, availableHeight));
   3113     }
   3114 
   3115     LayoutUnit heightIncludingScrollbar = computeContentAndScrollbarLogicalHeightUsing(h, -1);
   3116     if (heightIncludingScrollbar != -1)
   3117         return std::max<LayoutUnit>(0, adjustContentBoxLogicalHeightForBoxSizing(heightIncludingScrollbar) - scrollbarLogicalHeight());
   3118 
   3119     // FIXME: Check logicalTop/logicalBottom here to correctly handle vertical writing-mode.
   3120     // https://bugs.webkit.org/show_bug.cgi?id=46500
   3121     if (isRenderBlock() && isOutOfFlowPositioned() && style()->height().isAuto() && !(style()->top().isAuto() || style()->bottom().isAuto())) {
   3122         RenderBlock* block = const_cast<RenderBlock*>(toRenderBlock(this));
   3123         LogicalExtentComputedValues computedValues;
   3124         block->computeLogicalHeight(block->logicalHeight(), 0, computedValues);
   3125         LayoutUnit newContentHeight = computedValues.m_extent - block->borderAndPaddingLogicalHeight() - block->scrollbarLogicalHeight();
   3126         return adjustContentBoxLogicalHeightForBoxSizing(newContentHeight);
   3127     }
   3128 
   3129     // FIXME: This is wrong if the containingBlock has a perpendicular writing mode.
   3130     LayoutUnit availableHeight = containingBlockLogicalHeightForContent(heightType);
   3131     if (heightType == ExcludeMarginBorderPadding) {
   3132         // FIXME: Margin collapsing hasn't happened yet, so this incorrectly removes collapsed margins.
   3133         availableHeight -= marginBefore() + marginAfter() + borderAndPaddingLogicalHeight();
   3134     }
   3135     return availableHeight;
   3136 }
   3137 
   3138 void RenderBox::computeBlockDirectionMargins(const RenderBlock* containingBlock, LayoutUnit& marginBefore, LayoutUnit& marginAfter) const
   3139 {
   3140     if (isTableCell()) {
   3141         // FIXME: Not right if we allow cells to have different directionality than the table.  If we do allow this, though,
   3142         // we may just do it with an extra anonymous block inside the cell.
   3143         marginBefore = 0;
   3144         marginAfter = 0;
   3145         return;
   3146     }
   3147 
   3148     // Margins are calculated with respect to the logical width of
   3149     // the containing block (8.3)
   3150     LayoutUnit cw = containingBlockLogicalWidthForContent();
   3151     RenderView* renderView = view();
   3152     RenderStyle* containingBlockStyle = containingBlock->style();
   3153     marginBefore = minimumValueForLength(style()->marginBeforeUsing(containingBlockStyle), cw, renderView);
   3154     marginAfter = minimumValueForLength(style()->marginAfterUsing(containingBlockStyle), cw, renderView);
   3155 }
   3156 
   3157 void RenderBox::computeAndSetBlockDirectionMargins(const RenderBlock* containingBlock)
   3158 {
   3159     LayoutUnit marginBefore;
   3160     LayoutUnit marginAfter;
   3161     computeBlockDirectionMargins(containingBlock, marginBefore, marginAfter);
   3162     containingBlock->setMarginBeforeForChild(this, marginBefore);
   3163     containingBlock->setMarginAfterForChild(this, marginAfter);
   3164 }
   3165 
   3166 LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* region, bool checkForPerpendicularWritingMode) const
   3167 {
   3168     if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
   3169         return containingBlockLogicalHeightForPositioned(containingBlock, false);
   3170 
   3171     // Use viewport as container for top-level fixed-position elements.
   3172     if (style()->position() == FixedPosition && containingBlock->isRenderView()) {
   3173         const RenderView* view = toRenderView(containingBlock);
   3174         if (FrameView* frameView = view->frameView()) {
   3175             LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
   3176             return containingBlock->isHorizontalWritingMode() ? viewportRect.width() : viewportRect.height();
   3177         }
   3178     }
   3179 
   3180     if (containingBlock->isBox()) {
   3181         RenderFlowThread* flowThread = flowThreadContainingBlock();
   3182         if (!flowThread)
   3183             return toRenderBox(containingBlock)->clientLogicalWidth();
   3184 
   3185         const RenderBlock* cb = toRenderBlock(containingBlock);
   3186         RenderBoxRegionInfo* boxInfo = 0;
   3187         if (!region) {
   3188             if (containingBlock->isRenderFlowThread() && !checkForPerpendicularWritingMode)
   3189                 return toRenderFlowThread(containingBlock)->contentLogicalWidthOfFirstRegion();
   3190             if (isWritingModeRoot()) {
   3191                 LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage();
   3192                 RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
   3193                 if (cbRegion) {
   3194                     cbRegion = cb->clampToStartAndEndRegions(cbRegion);
   3195                     boxInfo = cb->renderBoxRegionInfo(cbRegion);
   3196                 }
   3197             }
   3198         } else if (region && flowThread->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode()) {
   3199             RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region);
   3200             boxInfo = cb->renderBoxRegionInfo(containingBlockRegion);
   3201         }
   3202         return (boxInfo) ? max<LayoutUnit>(0, cb->clientLogicalWidth() - (cb->logicalWidth() - boxInfo->logicalWidth())) : cb->clientLogicalWidth();
   3203     }
   3204 
   3205     ASSERT(containingBlock->isRenderInline() && containingBlock->isInFlowPositioned());
   3206 
   3207     const RenderInline* flow = toRenderInline(containingBlock);
   3208     InlineFlowBox* first = flow->firstLineBox();
   3209     InlineFlowBox* last = flow->lastLineBox();
   3210 
   3211     // If the containing block is empty, return a width of 0.
   3212     if (!first || !last)
   3213         return 0;
   3214 
   3215     LayoutUnit fromLeft;
   3216     LayoutUnit fromRight;
   3217     if (containingBlock->style()->isLeftToRightDirection()) {
   3218         fromLeft = first->logicalLeft() + first->borderLogicalLeft();
   3219         fromRight = last->logicalLeft() + last->logicalWidth() - last->borderLogicalRight();
   3220     } else {
   3221         fromRight = first->logicalLeft() + first->logicalWidth() - first->borderLogicalRight();
   3222         fromLeft = last->logicalLeft() + last->borderLogicalLeft();
   3223     }
   3224 
   3225     return max<LayoutUnit>(0, fromRight - fromLeft);
   3226 }
   3227 
   3228 LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode) const
   3229 {
   3230     if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
   3231         return containingBlockLogicalWidthForPositioned(containingBlock, 0, false);
   3232 
   3233     // Use viewport as container for top-level fixed-position elements.
   3234     if (style()->position() == FixedPosition && containingBlock->isRenderView()) {
   3235         const RenderView* view = toRenderView(containingBlock);
   3236         if (FrameView* frameView = view->frameView()) {
   3237             LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
   3238             return containingBlock->isHorizontalWritingMode() ? viewportRect.height() : viewportRect.width();
   3239         }
   3240     }
   3241 
   3242     if (containingBlock->isBox()) {
   3243         const RenderBlock* cb = toRenderBlock(containingBlock);
   3244         LayoutUnit result = cb->clientLogicalHeight();
   3245         RenderFlowThread* flowThread = flowThreadContainingBlock();
   3246         if (flowThread && containingBlock->isRenderFlowThread() && flowThread->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode())
   3247             return toRenderFlowThread(containingBlock)->contentLogicalHeightOfFirstRegion();
   3248         return result;
   3249     }
   3250 
   3251     ASSERT(containingBlock->isRenderInline() && containingBlock->isInFlowPositioned());
   3252 
   3253     const RenderInline* flow = toRenderInline(containingBlock);
   3254     InlineFlowBox* first = flow->firstLineBox();
   3255     InlineFlowBox* last = flow->lastLineBox();
   3256 
   3257     // If the containing block is empty, return a height of 0.
   3258     if (!first || !last)
   3259         return 0;
   3260 
   3261     LayoutUnit heightResult;
   3262     LayoutRect boundingBox = flow->linesBoundingBox();
   3263     if (containingBlock->isHorizontalWritingMode())
   3264         heightResult = boundingBox.height();
   3265     else
   3266         heightResult = boundingBox.width();
   3267     heightResult -= (containingBlock->borderBefore() + containingBlock->borderAfter());
   3268     return heightResult;
   3269 }
   3270 
   3271 static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRight, const RenderBox* child, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth, RenderRegion* region)
   3272 {
   3273     if (!logicalLeft.isAuto() || !logicalRight.isAuto())
   3274         return;
   3275 
   3276     // FIXME: The static distance computation has not been patched for mixed writing modes yet.
   3277     if (child->parent()->style()->direction() == LTR) {
   3278         LayoutUnit staticPosition = child->layer()->staticInlinePosition() - containerBlock->borderLogicalLeft();
   3279         for (RenderObject* curr = child->parent(); curr && curr != containerBlock; curr = curr->container()) {
   3280             if (curr->isBox()) {
   3281                 staticPosition += toRenderBox(curr)->logicalLeft();
   3282                 if (toRenderBox(curr)->isRelPositioned())
   3283                     staticPosition += toRenderBox(curr)->relativePositionOffset().width();
   3284                 if (region && curr->isRenderBlock()) {
   3285                     const RenderBlock* cb = toRenderBlock(curr);
   3286                     region = cb->clampToStartAndEndRegions(region);
   3287                     RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region);
   3288                     if (boxInfo)
   3289                         staticPosition += boxInfo->logicalLeft();
   3290                 }
   3291             } else if (curr->isInline()) {
   3292                 if (curr->isRelPositioned()) {
   3293                     if (!curr->style()->logicalLeft().isAuto())
   3294                         staticPosition += curr->style()->logicalLeft().value();
   3295                     else
   3296                         staticPosition -= curr->style()->logicalRight().value();
   3297                 }
   3298             }
   3299         }
   3300         logicalLeft.setValue(Fixed, staticPosition);
   3301     } else {
   3302         RenderBox* enclosingBox = child->parent()->enclosingBox();
   3303         LayoutUnit staticPosition = child->layer()->staticInlinePosition() + containerLogicalWidth + containerBlock->borderLogicalLeft();
   3304         for (RenderObject* curr = child->parent(); curr; curr = curr->container()) {
   3305             if (curr->isBox()) {
   3306                 if (curr != containerBlock) {
   3307                     staticPosition -= toRenderBox(curr)->logicalLeft();
   3308                     if (toRenderBox(curr)->isRelPositioned())
   3309                         staticPosition -= toRenderBox(curr)->relativePositionOffset().width();
   3310                 }
   3311                 if (curr == enclosingBox)
   3312                     staticPosition -= enclosingBox->logicalWidth();
   3313                 if (region && curr->isRenderBlock()) {
   3314                     const RenderBlock* cb = toRenderBlock(curr);
   3315                     region = cb->clampToStartAndEndRegions(region);
   3316                     RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region);
   3317                     if (boxInfo) {
   3318                         if (curr != containerBlock)
   3319                             staticPosition -= cb->logicalWidth() - (boxInfo->logicalLeft() + boxInfo->logicalWidth());
   3320                         if (curr == enclosingBox)
   3321                             staticPosition += enclosingBox->logicalWidth() - boxInfo->logicalWidth();
   3322                     }
   3323                 }
   3324             } else if (curr->isInline()) {
   3325                 if (curr->isRelPositioned()) {
   3326                     if (!curr->style()->logicalLeft().isAuto())
   3327                         staticPosition -= curr->style()->logicalLeft().value();
   3328                     else
   3329                         staticPosition += curr->style()->logicalRight().value();
   3330                 }
   3331             }
   3332             if (curr == containerBlock)
   3333                 break;
   3334         }
   3335         logicalRight.setValue(Fixed, staticPosition);
   3336     }
   3337 }
   3338 
   3339 void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& computedValues, RenderRegion* region) const
   3340 {
   3341     if (isReplaced()) {
   3342         // FIXME: Positioned replaced elements inside a flow thread are not working properly
   3343         // with variable width regions (see https://bugs.webkit.org/show_bug.cgi?id=69896 ).
   3344         computePositionedLogicalWidthReplaced(computedValues);
   3345         return;
   3346     }
   3347 
   3348     // QUESTIONS
   3349     // FIXME 1: Should we still deal with these the cases of 'left' or 'right' having
   3350     // the type 'static' in determining whether to calculate the static distance?
   3351     // NOTE: 'static' is not a legal value for 'left' or 'right' as of CSS 2.1.
   3352 
   3353     // FIXME 2: Can perhaps optimize out cases when max-width/min-width are greater
   3354     // than or less than the computed width().  Be careful of box-sizing and
   3355     // percentage issues.
   3356 
   3357     // The following is based off of the W3C Working Draft from April 11, 2006 of
   3358     // CSS 2.1: Section 10.3.7 "Absolutely positioned, non-replaced elements"
   3359     // <http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width>
   3360     // (block-style-comments in this function and in computePositionedLogicalWidthUsing()
   3361     // correspond to text from the spec)
   3362 
   3363 
   3364     // We don't use containingBlock(), since we may be positioned by an enclosing
   3365     // relative positioned inline.
   3366     const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
   3367 
   3368     const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, region);
   3369 
   3370     // Use the container block's direction except when calculating the static distance
   3371     // This conforms with the reference results for abspos-replaced-width-margin-000.htm
   3372     // of the CSS 2.1 test suite
   3373     TextDirection containerDirection = containerBlock->style()->direction();
   3374 
   3375     bool isHorizontal = isHorizontalWritingMode();
   3376     const LayoutUnit bordersPlusPadding = borderAndPaddingLogicalWidth();
   3377     const Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop();
   3378     const Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom();
   3379 
   3380     Length logicalLeftLength = style()->logicalLeft();
   3381     Length logicalRightLength = style()->logicalRight();
   3382 
   3383     /*---------------------------------------------------------------------------*\
   3384      * For the purposes of this section and the next, the term "static position"
   3385      * (of an element) refers, roughly, to the position an element would have had
   3386      * in the normal flow. More precisely:
   3387      *
   3388      * * The static position for 'left' is the distance from the left edge of the
   3389      *   containing block to the left margin edge of a hypothetical box that would
   3390      *   have been the first box of the element if its 'position' property had
   3391      *   been 'static' and 'float' had been 'none'. The value is negative if the
   3392      *   hypothetical box is to the left of the containing block.
   3393      * * The static position for 'right' is the distance from the right edge of the
   3394      *   containing block to the right margin edge of the same hypothetical box as
   3395      *   above. The value is positive if the hypothetical box is to the left of the
   3396      *   containing block's edge.
   3397      *
   3398      * But rather than actually calculating the dimensions of that hypothetical box,
   3399      * user agents are free to make a guess at its probable position.
   3400      *
   3401      * For the purposes of calculating the static position, the containing block of
   3402      * fixed positioned elements is the initial containing block instead of the
   3403      * viewport, and all scrollable boxes should be assumed to be scrolled to their
   3404      * origin.
   3405     \*---------------------------------------------------------------------------*/
   3406 
   3407     // see FIXME 1
   3408     // Calculate the static distance if needed.
   3409     computeInlineStaticDistance(logicalLeftLength, logicalRightLength, this, containerBlock, containerLogicalWidth, region);
   3410 
   3411     // Calculate constraint equation values for 'width' case.
   3412     computePositionedLogicalWidthUsing(style()->logicalWidth(), containerBlock, containerDirection,
   3413                                        containerLogicalWidth, bordersPlusPadding,
   3414                                        logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
   3415                                        computedValues);
   3416 
   3417     // Calculate constraint equation values for 'max-width' case.
   3418     if (!style()->logicalMaxWidth().isUndefined()) {
   3419         LogicalExtentComputedValues maxValues;
   3420 
   3421         computePositionedLogicalWidthUsing(style()->logicalMaxWidth(), containerBlock, containerDirection,
   3422                                            containerLogicalWidth, bordersPlusPadding,
   3423                                            logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
   3424                                            maxValues);
   3425 
   3426         if (computedValues.m_extent > maxValues.m_extent) {
   3427             computedValues.m_extent = maxValues.m_extent;
   3428             computedValues.m_position = maxValues.m_position;
   3429             computedValues.m_margins.m_start = maxValues.m_margins.m_start;
   3430             computedValues.m_margins.m_end = maxValues.m_margins.m_end;
   3431         }
   3432     }
   3433 
   3434     // Calculate constraint equation values for 'min-width' case.
   3435     if (!style()->logicalMinWidth().isZero() || style()->logicalMinWidth().isIntrinsic()) {
   3436         LogicalExtentComputedValues minValues;
   3437 
   3438         computePositionedLogicalWidthUsing(style()->logicalMinWidth(), containerBlock, containerDirection,
   3439                                            containerLogicalWidth, bordersPlusPadding,
   3440                                            logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
   3441                                            minValues);
   3442 
   3443         if (computedValues.m_extent < minValues.m_extent) {
   3444             computedValues.m_extent = minValues.m_extent;
   3445             computedValues.m_position = minValues.m_position;
   3446             computedValues.m_margins.m_start = minValues.m_margins.m_start;
   3447             computedValues.m_margins.m_end = minValues.m_margins.m_end;
   3448         }
   3449     }
   3450 
   3451     computedValues.m_extent += bordersPlusPadding;
   3452 
   3453     // Adjust logicalLeft if we need to for the flipped version of our writing mode in regions.
   3454     // FIXME: Add support for other types of objects as containerBlock, not only RenderBlock.
   3455     RenderFlowThread* flowThread = flowThreadContainingBlock();
   3456     if (flowThread && !region && isWritingModeRoot() && isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode() && containerBlock->isRenderBlock()) {
   3457         ASSERT(containerBlock->canHaveBoxInfoInRegion());
   3458         LayoutUnit logicalLeftPos = computedValues.m_position;
   3459         const RenderBlock* cb = toRenderBlock(containerBlock);
   3460         LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage();
   3461         RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
   3462         if (cbRegion) {
   3463             cbRegion = cb->clampToStartAndEndRegions(cbRegion);
   3464             RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion);
   3465             if (boxInfo) {
   3466                 logicalLeftPos += boxInfo->logicalLeft();
   3467                 computedValues.m_position = logicalLeftPos;
   3468             }
   3469         }
   3470     }
   3471 }
   3472 
   3473 static void computeLogicalLeftPositionedOffset(LayoutUnit& logicalLeftPos, const RenderBox* child, LayoutUnit logicalWidthValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth)
   3474 {
   3475     // Deal with differing writing modes here.  Our offset needs to be in the containing block's coordinate space. If the containing block is flipped
   3476     // along this axis, then we need to flip the coordinate.  This can only happen if the containing block is both a flipped mode and perpendicular to us.
   3477     if (containerBlock->isHorizontalWritingMode() != child->isHorizontalWritingMode() && containerBlock->style()->isFlippedBlocksWritingMode()) {
   3478         logicalLeftPos = containerLogicalWidth - logicalWidthValue - logicalLeftPos;
   3479         logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderRight() : containerBlock->borderBottom());
   3480     } else
   3481         logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderLeft() : containerBlock->borderTop());
   3482 }
   3483 
   3484 void RenderBox::shrinkToFitWidth(const LayoutUnit availableSpace, const LayoutUnit logicalLeftValue, const LayoutUnit bordersPlusPadding, LogicalExtentComputedValues& computedValues) const
   3485 {
   3486     // FIXME: would it be better to have shrink-to-fit in one step?
   3487     LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
   3488     LayoutUnit preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding;
   3489     LayoutUnit availableWidth = availableSpace - logicalLeftValue;
   3490     computedValues.m_extent = min(max(preferredMinWidth, availableWidth), preferredWidth);
   3491 }
   3492 
   3493 void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const RenderBoxModelObject* containerBlock, TextDirection containerDirection,
   3494                                                    LayoutUnit containerLogicalWidth, LayoutUnit bordersPlusPadding,
   3495                                                    Length logicalLeft, Length logicalRight, Length marginLogicalLeft, Length marginLogicalRight,
   3496                                                    LogicalExtentComputedValues& computedValues) const
   3497 {
   3498     if (logicalWidth.isIntrinsic())
   3499         logicalWidth = Length(computeIntrinsicLogicalWidthUsing(logicalWidth, containerLogicalWidth, bordersPlusPadding) - bordersPlusPadding, Fixed);
   3500 
   3501     // 'left' and 'right' cannot both be 'auto' because one would of been
   3502     // converted to the static position already
   3503     ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));
   3504 
   3505     LayoutUnit logicalLeftValue = 0;
   3506 
   3507     const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, false);
   3508 
   3509     bool logicalWidthIsAuto = logicalWidth.isIntrinsicOrAuto();
   3510     bool logicalLeftIsAuto = logicalLeft.isAuto();
   3511     bool logicalRightIsAuto = logicalRight.isAuto();
   3512     RenderView* renderView = view();
   3513     LayoutUnit& marginLogicalLeftValue = style()->isLeftToRightDirection() ? computedValues.m_margins.m_start : computedValues.m_margins.m_end;
   3514     LayoutUnit& marginLogicalRightValue = style()->isLeftToRightDirection() ? computedValues.m_margins.m_end : computedValues.m_margins.m_start;
   3515     if (!logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
   3516         /*-----------------------------------------------------------------------*\
   3517          * If none of the three is 'auto': If both 'margin-left' and 'margin-
   3518          * right' are 'auto', solve the equation under the extra constraint that
   3519          * the two margins get equal values, unless this would make them negative,
   3520          * in which case when direction of the containing block is 'ltr' ('rtl'),
   3521          * set 'margin-left' ('margin-right') to zero and solve for 'margin-right'
   3522          * ('margin-left'). If one of 'margin-left' or 'margin-right' is 'auto',
   3523          * solve the equation for that value. If the values are over-constrained,
   3524          * ignore the value for 'left' (in case the 'direction' property of the
   3525          * containing block is 'rtl') or 'right' (in case 'direction' is 'ltr')
   3526          * and solve for that value.
   3527         \*-----------------------------------------------------------------------*/
   3528         // NOTE:  It is not necessary to solve for 'right' in the over constrained
   3529         // case because the value is not used for any further calculations.
   3530 
   3531         logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
   3532         computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth, renderView));
   3533 
   3534         const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth, renderView) + bordersPlusPadding);
   3535 
   3536         // Margins are now the only unknown
   3537         if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
   3538             // Both margins auto, solve for equality
   3539             if (availableSpace >= 0) {
   3540                 marginLogicalLeftValue = availableSpace / 2; // split the difference
   3541                 marginLogicalRightValue = availableSpace - marginLogicalLeftValue; // account for odd valued differences
   3542             } else {
   3543                 // Use the containing block's direction rather than the parent block's
   3544                 // per CSS 2.1 reference test abspos-non-replaced-width-margin-000.
   3545                 if (containerDirection == LTR) {
   3546                     marginLogicalLeftValue = 0;
   3547                     marginLogicalRightValue = availableSpace; // will be negative
   3548                 } else {
   3549                     marginLogicalLeftValue = availableSpace; // will be negative
   3550                     marginLogicalRightValue = 0;
   3551                 }
   3552             }
   3553         } else if (marginLogicalLeft.isAuto()) {
   3554             // Solve for left margin
   3555             marginLogicalRightValue = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
   3556             marginLogicalLeftValue = availableSpace - marginLogicalRightValue;
   3557         } else if (marginLogicalRight.isAuto()) {
   3558             // Solve for right margin
   3559             marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
   3560             marginLogicalRightValue = availableSpace - marginLogicalLeftValue;
   3561         } else {
   3562             // Over-constrained, solve for left if direction is RTL
   3563             marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
   3564             marginLogicalRightValue = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
   3565 
   3566             // Use the containing block's direction rather than the parent block's
   3567             // per CSS 2.1 reference test abspos-non-replaced-width-margin-000.
   3568             if (containerDirection == RTL)
   3569                 logicalLeftValue = (availableSpace + logicalLeftValue) - marginLogicalLeftValue - marginLogicalRightValue;
   3570         }
   3571     } else {
   3572         /*--------------------------------------------------------------------*\
   3573          * Otherwise, set 'auto' values for 'margin-left' and 'margin-right'
   3574          * to 0, and pick the one of the following six rules that applies.
   3575          *
   3576          * 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the
   3577          *    width is shrink-to-fit. Then solve for 'left'
   3578          *
   3579          *              OMIT RULE 2 AS IT SHOULD NEVER BE HIT
   3580          * ------------------------------------------------------------------
   3581          * 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if
   3582          *    the 'direction' property of the containing block is 'ltr' set
   3583          *    'left' to the static position, otherwise set 'right' to the
   3584          *    static position. Then solve for 'left' (if 'direction is 'rtl')
   3585          *    or 'right' (if 'direction' is 'ltr').
   3586          * ------------------------------------------------------------------
   3587          *
   3588          * 3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the
   3589          *    width is shrink-to-fit . Then solve for 'right'
   3590          * 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve
   3591          *    for 'left'
   3592          * 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve
   3593          *    for 'width'
   3594          * 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve
   3595          *    for 'right'
   3596          *
   3597          * Calculation of the shrink-to-fit width is similar to calculating the
   3598          * width of a table cell using the automatic table layout algorithm.
   3599          * Roughly: calculate the preferred width by formatting the content
   3600          * without breaking lines other than where explicit line breaks occur,
   3601          * and also calculate the preferred minimum width, e.g., by trying all
   3602          * possible line breaks. CSS 2.1 does not define the exact algorithm.
   3603          * Thirdly, calculate the available width: this is found by solving
   3604          * for 'width' after setting 'left' (in case 1) or 'right' (in case 3)
   3605          * to 0.
   3606          *
   3607          * Then the shrink-to-fit width is:
   3608          * min(max(preferred minimum width, available width), preferred width).
   3609         \*--------------------------------------------------------------------*/
   3610         // NOTE: For rules 3 and 6 it is not necessary to solve for 'right'
   3611         // because the value is not used for any further calculations.
   3612 
   3613         // Calculate margins, 'auto' margins are ignored.
   3614         marginLogicalLeftValue = minimumValueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
   3615         marginLogicalRightValue = minimumValueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
   3616 
   3617         const LayoutUnit availableSpace = containerLogicalWidth - (marginLogicalLeftValue + marginLogicalRightValue + bordersPlusPadding);
   3618 
   3619         // FIXME: Is there a faster way to find the correct case?
   3620         // Use rule/case that applies.
   3621         if (logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
   3622             // RULE 1: (use shrink-to-fit for width, and solve of left)
   3623             LayoutUnit logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
   3624 
   3625             // FIXME: would it be better to have shrink-to-fit in one step?
   3626             LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
   3627             LayoutUnit preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding;
   3628             LayoutUnit availableWidth = availableSpace - logicalRightValue;
   3629             computedValues.m_extent = min(max(preferredMinWidth, availableWidth), preferredWidth);
   3630             logicalLeftValue = availableSpace - (computedValues.m_extent + logicalRightValue);
   3631         } else if (!logicalLeftIsAuto && logicalWidthIsAuto && logicalRightIsAuto) {
   3632             // RULE 3: (use shrink-to-fit for width, and no need solve of right)
   3633             logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
   3634 
   3635             shrinkToFitWidth(availableSpace, logicalLeftValue, bordersPlusPadding, computedValues);
   3636         } else if (logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
   3637             // RULE 4: (solve for left)
   3638             computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth, renderView));
   3639             logicalLeftValue = availableSpace - (computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth, renderView));
   3640         } else if (!logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
   3641             // RULE 5: (solve for width)
   3642             logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
   3643             if (autoWidthShouldFitContent())
   3644                 shrinkToFitWidth(availableSpace, logicalLeftValue, bordersPlusPadding, computedValues);
   3645             else
   3646                 computedValues.m_extent = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth, renderView));
   3647         } else if (!logicalLeftIsAuto && !logicalWidthIsAuto && logicalRightIsAuto) {
   3648             // RULE 6: (no need solve for right)
   3649             logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
   3650             computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth, renderView));
   3651         }
   3652     }
   3653 
   3654     // Use computed values to calculate the horizontal position.
   3655 
   3656     // FIXME: This hack is needed to calculate the  logical left position for a 'rtl' relatively
   3657     // positioned, inline because right now, it is using the logical left position
   3658     // of the first line box when really it should use the last line box.  When
   3659     // this is fixed elsewhere, this block should be removed.
   3660     if (containerBlock->isRenderInline() && !containerBlock->style()->isLeftToRightDirection()) {
   3661         const RenderInline* flow = toRenderInline(containerBlock);
   3662         InlineFlowBox* firstLine = flow->firstLineBox();
   3663         InlineFlowBox* lastLine = flow->lastLineBox();
   3664         if (firstLine && lastLine && firstLine != lastLine) {
   3665             computedValues.m_position = logicalLeftValue + marginLogicalLeftValue + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft());
   3666             return;
   3667         }
   3668     }
   3669 
   3670     if (containerBlock->isBox() && toRenderBox(containerBlock)->scrollsOverflowY() && containerBlock->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
   3671         logicalLeftValue = logicalLeftValue + toRenderBox(containerBlock)->verticalScrollbarWidth();
   3672     }
   3673 
   3674     computedValues.m_position = logicalLeftValue + marginLogicalLeftValue;
   3675     computeLogicalLeftPositionedOffset(computedValues.m_position, this, computedValues.m_extent, containerBlock, containerLogicalWidth);
   3676 }
   3677 
   3678 static void computeBlockStaticDistance(Length& logicalTop, Length& logicalBottom, const RenderBox* child, const RenderBoxModelObject* containerBlock)
   3679 {
   3680     if (!logicalTop.isAuto() || !logicalBottom.isAuto())
   3681         return;
   3682 
   3683     // FIXME: The static distance computation has not been patched for mixed writing modes.
   3684     LayoutUnit staticLogicalTop = child->layer()->staticBlockPosition() - containerBlock->borderBefore();
   3685     for (RenderObject* curr = child->parent(); curr && curr != containerBlock; curr = curr->container()) {
   3686         if (curr->isBox() && !curr->isTableRow())
   3687             staticLogicalTop += toRenderBox(curr)->logicalTop();
   3688     }
   3689     logicalTop.setValue(Fixed, staticLogicalTop);
   3690 }
   3691 
   3692 void RenderBox::computePositionedLogicalHeight(LogicalExtentComputedValues& computedValues) const
   3693 {
   3694     if (isReplaced()) {
   3695         computePositionedLogicalHeightReplaced(computedValues);
   3696         return;
   3697     }
   3698 
   3699     // The following is based off of the W3C Working Draft from April 11, 2006 of
   3700     // CSS 2.1: Section 10.6.4 "Absolutely positioned, non-replaced elements"
   3701     // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-non-replaced-height>
   3702     // (block-style-comments in this function and in computePositionedLogicalHeightUsing()
   3703     // correspond to text from the spec)
   3704 
   3705 
   3706     // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
   3707     const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
   3708 
   3709     const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock);
   3710 
   3711     RenderStyle* styleToUse = style();
   3712     const LayoutUnit bordersPlusPadding = borderAndPaddingLogicalHeight();
   3713     const Length marginBefore = styleToUse->marginBefore();
   3714     const Length marginAfter = styleToUse->marginAfter();
   3715     Length logicalTopLength = styleToUse->logicalTop();
   3716     Length logicalBottomLength = styleToUse->logicalBottom();
   3717 
   3718     /*---------------------------------------------------------------------------*\
   3719      * For the purposes of this section and the next, the term "static position"
   3720      * (of an element) refers, roughly, to the position an element would have had
   3721      * in the normal flow. More precisely, the static position for 'top' is the
   3722      * distance from the top edge of the containing block to the top margin edge
   3723      * of a hypothetical box that would have been the first box of the element if
   3724      * its 'position' property had been 'static' and 'float' had been 'none'. The
   3725      * value is negative if the hypothetical box is above the containing block.
   3726      *
   3727      * But rather than actually calculating the dimensions of that hypothetical
   3728      * box, user agents are free to make a guess at its probable position.
   3729      *
   3730      * For the purposes of calculating the static position, the containing block
   3731      * of fixed positioned elements is the initial containing block instead of
   3732      * the viewport.
   3733     \*---------------------------------------------------------------------------*/
   3734 
   3735     // see FIXME 1
   3736     // Calculate the static distance if needed.
   3737     computeBlockStaticDistance(logicalTopLength, logicalBottomLength, this, containerBlock);
   3738 
   3739     // Calculate constraint equation values for 'height' case.
   3740     LayoutUnit logicalHeight = computedValues.m_extent;
   3741     computePositionedLogicalHeightUsing(styleToUse->logicalHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding, logicalHeight,
   3742                                         logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
   3743                                         computedValues);
   3744 
   3745     // Avoid doing any work in the common case (where the values of min-height and max-height are their defaults).
   3746     // see FIXME 2
   3747 
   3748     // Calculate constraint equation values for 'max-height' case.
   3749     if (!styleToUse->logicalMaxHeight().isUndefined()) {
   3750         LogicalExtentComputedValues maxValues;
   3751 
   3752         computePositionedLogicalHeightUsing(styleToUse->logicalMaxHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding, logicalHeight,
   3753                                             logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
   3754                                             maxValues);
   3755 
   3756         if (computedValues.m_extent > maxValues.m_extent) {
   3757             computedValues.m_extent = maxValues.m_extent;
   3758             computedValues.m_position = maxValues.m_position;
   3759             computedValues.m_margins.m_before = maxValues.m_margins.m_before;
   3760             computedValues.m_margins.m_after = maxValues.m_margins.m_after;
   3761         }
   3762     }
   3763 
   3764     // Calculate constraint equation values for 'min-height' case.
   3765     if (!styleToUse->logicalMinHeight().isZero() || styleToUse->logicalMinHeight().isIntrinsic()) {
   3766         LogicalExtentComputedValues minValues;
   3767 
   3768         computePositionedLogicalHeightUsing(styleToUse->logicalMinHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding, logicalHeight,
   3769                                             logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
   3770                                             minValues);
   3771 
   3772         if (computedValues.m_extent < minValues.m_extent) {
   3773             computedValues.m_extent = minValues.m_extent;
   3774             computedValues.m_position = minValues.m_position;
   3775             computedValues.m_margins.m_before = minValues.m_margins.m_before;
   3776             computedValues.m_margins.m_after = minValues.m_margins.m_after;
   3777         }
   3778     }
   3779 
   3780     // Set final height value.
   3781     computedValues.m_extent += bordersPlusPadding;
   3782 
   3783     // Adjust logicalTop if we need to for perpendicular writing modes in regions.
   3784     // FIXME: Add support for other types of objects as containerBlock, not only RenderBlock.
   3785     RenderFlowThread* flowThread = flowThreadContainingBlock();
   3786     if (flowThread && isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode() && containerBlock->isRenderBlock()) {
   3787         ASSERT(containerBlock->canHaveBoxInfoInRegion());
   3788         LayoutUnit logicalTopPos = computedValues.m_position;
   3789         const RenderBlock* cb = toRenderBlock(containerBlock);
   3790         LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage() - logicalLeft();
   3791         RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
   3792         if (cbRegion) {
   3793             cbRegion = cb->clampToStartAndEndRegions(cbRegion);
   3794             RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion);
   3795             if (boxInfo) {
   3796                 logicalTopPos += boxInfo->logicalLeft();
   3797                 computedValues.m_position = logicalTopPos;
   3798             }
   3799         }
   3800     }
   3801 }
   3802 
   3803 static void computeLogicalTopPositionedOffset(LayoutUnit& logicalTopPos, const RenderBox* child, LayoutUnit logicalHeightValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalHeight)
   3804 {
   3805     // Deal with differing writing modes here.  Our offset needs to be in the containing block's coordinate space. If the containing block is flipped
   3806     // along this axis, then we need to flip the coordinate.  This can only happen if the containing block is both a flipped mode and perpendicular to us.
   3807     if ((child->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode())
   3808         || (child->style()->isFlippedBlocksWritingMode() != containerBlock->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()))
   3809         logicalTopPos = containerLogicalHeight - logicalHeightValue - logicalTopPos;
   3810 
   3811     // Our offset is from the logical bottom edge in a flipped environment, e.g., right for vertical-rl and bottom for horizontal-bt.
   3812     if (containerBlock->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()) {
   3813         if (child->isHorizontalWritingMode())
   3814             logicalTopPos += containerBlock->borderBottom();
   3815         else
   3816             logicalTopPos += containerBlock->borderRight();
   3817     } else {
   3818         if (child->isHorizontalWritingMode())
   3819             logicalTopPos += containerBlock->borderTop();
   3820         else
   3821             logicalTopPos += containerBlock->borderLeft();
   3822     }
   3823 }
   3824 
   3825 void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength, const RenderBoxModelObject* containerBlock,
   3826                                                     LayoutUnit containerLogicalHeight, LayoutUnit bordersPlusPadding, LayoutUnit logicalHeight,
   3827                                                     Length logicalTop, Length logicalBottom, Length marginBefore, Length marginAfter,
   3828                                                     LogicalExtentComputedValues& computedValues) const
   3829 {
   3830     // 'top' and 'bottom' cannot both be 'auto' because 'top would of been
   3831     // converted to the static position in computePositionedLogicalHeight()
   3832     ASSERT(!(logicalTop.isAuto() && logicalBottom.isAuto()));
   3833 
   3834     LayoutUnit logicalHeightValue;
   3835     LayoutUnit contentLogicalHeight = logicalHeight - bordersPlusPadding;
   3836 
   3837     const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, false);
   3838 
   3839     LayoutUnit logicalTopValue = 0;
   3840 
   3841     bool logicalHeightIsAuto = logicalHeightLength.isAuto();
   3842     bool logicalTopIsAuto = logicalTop.isAuto();
   3843     bool logicalBottomIsAuto = logicalBottom.isAuto();
   3844     RenderView* renderView = view();
   3845 
   3846     LayoutUnit resolvedLogicalHeight;
   3847     // Height is never unsolved for tables.
   3848     if (isTable()) {
   3849         resolvedLogicalHeight = contentLogicalHeight;
   3850         logicalHeightIsAuto = false;
   3851     } else {
   3852         if (logicalHeightLength.isIntrinsic())
   3853             resolvedLogicalHeight = computeIntrinsicLogicalContentHeightUsing(logicalHeightLength, contentLogicalHeight, bordersPlusPadding);
   3854         else
   3855             resolvedLogicalHeight = adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeightLength, containerLogicalHeight, renderView));
   3856     }
   3857 
   3858     if (!logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
   3859         /*-----------------------------------------------------------------------*\
   3860          * If none of the three are 'auto': If both 'margin-top' and 'margin-
   3861          * bottom' are 'auto', solve the equation under the extra constraint that
   3862          * the two margins get equal values. If one of 'margin-top' or 'margin-
   3863          * bottom' is 'auto', solve the equation for that value. If the values
   3864          * are over-constrained, ignore the value for 'bottom' and solve for that
   3865          * value.
   3866         \*-----------------------------------------------------------------------*/
   3867         // NOTE:  It is not necessary to solve for 'bottom' in the over constrained
   3868         // case because the value is not used for any further calculations.
   3869 
   3870         logicalHeightValue = resolvedLogicalHeight;
   3871         logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
   3872 
   3873         const LayoutUnit availableSpace = containerLogicalHeight - (logicalTopValue + logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView) + bordersPlusPadding);
   3874 
   3875         // Margins are now the only unknown
   3876         if (marginBefore.isAuto() && marginAfter.isAuto()) {
   3877             // Both margins auto, solve for equality
   3878             // NOTE: This may result in negative values.
   3879             computedValues.m_margins.m_before = availableSpace / 2; // split the difference
   3880             computedValues.m_margins.m_after = availableSpace - computedValues.m_margins.m_before; // account for odd valued differences
   3881         } else if (marginBefore.isAuto()) {
   3882             // Solve for top margin
   3883             computedValues.m_margins.m_after = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
   3884             computedValues.m_margins.m_before = availableSpace - computedValues.m_margins.m_after;
   3885         } else if (marginAfter.isAuto()) {
   3886             // Solve for bottom margin
   3887             computedValues.m_margins.m_before = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
   3888             computedValues.m_margins.m_after = availableSpace - computedValues.m_margins.m_before;
   3889         } else {
   3890             // Over-constrained, (no need solve for bottom)
   3891             computedValues.m_margins.m_before = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
   3892             computedValues.m_margins.m_after = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
   3893         }
   3894     } else {
   3895         /*--------------------------------------------------------------------*\
   3896          * Otherwise, set 'auto' values for 'margin-top' and 'margin-bottom'
   3897          * to 0, and pick the one of the following six rules that applies.
   3898          *
   3899          * 1. 'top' and 'height' are 'auto' and 'bottom' is not 'auto', then
   3900          *    the height is based on the content, and solve for 'top'.
   3901          *
   3902          *              OMIT RULE 2 AS IT SHOULD NEVER BE HIT
   3903          * ------------------------------------------------------------------
   3904          * 2. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then
   3905          *    set 'top' to the static position, and solve for 'bottom'.
   3906          * ------------------------------------------------------------------
   3907          *
   3908          * 3. 'height' and 'bottom' are 'auto' and 'top' is not 'auto', then
   3909          *    the height is based on the content, and solve for 'bottom'.
   3910          * 4. 'top' is 'auto', 'height' and 'bottom' are not 'auto', and
   3911          *    solve for 'top'.
   3912          * 5. 'height' is 'auto', 'top' and 'bottom' are not 'auto', and
   3913          *    solve for 'height'.
   3914          * 6. 'bottom' is 'auto', 'top' and 'height' are not 'auto', and
   3915          *    solve for 'bottom'.
   3916         \*--------------------------------------------------------------------*/
   3917         // NOTE: For rules 3 and 6 it is not necessary to solve for 'bottom'
   3918         // because the value is not used for any further calculations.
   3919 
   3920         // Calculate margins, 'auto' margins are ignored.
   3921         computedValues.m_margins.m_before = minimumValueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
   3922         computedValues.m_margins.m_after = minimumValueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
   3923 
   3924         const LayoutUnit availableSpace = containerLogicalHeight - (computedValues.m_margins.m_before + computedValues.m_margins.m_after + bordersPlusPadding);
   3925 
   3926         // Use rule/case that applies.
   3927         if (logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
   3928             // RULE 1: (height is content based, solve of top)
   3929             logicalHeightValue = contentLogicalHeight;
   3930             logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView));
   3931         } else if (!logicalTopIsAuto && logicalHeightIsAuto && logicalBottomIsAuto) {
   3932             // RULE 3: (height is content based, no need solve of bottom)
   3933             logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
   3934             logicalHeightValue = contentLogicalHeight;
   3935         } else if (logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
   3936             // RULE 4: (solve of top)
   3937             logicalHeightValue = resolvedLogicalHeight;
   3938             logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView));
   3939         } else if (!logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
   3940             // RULE 5: (solve of height)
   3941             logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
   3942             logicalHeightValue = max<LayoutUnit>(0, availableSpace - (logicalTopValue + valueForLength(logicalBottom, containerLogicalHeight, renderView)));
   3943         } else if (!logicalTopIsAuto && !logicalHeightIsAuto && logicalBottomIsAuto) {
   3944             // RULE 6: (no need solve of bottom)
   3945             logicalHeightValue = resolvedLogicalHeight;
   3946             logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
   3947         }
   3948     }
   3949     computedValues.m_extent = logicalHeightValue;
   3950 
   3951     // Use computed values to calculate the vertical position.
   3952     computedValues.m_position = logicalTopValue + computedValues.m_margins.m_before;
   3953     computeLogicalTopPositionedOffset(computedValues.m_position, this, logicalHeightValue, containerBlock, containerLogicalHeight);
   3954 }
   3955 
   3956 void RenderBox::computePositionedLogicalWidthReplaced(LogicalExtentComputedValues& computedValues) const
   3957 {
   3958     // The following is based off of the W3C Working Draft from April 11, 2006 of
   3959     // CSS 2.1: Section 10.3.8 "Absolutely positioned, replaced elements"
   3960     // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-width>
   3961     // (block-style-comments in this function correspond to text from the spec and
   3962     // the numbers correspond to numbers in spec)
   3963 
   3964     // We don't use containingBlock(), since we may be positioned by an enclosing
   3965     // relative positioned inline.
   3966     const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
   3967 
   3968     const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock);
   3969     const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, false);
   3970 
   3971     // To match WinIE, in quirks mode use the parent's 'direction' property
   3972     // instead of the the container block's.
   3973     TextDirection containerDirection = containerBlock->style()->direction();
   3974 
   3975     // Variables to solve.
   3976     bool isHorizontal = isHorizontalWritingMode();
   3977     Length logicalLeft = style()->logicalLeft();
   3978     Length logicalRight = style()->logicalRight();
   3979     Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop();
   3980     Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom();
   3981     LayoutUnit& marginLogicalLeftAlias = style()->isLeftToRightDirection() ? computedValues.m_margins.m_start : computedValues.m_margins.m_end;
   3982     LayoutUnit& marginLogicalRightAlias = style()->isLeftToRightDirection() ? computedValues.m_margins.m_end : computedValues.m_margins.m_start;
   3983 
   3984     /*-----------------------------------------------------------------------*\
   3985      * 1. The used value of 'width' is determined as for inline replaced
   3986      *    elements.
   3987     \*-----------------------------------------------------------------------*/
   3988     // NOTE: This value of width is FINAL in that the min/max width calculations
   3989     // are dealt with in computeReplacedWidth().  This means that the steps to produce
   3990     // correct max/min in the non-replaced version, are not necessary.
   3991     computedValues.m_extent = computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth();
   3992 
   3993     const LayoutUnit availableSpace = containerLogicalWidth - computedValues.m_extent;
   3994 
   3995     /*-----------------------------------------------------------------------*\
   3996      * 2. If both 'left' and 'right' have the value 'auto', then if 'direction'
   3997      *    of the containing block is 'ltr', set 'left' to the static position;
   3998      *    else if 'direction' is 'rtl', set 'right' to the static position.
   3999     \*-----------------------------------------------------------------------*/
   4000     // see FIXME 1
   4001     computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, containerLogicalWidth, 0); // FIXME: Pass the region.
   4002 
   4003     /*-----------------------------------------------------------------------*\
   4004      * 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left'
   4005      *    or 'margin-right' with '0'.
   4006     \*-----------------------------------------------------------------------*/
   4007     if (logicalLeft.isAuto() || logicalRight.isAuto()) {
   4008         if (marginLogicalLeft.isAuto())
   4009             marginLogicalLeft.setValue(Fixed, 0);
   4010         if (marginLogicalRight.isAuto())
   4011             marginLogicalRight.setValue(Fixed, 0);
   4012     }
   4013 
   4014     /*-----------------------------------------------------------------------*\
   4015      * 4. If at this point both 'margin-left' and 'margin-right' are still
   4016      *    'auto', solve the equation under the extra constraint that the two
   4017      *    margins must get equal values, unless this would make them negative,
   4018      *    in which case when the direction of the containing block is 'ltr'
   4019      *    ('rtl'), set 'margin-left' ('margin-right') to zero and solve for
   4020      *    'margin-right' ('margin-left').
   4021     \*-----------------------------------------------------------------------*/
   4022     LayoutUnit logicalLeftValue = 0;
   4023     LayoutUnit logicalRightValue = 0;
   4024     RenderView* renderView = view();
   4025 
   4026     if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
   4027         // 'left' and 'right' cannot be 'auto' due to step 3
   4028         ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));
   4029 
   4030         logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
   4031         logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
   4032 
   4033         LayoutUnit difference = availableSpace - (logicalLeftValue + logicalRightValue);
   4034         if (difference > 0) {
   4035             marginLogicalLeftAlias = difference / 2; // split the difference
   4036             marginLogicalRightAlias = difference - marginLogicalLeftAlias; // account for odd valued differences
   4037         } else {
   4038             // Use the containing block's direction rather than the parent block's
   4039             // per CSS 2.1 reference test abspos-replaced-width-margin-000.
   4040             if (containerDirection == LTR) {
   4041                 marginLogicalLeftAlias = 0;
   4042                 marginLogicalRightAlias = difference; // will be negative
   4043             } else {
   4044                 marginLogicalLeftAlias = difference; // will be negative
   4045                 marginLogicalRightAlias = 0;
   4046             }
   4047         }
   4048 
   4049     /*-----------------------------------------------------------------------*\
   4050      * 5. If at this point there is an 'auto' left, solve the equation for
   4051      *    that value.
   4052     \*-----------------------------------------------------------------------*/
   4053     } else if (logicalLeft.isAuto()) {
   4054         marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
   4055         marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
   4056         logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
   4057 
   4058         // Solve for 'left'
   4059         logicalLeftValue = availableSpace - (logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias);
   4060     } else if (logicalRight.isAuto()) {
   4061         marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
   4062         marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
   4063         logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
   4064 
   4065         // Solve for 'right'
   4066         logicalRightValue = availableSpace - (logicalLeftValue + marginLogicalLeftAlias + marginLogicalRightAlias);
   4067     } else if (marginLogicalLeft.isAuto()) {
   4068         marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
   4069         logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
   4070         logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
   4071 
   4072         // Solve for 'margin-left'
   4073         marginLogicalLeftAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalRightAlias);
   4074     } else if (marginLogicalRight.isAuto()) {
   4075         marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
   4076         logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
   4077         logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
   4078 
   4079         // Solve for 'margin-right'
   4080         marginLogicalRightAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias);
   4081     } else {
   4082         // Nothing is 'auto', just calculate the values.
   4083         marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
   4084         marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
   4085         logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
   4086         logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
   4087         // If the containing block is right-to-left, then push the left position as far to the right as possible
   4088         if (containerDirection == RTL) {
   4089             int totalLogicalWidth = computedValues.m_extent + logicalLeftValue + logicalRightValue +  marginLogicalLeftAlias + marginLogicalRightAlias;
   4090             logicalLeftValue = containerLogicalWidth - (totalLogicalWidth - logicalLeftValue);
   4091         }
   4092     }
   4093 
   4094     /*-----------------------------------------------------------------------*\
   4095      * 6. If at this point the values are over-constrained, ignore the value
   4096      *    for either 'left' (in case the 'direction' property of the
   4097      *    containing block is 'rtl') or 'right' (in case 'direction' is
   4098      *    'ltr') and solve for that value.
   4099     \*-----------------------------------------------------------------------*/
   4100     // NOTE: Constraints imposed by the width of the containing block and its content have already been accounted for above.
   4101 
   4102     // FIXME: Deal with differing writing modes here.  Our offset needs to be in the containing block's coordinate space, so that
   4103     // can make the result here rather complicated to compute.
   4104 
   4105     // Use computed values to calculate the horizontal position.
   4106 
   4107     // FIXME: This hack is needed to calculate the logical left position for a 'rtl' relatively
   4108     // positioned, inline containing block because right now, it is using the logical left position
   4109     // of the first line box when really it should use the last line box.  When
   4110     // this is fixed elsewhere, this block should be removed.
   4111     if (containerBlock->isRenderInline() && !containerBlock->style()->isLeftToRightDirection()) {
   4112         const RenderInline* flow = toRenderInline(containerBlock);
   4113         InlineFlowBox* firstLine = flow->firstLineBox();
   4114         InlineFlowBox* lastLine = flow->lastLineBox();
   4115         if (firstLine && lastLine && firstLine != lastLine) {
   4116             computedValues.m_position = logicalLeftValue + marginLogicalLeftAlias + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft());
   4117             return;
   4118         }
   4119     }
   4120 
   4121     LayoutUnit logicalLeftPos = logicalLeftValue + marginLogicalLeftAlias;
   4122     computeLogicalLeftPositionedOffset(logicalLeftPos, this, computedValues.m_extent, containerBlock, containerLogicalWidth);
   4123     computedValues.m_position = logicalLeftPos;
   4124 }
   4125 
   4126 void RenderBox::computePositionedLogicalHeightReplaced(LogicalExtentComputedValues& computedValues) const
   4127 {
   4128     // The following is based off of the W3C Working Draft from April 11, 2006 of
   4129     // CSS 2.1: Section 10.6.5 "Absolutely positioned, replaced elements"
   4130     // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-height>
   4131     // (block-style-comments in this function correspond to text from the spec and
   4132     // the numbers correspond to numbers in spec)
   4133 
   4134     // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
   4135     const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
   4136 
   4137     const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock);
   4138     const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, false);
   4139 
   4140     // Variables to solve.
   4141     Length marginBefore = style()->marginBefore();
   4142     Length marginAfter = style()->marginAfter();
   4143     LayoutUnit& marginBeforeAlias = computedValues.m_margins.m_before;
   4144     LayoutUnit& marginAfterAlias = computedValues.m_margins.m_after;
   4145 
   4146     Length logicalTop = style()->logicalTop();
   4147     Length logicalBottom = style()->logicalBottom();
   4148     RenderView* renderView = view();
   4149 
   4150     /*-----------------------------------------------------------------------*\
   4151      * 1. The used value of 'height' is determined as for inline replaced
   4152      *    elements.
   4153     \*-----------------------------------------------------------------------*/
   4154     // NOTE: This value of height is FINAL in that the min/max height calculations
   4155     // are dealt with in computeReplacedHeight().  This means that the steps to produce
   4156     // correct max/min in the non-replaced version, are not necessary.
   4157     computedValues.m_extent = computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight();
   4158     const LayoutUnit availableSpace = containerLogicalHeight - computedValues.m_extent;
   4159 
   4160     /*-----------------------------------------------------------------------*\
   4161      * 2. If both 'top' and 'bottom' have the value 'auto', replace 'top'
   4162      *    with the element's static position.
   4163     \*-----------------------------------------------------------------------*/
   4164     // see FIXME 1
   4165     computeBlockStaticDistance(logicalTop, logicalBottom, this, containerBlock);
   4166 
   4167     /*-----------------------------------------------------------------------*\
   4168      * 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or
   4169      *    'margin-bottom' with '0'.
   4170     \*-----------------------------------------------------------------------*/
   4171     // FIXME: The spec. says that this step should only be taken when bottom is
   4172     // auto, but if only top is auto, this makes step 4 impossible.
   4173     if (logicalTop.isAuto() || logicalBottom.isAuto()) {
   4174         if (marginBefore.isAuto())
   4175             marginBefore.setValue(Fixed, 0);
   4176         if (marginAfter.isAuto())
   4177             marginAfter.setValue(Fixed, 0);
   4178     }
   4179 
   4180     /*-----------------------------------------------------------------------*\
   4181      * 4. If at this point both 'margin-top' and 'margin-bottom' are still
   4182      *    'auto', solve the equation under the extra constraint that the two
   4183      *    margins must get equal values.
   4184     \*-----------------------------------------------------------------------*/
   4185     LayoutUnit logicalTopValue = 0;
   4186     LayoutUnit logicalBottomValue = 0;
   4187 
   4188     if (marginBefore.isAuto() && marginAfter.isAuto()) {
   4189         // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined.
   4190         ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto()));
   4191 
   4192         logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
   4193         logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
   4194 
   4195         LayoutUnit difference = availableSpace - (logicalTopValue + logicalBottomValue);
   4196         // NOTE: This may result in negative values.
   4197         marginBeforeAlias =  difference / 2; // split the difference
   4198         marginAfterAlias = difference - marginBeforeAlias; // account for odd valued differences
   4199 
   4200     /*-----------------------------------------------------------------------*\
   4201      * 5. If at this point there is only one 'auto' left, solve the equation
   4202      *    for that value.
   4203     \*-----------------------------------------------------------------------*/
   4204     } else if (logicalTop.isAuto()) {
   4205         marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
   4206         marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
   4207         logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
   4208 
   4209         // Solve for 'top'
   4210         logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias + marginAfterAlias);
   4211     } else if (logicalBottom.isAuto()) {
   4212         marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
   4213         marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
   4214         logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
   4215 
   4216         // Solve for 'bottom'
   4217         // NOTE: It is not necessary to solve for 'bottom' because we don't ever
   4218         // use the value.
   4219     } else if (marginBefore.isAuto()) {
   4220         marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
   4221         logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
   4222         logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
   4223 
   4224         // Solve for 'margin-top'
   4225         marginBeforeAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginAfterAlias);
   4226     } else if (marginAfter.isAuto()) {
   4227         marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
   4228         logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
   4229         logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
   4230 
   4231         // Solve for 'margin-bottom'
   4232         marginAfterAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginBeforeAlias);
   4233     } else {
   4234         // Nothing is 'auto', just calculate the values.
   4235         marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
   4236         marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
   4237         logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
   4238         // NOTE: It is not necessary to solve for 'bottom' because we don't ever
   4239         // use the value.
   4240      }
   4241 
   4242     /*-----------------------------------------------------------------------*\
   4243      * 6. If at this point the values are over-constrained, ignore the value
   4244      *    for 'bottom' and solve for that value.
   4245     \*-----------------------------------------------------------------------*/
   4246     // NOTE: It is not necessary to do this step because we don't end up using
   4247     // the value of 'bottom' regardless of whether the values are over-constrained
   4248     // or not.
   4249 
   4250     // Use computed values to calculate the vertical position.
   4251     LayoutUnit logicalTopPos = logicalTopValue + marginBeforeAlias;
   4252     computeLogicalTopPositionedOffset(logicalTopPos, this, computedValues.m_extent, containerBlock, containerLogicalHeight);
   4253     computedValues.m_position = logicalTopPos;
   4254 }
   4255 
   4256 LayoutRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, LayoutUnit* extraWidthToEndOfLine)
   4257 {
   4258     // VisiblePositions at offsets inside containers either a) refer to the positions before/after
   4259     // those containers (tables and select elements) or b) refer to the position inside an empty block.
   4260     // They never refer to children.
   4261     // FIXME: Paint the carets inside empty blocks differently than the carets before/after elements.
   4262 
   4263     LayoutRect rect(location(), LayoutSize(caretWidth, height()));
   4264     bool ltr = box ? box->isLeftToRightDirection() : style()->isLeftToRightDirection();
   4265 
   4266     if ((!caretOffset) ^ ltr)
   4267         rect.move(LayoutSize(width() - caretWidth, 0));
   4268 
   4269     if (box) {
   4270         RootInlineBox* rootBox = box->root();
   4271         LayoutUnit top = rootBox->lineTop();
   4272         rect.setY(top);
   4273         rect.setHeight(rootBox->lineBottom() - top);
   4274     }
   4275 
   4276     // If height of box is smaller than font height, use the latter one,
   4277     // otherwise the caret might become invisible.
   4278     //
   4279     // Also, if the box is not a replaced element, always use the font height.
   4280     // This prevents the "big caret" bug described in:
   4281     // <rdar://problem/3777804> Deleting all content in a document can result in giant tall-as-window insertion point
   4282     //
   4283     // FIXME: ignoring :first-line, missing good reason to take care of
   4284     LayoutUnit fontHeight = style()->fontMetrics().height();
   4285     if (fontHeight > rect.height() || (!isReplaced() && !isTable()))
   4286         rect.setHeight(fontHeight);
   4287 
   4288     if (extraWidthToEndOfLine)
   4289         *extraWidthToEndOfLine = x() + width() - rect.maxX();
   4290 
   4291     // Move to local coords
   4292     rect.moveBy(-location());
   4293 
   4294     // FIXME: Border/padding should be added for all elements but this workaround
   4295     // is needed because we use offsets inside an "atomic" element to represent
   4296     // positions before and after the element in deprecated editing offsets.
   4297     if (node() && !(editingIgnoresContent(node()) || isRenderedTable(node()))) {
   4298         rect.setX(rect.x() + borderLeft() + paddingLeft());
   4299         rect.setY(rect.y() + paddingTop() + borderTop());
   4300     }
   4301 
   4302     if (!isHorizontalWritingMode())
   4303         return rect.transposedRect();
   4304 
   4305     return rect;
   4306 }
   4307 
   4308 PositionWithAffinity RenderBox::positionForPoint(const LayoutPoint& point)
   4309 {
   4310     // no children...return this render object's element, if there is one, and offset 0
   4311     if (!firstChild())
   4312         return createPositionWithAffinity(nonPseudoNode() ? firstPositionInOrBeforeNode(nonPseudoNode()) : Position());
   4313 
   4314     if (isTable() && nonPseudoNode()) {
   4315         LayoutUnit right = contentWidth() + borderAndPaddingWidth();
   4316         LayoutUnit bottom = contentHeight() + borderAndPaddingHeight();
   4317 
   4318         if (point.x() < 0 || point.x() > right || point.y() < 0 || point.y() > bottom) {
   4319             if (point.x() <= right / 2)
   4320                 return createPositionWithAffinity(firstPositionInOrBeforeNode(nonPseudoNode()));
   4321             return createPositionWithAffinity(lastPositionInOrAfterNode(nonPseudoNode()));
   4322         }
   4323     }
   4324 
   4325     // Pass off to the closest child.
   4326     LayoutUnit minDist = LayoutUnit::max();
   4327     RenderBox* closestRenderer = 0;
   4328     LayoutPoint adjustedPoint = point;
   4329     if (isTableRow())
   4330         adjustedPoint.moveBy(location());
   4331 
   4332     for (RenderObject* renderObject = firstChild(); renderObject; renderObject = renderObject->nextSibling()) {
   4333         if ((!renderObject->firstChild() && !renderObject->isInline() && !renderObject->isRenderBlockFlow() )
   4334             || renderObject->style()->visibility() != VISIBLE)
   4335             continue;
   4336 
   4337         if (!renderObject->isBox())
   4338             continue;
   4339 
   4340         RenderBox* renderer = toRenderBox(renderObject);
   4341 
   4342         LayoutUnit top = renderer->borderTop() + renderer->paddingTop() + (isTableRow() ? LayoutUnit() : renderer->y());
   4343         LayoutUnit bottom = top + renderer->contentHeight();
   4344         LayoutUnit left = renderer->borderLeft() + renderer->paddingLeft() + (isTableRow() ? LayoutUnit() : renderer->x());
   4345         LayoutUnit right = left + renderer->contentWidth();
   4346 
   4347         if (point.x() <= right && point.x() >= left && point.y() <= top && point.y() >= bottom) {
   4348             if (renderer->isTableRow())
   4349                 return renderer->positionForPoint(point + adjustedPoint - renderer->locationOffset());
   4350             return renderer->positionForPoint(point - renderer->locationOffset());
   4351         }
   4352 
   4353         // Find the distance from (x, y) to the box.  Split the space around the box into 8 pieces
   4354         // and use a different compare depending on which piece (x, y) is in.
   4355         LayoutPoint cmp;
   4356         if (point.x() > right) {
   4357             if (point.y() < top)
   4358                 cmp = LayoutPoint(right, top);
   4359             else if (point.y() > bottom)
   4360                 cmp = LayoutPoint(right, bottom);
   4361             else
   4362                 cmp = LayoutPoint(right, point.y());
   4363         } else if (point.x() < left) {
   4364             if (point.y() < top)
   4365                 cmp = LayoutPoint(left, top);
   4366             else if (point.y() > bottom)
   4367                 cmp = LayoutPoint(left, bottom);
   4368             else
   4369                 cmp = LayoutPoint(left, point.y());
   4370         } else {
   4371             if (point.y() < top)
   4372                 cmp = LayoutPoint(point.x(), top);
   4373             else
   4374                 cmp = LayoutPoint(point.x(), bottom);
   4375         }
   4376 
   4377         LayoutSize difference = cmp - point;
   4378 
   4379         LayoutUnit dist = difference.width() * difference.width() + difference.height() * difference.height();
   4380         if (dist < minDist) {
   4381             closestRenderer = renderer;
   4382             minDist = dist;
   4383         }
   4384     }
   4385 
   4386     if (closestRenderer)
   4387         return closestRenderer->positionForPoint(adjustedPoint - closestRenderer->locationOffset());
   4388     return createPositionWithAffinity(firstPositionInOrBeforeNode(nonPseudoNode()));
   4389 }
   4390 
   4391 bool RenderBox::shrinkToAvoidFloats() const
   4392 {
   4393     // Floating objects don't shrink.  Objects that don't avoid floats don't shrink.  Marquees don't shrink.
   4394     if ((isInline() && !isMarquee()) || !avoidsFloats() || isFloating())
   4395         return false;
   4396 
   4397     // Only auto width objects can possibly shrink to avoid floats.
   4398     return style()->width().isAuto();
   4399 }
   4400 
   4401 bool RenderBox::avoidsFloats() const
   4402 {
   4403     return isReplaced() || hasOverflowClip() || isHR() || isLegend() || isWritingModeRoot() || isFlexItemIncludingDeprecated();
   4404 }
   4405 
   4406 void RenderBox::addVisualEffectOverflow()
   4407 {
   4408     if (!style()->boxShadow() && !style()->hasBorderImageOutsets())
   4409         return;
   4410 
   4411     bool isFlipped = style()->isFlippedBlocksWritingMode();
   4412     bool isHorizontal = isHorizontalWritingMode();
   4413 
   4414     LayoutRect borderBox = borderBoxRect();
   4415     LayoutUnit overflowMinX = borderBox.x();
   4416     LayoutUnit overflowMaxX = borderBox.maxX();
   4417     LayoutUnit overflowMinY = borderBox.y();
   4418     LayoutUnit overflowMaxY = borderBox.maxY();
   4419 
   4420     // Compute box-shadow overflow first.
   4421     if (style()->boxShadow()) {
   4422         LayoutUnit shadowLeft;
   4423         LayoutUnit shadowRight;
   4424         LayoutUnit shadowTop;
   4425         LayoutUnit shadowBottom;
   4426         style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft);
   4427 
   4428         // In flipped blocks writing modes such as vertical-rl, the physical right shadow value is actually at the lower x-coordinate.
   4429         overflowMinX = borderBox.x() + ((!isFlipped || isHorizontal) ? shadowLeft : -shadowRight);
   4430         overflowMaxX = borderBox.maxX() + ((!isFlipped || isHorizontal) ? shadowRight : -shadowLeft);
   4431         overflowMinY = borderBox.y() + ((!isFlipped || !isHorizontal) ? shadowTop : -shadowBottom);
   4432         overflowMaxY = borderBox.maxY() + ((!isFlipped || !isHorizontal) ? shadowBottom : -shadowTop);
   4433     }
   4434 
   4435     // Now compute border-image-outset overflow.
   4436     if (style()->hasBorderImageOutsets()) {
   4437         LayoutBoxExtent borderOutsets = style()->borderImageOutsets();
   4438 
   4439         // In flipped blocks writing modes, the physical sides are inverted. For example in vertical-rl, the right
   4440         // border is at the lower x coordinate value.
   4441         overflowMinX = min(overflowMinX, borderBox.x() - ((!isFlipped || isHorizontal) ? borderOutsets.left() : borderOutsets.right()));
   4442         overflowMaxX = max(overflowMaxX, borderBox.maxX() + ((!isFlipped || isHorizontal) ? borderOutsets.right() : borderOutsets.left()));
   4443         overflowMinY = min(overflowMinY, borderBox.y() - ((!isFlipped || !isHorizontal) ? borderOutsets.top() : borderOutsets.bottom()));
   4444         overflowMaxY = max(overflowMaxY, borderBox.maxY() + ((!isFlipped || !isHorizontal) ? borderOutsets.bottom() : borderOutsets.top()));
   4445     }
   4446 
   4447     // Add in the final overflow with shadows and outsets combined.
   4448     LayoutRect visualEffectOverflow(overflowMinX, overflowMinY, overflowMaxX - overflowMinX, overflowMaxY - overflowMinY);
   4449     addVisualOverflow(visualEffectOverflow);
   4450 }
   4451 
   4452 void RenderBox::addOverflowFromChild(RenderBox* child, const LayoutSize& delta)
   4453 {
   4454     // Never allow flow threads to propagate overflow up to a parent.
   4455     if (child->isRenderFlowThread())
   4456         return;
   4457 
   4458     // Only propagate layout overflow from the child if the child isn't clipping its overflow.  If it is, then
   4459     // its overflow is internal to it, and we don't care about it.  layoutOverflowRectForPropagation takes care of this
   4460     // and just propagates the border box rect instead.
   4461     LayoutRect childLayoutOverflowRect = child->layoutOverflowRectForPropagation(style());
   4462     childLayoutOverflowRect.move(delta);
   4463     addLayoutOverflow(childLayoutOverflowRect);
   4464 
   4465     // Add in visual overflow from the child.  Even if the child clips its overflow, it may still
   4466     // have visual overflow of its own set from box shadows or reflections.  It is unnecessary to propagate this
   4467     // overflow if we are clipping our own overflow.
   4468     if (child->hasSelfPaintingLayer())
   4469         return;
   4470     LayoutRect childVisualOverflowRect = child->visualOverflowRectForPropagation(style());
   4471     childVisualOverflowRect.move(delta);
   4472     addContentsVisualOverflow(childVisualOverflowRect);
   4473 }
   4474 
   4475 void RenderBox::addLayoutOverflow(const LayoutRect& rect)
   4476 {
   4477     LayoutRect clientBox = noOverflowRect();
   4478     if (clientBox.contains(rect) || rect.isEmpty())
   4479         return;
   4480 
   4481     // For overflow clip objects, we don't want to propagate overflow into unreachable areas.
   4482     LayoutRect overflowRect(rect);
   4483     if (hasOverflowClip() || isRenderView()) {
   4484         // Overflow is in the block's coordinate space and thus is flipped for horizontal-bt and vertical-rl
   4485         // writing modes.  At this stage that is actually a simplification, since we can treat horizontal-tb/bt as the same
   4486         // and vertical-lr/rl as the same.
   4487         bool hasTopOverflow = !style()->isLeftToRightDirection() && !isHorizontalWritingMode();
   4488         bool hasLeftOverflow = !style()->isLeftToRightDirection() && isHorizontalWritingMode();
   4489         if (isFlexibleBox() && style()->isReverseFlexDirection()) {
   4490             RenderFlexibleBox* flexibleBox = toRenderFlexibleBox(this);
   4491             if (flexibleBox->isHorizontalFlow())
   4492                 hasLeftOverflow = true;
   4493             else
   4494                 hasTopOverflow = true;
   4495         }
   4496 
   4497         if (hasColumns() && style()->columnProgression() == ReverseColumnProgression) {
   4498             if (isHorizontalWritingMode() ^ !style()->hasInlineColumnAxis())
   4499                 hasLeftOverflow = !hasLeftOverflow;
   4500             else
   4501                 hasTopOverflow = !hasTopOverflow;
   4502         }
   4503 
   4504         if (!hasTopOverflow)
   4505             overflowRect.shiftYEdgeTo(max(overflowRect.y(), clientBox.y()));
   4506         else
   4507             overflowRect.shiftMaxYEdgeTo(min(overflowRect.maxY(), clientBox.maxY()));
   4508         if (!hasLeftOverflow)
   4509             overflowRect.shiftXEdgeTo(max(overflowRect.x(), clientBox.x()));
   4510         else
   4511             overflowRect.shiftMaxXEdgeTo(min(overflowRect.maxX(), clientBox.maxX()));
   4512 
   4513         // Now re-test with the adjusted rectangle and see if it has become unreachable or fully
   4514         // contained.
   4515         if (clientBox.contains(overflowRect) || overflowRect.isEmpty())
   4516             return;
   4517     }
   4518 
   4519     if (!m_overflow)
   4520         m_overflow = adoptPtr(new RenderOverflow(clientBox, borderBoxRect()));
   4521 
   4522     m_overflow->addLayoutOverflow(overflowRect);
   4523 }
   4524 
   4525 void RenderBox::addVisualOverflow(const LayoutRect& rect)
   4526 {
   4527     LayoutRect borderBox = borderBoxRect();
   4528     if (borderBox.contains(rect) || rect.isEmpty())
   4529         return;
   4530 
   4531     if (!m_overflow)
   4532         m_overflow = adoptPtr(new RenderOverflow(noOverflowRect(), borderBox));
   4533 
   4534     m_overflow->addVisualOverflow(rect);
   4535 }
   4536 
   4537 void RenderBox::addContentsVisualOverflow(const LayoutRect& rect)
   4538 {
   4539     if (!hasOverflowClip()) {
   4540         addVisualOverflow(rect);
   4541         return;
   4542     }
   4543 
   4544     if (!m_overflow)
   4545         m_overflow = adoptPtr(new RenderOverflow(clientBoxRect(), borderBoxRect()));
   4546     m_overflow->addContentsVisualOverflow(rect);
   4547 }
   4548 
   4549 void RenderBox::clearLayoutOverflow()
   4550 {
   4551     if (!m_overflow)
   4552         return;
   4553 
   4554     if (!hasVisualOverflow() && contentsVisualOverflowRect().isEmpty()) {
   4555         m_overflow.clear();
   4556         return;
   4557     }
   4558 
   4559     m_overflow->setLayoutOverflow(noOverflowRect());
   4560 }
   4561 
   4562 inline static bool percentageLogicalHeightIsResolvable(const RenderBox* box)
   4563 {
   4564     return RenderBox::percentageLogicalHeightIsResolvableFromBlock(box->containingBlock(), box->isOutOfFlowPositioned());
   4565 }
   4566 
   4567 bool RenderBox::percentageLogicalHeightIsResolvableFromBlock(const RenderBlock* containingBlock, bool isOutOfFlowPositioned)
   4568 {
   4569     // In quirks mode, blocks with auto height are skipped, and we keep looking for an enclosing
   4570     // block that may have a specified height and then use it. In strict mode, this violates the
   4571     // specification, which states that percentage heights just revert to auto if the containing
   4572     // block has an auto height. We still skip anonymous containing blocks in both modes, though, and look
   4573     // only at explicit containers.
   4574     const RenderBlock* cb = containingBlock;
   4575     bool inQuirksMode = cb->document().inQuirksMode();
   4576     while (!cb->isRenderView() && !cb->isBody() && !cb->isTableCell() && !cb->isOutOfFlowPositioned() && cb->style()->logicalHeight().isAuto()) {
   4577         if (!inQuirksMode && !cb->isAnonymousBlock())
   4578             break;
   4579         cb = cb->containingBlock();
   4580     }
   4581 
   4582     // A positioned element that specified both top/bottom or that specifies height should be treated as though it has a height
   4583     // explicitly specified that can be used for any percentage computations.
   4584     // FIXME: We can't just check top/bottom here.
   4585     // https://bugs.webkit.org/show_bug.cgi?id=46500
   4586     bool isOutOfFlowPositionedWithSpecifiedHeight = cb->isOutOfFlowPositioned() && (!cb->style()->logicalHeight().isAuto() || (!cb->style()->top().isAuto() && !cb->style()->bottom().isAuto()));
   4587 
   4588     // Table cells violate what the CSS spec says to do with heights.  Basically we
   4589     // don't care if the cell specified a height or not.  We just always make ourselves
   4590     // be a percentage of the cell's current content height.
   4591     if (cb->isTableCell())
   4592         return true;
   4593 
   4594     // Otherwise we only use our percentage height if our containing block had a specified
   4595     // height.
   4596     if (cb->style()->logicalHeight().isFixed())
   4597         return true;
   4598     if (cb->style()->logicalHeight().isPercent() && !isOutOfFlowPositionedWithSpecifiedHeight)
   4599         return percentageLogicalHeightIsResolvableFromBlock(cb->containingBlock(), cb->isOutOfFlowPositioned());
   4600     if (cb->isRenderView() || inQuirksMode || isOutOfFlowPositionedWithSpecifiedHeight)
   4601         return true;
   4602     if (cb->isRoot() && isOutOfFlowPositioned) {
   4603         // Match the positioned objects behavior, which is that positioned objects will fill their viewport
   4604         // always.  Note we could only hit this case by recurring into computePercentageLogicalHeight on a positioned containing block.
   4605         return true;
   4606     }
   4607 
   4608     return false;
   4609 }
   4610 
   4611 bool RenderBox::hasUnsplittableScrollingOverflow() const
   4612 {
   4613     // We will paginate as long as we don't scroll overflow in the pagination direction.
   4614     bool isHorizontal = isHorizontalWritingMode();
   4615     if ((isHorizontal && !scrollsOverflowY()) || (!isHorizontal && !scrollsOverflowX()))
   4616         return false;
   4617 
   4618     // We do have overflow. We'll still be willing to paginate as long as the block
   4619     // has auto logical height, auto or undefined max-logical-height and a zero or auto min-logical-height.
   4620     // Note this is just a heuristic, and it's still possible to have overflow under these
   4621     // conditions, but it should work out to be good enough for common cases. Paginating overflow
   4622     // with scrollbars present is not the end of the world and is what we used to do in the old model anyway.
   4623     return !style()->logicalHeight().isIntrinsicOrAuto()
   4624         || (!style()->logicalMaxHeight().isIntrinsicOrAuto() && !style()->logicalMaxHeight().isUndefined() && (!style()->logicalMaxHeight().isPercent() || percentageLogicalHeightIsResolvable(this)))
   4625         || (!style()->logicalMinHeight().isIntrinsicOrAuto() && style()->logicalMinHeight().isPositive() && (!style()->logicalMinHeight().isPercent() || percentageLogicalHeightIsResolvable(this)));
   4626 }
   4627 
   4628 bool RenderBox::isUnsplittableForPagination() const
   4629 {
   4630     return isReplaced() || hasUnsplittableScrollingOverflow() || (parent() && isWritingModeRoot());
   4631 }
   4632 
   4633 LayoutUnit RenderBox::lineHeight(bool /*firstLine*/, LineDirectionMode direction, LinePositionMode /*linePositionMode*/) const
   4634 {
   4635     if (isReplaced())
   4636         return direction == HorizontalLine ? m_marginBox.top() + height() + m_marginBox.bottom() : m_marginBox.right() + width() + m_marginBox.left();
   4637     return 0;
   4638 }
   4639 
   4640 int RenderBox::baselinePosition(FontBaseline baselineType, bool /*firstLine*/, LineDirectionMode direction, LinePositionMode linePositionMode) const
   4641 {
   4642     ASSERT(linePositionMode == PositionOnContainingLine);
   4643     if (isReplaced()) {
   4644         int result = direction == HorizontalLine ? m_marginBox.top() + height() + m_marginBox.bottom() : m_marginBox.right() + width() + m_marginBox.left();
   4645         if (baselineType == AlphabeticBaseline)
   4646             return result;
   4647         return result - result / 2;
   4648     }
   4649     return 0;
   4650 }
   4651 
   4652 
   4653 RenderLayer* RenderBox::enclosingFloatPaintingLayer() const
   4654 {
   4655     const RenderObject* curr = this;
   4656     while (curr) {
   4657         RenderLayer* layer = curr->hasLayer() && curr->isBox() ? toRenderBox(curr)->layer() : 0;
   4658         if (layer && layer->isSelfPaintingLayer())
   4659             return layer;
   4660         curr = curr->parent();
   4661     }
   4662     return 0;
   4663 }
   4664 
   4665 LayoutRect RenderBox::logicalVisualOverflowRectForPropagation(RenderStyle* parentStyle) const
   4666 {
   4667     LayoutRect rect = visualOverflowRectForPropagation(parentStyle);
   4668     if (!parentStyle->isHorizontalWritingMode())
   4669         return rect.transposedRect();
   4670     return rect;
   4671 }
   4672 
   4673 LayoutRect RenderBox::visualOverflowRectForPropagation(RenderStyle* parentStyle) const
   4674 {
   4675     // If the writing modes of the child and parent match, then we don't have to
   4676     // do anything fancy. Just return the result.
   4677     LayoutRect rect = visualOverflowRect();
   4678     if (parentStyle->writingMode() == style()->writingMode())
   4679         return rect;
   4680 
   4681     // We are putting ourselves into our parent's coordinate space.  If there is a flipped block mismatch
   4682     // in a particular axis, then we have to flip the rect along that axis.
   4683     if (style()->writingMode() == RightToLeftWritingMode || parentStyle->writingMode() == RightToLeftWritingMode)
   4684         rect.setX(width() - rect.maxX());
   4685     else if (style()->writingMode() == BottomToTopWritingMode || parentStyle->writingMode() == BottomToTopWritingMode)
   4686         rect.setY(height() - rect.maxY());
   4687 
   4688     return rect;
   4689 }
   4690 
   4691 LayoutRect RenderBox::logicalLayoutOverflowRectForPropagation(RenderStyle* parentStyle) const
   4692 {
   4693     LayoutRect rect = layoutOverflowRectForPropagation(parentStyle);
   4694     if (!parentStyle->isHorizontalWritingMode())
   4695         return rect.transposedRect();
   4696     return rect;
   4697 }
   4698 
   4699 LayoutRect RenderBox::layoutOverflowRectForPropagation(RenderStyle* parentStyle) const
   4700 {
   4701     // Only propagate interior layout overflow if we don't clip it.
   4702     LayoutRect rect = borderBoxRect();
   4703     // We want to include the margin, but only when it adds height. Quirky margins don't contribute height
   4704     // nor do the margins of self-collapsing blocks.
   4705     if (!style()->hasMarginAfterQuirk() && !isSelfCollapsingBlock())
   4706         rect.expand(isHorizontalWritingMode() ? LayoutSize(LayoutUnit(), marginAfter()) : LayoutSize(marginAfter(), LayoutUnit()));
   4707 
   4708     if (!hasOverflowClip())
   4709         rect.unite(layoutOverflowRect());
   4710 
   4711     bool hasTransform = hasLayer() && layer()->transform();
   4712     if (isInFlowPositioned() || hasTransform) {
   4713         // If we are relatively positioned or if we have a transform, then we have to convert
   4714         // this rectangle into physical coordinates, apply relative positioning and transforms
   4715         // to it, and then convert it back.
   4716         flipForWritingMode(rect);
   4717 
   4718         if (hasTransform)
   4719             rect = layer()->currentTransform().mapRect(rect);
   4720 
   4721         if (isInFlowPositioned())
   4722             rect.move(offsetForInFlowPosition());
   4723 
   4724         // Now we need to flip back.
   4725         flipForWritingMode(rect);
   4726     }
   4727 
   4728     // If the writing modes of the child and parent match, then we don't have to
   4729     // do anything fancy. Just return the result.
   4730     if (parentStyle->writingMode() == style()->writingMode())
   4731         return rect;
   4732 
   4733     // We are putting ourselves into our parent's coordinate space.  If there is a flipped block mismatch
   4734     // in a particular axis, then we have to flip the rect along that axis.
   4735     if (style()->writingMode() == RightToLeftWritingMode || parentStyle->writingMode() == RightToLeftWritingMode)
   4736         rect.setX(width() - rect.maxX());
   4737     else if (style()->writingMode() == BottomToTopWritingMode || parentStyle->writingMode() == BottomToTopWritingMode)
   4738         rect.setY(height() - rect.maxY());
   4739 
   4740     return rect;
   4741 }
   4742 
   4743 LayoutRect RenderBox::noOverflowRect() const
   4744 {
   4745     // Because of the special coodinate system used for overflow rectangles and many other
   4746     // rectangles (not quite logical, not quite physical), we need to flip the block progression
   4747     // coordinate in vertical-rl and horizontal-bt writing modes. In other words, the rectangle
   4748     // returned is physical, except for the block direction progression coordinate (y in horizontal
   4749     // writing modes, x in vertical writing modes), which is always "logical top". Apart from the
   4750     // flipping, this method does the same as clientBoxRect().
   4751 
   4752     LayoutUnit left = borderLeft() + (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft() ? verticalScrollbarWidth() : 0);
   4753     LayoutUnit top = borderTop();
   4754     LayoutUnit right = borderRight();
   4755     LayoutUnit bottom = borderBottom();
   4756     LayoutRect rect(left, top, width() - left - right, height() - top - bottom);
   4757     flipForWritingMode(rect);
   4758     // Subtract space occupied by scrollbars. Order is important here: first flip, then subtract
   4759     // scrollbars. This may seem backwards and weird, since one would think that a horizontal
   4760     // scrollbar at the physical bottom in horizontal-bt ought to be at the logical top (physical
   4761     // bottom), between the logical top (physical bottom) border and the logical top (physical
   4762     // bottom) padding. But this is how the rest of the code expects us to behave. This is highly
   4763     // related to https://bugs.webkit.org/show_bug.cgi?id=76129
   4764     // FIXME: when the above mentioned bug is fixed, it should hopefully be possible to call
   4765     // clientBoxRect() or paddingBoxRect() in this method, rather than fiddling with the edges on
   4766     // our own.
   4767     if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
   4768         rect.contract(0, horizontalScrollbarHeight());
   4769     else
   4770         rect.contract(verticalScrollbarWidth(), horizontalScrollbarHeight());
   4771     return rect;
   4772 }
   4773 
   4774 LayoutRect RenderBox::overflowRectForPaintRejection() const
   4775 {
   4776     LayoutRect overflowRect = visualOverflowRect();
   4777     if (!m_overflow || !usesCompositedScrolling())
   4778         return overflowRect;
   4779 
   4780     overflowRect.unite(layoutOverflowRect());
   4781     overflowRect.move(-scrolledContentOffset());
   4782     return overflowRect;
   4783 }
   4784 
   4785 LayoutUnit RenderBox::offsetLeft() const
   4786 {
   4787     return adjustedPositionRelativeToOffsetParent(topLeftLocation()).x();
   4788 }
   4789 
   4790 LayoutUnit RenderBox::offsetTop() const
   4791 {
   4792     return adjustedPositionRelativeToOffsetParent(topLeftLocation()).y();
   4793 }
   4794 
   4795 LayoutPoint RenderBox::flipForWritingModeForChild(const RenderBox* child, const LayoutPoint& point) const
   4796 {
   4797     if (!style()->isFlippedBlocksWritingMode())
   4798         return point;
   4799 
   4800     // The child is going to add in its x() and y(), so we have to make sure it ends up in
   4801     // the right place.
   4802     if (isHorizontalWritingMode())
   4803         return LayoutPoint(point.x(), point.y() + height() - child->height() - (2 * child->y()));
   4804     return LayoutPoint(point.x() + width() - child->width() - (2 * child->x()), point.y());
   4805 }
   4806 
   4807 void RenderBox::flipForWritingMode(LayoutRect& rect) const
   4808 {
   4809     if (!style()->isFlippedBlocksWritingMode())
   4810         return;
   4811 
   4812     if (isHorizontalWritingMode())
   4813         rect.setY(height() - rect.maxY());
   4814     else
   4815         rect.setX(width() - rect.maxX());
   4816 }
   4817 
   4818 LayoutUnit RenderBox::flipForWritingMode(LayoutUnit position) const
   4819 {
   4820     if (!style()->isFlippedBlocksWritingMode())
   4821         return position;
   4822     return logicalHeight() - position;
   4823 }
   4824 
   4825 LayoutPoint RenderBox::flipForWritingMode(const LayoutPoint& position) const
   4826 {
   4827     if (!style()->isFlippedBlocksWritingMode())
   4828         return position;
   4829     return isHorizontalWritingMode() ? LayoutPoint(position.x(), height() - position.y()) : LayoutPoint(width() - position.x(), position.y());
   4830 }
   4831 
   4832 LayoutPoint RenderBox::flipForWritingModeIncludingColumns(const LayoutPoint& point) const
   4833 {
   4834     if (!hasColumns() || !style()->isFlippedBlocksWritingMode())
   4835         return flipForWritingMode(point);
   4836     return toRenderBlock(this)->flipForWritingModeIncludingColumns(point);
   4837 }
   4838 
   4839 LayoutSize RenderBox::flipForWritingMode(const LayoutSize& offset) const
   4840 {
   4841     if (!style()->isFlippedBlocksWritingMode())
   4842         return offset;
   4843     return isHorizontalWritingMode() ? LayoutSize(offset.width(), height() - offset.height()) : LayoutSize(width() - offset.width(), offset.height());
   4844 }
   4845 
   4846 FloatPoint RenderBox::flipForWritingMode(const FloatPoint& position) const
   4847 {
   4848     if (!style()->isFlippedBlocksWritingMode())
   4849         return position;
   4850     return isHorizontalWritingMode() ? FloatPoint(position.x(), height() - position.y()) : FloatPoint(width() - position.x(), position.y());
   4851 }
   4852 
   4853 void RenderBox::flipForWritingMode(FloatRect& rect) const
   4854 {
   4855     if (!style()->isFlippedBlocksWritingMode())
   4856         return;
   4857 
   4858     if (isHorizontalWritingMode())
   4859         rect.setY(height() - rect.maxY());
   4860     else
   4861         rect.setX(width() - rect.maxX());
   4862 }
   4863 
   4864 LayoutPoint RenderBox::topLeftLocation() const
   4865 {
   4866     RenderBlock* containerBlock = containingBlock();
   4867     if (!containerBlock || containerBlock == this)
   4868         return location();
   4869     return containerBlock->flipForWritingModeForChild(this, location());
   4870 }
   4871 
   4872 LayoutSize RenderBox::topLeftLocationOffset() const
   4873 {
   4874     RenderBlock* containerBlock = containingBlock();
   4875     if (!containerBlock || containerBlock == this)
   4876         return locationOffset();
   4877 
   4878     LayoutRect rect(frameRect());
   4879     containerBlock->flipForWritingMode(rect); // FIXME: This is wrong if we are an absolutely positioned object enclosed by a relative-positioned inline.
   4880     return LayoutSize(rect.x(), rect.y());
   4881 }
   4882 
   4883 bool RenderBox::hasRelativeDimensions() const
   4884 {
   4885     // FIXME: This should probably include viewport percentage heights as well.
   4886     return style()->height().isPercent() || style()->width().isPercent()
   4887         || style()->maxHeight().isPercent() || style()->maxWidth().isPercent()
   4888         || style()->minHeight().isPercent() || style()->minWidth().isPercent();
   4889 }
   4890 
   4891 bool RenderBox::hasRelativeLogicalHeight() const
   4892 {
   4893     return style()->logicalHeight().isPercent()
   4894         || style()->logicalMinHeight().isPercent()
   4895         || style()->logicalMaxHeight().isPercent()
   4896         || style()->logicalHeight().isViewportPercentage()
   4897         || style()->logicalMinHeight().isViewportPercentage()
   4898         || style()->logicalMaxHeight().isViewportPercentage();
   4899 }
   4900 
   4901 static void markBoxForRelayoutAfterSplit(RenderBox* box)
   4902 {
   4903     // FIXME: The table code should handle that automatically. If not,
   4904     // we should fix it and remove the table part checks.
   4905     if (box->isTable()) {
   4906         // Because we may have added some sections with already computed column structures, we need to
   4907         // sync the table structure with them now. This avoids crashes when adding new cells to the table.
   4908         toRenderTable(box)->forceSectionsRecalc();
   4909     } else if (box->isTableSection())
   4910         toRenderTableSection(box)->setNeedsCellRecalc();
   4911 
   4912     box->setNeedsLayoutAndPrefWidthsRecalc();
   4913 }
   4914 
   4915 RenderObject* RenderBox::splitAnonymousBoxesAroundChild(RenderObject* beforeChild)
   4916 {
   4917     bool didSplitParentAnonymousBoxes = false;
   4918 
   4919     while (beforeChild->parent() != this) {
   4920         RenderBox* boxToSplit = toRenderBox(beforeChild->parent());
   4921         if (boxToSplit->firstChild() != beforeChild && boxToSplit->isAnonymous()) {
   4922             didSplitParentAnonymousBoxes = true;
   4923 
   4924             // We have to split the parent box into two boxes and move children
   4925             // from |beforeChild| to end into the new post box.
   4926             RenderBox* postBox = boxToSplit->createAnonymousBoxWithSameTypeAs(this);
   4927             postBox->setChildrenInline(boxToSplit->childrenInline());
   4928             RenderBox* parentBox = toRenderBox(boxToSplit->parent());
   4929             // We need to invalidate the |parentBox| before inserting the new node
   4930             // so that the table repainting logic knows the structure is dirty.
   4931             // See for example RenderTableCell:clippedOverflowRectForRepaint.
   4932             markBoxForRelayoutAfterSplit(parentBox);
   4933             parentBox->virtualChildren()->insertChildNode(parentBox, postBox, boxToSplit->nextSibling());
   4934             boxToSplit->moveChildrenTo(postBox, beforeChild, 0, true);
   4935 
   4936             markBoxForRelayoutAfterSplit(boxToSplit);
   4937             markBoxForRelayoutAfterSplit(postBox);
   4938 
   4939             beforeChild = postBox;
   4940         } else
   4941             beforeChild = boxToSplit;
   4942     }
   4943 
   4944     if (didSplitParentAnonymousBoxes)
   4945         markBoxForRelayoutAfterSplit(this);
   4946 
   4947     ASSERT(beforeChild->parent() == this);
   4948     return beforeChild;
   4949 }
   4950 
   4951 LayoutUnit RenderBox::offsetFromLogicalTopOfFirstPage() const
   4952 {
   4953     LayoutState* layoutState = view()->layoutState();
   4954     if (layoutState && !layoutState->isPaginated())
   4955         return 0;
   4956 
   4957     if (!layoutState && !flowThreadContainingBlock())
   4958         return 0;
   4959 
   4960     RenderBlock* containerBlock = containingBlock();
   4961     return containerBlock->offsetFromLogicalTopOfFirstPage() + logicalTop();
   4962 }
   4963 
   4964 } // namespace WebCore
   4965