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