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