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