Crash in WebCore::RenderElement::containingBlockForObjectInFlow
[WebKit-https.git] / Source / WebCore / 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-2010, 2015 Apple Inc. All rights reserved.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24
25 #include "config.h"
26 #include "RenderBox.h"
27
28 #include "CSSFontSelector.h"
29 #include "Chrome.h"
30 #include "ChromeClient.h"
31 #include "Document.h"
32 #include "EventHandler.h"
33 #include "FloatQuad.h"
34 #include "FloatRoundedRect.h"
35 #include "Frame.h"
36 #include "FrameView.h"
37 #include "GraphicsContext.h"
38 #include "HTMLBodyElement.h"
39 #include "HTMLButtonElement.h"
40 #include "HTMLElement.h"
41 #include "HTMLFrameOwnerElement.h"
42 #include "HTMLInputElement.h"
43 #include "HTMLNames.h"
44 #include "HTMLTextAreaElement.h"
45 #include "HitTestResult.h"
46 #include "InlineElementBox.h"
47 #include "MainFrame.h"
48 #include "Page.h"
49 #include "PaintInfo.h"
50 #include "RenderBoxRegionInfo.h"
51 #include "RenderDeprecatedFlexibleBox.h"
52 #include "RenderFlexibleBox.h"
53 #include "RenderGeometryMap.h"
54 #include "RenderInline.h"
55 #include "RenderIterator.h"
56 #include "RenderLayer.h"
57 #include "RenderLayerCompositor.h"
58 #include "RenderNamedFlowFragment.h"
59 #include "RenderNamedFlowThread.h"
60 #include "RenderTableCell.h"
61 #include "RenderTheme.h"
62 #include "RenderView.h"
63 #include "ScrollAnimator.h"
64 #include "ScrollbarTheme.h"
65 #include "TransformState.h"
66 #include "htmlediting.h"
67 #include <algorithm>
68 #include <math.h>
69 #include <wtf/StackStats.h>
70
71 #if PLATFORM(IOS)
72 #include "Settings.h"
73 #endif
74
75 namespace WebCore {
76
77 struct SameSizeAsRenderBox : public RenderBoxModelObject {
78     virtual ~SameSizeAsRenderBox() { }
79     LayoutRect frameRect;
80     LayoutBoxExtent marginBox;
81     LayoutUnit preferredLogicalWidths[2];
82     void* pointers[2];
83 };
84
85 COMPILE_ASSERT(sizeof(RenderBox) == sizeof(SameSizeAsRenderBox), RenderBox_should_stay_small);
86
87 using namespace HTMLNames;
88
89 // Used by flexible boxes when flexing this element and by table cells.
90 typedef WTF::HashMap<const RenderBox*, LayoutUnit> OverrideSizeMap;
91 static OverrideSizeMap* gOverrideHeightMap = nullptr;
92 static OverrideSizeMap* gOverrideWidthMap = nullptr;
93
94 #if ENABLE(CSS_GRID_LAYOUT)
95 // Used by grid elements to properly size their grid items.
96 typedef WTF::HashMap<const RenderBox*, Optional<LayoutUnit>> OverrideOptionalSizeMap;
97 static OverrideOptionalSizeMap* gOverrideContainingBlockLogicalHeightMap = nullptr;
98 static OverrideOptionalSizeMap* gOverrideContainingBlockLogicalWidthMap = nullptr;
99 static OverrideSizeMap* gExtraInlineOffsetMap = nullptr;
100 static OverrideSizeMap* gExtraBlockOffsetMap = nullptr;
101 #endif
102
103 // Size of border belt for autoscroll. When mouse pointer in border belt,
104 // autoscroll is started.
105 static const int autoscrollBeltSize = 20;
106 static const unsigned backgroundObscurationTestMaxDepth = 4;
107
108 bool RenderBox::s_hadOverflowClip = false;
109
110 static bool skipBodyBackground(const RenderBox* bodyElementRenderer)
111 {
112     ASSERT(bodyElementRenderer->isBody());
113     // The <body> only paints its background if the root element has defined a background independent of the body,
114     // or if the <body>'s parent is not the document element's renderer (e.g. inside SVG foreignObject).
115     auto documentElementRenderer = bodyElementRenderer->document().documentElement()->renderer();
116     return documentElementRenderer
117         && !documentElementRenderer->hasBackground()
118         && (documentElementRenderer == bodyElementRenderer->parent());
119 }
120
121 RenderBox::RenderBox(Element& element, Ref<RenderStyle>&& style, BaseTypeFlags baseTypeFlags)
122     : RenderBoxModelObject(element, WTFMove(style), baseTypeFlags)
123     , m_minPreferredLogicalWidth(-1)
124     , m_maxPreferredLogicalWidth(-1)
125     , m_inlineBoxWrapper(nullptr)
126 {
127     setIsBox();
128 }
129
130 RenderBox::RenderBox(Document& document, Ref<RenderStyle>&& style, BaseTypeFlags baseTypeFlags)
131     : RenderBoxModelObject(document, WTFMove(style), baseTypeFlags)
132     , m_minPreferredLogicalWidth(-1)
133     , m_maxPreferredLogicalWidth(-1)
134     , m_inlineBoxWrapper(nullptr)
135 {
136     setIsBox();
137 }
138
139 RenderBox::~RenderBox()
140 {
141     if (frame().eventHandler().autoscrollRenderer() == this)
142         frame().eventHandler().stopAutoscrollTimer(true);
143
144     clearOverrideSize();
145 #if ENABLE(CSS_GRID_LAYOUT)
146     clearContainingBlockOverrideSize();
147     clearExtraInlineAndBlockOffests();
148 #endif
149
150     RenderBlock::removePercentHeightDescendantIfNeeded(*this);
151
152 #if ENABLE(CSS_SHAPES)
153     ShapeOutsideInfo::removeInfo(*this);
154 #endif
155
156     view().unscheduleLazyRepaint(*this);
157     if (hasControlStatesForRenderer(this))
158         removeControlStatesForRenderer(this);
159 }
160
161 RenderRegion* RenderBox::clampToStartAndEndRegions(RenderRegion* region) const
162 {
163     RenderFlowThread* flowThread = flowThreadContainingBlock();
164
165     ASSERT(isRenderView() || (region && flowThread));
166     if (isRenderView())
167         return region;
168
169     // We need to clamp to the block, since we want any lines or blocks that overflow out of the
170     // logical top or logical bottom of the block to size as though the border box in the first and
171     // last regions extended infinitely. Otherwise the lines are going to size according to the regions
172     // they overflow into, which makes no sense when this block doesn't exist in |region| at all.
173     RenderRegion* startRegion = nullptr;
174     RenderRegion* endRegion = nullptr;
175     if (!flowThread->getRegionRangeForBox(this, startRegion, endRegion))
176         return region;
177
178     if (region->logicalTopForFlowThreadContent() < startRegion->logicalTopForFlowThreadContent())
179         return startRegion;
180     if (region->logicalTopForFlowThreadContent() > endRegion->logicalTopForFlowThreadContent())
181         return endRegion;
182
183     return region;
184 }
185
186 bool RenderBox::hasRegionRangeInFlowThread() const
187 {
188     RenderFlowThread* flowThread = flowThreadContainingBlock();
189     if (!flowThread || !flowThread->hasValidRegionInfo())
190         return false;
191
192     return flowThread->hasCachedRegionRangeForBox(this);
193 }
194
195 LayoutRect RenderBox::clientBoxRectInRegion(RenderRegion* region) const
196 {
197     if (!region)
198         return clientBoxRect();
199
200     LayoutRect clientBox = borderBoxRectInRegion(region);
201     clientBox.setLocation(clientBox.location() + LayoutSize(borderLeft(), borderTop()));
202     clientBox.setSize(clientBox.size() - LayoutSize(borderLeft() + borderRight() + verticalScrollbarWidth(), borderTop() + borderBottom() + horizontalScrollbarHeight()));
203
204     return clientBox;
205 }
206
207 LayoutRect RenderBox::borderBoxRectInRegion(RenderRegion* region, RenderBoxRegionInfoFlags cacheFlag) const
208 {
209     if (!region)
210         return borderBoxRect();
211
212     RenderFlowThread* flowThread = flowThreadContainingBlock();
213     if (!flowThread)
214         return borderBoxRect();
215
216     RenderRegion* startRegion = nullptr;
217     RenderRegion* endRegion = nullptr;
218     if (!flowThread->getRegionRangeForBox(this, startRegion, endRegion)) {
219         // FIXME: In a perfect world this condition should never happen.
220         return borderBoxRect();
221     }
222
223     ASSERT(flowThread->regionInRange(region, startRegion, endRegion));
224
225     // Compute the logical width and placement in this region.
226     RenderBoxRegionInfo* boxInfo = renderBoxRegionInfo(region, cacheFlag);
227     if (!boxInfo)
228         return borderBoxRect();
229
230     // We have cached insets.
231     LayoutUnit logicalWidth = boxInfo->logicalWidth();
232     LayoutUnit logicalLeft = boxInfo->logicalLeft();
233
234     // Now apply the parent inset since it is cumulative whenever anything in the containing block chain shifts.
235     // FIXME: Doesn't work right with perpendicular writing modes.
236     const RenderBlock* currentBox = containingBlock();
237     RenderBoxRegionInfo* currentBoxInfo = isRenderFlowThread() ? nullptr : currentBox->renderBoxRegionInfo(region);
238     while (currentBoxInfo && currentBoxInfo->isShifted()) {
239         if (currentBox->style().direction() == LTR)
240             logicalLeft += currentBoxInfo->logicalLeft();
241         else
242             logicalLeft -= (currentBox->logicalWidth() - currentBoxInfo->logicalWidth()) - currentBoxInfo->logicalLeft();
243
244         // Once we reach the fragmentation container we should stop.
245         if (currentBox->isRenderFlowThread())
246             break;
247
248         currentBox = currentBox->containingBlock();
249         if (!currentBox)
250             break;
251         region = currentBox->clampToStartAndEndRegions(region);
252         currentBoxInfo = currentBox->renderBoxRegionInfo(region);
253     }
254
255     if (cacheFlag == DoNotCacheRenderBoxRegionInfo)
256         delete boxInfo;
257
258     if (isHorizontalWritingMode())
259         return LayoutRect(logicalLeft, 0, logicalWidth, height());
260     return LayoutRect(0, logicalLeft, width(), logicalWidth);
261 }
262
263 static RenderBlockFlow* outermostBlockContainingFloatingObject(RenderBox& box)
264 {
265     ASSERT(box.isFloating());
266     RenderBlockFlow* parentBlock = nullptr;
267     for (auto& ancestor : ancestorsOfType<RenderBlockFlow>(box)) {
268         if (ancestor.isRenderView())
269             break;
270         if (!parentBlock || ancestor.containsFloat(box))
271             parentBlock = &ancestor;
272     }
273     return parentBlock;
274 }
275
276 void RenderBox::removeFloatingOrPositionedChildFromBlockLists()
277 {
278     ASSERT(isFloatingOrOutOfFlowPositioned());
279
280     if (documentBeingDestroyed())
281         return;
282
283     if (isFloating()) {
284         if (RenderBlockFlow* parentBlock = outermostBlockContainingFloatingObject(*this)) {
285             parentBlock->markSiblingsWithFloatsForLayout(this);
286             parentBlock->markAllDescendantsWithFloatsForLayout(this, false);
287         }
288     }
289
290     if (isOutOfFlowPositioned())
291         RenderBlock::removePositionedObject(*this);
292 }
293
294 void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
295 {
296     s_hadOverflowClip = hasOverflowClip();
297
298     const RenderStyle* oldStyle = hasInitializedStyle() ? &style() : nullptr;
299     if (oldStyle) {
300         // The background of the root element or the body element could propagate up to
301         // the canvas. Issue full repaint, when our style changes substantially.
302         if (diff >= StyleDifferenceRepaint && (isDocumentElementRenderer() || isBody())) {
303             view().repaintRootContents();
304             if (oldStyle->hasEntirelyFixedBackground() != newStyle.hasEntirelyFixedBackground())
305                 view().compositor().rootFixedBackgroundsChanged();
306         }
307         
308         // When a layout hint happens and an object's position style changes, we have to do a layout
309         // to dirty the render tree using the old position value now.
310         if (diff == StyleDifferenceLayout && parent() && oldStyle->position() != newStyle.position()) {
311             markContainingBlocksForLayout();
312             if (oldStyle->position() == StaticPosition)
313                 repaint();
314             else if (newStyle.hasOutOfFlowPosition())
315                 parent()->setChildNeedsLayout();
316             if (isFloating() && !isOutOfFlowPositioned() && newStyle.hasOutOfFlowPosition())
317                 removeFloatingOrPositionedChildFromBlockLists();
318         }
319     } else if (isBody())
320         view().repaintRootContents();
321
322 #if ENABLE(CSS_SCROLL_SNAP)
323     if (!newStyle.scrollSnapCoordinates().isEmpty() || (oldStyle && !oldStyle->scrollSnapCoordinates().isEmpty())) {
324         if (newStyle.scrollSnapCoordinates().isEmpty())
325             view().unregisterBoxWithScrollSnapCoordinates(*this);
326         else
327             view().registerBoxWithScrollSnapCoordinates(*this);
328     }
329 #endif
330
331     RenderBoxModelObject::styleWillChange(diff, newStyle);
332 }
333
334 void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
335 {
336     // Horizontal writing mode definition is updated in RenderBoxModelObject::updateFromStyle,
337     // (as part of the RenderBoxModelObject::styleDidChange call below). So, we can safely cache the horizontal
338     // writing mode value before style change here.
339     bool oldHorizontalWritingMode = isHorizontalWritingMode();
340
341     RenderBoxModelObject::styleDidChange(diff, oldStyle);
342
343     const RenderStyle& newStyle = style();
344     if (needsLayout() && oldStyle) {
345         RenderBlock::removePercentHeightDescendantIfNeeded(*this);
346
347         // Normally we can do optimized positioning layout for absolute/fixed positioned objects. There is one special case, however, which is
348         // 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
349         // to determine the new static position.
350         if (isOutOfFlowPositioned() && newStyle.hasStaticBlockPosition(isHorizontalWritingMode()) && oldStyle->marginBefore() != newStyle.marginBefore()
351             && parent() && !parent()->normalChildNeedsLayout())
352             parent()->setChildNeedsLayout();
353     }
354
355     if (RenderBlock::hasPercentHeightContainerMap() && firstChild()
356         && oldHorizontalWritingMode != isHorizontalWritingMode())
357         RenderBlock::clearPercentHeightDescendantsFrom(*this);
358
359     // If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the
360     // new zoomed coordinate space.
361     if (hasOverflowClip() && layer() && oldStyle && oldStyle->effectiveZoom() != newStyle.effectiveZoom()) {
362         if (int left = layer()->scrollOffset().x()) {
363             left = (left / oldStyle->effectiveZoom()) * newStyle.effectiveZoom();
364             layer()->scrollToXOffset(left);
365         }
366         if (int top = layer()->scrollOffset().y()) {
367             top = (top / oldStyle->effectiveZoom()) * newStyle.effectiveZoom();
368             layer()->scrollToYOffset(top);
369         }
370     }
371
372     // Our opaqueness might have changed without triggering layout.
373     if (diff >= StyleDifferenceRepaint && diff <= StyleDifferenceRepaintLayer) {
374         auto parentToInvalidate = parent();
375         for (unsigned i = 0; i < backgroundObscurationTestMaxDepth && parentToInvalidate; ++i) {
376             parentToInvalidate->invalidateBackgroundObscurationStatus();
377             parentToInvalidate = parentToInvalidate->parent();
378         }
379     }
380
381     bool isBodyRenderer = isBody();
382     bool isDocElementRenderer = isDocumentElementRenderer();
383
384     // Set the text color if we're the body.
385     if (isBodyRenderer)
386         document().setTextColor(newStyle.visitedDependentColor(CSSPropertyColor));
387
388     if (isDocElementRenderer || isBodyRenderer) {
389         // Propagate the new writing mode and direction up to the RenderView.
390         auto* documentElementRenderer = document().documentElement()->renderer();
391         RenderStyle& viewStyle = view().style();
392         bool viewChangedWritingMode = false;
393         bool rootStyleChanged = false;
394         bool viewStyleChanged = false;
395         auto* rootRenderer = isBodyRenderer ? documentElementRenderer : nullptr;
396         if (viewStyle.direction() != newStyle.direction() && (isDocElementRenderer || !documentElementRenderer->style().hasExplicitlySetDirection())) {
397             viewStyle.setDirection(newStyle.direction());
398             viewStyleChanged = true;
399             if (isBodyRenderer) {
400                 rootRenderer->style().setDirection(newStyle.direction());
401                 rootStyleChanged = true;
402             }
403             setNeedsLayoutAndPrefWidthsRecalc();
404         }
405
406         if (viewStyle.writingMode() != newStyle.writingMode() && (isDocElementRenderer || !documentElementRenderer->style().hasExplicitlySetWritingMode())) {
407             viewStyle.setWritingMode(newStyle.writingMode());
408             viewChangedWritingMode = true;
409             viewStyleChanged = true;
410             view().setHorizontalWritingMode(newStyle.isHorizontalWritingMode());
411             view().markAllDescendantsWithFloatsForLayout();
412             if (isBodyRenderer) {
413                 rootStyleChanged = true;
414                 rootRenderer->style().setWritingMode(newStyle.writingMode());
415                 rootRenderer->setHorizontalWritingMode(newStyle.isHorizontalWritingMode());
416             }
417             setNeedsLayoutAndPrefWidthsRecalc();
418         }
419
420         view().frameView().recalculateScrollbarOverlayStyle();
421         
422         const Pagination& pagination = view().frameView().pagination();
423         if (viewChangedWritingMode && pagination.mode != Pagination::Unpaginated) {
424             viewStyle.setColumnStylesFromPaginationMode(pagination.mode);
425             if (view().multiColumnFlowThread())
426                 view().updateColumnProgressionFromStyle(viewStyle);
427         }
428         
429         if (viewStyleChanged && view().multiColumnFlowThread())
430             view().updateStylesForColumnChildren();
431         
432         if (rootStyleChanged && is<RenderBlockFlow>(rootRenderer) && downcast<RenderBlockFlow>(*rootRenderer).multiColumnFlowThread())
433             downcast<RenderBlockFlow>(*rootRenderer).updateStylesForColumnChildren();
434         
435         if (isBodyRenderer && pagination.mode != Pagination::Unpaginated && frame().page()->paginationLineGridEnabled()) {
436             // Propagate the body font back up to the RenderView and use it as
437             // the basis of the grid.
438             if (newStyle.fontDescription() != view().style().fontDescription()) {
439                 view().style().setFontDescription(newStyle.fontDescription());
440                 view().style().fontCascade().update(&document().fontSelector());
441             }
442         }
443
444         if (diff != StyleDifferenceEqual)
445             view().compositor().rootOrBodyStyleChanged(*this, oldStyle);
446     }
447
448 #if ENABLE(CSS_SHAPES)
449     if ((oldStyle && oldStyle->shapeOutside()) || style().shapeOutside())
450         updateShapeOutsideInfoAfterStyleChange(style(), oldStyle);
451 #endif
452 }
453
454 void RenderBox::willBeRemovedFromTree()
455 {
456 #if ENABLE(CSS_SCROLL_SNAP)
457     if (hasInitializedStyle() && !style().scrollSnapCoordinates().isEmpty())
458         view().unregisterBoxWithScrollSnapCoordinates(*this);
459 #endif
460     
461     RenderBoxModelObject::willBeRemovedFromTree();
462 }
463     
464
465 #if ENABLE(CSS_SHAPES)
466 void RenderBox::updateShapeOutsideInfoAfterStyleChange(const RenderStyle& style, const RenderStyle* oldStyle)
467 {
468     const ShapeValue* shapeOutside = style.shapeOutside();
469     const ShapeValue* oldShapeOutside = oldStyle ? oldStyle->shapeOutside() : nullptr;
470
471     Length shapeMargin = style.shapeMargin();
472     Length oldShapeMargin = oldStyle ? oldStyle->shapeMargin() : RenderStyle::initialShapeMargin();
473
474     float shapeImageThreshold = style.shapeImageThreshold();
475     float oldShapeImageThreshold = oldStyle ? oldStyle->shapeImageThreshold() : RenderStyle::initialShapeImageThreshold();
476
477     // FIXME: A future optimization would do a deep comparison for equality. (bug 100811)
478     if (shapeOutside == oldShapeOutside && shapeMargin == oldShapeMargin && shapeImageThreshold == oldShapeImageThreshold)
479         return;
480
481     if (!shapeOutside)
482         ShapeOutsideInfo::removeInfo(*this);
483     else
484         ShapeOutsideInfo::ensureInfo(*this).markShapeAsDirty();
485
486     if (shapeOutside || shapeOutside != oldShapeOutside)
487         markShapeOutsideDependentsForLayout();
488 }
489 #endif
490
491 void RenderBox::updateFromStyle()
492 {
493     RenderBoxModelObject::updateFromStyle();
494
495     const RenderStyle& styleToUse = style();
496     bool isDocElementRenderer = isDocumentElementRenderer();
497     bool isViewObject = isRenderView();
498
499     // The root and the RenderView always paint their backgrounds/borders.
500     if (isDocElementRenderer || isViewObject)
501         setHasBoxDecorations(true);
502
503     setFloating(!isOutOfFlowPositioned() && styleToUse.isFloating());
504
505     // We also handle <body> and <html>, whose overflow applies to the viewport.
506     if (styleToUse.overflowX() != OVISIBLE && !isDocElementRenderer && isRenderBlock()) {
507         bool boxHasOverflowClip = true;
508         if (isBody()) {
509             // Overflow on the body can propagate to the viewport under the following conditions.
510             // (1) The root element is <html>.
511             // (2) We are the primary <body> (can be checked by looking at document.body).
512             // (3) The root element has visible overflow.
513             if (is<HTMLHtmlElement>(*document().documentElement())
514                 && document().body() == element()
515                 && document().documentElement()->renderer()->style().overflowX() == OVISIBLE) {
516                 boxHasOverflowClip = false;
517             }
518         }
519         
520         // Check for overflow clip.
521         // It's sufficient to just check one direction, since it's illegal to have visible on only one overflow value.
522         if (boxHasOverflowClip) {
523             if (!s_hadOverflowClip)
524                 // Erase the overflow
525                 repaint();
526             setHasOverflowClip();
527         }
528     }
529
530     setHasTransformRelatedProperty(styleToUse.hasTransformRelatedProperty());
531     setHasReflection(styleToUse.boxReflect());
532 }
533
534 void RenderBox::layout()
535 {
536     StackStats::LayoutCheckPoint layoutCheckPoint;
537     ASSERT(needsLayout());
538
539     RenderObject* child = firstChild();
540     if (!child) {
541         clearNeedsLayout();
542         return;
543     }
544
545     LayoutStateMaintainer statePusher(view(), *this, locationOffset(), style().isFlippedBlocksWritingMode());
546     while (child) {
547         if (child->needsLayout())
548             downcast<RenderElement>(*child).layout();
549         ASSERT(!child->needsLayout());
550         child = child->nextSibling();
551     }
552     statePusher.pop();
553     invalidateBackgroundObscurationStatus();
554     clearNeedsLayout();
555 }
556
557 // More IE extensions.  clientWidth and clientHeight represent the interior of an object
558 // excluding border and scrollbar.
559 LayoutUnit RenderBox::clientWidth() const
560 {
561     return width() - borderLeft() - borderRight() - verticalScrollbarWidth();
562 }
563
564 LayoutUnit RenderBox::clientHeight() const
565 {
566     return height() - borderTop() - borderBottom() - horizontalScrollbarHeight();
567 }
568
569 int RenderBox::scrollWidth() const
570 {
571     if (hasOverflowClip() && layer())
572         return layer()->scrollWidth();
573     // For objects with visible overflow, this matches IE.
574     // FIXME: Need to work right with writing modes.
575     if (style().isLeftToRightDirection()) {
576         // FIXME: This should use snappedIntSize() instead with absolute coordinates.
577         return roundToInt(std::max(clientWidth(), layoutOverflowRect().maxX() - borderLeft()));
578     }
579     return clientWidth() - std::min<LayoutUnit>(0, layoutOverflowRect().x() - borderLeft());
580 }
581
582 int RenderBox::scrollHeight() const
583 {
584     if (hasOverflowClip() && layer())
585         return layer()->scrollHeight();
586     // For objects with visible overflow, this matches IE.
587     // FIXME: Need to work right with writing modes.
588     // FIXME: This should use snappedIntSize() instead with absolute coordinates.
589     return roundToInt(std::max(clientHeight(), layoutOverflowRect().maxY() - borderTop()));
590 }
591
592 int RenderBox::scrollLeft() const
593 {
594     return hasOverflowClip() && layer() ? layer()->scrollPosition().x() : 0;
595 }
596
597 int RenderBox::scrollTop() const
598 {
599     return hasOverflowClip() && layer() ? layer()->scrollPosition().y() : 0;
600 }
601
602 static void setupWheelEventTestTrigger(RenderLayer& layer, Frame* frame)
603 {
604     if (!frame)
605         return;
606
607     Page* page = frame->page();
608     if (!page || !page->expectsWheelEventTriggers())
609         return;
610
611     layer.scrollAnimator().setWheelEventTestTrigger(page->testTrigger());
612 }
613
614 void RenderBox::setScrollLeft(int newLeft)
615 {
616     if (!hasOverflowClip() || !layer())
617         return;
618     setupWheelEventTestTrigger(*layer(), document().frame());
619     layer()->scrollToXPosition(newLeft, RenderLayer::ScrollOffsetClamped);
620 }
621
622 void RenderBox::setScrollTop(int newTop)
623 {
624     if (!hasOverflowClip() || !layer())
625         return;
626     setupWheelEventTestTrigger(*layer(), document().frame());
627     layer()->scrollToYPosition(newTop, RenderLayer::ScrollOffsetClamped);
628 }
629
630 void RenderBox::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
631 {
632     rects.append(snappedIntRect(accumulatedOffset, size()));
633 }
634
635 void RenderBox::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
636 {
637     FloatRect localRect(0, 0, width(), height());
638
639     RenderFlowThread* flowThread = flowThreadContainingBlock();
640     if (flowThread && flowThread->absoluteQuadsForBox(quads, wasFixed, this, localRect.y(), localRect.maxY()))
641         return;
642
643     quads.append(localToAbsoluteQuad(localRect, UseTransforms, wasFixed));
644 }
645
646 void RenderBox::updateLayerTransform()
647 {
648     // Transform-origin depends on box size, so we need to update the layer transform after layout.
649     if (hasLayer())
650         layer()->updateTransform();
651 }
652
653 LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb, RenderRegion* region) const
654 {
655     const RenderStyle& styleToUse = style();
656     if (!styleToUse.logicalMaxWidth().isUndefined())
657         logicalWidth = std::min(logicalWidth, computeLogicalWidthInRegionUsing(MaxSize, styleToUse.logicalMaxWidth(), availableWidth, cb, region));
658     return std::max(logicalWidth, computeLogicalWidthInRegionUsing(MinSize, styleToUse.logicalMinWidth(), availableWidth, cb, region));
659 }
660
661 LayoutUnit RenderBox::constrainLogicalHeightByMinMax(LayoutUnit logicalHeight, Optional<LayoutUnit> intrinsicContentHeight) const
662 {
663     const RenderStyle& styleToUse = style();
664     if (!styleToUse.logicalMaxHeight().isUndefined()) {
665         if (Optional<LayoutUnit> maxH = computeLogicalHeightUsing(MaxSize, styleToUse.logicalMaxHeight(), intrinsicContentHeight))
666             logicalHeight = std::min(logicalHeight, maxH.value());
667     }
668     if (Optional<LayoutUnit> computedLogicalHeight = computeLogicalHeightUsing(MinSize, styleToUse.logicalMinHeight(), intrinsicContentHeight))
669         return std::max(logicalHeight, computedLogicalHeight.value());
670     return logicalHeight;
671 }
672
673 LayoutUnit RenderBox::constrainContentBoxLogicalHeightByMinMax(LayoutUnit logicalHeight, Optional<LayoutUnit> intrinsicContentHeight) const
674 {
675     const RenderStyle& styleToUse = style();
676     if (!styleToUse.logicalMaxHeight().isUndefined()) {
677         if (Optional<LayoutUnit> maxH = computeContentLogicalHeight(MaxSize, styleToUse.logicalMaxHeight(), intrinsicContentHeight))
678             logicalHeight = std::min(logicalHeight, maxH.value());
679     }
680     if (Optional<LayoutUnit> computedContentLogicalHeight = computeContentLogicalHeight(MinSize, styleToUse.logicalMinHeight(), intrinsicContentHeight))
681         return std::max(logicalHeight, computedContentLogicalHeight.value());
682     return logicalHeight;
683 }
684
685 RoundedRect::Radii RenderBox::borderRadii() const
686 {
687     RenderStyle& style = this->style();
688     LayoutRect bounds = frameRect();
689
690     unsigned borderLeft = style.borderLeftWidth();
691     unsigned borderTop = style.borderTopWidth();
692     bounds.moveBy(LayoutPoint(borderLeft, borderTop));
693     bounds.contract(borderLeft + style.borderRightWidth(), borderTop + style.borderBottomWidth());
694     return style.getRoundedBorderFor(bounds).radii();
695 }
696
697 IntRect RenderBox::absoluteContentBox() const
698 {
699     // This is wrong with transforms and flipped writing modes.
700     IntRect rect = snappedIntRect(contentBoxRect());
701     FloatPoint absPos = localToAbsolute();
702     rect.move(absPos.x(), absPos.y());
703     return rect;
704 }
705
706 FloatQuad RenderBox::absoluteContentQuad() const
707 {
708     LayoutRect rect = contentBoxRect();
709     return localToAbsoluteQuad(FloatRect(rect));
710 }
711
712 LayoutRect RenderBox::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap) const
713 {
714     LayoutRect box = borderBoundingBox();
715     adjustRectForOutlineAndShadow(box);
716
717     if (repaintContainer != this) {
718         FloatQuad containerRelativeQuad;
719         if (geometryMap)
720             containerRelativeQuad = geometryMap->mapToContainer(box, repaintContainer);
721         else
722             containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer);
723
724         box = LayoutRect(containerRelativeQuad.boundingBox());
725     }
726     
727     // FIXME: layoutDelta needs to be applied in parts before/after transforms and
728     // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
729     box.move(view().layoutDelta());
730
731     return LayoutRect(snapRectToDevicePixels(box, document().deviceScaleFactor()));
732 }
733
734 void RenderBox::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*)
735 {
736     if (!size().isEmpty())
737         rects.append(LayoutRect(additionalOffset, size()));
738 }
739
740 int RenderBox::reflectionOffset() const
741 {
742     if (!style().boxReflect())
743         return 0;
744     if (style().boxReflect()->direction() == ReflectionLeft || style().boxReflect()->direction() == ReflectionRight)
745         return valueForLength(style().boxReflect()->offset(), borderBoxRect().width());
746     return valueForLength(style().boxReflect()->offset(), borderBoxRect().height());
747 }
748
749 LayoutRect RenderBox::reflectedRect(const LayoutRect& r) const
750 {
751     if (!style().boxReflect())
752         return LayoutRect();
753
754     LayoutRect box = borderBoxRect();
755     LayoutRect result = r;
756     switch (style().boxReflect()->direction()) {
757         case ReflectionBelow:
758             result.setY(box.maxY() + reflectionOffset() + (box.maxY() - r.maxY()));
759             break;
760         case ReflectionAbove:
761             result.setY(box.y() - reflectionOffset() - box.height() + (box.maxY() - r.maxY()));
762             break;
763         case ReflectionLeft:
764             result.setX(box.x() - reflectionOffset() - box.width() + (box.maxX() - r.maxX()));
765             break;
766         case ReflectionRight:
767             result.setX(box.maxX() + reflectionOffset() + (box.maxX() - r.maxX()));
768             break;
769     }
770     return result;
771 }
772
773 bool RenderBox::fixedElementLaysOutRelativeToFrame(const FrameView& frameView) const
774 {
775     return style().position() == FixedPosition && container()->isRenderView() && frameView.fixedElementsLayoutRelativeToFrame();
776 }
777
778 bool RenderBox::includeVerticalScrollbarSize() const
779 {
780     return hasOverflowClip() && layer() && !layer()->hasOverlayScrollbars()
781         && (style().overflowY() == OSCROLL || style().overflowY() == OAUTO);
782 }
783
784 bool RenderBox::includeHorizontalScrollbarSize() const
785 {
786     return hasOverflowClip() && layer() && !layer()->hasOverlayScrollbars()
787         && (style().overflowX() == OSCROLL || style().overflowX() == OAUTO);
788 }
789
790 int RenderBox::verticalScrollbarWidth() const
791 {
792     return includeVerticalScrollbarSize() ? layer()->verticalScrollbarWidth() : 0;
793 }
794
795 int RenderBox::horizontalScrollbarHeight() const
796 {
797     return includeHorizontalScrollbarSize() ? layer()->horizontalScrollbarHeight() : 0;
798 }
799
800 int RenderBox::intrinsicScrollbarLogicalWidth() const
801 {
802     if (!hasOverflowClip())
803         return 0;
804
805     if (isHorizontalWritingMode() && (style().overflowY() == OSCROLL && !hasVerticalScrollbarWithAutoBehavior())) {
806         ASSERT(layer() && layer()->hasVerticalScrollbar());
807         return verticalScrollbarWidth();
808     }
809
810     if (!isHorizontalWritingMode() && (style().overflowX() == OSCROLL && !hasHorizontalScrollbarWithAutoBehavior())) {
811         ASSERT(layer() && layer()->hasHorizontalScrollbar());
812         return horizontalScrollbarHeight();
813     }
814
815     return 0;
816 }
817
818 bool RenderBox::scrollLayer(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Element** stopElement)
819 {
820     RenderLayer* boxLayer = layer();
821     if (boxLayer && boxLayer->scroll(direction, granularity, multiplier)) {
822         if (stopElement)
823             *stopElement = element();
824
825         return true;
826     }
827
828     return false;
829 }
830
831 bool RenderBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Element** stopElement, RenderBox* startBox, const IntPoint& wheelEventAbsolutePoint)
832 {
833     if (scrollLayer(direction, granularity, multiplier, stopElement))
834         return true;
835
836     if (stopElement && *stopElement && *stopElement == element())
837         return true;
838
839     RenderBlock* nextScrollBlock = containingBlock();
840     if (is<RenderNamedFlowThread>(nextScrollBlock)) {
841         ASSERT(startBox);
842         nextScrollBlock = downcast<RenderNamedFlowThread>(*nextScrollBlock).fragmentFromAbsolutePointAndBox(wheelEventAbsolutePoint, *startBox);
843     }
844
845     if (nextScrollBlock && !nextScrollBlock->isRenderView())
846         return nextScrollBlock->scroll(direction, granularity, multiplier, stopElement, startBox, wheelEventAbsolutePoint);
847
848     return false;
849 }
850
851 bool RenderBox::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Element** stopElement)
852 {
853     bool scrolled = false;
854     
855     RenderLayer* l = layer();
856     if (l) {
857 #if PLATFORM(COCOA)
858         // On Mac only we reset the inline direction position when doing a document scroll (e.g., hitting Home/End).
859         if (granularity == ScrollByDocument)
860             scrolled = l->scroll(logicalToPhysical(ScrollInlineDirectionBackward, isHorizontalWritingMode(), style().isFlippedBlocksWritingMode()), ScrollByDocument, multiplier);
861 #endif
862         if (l->scroll(logicalToPhysical(direction, isHorizontalWritingMode(), style().isFlippedBlocksWritingMode()), granularity, multiplier))
863             scrolled = true;
864         
865         if (scrolled) {
866             if (stopElement)
867                 *stopElement = element();
868             return true;
869         }
870     }
871
872     if (stopElement && *stopElement && *stopElement == element())
873         return true;
874
875     RenderBlock* b = containingBlock();
876     if (b && !b->isRenderView())
877         return b->logicalScroll(direction, granularity, multiplier, stopElement);
878     return false;
879 }
880
881 bool RenderBox::canBeScrolledAndHasScrollableArea() const
882 {
883     return canBeProgramaticallyScrolled() && (hasHorizontalOverflow() || hasVerticalOverflow());
884 }
885
886 bool RenderBox::isScrollableOrRubberbandableBox() const
887 {
888     return canBeScrolledAndHasScrollableArea();
889 }
890
891 // FIXME: This is badly named. overflow:hidden can be programmatically scrolled, yet this returns false in that case.
892 bool RenderBox::canBeProgramaticallyScrolled() const
893 {
894     if (isRenderView())
895         return true;
896
897     if (!hasOverflowClip())
898         return false;
899
900     if (hasScrollableOverflowX() || hasScrollableOverflowY())
901         return true;
902
903     return element() && element()->hasEditableStyle();
904 }
905
906 bool RenderBox::usesCompositedScrolling() const
907 {
908     return hasOverflowClip() && hasLayer() && layer()->usesCompositedScrolling();
909 }
910
911 void RenderBox::autoscroll(const IntPoint& position)
912 {
913     if (layer())
914         layer()->autoscroll(position);
915 }
916
917 // There are two kinds of renderer that can autoscroll.
918 bool RenderBox::canAutoscroll() const
919 {
920     if (isRenderView())
921         return view().frameView().isScrollable();
922
923     // Check for a box that can be scrolled in its own right.
924     if (canBeScrolledAndHasScrollableArea())
925         return true;
926
927     return false;
928 }
929
930 // If specified point is in border belt, returned offset denotes direction of
931 // scrolling.
932 IntSize RenderBox::calculateAutoscrollDirection(const IntPoint& windowPoint) const
933 {
934     IntRect box(absoluteBoundingBoxRect());
935     box.moveBy(view().frameView().scrollPosition());
936     IntRect windowBox = view().frameView().contentsToWindow(box);
937
938     IntPoint windowAutoscrollPoint = windowPoint;
939
940     if (windowAutoscrollPoint.x() < windowBox.x() + autoscrollBeltSize)
941         windowAutoscrollPoint.move(-autoscrollBeltSize, 0);
942     else if (windowAutoscrollPoint.x() > windowBox.maxX() - autoscrollBeltSize)
943         windowAutoscrollPoint.move(autoscrollBeltSize, 0);
944
945     if (windowAutoscrollPoint.y() < windowBox.y() + autoscrollBeltSize)
946         windowAutoscrollPoint.move(0, -autoscrollBeltSize);
947     else if (windowAutoscrollPoint.y() > windowBox.maxY() - autoscrollBeltSize)
948         windowAutoscrollPoint.move(0, autoscrollBeltSize);
949
950     return windowAutoscrollPoint - windowPoint;
951 }
952
953 RenderBox* RenderBox::findAutoscrollable(RenderObject* renderer)
954 {
955     while (renderer && !(is<RenderBox>(*renderer) && downcast<RenderBox>(*renderer).canAutoscroll())) {
956         if (is<RenderView>(*renderer) && renderer->document().ownerElement())
957             renderer = renderer->document().ownerElement()->renderer();
958         else
959             renderer = renderer->parent();
960     }
961
962     return is<RenderBox>(renderer) ? downcast<RenderBox>(renderer) : nullptr;
963 }
964
965 void RenderBox::panScroll(const IntPoint& source)
966 {
967     if (layer())
968         layer()->panScrollFromPoint(source);
969 }
970
971 bool RenderBox::hasVerticalScrollbarWithAutoBehavior() const
972 {
973     bool overflowScrollActsLikeAuto = style().overflowY() == OSCROLL && !style().hasPseudoStyle(SCROLLBAR) && ScrollbarTheme::theme().usesOverlayScrollbars();
974     return hasOverflowClip() && (style().overflowY() == OAUTO || style().overflowY() == OOVERLAY || overflowScrollActsLikeAuto);
975 }
976
977 bool RenderBox::hasHorizontalScrollbarWithAutoBehavior() const
978 {
979     bool overflowScrollActsLikeAuto = style().overflowX() == OSCROLL && !style().hasPseudoStyle(SCROLLBAR) && ScrollbarTheme::theme().usesOverlayScrollbars();
980     return hasOverflowClip() && (style().overflowX() == OAUTO || style().overflowX() == OOVERLAY || overflowScrollActsLikeAuto);
981 }
982
983 bool RenderBox::needsPreferredWidthsRecalculation() const
984 {
985     return style().paddingStart().isPercentOrCalculated() || style().paddingEnd().isPercentOrCalculated();
986 }
987
988 IntSize RenderBox::scrolledContentOffset() const
989 {
990     if (!hasOverflowClip())
991         return IntSize();
992
993     ASSERT(hasLayer());
994     // FIXME: Renderer code needs scrollOffset/scrollPosition disambiguation.
995     return layer()->scrolledContentOffset();
996 }
997
998 LayoutSize RenderBox::cachedSizeForOverflowClip() const
999 {
1000     ASSERT(hasOverflowClip());
1001     ASSERT(hasLayer());
1002     return layer()->size();
1003 }
1004
1005 void RenderBox::applyCachedClipAndScrollOffsetForRepaint(LayoutRect& paintRect) const
1006 {
1007     flipForWritingMode(paintRect);
1008     paintRect.move(-scrolledContentOffset()); // For overflow:auto/scroll/hidden.
1009
1010     // Do not clip scroll layer contents to reduce the number of repaints while scrolling.
1011     if (usesCompositedScrolling()) {
1012         flipForWritingMode(paintRect);
1013         return;
1014     }
1015
1016     // height() is inaccurate if we're in the middle of a layout of this RenderBox, so use the
1017     // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
1018     // anyway if its size does change.
1019     LayoutRect clipRect(LayoutPoint(), cachedSizeForOverflowClip());
1020     paintRect = intersection(paintRect, clipRect);
1021     flipForWritingMode(paintRect);
1022 }
1023
1024 void RenderBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
1025 {
1026     minLogicalWidth = minPreferredLogicalWidth() - borderAndPaddingLogicalWidth();
1027     maxLogicalWidth = maxPreferredLogicalWidth() - borderAndPaddingLogicalWidth();
1028 }
1029
1030 LayoutUnit RenderBox::minPreferredLogicalWidth() const
1031 {
1032     if (preferredLogicalWidthsDirty()) {
1033 #ifndef NDEBUG
1034         SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox*>(this));
1035 #endif
1036         const_cast<RenderBox*>(this)->computePreferredLogicalWidths();
1037     }
1038         
1039     return m_minPreferredLogicalWidth;
1040 }
1041
1042 LayoutUnit RenderBox::maxPreferredLogicalWidth() const
1043 {
1044     if (preferredLogicalWidthsDirty()) {
1045 #ifndef NDEBUG
1046         SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox*>(this));
1047 #endif
1048         const_cast<RenderBox*>(this)->computePreferredLogicalWidths();
1049     }
1050         
1051     return m_maxPreferredLogicalWidth;
1052 }
1053
1054 bool RenderBox::hasOverrideLogicalContentHeight() const
1055 {
1056     return gOverrideHeightMap && gOverrideHeightMap->contains(this);
1057 }
1058
1059 bool RenderBox::hasOverrideLogicalContentWidth() const
1060 {
1061     return gOverrideWidthMap && gOverrideWidthMap->contains(this);
1062 }
1063
1064 void RenderBox::setOverrideLogicalContentHeight(LayoutUnit height)
1065 {
1066     if (!gOverrideHeightMap)
1067         gOverrideHeightMap = new OverrideSizeMap();
1068     gOverrideHeightMap->set(this, height);
1069 }
1070
1071 void RenderBox::setOverrideLogicalContentWidth(LayoutUnit width)
1072 {
1073     if (!gOverrideWidthMap)
1074         gOverrideWidthMap = new OverrideSizeMap();
1075     gOverrideWidthMap->set(this, width);
1076 }
1077
1078 void RenderBox::clearOverrideLogicalContentHeight()
1079 {
1080     if (gOverrideHeightMap)
1081         gOverrideHeightMap->remove(this);
1082 }
1083
1084 void RenderBox::clearOverrideLogicalContentWidth()
1085 {
1086     if (gOverrideWidthMap)
1087         gOverrideWidthMap->remove(this);
1088 }
1089
1090 void RenderBox::clearOverrideSize()
1091 {
1092     clearOverrideLogicalContentHeight();
1093     clearOverrideLogicalContentWidth();
1094 }
1095
1096 LayoutUnit RenderBox::overrideLogicalContentWidth() const
1097 {
1098     ASSERT(hasOverrideLogicalContentWidth());
1099     return gOverrideWidthMap->get(this);
1100 }
1101
1102 LayoutUnit RenderBox::overrideLogicalContentHeight() const
1103 {
1104     ASSERT(hasOverrideLogicalContentHeight());
1105     return gOverrideHeightMap->get(this);
1106 }
1107
1108 #if ENABLE(CSS_GRID_LAYOUT)
1109 Optional<LayoutUnit> RenderBox::overrideContainingBlockContentLogicalWidth() const
1110 {
1111     ASSERT(hasOverrideContainingBlockLogicalWidth());
1112     return gOverrideContainingBlockLogicalWidthMap->get(this);
1113 }
1114
1115 Optional<LayoutUnit> RenderBox::overrideContainingBlockContentLogicalHeight() const
1116 {
1117     ASSERT(hasOverrideContainingBlockLogicalHeight());
1118     return gOverrideContainingBlockLogicalHeightMap->get(this);
1119 }
1120
1121 bool RenderBox::hasOverrideContainingBlockLogicalWidth() const
1122 {
1123     return gOverrideContainingBlockLogicalWidthMap && gOverrideContainingBlockLogicalWidthMap->contains(this);
1124 }
1125
1126 bool RenderBox::hasOverrideContainingBlockLogicalHeight() const
1127 {
1128     return gOverrideContainingBlockLogicalHeightMap && gOverrideContainingBlockLogicalHeightMap->contains(this);
1129 }
1130
1131 void RenderBox::setOverrideContainingBlockContentLogicalWidth(Optional<LayoutUnit> logicalWidth)
1132 {
1133     if (!gOverrideContainingBlockLogicalWidthMap)
1134         gOverrideContainingBlockLogicalWidthMap = new OverrideOptionalSizeMap;
1135     gOverrideContainingBlockLogicalWidthMap->set(this, logicalWidth);
1136 }
1137
1138 void RenderBox::setOverrideContainingBlockContentLogicalHeight(Optional<LayoutUnit> logicalHeight)
1139 {
1140     if (!gOverrideContainingBlockLogicalHeightMap)
1141         gOverrideContainingBlockLogicalHeightMap = new OverrideOptionalSizeMap;
1142     gOverrideContainingBlockLogicalHeightMap->set(this, logicalHeight);
1143 }
1144
1145 void RenderBox::clearContainingBlockOverrideSize()
1146 {
1147     if (gOverrideContainingBlockLogicalWidthMap)
1148         gOverrideContainingBlockLogicalWidthMap->remove(this);
1149     clearOverrideContainingBlockContentLogicalHeight();
1150 }
1151
1152 void RenderBox::clearOverrideContainingBlockContentLogicalHeight()
1153 {
1154     if (gOverrideContainingBlockLogicalHeightMap)
1155         gOverrideContainingBlockLogicalHeightMap->remove(this);
1156 }
1157
1158 LayoutUnit RenderBox::extraInlineOffset() const
1159 {
1160     return gExtraInlineOffsetMap ? gExtraInlineOffsetMap->get(this) : LayoutUnit();
1161 }
1162
1163 LayoutUnit RenderBox::extraBlockOffset() const
1164 {
1165     return gExtraBlockOffsetMap ? gExtraBlockOffsetMap->get(this) : LayoutUnit();
1166 }
1167
1168 void RenderBox::setExtraInlineOffset(LayoutUnit inlineOffest)
1169 {
1170     if (!gExtraInlineOffsetMap)
1171         gExtraInlineOffsetMap = new OverrideSizeMap;
1172     gExtraInlineOffsetMap->set(this, inlineOffest);
1173 }
1174
1175 void RenderBox::setExtraBlockOffset(LayoutUnit blockOffest)
1176 {
1177     if (!gExtraBlockOffsetMap)
1178         gExtraBlockOffsetMap = new OverrideSizeMap;
1179     gExtraBlockOffsetMap->set(this, blockOffest);
1180 }
1181
1182 void RenderBox::clearExtraInlineAndBlockOffests()
1183 {
1184     if (gExtraInlineOffsetMap)
1185         gExtraInlineOffsetMap->remove(this);
1186     if (gExtraBlockOffsetMap)
1187         gExtraBlockOffsetMap->remove(this);
1188 }
1189 #endif // ENABLE(CSS_GRID_LAYOUT)
1190
1191 LayoutUnit RenderBox::adjustBorderBoxLogicalWidthForBoxSizing(LayoutUnit width) const
1192 {
1193     LayoutUnit bordersPlusPadding = borderAndPaddingLogicalWidth();
1194     if (style().boxSizing() == CONTENT_BOX)
1195         return width + bordersPlusPadding;
1196     return std::max(width, bordersPlusPadding);
1197 }
1198
1199 LayoutUnit RenderBox::adjustBorderBoxLogicalHeightForBoxSizing(LayoutUnit height) const
1200 {
1201     LayoutUnit bordersPlusPadding = borderAndPaddingLogicalHeight();
1202     if (style().boxSizing() == CONTENT_BOX)
1203         return height + bordersPlusPadding;
1204     return std::max(height, bordersPlusPadding);
1205 }
1206
1207 LayoutUnit RenderBox::adjustContentBoxLogicalWidthForBoxSizing(LayoutUnit width) const
1208 {
1209     if (style().boxSizing() == BORDER_BOX)
1210         width -= borderAndPaddingLogicalWidth();
1211     return std::max<LayoutUnit>(0, width);
1212 }
1213
1214 LayoutUnit RenderBox::adjustContentBoxLogicalHeightForBoxSizing(Optional<LayoutUnit> height) const
1215 {
1216     if (!height)
1217         return 0;
1218     LayoutUnit result = height.value();
1219     if (style().boxSizing() == BORDER_BOX)
1220         result -= borderAndPaddingLogicalHeight();
1221     return std::max(LayoutUnit(), result);
1222 }
1223
1224 // Hit Testing
1225 bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
1226 {
1227     LayoutPoint adjustedLocation = accumulatedOffset + location();
1228
1229     // Check kids first.
1230     for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
1231         if (!child->hasLayer() && child->nodeAtPoint(request, result, locationInContainer, adjustedLocation, action)) {
1232             updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
1233             return true;
1234         }
1235     }
1236
1237     RenderFlowThread* flowThread = flowThreadContainingBlock();
1238     RenderRegion* regionToUse = flowThread ? downcast<RenderNamedFlowFragment>(flowThread->currentRegion()) : nullptr;
1239
1240     // If the box is not contained by this region there's no point in going further.
1241     if (regionToUse && !flowThread->objectShouldFragmentInFlowRegion(this, regionToUse))
1242         return false;
1243
1244     // Check our bounds next. For this purpose always assume that we can only be hit in the
1245     // foreground phase (which is true for replaced elements like images).
1246     LayoutRect boundsRect = borderBoxRectInRegion(regionToUse);
1247     boundsRect.moveBy(adjustedLocation);
1248     if (visibleToHitTesting() && action == HitTestForeground && locationInContainer.intersects(boundsRect)) {
1249         updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
1250         if (!result.addNodeToRectBasedTestResult(element(), request, locationInContainer, boundsRect))
1251             return true;
1252     }
1253
1254     return false;
1255 }
1256
1257 // --------------------- painting stuff -------------------------------
1258
1259 void RenderBox::paintRootBoxFillLayers(const PaintInfo& paintInfo)
1260 {
1261     if (paintInfo.skipRootBackground())
1262         return;
1263
1264     auto& rootBackgroundRenderer = rendererForRootBackground();
1265     
1266     const FillLayer* bgLayer = rootBackgroundRenderer.style().backgroundLayers();
1267     Color bgColor = rootBackgroundRenderer.style().visitedDependentColor(CSSPropertyBackgroundColor);
1268
1269     paintFillLayers(paintInfo, bgColor, bgLayer, view().backgroundRect(), BackgroundBleedNone, CompositeSourceOver, &rootBackgroundRenderer);
1270 }
1271
1272 BackgroundBleedAvoidance RenderBox::determineBackgroundBleedAvoidance(GraphicsContext& context) const
1273 {
1274     if (context.paintingDisabled())
1275         return BackgroundBleedNone;
1276
1277     const RenderStyle& style = this->style();
1278
1279     if (!style.hasBackground() || !style.hasBorder() || !style.hasBorderRadius() || borderImageIsLoadedAndCanBeRendered())
1280         return BackgroundBleedNone;
1281
1282     AffineTransform ctm = context.getCTM();
1283     FloatSize contextScaling(static_cast<float>(ctm.xScale()), static_cast<float>(ctm.yScale()));
1284
1285     // Because RoundedRect uses IntRect internally the inset applied by the 
1286     // BackgroundBleedShrinkBackground strategy cannot be less than one integer
1287     // layout coordinate, even with subpixel layout enabled. To take that into
1288     // account, we clamp the contextScaling to 1.0 for the following test so
1289     // that borderObscuresBackgroundEdge can only return true if the border
1290     // widths are greater than 2 in both layout coordinates and screen
1291     // coordinates.
1292     // This precaution will become obsolete if RoundedRect is ever promoted to
1293     // a sub-pixel representation.
1294     if (contextScaling.width() > 1) 
1295         contextScaling.setWidth(1);
1296     if (contextScaling.height() > 1) 
1297         contextScaling.setHeight(1);
1298
1299     if (borderObscuresBackgroundEdge(contextScaling))
1300         return BackgroundBleedShrinkBackground;
1301     if (!style.hasAppearance() && borderObscuresBackground() && backgroundHasOpaqueTopLayer())
1302         return BackgroundBleedBackgroundOverBorder;
1303
1304     return BackgroundBleedUseTransparencyLayer;
1305 }
1306
1307 void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1308 {
1309     if (!paintInfo.shouldPaintWithinRoot(*this))
1310         return;
1311
1312     LayoutRect paintRect = borderBoxRectInRegion(currentRenderNamedFlowFragment());
1313     paintRect.moveBy(paintOffset);
1314
1315 #if PLATFORM(IOS)
1316     // Workaround for <rdar://problem/6209763>. Force the painting bounds of checkboxes and radio controls to be square.
1317     if (style().appearance() == CheckboxPart || style().appearance() == RadioPart) {
1318         int width = std::min(paintRect.width(), paintRect.height());
1319         int height = width;
1320         paintRect = IntRect(paintRect.x(), paintRect.y() + (this->height() - height) / 2, width, height); // Vertically center the checkbox, like on desktop
1321     }
1322 #endif
1323     BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context());
1324
1325     // FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have
1326     // custom shadows of their own.
1327     if (!boxShadowShouldBeAppliedToBackground(paintRect.location(), bleedAvoidance))
1328         paintBoxShadow(paintInfo, paintRect, style(), Normal);
1329
1330     GraphicsContextStateSaver stateSaver(paintInfo.context(), false);
1331     if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) {
1332         // To avoid the background color bleeding out behind the border, we'll render background and border
1333         // into a transparency layer, and then clip that in one go (which requires setting up the clip before
1334         // beginning the layer).
1335         stateSaver.save();
1336         paintInfo.context().clipRoundedRect(style().getRoundedBorderFor(paintRect).pixelSnappedRoundedRectForPainting(document().deviceScaleFactor()));
1337         paintInfo.context().beginTransparencyLayer(1);
1338     }
1339
1340     // If we have a native theme appearance, paint that before painting our background.
1341     // The theme will tell us whether or not we should also paint the CSS background.
1342     ControlStates* controlStates = nullptr;
1343     bool borderOrBackgroundPaintingIsNeeded = true;
1344     if (style().hasAppearance()) {
1345         if (hasControlStatesForRenderer(this))
1346             controlStates = controlStatesForRenderer(this);
1347         else {
1348             controlStates = new ControlStates();
1349             addControlStatesForRenderer(this, controlStates);
1350         }
1351         borderOrBackgroundPaintingIsNeeded = theme().paint(*this, *controlStates, paintInfo, paintRect);
1352         if (controlStates->needsRepaint())
1353             view().scheduleLazyRepaint(*this);
1354     }
1355
1356     if (borderOrBackgroundPaintingIsNeeded) {
1357         if (bleedAvoidance == BackgroundBleedBackgroundOverBorder)
1358             paintBorder(paintInfo, paintRect, style(), bleedAvoidance);
1359
1360         paintBackground(paintInfo, paintRect, bleedAvoidance);
1361
1362         if (style().hasAppearance())
1363             theme().paintDecorations(*this, paintInfo, paintRect);
1364     }
1365     paintBoxShadow(paintInfo, paintRect, style(), Inset);
1366
1367     // The theme will tell us whether or not we should also paint the CSS border.
1368     if (bleedAvoidance != BackgroundBleedBackgroundOverBorder && (!style().hasAppearance() || (borderOrBackgroundPaintingIsNeeded && theme().paintBorderOnly(*this, paintInfo, paintRect))) && style().hasBorderDecoration())
1369         paintBorder(paintInfo, paintRect, style(), bleedAvoidance);
1370
1371     if (bleedAvoidance == BackgroundBleedUseTransparencyLayer)
1372         paintInfo.context().endTransparencyLayer();
1373 }
1374
1375 void RenderBox::paintBackground(const PaintInfo& paintInfo, const LayoutRect& paintRect, BackgroundBleedAvoidance bleedAvoidance)
1376 {
1377     if (isDocumentElementRenderer()) {
1378         paintRootBoxFillLayers(paintInfo);
1379         return;
1380     }
1381     if (isBody() && skipBodyBackground(this))
1382         return;
1383     if (backgroundIsKnownToBeObscured(paintRect.location()) && !boxShadowShouldBeAppliedToBackground(paintRect.location(), bleedAvoidance))
1384         return;
1385     paintFillLayers(paintInfo, style().visitedDependentColor(CSSPropertyBackgroundColor), style().backgroundLayers(), paintRect, bleedAvoidance);
1386 }
1387
1388 bool RenderBox::getBackgroundPaintedExtent(const LayoutPoint& paintOffset, LayoutRect& paintedExtent) const
1389 {
1390     ASSERT(hasBackground());
1391     LayoutRect backgroundRect = snappedIntRect(borderBoxRect());
1392
1393     Color backgroundColor = style().visitedDependentColor(CSSPropertyBackgroundColor);
1394     if (backgroundColor.isValid() && backgroundColor.alpha()) {
1395         paintedExtent = backgroundRect;
1396         return true;
1397     }
1398
1399     if (!style().backgroundLayers()->image() || style().backgroundLayers()->next()) {
1400         paintedExtent =  backgroundRect;
1401         return true;
1402     }
1403
1404     BackgroundImageGeometry geometry = calculateBackgroundImageGeometry(nullptr, *style().backgroundLayers(), paintOffset, backgroundRect);
1405     paintedExtent = geometry.destRect();
1406     return !geometry.hasNonLocalGeometry();
1407 }
1408
1409 bool RenderBox::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
1410 {
1411     if (isBody() && skipBodyBackground(this))
1412         return false;
1413
1414     Color backgroundColor = style().visitedDependentColor(CSSPropertyBackgroundColor);
1415     if (!backgroundColor.isValid() || backgroundColor.hasAlpha())
1416         return false;
1417
1418     // If the element has appearance, it might be painted by theme.
1419     // We cannot be sure if theme paints the background opaque.
1420     // In this case it is safe to not assume opaqueness.
1421     // FIXME: May be ask theme if it paints opaque.
1422     if (style().hasAppearance())
1423         return false;
1424     // FIXME: Check the opaqueness of background images.
1425
1426     if (hasClip() || hasClipPath())
1427         return false;
1428
1429     // FIXME: Use rounded rect if border radius is present.
1430     if (style().hasBorderRadius())
1431         return false;
1432     
1433     // FIXME: The background color clip is defined by the last layer.
1434     if (style().backgroundLayers()->next())
1435         return false;
1436     LayoutRect backgroundRect;
1437     switch (style().backgroundClip()) {
1438     case BorderFillBox:
1439         backgroundRect = borderBoxRect();
1440         break;
1441     case PaddingFillBox:
1442         backgroundRect = paddingBoxRect();
1443         break;
1444     case ContentFillBox:
1445         backgroundRect = contentBoxRect();
1446         break;
1447     default:
1448         break;
1449     }
1450     return backgroundRect.contains(localRect);
1451 }
1452
1453 static bool isCandidateForOpaquenessTest(const RenderBox& childBox)
1454 {
1455     const RenderStyle& childStyle = childBox.style();
1456     if (childStyle.position() != StaticPosition && childBox.containingBlock() != childBox.parent())
1457         return false;
1458     if (childStyle.visibility() != VISIBLE)
1459         return false;
1460 #if ENABLE(CSS_SHAPES)
1461     if (childStyle.shapeOutside())
1462         return false;
1463 #endif
1464     if (!childBox.width() || !childBox.height())
1465         return false;
1466     if (RenderLayer* childLayer = childBox.layer()) {
1467         if (childLayer->isComposited())
1468             return false;
1469         // FIXME: Deal with z-index.
1470         if (!childStyle.hasAutoZIndex())
1471             return false;
1472         if (childLayer->hasTransform() || childLayer->isTransparent() || childLayer->hasFilter())
1473             return false;
1474         if (!childBox.scrolledContentOffset().isZero())
1475             return false;
1476     }
1477     return true;
1478 }
1479
1480 bool RenderBox::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const
1481 {
1482     if (!maxDepthToTest)
1483         return false;
1484     for (auto& childBox : childrenOfType<RenderBox>(*this)) {
1485         if (!isCandidateForOpaquenessTest(childBox))
1486             continue;
1487         LayoutPoint childLocation = childBox.location();
1488         if (childBox.isRelPositioned())
1489             childLocation.move(childBox.relativePositionOffset());
1490         LayoutRect childLocalRect = localRect;
1491         childLocalRect.moveBy(-childLocation);
1492         if (childLocalRect.y() < 0 || childLocalRect.x() < 0) {
1493             // If there is unobscured area above/left of a static positioned box then the rect is probably not covered.
1494             if (childBox.style().position() == StaticPosition)
1495                 return false;
1496             continue;
1497         }
1498         if (childLocalRect.maxY() > childBox.height() || childLocalRect.maxX() > childBox.width())
1499             continue;
1500         if (childBox.backgroundIsKnownToBeOpaqueInRect(childLocalRect))
1501             return true;
1502         if (childBox.foregroundIsKnownToBeOpaqueInRect(childLocalRect, maxDepthToTest - 1))
1503             return true;
1504     }
1505     return false;
1506 }
1507
1508 bool RenderBox::computeBackgroundIsKnownToBeObscured(const LayoutPoint& paintOffset)
1509 {
1510     // Test to see if the children trivially obscure the background.
1511     // FIXME: This test can be much more comprehensive.
1512     if (!hasBackground())
1513         return false;
1514     // Table and root background painting is special.
1515     if (isTable() || isDocumentElementRenderer())
1516         return false;
1517
1518     LayoutRect backgroundRect;
1519     if (!getBackgroundPaintedExtent(paintOffset, backgroundRect))
1520         return false;
1521     return foregroundIsKnownToBeOpaqueInRect(backgroundRect, backgroundObscurationTestMaxDepth);
1522 }
1523
1524 bool RenderBox::backgroundHasOpaqueTopLayer() const
1525 {
1526     const FillLayer* fillLayer = style().backgroundLayers();
1527     if (!fillLayer || fillLayer->clip() != BorderFillBox)
1528         return false;
1529
1530     // Clipped with local scrolling
1531     if (hasOverflowClip() && fillLayer->attachment() == LocalBackgroundAttachment)
1532         return false;
1533
1534     if (fillLayer->hasOpaqueImage(*this) && fillLayer->hasRepeatXY() && fillLayer->image()->canRender(this, style().effectiveZoom()))
1535         return true;
1536
1537     // If there is only one layer and no image, check whether the background color is opaque
1538     if (!fillLayer->next() && !fillLayer->hasImage()) {
1539         Color bgColor = style().visitedDependentColor(CSSPropertyBackgroundColor);
1540         if (bgColor.isValid() && bgColor.alpha() == 255)
1541             return true;
1542     }
1543
1544     return false;
1545 }
1546
1547 void RenderBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1548 {
1549     if (!paintInfo.shouldPaintWithinRoot(*this) || style().visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask || paintInfo.context().paintingDisabled())
1550         return;
1551
1552     LayoutRect paintRect = LayoutRect(paintOffset, size());
1553     paintMaskImages(paintInfo, paintRect);
1554 }
1555
1556 void RenderBox::paintClippingMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1557 {
1558     if (!paintInfo.shouldPaintWithinRoot(*this) || style().visibility() != VISIBLE || paintInfo.phase != PaintPhaseClippingMask || paintInfo.context().paintingDisabled())
1559         return;
1560
1561     LayoutRect paintRect = LayoutRect(paintOffset, size());
1562     paintInfo.context().fillRect(snappedIntRect(paintRect), Color::black);
1563 }
1564
1565 void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& paintRect)
1566 {
1567     // Figure out if we need to push a transparency layer to render our mask.
1568     bool pushTransparencyLayer = false;
1569     bool compositedMask = hasLayer() && layer()->hasCompositedMask();
1570     bool flattenCompositingLayers = view().frameView().paintBehavior() & PaintBehaviorFlattenCompositingLayers;
1571     CompositeOperator compositeOp = CompositeSourceOver;
1572
1573     bool allMaskImagesLoaded = true;
1574     
1575     if (!compositedMask || flattenCompositingLayers) {
1576         pushTransparencyLayer = true;
1577         StyleImage* maskBoxImage = style().maskBoxImage().image();
1578         const FillLayer* maskLayers = style().maskLayers();
1579
1580         // Don't render a masked element until all the mask images have loaded, to prevent a flash of unmasked content.
1581         if (maskBoxImage)
1582             allMaskImagesLoaded &= maskBoxImage->isLoaded();
1583
1584         if (maskLayers)
1585             allMaskImagesLoaded &= maskLayers->imagesAreLoaded();
1586
1587         paintInfo.context().setCompositeOperation(CompositeDestinationIn);
1588         paintInfo.context().beginTransparencyLayer(1);
1589         compositeOp = CompositeSourceOver;
1590     }
1591
1592     if (allMaskImagesLoaded) {
1593         paintFillLayers(paintInfo, Color(), style().maskLayers(), paintRect, BackgroundBleedNone, compositeOp);
1594         paintNinePieceImage(paintInfo.context(), paintRect, style(), style().maskBoxImage(), compositeOp);
1595     }
1596     
1597     if (pushTransparencyLayer)
1598         paintInfo.context().endTransparencyLayer();
1599 }
1600
1601 LayoutRect RenderBox::maskClipRect(const LayoutPoint& paintOffset)
1602 {
1603     const NinePieceImage& maskBoxImage = style().maskBoxImage();
1604     if (maskBoxImage.image()) {
1605         LayoutRect borderImageRect = borderBoxRect();
1606         
1607         // Apply outsets to the border box.
1608         borderImageRect.expand(style().maskBoxImageOutsets());
1609         return borderImageRect;
1610     }
1611     
1612     LayoutRect result;
1613     LayoutRect borderBox = borderBoxRect();
1614     for (const FillLayer* maskLayer = style().maskLayers(); maskLayer; maskLayer = maskLayer->next()) {
1615         if (maskLayer->image()) {
1616             // Masks should never have fixed attachment, so it's OK for paintContainer to be null.
1617             BackgroundImageGeometry geometry = calculateBackgroundImageGeometry(nullptr, *maskLayer, paintOffset, borderBox);
1618             result.unite(geometry.destRect());
1619         }
1620     }
1621     return result;
1622 }
1623
1624 void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect,
1625     BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderElement* backgroundObject)
1626 {
1627     Vector<const FillLayer*, 8> layers;
1628     const FillLayer* curLayer = fillLayer;
1629     bool shouldDrawBackgroundInSeparateBuffer = false;
1630     while (curLayer) {
1631         layers.append(curLayer);
1632         // Stop traversal when an opaque layer is encountered.
1633         // FIXME : It would be possible for the following occlusion culling test to be more aggressive 
1634         // on layers with no repeat by testing whether the image covers the layout rect.
1635         // Testing that here would imply duplicating a lot of calculations that are currently done in
1636         // RenderBoxModelObject::paintFillLayerExtended. A more efficient solution might be to move
1637         // the layer recursion into paintFillLayerExtended, or to compute the layer geometry here
1638         // and pass it down.
1639
1640         if (!shouldDrawBackgroundInSeparateBuffer && curLayer->blendMode() != BlendModeNormal)
1641             shouldDrawBackgroundInSeparateBuffer = true;
1642
1643         // The clipOccludesNextLayers condition must be evaluated first to avoid short-circuiting.
1644         if (curLayer->clipOccludesNextLayers(curLayer == fillLayer) && curLayer->hasOpaqueImage(*this) && curLayer->image()->canRender(this, style().effectiveZoom()) && curLayer->hasRepeatXY() && curLayer->blendMode() == BlendModeNormal)
1645             break;
1646         curLayer = curLayer->next();
1647     }
1648
1649     GraphicsContext& context = paintInfo.context();
1650     BaseBackgroundColorUsage baseBgColorUsage = BaseBackgroundColorUse;
1651
1652     if (shouldDrawBackgroundInSeparateBuffer) {
1653         paintFillLayer(paintInfo, c, *layers.rbegin(), rect, bleedAvoidance, op, backgroundObject, BaseBackgroundColorOnly);
1654         baseBgColorUsage = BaseBackgroundColorSkip;
1655         context.beginTransparencyLayer(1);
1656     }
1657
1658     Vector<const FillLayer*>::const_reverse_iterator topLayer = layers.rend();
1659     for (Vector<const FillLayer*>::const_reverse_iterator it = layers.rbegin(); it != topLayer; ++it)
1660         paintFillLayer(paintInfo, c, *it, rect, bleedAvoidance, op, backgroundObject, baseBgColorUsage);
1661
1662     if (shouldDrawBackgroundInSeparateBuffer)
1663         context.endTransparencyLayer();
1664 }
1665
1666 void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect,
1667     BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderElement* backgroundObject, BaseBackgroundColorUsage baseBgColorUsage)
1668 {
1669     paintFillLayerExtended(paintInfo, c, fillLayer, rect, bleedAvoidance, nullptr, LayoutSize(), op, backgroundObject, baseBgColorUsage);
1670 }
1671
1672 static bool layersUseImage(WrappedImagePtr image, const FillLayer* layers)
1673 {
1674     for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
1675         if (curLayer->image() && image == curLayer->image()->data())
1676             return true;
1677     }
1678
1679     return false;
1680 }
1681
1682 void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*)
1683 {
1684     if (!parent())
1685         return;
1686
1687     if ((style().borderImage().image() && style().borderImage().image()->data() == image) ||
1688         (style().maskBoxImage().image() && style().maskBoxImage().image()->data() == image)) {
1689         repaint();
1690         return;
1691     }
1692
1693 #if ENABLE(CSS_SHAPES)
1694     ShapeValue* shapeOutsideValue = style().shapeOutside();
1695     if (!view().frameView().isInLayout() && isFloating() && shapeOutsideValue && shapeOutsideValue->image() && shapeOutsideValue->image()->data() == image) {
1696         ShapeOutsideInfo::ensureInfo(*this).markShapeAsDirty();
1697         markShapeOutsideDependentsForLayout();
1698     }
1699 #endif
1700
1701     bool didFullRepaint = repaintLayerRectsForImage(image, style().backgroundLayers(), true);
1702     if (!didFullRepaint)
1703         repaintLayerRectsForImage(image, style().maskLayers(), false);
1704
1705     if (!isComposited())
1706         return;
1707
1708     if (layer()->hasCompositedMask() && layersUseImage(image, style().maskLayers()))
1709         layer()->contentChanged(MaskImageChanged);
1710     if (layersUseImage(image, style().backgroundLayers()))
1711         layer()->contentChanged(BackgroundImageChanged);
1712 }
1713
1714 bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer* layers, bool drawingBackground)
1715 {
1716     LayoutRect rendererRect;
1717     RenderBox* layerRenderer = nullptr;
1718
1719     for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
1720         if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(this, style().effectiveZoom())) {
1721             // Now that we know this image is being used, compute the renderer and the rect if we haven't already.
1722             bool drawingRootBackground = drawingBackground && (isDocumentElementRenderer() || (isBody() && !document().documentElement()->renderer()->hasBackground()));
1723             if (!layerRenderer) {
1724                 if (drawingRootBackground) {
1725                     layerRenderer = &view();
1726
1727                     LayoutUnit rw = downcast<RenderView>(*layerRenderer).frameView().contentsWidth();
1728                     LayoutUnit rh = downcast<RenderView>(*layerRenderer).frameView().contentsHeight();
1729
1730                     rendererRect = LayoutRect(-layerRenderer->marginLeft(),
1731                         -layerRenderer->marginTop(),
1732                         std::max(layerRenderer->width() + layerRenderer->horizontalMarginExtent() + layerRenderer->borderLeft() + layerRenderer->borderRight(), rw),
1733                         std::max(layerRenderer->height() + layerRenderer->verticalMarginExtent() + layerRenderer->borderTop() + layerRenderer->borderBottom(), rh));
1734                 } else {
1735                     layerRenderer = this;
1736                     rendererRect = borderBoxRect();
1737                 }
1738             }
1739             // FIXME: Figure out how to pass absolute position to calculateBackgroundImageGeometry (for pixel snapping)
1740             BackgroundImageGeometry geometry = layerRenderer->calculateBackgroundImageGeometry(nullptr, *curLayer, LayoutPoint(), rendererRect);
1741             if (geometry.hasNonLocalGeometry()) {
1742                 // Rather than incur the costs of computing the paintContainer for renderers with fixed backgrounds
1743                 // in order to get the right destRect, just repaint the entire renderer.
1744                 layerRenderer->repaint();
1745                 return true;
1746             }
1747             
1748             LayoutRect rectToRepaint = geometry.destRect();
1749             bool shouldClipToLayer = true;
1750
1751             // If this is the root background layer, we may need to extend the repaintRect if the FrameView has an
1752             // extendedBackground. We should only extend the rect if it is already extending the full width or height
1753             // of the rendererRect.
1754             if (drawingRootBackground && view().frameView().hasExtendedBackgroundRectForPainting()) {
1755                 shouldClipToLayer = false;
1756                 IntRect extendedBackgroundRect = view().frameView().extendedBackgroundRectForPainting();
1757                 if (rectToRepaint.width() == rendererRect.width()) {
1758                     rectToRepaint.move(extendedBackgroundRect.x(), 0);
1759                     rectToRepaint.setWidth(extendedBackgroundRect.width());
1760                 }
1761                 if (rectToRepaint.height() == rendererRect.height()) {
1762                     rectToRepaint.move(0, extendedBackgroundRect.y());
1763                     rectToRepaint.setHeight(extendedBackgroundRect.height());
1764                 }
1765             }
1766
1767             layerRenderer->repaintRectangle(rectToRepaint, shouldClipToLayer);
1768             if (geometry.destRect() == rendererRect)
1769                 return true;
1770         }
1771     }
1772     return false;
1773 }
1774
1775 bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumulatedOffset)
1776 {
1777     if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseSelfOutline || paintInfo.phase == PaintPhaseMask)
1778         return false;
1779         
1780     bool isControlClip = hasControlClip();
1781     bool isOverflowClip = hasOverflowClip() && !layer()->isSelfPaintingLayer();
1782     
1783     if (!isControlClip && !isOverflowClip)
1784         return false;
1785     
1786     if (paintInfo.phase == PaintPhaseOutline)
1787         paintInfo.phase = PaintPhaseChildOutlines;
1788     else if (paintInfo.phase == PaintPhaseChildBlockBackground) {
1789         paintInfo.phase = PaintPhaseBlockBackground;
1790         paintObject(paintInfo, accumulatedOffset);
1791         paintInfo.phase = PaintPhaseChildBlockBackgrounds;
1792     }
1793     float deviceScaleFactor = document().deviceScaleFactor();
1794     FloatRect clipRect = snapRectToDevicePixels((isControlClip ? controlClipRect(accumulatedOffset) : overflowClipRect(accumulatedOffset, currentRenderNamedFlowFragment(), IgnoreOverlayScrollbarSize, paintInfo.phase)), deviceScaleFactor);
1795     paintInfo.context().save();
1796     if (style().hasBorderRadius())
1797         paintInfo.context().clipRoundedRect(style().getRoundedInnerBorderFor(LayoutRect(accumulatedOffset, size())).pixelSnappedRoundedRectForPainting(deviceScaleFactor));
1798     paintInfo.context().clip(clipRect);
1799     return true;
1800 }
1801
1802 void RenderBox::popContentsClip(PaintInfo& paintInfo, PaintPhase originalPhase, const LayoutPoint& accumulatedOffset)
1803 {
1804     ASSERT(hasControlClip() || (hasOverflowClip() && !layer()->isSelfPaintingLayer()));
1805
1806     paintInfo.context().restore();
1807     if (originalPhase == PaintPhaseOutline) {
1808         paintInfo.phase = PaintPhaseSelfOutline;
1809         paintObject(paintInfo, accumulatedOffset);
1810         paintInfo.phase = originalPhase;
1811     } else if (originalPhase == PaintPhaseChildBlockBackground)
1812         paintInfo.phase = originalPhase;
1813 }
1814
1815 LayoutRect RenderBox::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy, PaintPhase)
1816 {
1817     // FIXME: When overflow-clip (CSS3) is implemented, we'll obtain the property
1818     // here.
1819     LayoutRect clipRect = borderBoxRectInRegion(region);
1820     clipRect.setLocation(location + clipRect.location() + LayoutSize(borderLeft(), borderTop()));
1821     clipRect.setSize(clipRect.size() - LayoutSize(borderLeft() + borderRight(), borderTop() + borderBottom()));
1822
1823     // Subtract out scrollbars if we have them.
1824      if (layer()) {
1825         if (style().shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
1826             clipRect.move(layer()->verticalScrollbarWidth(relevancy), 0);
1827         clipRect.contract(layer()->verticalScrollbarWidth(relevancy), layer()->horizontalScrollbarHeight(relevancy));
1828      }
1829
1830     return clipRect;
1831 }
1832
1833 LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region)
1834 {
1835     LayoutRect borderBoxRect = borderBoxRectInRegion(region);
1836     LayoutRect clipRect = LayoutRect(borderBoxRect.location() + location, borderBoxRect.size());
1837
1838     if (!style().clipLeft().isAuto()) {
1839         LayoutUnit c = valueForLength(style().clipLeft(), borderBoxRect.width());
1840         clipRect.move(c, 0);
1841         clipRect.contract(c, 0);
1842     }
1843
1844     // We don't use the region-specific border box's width and height since clip offsets are (stupidly) specified
1845     // from the left and top edges. Therefore it's better to avoid constraining to smaller widths and heights.
1846
1847     if (!style().clipRight().isAuto())
1848         clipRect.contract(width() - valueForLength(style().clipRight(), width()), 0);
1849
1850     if (!style().clipTop().isAuto()) {
1851         LayoutUnit c = valueForLength(style().clipTop(), borderBoxRect.height());
1852         clipRect.move(0, c);
1853         clipRect.contract(0, c);
1854     }
1855
1856     if (!style().clipBottom().isAuto())
1857         clipRect.contract(0, height() - valueForLength(style().clipBottom(), height()));
1858
1859     return clipRect;
1860 }
1861
1862 LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion* region) const
1863 {    
1864     RenderRegion* containingBlockRegion = nullptr;
1865     LayoutUnit logicalTopPosition = logicalTop();
1866     if (region) {
1867         LayoutUnit offsetFromLogicalTopOfRegion = region ? region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage() : LayoutUnit();
1868         logicalTopPosition = std::max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
1869         containingBlockRegion = cb->clampToStartAndEndRegions(region);
1870     }
1871
1872     LayoutUnit logicalHeight = cb->logicalHeightForChild(*this);
1873     LayoutUnit result = cb->availableLogicalWidthForLineInRegion(logicalTopPosition, DoNotIndentText, containingBlockRegion, logicalHeight) - childMarginStart - childMarginEnd;
1874
1875     // We need to see if margins on either the start side or the end side can contain the floats in question. If they can,
1876     // then just using the line width is inaccurate. In the case where a float completely fits, we don't need to use the line
1877     // offset at all, but can instead push all the way to the content edge of the containing block. In the case where the float
1878     // 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
1879     // "consumed" by the float. Negative margins aren't consumed by the float, and so we ignore them.
1880     if (childMarginStart > 0) {
1881         LayoutUnit startContentSide = cb->startOffsetForContent(containingBlockRegion);
1882         LayoutUnit startContentSideWithMargin = startContentSide + childMarginStart;
1883         LayoutUnit startOffset = cb->startOffsetForLineInRegion(logicalTopPosition, DoNotIndentText, containingBlockRegion, logicalHeight);
1884         if (startOffset > startContentSideWithMargin)
1885             result += childMarginStart;
1886         else
1887             result += startOffset - startContentSide;
1888     }
1889     
1890     if (childMarginEnd > 0) {
1891         LayoutUnit endContentSide = cb->endOffsetForContent(containingBlockRegion);
1892         LayoutUnit endContentSideWithMargin = endContentSide + childMarginEnd;
1893         LayoutUnit endOffset = cb->endOffsetForLineInRegion(logicalTopPosition, DoNotIndentText, containingBlockRegion, logicalHeight);
1894         if (endOffset > endContentSideWithMargin)
1895             result += childMarginEnd;
1896         else
1897             result += endOffset - endContentSide;
1898     }
1899
1900     return result;
1901 }
1902
1903 LayoutUnit RenderBox::containingBlockLogicalWidthForContent() const
1904 {
1905 #if ENABLE(CSS_GRID_LAYOUT)
1906     if (hasOverrideContainingBlockLogicalWidth()) {
1907         if (auto overrideLogicalWidth = overrideContainingBlockContentLogicalWidth())
1908             return overrideLogicalWidth.value();
1909     }
1910 #endif
1911
1912     if (RenderBlock* cb = containingBlock())
1913         return cb->availableLogicalWidth();
1914     return LayoutUnit();
1915 }
1916
1917 LayoutUnit RenderBox::containingBlockLogicalHeightForContent(AvailableLogicalHeightType heightType) const
1918 {
1919 #if ENABLE(CSS_GRID_LAYOUT)
1920     if (hasOverrideContainingBlockLogicalHeight()) {
1921         if (auto overrideLogicalHeight = overrideContainingBlockContentLogicalHeight())
1922             return overrideLogicalHeight.value();
1923     }
1924 #endif
1925
1926     if (RenderBlock* cb = containingBlock())
1927         return cb->availableLogicalHeight(heightType);
1928     return LayoutUnit();
1929 }
1930
1931 LayoutUnit RenderBox::containingBlockLogicalWidthForContentInRegion(RenderRegion* region) const
1932 {
1933     if (!region)
1934         return containingBlockLogicalWidthForContent();
1935
1936     RenderBlock* cb = containingBlock();
1937     RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region);
1938     // FIXME: It's unclear if a region's content should use the containing block's override logical width.
1939     // If it should, the following line should call containingBlockLogicalWidthForContent.
1940     LayoutUnit result = cb->availableLogicalWidth();
1941     RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(containingBlockRegion);
1942     if (!boxInfo)
1943         return result;
1944     return std::max<LayoutUnit>(0, result - (cb->logicalWidth() - boxInfo->logicalWidth()));
1945 }
1946
1947 LayoutUnit RenderBox::containingBlockAvailableLineWidthInRegion(RenderRegion* region) const
1948 {
1949     RenderBlock* cb = containingBlock();
1950     RenderRegion* containingBlockRegion = nullptr;
1951     LayoutUnit logicalTopPosition = logicalTop();
1952     if (region) {
1953         LayoutUnit offsetFromLogicalTopOfRegion = region ? region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage() : LayoutUnit();
1954         logicalTopPosition = std::max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
1955         containingBlockRegion = cb->clampToStartAndEndRegions(region);
1956     }
1957     return cb->availableLogicalWidthForLineInRegion(logicalTopPosition, DoNotIndentText, containingBlockRegion, availableLogicalHeight(IncludeMarginBorderPadding));
1958 }
1959
1960 LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const
1961 {
1962 #if ENABLE(CSS_GRID_LAYOUT)
1963     if (hasOverrideContainingBlockLogicalHeight()) {
1964         if (auto overrideLogicalHeight = overrideContainingBlockContentLogicalHeight())
1965             return overrideLogicalHeight.value();
1966     }
1967 #endif
1968
1969     RenderBlock* cb = containingBlock();
1970     if (cb->hasOverrideLogicalContentHeight())
1971         return cb->overrideLogicalContentHeight();
1972
1973     const RenderStyle& containingBlockStyle = cb->style();
1974     Length logicalHeightLength = containingBlockStyle.logicalHeight();
1975
1976     // FIXME: For now just support fixed heights.  Eventually should support percentage heights as well.
1977     if (!logicalHeightLength.isFixed()) {
1978         LayoutUnit fillFallbackExtent = containingBlockStyle.isHorizontalWritingMode() ? view().frameView().visibleHeight() : view().frameView().visibleWidth();
1979         LayoutUnit fillAvailableExtent = containingBlock()->availableLogicalHeight(ExcludeMarginBorderPadding);
1980         return std::min(fillAvailableExtent, fillFallbackExtent);
1981     }
1982
1983     // Use the content box logical height as specified by the style.
1984     return cb->adjustContentBoxLogicalHeightForBoxSizing(LayoutUnit(logicalHeightLength.value()));
1985 }
1986
1987 void RenderBox::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
1988 {
1989     if (repaintContainer == this)
1990         return;
1991
1992     if (view().layoutStateEnabled() && !repaintContainer) {
1993         LayoutState* layoutState = view().layoutState();
1994         LayoutSize offset = layoutState->m_paintOffset + locationOffset();
1995         if (style().hasInFlowPosition() && layer())
1996             offset += layer()->offsetForInFlowPosition();
1997         transformState.move(offset);
1998         return;
1999     }
2000
2001     bool containerSkipped;
2002     RenderElement* container = this->container(repaintContainer, &containerSkipped);
2003     if (!container)
2004         return;
2005
2006     bool isFixedPos = style().position() == FixedPosition;
2007     // If this box has a transform, it acts as a fixed position container for fixed descendants,
2008     // and may itself also be fixed position. So propagate 'fixed' up only if this box is fixed position.
2009     if (hasTransform() && !isFixedPos)
2010         mode &= ~IsFixed;
2011     else if (isFixedPos)
2012         mode |= IsFixed;
2013
2014     if (wasFixed)
2015         *wasFixed = mode & IsFixed;
2016     
2017     LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(transformState.mappedPoint()));
2018     
2019     bool preserve3D = mode & UseTransforms && (container->style().preserves3D() || style().preserves3D());
2020     if (mode & UseTransforms && shouldUseTransformFromContainer(container)) {
2021         TransformationMatrix t;
2022         getTransformFromContainer(container, containerOffset, t);
2023         transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
2024     } else
2025         transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
2026
2027     if (containerSkipped) {
2028         // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
2029         // to just subtract the delta between the repaintContainer and o.
2030         LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(*container);
2031         transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
2032         return;
2033     }
2034
2035     mode &= ~ApplyContainerFlip;
2036
2037     // For fixed positioned elements inside out-of-flow named flows, we do not want to
2038     // map their position further to regions based on their coordinates inside the named flows.
2039     if (!container->isOutOfFlowRenderFlowThread() || !fixedPositionedWithNamedFlowContainingBlock())
2040         container->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
2041     else
2042         container->mapLocalToContainer(downcast<RenderLayerModelObject>(container), transformState, mode, wasFixed);
2043 }
2044
2045 const RenderObject* RenderBox::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
2046 {
2047     ASSERT(ancestorToStopAt != this);
2048
2049     bool ancestorSkipped;
2050     RenderElement* container = this->container(ancestorToStopAt, &ancestorSkipped);
2051     if (!container)
2052         return nullptr;
2053
2054     bool isFixedPos = style().position() == FixedPosition;
2055     LayoutSize adjustmentForSkippedAncestor;
2056     if (ancestorSkipped) {
2057         // There can't be a transform between repaintContainer and container, because transforms create containers, so it should be safe
2058         // to just subtract the delta between the ancestor and container.
2059         adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(*container);
2060     }
2061
2062     bool offsetDependsOnPoint = false;
2063     LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(), &offsetDependsOnPoint);
2064
2065     bool preserve3D = container->style().preserves3D() || style().preserves3D();
2066     if (shouldUseTransformFromContainer(container) && (geometryMap.mapCoordinatesFlags() & UseTransforms)) {
2067         TransformationMatrix t;
2068         getTransformFromContainer(container, containerOffset, t);
2069         t.translateRight(adjustmentForSkippedAncestor.width(), adjustmentForSkippedAncestor.height());
2070         
2071         geometryMap.push(this, t, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform());
2072     } else {
2073         containerOffset += adjustmentForSkippedAncestor;
2074         geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform());
2075     }
2076     
2077     return ancestorSkipped ? ancestorToStopAt : container;
2078 }
2079
2080 void RenderBox::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
2081 {
2082     bool isFixedPos = style().position() == FixedPosition;
2083     if (hasTransform() && !isFixedPos) {
2084         // If this box has a transform, it acts as a fixed position container for fixed descendants,
2085         // and may itself also be fixed position. So propagate 'fixed' up only if this box is fixed position.
2086         mode &= ~IsFixed;
2087     } else if (isFixedPos)
2088         mode |= IsFixed;
2089
2090     RenderBoxModelObject::mapAbsoluteToLocalPoint(mode, transformState);
2091 }
2092
2093 LayoutSize RenderBox::offsetFromContainer(RenderElement& renderer, const LayoutPoint&, bool* offsetDependsOnPoint) const
2094 {
2095     // A region "has" boxes inside it without being their container. 
2096     ASSERT(&renderer == container() || is<RenderRegion>(renderer));
2097
2098     LayoutSize offset;    
2099     if (isInFlowPositioned())
2100         offset += offsetForInFlowPosition();
2101
2102     if (!isInline() || isReplaced())
2103         offset += topLeftLocationOffset();
2104
2105     if (is<RenderBox>(renderer))
2106         offset -= downcast<RenderBox>(renderer).scrolledContentOffset();
2107
2108     if (style().position() == AbsolutePosition && renderer.isInFlowPositioned() && is<RenderInline>(renderer))
2109         offset += downcast<RenderInline>(renderer).offsetForInFlowPositionedInline(this);
2110
2111     if (offsetDependsOnPoint)
2112         *offsetDependsOnPoint |= is<RenderFlowThread>(renderer);
2113
2114     return offset;
2115 }
2116
2117 std::unique_ptr<InlineElementBox> RenderBox::createInlineBox()
2118 {
2119     return std::make_unique<InlineElementBox>(*this);
2120 }
2121
2122 void RenderBox::dirtyLineBoxes(bool fullLayout)
2123 {
2124     if (m_inlineBoxWrapper) {
2125         if (fullLayout) {
2126             delete m_inlineBoxWrapper;
2127             m_inlineBoxWrapper = nullptr;
2128         } else
2129             m_inlineBoxWrapper->dirtyLineBoxes();
2130     }
2131 }
2132
2133 void RenderBox::positionLineBox(InlineElementBox& box)
2134 {
2135     if (isOutOfFlowPositioned()) {
2136         // Cache the x position only if we were an INLINE type originally.
2137         bool wasInline = style().isOriginalDisplayInlineType();
2138         if (wasInline) {
2139             // The value is cached in the xPos of the box.  We only need this value if
2140             // our object was inline originally, since otherwise it would have ended up underneath
2141             // the inlines.
2142             RootInlineBox& rootBox = box.root();
2143             rootBox.blockFlow().setStaticInlinePositionForChild(*this, rootBox.lineTopWithLeading(), LayoutUnit::fromFloatRound(box.logicalLeft()));
2144             if (style().hasStaticInlinePosition(box.isHorizontal()))
2145                 setChildNeedsLayout(MarkOnlyThis); // Just mark the positioned object as needing layout, so it will update its position properly.
2146         } else {
2147             // Our object was a block originally, so we make our normal flow position be
2148             // just below the line box (as though all the inlines that came before us got
2149             // wrapped in an anonymous block, which is what would have happened had we been
2150             // in flow).  This value was cached in the y() of the box.
2151             layer()->setStaticBlockPosition(box.logicalTop());
2152             if (style().hasStaticBlockPosition(box.isHorizontal()))
2153                 setChildNeedsLayout(MarkOnlyThis); // Just mark the positioned object as needing layout, so it will update its position properly.
2154         }
2155
2156         // Nuke the box.
2157         box.removeFromParent();
2158         delete &box;
2159         return;
2160     }
2161
2162     if (isReplaced()) {
2163         setLocation(LayoutPoint(box.topLeft()));
2164         setInlineBoxWrapper(&box);
2165     }
2166 }
2167
2168 void RenderBox::deleteLineBoxWrapper()
2169 {
2170     if (m_inlineBoxWrapper) {
2171         if (!documentBeingDestroyed())
2172             m_inlineBoxWrapper->removeFromParent();
2173         delete m_inlineBoxWrapper;
2174         m_inlineBoxWrapper = nullptr;
2175     }
2176 }
2177
2178 LayoutRect RenderBox::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
2179 {
2180     if (style().visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
2181         return LayoutRect();
2182     LayoutRect r = visualOverflowRect();
2183     // FIXME: layoutDelta needs to be applied in parts before/after transforms and
2184     // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
2185     r.move(view().layoutDelta());
2186     return computeRectForRepaint(r, repaintContainer);
2187 }
2188
2189 static inline bool shouldApplyContainersClipAndOffset(const RenderLayerModelObject* repaintContainer, RenderBox* containerBox)
2190 {
2191 #if PLATFORM(IOS)
2192     if (!repaintContainer || repaintContainer != containerBox)
2193         return true;
2194
2195     return !containerBox->hasLayer() || !containerBox->layer()->usesCompositedScrolling();
2196 #else
2197     UNUSED_PARAM(repaintContainer);
2198     UNUSED_PARAM(containerBox);
2199     return true;
2200 #endif
2201 }
2202
2203 LayoutRect RenderBox::computeRectForRepaint(const LayoutRect& rect, const RenderLayerModelObject* repaintContainer, bool fixed) const
2204 {
2205     // The rect we compute at each step is shifted by our x/y offset in the parent container's coordinate space.
2206     // Only when we cross a writing mode boundary will we have to possibly flipForWritingMode (to convert into a more appropriate
2207     // offset corner for the enclosing container).  This allows for a fully RL or BT document to repaint
2208     // properly even during layout, since the rect remains flipped all the way until the end.
2209     //
2210     // RenderView::computeRectForRepaint then converts the rect to physical coordinates.  We also convert to
2211     // physical when we hit a repaintContainer boundary.  Therefore the final rect returned is always in the
2212     // physical coordinate space of the repaintContainer.
2213     LayoutRect adjustedRect = rect;
2214     const RenderStyle& styleToUse = style();
2215     // LayoutState is only valid for root-relative, non-fixed position repainting
2216     if (view().layoutStateEnabled() && !repaintContainer && styleToUse.position() != FixedPosition) {
2217         LayoutState* layoutState = view().layoutState();
2218
2219         if (layer() && layer()->transform())
2220             adjustedRect = LayoutRect(encloseRectToDevicePixels(layer()->transform()->mapRect(adjustedRect), document().deviceScaleFactor()));
2221
2222         // We can't trust the bits on RenderObject, because this might be called while re-resolving style.
2223         if (styleToUse.hasInFlowPosition() && layer())
2224             adjustedRect.move(layer()->offsetForInFlowPosition());
2225
2226         adjustedRect.moveBy(location());
2227         adjustedRect.move(layoutState->m_paintOffset);
2228         if (layoutState->m_clipped)
2229             adjustedRect.intersect(layoutState->m_clipRect);
2230         return adjustedRect;
2231     }
2232
2233     if (hasReflection())
2234         adjustedRect.unite(reflectedRect(adjustedRect));
2235
2236     if (repaintContainer == this) {
2237         if (repaintContainer->style().isFlippedBlocksWritingMode())
2238             flipForWritingMode(adjustedRect);
2239         return adjustedRect;
2240     }
2241
2242     bool containerSkipped;
2243     auto* renderer = container(repaintContainer, &containerSkipped);
2244     if (!renderer)
2245         return adjustedRect;
2246     
2247     EPosition position = styleToUse.position();
2248
2249     // This code isn't necessary for in-flow RenderFlowThreads.
2250     // Don't add the location of the region in the flow thread for absolute positioned
2251     // elements because their absolute position already pushes them down through
2252     // the regions so adding this here and then adding the topLeft again would cause
2253     // us to add the height twice.
2254     // The same logic applies for elements flowed directly into the flow thread. Their topLeft member
2255     // will already contain the portion rect of the region.
2256     if (renderer->isOutOfFlowRenderFlowThread() && position != AbsolutePosition && containingBlock() != flowThreadContainingBlock()) {
2257         RenderRegion* firstRegion = nullptr;
2258         RenderRegion* lastRegion = nullptr;
2259         if (downcast<RenderFlowThread>(*renderer).getRegionRangeForBox(this, firstRegion, lastRegion))
2260             adjustedRect.moveBy(firstRegion->flowThreadPortionRect().location());
2261     }
2262
2263     if (isWritingModeRoot() && !isOutOfFlowPositioned())
2264         flipForWritingMode(adjustedRect);
2265
2266     LayoutSize locationOffset = this->locationOffset();
2267     // FIXME: This is needed as long as RenderWidget snaps to integral size/position.
2268     if (isRenderReplaced() && isWidget()) {
2269         LayoutSize flooredLocationOffset = toIntSize(flooredIntPoint(locationOffset));
2270         adjustedRect.expand(locationOffset - flooredLocationOffset);
2271         locationOffset = flooredLocationOffset;
2272     }
2273     LayoutPoint topLeft = adjustedRect.location();
2274     topLeft.move(locationOffset);
2275
2276     // We are now in our parent container's coordinate space. Apply our transform to obtain a bounding box
2277     // in the parent's coordinate space that encloses us.
2278     if (hasLayer() && layer()->transform()) {
2279         fixed = position == FixedPosition;
2280         adjustedRect = LayoutRect(encloseRectToDevicePixels(layer()->transform()->mapRect(adjustedRect), document().deviceScaleFactor()));
2281         topLeft = adjustedRect.location();
2282         topLeft.move(locationOffset);
2283     } else if (position == FixedPosition)
2284         fixed = true;
2285
2286     if (position == AbsolutePosition && renderer->isInFlowPositioned() && is<RenderInline>(*renderer))
2287         topLeft += downcast<RenderInline>(*renderer).offsetForInFlowPositionedInline(this);
2288     else if (styleToUse.hasInFlowPosition() && layer()) {
2289         // Apply the relative position offset when invalidating a rectangle.  The layer
2290         // is translated, but the render box isn't, so we need to do this to get the
2291         // right dirty rect.  Since this is called from RenderObject::setStyle, the relative position
2292         // flag on the RenderObject has been cleared, so use the one on the style().
2293         topLeft += layer()->offsetForInFlowPosition();
2294     }
2295
2296     // FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout,
2297     // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer.
2298     adjustedRect.setLocation(topLeft);
2299     if (renderer->hasOverflowClip()) {
2300         RenderBox& containerBox = downcast<RenderBox>(*renderer);
2301         if (shouldApplyContainersClipAndOffset(repaintContainer, &containerBox)) {
2302             containerBox.applyCachedClipAndScrollOffsetForRepaint(adjustedRect);
2303             if (adjustedRect.isEmpty())
2304                 return adjustedRect;
2305         }
2306     }
2307
2308     if (containerSkipped) {
2309         // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
2310         LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(*renderer);
2311         adjustedRect.move(-containerOffset);
2312         return adjustedRect;
2313     }
2314     return renderer->computeRectForRepaint(adjustedRect, repaintContainer, fixed);
2315 }
2316
2317 void RenderBox::repaintDuringLayoutIfMoved(const LayoutRect& oldRect)
2318 {
2319     if (oldRect.location() != m_frameRect.location()) {
2320         LayoutRect newRect = m_frameRect;
2321         // The child moved.  Invalidate the object's old and new positions.  We have to do this
2322         // since the object may not have gotten a layout.
2323         m_frameRect = oldRect;
2324         repaint();
2325         repaintOverhangingFloats(true);
2326         m_frameRect = newRect;
2327         repaint();
2328         repaintOverhangingFloats(true);
2329     }
2330 }
2331
2332 void RenderBox::repaintOverhangingFloats(bool)
2333 {
2334 }
2335
2336 void RenderBox::updateLogicalWidth()
2337 {
2338     LogicalExtentComputedValues computedValues;
2339     computeLogicalWidthInRegion(computedValues);
2340
2341     setLogicalWidth(computedValues.m_extent);
2342     setLogicalLeft(computedValues.m_position);
2343     setMarginStart(computedValues.m_margins.m_start);
2344     setMarginEnd(computedValues.m_margins.m_end);
2345 }
2346
2347 void RenderBox::computeLogicalWidthInRegion(LogicalExtentComputedValues& computedValues, RenderRegion* region) const
2348 {
2349     computedValues.m_extent = logicalWidth();
2350     computedValues.m_position = logicalLeft();
2351     computedValues.m_margins.m_start = marginStart();
2352     computedValues.m_margins.m_end = marginEnd();
2353
2354     if (isOutOfFlowPositioned()) {
2355         // FIXME: This calculation is not patched for block-flow yet.
2356         // https://bugs.webkit.org/show_bug.cgi?id=46500
2357         computePositionedLogicalWidth(computedValues, region);
2358         return;
2359     }
2360
2361     // If layout is limited to a subtree, the subtree root's logical width does not change.
2362     if (element() && !view().frameView().layoutPending() && view().frameView().layoutRoot() == this)
2363         return;
2364
2365     // The parent box is flexing us, so it has increased or decreased our
2366     // width.  Use the width from the style context.
2367     // FIXME: Account for block-flow in flexible boxes.
2368     // https://bugs.webkit.org/show_bug.cgi?id=46418
2369     if (hasOverrideLogicalContentWidth() && (isRubyRun() || style().borderFit() == BorderFitLines || (parent()->isFlexibleBoxIncludingDeprecated()))) {
2370         computedValues.m_extent = overrideLogicalContentWidth() + borderAndPaddingLogicalWidth();
2371         return;
2372     }
2373
2374     // FIXME: Account for block-flow in flexible boxes.
2375     // https://bugs.webkit.org/show_bug.cgi?id=46418
2376     bool inVerticalBox = parent()->isDeprecatedFlexibleBox() && (parent()->style().boxOrient() == VERTICAL);
2377     bool stretching = (parent()->style().boxAlign() == BSTRETCH);
2378     // FIXME: Stretching is the only reason why we don't want the box to be treated as a replaced element, so we could perhaps
2379     // refactor all this logic, not only for flex and grid since alignment is intended to be applied to any block.
2380     bool treatAsReplaced = shouldComputeSizeAsReplaced() && (!inVerticalBox || !stretching);
2381 #if ENABLE(CSS_GRID_LAYOUT)
2382     treatAsReplaced = treatAsReplaced && (!isGridItem() || !hasStretchedLogicalWidth());
2383 #endif
2384
2385     const RenderStyle& styleToUse = style();
2386     Length logicalWidthLength = treatAsReplaced ? Length(computeReplacedLogicalWidth(), Fixed) : styleToUse.logicalWidth();
2387
2388     RenderBlock* cb = containingBlock();
2389     LayoutUnit containerLogicalWidth = std::max<LayoutUnit>(0, containingBlockLogicalWidthForContentInRegion(region));
2390     bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
2391
2392     if (isInline() && !isInlineBlockOrInlineTable()) {
2393         // just calculate margins
2394         computedValues.m_margins.m_start = minimumValueForLength(styleToUse.marginStart(), containerLogicalWidth);
2395         computedValues.m_margins.m_end = minimumValueForLength(styleToUse.marginEnd(), containerLogicalWidth);
2396         if (treatAsReplaced)
2397             computedValues.m_extent = std::max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth());
2398         return;
2399     }
2400
2401     // Width calculations
2402     if (treatAsReplaced) {
2403         computedValues.m_extent = logicalWidthLength.value() + borderAndPaddingLogicalWidth();
2404 #if ENABLE(CSS_GRID_LAYOUT)
2405     } else if (parent()->isRenderGrid() && style().logicalWidth().isAuto() && style().logicalMinWidth().isAuto() && style().overflowX() == OVISIBLE && containerLogicalWidth < minPreferredLogicalWidth()) {
2406         // TODO (lajava) Move this logic to the LayoutGrid class.
2407         // Implied minimum size of Grid items.
2408         computedValues.m_extent = constrainLogicalWidthInRegionByMinMax(minPreferredLogicalWidth(), containerLogicalWidth, cb);
2409 #endif
2410     } else {
2411         LayoutUnit containerWidthInInlineDirection = containerLogicalWidth;
2412         if (hasPerpendicularContainingBlock)
2413             containerWidthInInlineDirection = perpendicularContainingBlockLogicalHeight();
2414         LayoutUnit preferredWidth = computeLogicalWidthInRegionUsing(MainOrPreferredSize, styleToUse.logicalWidth(), containerWidthInInlineDirection, cb, region);
2415         computedValues.m_extent = constrainLogicalWidthInRegionByMinMax(preferredWidth, containerWidthInInlineDirection, cb, region);
2416     }
2417
2418     // Margin calculations.
2419     if (hasPerpendicularContainingBlock || isFloating() || isInline()) {
2420         computedValues.m_margins.m_start = minimumValueForLength(styleToUse.marginStart(), containerLogicalWidth);
2421         computedValues.m_margins.m_end = minimumValueForLength(styleToUse.marginEnd(), containerLogicalWidth);
2422     } else {
2423         LayoutUnit containerLogicalWidthForAutoMargins = containerLogicalWidth;
2424         if (avoidsFloats() && cb->containsFloats())
2425             containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(region);
2426         bool hasInvertedDirection = cb->style().isLeftToRightDirection() != style().isLeftToRightDirection();
2427         computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, computedValues.m_extent,
2428             hasInvertedDirection ? computedValues.m_margins.m_end : computedValues.m_margins.m_start,
2429             hasInvertedDirection ? computedValues.m_margins.m_start : computedValues.m_margins.m_end);
2430     }
2431     
2432     if (!hasPerpendicularContainingBlock && containerLogicalWidth && containerLogicalWidth != (computedValues.m_extent + computedValues.m_margins.m_start + computedValues.m_margins.m_end)
2433         && !isFloating() && !isInline() && !cb->isFlexibleBoxIncludingDeprecated()
2434 #if ENABLE(CSS_GRID_LAYOUT)
2435         && !cb->isRenderGrid()
2436 #endif
2437         ) {
2438         LayoutUnit newMargin = containerLogicalWidth - computedValues.m_extent - cb->marginStartForChild(*this);
2439         bool hasInvertedDirection = cb->style().isLeftToRightDirection() != style().isLeftToRightDirection();
2440         if (hasInvertedDirection)
2441             computedValues.m_margins.m_start = newMargin;
2442         else
2443             computedValues.m_margins.m_end = newMargin;
2444     }
2445 }
2446
2447 LayoutUnit RenderBox::fillAvailableMeasure(LayoutUnit availableLogicalWidth) const
2448 {
2449     LayoutUnit marginStart = 0;
2450     LayoutUnit marginEnd = 0;
2451     return fillAvailableMeasure(availableLogicalWidth, marginStart, marginEnd);
2452 }
2453
2454 LayoutUnit RenderBox::fillAvailableMeasure(LayoutUnit availableLogicalWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const
2455 {
2456     marginStart = minimumValueForLength(style().marginStart(), availableLogicalWidth);
2457     marginEnd = minimumValueForLength(style().marginEnd(), availableLogicalWidth);
2458     return availableLogicalWidth - marginStart - marginEnd;
2459 }
2460
2461 LayoutUnit RenderBox::computeIntrinsicLogicalWidthUsing(Length logicalWidthLength, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const
2462 {
2463     if (logicalWidthLength.type() == FillAvailable)
2464         return fillAvailableMeasure(availableLogicalWidth);
2465
2466     LayoutUnit minLogicalWidth = 0;
2467     LayoutUnit maxLogicalWidth = 0;
2468     computeIntrinsicLogicalWidths(minLogicalWidth, maxLogicalWidth);
2469
2470     if (logicalWidthLength.type() == MinContent)
2471         return minLogicalWidth + borderAndPadding;
2472
2473     if (logicalWidthLength.type() == MaxContent)
2474         return maxLogicalWidth + borderAndPadding;
2475
2476     if (logicalWidthLength.type() == FitContent) {
2477         minLogicalWidth += borderAndPadding;
2478         maxLogicalWidth += borderAndPadding;
2479         return std::max(minLogicalWidth, std::min(maxLogicalWidth, fillAvailableMeasure(availableLogicalWidth)));
2480     }
2481
2482     ASSERT_NOT_REACHED();
2483     return 0;
2484 }
2485
2486 LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(SizeType widthType, Length logicalWidth, LayoutUnit availableLogicalWidth,
2487     const RenderBlock* cb, RenderRegion* region) const
2488 {
2489     ASSERT(widthType == MinSize || widthType == MainOrPreferredSize || !logicalWidth.isAuto());
2490     if (widthType == MinSize && logicalWidth.isAuto())
2491         return adjustBorderBoxLogicalWidthForBoxSizing(0);
2492
2493     if (!logicalWidth.isIntrinsicOrAuto()) {
2494         // FIXME: If the containing block flow is perpendicular to our direction we need to use the available logical height instead.
2495         return adjustBorderBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, availableLogicalWidth));
2496     }
2497
2498     if (logicalWidth.isIntrinsic())
2499         return computeIntrinsicLogicalWidthUsing(logicalWidth, availableLogicalWidth, borderAndPaddingLogicalWidth());
2500
2501     LayoutUnit marginStart = 0;
2502     LayoutUnit marginEnd = 0;
2503     LayoutUnit logicalWidthResult = fillAvailableMeasure(availableLogicalWidth, marginStart, marginEnd);
2504
2505     if (shrinkToAvoidFloats() && cb->containsFloats())
2506         logicalWidthResult = std::min(logicalWidthResult, shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, region));
2507
2508     if (widthType == MainOrPreferredSize && sizesLogicalWidthToFitContent(widthType))
2509         return std::max(minPreferredLogicalWidth(), std::min(maxPreferredLogicalWidth(), logicalWidthResult));
2510     return logicalWidthResult;
2511 }
2512
2513 static bool flexItemHasStretchAlignment(const RenderBox& flexitem)
2514 {
2515     auto parent = flexitem.parent();
2516     return RenderStyle::resolveAlignment(parent->style(), flexitem.style(), ItemPositionStretch) == ItemPositionStretch;
2517 }
2518
2519 static bool isStretchingColumnFlexItem(const RenderBox& flexitem)
2520 {
2521     auto parent = flexitem.parent();
2522     if (parent->isDeprecatedFlexibleBox() && parent->style().boxOrient() == VERTICAL && parent->style().boxAlign() == BSTRETCH)
2523         return true;
2524
2525     // We don't stretch multiline flexboxes because they need to apply line spacing (align-content) first.
2526     if (parent->isFlexibleBox() && parent->style().flexWrap() == FlexNoWrap && parent->style().isColumnFlexDirection() && flexItemHasStretchAlignment(flexitem))
2527         return true;
2528     return false;
2529 }
2530
2531 // FIXME: Can/Should we move this inside specific layout classes (flex. grid)? Can we refactor columnFlexItemHasStretchAlignment logic?
2532 bool RenderBox::hasStretchedLogicalWidth() const
2533 {
2534     auto& style = this->style();
2535     if (!style.logicalWidth().isAuto() || style.marginStart().isAuto() || style.marginEnd().isAuto())
2536         return false;
2537     RenderBlock* containingBlock = this->containingBlock();
2538     if (!containingBlock) {
2539         // We are evaluating align-self/justify-self, which default to 'normal' for the root element.
2540         // The 'normal' value behaves like 'start' except for Flexbox Items, which obviously should have a container.
2541         return false;
2542     }
2543     if (containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
2544         return RenderStyle::resolveAlignment(containingBlock->style(), style, ItemPositionStretch) == ItemPositionStretch;
2545     return RenderStyle::resolveJustification(containingBlock->style(), style, ItemPositionStretch) == ItemPositionStretch;
2546 }
2547
2548 bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const
2549 {
2550     // Anonymous inline blocks always fill the width of their containing block.
2551     if (isAnonymousInlineBlock())
2552         return false;
2553
2554     // Marquees in WinIE are like a mixture of blocks and inline-blocks.  They size as though they're blocks,
2555     // but they allow text to sit on the same line as the marquee.
2556     if (isFloating() || (isInlineBlockOrInlineTable() && !isHTMLMarquee()))
2557         return true;
2558
2559 #if ENABLE(CSS_GRID_LAYOUT)
2560     if (isGridItem())
2561         return !hasStretchedLogicalWidth();
2562 #endif
2563
2564     // This code may look a bit strange.  Basically width:intrinsic should clamp the size when testing both
2565     // min-width and width.  max-width is only clamped if it is also intrinsic.
2566     Length logicalWidth = (widthType == MaxSize) ? style().logicalMaxWidth() : style().logicalWidth();
2567     if (logicalWidth.type() == Intrinsic)
2568         return true;
2569
2570     // Children of a horizontal marquee do not fill the container by default.
2571     // FIXME: Need to deal with MAUTO value properly.  It could be vertical.
2572     // FIXME: Think about block-flow here.  Need to find out how marquee direction relates to
2573     // block-flow (as well as how marquee overflow should relate to block flow).
2574     // https://bugs.webkit.org/show_bug.cgi?id=46472
2575     if (parent()->style().overflowX() == OMARQUEE) {
2576         EMarqueeDirection dir = parent()->style().marqueeDirection();
2577         if (dir == MAUTO || dir == MFORWARD || dir == MBACKWARD || dir == MLEFT || dir == MRIGHT)
2578             return true;
2579     }
2580
2581     // Flexible box items should shrink wrap, so we lay them out at their intrinsic widths.
2582     // In the case of columns that have a stretch alignment, we layout at the stretched size
2583     // to avoid an extra layout when applying alignment.
2584     if (parent()->isFlexibleBox()) {
2585         // For multiline columns, we need to apply align-content first, so we can't stretch now.
2586         if (!parent()->style().isColumnFlexDirection() || parent()->style().flexWrap() != FlexNoWrap)
2587             return true;
2588         if (!flexItemHasStretchAlignment(*this))
2589             return true;
2590     }
2591
2592     // Flexible horizontal boxes lay out children at their intrinsic widths.  Also vertical boxes
2593     // that don't stretch their kids lay out their children at their intrinsic widths.
2594     // FIXME: Think about block-flow here.
2595     // https://bugs.webkit.org/show_bug.cgi?id=46473
2596     if (parent()->isDeprecatedFlexibleBox() && (parent()->style().boxOrient() == HORIZONTAL || parent()->style().boxAlign() != BSTRETCH))
2597         return true;
2598
2599     // Button, input, select, textarea, and legend treat width value of 'auto' as 'intrinsic' unless it's in a
2600     // stretching column flexbox.
2601     // FIXME: Think about block-flow here.
2602     // https://bugs.webkit.org/show_bug.cgi?id=46473
2603     if (logicalWidth.type() == Auto && !isStretchingColumnFlexItem(*this) && element() && (is<HTMLInputElement>(*element()) || is<HTMLSelectElement>(*element()) || is<HTMLButtonElement>(*element()) || is<HTMLTextAreaElement>(*element()) || is<HTMLLegendElement>(*element())))
2604         return true;
2605
2606     if (isHorizontalWritingMode() != containingBlock()->isHorizontalWritingMode())
2607         return true;
2608
2609     return false;
2610 }
2611
2612 void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const
2613 {
2614     const RenderStyle& containingBlockStyle = containingBlock->style();
2615     Length marginStartLength = style().marginStartUsing(&containingBlockStyle);
2616     Length marginEndLength = style().marginEndUsing(&containingBlockStyle);
2617
2618     if (isFloating() || isInline()) {
2619         // Inline blocks/tables and floats don't have their margins increased.
2620         marginStart = minimumValueForLength(marginStartLength, containerWidth);
2621         marginEnd = minimumValueForLength(marginEndLength, containerWidth);
2622         return;
2623     }
2624
2625     // Case One: The object is being centered in the containing block's available logical width.
2626     if ((marginStartLength.isAuto() && marginEndLength.isAuto() && childWidth < containerWidth)
2627         || (!marginStartLength.isAuto() && !marginEndLength.isAuto() && containingBlock->style().textAlign() == WEBKIT_CENTER)) {
2628         // Other browsers center the margin box for align=center elements so we match them here.
2629         LayoutUnit marginStartWidth = minimumValueForLength(marginStartLength, containerWidth);
2630         LayoutUnit marginEndWidth = minimumValueForLength(marginEndLength, containerWidth);
2631         LayoutUnit centeredMarginBoxStart = std::max<LayoutUnit>(0, (containerWidth - childWidth - marginStartWidth - marginEndWidth) / 2);
2632         marginStart = centeredMarginBoxStart + marginStartWidth;
2633         marginEnd = containerWidth - childWidth - marginStart + marginEndWidth;
2634         return;
2635     } 
2636     
2637     // Case Two: The object is being pushed to the start of the containing block's available logical width.
2638     if (marginEndLength.isAuto() && childWidth < containerWidth) {
2639         marginStart = valueForLength(marginStartLength, containerWidth);
2640         marginEnd = containerWidth - childWidth - marginStart;
2641         return;
2642     } 
2643     
2644     // Case Three: The object is being pushed to the end of the containing block's available logical width.
2645     bool pushToEndFromTextAlign = !marginEndLength.isAuto() && ((!containingBlockStyle.isLeftToRightDirection() && containingBlockStyle.textAlign() == WEBKIT_LEFT)
2646         || (containingBlockStyle.isLeftToRightDirection() && containingBlockStyle.textAlign() == WEBKIT_RIGHT));
2647     if ((marginStartLength.isAuto() && childWidth < containerWidth) || pushToEndFromTextAlign) {
2648         marginEnd = valueForLength(marginEndLength, containerWidth);
2649         marginStart = containerWidth - childWidth - marginEnd;
2650         return;
2651     } 
2652     
2653     // Case Four: Either no auto margins, or our width is >= the container width (css2.1, 10.3.3).  In that case
2654     // auto margins will just turn into 0.
2655     marginStart = minimumValueForLength(marginStartLength, containerWidth);
2656     marginEnd = minimumValueForLength(marginEndLength, containerWidth);
2657 }
2658
2659 RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, RenderBoxRegionInfoFlags cacheFlag) const
2660 {
2661     // Make sure nobody is trying to call this with a null region.
2662     if (!region)
2663         return nullptr;
2664
2665     // If we have computed our width in this region already, it will be cached, and we can
2666     // just return it.
2667     RenderBoxRegionInfo* boxInfo = region->renderBoxRegionInfo(this);
2668     if (boxInfo && cacheFlag == CacheRenderBoxRegionInfo)
2669         return boxInfo;
2670
2671     // No cached value was found, so we have to compute our insets in this region.
2672     // FIXME: For now we limit this computation to normal RenderBlocks. Future patches will expand
2673     // support to cover all boxes.
2674     RenderFlowThread* flowThread = flowThreadContainingBlock();
2675     if (isRenderFlowThread() || !flowThread || !canHaveBoxInfoInRegion() || flowThread->style().writingMode() != style().writingMode())
2676         return nullptr;
2677
2678     LogicalExtentComputedValues computedValues;
2679     computeLogicalWidthInRegion(computedValues, region);
2680
2681     // Now determine the insets based off where this object is supposed to be positioned.
2682     RenderBlock* cb = containingBlock();
2683     RenderRegion* clampedContainingBlockRegion = cb->clampToStartAndEndRegions(region);
2684     RenderBoxRegionInfo* containingBlockInfo = cb->renderBoxRegionInfo(clampedContainingBlockRegion);
2685     LayoutUnit containingBlockLogicalWidth = cb->logicalWidth();
2686     LayoutUnit containingBlockLogicalWidthInRegion = containingBlockInfo ? containingBlockInfo->logicalWidth() : containingBlockLogicalWidth;
2687     
2688     LayoutUnit marginStartInRegion = computedValues.m_margins.m_start;
2689     LayoutUnit startMarginDelta = marginStartInRegion - marginStart();
2690     LayoutUnit logicalWidthInRegion = computedValues.m_extent;
2691     LayoutUnit logicalLeftInRegion = computedValues.m_position;
2692     LayoutUnit widthDelta = logicalWidthInRegion - logicalWidth();
2693     LayoutUnit logicalLeftDelta = isOutOfFlowPositioned() ? logicalLeftInRegion - logicalLeft() : startMarginDelta;
2694     LayoutUnit logicalRightInRegion = containingBlockLogicalWidthInRegion - (logicalLeftInRegion + logicalWidthInRegion);
2695     LayoutUnit oldLogicalRight = containingBlockLogicalWidth - (logicalLeft() + logicalWidth());
2696     LayoutUnit logicalRightDelta = isOutOfFlowPositioned() ? logicalRightInRegion - oldLogicalRight : startMarginDelta;
2697
2698     LayoutUnit logicalLeftOffset = 0;
2699     
2700     if (!isOutOfFlowPositioned() && avoidsFloats() && cb->containsFloats()) {
2701         LayoutUnit startPositionDelta = cb->computeStartPositionDeltaForChildAvoidingFloats(*this, marginStartInRegion, region);
2702         if (cb->style().isLeftToRightDirection())
2703             logicalLeftDelta += startPositionDelta;
2704         else
2705             logicalRightDelta += startPositionDelta;
2706     }
2707
2708     if (cb->style().isLeftToRightDirection())
2709         logicalLeftOffset += logicalLeftDelta;
2710     else
2711         logicalLeftOffset -= (widthDelta + logicalRightDelta);
2712     
2713     LayoutUnit logicalRightOffset = logicalWidth() - (logicalLeftOffset + logicalWidthInRegion);
2714     bool isShifted = (containingBlockInfo && containingBlockInfo->isShifted())
2715             || (style().isLeftToRightDirection() && logicalLeftOffset)
2716             || (!style().isLeftToRightDirection() && logicalRightOffset);
2717
2718     // FIXME: Although it's unlikely, these boxes can go outside our bounds, and so we will need to incorporate them into overflow.
2719     if (cacheFlag == CacheRenderBoxRegionInfo)
2720         return region->setRenderBoxRegionInfo(this, logicalLeftOffset, logicalWidthInRegion, isShifted);
2721     return new RenderBoxRegionInfo(logicalLeftOffset, logicalWidthInRegion, isShifted);
2722 }
2723
2724 static bool shouldFlipBeforeAfterMargins(const RenderStyle& containingBlockStyle, const RenderStyle* childStyle)
2725 {
2726     ASSERT(containingBlockStyle.isHorizontalWritingMode() != childStyle->isHorizontalWritingMode());
2727     WritingMode childWritingMode = childStyle->writingMode();
2728     bool shouldFlip = false;
2729     switch (containingBlockStyle.writingMode()) {
2730     case TopToBottomWritingMode:
2731         shouldFlip = (childWritingMode == RightToLeftWritingMode);
2732         break;
2733     case BottomToTopWritingMode:
2734         shouldFlip = (childWritingMode == RightToLeftWritingMode);
2735         break;
2736     case RightToLeftWritingMode:
2737         shouldFlip = (childWritingMode == BottomToTopWritingMode);
2738         break;
2739     case LeftToRightWritingMode:
2740         shouldFlip = (childWritingMode == BottomToTopWritingMode);
2741         break;
2742     }
2743
2744     if (!containingBlockStyle.isLeftToRightDirection())
2745         shouldFlip = !shouldFlip;
2746
2747     return shouldFlip;
2748 }
2749
2750 void RenderBox::updateLogicalHeight()
2751 {
2752     LogicalExtentComputedValues computedValues;
2753     computeLogicalHeight(logicalHeight(), logicalTop(), computedValues);
2754
2755     setLogicalHeight(computedValues.m_extent);
2756     setLogicalTop(computedValues.m_position);
2757     setMarginBefore(computedValues.m_margins.m_before);
2758     setMarginAfter(computedValues.m_margins.m_after);
2759 }
2760
2761 void RenderBox::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
2762 {
2763     computedValues.m_extent = logicalHeight;
2764     computedValues.m_position = logicalTop;
2765
2766     // Cell height is managed by the table and inline non-replaced elements do not support a height property.
2767     if (isTableCell() || (isInline() && !isReplaced()))
2768         return;
2769
2770     Length h;
2771     if (isOutOfFlowPositioned())
2772         computePositionedLogicalHeight(computedValues);
2773     else {
2774         RenderBlock* cb = containingBlock();
2775         bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
2776     
2777         if (!hasPerpendicularContainingBlock) {
2778             bool shouldFlipBeforeAfter = cb->style().writingMode() != style().writingMode();
2779             computeBlockDirectionMargins(cb,
2780                 shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
2781                 shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
2782         }
2783
2784         // For tables, calculate margins only.
2785         if (isTable()) {
2786             if (hasPerpendicularContainingBlock) {
2787                 bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb->style(), &style());
2788                 computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), computedValues.m_extent,
2789                     shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
2790                     shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
2791             }
2792             return;
2793         }
2794
2795         // FIXME: Account for block-flow in flexible boxes.
2796         // https://bugs.webkit.org/show_bug.cgi?id=46418
2797         bool inHorizontalBox = parent()->isDeprecatedFlexibleBox() && parent()->style().boxOrient() == HORIZONTAL;
2798         bool stretching = parent()->style().boxAlign() == BSTRETCH;
2799         bool treatAsReplaced = shouldComputeSizeAsReplaced() && (!inHorizontalBox || !stretching);
2800         bool checkMinMaxHeight = false;
2801
2802         // The parent box is flexing us, so it has increased or decreased our height.  We have to
2803         // grab our cached flexible height.
2804         // FIXME: Account for block-flow in flexible boxes.
2805         // https://bugs.webkit.org/show_bug.cgi?id=46418
2806         if (hasOverrideLogicalContentHeight() && (parent()->isFlexibleBoxIncludingDeprecated()
2807 #if ENABLE(CSS_GRID_LAYOUT)
2808             || parent()->isRenderGrid()
2809 #endif
2810         )) {
2811             LayoutUnit contentHeight = overrideLogicalContentHeight();
2812 #if ENABLE(CSS_GRID_LAYOUT)
2813             if (parent()->isRenderGrid() && style().logicalHeight().isAuto() && style().logicalMinHeight().isAuto() && style().overflowX() == OVISIBLE) {
2814                 LayoutUnit intrinsicContentHeight = computedValues.m_extent - borderAndPaddingLogicalHeight();
2815                 if (auto minContentHeight = computeContentLogicalHeight(MinSize, Length(MinContent), intrinsicContentHeight))
2816                     contentHeight = std::max(contentHeight, constrainContentBoxLogicalHeightByMinMax(minContentHeight.value(), intrinsicContentHeight));
2817             }
2818 #endif
2819             h = Length(contentHeight, Fixed);
2820         } else if (treatAsReplaced)
2821             h = Length(computeReplacedLogicalHeight(), Fixed);
2822         else {
2823             h = style().logicalHeight();
2824             checkMinMaxHeight = true;
2825         }
2826
2827         // Block children of horizontal flexible boxes fill the height of the box.
2828         // FIXME: Account for block-flow in flexible boxes.
2829         // https://bugs.webkit.org/show_bug.cgi?id=46418
2830         if (h.isAuto() && is<RenderDeprecatedFlexibleBox>(*parent()) && parent()->style().boxOrient() == HORIZONTAL
2831                 && downcast<RenderDeprecatedFlexibleBox>(*parent()).isStretchingChildren()) {
2832             h = Length(parentBox()->contentLogicalHeight() - marginBefore() - marginAfter() - borderAndPaddingLogicalHeight(), Fixed);
2833             checkMinMaxHeight = false;
2834         }
2835
2836         LayoutUnit heightResult;
2837         if (checkMinMaxHeight) {
2838             LayoutUnit intrinsicHeight = computedValues.m_extent - borderAndPaddingLogicalHeight();
2839             heightResult = computeLogicalHeightUsing(MainOrPreferredSize, style().logicalHeight(), intrinsicHeight).valueOr(computedValues.m_extent);
2840             heightResult = constrainLogicalHeightByMinMax(heightResult, intrinsicHeight);
2841         } else {
2842             // The only times we don't check min/max height are when a fixed length has
2843             // been given as an override.  Just use that.  The value has already been adjusted
2844             // for box-sizing.
2845             ASSERT(h.isFixed());
2846             heightResult = h.value() + borderAndPaddingLogicalHeight();
2847         }
2848
2849         computedValues.m_extent = heightResult;
2850
2851         if (hasPerpendicularContainingBlock) {
2852             bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb->style(), &style());
2853             computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), heightResult,
2854                     shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
2855                     shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
2856         }
2857     }
2858
2859     // WinIE quirk: The <html> block always fills the entire canvas in quirks mode.  The <body> always fills the
2860     // <html> block in quirks mode.  Only apply this quirk if the block is normal flow and no height
2861     // is specified. When we're printing, we also need this quirk if the body or root has a percentage 
2862     // height since we don't set a height in RenderView when we're printing. So without this quirk, the 
2863     // height has nothing to be a percentage of, and it ends up being 0. That is bad.
2864     bool paginatedContentNeedsBaseHeight = document().printing() && h.isPercentOrCalculated()
2865         && (isDocumentElementRenderer() || (isBody() && document().documentElement()->renderer()->style().logicalHeight().isPercentOrCalculated())) && !isInline();
2866     if (stretchesToViewport() || paginatedContentNeedsBaseHeight) {
2867         LayoutUnit margins = collapsedMarginBefore() + collapsedMarginAfter();
2868         LayoutUnit visibleHeight = view().pageOrViewLogicalHeight();
2869         if (isDocumentElementRenderer())
2870             computedValues.m_extent = std::max(computedValues.m_extent, visibleHeight - margins);
2871         else {
2872             LayoutUnit marginsBordersPadding = margins + parentBox()->marginBefore() + parentBox()->marginAfter() + parentBox()->borderAndPaddingLogicalHeight();
2873             computedValues.m_extent = std::max(computedValues.m_extent, visibleHeight - marginsBordersPadding);
2874         }
2875     }
2876 }
2877
2878 Optional<LayoutUnit> RenderBox::computeLogicalHeightUsing(SizeType heightType, const Length& height, Optional<LayoutUnit> intrinsicContentHeight) const
2879 {
2880     if (Optional<LayoutUnit> logicalHeight = computeContentAndScrollbarLogicalHeightUsing(heightType, height, intrinsicContentHeight))
2881         return adjustBorderBoxLogicalHeightForBoxSizing(logicalHeight.value());
2882     return Nullopt;
2883 }
2884
2885 Optional<LayoutUnit> RenderBox::computeContentLogicalHeight(SizeType heightType, const Length& height, Optional<LayoutUnit> intrinsicContentHeight) const
2886 {
2887     if (Optional<LayoutUnit> heightIncludingScrollbar = computeContentAndScrollbarLogicalHeightUsing(heightType, height, intrinsicContentHeight))
2888         return std::max<LayoutUnit>(0, adjustContentBoxLogicalHeightForBoxSizing(heightIncludingScrollbar) - scrollbarLogicalHeight());
2889     return Nullopt;
2890 }
2891
2892 Optional<LayoutUnit> RenderBox::computeIntrinsicLogicalContentHeightUsing(Length logicalHeightLength, Optional<LayoutUnit> intrinsicContentHeight, LayoutUnit borderAndPadding) const
2893 {
2894     // FIXME: The CSS sizing spec is considering changing what min-content/max-content should resolve to.
2895     // If that happens, this code will have to change.
2896     if (logicalHeightLength.isMinContent() || logicalHeightLength.isMaxContent() || logicalHeightLength.isFitContent())
2897         return intrinsicContentHeight;
2898     if (logicalHeightLength.isFillAvailable())
2899         return containingBlock()->availableLogicalHeight(ExcludeMarginBorderPadding) - borderAndPadding;
2900     ASSERT_NOT_REACHED();
2901     return LayoutUnit(0);
2902 }
2903
2904 Optional<LayoutUnit> RenderBox::computeContentAndScrollbarLogicalHeightUsing(SizeType heightType, const Length& height, Optional<LayoutUnit> intrinsicContentHeight) const
2905 {
2906     if (height.isAuto())
2907         return heightType == MinSize ? Optional<LayoutUnit>(0) : Nullopt;
2908     // FIXME: The CSS sizing spec is considering changing what min-content/max-content should resolve to.
2909     // If that happens, this code will have to change.
2910     if (height.isIntrinsic())
2911         return computeIntrinsicLogicalContentHeightUsing(height, intrinsicContentHeight, borderAndPaddingLogicalHeight());
2912     if (height.isFixed())
2913         return LayoutUnit(height.value());
2914     if (height.isPercentOrCalculated())
2915         return computePercentageLogicalHeight(height);
2916     return Nullopt;
2917 }
2918
2919 bool RenderBox::skipContainingBlockForPercentHeightCalculation(const RenderBox* containingBlock, bool isPerpendicularWritingMode) const
2920 {
2921     // Flow threads for multicol or paged overflow should be skipped. They are invisible to the DOM,
2922     // and percent heights of children should be resolved against the multicol or paged container.
2923     if (containingBlock->isInFlowRenderFlowThread() && !isPerpendicularWritingMode)
2924         return true;
2925
2926     // For quirks mode and anonymous blocks, we skip auto-height containingBlocks when computing percentages.
2927     // For standards mode, we treat the percentage as auto if it has an auto-height containing block.
2928     if (!document().inQuirksMode() && !containingBlock->isAnonymousBlock())
2929         return false;
2930     return !containingBlock->isTableCell() && !containingBlock->isOutOfFlowPositioned() && containingBlock->style().logicalHeight().isAuto() && isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode();
2931 }
2932
2933 static bool tableCellShouldHaveZeroInitialSize(const RenderBlock& block, bool scrollsOverflowY)
2934 {
2935     // Normally we would let the cell size intrinsically, but scrolling overflow has to be
2936     // treated differently, since WinIE lets scrolled overflow regions shrink as needed.
2937     // While we can't get all cases right, we can at least detect when the cell has a specified
2938     // height or when the table has a specified height. In these cases we want to initially have
2939     // no size and allow the flexing of the table or the cell to its specified height to cause us
2940     // to grow to fill the space. This could end up being wrong in some cases, but it is
2941     // preferable to the alternative (sizing intrinsically and making the row end up too big).
2942     const RenderTableCell& cell = downcast<RenderTableCell>(block);
2943     return scrollsOverflowY && (!cell.style().logicalHeight().isAuto() || !cell.table()->style().logicalHeight().isAuto());
2944 }
2945
2946 Optional<LayoutUnit> RenderBox::computePercentageLogicalHeight(const Length& height) const
2947 {
2948     Optional<LayoutUnit> availableHeight;
2949
2950     bool skippedAutoHeightContainingBlock = false;
2951     RenderBlock* cb = containingBlock();
2952     const RenderBox* containingBlockChild = this;
2953     LayoutUnit rootMarginBorderPaddingHeight = 0;
2954     bool isHorizontal = isHorizontalWritingMode();
2955     while (cb && !is<RenderView>(*cb) && skipContainingBlockForPercentHeightCalculation(cb, isHorizontal != cb->isHorizontalWritingMode())) {
2956         if (cb->isBody() || cb->isDocumentElementRenderer())
2957             rootMarginBorderPaddingHeight += cb->marginBefore() + cb->marginAfter() + cb->borderAndPaddingLogicalHeight();
2958         skippedAutoHeightContainingBlock = true;
2959         containingBlockChild = cb;
2960         cb = cb->containingBlock();
2961         cb->addPercentHeightDescendant(const_cast<RenderBox&>(*this));
2962     }
2963
2964     const RenderStyle& cbstyle = cb->style();
2965
2966     // A positioned element that specified both top/bottom or that specifies height should be treated as though it has a height
2967     // explicitly specified that can be used for any percentage computations.
2968     bool isOutOfFlowPositionedWithSpecifiedHeight = cb->isOutOfFlowPositioned() && (!cbstyle.logicalHeight().isAuto() || (!cbstyle.logicalTop().isAuto() && !cbstyle.logicalBottom().isAuto()));
2969
2970     bool includeBorderPadding = isTable();
2971
2972     if (isHorizontal != cb->isHorizontalWritingMode())
2973         availableHeight = containingBlockChild->containingBlockLogicalWidthForContent();
2974 #if ENABLE(CSS_GRID_LAYOUT)
2975     else if (hasOverrideContainingBlockLogicalHeight())
2976         availableHeight = overrideContainingBlockContentLogicalHeight();
2977 #endif
2978     else if (is<RenderTableCell>(*cb)) {
2979         if (!skippedAutoHeightContainingBlock) {
2980             // Table cells violate what the CSS spec says to do with heights. Basically we
2981             // don't care if the cell specified a height or not. We just always make ourselves
2982             // be a percentage of the cell's current content height.
2983             if (!cb->hasOverrideLogicalContentHeight())
2984                 return tableCellShouldHaveZeroInitialSize(*cb, scrollsOverflowY()) ? Optional<LayoutUnit>() : Nullopt;
2985
2986             availableHeight = cb->overrideLogicalContentHeight();
2987             includeBorderPadding = true;
2988         }
2989     } else if (cbstyle.logicalHeight().isFixed()) {
2990         LayoutUnit contentBoxHeight = cb->adjustContentBoxLogicalHeightForBoxSizing(LayoutUnit(cbstyle.logicalHeight().value()));
2991         availableHeight = std::max<LayoutUnit>(0, cb->constrainContentBoxLogicalHeightByMinMax(contentBoxHeight - cb->scrollbarLogicalHeight(), Nullopt));
2992     } else if (cbstyle.logicalHeight().isPercentOrCalculated() && !isOutOfFlowPositionedWithSpecifiedHeight) {
2993         // We need to recur and compute the percentage height for our containing block.
2994         if (Optional<LayoutUnit> heightWithScrollbar = cb->computePercentageLogicalHeight(cbstyle.logicalHeight())) {
2995             LayoutUnit contentBoxHeightWithScrollbar = cb->adjustContentBoxLogicalHeightForBoxSizing(heightWithScrollbar);
2996             // We need to adjust for min/max height because this method does not
2997             // handle the min/max of the current block, its caller does. So the
2998             // return value from the recursive call will not have been adjusted
2999             // yet.
3000             LayoutUnit contentBoxHeight = cb->constrainContentBoxLogicalHeightByMinMax(contentBoxHeightWithScrollbar - cb->scrollbarLogicalHeight(), Nullopt);
3001             availableHeight = std::max<LayoutUnit>(0, contentBoxHeight);
3002         }
3003     } else if (isOutOfFlowPositionedWithSpecifiedHeight) {
3004         // Don't allow this to affect the block' height() member variable, since this
3005         // can get called while the block is still laying out its kids.
3006         LogicalExtentComputedValues computedValues;
3007         cb->computeLogicalHeight(cb->logicalHeight(), 0, computedValues);
3008         availableHeight = computedValues.m_extent - cb->borderAndPaddingLogicalHeight() - cb->scrollbarLogicalHeight();
3009     } else if (cb->isRenderView())
3010         availableHeight = view().pageOrViewLogicalHeight();
3011
3012     if (!availableHeight)
3013         return availableHeight;
3014
3015     LayoutUnit result = valueForLength(height, availableHeight.value() - rootMarginBorderPaddingHeight);
3016     if (includeBorderPadding) {
3017         // FIXME: Table cells should default to box-sizing: border-box so we can avoid this hack.
3018         // It is necessary to use the border-box to match WinIE's broken
3019         // box model. This is essential for sizing inside
3020         // table cells using percentage heights.
3021         result -= borderAndPaddingLogicalHeight();
3022         return std::max<LayoutUnit>(0, result);
3023     }
3024     return result;
3025 }
3026
3027 LayoutUnit RenderBox::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const
3028 {
3029     return computeReplacedLogicalWidthRespectingMinMaxWidth(computeReplacedLogicalWidthUsing(MainOrPreferredSize, style().logicalWidth()), shouldComputePreferred);
3030 }
3031
3032 LayoutUnit RenderBox::computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit logicalWidth, ShouldComputePreferred shouldComputePreferred) const
3033 {
3034     LayoutUnit minLogicalWidth = (shouldComputePreferred == ComputePreferred && style().logicalMinWidth().isPercentOrCalculated()) || style().logicalMinWidth().isUndefined() ? logicalWidth : computeReplacedLogicalWidthUsing(MinSize, style().logicalMinWidth());
3035     LayoutUnit maxLogicalWidth = (shouldComputePreferred == ComputePreferred && style().logicalMaxWidth().isPercentOrCalculated()) || style().logicalMaxWidth().isUndefined() ? logicalWidth : computeReplacedLogicalWidthUsing(MaxSize, style().logicalMaxWidth());
3036     return std::max(minLogicalWidth, std::min(logicalWidth, maxLogicalWidth));
3037 }
3038
3039 LayoutUnit RenderBox::computeReplacedLogicalWidthUsing(SizeType widthType, Length logicalWidth) const
3040 {
3041     ASSERT(widthType == MinSize || widthType == MainOrPreferredSize || !logicalWidth.isAuto());
3042     if (widthType == MinSize && logicalWidth.isAuto())
3043         return adjustContentBoxLogicalWidthForBoxSizing(0);
3044
3045     switch (logicalWidth.type()) {
3046         case Fixed:
3047             return adjustContentBoxLogicalWidthForBoxSizing(logicalWidth.value());
3048         case MinContent:
3049         case MaxContent: {
3050             // MinContent/MaxContent don't need the availableLogicalWidth argument.
3051             LayoutUnit availableLogicalWidth = 0;
3052             return computeIntrinsicLogicalWidthUsing(logicalWidth, availableLogicalWidth, borderAndPaddingLogicalWidth()) - borderAndPaddingLogicalWidth();
3053         }
3054         case FitContent:
3055         case FillAvailable:
3056         case Percent: 
3057         case Calculated: {
3058             // FIXME: containingBlockLogicalWidthForContent() is wrong if the replaced element's block-flow is perpendicular to the
3059             // containing block's block-flow.
3060             // https://bugs.webkit.org/show_bug.cgi?id=46496
3061             const LayoutUnit cw = isOutOfFlowPositioned() ? containingBlockLogicalWidthForPositioned(downcast<RenderBoxModelObject>(container())) : containingBlockLogicalWidthForContent();
3062             Length containerLogicalWidth = containingBlock()->style().logicalWidth();
3063             // FIXME: Handle cases when containing block width is calculated or viewport percent.
3064             // https://bugs.webkit.org/show_bug.cgi?id=91071
3065             if (logicalWidth.isIntrinsic())
3066                 return computeIntrinsicLogicalWidthUsing(logicalWidth, cw, borderAndPaddingLogicalWidth()) - borderAndPaddingLogicalWidth();
3067             if (cw > 0 || (!cw && (containerLogicalWidth.isFixed() || containerLogicalWidth.isPercentOrCalculated())))
3068                 return adjustContentBoxLogicalWidthForBoxSizing(minimumValueForLength(logicalWidth, cw));
3069         }
3070         FALLTHROUGH;
3071         case Intrinsic:
3072         case MinIntrinsic:
3073         case Auto:
3074         case Relative:
3075         case Undefined:
3076             return intrinsicLogicalWidth();
3077     }
3078
3079     ASSERT_NOT_REACHED();
3080     return 0;
3081 }
3082
3083 LayoutUnit RenderBox::computeReplacedLogicalHeight() const
3084 {
3085     return computeReplacedLogicalHeightRespectingMinMaxHeight(computeReplacedLogicalHeightUsing(MainOrPreferredSize, style().logicalHeight()));
3086 }
3087
3088 LayoutUnit RenderBox::computeReplacedLogicalHeightRespectingMinMaxHeight(LayoutUnit logicalHeight) const
3089 {
3090     LayoutUnit minLogicalHeight = computeReplacedLogicalHeightUsing(MinSize, style().logicalMinHeight());
3091     LayoutUnit maxLogicalHeight = style().logicalMaxHeight().isUndefined() ? logicalHeight : computeReplacedLogicalHeightUsing(MaxSize, style().logicalMaxHeight());
3092     return std::max(minLogicalHeight, std::min(logicalHeight, maxLogicalHeight));
3093 }
3094
3095 LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(SizeType heightType, Length logicalHeight) const
3096 {
3097     ASSERT(heightType == MinSize || heightType == MainOrPreferredSize || !logicalHeight.isAuto());
3098     if (heightType == MinSize && logicalHeight.isAuto())
3099         return adjustContentBoxLogicalHeightForBoxSizing(Optional<LayoutUnit>(0));
3100
3101     switch (logicalHeight.type()) {
3102         case Fixed:
3103             return adjustContentBoxLogicalHeightForBoxSizing(LayoutUnit(logicalHeight.value()));
3104         case Percent:
3105         case Calculated:
3106         {
3107             auto cb = isOutOfFlowPositioned() ? container() : containingBlock();
3108             while (cb && cb->isAnonymous() && !is<RenderView>(*cb)) {
3109                 cb = cb->containingBlock();
3110                 downcast<RenderBlock>(*cb).addPercentHeightDescendant(const_cast<RenderBox&>(*this));
3111             }
3112
3113             // FIXME: This calculation is not patched for block-flow yet.
3114             // https://bugs.webkit.org/show_bug.cgi?id=46500
3115             if (cb->isOutOfFlowPositioned() && cb->style().height().isAuto() && !(cb->style().top().isAuto() || cb->style().bottom().isAuto())) {
3116                 ASSERT_WITH_SECURITY_IMPLICATION(cb->isRenderBlock());
3117                 RenderBlock& block = downcast<RenderBlock>(*cb);
3118                 LogicalExtentComputedValues computedValues;
3119                 block.computeLogicalHeight(block.logicalHeight(), 0, computedValues);
3120                 LayoutUnit newContentHeight = computedValues.m_extent - block.borderAndPaddingLogicalHeight() - block.scrollbarLogicalHeight();
3121                 LayoutUnit newHeight = block.adjustContentBoxLogicalHeightForBoxSizing(newContentHeight);
3122                 return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeight, newHeight));
3123             }
3124             
3125             // FIXME: availableLogicalHeight() is wrong if the replaced element's block-flow is perpendicular to the
3126             // containing block's block-flow.
3127             // https://bugs.webkit.org/show_bug.cgi?id=46496
3128             LayoutUnit availableHeight;
3129             if (isOutOfFlowPositioned())
3130                 availableHeight = containingBlockLogicalHeightForPositioned(downcast<RenderBoxModelObject>(cb));
3131             else {
3132                 availableHeight = containingBlockLogicalHeightForContent(IncludeMarginBorderPadding);
3133                 // It is necessary to use the border-box to match WinIE's broken
3134                 // box model.  This is essential for sizing inside
3135                 // table cells using percentage heights.
3136                 // FIXME: This needs to be made block-flow-aware.  If the cell and image are perpendicular block-flows, this isn't right.
3137                 // https://bugs.webkit.org/show_bug.cgi?id=46997
3138                 while (cb && !is<RenderView>(*cb) && (cb->style().logicalHeight().isAuto() || cb->style().logicalHeight().isPercentOrCalculated())) {
3139                     if (cb->isTableCell()) {
3140                         // Don't let table cells squeeze percent-height replaced elements
3141                         // <http://bugs.webkit.org/show_bug.cgi?id=15359>
3142                         availableHeight = std::max(availableHeight, intrinsicLogicalHeight());
3143                         return valueForLength(logicalHeight, availableHeight - borderAndPaddingLogicalHeight());
3144                     }
3145                     downcast<RenderBlock>(*cb).addPercentHeightDescendant(const_cast<RenderBox&>(*this));
3146                     cb = cb->containingBlock();
3147                 }
3148             }
3149             return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeight, availableHeight));
3150         }
3151         case MinContent:
3152         case MaxContent:
3153         case FitContent:
3154         case FillAvailable:
3155             return adjustContentBoxLogicalHeightForBoxSizing(computeIntrinsicLogicalContentHeightUsing(logicalHeight, intrinsicLogicalHeight(), borderAndPaddingLogicalHeight()));
3156         default:
3157             return intrinsicLogicalHeight();
3158     }
3159 }
3160
3161 LayoutUnit RenderBox::availableLogicalHeight(AvailableLogicalHeightType heightType) const
3162 {
3163     return constrainLogicalHeightByMinMax(availableLogicalHeightUsing(style().logicalHeight(), heightType), Nullopt);
3164 }
3165
3166 LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h, AvailableLogicalHeightType heightType) const
3167 {
3168     // We need to stop here, since we don't want to increase the height of the table
3169     // artificially.  We're going to rely on this cell getting expanded to some new
3170     // height, and then when we lay out again we'll use the calculation below.
3171     if (isTableCell() && (h.isAuto() || h.isPercentOrCalculated())) {
3172         if (hasOverrideLogicalContentHeight())
3173             return overrideLogicalContentHeight();
3174         return logicalHeight() - borderAndPaddingLogicalHeight();
3175     }
3176
3177     if (h.isPercentOrCalculated() && isOutOfFlowPositioned() && !isRenderFlowThread()) {
3178         // FIXME: This is wrong if the containingBlock has a perpendicular writing mode.
3179         LayoutUnit availableHeight = containingBlockLogicalHeightForPositioned(containingBlock());
3180         return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(h, availableHeight));
3181     }
3182
3183     if (Optional<LayoutUnit> heightIncludingScrollbar = computeContentAndScrollbarLogicalHeightUsing(MainOrPreferredSize, h, Nullopt))
3184         return std::max<LayoutUnit>(0, adjustContentBoxLogicalHeightForBoxSizing(heightIncludingScrollbar) - scrollbarLogicalHeight());
3185
3186     // FIXME: Check logicalTop/logicalBottom here to correctly handle vertical writing-mode.
3187     // https://bugs.webkit.org/show_bug.cgi?id=46500
3188     if (is<RenderBlock>(*this) && isOutOfFlowPositioned() && style().height().isAuto() && !(style().top().isAuto() || style().bottom().isAuto())) {
3189         RenderBlock& block = const_cast<RenderBlock&>(downcast<RenderBlock>(*this));
3190         LogicalExtentComputedValues computedValues;
3191         block.computeLogicalHeight(block.logicalHeight(), 0, computedValues);
3192         LayoutUnit newContentHeight = computedValues.m_extent - block.borderAndPaddingLogicalHeight() - block.scrollbarLogicalHeight();
3193         return adjustContentBoxLogicalHeightForBoxSizing(newContentHeight);
3194     }
3195
3196     // FIXME: This is wrong if the containingBlock has a perpendicular writing mode.
3197     LayoutUnit availableHeight = containingBlockLogicalHeightForContent(heightType);
3198     if (heightType == ExcludeMarginBorderPadding) {
3199         // FIXME: Margin collapsing hasn't happened yet, so this incorrectly removes collapsed margins.
3200         availableHeight -= marginBefore() + marginAfter() + borderAndPaddingLogicalHeight();
3201     }
3202     return availableHeight;
3203 }
3204
3205 void RenderBox::computeBlockDirectionMargins(const RenderBlock* containingBlock, LayoutUnit& marginBefore, LayoutUnit& marginAfter) const
3206 {
3207     if (isTableCell()) {
3208         // FIXME: Not right if we allow cells to have different directionality than the table.  If we do allow this, though,
3209         // we may just do it with an extra anonymous block inside the cell.
3210         marginBefore = 0;
3211         marginAfter = 0;
3212         return;
3213     }
3214
3215     // Margins are calculated with respect to the logical width of
3216     // the containing block (8.3)
3217     LayoutUnit cw = containingBlockLogicalWidthForContent();
3218     const RenderStyle& containingBlockStyle = containingBlock->style();
3219     marginBefore = minimumValueForLength(style().marginBeforeUsing(&containingBlockStyle), cw);
3220     marginAfter = minimumValueForLength(style().marginAfterUsing(&containingBlockStyle), cw);
3221 }
3222
3223 void RenderBox::computeAndSetBlockDirectionMargins(const RenderBlock* containingBlock)
3224 {
3225     LayoutUnit marginBefore;
3226     LayoutUnit marginAfter;
3227     computeBlockDirectionMargins(containingBlock, marginBefore, marginAfter);
3228     containingBlock->setMarginBeforeForChild(*this, marginBefore);
3229     containingBlock->setMarginAfterForChild(*this, marginAfter);
3230 }
3231
3232 LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* region, bool checkForPerpendicularWritingMode) const
3233 {
3234     if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
3235         return containingBlockLogicalHeightForPositioned(containingBlock, false);
3236
3237 #if ENABLE(CSS_GRID_LAYOUT)
3238     if (hasOverrideContainingBlockLogicalWidth()) {
3239         if (auto overrideLogicalWidth = overrideContainingBlockContentLogicalWidth())
3240             return overrideLogicalWidth.value();
3241     }
3242 #endif
3243
3244     if (is<RenderBox>(*containingBlock)) {
3245         bool isFixedPosition = style().position() == FixedPosition;
3246
3247         RenderFlowThread* flowThread = flowThreadContainingBlock();
3248         if (!flowThread) {
3249             if (isFixedPosition && is<RenderView>(*containingBlock))
3250                 return downcast<RenderView>(*containingBlock).clientLogicalWidthForFixedPosition();
3251
3252             return downcast<RenderBox>(*containingBlock).clientLogicalWidth();
3253         }
3254
3255         if (isFixedPosition && is<RenderNamedFlowThread>(*containingBlock))
3256             return containingBlock->view().clientLogicalWidth();
3257
3258         if (!is<RenderBlock>(*containingBlock))
3259             return downcast<RenderBox>(*containingBlock).clientLogicalWidth();
3260
3261         const RenderBlock& cb = downcast<RenderBlock>(*containingBlock);
3262         RenderBoxRegionInfo* boxInfo = nullptr;
3263         if (!region) {
3264             if (is<RenderFlowThread>(*containingBlock) && !checkForPerpendicularWritingMode)
3265                 return downcast<RenderFlowThread>(*containingBlock).contentLogicalWidthOfFirstRegion();
3266             if (isWritingModeRoot()) {
3267                 LayoutUnit cbPageOffset = cb.offsetFromLogicalTopOfFirstPage();
3268                 RenderRegion* cbRegion = cb.regionAtBlockOffset(cbPageOffset);
3269                 if (cbRegion)
3270                     boxInfo = cb.renderBoxRegionInfo(cbRegion);
3271             }
3272         } else if (flowThread->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode()) {
3273             RenderRegion* containingBlockRegion = cb.clampToStartAndEndRegions(region);
3274             boxInfo = cb.renderBoxRegionInfo(containingBlockRegion);
3275         }
3276         return (boxInfo) ? std::max<LayoutUnit>(0, cb.clientLogicalWidth() - (cb.logicalWidth() - boxInfo->logicalWidth())) : cb.clientLogicalWidth();
3277     }
3278
3279     ASSERT(containingBlock->isInFlowPositioned());
3280
3281     const auto& flow = downcast<RenderInline>(*containingBlock);
3282     InlineFlowBox* first = flow.firstLineBox();
3283     InlineFlowBox* last = flow.lastLineBox();
3284
3285     // If the containing block is empty, return a width of 0.
3286     if (!first || !last)
3287         return 0;
3288
3289     LayoutUnit fromLeft;
3290     LayoutUnit fromRight;
3291     if (containingBlock->style().isLeftToRightDirection()) {
3292         fromLeft = first->logicalLeft() + first->borderLogicalLeft();
3293         fromRight = last->logicalLeft() + last->logicalWidth() - last->borderLogicalRight();
3294     } else {
3295         fromRight = first->logicalLeft() + first->logicalWidth() - first->borderLogicalRight();
3296         fromLeft = last->logicalLeft() + last->borderLogicalLeft();
3297     }
3298
3299     return std::max<LayoutUnit>(0, fromRight - fromLeft);
3300 }
3301
3302 LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode) const
3303 {
3304     if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
3305         return containingBlockLogicalWidthForPositioned(containingBlock, nullptr, false);
3306
3307 #if ENABLE(CSS_GRID_LAYOUT)
3308     if (hasOverrideContainingBlockLogicalHeight()) {
3309         if (auto overrideLogicalHeight = overrideContainingBlockContentLogicalHeight())
3310             return overrideLogicalHeight.value();
3311     }
3312 #endif
3313
3314     if (containingBlock->isBox()) {
3315         bool isFixedPosition = style().position() == FixedPosition;
3316
3317         if (isFixedPosition && is<RenderView>(*containingBlock))
3318             return downcast<RenderView>(*containingBlock).clientLogicalHeightForFixedPosition();
3319
3320         const RenderBlock* cb = is<RenderBlock>(*containingBlock) ? downcast<RenderBlock>(containingBlock) : containingBlock->containingBlock();
3321         LayoutUnit result = cb->clientLogicalHeight();
3322         RenderFlowThread* flowThread = flowThreadContainingBlock();
3323         if (flowThread && is<RenderFlowThread>(*containingBlock) && flowThread->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode()) {
3324             if (is<RenderNamedFlowThread>(*containingBlock) && isFixedPosition)
3325                 return containingBlock->view().clientLogicalHeight();
3326             return downcast<RenderFlowThread>(*containingBlock).contentLogicalHeightOfFirstRegion();
3327         }
3328         return result;
3329     }
3330         
3331     ASSERT(containingBlock->isInFlowPositioned());
3332
3333     const auto& flow = downcast<RenderInline>(*containingBlock);
3334     InlineFlowBox* first = flow.firstLineBox();
3335     InlineFlowBox* last = flow.lastLineBox();
3336
3337     // If the containing block is empty, return a height of 0.
3338     if (!first || !last)