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