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