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