multiline column flexbox with auto height wrap too much
[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 "HTMLNames.h"
38 #include "ImageBuffer.h"
39 #include "FloatQuad.h"
40 #include "Frame.h"
41 #include "Page.h"
42 #include "PaintInfo.h"
43 #include "RenderArena.h"
44 #include "RenderBoxRegionInfo.h"
45 #include "RenderFlexibleBox.h"
46 #include "RenderFlowThread.h"
47 #include "RenderInline.h"
48 #include "RenderLayer.h"
49 #include "RenderPart.h"
50 #include "RenderRegion.h"
51 #include "RenderTableCell.h"
52 #include "RenderTheme.h"
53 #include "RenderView.h"
54 #include "ScrollbarTheme.h"
55 #include "TransformState.h"
56 #include <algorithm>
57 #include <math.h>
58
59 using namespace std;
60
61 namespace WebCore {
62
63 using namespace HTMLNames;
64
65 // Used by flexible boxes when flexing this element and by table cells.
66 typedef WTF::HashMap<const RenderBox*, LayoutUnit> OverrideSizeMap;
67 static OverrideSizeMap* gOverrideHeightMap = 0;
68 static OverrideSizeMap* gOverrideWidthMap = 0;
69
70 bool RenderBox::s_hadOverflowClip = false;
71
72 RenderBox::RenderBox(Node* node)
73     : RenderBoxModelObject(node)
74     , m_marginLeft(0)
75     , m_marginRight(0)
76     , m_marginTop(0)
77     , m_marginBottom(0)
78     , m_minPreferredLogicalWidth(-1)
79     , m_maxPreferredLogicalWidth(-1)
80     , m_inlineBoxWrapper(0)
81 {
82     setIsBox();
83 }
84
85 RenderBox::~RenderBox()
86 {
87 }
88
89 LayoutUnit RenderBox::marginBefore() const
90 {
91     switch (style()->writingMode()) {
92     case TopToBottomWritingMode:
93         return m_marginTop;
94     case BottomToTopWritingMode:
95         return m_marginBottom;
96     case LeftToRightWritingMode:
97         return m_marginLeft;
98     case RightToLeftWritingMode:
99         return m_marginRight;
100     }
101     ASSERT_NOT_REACHED();
102     return m_marginTop;
103 }
104
105 LayoutUnit RenderBox::marginAfter() const
106 {
107     switch (style()->writingMode()) {
108     case TopToBottomWritingMode:
109         return m_marginBottom;
110     case BottomToTopWritingMode:
111         return m_marginTop;
112     case LeftToRightWritingMode:
113         return m_marginRight;
114     case RightToLeftWritingMode:
115         return m_marginLeft;
116     }
117     ASSERT_NOT_REACHED();
118     return m_marginBottom;
119 }
120
121 LayoutUnit RenderBox::marginStart() const
122 {
123     if (isHorizontalWritingMode())
124         return style()->isLeftToRightDirection() ? m_marginLeft : m_marginRight;
125     return style()->isLeftToRightDirection() ? m_marginTop : m_marginBottom;
126 }
127
128 LayoutUnit RenderBox::marginEnd() const
129 {
130     if (isHorizontalWritingMode())
131         return style()->isLeftToRightDirection() ? m_marginRight : m_marginLeft;
132     return style()->isLeftToRightDirection() ? m_marginBottom : m_marginTop;
133 }
134
135 void RenderBox::setMarginStart(LayoutUnit margin)
136 {
137     if (isHorizontalWritingMode()) {
138         if (style()->isLeftToRightDirection())
139             m_marginLeft = margin;
140         else
141             m_marginRight = margin;
142     } else {
143         if (style()->isLeftToRightDirection())
144             m_marginTop = margin;
145         else
146             m_marginBottom = margin;
147     }
148 }
149
150 void RenderBox::setMarginEnd(LayoutUnit margin)
151 {
152     if (isHorizontalWritingMode()) {
153         if (style()->isLeftToRightDirection())
154             m_marginRight = margin;
155         else
156             m_marginLeft = margin;
157     } else {
158         if (style()->isLeftToRightDirection())
159             m_marginBottom = margin;
160         else
161             m_marginTop = margin;
162     }
163 }
164
165 void RenderBox::setMarginBefore(LayoutUnit margin)
166 {
167     switch (style()->writingMode()) {
168     case TopToBottomWritingMode:
169         m_marginTop = margin;
170         break;
171     case BottomToTopWritingMode:
172         m_marginBottom = margin;
173         break;
174     case LeftToRightWritingMode:
175         m_marginLeft = margin;
176         break;
177     case RightToLeftWritingMode:
178         m_marginRight = margin;
179         break;
180     }
181 }
182
183 void RenderBox::setMarginAfter(LayoutUnit margin)
184 {
185     switch (style()->writingMode()) {
186     case TopToBottomWritingMode:
187         m_marginBottom = margin;
188         break;
189     case BottomToTopWritingMode:
190         m_marginTop = margin;
191         break;
192     case LeftToRightWritingMode:
193         m_marginRight = margin;
194         break;
195     case RightToLeftWritingMode:
196         m_marginLeft = margin;
197         break;
198     }
199 }
200
201 LayoutRect RenderBox::borderBoxRectInRegion(RenderRegion* region, LayoutUnit offsetFromTopOfFirstPage, RenderBoxRegionInfoFlags cacheFlag) const
202 {
203     if (!region)
204         return borderBoxRect();
205     
206     // Compute the logical width and placement in this region.
207     RenderBoxRegionInfo* boxInfo = renderBoxRegionInfo(region, offsetFromTopOfFirstPage, cacheFlag);
208     if (!boxInfo)
209         return borderBoxRect();
210
211     // We have cached insets.
212     LayoutUnit logicalWidth = boxInfo->logicalWidth();
213     LayoutUnit logicalLeft = boxInfo->logicalLeft();
214         
215     // Now apply the parent inset since it is cumulative whenever anything in the containing block chain shifts.
216     // FIXME: Doesn't work right with perpendicular writing modes.
217     const RenderBlock* currentBox = containingBlock();
218     offsetFromTopOfFirstPage -= logicalTop();
219     RenderBoxRegionInfo* currentBoxInfo = currentBox->renderBoxRegionInfo(region, offsetFromTopOfFirstPage);
220     while (currentBoxInfo && currentBoxInfo->isShifted()) {
221         if (currentBox->style()->direction() == LTR)
222             logicalLeft += currentBoxInfo->logicalLeft();
223         else
224             logicalLeft -= (currentBox->logicalWidth() - currentBoxInfo->logicalWidth()) - currentBoxInfo->logicalLeft();
225         offsetFromTopOfFirstPage -= logicalTop();
226         currentBox = currentBox->containingBlock();
227         region = currentBox->clampToStartAndEndRegions(region);
228         currentBoxInfo = currentBox->renderBoxRegionInfo(region, offsetFromTopOfFirstPage);
229     }
230     
231     if (cacheFlag == DoNotCacheRenderBoxRegionInfo)
232         delete boxInfo;
233
234     if (isHorizontalWritingMode())
235         return LayoutRect(logicalLeft, 0, logicalWidth, height());
236     return LayoutRect(0, logicalLeft, width(), logicalWidth);
237 }
238
239 void RenderBox::clearRenderBoxRegionInfo()
240 {
241     if (!inRenderFlowThread() || isRenderFlowThread())
242         return;
243
244     RenderFlowThread* flowThread = enclosingRenderFlowThread();
245     flowThread->removeRenderBoxRegionInfo(this);
246 }
247
248 void RenderBox::willBeDestroyed()
249 {
250     clearOverrideSize();
251
252     RenderStyle* styleToUse = style();
253     if (styleToUse && (styleToUse->logicalHeight().isPercent() || styleToUse->logicalMinHeight().isPercent() || styleToUse->logicalMaxHeight().isPercent()))
254         RenderBlock::removePercentHeightDescendant(this);
255
256     // If this renderer is owning renderer for the frameview's custom scrollbars,
257     // we need to clear it from the scrollbar. See webkit bug 64737.
258     if (styleToUse && styleToUse->hasPseudoStyle(SCROLLBAR) && frame() && frame()->view())
259         frame()->view()->clearOwningRendererForCustomScrollbars(this);
260
261     // If the following assertion fails, logicalHeight()/logicalMinHeight()/
262     // logicalMaxHeight() values are changed from a percent value to a non-percent
263     // value during laying out. It causes a use-after-free bug.
264     ASSERT(!RenderBlock::hasPercentHeightDescendant(this));
265
266     if (hasOverflowClip() && everHadLayout() && !hasLayer())
267         clearCachedSizeForOverflowClip();
268
269     RenderBoxModelObject::willBeDestroyed();
270 }
271
272 void RenderBox::removeFloatingOrPositionedChildFromBlockLists()
273 {
274     ASSERT(isFloatingOrPositioned());
275
276     if (documentBeingDestroyed())
277         return;
278
279     if (isFloating()) {
280         RenderBlock* parentBlock = 0;
281         for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) {
282             if (curr->isRenderBlock()) {
283                 RenderBlock* currBlock = toRenderBlock(curr);
284                 if (!parentBlock || currBlock->containsFloat(this))
285                     parentBlock = currBlock;
286             }
287         }
288
289         if (parentBlock) {
290             RenderObject* parent = parentBlock->parent();
291             if (parent && parent->isFlexibleBoxIncludingDeprecated())
292                 parentBlock = toRenderBlock(parent);
293
294             parentBlock->markSiblingsWithFloatsForLayout(this);
295             parentBlock->markAllDescendantsWithFloatsForLayout(this, false);
296         }
297     }
298
299     if (isPositioned()) {
300         for (RenderObject* curr = parent(); curr; curr = curr->parent()) {
301             if (curr->isRenderBlock())
302                 toRenderBlock(curr)->removePositionedObject(this);
303         }
304     }
305 }
306
307 void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
308 {
309     s_hadOverflowClip = hasOverflowClip();
310
311     RenderStyle* oldStyle = style();
312     if (oldStyle) {
313         // The background of the root element or the body element could propagate up to
314         // the canvas.  Just dirty the entire canvas when our style changes substantially.
315         if (diff >= StyleDifferenceRepaint && node() &&
316                 (node()->hasTagName(htmlTag) || node()->hasTagName(bodyTag)))
317             view()->repaint();
318         
319         // When a layout hint happens and an object's position style changes, we have to do a layout
320         // to dirty the render tree using the old position value now.
321         if (diff == StyleDifferenceLayout && parent() && oldStyle->position() != newStyle->position()) {
322             markContainingBlocksForLayout();
323             if (oldStyle->position() == StaticPosition)
324                 repaint();
325             else if (newStyle->isPositioned())
326                 parent()->setChildNeedsLayout(true);
327             if (isFloating() && !isPositioned() && newStyle->isPositioned())
328                 removeFloatingOrPositionedChildFromBlockLists();
329         }
330     } else if (newStyle && isBody())
331         view()->repaint();
332
333     if (FrameView *frameView = view()->frameView()) {
334         bool newStyleIsFixed = newStyle && newStyle->position() == FixedPosition;
335         bool oldStyleIsFixed = oldStyle && oldStyle->position() == FixedPosition;
336         if (newStyleIsFixed != oldStyleIsFixed) {
337             if (newStyleIsFixed)
338                 frameView->addFixedObject();
339             else
340                 frameView->removeFixedObject();
341         }
342     }
343
344     RenderBoxModelObject::styleWillChange(diff, newStyle);
345 }
346
347 void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
348 {
349     RenderBoxModelObject::styleDidChange(diff, oldStyle);
350
351     RenderStyle* newStyle = style();
352     if (needsLayout() && oldStyle) {
353         if (oldStyle && (oldStyle->logicalHeight().isPercent() || oldStyle->logicalMinHeight().isPercent() || oldStyle->logicalMaxHeight().isPercent()))
354             RenderBlock::removePercentHeightDescendant(this);
355
356         // Normally we can do optimized positioning layout for absolute/fixed positioned objects. There is one special case, however, which is
357         // 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
358         // to determine the new static position.
359         if (isPositioned() && newStyle->hasStaticBlockPosition(isHorizontalWritingMode()) && oldStyle->marginBefore() != newStyle->marginBefore()
360             && parent() && !parent()->normalChildNeedsLayout())
361             parent()->setChildNeedsLayout(true);
362     }
363
364     // If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the
365     // new zoomed coordinate space.
366     if (hasOverflowClipWithLayer() && oldStyle && newStyle && oldStyle->effectiveZoom() != newStyle->effectiveZoom()) {
367         if (int left = layer()->scrollXOffset()) {
368             left = (left / oldStyle->effectiveZoom()) * newStyle->effectiveZoom();
369             layer()->scrollToXOffset(left);
370         }
371         if (int top = layer()->scrollYOffset()) {
372             top = (top / oldStyle->effectiveZoom()) * newStyle->effectiveZoom();
373             layer()->scrollToYOffset(top);
374         }
375     }
376
377     bool isBodyRenderer = isBody();
378     bool isRootRenderer = isRoot();
379
380     // Set the text color if we're the body.
381     if (isBodyRenderer)
382         document()->setTextColor(newStyle->visitedDependentColor(CSSPropertyColor));
383
384     if (isRootRenderer || isBodyRenderer) {
385         // Propagate the new writing mode and direction up to the RenderView.
386         RenderView* viewRenderer = view();
387         RenderStyle* viewStyle = viewRenderer->style();
388         if (viewStyle->direction() != newStyle->direction() && (isRootRenderer || !document()->directionSetOnDocumentElement())) {
389             viewStyle->setDirection(newStyle->direction());
390             if (isBodyRenderer)
391                 document()->documentElement()->renderer()->style()->setDirection(newStyle->direction());
392             setNeedsLayoutAndPrefWidthsRecalc();
393         }
394
395         if (viewStyle->writingMode() != newStyle->writingMode() && (isRootRenderer || !document()->writingModeSetOnDocumentElement())) {
396             viewStyle->setWritingMode(newStyle->writingMode());
397             viewRenderer->setHorizontalWritingMode(newStyle->isHorizontalWritingMode());
398             if (isBodyRenderer) {
399                 document()->documentElement()->renderer()->style()->setWritingMode(newStyle->writingMode());
400                 document()->documentElement()->renderer()->setHorizontalWritingMode(newStyle->isHorizontalWritingMode());
401             }
402             setNeedsLayoutAndPrefWidthsRecalc();
403         }
404
405         frame()->view()->recalculateScrollbarOverlayStyle();
406     }
407 }
408
409 void RenderBox::updateBoxModelInfoFromStyle()
410 {
411     RenderBoxModelObject::updateBoxModelInfoFromStyle();
412
413     RenderStyle* styleToUse = style();
414     bool isRootObject = isRoot();
415     bool isViewObject = isRenderView();
416
417     // The root and the RenderView always paint their backgrounds/borders.
418     if (isRootObject || isViewObject)
419         setHasBoxDecorations(true);
420
421     setPositioned(styleToUse->isPositioned());
422     setFloating(styleToUse->isFloating() && (!isPositioned() || styleToUse->floating() == PositionedFloat));
423
424     // We also handle <body> and <html>, whose overflow applies to the viewport.
425     if (styleToUse->overflowX() != OVISIBLE && !isRootObject && (isRenderBlock() || isTableRow() || isTableSection())) {
426         bool boxHasOverflowClip = true;
427         if (isBody()) {
428             // Overflow on the body can propagate to the viewport under the following conditions.
429             // (1) The root element is <html>.
430             // (2) We are the primary <body> (can be checked by looking at document.body).
431             // (3) The root element has visible overflow.
432             if (document()->documentElement()->hasTagName(htmlTag) &&
433                 document()->body() == node() &&
434                 document()->documentElement()->renderer()->style()->overflowX() == OVISIBLE)
435                 boxHasOverflowClip = false;
436         }
437         
438         // Check for overflow clip.
439         // It's sufficient to just check one direction, since it's illegal to have visible on only one overflow value.
440         if (boxHasOverflowClip) {
441             if (!s_hadOverflowClip)
442                 // Erase the overflow
443                 repaint();
444             setHasOverflowClip();
445         }
446     }
447
448     setHasTransform(styleToUse->hasTransformRelatedProperty());
449     setHasReflection(styleToUse->boxReflect());
450 }
451
452 void RenderBox::layout()
453 {
454     ASSERT(needsLayout());
455
456     RenderObject* child = firstChild();
457     if (!child) {
458         setNeedsLayout(false);
459         return;
460     }
461
462     LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
463     while (child) {
464         child->layoutIfNeeded();
465         ASSERT(!child->needsLayout());
466         child = child->nextSibling();
467     }
468     statePusher.pop();
469
470     if (hasOverflowClip() && !hasLayer())
471         updateCachedSizeForOverflowClip();
472
473     setNeedsLayout(false);
474 }
475
476 // More IE extensions.  clientWidth and clientHeight represent the interior of an object
477 // excluding border and scrollbar.
478 LayoutUnit RenderBox::clientWidth() const
479 {
480     return width() - borderLeft() - borderRight() - verticalScrollbarWidth();
481 }
482
483 LayoutUnit RenderBox::clientHeight() const
484 {
485     return height() - borderTop() - borderBottom() - horizontalScrollbarHeight();
486 }
487
488 int RenderBox::pixelSnappedClientWidth() const
489 {
490     return snapSizeToPixel(clientWidth(), clientLeft());
491 }
492
493 int RenderBox::pixelSnappedClientHeight() const
494 {
495     return snapSizeToPixel(clientHeight(), clientTop());
496 }
497
498 int RenderBox::scrollWidth() const
499 {
500     if (hasOverflowClipWithLayer())
501         return layer()->scrollWidth();
502     // For objects with visible overflow, this matches IE.
503     // FIXME: Need to work right with writing modes.
504     if (style()->isLeftToRightDirection())
505         return max(clientWidth(), maxXLayoutOverflow() - borderLeft());
506     return clientWidth() - min(0, minXLayoutOverflow() - borderLeft());
507 }
508
509 int RenderBox::scrollHeight() const
510 {
511     if (hasOverflowClipWithLayer())
512         return layer()->scrollHeight();
513     // For objects with visible overflow, this matches IE.
514     // FIXME: Need to work right with writing modes.
515     return max(pixelSnappedClientHeight(), maxYLayoutOverflow() - borderTop());
516 }
517
518 int RenderBox::scrollLeft() const
519 {
520     return hasOverflowClipWithLayer() ? layer()->scrollXOffset() : 0;
521 }
522
523 int RenderBox::scrollTop() const
524 {
525     return hasOverflowClipWithLayer() ? layer()->scrollYOffset() : 0;
526 }
527
528 void RenderBox::setScrollLeft(int newLeft)
529 {
530     if (hasOverflowClipWithLayer())
531         layer()->scrollToXOffset(newLeft, RenderLayer::ScrollOffsetClamped);
532 }
533
534 void RenderBox::setScrollTop(int newTop)
535 {
536     if (hasOverflowClipWithLayer())
537         layer()->scrollToYOffset(newTop, RenderLayer::ScrollOffsetClamped);
538 }
539
540 void RenderBox::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
541 {
542     rects.append(pixelSnappedIntRect(accumulatedOffset, size()));
543 }
544
545 void RenderBox::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
546 {
547     quads.append(localToAbsoluteQuad(FloatRect(0, 0, width(), height()), false, wasFixed));
548 }
549
550 void RenderBox::updateLayerTransform()
551 {
552     // Transform-origin depends on box size, so we need to update the layer transform after layout.
553     if (hasLayer())
554         layer()->updateTransform();
555 }
556
557 LayoutRect RenderBox::absoluteContentBox() const
558 {
559     LayoutRect rect = contentBoxRect();
560     FloatPoint absPos = localToAbsolute(FloatPoint());
561     rect.move(absPos.x(), absPos.y());
562     return rect;
563 }
564
565 FloatQuad RenderBox::absoluteContentQuad() const
566 {
567     LayoutRect rect = contentBoxRect();
568     return localToAbsoluteQuad(FloatRect(rect));
569 }
570
571 LayoutRect RenderBox::outlineBoundsForRepaint(RenderBoxModelObject* repaintContainer, LayoutPoint* cachedOffsetToRepaintContainer) const
572 {
573     LayoutRect box = borderBoundingBox();
574     adjustRectForOutlineAndShadow(box);
575
576     FloatQuad containerRelativeQuad = FloatRect(box);
577     if (cachedOffsetToRepaintContainer)
578         containerRelativeQuad.move(cachedOffsetToRepaintContainer->x(), cachedOffsetToRepaintContainer->y());
579     else
580         containerRelativeQuad = localToContainerQuad(containerRelativeQuad, repaintContainer);
581
582     box = containerRelativeQuad.enclosingBoundingBox();
583
584     // FIXME: layoutDelta needs to be applied in parts before/after transforms and
585     // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
586     box.move(view()->layoutDelta());
587
588     return box;
589 }
590
591 void RenderBox::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset)
592 {
593     if (!size().isEmpty())
594         rects.append(pixelSnappedIntRect(additionalOffset, size()));
595 }
596
597 LayoutRect RenderBox::reflectionBox() const
598 {
599     LayoutRect result;
600     if (!style()->boxReflect())
601         return result;
602     LayoutRect box = borderBoxRect();
603     result = box;
604     switch (style()->boxReflect()->direction()) {
605         case ReflectionBelow:
606             result.move(0, box.height() + reflectionOffset());
607             break;
608         case ReflectionAbove:
609             result.move(0, -box.height() - reflectionOffset());
610             break;
611         case ReflectionLeft:
612             result.move(-box.width() - reflectionOffset(), 0);
613             break;
614         case ReflectionRight:
615             result.move(box.width() + reflectionOffset(), 0);
616             break;
617     }
618     return result;
619 }
620
621 int RenderBox::reflectionOffset() const
622 {
623     if (!style()->boxReflect())
624         return 0;
625     if (style()->boxReflect()->direction() == ReflectionLeft || style()->boxReflect()->direction() == ReflectionRight)
626         return style()->boxReflect()->offset().calcValue(borderBoxRect().width());
627     return style()->boxReflect()->offset().calcValue(borderBoxRect().height());
628 }
629
630 LayoutRect RenderBox::reflectedRect(const LayoutRect& r) const
631 {
632     if (!style()->boxReflect())
633         return LayoutRect();
634
635     LayoutRect box = borderBoxRect();
636     LayoutRect result = r;
637     switch (style()->boxReflect()->direction()) {
638         case ReflectionBelow:
639             result.setY(box.maxY() + reflectionOffset() + (box.maxY() - r.maxY()));
640             break;
641         case ReflectionAbove:
642             result.setY(box.y() - reflectionOffset() - box.height() + (box.maxY() - r.maxY()));
643             break;
644         case ReflectionLeft:
645             result.setX(box.x() - reflectionOffset() - box.width() + (box.maxX() - r.maxX()));
646             break;
647         case ReflectionRight:
648             result.setX(box.maxX() + reflectionOffset() + (box.maxX() - r.maxX()));
649             break;
650     }
651     return result;
652 }
653
654 bool RenderBox::fixedElementLaysOutRelativeToFrame(Frame* frame, FrameView* frameView) const
655 {
656     return style() && style()->position() == FixedPosition && container()->isRenderView() && frame && frameView && frameView->fixedElementsLayoutRelativeToFrame();
657 }
658
659 bool RenderBox::includeVerticalScrollbarSize() const
660 {
661     return hasOverflowClipWithLayer() && !layer()->hasOverlayScrollbars()
662         && (style()->overflowY() == OSCROLL || style()->overflowY() == OAUTO);
663 }
664
665 bool RenderBox::includeHorizontalScrollbarSize() const
666 {
667     return hasOverflowClipWithLayer() && !layer()->hasOverlayScrollbars()
668         && (style()->overflowX() == OSCROLL || style()->overflowX() == OAUTO);
669 }
670
671 int RenderBox::verticalScrollbarWidth() const
672 {
673     return includeVerticalScrollbarSize() ? layer()->verticalScrollbarWidth() : 0;
674 }
675
676 int RenderBox::horizontalScrollbarHeight() const
677 {
678     return includeHorizontalScrollbarSize() ? layer()->horizontalScrollbarHeight() : 0;
679 }
680
681 bool RenderBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
682 {
683     RenderLayer* l = layer();
684     if (l && l->scroll(direction, granularity, multiplier)) {
685         if (stopNode)
686             *stopNode = node();
687         return true;
688     }
689
690     if (stopNode && *stopNode && *stopNode == node())
691         return true;
692
693     RenderBlock* b = containingBlock();
694     if (b && !b->isRenderView())
695         return b->scroll(direction, granularity, multiplier, stopNode);
696     return false;
697 }
698
699 bool RenderBox::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
700 {
701     bool scrolled = false;
702     
703     RenderLayer* l = layer();
704     if (l) {
705 #if PLATFORM(MAC)
706         // On Mac only we reset the inline direction position when doing a document scroll (e.g., hitting Home/End).
707         if (granularity == ScrollByDocument)
708             scrolled = l->scroll(logicalToPhysical(ScrollInlineDirectionBackward, isHorizontalWritingMode(), style()->isFlippedBlocksWritingMode()), ScrollByDocument, multiplier);
709 #endif
710         if (l->scroll(logicalToPhysical(direction, isHorizontalWritingMode(), style()->isFlippedBlocksWritingMode()), granularity, multiplier))
711             scrolled = true;
712         
713         if (scrolled) {
714             if (stopNode)
715                 *stopNode = node();
716             return true;
717         }
718     }
719
720     if (stopNode && *stopNode && *stopNode == node())
721         return true;
722
723     RenderBlock* b = containingBlock();
724     if (b && !b->isRenderView())
725         return b->logicalScroll(direction, granularity, multiplier, stopNode);
726     return false;
727 }
728
729 bool RenderBox::canBeScrolledAndHasScrollableArea() const
730 {
731     return canBeProgramaticallyScrolled() && (scrollHeight() != clientHeight() || scrollWidth() != clientWidth());
732 }
733     
734 bool RenderBox::canBeProgramaticallyScrolled() const
735 {
736     return (hasOverflowClip() && (scrollsOverflow() || (node() && node()->rendererIsEditable()))) || (node() && node()->isDocumentNode());
737 }
738
739 void RenderBox::autoscroll()
740 {
741     if (layer())
742         layer()->autoscroll();
743 }
744
745 void RenderBox::panScroll(const IntPoint& source)
746 {
747     if (layer())
748         layer()->panScrollFromPoint(source);
749 }
750
751 bool RenderBox::needsPreferredWidthsRecalculation() const
752 {
753     return style()->paddingStart().isPercent() || style()->paddingEnd().isPercent();
754 }
755
756 IntSize RenderBox::scrolledContentOffset() const
757 {
758     ASSERT(hasOverflowClip());
759
760     if (hasLayer())
761         return layer()->scrolledContentOffset();
762
763     // If we have no layer, it means that we have no overflowing content as we lazily
764     // allocate it on demand. Thus we don't have any scroll offset.
765     ASSERT(!requiresLayerForOverflowClip());
766     return LayoutSize();
767 }
768
769 typedef HashMap<const RenderBox*, LayoutSize> RendererSizeCache;
770 static RendererSizeCache& cachedSizeForOverflowClipMap()
771 {
772     DEFINE_STATIC_LOCAL(RendererSizeCache, cachedSizeForOverflowClipMap, ());
773     return cachedSizeForOverflowClipMap;
774 }
775
776 IntSize RenderBox::cachedSizeForOverflowClip() const
777 {
778     ASSERT(hasOverflowClip());
779     if (hasLayer())
780         return layer()->size();
781
782     ASSERT(!requiresLayerForOverflowClip());
783     RendererSizeCache::iterator it = cachedSizeForOverflowClipMap().find(this);
784     if (it == cachedSizeForOverflowClipMap().end())
785         return LayoutSize();
786
787     return it->second;
788 }
789
790 void RenderBox::updateCachedSizeForOverflowClip()
791 {
792     ASSERT(hasOverflowClip());
793     ASSERT(!requiresLayerForOverflowClip());
794     ASSERT(!hasLayer());
795
796     cachedSizeForOverflowClipMap().set(this, size());
797 }
798
799 void RenderBox::clearCachedSizeForOverflowClip()
800 {
801     ASSERT(hasOverflowClip());
802     ASSERT(!requiresLayerForOverflowClip());
803     ASSERT(!hasLayer());
804
805     // FIXME: We really would like to enable this ASSERT. However the current updateScrollInfoAfterLayout
806     // is not bullet-proof and it triggers in non-obvious ways under NRWT.
807     // ASSERT(cachedSizeForOverflowClipMap().contains(this));
808     cachedSizeForOverflowClipMap().remove(this);
809 }
810
811 LayoutUnit RenderBox::minPreferredLogicalWidth() const
812 {
813     if (preferredLogicalWidthsDirty())
814         const_cast<RenderBox*>(this)->computePreferredLogicalWidths();
815         
816     return m_minPreferredLogicalWidth;
817 }
818
819 LayoutUnit RenderBox::maxPreferredLogicalWidth() const
820 {
821     if (preferredLogicalWidthsDirty())
822         const_cast<RenderBox*>(this)->computePreferredLogicalWidths();
823         
824     return m_maxPreferredLogicalWidth;
825 }
826
827 bool RenderBox::hasOverrideHeight() const
828 {
829     return gOverrideHeightMap && gOverrideHeightMap->contains(this);
830 }
831
832 bool RenderBox::hasOverrideWidth() const
833 {
834     return gOverrideWidthMap && gOverrideWidthMap->contains(this);
835 }
836
837 void RenderBox::setOverrideHeight(LayoutUnit height)
838 {
839     if (!gOverrideHeightMap)
840         gOverrideHeightMap = new OverrideSizeMap();
841     gOverrideHeightMap->set(this, height);
842 }
843
844 void RenderBox::setOverrideWidth(LayoutUnit width)
845 {
846     if (!gOverrideWidthMap)
847         gOverrideWidthMap = new OverrideSizeMap();
848     gOverrideWidthMap->set(this, width);
849 }
850
851 void RenderBox::clearOverrideSize()
852 {
853     if (gOverrideHeightMap)
854         gOverrideHeightMap->remove(this);
855     if (gOverrideWidthMap)
856         gOverrideWidthMap->remove(this);
857 }
858
859 LayoutUnit RenderBox::overrideWidth() const
860 {
861     return hasOverrideWidth() ? gOverrideWidthMap->get(this) : width();
862 }
863
864 LayoutUnit RenderBox::overrideHeight() const
865 {
866     return hasOverrideHeight() ? gOverrideHeightMap->get(this) : height();
867 }
868
869 LayoutUnit RenderBox::computeBorderBoxLogicalWidth(LayoutUnit width) const
870 {
871     LayoutUnit bordersPlusPadding = borderAndPaddingLogicalWidth();
872     if (style()->boxSizing() == CONTENT_BOX)
873         return width + bordersPlusPadding;
874     return max(width, bordersPlusPadding);
875 }
876
877 LayoutUnit RenderBox::computeBorderBoxLogicalHeight(LayoutUnit height) const
878 {
879     LayoutUnit bordersPlusPadding = borderAndPaddingLogicalHeight();
880     if (style()->boxSizing() == CONTENT_BOX)
881         return height + bordersPlusPadding;
882     return max(height, bordersPlusPadding);
883 }
884
885 LayoutUnit RenderBox::computeContentBoxLogicalWidth(LayoutUnit width) const
886 {
887     if (style()->boxSizing() == BORDER_BOX)
888         width -= borderAndPaddingLogicalWidth();
889     return max<LayoutUnit>(0, width);
890 }
891
892 LayoutUnit RenderBox::computeContentBoxLogicalHeight(LayoutUnit height) const
893 {
894     if (style()->boxSizing() == BORDER_BOX)
895         height -= borderAndPaddingLogicalHeight();
896     return max<LayoutUnit>(0, height);
897 }
898
899 // Hit Testing
900 bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
901 {
902     LayoutPoint adjustedLocation = accumulatedOffset + location();
903
904     // Check kids first.
905     for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
906         if (!child->hasLayer() && child->nodeAtPoint(request, result, pointInContainer, adjustedLocation, action)) {
907             updateHitTestResult(result, pointInContainer - toLayoutSize(adjustedLocation));
908             return true;
909         }
910     }
911
912     // Check our bounds next. For this purpose always assume that we can only be hit in the
913     // foreground phase (which is true for replaced elements like images).
914     LayoutRect boundsRect = borderBoxRectInRegion(result.region());
915     boundsRect.moveBy(adjustedLocation);
916     if (visibleToHitTesting() && action == HitTestForeground && boundsRect.intersects(result.rectForPoint(pointInContainer))) {
917         updateHitTestResult(result, pointInContainer - toLayoutSize(adjustedLocation));
918         if (!result.addNodeToRectBasedTestResult(node(), pointInContainer, boundsRect))
919             return true;
920     }
921
922     return false;
923 }
924
925 // --------------------- painting stuff -------------------------------
926
927 void RenderBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
928 {
929     LayoutPoint adjustedPaintOffset = paintOffset + location();
930     // default implementation. Just pass paint through to the children
931     PaintInfo childInfo(paintInfo);
932     childInfo.updatePaintingRootForChildren(this);
933     for (RenderObject* child = firstChild(); child; child = child->nextSibling())
934         child->paint(childInfo, adjustedPaintOffset);
935 }
936
937 void RenderBox::paintRootBoxFillLayers(const PaintInfo& paintInfo)
938 {
939     RenderObject* rootBackgroundRenderer = rendererForRootBackground();
940     
941     const FillLayer* bgLayer = rootBackgroundRenderer->style()->backgroundLayers();
942     Color bgColor = rootBackgroundRenderer->style()->visitedDependentColor(CSSPropertyBackgroundColor);
943
944     paintFillLayers(paintInfo, bgColor, bgLayer, view()->backgroundRect(this), BackgroundBleedNone, CompositeSourceOver, rootBackgroundRenderer);
945 }
946
947 BackgroundBleedAvoidance RenderBox::determineBackgroundBleedAvoidance(GraphicsContext* context) const
948 {
949     if (context->paintingDisabled())
950         return BackgroundBleedNone;
951
952     const RenderStyle* style = this->style();
953
954     if (!style->hasBackground() || !style->hasBorder() || !style->hasBorderRadius() || borderImageIsLoadedAndCanBeRendered())
955         return BackgroundBleedNone;
956
957     AffineTransform ctm = context->getCTM();
958     FloatSize contextScaling(static_cast<float>(ctm.xScale()), static_cast<float>(ctm.yScale()));
959     if (borderObscuresBackgroundEdge(contextScaling))
960         return BackgroundBleedShrinkBackground;
961     
962     // FIXME: there is one more strategy possible, for opaque backgrounds and
963     // translucent borders. In that case we could avoid using a transparency layer,
964     // and paint the border first, and then paint the background clipped to the
965     // inside of the border.
966
967     return BackgroundBleedUseTransparencyLayer;
968 }
969
970 void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
971 {
972     if (!paintInfo.shouldPaintWithinRoot(this))
973         return;
974
975     LayoutRect paintRect = borderBoxRectInRegion(paintInfo.renderRegion);
976     paintRect.moveBy(paintOffset);
977
978     // border-fit can adjust where we paint our border and background.  If set, we snugly fit our line box descendants.  (The iChat
979     // balloon layout is an example of this).
980     borderFitAdjust(paintRect);
981
982     BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context);
983
984     // FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have
985     // custom shadows of their own.
986     if (!boxShadowShouldBeAppliedToBackground(bleedAvoidance))
987         paintBoxShadow(paintInfo, paintRect, style(), Normal);
988
989     GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
990     if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) {
991         // To avoid the background color bleeding out behind the border, we'll render background and border
992         // into a transparency layer, and then clip that in one go (which requires setting up the clip before
993         // beginning the layer).
994         RoundedRect border = style()->getRoundedBorderFor(paintRect);
995         stateSaver.save();
996         paintInfo.context->addRoundedRectClip(border);
997         paintInfo.context->beginTransparencyLayer(1);
998     }
999     
1000     // If we have a native theme appearance, paint that before painting our background.
1001     // The theme will tell us whether or not we should also paint the CSS background.
1002     bool themePainted = style()->hasAppearance() && !theme()->paint(this, paintInfo, paintRect);
1003     if (!themePainted) {
1004         paintBackground(paintInfo, paintRect, bleedAvoidance);
1005
1006         if (style()->hasAppearance())
1007             theme()->paintDecorations(this, paintInfo, pixelSnappedIntRect(paintRect));
1008     }
1009     paintBoxShadow(paintInfo, paintRect, style(), Inset);
1010
1011     // The theme will tell us whether or not we should also paint the CSS border.
1012     if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, pixelSnappedIntRect(paintRect)))) && style()->hasBorder())
1013         paintBorder(paintInfo, paintRect, style(), bleedAvoidance);
1014
1015     if (bleedAvoidance == BackgroundBleedUseTransparencyLayer)
1016         paintInfo.context->endTransparencyLayer();
1017 }
1018
1019 void RenderBox::paintBackground(const PaintInfo& paintInfo, const LayoutRect& paintRect, BackgroundBleedAvoidance bleedAvoidance)
1020 {
1021     if (isRoot())
1022         paintRootBoxFillLayers(paintInfo);
1023     else if (!isBody()
1024             || (document()->documentElement()->renderer() && document()->documentElement()->renderer()->hasBackground())
1025             || (document()->documentElement()->renderer() != parent())) {
1026         // The <body> only paints its background if the root element has defined a background independent of the body,
1027         // or if the <body>'s parent is not the document element's renderer (e.g. inside SVG foreignObject).
1028         if (!backgroundIsObscured())
1029             paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect, bleedAvoidance);
1030     }
1031 }
1032
1033 void RenderBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1034 {
1035     if (!paintInfo.shouldPaintWithinRoot(this) || style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask || paintInfo.context->paintingDisabled())
1036         return;
1037
1038     LayoutRect paintRect = LayoutRect(paintOffset, size());
1039
1040     // border-fit can adjust where we paint our border and background.  If set, we snugly fit our line box descendants.  (The iChat
1041     // balloon layout is an example of this).
1042     borderFitAdjust(paintRect);
1043
1044     paintMaskImages(paintInfo, paintRect);
1045 }
1046
1047 void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& paintRect)
1048 {
1049     // Figure out if we need to push a transparency layer to render our mask.
1050     bool pushTransparencyLayer = false;
1051     bool compositedMask = hasLayer() && layer()->hasCompositedMask();
1052     CompositeOperator compositeOp = CompositeSourceOver;
1053
1054     bool allMaskImagesLoaded = true;
1055     
1056     if (!compositedMask) {
1057         pushTransparencyLayer = true;
1058         StyleImage* maskBoxImage = style()->maskBoxImage().image();
1059         const FillLayer* maskLayers = style()->maskLayers();
1060
1061         // Don't render a masked element until all the mask images have loaded, to prevent a flash of unmasked content.
1062         if (maskBoxImage)
1063             allMaskImagesLoaded &= maskBoxImage->isLoaded();
1064
1065         if (maskLayers)
1066             allMaskImagesLoaded &= maskLayers->imagesAreLoaded();
1067
1068         paintInfo.context->setCompositeOperation(CompositeDestinationIn);
1069         paintInfo.context->beginTransparencyLayer(1);
1070         compositeOp = CompositeSourceOver;
1071     }
1072
1073     if (allMaskImagesLoaded) {
1074         paintFillLayers(paintInfo, Color(), style()->maskLayers(), paintRect, BackgroundBleedNone, compositeOp);
1075         paintNinePieceImage(paintInfo.context, paintRect, style(), style()->maskBoxImage(), compositeOp);
1076     }
1077     
1078     if (pushTransparencyLayer)
1079         paintInfo.context->endTransparencyLayer();
1080 }
1081
1082 LayoutRect RenderBox::maskClipRect()
1083 {
1084     const NinePieceImage& maskBoxImage = style()->maskBoxImage();
1085     if (maskBoxImage.image()) {
1086         LayoutRect borderImageRect = borderBoxRect();
1087         
1088         // Apply outsets to the border box.
1089         LayoutUnit topOutset;
1090         LayoutUnit rightOutset;
1091         LayoutUnit bottomOutset;
1092         LayoutUnit leftOutset;
1093         style()->getMaskBoxImageOutsets(topOutset, rightOutset, bottomOutset, leftOutset);
1094          
1095         borderImageRect.setX(borderImageRect.x() - leftOutset);
1096         borderImageRect.setY(borderImageRect.y() - topOutset);
1097         borderImageRect.setWidth(borderImageRect.width() + leftOutset + rightOutset);
1098         borderImageRect.setHeight(borderImageRect.height() + topOutset + bottomOutset);
1099
1100         return borderImageRect;
1101     }
1102     
1103     LayoutRect result;
1104     LayoutRect borderBox = borderBoxRect();
1105     for (const FillLayer* maskLayer = style()->maskLayers(); maskLayer; maskLayer = maskLayer->next()) {
1106         if (maskLayer->image()) {
1107             BackgroundImageGeometry geometry;
1108             calculateBackgroundImageGeometry(maskLayer, borderBox, geometry);
1109             result.unite(geometry.destRect());
1110         }
1111     }
1112     return result;
1113 }
1114
1115 void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect,
1116     BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
1117 {
1118     if (!fillLayer)
1119         return;
1120
1121     paintFillLayers(paintInfo, c, fillLayer->next(), rect, bleedAvoidance, op, backgroundObject);
1122     paintFillLayer(paintInfo, c, fillLayer, rect, bleedAvoidance, op, backgroundObject);
1123 }
1124
1125 void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect,
1126     BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
1127 {
1128     paintFillLayerExtended(paintInfo, c, fillLayer, rect, bleedAvoidance, 0, LayoutSize(), op, backgroundObject);
1129 }
1130
1131 #if USE(ACCELERATED_COMPOSITING)
1132 static bool layersUseImage(WrappedImagePtr image, const FillLayer* layers)
1133 {
1134     for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
1135         if (curLayer->image() && image == curLayer->image()->data())
1136             return true;
1137     }
1138
1139     return false;
1140 }
1141 #endif
1142
1143 void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*)
1144 {
1145     if (!parent())
1146         return;
1147
1148     if ((style()->borderImage().image() && style()->borderImage().image()->data() == image) ||
1149         (style()->maskBoxImage().image() && style()->maskBoxImage().image()->data() == image)) {
1150         repaint();
1151         return;
1152     }
1153
1154     bool didFullRepaint = repaintLayerRectsForImage(image, style()->backgroundLayers(), true);
1155     if (!didFullRepaint)
1156         repaintLayerRectsForImage(image, style()->maskLayers(), false);
1157
1158
1159 #if USE(ACCELERATED_COMPOSITING)
1160     if (hasLayer() && layer()->hasCompositedMask() && layersUseImage(image, style()->maskLayers()))
1161         layer()->contentChanged(RenderLayer::MaskImageChanged);
1162 #endif
1163 }
1164
1165 bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer* layers, bool drawingBackground)
1166 {
1167     LayoutRect rendererRect;
1168     RenderBox* layerRenderer = 0;
1169
1170     for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
1171         if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(this, style()->effectiveZoom())) {
1172             // Now that we know this image is being used, compute the renderer and the rect
1173             // if we haven't already
1174             if (!layerRenderer) {
1175                 bool drawingRootBackground = drawingBackground && (isRoot() || (isBody() && !document()->documentElement()->renderer()->hasBackground()));
1176                 if (drawingRootBackground) {
1177                     layerRenderer = view();
1178
1179                     LayoutUnit rw;
1180                     LayoutUnit rh;
1181
1182                     if (FrameView* frameView = toRenderView(layerRenderer)->frameView()) {
1183                         rw = frameView->contentsWidth();
1184                         rh = frameView->contentsHeight();
1185                     } else {
1186                         rw = layerRenderer->width();
1187                         rh = layerRenderer->height();
1188                     }
1189                     rendererRect = LayoutRect(-layerRenderer->marginLeft(),
1190                         -layerRenderer->marginTop(),
1191                         max(layerRenderer->width() + layerRenderer->marginWidth() + layerRenderer->borderLeft() + layerRenderer->borderRight(), rw),
1192                         max(layerRenderer->height() + layerRenderer->marginHeight() + layerRenderer->borderTop() + layerRenderer->borderBottom(), rh));
1193                 } else {
1194                     layerRenderer = this;
1195                     rendererRect = borderBoxRect();
1196                 }
1197             }
1198
1199             BackgroundImageGeometry geometry;
1200             layerRenderer->calculateBackgroundImageGeometry(curLayer, rendererRect, geometry);
1201             layerRenderer->repaintRectangle(geometry.destRect());
1202             if (geometry.destRect() == rendererRect)
1203                 return true;
1204         }
1205     }
1206     return false;
1207 }
1208
1209 #if PLATFORM(MAC)
1210
1211 void RenderBox::paintCustomHighlight(const LayoutPoint& paintOffset, const AtomicString& type, bool behindText)
1212 {
1213     Frame* frame = this->frame();
1214     if (!frame)
1215         return;
1216     Page* page = frame->page();
1217     if (!page)
1218         return;
1219
1220     InlineBox* boxWrap = inlineBoxWrapper();
1221     RootInlineBox* r = boxWrap ? boxWrap->root() : 0;
1222     if (r) {
1223         FloatRect rootRect(paintOffset.x() + r->x(), paintOffset.y() + r->selectionTop(), r->logicalWidth(), r->selectionHeight());
1224         FloatRect imageRect(paintOffset.x() + x(), rootRect.y(), width(), rootRect.height());
1225         page->chrome()->client()->paintCustomHighlight(node(), type, imageRect, rootRect, behindText, false);
1226     } else {
1227         FloatRect imageRect(paintOffset.x() + x(), paintOffset.y() + y(), width(), height());
1228         page->chrome()->client()->paintCustomHighlight(node(), type, imageRect, imageRect, behindText, false);
1229     }
1230 }
1231
1232 #endif
1233
1234 bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumulatedOffset)
1235 {
1236     if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseSelfOutline || paintInfo.phase == PaintPhaseMask)
1237         return false;
1238         
1239     bool isControlClip = hasControlClip();
1240     bool isOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer();
1241     
1242     if (!isControlClip && !isOverflowClip)
1243         return false;
1244     
1245     if (paintInfo.phase == PaintPhaseOutline)
1246         paintInfo.phase = PaintPhaseChildOutlines;
1247     else if (paintInfo.phase == PaintPhaseChildBlockBackground) {
1248         paintInfo.phase = PaintPhaseBlockBackground;
1249         paintObject(paintInfo, accumulatedOffset);
1250         paintInfo.phase = PaintPhaseChildBlockBackgrounds;
1251     }
1252     IntRect clipRect = pixelSnappedIntRect(isControlClip ? controlClipRect(accumulatedOffset) : overflowClipRect(accumulatedOffset, paintInfo.renderRegion));
1253     paintInfo.context->save();
1254     if (style()->hasBorderRadius())
1255         paintInfo.context->addRoundedRectClip(style()->getRoundedInnerBorderFor(LayoutRect(accumulatedOffset, size())));
1256     paintInfo.context->clip(clipRect);
1257     return true;
1258 }
1259
1260 void RenderBox::popContentsClip(PaintInfo& paintInfo, PaintPhase originalPhase, const LayoutPoint& accumulatedOffset)
1261 {
1262     ASSERT(hasControlClip() || (hasOverflowClip() && !hasSelfPaintingLayer()));
1263
1264     paintInfo.context->restore();
1265     if (originalPhase == PaintPhaseOutline) {
1266         paintInfo.phase = PaintPhaseSelfOutline;
1267         paintObject(paintInfo, accumulatedOffset);
1268         paintInfo.phase = originalPhase;
1269     } else if (originalPhase == PaintPhaseChildBlockBackground)
1270         paintInfo.phase = originalPhase;
1271 }
1272
1273 LayoutRect RenderBox::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy)
1274 {
1275     // FIXME: When overflow-clip (CSS3) is implemented, we'll obtain the property
1276     // here.
1277     LayoutRect clipRect = borderBoxRectInRegion(region);
1278     clipRect.setLocation(location + clipRect.location() + LayoutSize(borderLeft(), borderTop()));
1279     clipRect.setSize(clipRect.size() - LayoutSize(borderLeft() + borderRight(), borderTop() + borderBottom()));
1280
1281     // Subtract out scrollbars if we have them.
1282      if (layer()) {
1283         if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
1284             clipRect.move(layer()->verticalScrollbarWidth(relevancy), 0);
1285         clipRect.contract(layer()->verticalScrollbarWidth(relevancy), layer()->horizontalScrollbarHeight(relevancy));
1286      }
1287
1288     return clipRect;
1289 }
1290
1291 LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region)
1292 {
1293     LayoutRect borderBoxRect = borderBoxRectInRegion(region);
1294     LayoutRect clipRect = LayoutRect(borderBoxRect.location() + location, borderBoxRect.size());
1295
1296     if (!style()->clipLeft().isAuto()) {
1297         LayoutUnit c = style()->clipLeft().calcValue(borderBoxRect.width());
1298         clipRect.move(c, 0);
1299         clipRect.contract(c, 0);
1300     }
1301
1302     // We don't use the region-specific border box's width and height since clip offsets are (stupidly) specified
1303     // from the left and top edges. Therefore it's better to avoid constraining to smaller widths and heights.
1304
1305     if (!style()->clipRight().isAuto())
1306         clipRect.contract(width() - style()->clipRight().calcValue(width()), 0);
1307
1308     if (!style()->clipTop().isAuto()) {
1309         LayoutUnit c = style()->clipTop().calcValue(borderBoxRect.height());
1310         clipRect.move(0, c);
1311         clipRect.contract(0, c);
1312     }
1313
1314     if (!style()->clipBottom().isAuto())
1315         clipRect.contract(0, height() - style()->clipBottom().calcValue(height()));
1316
1317     return clipRect;
1318 }
1319
1320 LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
1321 {    
1322     RenderRegion* containingBlockRegion = 0;
1323     LayoutUnit logicalTopPosition = logicalTop();
1324     LayoutUnit adjustedPageOffsetForContainingBlock = offsetFromLogicalTopOfFirstPage - logicalTop();
1325     if (region) {
1326         LayoutUnit offsetFromLogicalTopOfRegion = region ? region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage : zeroLayoutUnit;
1327         logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
1328         containingBlockRegion = cb->clampToStartAndEndRegions(region);
1329     }
1330
1331     LayoutUnit result = cb->availableLogicalWidthForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock) - childMarginStart - childMarginEnd;
1332
1333     // We need to see if margins on either the start side or the end side can contain the floats in question. If they can,
1334     // then just using the line width is inaccurate. In the case where a float completely fits, we don't need to use the line
1335     // offset at all, but can instead push all the way to the content edge of the containing block. In the case where the float
1336     // 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
1337     // "consumed" by the float. Negative margins aren't consumed by the float, and so we ignore them.
1338     if (childMarginStart > 0) {
1339         LayoutUnit startContentSide = cb->startOffsetForContent(containingBlockRegion, adjustedPageOffsetForContainingBlock);
1340         LayoutUnit startContentSideWithMargin = startContentSide + childMarginStart;
1341         LayoutUnit startOffset = cb->startOffsetForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock);
1342         if (startOffset > startContentSideWithMargin)
1343             result += childMarginStart;
1344         else
1345             result += startOffset - startContentSide;
1346     }
1347     
1348     if (childMarginEnd > 0) {
1349         LayoutUnit endContentSide = cb->endOffsetForContent(containingBlockRegion, adjustedPageOffsetForContainingBlock);
1350         LayoutUnit endContentSideWithMargin = endContentSide + childMarginEnd;
1351         LayoutUnit endOffset = cb->endOffsetForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock);
1352         if (endOffset > endContentSideWithMargin)
1353             result += childMarginEnd;
1354         else
1355             result += endOffset - endContentSide;
1356     }
1357
1358     return result;
1359 }
1360
1361 LayoutUnit RenderBox::containingBlockLogicalWidthForContent() const
1362 {
1363     RenderBlock* cb = containingBlock();
1364     return cb->availableLogicalWidth();
1365 }
1366
1367 LayoutUnit RenderBox::containingBlockLogicalWidthForContentInRegion(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
1368 {
1369     if (!region)
1370         return containingBlockLogicalWidthForContent();
1371
1372     RenderBlock* cb = containingBlock();
1373     RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region);
1374     LayoutUnit result = cb->availableLogicalWidth();
1375     RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(containingBlockRegion, offsetFromLogicalTopOfFirstPage - logicalTop());
1376     if (!boxInfo)
1377         return result;
1378     return max<LayoutUnit>(0, result - (cb->logicalWidth() - boxInfo->logicalWidth()));
1379 }
1380
1381 LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const
1382 {
1383     RenderBlock* cb = containingBlock();
1384     RenderStyle* containingBlockStyle = cb->style();
1385     Length logicalHeightLength = containingBlockStyle->logicalHeight();
1386     
1387     // FIXME: For now just support fixed heights.  Eventually should support percentage heights as well.
1388     if (!logicalHeightLength.isFixed()) {
1389         // Rather than making the child be completely unconstrained, WinIE uses the viewport width and height
1390         // as a constraint.  We do that for now as well even though it's likely being unconstrained is what the spec
1391         // will decide.
1392         return containingBlockStyle->isHorizontalWritingMode() ? view()->frameView()->visibleHeight() : view()->frameView()->visibleWidth();
1393     }
1394     
1395     // Use the content box logical height as specified by the style.
1396     return cb->computeContentBoxLogicalHeight(logicalHeightLength.value());
1397 }
1398
1399 void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, bool* wasFixed) const
1400 {
1401     if (repaintContainer == this)
1402         return;
1403
1404     if (RenderView* v = view()) {
1405         if (v->layoutStateEnabled() && !repaintContainer) {
1406             LayoutState* layoutState = v->layoutState();
1407             LayoutSize offset = layoutState->m_paintOffset + locationOffset();
1408             if (style()->position() == RelativePosition && layer())
1409                 offset += layer()->relativePositionOffset();
1410             transformState.move(offset);
1411             return;
1412         }
1413     }
1414
1415     bool containerSkipped;
1416     RenderObject* o = container(repaintContainer, &containerSkipped);
1417     if (!o)
1418         return;
1419
1420     bool isFixedPos = style()->position() == FixedPosition;
1421     bool hasTransform = hasLayer() && layer()->transform();
1422     if (hasTransform) {
1423         // If this box has a transform, it acts as a fixed position container for fixed descendants,
1424         // and may itself also be fixed position. So propagate 'fixed' up only if this box is fixed position.
1425         fixed &= isFixedPos;
1426     } else
1427         fixed |= isFixedPos;
1428     if (wasFixed)
1429         *wasFixed = fixed;
1430     
1431     LayoutSize containerOffset = offsetFromContainer(o, roundedLayoutPoint(transformState.mappedPoint()));
1432     
1433     bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D());
1434     if (useTransforms && shouldUseTransformFromContainer(o)) {
1435         TransformationMatrix t;
1436         getTransformFromContainer(o, containerOffset, t);
1437         transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1438     } else
1439         transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1440
1441     if (containerSkipped) {
1442         // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
1443         // to just subtract the delta between the repaintContainer and o.
1444         LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
1445         transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1446         return;
1447     }
1448
1449     if (o->isRenderFlowThread()) {
1450         // Transform from render flow coordinates into region coordinates.
1451         RenderRegion* region = toRenderFlowThread(o)->mapFromFlowToRegion(transformState);
1452         if (region)
1453             region->mapLocalToContainer(region->containerForRepaint(), fixed, useTransforms, transformState, wasFixed);
1454         return;
1455     }
1456
1457     o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, wasFixed);
1458 }
1459
1460 void RenderBox::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const
1461 {
1462     // We don't expect absoluteToLocal() to be called during layout (yet)
1463     ASSERT(!view() || !view()->layoutStateEnabled());
1464     
1465     bool isFixedPos = style()->position() == FixedPosition;
1466     bool hasTransform = hasLayer() && layer()->transform();
1467     if (hasTransform) {
1468         // If this box has a transform, it acts as a fixed position container for fixed descendants,
1469         // and may itself also be fixed position. So propagate 'fixed' up only if this box is fixed position.
1470         fixed &= isFixedPos;
1471     } else
1472         fixed |= isFixedPos;
1473
1474     RenderBoxModelObject::mapAbsoluteToLocalPoint(fixed, useTransforms, transformState);
1475 }
1476
1477 LayoutSize RenderBox::offsetFromContainer(RenderObject* o, const LayoutPoint& point) const
1478 {
1479     ASSERT(o == container());
1480
1481     LayoutSize offset;    
1482     if (isRelPositioned())
1483         offset += relativePositionOffset();
1484
1485     if (!isInline() || isReplaced()) {
1486         if (!style()->isPositioned() && o->hasColumns()) {
1487             RenderBlock* block = toRenderBlock(o);
1488             LayoutRect columnRect(frameRect());
1489             block->adjustStartEdgeForWritingModeIncludingColumns(columnRect);
1490             offset += toSize(columnRect.location());
1491             LayoutPoint columnPoint = block->flipForWritingModeIncludingColumns(point + offset);
1492             offset = toLayoutSize(block->flipForWritingModeIncludingColumns(toLayoutPoint(offset)));
1493             o->adjustForColumns(offset, columnPoint);
1494             offset = block->flipForWritingMode(offset);
1495         } else
1496             offset += topLeftLocationOffset();
1497     }
1498
1499     if (o->hasOverflowClip())
1500         offset -= toRenderBox(o)->scrolledContentOffset();
1501
1502     if (style()->position() == AbsolutePosition && o->isRelPositioned() && o->isRenderInline())
1503         offset += toRenderInline(o)->relativePositionedInlineOffset(this);
1504
1505     return offset;
1506 }
1507
1508 InlineBox* RenderBox::createInlineBox()
1509 {
1510     return new (renderArena()) InlineBox(this);
1511 }
1512
1513 void RenderBox::dirtyLineBoxes(bool fullLayout)
1514 {
1515     if (m_inlineBoxWrapper) {
1516         if (fullLayout) {
1517             m_inlineBoxWrapper->destroy(renderArena());
1518             m_inlineBoxWrapper = 0;
1519         } else
1520             m_inlineBoxWrapper->dirtyLineBoxes();
1521     }
1522 }
1523
1524 void RenderBox::positionLineBox(InlineBox* box)
1525 {
1526     if (isPositioned()) {
1527         // Cache the x position only if we were an INLINE type originally.
1528         bool wasInline = style()->isOriginalDisplayInlineType();
1529         if (wasInline) {
1530             // The value is cached in the xPos of the box.  We only need this value if
1531             // our object was inline originally, since otherwise it would have ended up underneath
1532             // the inlines.
1533             RootInlineBox* root = box->root();
1534             root->block()->setStaticInlinePositionForChild(this, root->lineTopWithLeading(), roundedLayoutUnit(box->logicalLeft()));
1535             if (style()->hasStaticInlinePosition(box->isHorizontal()))
1536                 setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
1537         } else {
1538             // Our object was a block originally, so we make our normal flow position be
1539             // just below the line box (as though all the inlines that came before us got
1540             // wrapped in an anonymous block, which is what would have happened had we been
1541             // in flow).  This value was cached in the y() of the box.
1542             layer()->setStaticBlockPosition(box->logicalTop());
1543             if (style()->hasStaticBlockPosition(box->isHorizontal()))
1544                 setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
1545         }
1546
1547         // Nuke the box.
1548         box->remove();
1549         box->destroy(renderArena());
1550     } else if (isReplaced()) {
1551         setLocation(roundedLayoutPoint(box->topLeft()));
1552         // m_inlineBoxWrapper should already be 0. Deleting it is a safeguard against security issues.
1553         ASSERT(!m_inlineBoxWrapper);
1554         if (m_inlineBoxWrapper)
1555             deleteLineBoxWrapper();
1556         m_inlineBoxWrapper = box;
1557     }
1558 }
1559
1560 void RenderBox::deleteLineBoxWrapper()
1561 {
1562     if (m_inlineBoxWrapper) {
1563         if (!documentBeingDestroyed())
1564             m_inlineBoxWrapper->remove();
1565         m_inlineBoxWrapper->destroy(renderArena());
1566         m_inlineBoxWrapper = 0;
1567     }
1568 }
1569
1570 LayoutRect RenderBox::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const
1571 {
1572     if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
1573         return LayoutRect();
1574
1575     LayoutRect r = visualOverflowRect();
1576
1577     RenderView* v = view();
1578     if (v) {
1579         // FIXME: layoutDelta needs to be applied in parts before/after transforms and
1580         // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
1581         r.move(v->layoutDelta());
1582     }
1583     
1584     if (style()) {
1585         // We have to use maximalOutlineSize() because a child might have an outline
1586         // that projects outside of our overflowRect.
1587         if (v) {
1588             ASSERT(style()->outlineSize() <= v->maximalOutlineSize());
1589             r.inflate(v->maximalOutlineSize());
1590         }
1591     }
1592     
1593     computeRectForRepaint(repaintContainer, r);
1594     return r;
1595 }
1596
1597 void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
1598 {
1599     // The rect we compute at each step is shifted by our x/y offset in the parent container's coordinate space.
1600     // Only when we cross a writing mode boundary will we have to possibly flipForWritingMode (to convert into a more appropriate
1601     // offset corner for the enclosing container).  This allows for a fully RL or BT document to repaint
1602     // properly even during layout, since the rect remains flipped all the way until the end.
1603     //
1604     // RenderView::computeRectForRepaint then converts the rect to physical coordinates.  We also convert to
1605     // physical when we hit a repaintContainer boundary.  Therefore the final rect returned is always in the
1606     // physical coordinate space of the repaintContainer.
1607     RenderStyle* styleToUse = style();
1608     if (RenderView* v = view()) {
1609         // LayoutState is only valid for root-relative, non-fixed position repainting
1610         if (v->layoutStateEnabled() && !repaintContainer && styleToUse->position() != FixedPosition) {
1611             LayoutState* layoutState = v->layoutState();
1612
1613             if (layer() && layer()->transform())
1614                 rect = layer()->transform()->mapRect(rect);
1615
1616             if (styleToUse->position() == RelativePosition && layer())
1617                 rect.move(layer()->relativePositionOffset());
1618
1619             rect.moveBy(location());
1620             rect.move(layoutState->m_paintOffset);
1621             if (layoutState->m_clipped)
1622                 rect.intersect(layoutState->m_clipRect);
1623             return;
1624         }
1625     }
1626
1627     if (hasReflection())
1628         rect.unite(reflectedRect(rect));
1629
1630     if (repaintContainer == this) {
1631         if (repaintContainer->style()->isFlippedBlocksWritingMode())
1632             flipForWritingMode(rect);
1633         return;
1634     }
1635
1636     bool containerSkipped;
1637     RenderObject* o = container(repaintContainer, &containerSkipped);
1638     if (!o)
1639         return;
1640
1641     if (isWritingModeRoot() && !isPositioned())
1642         flipForWritingMode(rect);
1643
1644 #if ENABLE(CSS_FILTERS)
1645     if (styleToUse->hasFilterOutsets()) {
1646         LayoutUnit topOutset;
1647         LayoutUnit rightOutset;
1648         LayoutUnit bottomOutset;
1649         LayoutUnit leftOutset;
1650         styleToUse->filter().getOutsets(topOutset, rightOutset, bottomOutset, leftOutset);
1651         rect.move(-leftOutset, -topOutset);
1652         rect.expand(leftOutset + rightOutset, topOutset + bottomOutset);
1653     }
1654 #endif
1655
1656     LayoutPoint topLeft = rect.location();
1657     topLeft.move(locationOffset());
1658
1659     EPosition position = styleToUse->position();
1660
1661     // We are now in our parent container's coordinate space.  Apply our transform to obtain a bounding box
1662     // in the parent's coordinate space that encloses us.
1663     if (layer() && layer()->transform()) {
1664         fixed = position == FixedPosition;
1665         rect = layer()->transform()->mapRect(rect);
1666         topLeft = rect.location();
1667         topLeft.move(locationOffset());
1668     } else if (position == FixedPosition)
1669         fixed = true;
1670
1671     if (position == AbsolutePosition && o->isRelPositioned() && o->isRenderInline())
1672         topLeft += toRenderInline(o)->relativePositionedInlineOffset(this);
1673     else if (position == RelativePosition && layer()) {
1674         // Apply the relative position offset when invalidating a rectangle.  The layer
1675         // is translated, but the render box isn't, so we need to do this to get the
1676         // right dirty rect.  Since this is called from RenderObject::setStyle, the relative position
1677         // flag on the RenderObject has been cleared, so use the one on the style().
1678         topLeft += layer()->relativePositionOffset();
1679     }
1680     
1681     if (o->isBlockFlow() && position != AbsolutePosition && position != FixedPosition) {
1682         RenderBlock* cb = toRenderBlock(o);
1683         if (cb->hasColumns()) {
1684             LayoutRect repaintRect(topLeft, rect.size());
1685             cb->adjustRectForColumns(repaintRect);
1686             topLeft = repaintRect.location();
1687             rect = repaintRect;
1688         }
1689     }
1690
1691     // FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout,
1692     // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer.
1693     if (o->hasOverflowClip()) {
1694         RenderBox* containerBox = toRenderBox(o);
1695
1696         // o->height() is inaccurate if we're in the middle of a layout of |o|, so use the
1697         // layer's size instead.  Even if the layer's size is wrong, the layer itself will repaint
1698         // anyway if its size does change.
1699         topLeft -= containerBox->scrolledContentOffset(); // For overflow:auto/scroll/hidden.
1700
1701         LayoutRect repaintRect(topLeft, rect.size());
1702         LayoutRect boxRect(LayoutPoint(), containerBox->cachedSizeForOverflowClip());
1703         rect = intersection(repaintRect, boxRect);
1704         if (rect.isEmpty())
1705             return;
1706     } else
1707         rect.setLocation(topLeft);
1708
1709     if (containerSkipped) {
1710         // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
1711         LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
1712         rect.move(-containerOffset);
1713         return;
1714     }
1715
1716     o->computeRectForRepaint(repaintContainer, rect, fixed);
1717 }
1718
1719 void RenderBox::repaintDuringLayoutIfMoved(const LayoutRect& rect)
1720 {
1721     LayoutUnit newX = x();
1722     LayoutUnit newY = y();
1723     LayoutUnit newWidth = width();
1724     LayoutUnit newHeight = height();
1725     if (rect.x() != newX || rect.y() != newY) {
1726         // The child moved.  Invalidate the object's old and new positions.  We have to do this
1727         // since the object may not have gotten a layout.
1728         m_frameRect = rect;
1729         repaint();
1730         repaintOverhangingFloats(true);
1731         m_frameRect = LayoutRect(newX, newY, newWidth, newHeight);
1732         repaint();
1733         repaintOverhangingFloats(true);
1734     }
1735 }
1736
1737 void RenderBox::computeLogicalWidth()
1738 {
1739     computeLogicalWidthInRegion();
1740 }
1741
1742 void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
1743 {
1744     if (isPositioned()) {
1745         // FIXME: This calculation is not patched for block-flow yet.
1746         // https://bugs.webkit.org/show_bug.cgi?id=46500
1747         computePositionedLogicalWidth(region, offsetFromLogicalTopOfFirstPage);
1748         return;
1749     }
1750
1751     // If layout is limited to a subtree, the subtree root's logical width does not change.
1752     if (node() && view()->frameView() && view()->frameView()->layoutRoot(true) == this)
1753         return;
1754
1755     // The parent box is flexing us, so it has increased or decreased our
1756     // width.  Use the width from the style context.
1757     // FIXME: Account for block-flow in flexible boxes.
1758     // https://bugs.webkit.org/show_bug.cgi?id=46418
1759     if (hasOverrideWidth() && parent()->isFlexibleBoxIncludingDeprecated()) {
1760         setLogicalWidth(overrideWidth());
1761         return;
1762     }
1763
1764     // FIXME: Account for block-flow in flexible boxes.
1765     // https://bugs.webkit.org/show_bug.cgi?id=46418
1766     bool inVerticalBox = parent()->isDeprecatedFlexibleBox() && (parent()->style()->boxOrient() == VERTICAL);
1767     bool stretching = (parent()->style()->boxAlign() == BSTRETCH);
1768     bool treatAsReplaced = shouldComputeSizeAsReplaced() && (!inVerticalBox || !stretching);
1769
1770     RenderStyle* styleToUse = style();
1771     Length logicalWidthLength = (treatAsReplaced) ? Length(computeReplacedLogicalWidth(), Fixed) : styleToUse->logicalWidth();
1772
1773     RenderBlock* cb = containingBlock();
1774     LayoutUnit containerLogicalWidth = max<LayoutUnit>(0, containingBlockLogicalWidthForContentInRegion(region, offsetFromLogicalTopOfFirstPage));
1775     bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
1776     LayoutUnit containerWidthInInlineDirection = containerLogicalWidth;
1777     if (hasPerpendicularContainingBlock)
1778         containerWidthInInlineDirection = perpendicularContainingBlockLogicalHeight();
1779     
1780     if (isInline() && !isInlineBlockOrInlineTable()) {
1781         // just calculate margins
1782         setMarginStart(styleToUse->marginStart().calcMinValue(containerLogicalWidth));
1783         setMarginEnd(styleToUse->marginEnd().calcMinValue(containerLogicalWidth));
1784         if (treatAsReplaced)
1785             setLogicalWidth(max<LayoutUnit>(logicalWidthLength.calcFloatValue(0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth()));
1786         return;
1787     }
1788
1789     // Width calculations
1790     if (treatAsReplaced)
1791         setLogicalWidth(logicalWidthLength.value() + borderAndPaddingLogicalWidth());
1792     else {
1793         // Calculate LogicalWidth
1794         setLogicalWidth(computeLogicalWidthInRegionUsing(LogicalWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage));
1795
1796         // Calculate MaxLogicalWidth
1797         if (!styleToUse->logicalMaxWidth().isUndefined()) {
1798             LayoutUnit maxLogicalWidth = computeLogicalWidthInRegionUsing(MaxLogicalWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage);
1799             if (logicalWidth() > maxLogicalWidth) {
1800                 setLogicalWidth(maxLogicalWidth);
1801                 logicalWidthLength = styleToUse->logicalMaxWidth();
1802             }
1803         }
1804
1805         // Calculate MinLogicalWidth
1806         LayoutUnit minLogicalWidth = computeLogicalWidthInRegionUsing(MinLogicalWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage);
1807         if (logicalWidth() < minLogicalWidth) {
1808             setLogicalWidth(minLogicalWidth);
1809             logicalWidthLength = styleToUse->logicalMinWidth();
1810         }
1811     }
1812
1813     // Fieldsets are currently the only objects that stretch to their minimum width.
1814     if (stretchesToMinIntrinsicLogicalWidth()) {
1815         setLogicalWidth(max(logicalWidth(), minPreferredLogicalWidth()));
1816         logicalWidthLength = Length(logicalWidth(), Fixed);
1817     }
1818
1819     // Margin calculations.
1820     if (logicalWidthLength.isAuto() || hasPerpendicularContainingBlock) {
1821         setMarginStart(styleToUse->marginStart().calcMinValue(containerLogicalWidth));
1822         setMarginEnd(styleToUse->marginEnd().calcMinValue(containerLogicalWidth));
1823     } else
1824         computeInlineDirectionMargins(cb, containerLogicalWidth, logicalWidth());
1825
1826     if (!hasPerpendicularContainingBlock && containerLogicalWidth && containerLogicalWidth != (logicalWidth() + marginStart() + marginEnd())
1827             && !isFloating() && !isInline() && !cb->isFlexibleBoxIncludingDeprecated())
1828         cb->setMarginEndForChild(this, containerLogicalWidth - logicalWidth() - cb->marginStartForChild(this));
1829 }
1830
1831 LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(LogicalWidthType widthType, LayoutUnit availableLogicalWidth,
1832     const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
1833 {
1834     LayoutUnit logicalWidthResult = logicalWidth();
1835     RenderStyle* styleToUse = style();
1836     Length logicalWidth;
1837     if (widthType == LogicalWidth)
1838         logicalWidth = styleToUse->logicalWidth();
1839     else if (widthType == MinLogicalWidth)
1840         logicalWidth = styleToUse->logicalMinWidth();
1841     else
1842         logicalWidth = styleToUse->logicalMaxWidth();
1843
1844     if (logicalWidth.isIntrinsicOrAuto()) {
1845         LayoutUnit marginStart = styleToUse->marginStart().calcMinValue(availableLogicalWidth);
1846         LayoutUnit marginEnd = styleToUse->marginEnd().calcMinValue(availableLogicalWidth);
1847         logicalWidthResult = availableLogicalWidth - marginStart - marginEnd;
1848
1849         if (shrinkToAvoidFloats() && cb->containsFloats())
1850             logicalWidthResult = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, region, offsetFromLogicalTopOfFirstPage);
1851
1852         if (sizesToIntrinsicLogicalWidth(widthType)) {
1853             logicalWidthResult = max(logicalWidthResult, minPreferredLogicalWidth());
1854             logicalWidthResult = min(logicalWidthResult, maxPreferredLogicalWidth());
1855         }
1856     } else // FIXME: If the containing block flow is perpendicular to our direction we need to use the available logical height instead.
1857         logicalWidthResult = computeBorderBoxLogicalWidth(logicalWidth.calcValue(availableLogicalWidth)); 
1858
1859     return logicalWidthResult;
1860 }
1861
1862 bool RenderBox::sizesToIntrinsicLogicalWidth(LogicalWidthType widthType) const
1863 {
1864     // Marquees in WinIE are like a mixture of blocks and inline-blocks.  They size as though they're blocks,
1865     // but they allow text to sit on the same line as the marquee.
1866     if (isFloating() || (isInlineBlockOrInlineTable() && !isHTMLMarquee()))
1867         return true;
1868
1869     // This code may look a bit strange.  Basically width:intrinsic should clamp the size when testing both
1870     // min-width and width.  max-width is only clamped if it is also intrinsic.
1871     Length logicalWidth = (widthType == MaxLogicalWidth) ? style()->logicalMaxWidth() : style()->logicalWidth();
1872     if (logicalWidth.type() == Intrinsic)
1873         return true;
1874
1875     // Children of a horizontal marquee do not fill the container by default.
1876     // FIXME: Need to deal with MAUTO value properly.  It could be vertical.
1877     // FIXME: Think about block-flow here.  Need to find out how marquee direction relates to
1878     // block-flow (as well as how marquee overflow should relate to block flow).
1879     // https://bugs.webkit.org/show_bug.cgi?id=46472
1880     if (parent()->style()->overflowX() == OMARQUEE) {
1881         EMarqueeDirection dir = parent()->style()->marqueeDirection();
1882         if (dir == MAUTO || dir == MFORWARD || dir == MBACKWARD || dir == MLEFT || dir == MRIGHT)
1883             return true;
1884     }
1885
1886     // Flexible box items should shrink wrap, so we lay them out at their intrinsic widths.
1887     // In the case of columns that have a stretch alignment, we go ahead and layout at the
1888     // stretched size to avoid an extra layout when applying alignment.
1889     if (parent()->isFlexibleBox()) {
1890         // For multiline columns, we need to apply the flex-line-pack first, so we can't stretch now.
1891         if (!parent()->style()->isColumnFlexDirection() || parent()->style()->flexWrap() != FlexWrapNone)
1892             return true;
1893         EFlexAlign itemAlign = style()->flexItemAlign();
1894         if (itemAlign != AlignStretch && (itemAlign != AlignAuto || parent()->style()->flexAlign() != AlignStretch))
1895             return true;
1896     }
1897
1898     // Flexible horizontal boxes lay out children at their intrinsic widths.  Also vertical boxes
1899     // that don't stretch their kids lay out their children at their intrinsic widths.
1900     // FIXME: Think about block-flow here.
1901     // https://bugs.webkit.org/show_bug.cgi?id=46473
1902     if (parent()->isDeprecatedFlexibleBox()
1903             && (parent()->style()->boxOrient() == HORIZONTAL || parent()->style()->boxAlign() != BSTRETCH))
1904         return true;
1905
1906     // Button, input, select, textarea, and legend treat
1907     // width value of 'auto' as 'intrinsic' unless it's in a
1908     // stretching vertical flexbox.
1909     // FIXME: Think about block-flow here.
1910     // https://bugs.webkit.org/show_bug.cgi?id=46473
1911     if (logicalWidth.type() == Auto && !(parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == VERTICAL && parent()->style()->boxAlign() == BSTRETCH) && node() && (node()->hasTagName(inputTag) || node()->hasTagName(selectTag) || node()->hasTagName(buttonTag) || node()->hasTagName(textareaTag) || node()->hasTagName(legendTag)))
1912         return true;
1913
1914     if (isHorizontalWritingMode() != containingBlock()->isHorizontalWritingMode())
1915         return true;
1916
1917     return false;
1918 }
1919
1920 void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth)
1921 {
1922     const RenderStyle* containingBlockStyle = containingBlock->style();
1923     Length marginStartLength = style()->marginStartUsing(containingBlockStyle);
1924     Length marginEndLength = style()->marginEndUsing(containingBlockStyle);
1925
1926     if (isFloating() || isInline()) {
1927         // Inline blocks/tables and floats don't have their margins increased.
1928         containingBlock->setMarginStartForChild(this, marginStartLength.calcMinValue(containerWidth));
1929         containingBlock->setMarginEndForChild(this, marginEndLength.calcMinValue(containerWidth));
1930         return;
1931     }
1932
1933     // Case One: The object is being centered in the containing block's available logical width.
1934     if ((marginStartLength.isAuto() && marginEndLength.isAuto() && childWidth < containerWidth)
1935         || (!marginStartLength.isAuto() && !marginEndLength.isAuto() && containingBlock->style()->textAlign() == WEBKIT_CENTER)) {
1936         containingBlock->setMarginStartForChild(this, max<LayoutUnit>(0, (containerWidth - childWidth) / 2));
1937         containingBlock->setMarginEndForChild(this, containerWidth - childWidth - containingBlock->marginStartForChild(this));
1938         return;
1939     } 
1940     
1941     // Case Two: The object is being pushed to the start of the containing block's available logical width.
1942     if (marginEndLength.isAuto() && childWidth < containerWidth) {
1943         containingBlock->setMarginStartForChild(this, marginStartLength.calcValue(containerWidth));
1944         containingBlock->setMarginEndForChild(this, containerWidth - childWidth - containingBlock->marginStartForChild(this));
1945         return;
1946     } 
1947     
1948     // Case Three: The object is being pushed to the end of the containing block's available logical width.
1949     bool pushToEndFromTextAlign = !marginEndLength.isAuto() && ((!containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_LEFT)
1950         || (containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_RIGHT));
1951     if ((marginStartLength.isAuto() && childWidth < containerWidth) || pushToEndFromTextAlign) {
1952         containingBlock->setMarginEndForChild(this, marginEndLength.calcValue(containerWidth));
1953         containingBlock->setMarginStartForChild(this, containerWidth - childWidth - containingBlock->marginEndForChild(this));
1954         return;
1955     } 
1956     
1957     // Case Four: Either no auto margins, or our width is >= the container width (css2.1, 10.3.3).  In that case
1958     // auto margins will just turn into 0.
1959     containingBlock->setMarginStartForChild(this, marginStartLength.calcMinValue(containerWidth));
1960     containingBlock->setMarginEndForChild(this, marginEndLength.calcMinValue(containerWidth));
1961 }
1962
1963 RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, RenderBoxRegionInfoFlags cacheFlag) const
1964 {
1965     // Make sure nobody is trying to call this with a null region.
1966     if (!region)
1967         return 0;
1968
1969     // If we have computed our width in this region already, it will be cached, and we can
1970     // just return it.
1971     RenderBoxRegionInfo* boxInfo = region->renderBoxRegionInfo(this);
1972     if (boxInfo && cacheFlag == CacheRenderBoxRegionInfo)
1973         return boxInfo;
1974
1975     // No cached value was found, so we have to compute our insets in this region.
1976     // FIXME: For now we limit this computation to normal RenderBlocks. Future patches will expand
1977     // support to cover all boxes.
1978     if (!inRenderFlowThread() || isFloating() || isReplaced() || isInline() || hasColumns()
1979         || isTableCell() || !isBlockFlow() || isRenderFlowThread())
1980         return 0;
1981
1982     // FIXME: It's gross to cast away the const, but it would be a huge refactoring to
1983     // change all width computation to avoid updating any member variables, and it would be pretty lame to
1984     // make all the variables mutable as well.
1985     RenderFlowThread* flowThread = enclosingRenderFlowThread();
1986     if (flowThread->style()->writingMode() != style()->writingMode())
1987         return 0;
1988
1989     LayoutUnit oldLogicalWidth = logicalWidth();
1990     LayoutUnit oldLogicalLeft = logicalLeft();
1991     LayoutUnit oldMarginStart = marginStart();
1992     LayoutUnit oldMarginEnd = marginEnd();
1993
1994     RenderBox* mutableBox = const_cast<RenderBox*>(this);
1995     
1996     mutableBox->computeLogicalWidthInRegion(region, offsetFromLogicalTopOfFirstPage);
1997
1998     // Now determine the insets based off where this object is supposed to be positioned.
1999     RenderBlock* cb = containingBlock();
2000     RenderRegion* clampedContainingBlockRegion = cb->clampToStartAndEndRegions(region);
2001     RenderBoxRegionInfo* containingBlockInfo = cb->renderBoxRegionInfo(clampedContainingBlockRegion,
2002         offsetFromLogicalTopOfFirstPage - logicalTop());
2003     LayoutUnit containingBlockLogicalWidth = cb->logicalWidth();
2004     LayoutUnit containingBlockLogicalWidthInRegion = containingBlockInfo ? containingBlockInfo->logicalWidth() : containingBlockLogicalWidth;
2005     
2006     LayoutUnit marginStartInRegion = marginStart();
2007     LayoutUnit startMarginDelta = marginStartInRegion - oldMarginStart;
2008     LayoutUnit logicalWidthInRegion = logicalWidth();
2009     LayoutUnit logicalLeftInRegion = logicalLeft();
2010     LayoutUnit widthDelta = logicalWidthInRegion - oldLogicalWidth;
2011     LayoutUnit logicalLeftDelta = isPositioned() ? logicalLeftInRegion - oldLogicalLeft : startMarginDelta;
2012     LayoutUnit logicalRightInRegion = containingBlockLogicalWidthInRegion - (logicalLeftInRegion + logicalWidthInRegion);
2013     LayoutUnit oldLogicalRight = containingBlockLogicalWidth - (oldLogicalLeft + oldLogicalWidth);
2014     LayoutUnit logicalRightDelta = isPositioned() ? logicalRightInRegion - oldLogicalRight : startMarginDelta;
2015
2016     // Set our values back.
2017     mutableBox->setLogicalWidth(oldLogicalWidth);
2018     mutableBox->setLogicalLeft(oldLogicalLeft);
2019     mutableBox->setMarginStart(oldMarginStart);
2020     mutableBox->setMarginEnd(oldMarginEnd);
2021
2022     LayoutUnit logicalLeftOffset = 0;
2023     
2024     if (!isPositioned() && avoidsFloats() && cb->containsFloats()) {
2025         LayoutUnit startPositionDelta = cb->computeStartPositionDeltaForChildAvoidingFloats(this, marginStartInRegion, logicalWidthInRegion,
2026             region, offsetFromLogicalTopOfFirstPage);
2027         if (cb->style()->isLeftToRightDirection())
2028             logicalLeftDelta += startPositionDelta;
2029         else
2030             logicalRightDelta += startPositionDelta;
2031     }
2032
2033     if (cb->style()->isLeftToRightDirection())
2034         logicalLeftOffset += logicalLeftDelta;
2035     else
2036         logicalLeftOffset -= (widthDelta + logicalRightDelta);
2037     
2038     LayoutUnit logicalRightOffset = logicalWidth() - (logicalLeftOffset + logicalWidthInRegion);
2039     bool isShifted = (containingBlockInfo && containingBlockInfo->isShifted())
2040             || (style()->isLeftToRightDirection() && logicalLeftOffset)
2041             || (!style()->isLeftToRightDirection() && logicalRightOffset);
2042
2043     // FIXME: Although it's unlikely, these boxes can go outside our bounds, and so we will need to incorporate them into overflow.
2044     if (cacheFlag == CacheRenderBoxRegionInfo)
2045         return region->setRenderBoxRegionInfo(this, logicalLeftOffset, logicalWidthInRegion, isShifted);
2046     return new RenderBoxRegionInfo(logicalLeftOffset, logicalWidthInRegion, isShifted);
2047 }
2048
2049 void RenderBox::computeLogicalHeight()
2050 {
2051     // Cell height is managed by the table and inline non-replaced elements do not support a height property.
2052     if (isTableCell() || (isInline() && !isReplaced()))
2053         return;
2054
2055     Length h;
2056     if (isPositioned())
2057         computePositionedLogicalHeight();
2058     else {
2059         RenderBlock* cb = containingBlock();
2060         bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
2061     
2062         if (!hasPerpendicularContainingBlock)
2063             computeBlockDirectionMargins(cb);
2064
2065         // For tables, calculate margins only.
2066         if (isTable()) {
2067             if (hasPerpendicularContainingBlock)
2068                 computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), logicalHeight());
2069             return;
2070         }
2071
2072         // FIXME: Account for block-flow in flexible boxes.
2073         // https://bugs.webkit.org/show_bug.cgi?id=46418
2074         bool inHorizontalBox = parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL;
2075         bool stretching = parent()->style()->boxAlign() == BSTRETCH;
2076         bool treatAsReplaced = shouldComputeSizeAsReplaced() && (!inHorizontalBox || !stretching);
2077         bool checkMinMaxHeight = false;
2078
2079         // The parent box is flexing us, so it has increased or decreased our height.  We have to
2080         // grab our cached flexible height.
2081         // FIXME: Account for block-flow in flexible boxes.
2082         // https://bugs.webkit.org/show_bug.cgi?id=46418
2083         RenderStyle* styleToUse = style();
2084         if (hasOverrideHeight() && parent()->isFlexibleBoxIncludingDeprecated())
2085             h = Length(overrideHeight() - borderAndPaddingLogicalHeight(), Fixed);
2086         else if (treatAsReplaced)
2087             h = Length(computeReplacedLogicalHeight(), Fixed);
2088         else {
2089             h = styleToUse->logicalHeight();
2090             checkMinMaxHeight = true;
2091         }
2092
2093         // Block children of horizontal flexible boxes fill the height of the box.
2094         // FIXME: Account for block-flow in flexible boxes.
2095         // https://bugs.webkit.org/show_bug.cgi?id=46418
2096         if (h.isAuto() && parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
2097                 && parent()->isStretchingChildren()) {
2098             h = Length(parentBox()->contentLogicalHeight() - marginBefore() - marginAfter() - borderAndPaddingLogicalHeight(), Fixed);
2099             checkMinMaxHeight = false;
2100         }
2101
2102         LayoutUnit heightResult;
2103         if (checkMinMaxHeight) {
2104             heightResult = computeLogicalHeightUsing(styleToUse->logicalHeight());
2105             if (heightResult == -1)
2106                 heightResult = logicalHeight();
2107             LayoutUnit minH = computeLogicalHeightUsing(styleToUse->logicalMinHeight()); // Leave as -1 if unset.
2108             LayoutUnit maxH = styleToUse->logicalMaxHeight().isUndefined() ? heightResult : computeLogicalHeightUsing(styleToUse->logicalMaxHeight());
2109             if (maxH == -1)
2110                 maxH = heightResult;
2111             heightResult = min(maxH, heightResult);
2112             heightResult = max(minH, heightResult);
2113         } else {
2114             // The only times we don't check min/max height are when a fixed length has
2115             // been given as an override.  Just use that.  The value has already been adjusted
2116             // for box-sizing.
2117             heightResult = h.value() + borderAndPaddingLogicalHeight();
2118         }
2119
2120         setLogicalHeight(heightResult);
2121         
2122         if (hasPerpendicularContainingBlock)
2123             computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), heightResult);
2124     }
2125
2126     // WinIE quirk: The <html> block always fills the entire canvas in quirks mode.  The <body> always fills the
2127     // <html> block in quirks mode.  Only apply this quirk if the block is normal flow and no height
2128     // is specified. When we're printing, we also need this quirk if the body or root has a percentage 
2129     // height since we don't set a height in RenderView when we're printing. So without this quirk, the 
2130     // height has nothing to be a percentage of, and it ends up being 0. That is bad.
2131     bool paginatedContentNeedsBaseHeight = document()->printing() && h.isPercent()
2132         && (isRoot() || (isBody() && document()->documentElement()->renderer()->style()->logicalHeight().isPercent()));
2133     if (stretchesToViewport() || paginatedContentNeedsBaseHeight) {
2134         // FIXME: Finish accounting for block flow here.
2135         // https://bugs.webkit.org/show_bug.cgi?id=46603
2136         LayoutUnit margins = collapsedMarginBefore() + collapsedMarginAfter();
2137         LayoutUnit visHeight;
2138         if (document()->printing())
2139             visHeight = static_cast<LayoutUnit>(view()->pageLogicalHeight());
2140         else  {
2141             if (isHorizontalWritingMode())
2142                 visHeight = view()->viewHeight();
2143             else
2144                 visHeight = view()->viewWidth();
2145         }
2146         if (isRoot())
2147             setLogicalHeight(max(logicalHeight(), visHeight - margins));
2148         else {
2149             LayoutUnit marginsBordersPadding = margins + parentBox()->marginBefore() + parentBox()->marginAfter() + parentBox()->borderAndPaddingLogicalHeight();
2150             setLogicalHeight(max(logicalHeight(), visHeight - marginsBordersPadding));
2151         }
2152     }
2153 }
2154
2155 LayoutUnit RenderBox::computeLogicalHeightUsing(const Length& height)
2156 {
2157     LayoutUnit logicalHeight = computeContentLogicalHeightUsing(height);
2158     if (logicalHeight != -1)
2159         logicalHeight = computeBorderBoxLogicalHeight(logicalHeight);
2160     return logicalHeight;
2161 }
2162
2163 LayoutUnit RenderBox::computeContentLogicalHeightUsing(const Length& height)
2164 {
2165     LayoutUnit logicalHeight = -1;
2166     if (!height.isAuto()) {
2167         if (height.isFixed())
2168             logicalHeight = height.value();
2169         else if (height.isPercent())
2170             logicalHeight = computePercentageLogicalHeight(height);
2171     }
2172     return logicalHeight;
2173 }
2174
2175 LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height)
2176 {
2177     LayoutUnit result = -1;
2178     
2179     // In quirks mode, blocks with auto height are skipped, and we keep looking for an enclosing
2180     // block that may have a specified height and then use it. In strict mode, this violates the
2181     // specification, which states that percentage heights just revert to auto if the containing
2182     // block has an auto height. We still skip anonymous containing blocks in both modes, though, and look
2183     // only at explicit containers.
2184     bool skippedAutoHeightContainingBlock = false;
2185     RenderBlock* cb = containingBlock();
2186     while (!cb->isRenderView() && !cb->isBody() && !cb->isTableCell() && !cb->isPositioned() && cb->style()->logicalHeight().isAuto()) {
2187         if (!document()->inQuirksMode() && !cb->isAnonymousBlock())
2188             break;
2189         skippedAutoHeightContainingBlock = true;
2190         cb = cb->containingBlock();
2191         cb->addPercentHeightDescendant(this);
2192     }
2193
2194     RenderStyle* cbstyle = cb->style();
2195
2196     // A positioned element that specified both top/bottom or that specifies height should be treated as though it has a height
2197     // explicitly specified that can be used for any percentage computations.
2198     // FIXME: We can't just check top/bottom here.
2199     // https://bugs.webkit.org/show_bug.cgi?id=46500
2200     bool isPositionedWithSpecifiedHeight = cb->isPositioned() && (!cbstyle->logicalHeight().isAuto() || (!cbstyle->top().isAuto() && !cbstyle->bottom().isAuto()));
2201
2202     bool includeBorderPadding = isTable();
2203
2204     // Table cells violate what the CSS spec says to do with heights.  Basically we
2205     // don't care if the cell specified a height or not.  We just always make ourselves
2206     // be a percentage of the cell's current content height.
2207     if (cb->isTableCell()) {
2208         if (!skippedAutoHeightContainingBlock) {
2209             if (!cb->hasOverrideHeight()) {
2210                 // Normally we would let the cell size intrinsically, but scrolling overflow has to be
2211                 // treated differently, since WinIE lets scrolled overflow regions shrink as needed.
2212                 // While we can't get all cases right, we can at least detect when the cell has a specified
2213                 // height or when the table has a specified height.  In these cases we want to initially have
2214                 // no size and allow the flexing of the table or the cell to its specified height to cause us
2215                 // to grow to fill the space.  This could end up being wrong in some cases, but it is
2216                 // preferable to the alternative (sizing intrinsically and making the row end up too big).
2217                 RenderTableCell* cell = toRenderTableCell(cb);
2218                 if (scrollsOverflowY() && (!cell->style()->logicalHeight().isAuto() || !cell->table()->style()->logicalHeight().isAuto()))
2219                     return 0;
2220                 return -1;
2221             }
2222             result = cb->overrideHeight();
2223             includeBorderPadding = true;
2224         }
2225     }
2226     // Otherwise we only use our percentage height if our containing block had a specified
2227     // height.
2228     else if (cbstyle->logicalHeight().isFixed())
2229         result = cb->computeContentBoxLogicalHeight(cbstyle->logicalHeight().value());
2230     else if (cbstyle->logicalHeight().isPercent() && !isPositionedWithSpecifiedHeight) {
2231         // We need to recur and compute the percentage height for our containing block.
2232         result = cb->computePercentageLogicalHeight(cbstyle->logicalHeight());
2233         if (result != -1)
2234             result = cb->computeContentBoxLogicalHeight(result);
2235     } else if (cb->isRenderView() || (cb->isBody() && document()->inQuirksMode()) || isPositionedWithSpecifiedHeight) {
2236         // Don't allow this to affect the block' height() member variable, since this
2237         // can get called while the block is still laying out its kids.
2238         LayoutUnit oldHeight = cb->logicalHeight();
2239         cb->computeLogicalHeight();
2240         result = cb->contentLogicalHeight();
2241         cb->setLogicalHeight(oldHeight);
2242     } else if (cb->isRoot() && isPositioned())
2243         // Match the positioned objects behavior, which is that positioned objects will fill their viewport
2244         // always.  Note we could only hit this case by recurring into computePercentageLogicalHeight on a positioned containing block.
2245         result = cb->computeContentBoxLogicalHeight(cb->availableLogicalHeight());
2246
2247     if (result != -1) {
2248         result = height.calcValue(result);
2249         if (includeBorderPadding) {
2250             // It is necessary to use the border-box to match WinIE's broken
2251             // box model.  This is essential for sizing inside
2252             // table cells using percentage heights.
2253             result -= borderAndPaddingLogicalHeight();
2254             result = max<LayoutUnit>(0, result);
2255         }
2256     }
2257     return result;
2258 }
2259
2260 LayoutUnit RenderBox::computeReplacedLogicalWidth(bool includeMaxWidth) const
2261 {
2262     return computeReplacedLogicalWidthRespectingMinMaxWidth(computeReplacedLogicalWidthUsing(style()->logicalWidth()), includeMaxWidth);
2263 }
2264
2265 LayoutUnit RenderBox::computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit logicalWidth, bool includeMaxWidth) const
2266 {
2267     LayoutUnit minLogicalWidth = computeReplacedLogicalWidthUsing(style()->logicalMinWidth());
2268     LayoutUnit maxLogicalWidth = !includeMaxWidth || style()->logicalMaxWidth().isUndefined() ? logicalWidth : computeReplacedLogicalWidthUsing(style()->logicalMaxWidth());
2269     return max(minLogicalWidth, min(logicalWidth, maxLogicalWidth));
2270 }
2271
2272 LayoutUnit RenderBox::computeReplacedLogicalWidthUsing(Length logicalWidth) const
2273 {
2274     switch (logicalWidth.type()) {
2275         case Fixed:
2276             return computeContentBoxLogicalWidth(logicalWidth.value());
2277         case Percent: {
2278             // FIXME: containingBlockLogicalWidthForContent() is wrong if the replaced element's block-flow is perpendicular to the
2279             // containing block's block-flow.
2280             // https://bugs.webkit.org/show_bug.cgi?id=46496
2281             const LayoutUnit cw = isPositioned() ? containingBlockLogicalWidthForPositioned(toRenderBoxModelObject(container())) : containingBlockLogicalWidthForContent();
2282             if (cw > 0)
2283                 return computeContentBoxLogicalWidth(logicalWidth.calcMinValue(cw));
2284         }
2285         // fall through
2286         default:
2287             return intrinsicLogicalWidth();
2288      }
2289 }
2290
2291 LayoutUnit RenderBox::computeReplacedLogicalHeight() const
2292 {
2293     return computeReplacedLogicalHeightRespectingMinMaxHeight(computeReplacedLogicalHeightUsing(style()->logicalHeight()));
2294 }
2295
2296 LayoutUnit RenderBox::computeReplacedLogicalHeightRespectingMinMaxHeight(LayoutUnit logicalHeight) const
2297 {
2298     LayoutUnit minLogicalHeight = computeReplacedLogicalHeightUsing(style()->logicalMinHeight());
2299     LayoutUnit maxLogicalHeight = style()->logicalMaxHeight().isUndefined() ? logicalHeight : computeReplacedLogicalHeightUsing(style()->logicalMaxHeight());
2300     return max(minLogicalHeight, min(logicalHeight, maxLogicalHeight));
2301 }
2302
2303 LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(Length logicalHeight) const
2304 {
2305     switch (logicalHeight.type()) {
2306         case Fixed:
2307             return computeContentBoxLogicalHeight(logicalHeight.value());
2308         case Percent:
2309         {
2310             RenderObject* cb = isPositioned() ? container() : containingBlock();
2311             while (cb->isAnonymous()) {
2312                 cb = cb->containingBlock();
2313                 toRenderBlock(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this));
2314             }
2315
2316             // FIXME: This calculation is not patched for block-flow yet.
2317             // https://bugs.webkit.org/show_bug.cgi?id=46500
2318             if (cb->isPositioned() && cb->style()->height().isAuto() && !(cb->style()->top().isAuto() || cb->style()->bottom().isAuto())) {
2319                 ASSERT(cb->isRenderBlock());
2320                 RenderBlock* block = toRenderBlock(cb);
2321                 LayoutUnit oldHeight = block->height();
2322                 block->computeLogicalHeight();
2323                 LayoutUnit newHeight = block->computeContentBoxLogicalHeight(block->contentHeight());
2324                 block->setHeight(oldHeight);
2325                 return computeContentBoxLogicalHeight(logicalHeight.calcValue(newHeight));
2326             }
2327             
2328             // FIXME: availableLogicalHeight() is wrong if the replaced element's block-flow is perpendicular to the
2329             // containing block's block-flow.
2330             // https://bugs.webkit.org/show_bug.cgi?id=46496
2331             LayoutUnit availableHeight;
2332             if (isPositioned())
2333                 availableHeight = containingBlockLogicalHeightForPositioned(toRenderBoxModelObject(cb));
2334             else {
2335                 availableHeight =  toRenderBox(cb)->availableLogicalHeight();
2336                 // It is necessary to use the border-box to match WinIE's broken
2337                 // box model.  This is essential for sizing inside
2338                 // table cells using percentage heights.
2339                 // FIXME: This needs to be made block-flow-aware.  If the cell and image are perpendicular block-flows, this isn't right.
2340                 // https://bugs.webkit.org/show_bug.cgi?id=46997
2341                 while (cb && !cb->isRenderView() && (cb->style()->logicalHeight().isAuto() || cb->style()->logicalHeight().isPercent())) {
2342                     if (cb->isTableCell()) {
2343                         // Don't let table cells squeeze percent-height replaced elements
2344                         // <http://bugs.webkit.org/show_bug.cgi?id=15359>
2345                         availableHeight = max(availableHeight, intrinsicLogicalHeight());
2346                         return logicalHeight.calcValue(availableHeight - borderAndPaddingLogicalHeight());
2347                     }
2348                     cb = cb->containingBlock();
2349                 }
2350             }
2351             return computeContentBoxLogicalHeight(logicalHeight.calcValue(availableHeight));
2352         }
2353         default:
2354             return intrinsicLogicalHeight();
2355     }
2356 }
2357
2358 LayoutUnit RenderBox::availableLogicalHeight() const
2359 {
2360     return availableLogicalHeightUsing(style()->logicalHeight());
2361 }
2362
2363 LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h) const
2364 {
2365     if (h.isFixed())
2366         return computeContentBoxLogicalHeight(h.value());
2367
2368     if (isRenderView())
2369         return isHorizontalWritingMode() ? toRenderView(this)->frameView()->visibleHeight() : toRenderView(this)->frameView()->visibleWidth();
2370
2371     // We need to stop here, since we don't want to increase the height of the table
2372     // artificially.  We're going to rely on this cell getting expanded to some new
2373     // height, and then when we lay out again we'll use the calculation below.
2374     if (isTableCell() && (h.isAuto() || h.isPercent()))
2375         return overrideHeight() - borderAndPaddingLogicalWidth();
2376
2377     if (h.isPercent()) {
2378         LayoutUnit availableHeight;
2379         // https://bugs.webkit.org/show_bug.cgi?id=64046
2380         // For absolutely positioned elements whose containing block is based on a block-level element,
2381         // the percentage is calculated with respect to the height of the padding box of that element
2382         if (isPositioned())
2383             availableHeight = containingBlockLogicalHeightForPositioned(containingBlock());
2384         else
2385             availableHeight = containingBlock()->availableLogicalHeight();
2386         return computeContentBoxLogicalHeight(h.calcValue(availableHeight));
2387     }
2388
2389     // FIXME: We can't just check top/bottom here.
2390     // https://bugs.webkit.org/show_bug.cgi?id=46500
2391     if (isRenderBlock() && isPositioned() && style()->height().isAuto() && !(style()->top().isAuto() || style()->bottom().isAuto())) {
2392         RenderBlock* block = const_cast<RenderBlock*>(toRenderBlock(this));
2393         LayoutUnit oldHeight = block->logicalHeight();
2394         block->computeLogicalHeight();
2395         LayoutUnit newHeight = block->computeContentBoxLogicalHeight(block->contentLogicalHeight());
2396         block->setLogicalHeight(oldHeight);
2397         return computeContentBoxLogicalHeight(newHeight);
2398     }
2399
2400     return containingBlock()->availableLogicalHeight();
2401 }
2402
2403 void RenderBox::computeBlockDirectionMargins(RenderBlock* containingBlock)
2404 {
2405     if (isTableCell()) {
2406         // FIXME: Not right if we allow cells to have different directionality than the table.  If we do allow this, though,
2407         // we may just do it with an extra anonymous block inside the cell.
2408         setMarginBefore(0);
2409         setMarginAfter(0);
2410         return;
2411     }
2412
2413     // Margins are calculated with respect to the logical width of
2414     // the containing block (8.3)
2415     LayoutUnit cw = containingBlockLogicalWidthForContent();
2416
2417     RenderStyle* containingBlockStyle = containingBlock->style();
2418     containingBlock->setMarginBeforeForChild(this, style()->marginBeforeUsing(containingBlockStyle).calcMinValue(cw));
2419     containingBlock->setMarginAfterForChild(this, style()->marginAfterUsing(containingBlockStyle).calcMinValue(cw));
2420 }
2421
2422 LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* region,
2423     LayoutUnit offsetFromLogicalTopOfFirstPage, bool checkForPerpendicularWritingMode) const
2424 {
2425     // Container for position:fixed is the frame.
2426     Frame* frame = view() ? view()->frame(): 0;
2427     FrameView* frameView = view() ? view()->frameView() : 0;
2428     if (fixedElementLaysOutRelativeToFrame(frame, frameView))
2429         return (view()->isHorizontalWritingMode() ? frameView->visibleWidth() : frameView->visibleHeight()) / frame->frameScaleFactor();
2430
2431     if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
2432         return containingBlockLogicalHeightForPositioned(containingBlock, false);
2433
2434     if (containingBlock->isBox()) {
2435         const RenderBlock* cb = toRenderBlock(containingBlock);
2436         LayoutUnit result = cb->clientLogicalWidth();
2437         if (inRenderFlowThread()) {
2438             RenderBoxRegionInfo* boxInfo = 0;
2439             if (!region) {
2440                 if (containingBlock->isRenderFlowThread() && !checkForPerpendicularWritingMode)
2441                     return toRenderFlowThread(containingBlock)->contentLogicalWidthOfFirstRegion();
2442                 if (isWritingModeRoot()) {
2443                     LayoutUnit cbPageOffset = offsetFromLogicalTopOfFirstPage - logicalTop();
2444                     RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
2445                     cbRegion = cb->clampToStartAndEndRegions(cbRegion);
2446                     boxInfo = cb->renderBoxRegionInfo(cbRegion, cbPageOffset);
2447                 }
2448             } else if (region && enclosingRenderFlowThread()->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode()) {
2449                 RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region);
2450                 boxInfo = cb->renderBoxRegionInfo(containingBlockRegion, offsetFromLogicalTopOfFirstPage - logicalTop());
2451             }
2452             if (boxInfo)
2453                 return max<LayoutUnit>(0, result - (cb->logicalWidth() - boxInfo->logicalWidth()));
2454         }
2455         return result;
2456     }
2457
2458     ASSERT(containingBlock->isRenderInline() && containingBlock->isRelPositioned());
2459
2460     const RenderInline* flow = toRenderInline(containingBlock);
2461     InlineFlowBox* first = flow->firstLineBox();
2462     InlineFlowBox* last = flow->lastLineBox();
2463
2464     // If the containing block is empty, return a width of 0.
2465     if (!first || !last)
2466         return 0;
2467
2468     LayoutUnit fromLeft;
2469     LayoutUnit fromRight;
2470     if (containingBlock->style()->isLeftToRightDirection()) {
2471         fromLeft = first->logicalLeft() + first->borderLogicalLeft();
2472         fromRight = last->logicalLeft() + last->logicalWidth() - last->borderLogicalRight();
2473     } else {
2474         fromRight = first->logicalLeft() + first->logicalWidth() - first->borderLogicalRight();
2475         fromLeft = last->logicalLeft() + last->borderLogicalLeft();
2476     }
2477
2478     return max<LayoutUnit>(0, fromRight - fromLeft);
2479 }
2480
2481 LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode) const
2482 {
2483     Frame* frame = view() ? view()->frame(): 0;
2484     FrameView* frameView = view() ? view()->frameView() : 0;
2485     if (fixedElementLaysOutRelativeToFrame(frame, frameView))
2486         return (view()->isHorizontalWritingMode() ? frameView->visibleHeight() : frameView->visibleWidth()) / frame->frameScaleFactor();
2487
2488     if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
2489         return containingBlockLogicalWidthForPositioned(containingBlock, 0, 0, false);
2490
2491     if (containingBlock->isBox()) {
2492         const RenderBlock* cb = toRenderBlock(containingBlock);
2493         LayoutUnit result = cb->clientLogicalHeight();
2494         if (inRenderFlowThread() && containingBlock->isRenderFlowThread() && enclosingRenderFlowThread()->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode())
2495             return toRenderFlowThread(containingBlock)->contentLogicalHeightOfFirstRegion();
2496         return result;
2497     }
2498         
2499     ASSERT(containingBlock->isRenderInline() && containingBlock->isRelPositioned());
2500
2501     const RenderInline* flow = toRenderInline(containingBlock);
2502     InlineFlowBox* first = flow->firstLineBox();
2503     InlineFlowBox* last = flow->lastLineBox();
2504
2505     // If the containing block is empty, return a height of 0.
2506     if (!first || !last)
2507         return 0;
2508
2509     LayoutUnit heightResult;
2510     LayoutRect boundingBox = flow->linesBoundingBox();
2511     if (containingBlock->isHorizontalWritingMode())
2512         heightResult = boundingBox.height();
2513     else
2514         heightResult = boundingBox.width();
2515     heightResult -= (containingBlock->borderBefore() + containingBlock->borderAfter());
2516     return heightResult;
2517 }
2518
2519 static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRight, const RenderBox* child, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth, RenderRegion* region)
2520 {
2521     if (!logicalLeft.isAuto() || !logicalRight.isAuto())
2522         return;
2523
2524     // FIXME: The static distance computation has not been patched for mixed writing modes yet.
2525     if (child->parent()->style()->direction() == LTR) {
2526         LayoutUnit staticPosition = child->layer()->staticInlinePosition() - containerBlock->borderLogicalLeft();
2527         for (RenderObject* curr = child->parent(); curr && curr != containerBlock; curr = curr->container()) {
2528             if (curr->isBox()) {
2529                 staticPosition += toRenderBox(curr)->logicalLeft();
2530                 if (region && curr->isRenderBlock()) {
2531                     const RenderBlock* cb = toRenderBlock(curr);
2532                     region = cb->clampToStartAndEndRegions(region);
2533                     RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region, region->offsetFromLogicalTopOfFirstPage());
2534                     if (boxInfo)
2535                         staticPosition += boxInfo->logicalLeft();
2536                 }
2537             }
2538         }
2539         logicalLeft.setValue(Fixed, staticPosition);
2540     } else {
2541         RenderBox* enclosingBox = child->parent()->enclosingBox();
2542         LayoutUnit staticPosition = child->layer()->staticInlinePosition() + containerLogicalWidth + containerBlock->borderLogicalLeft();
2543         for (RenderObject* curr = enclosingBox; curr; curr = curr->container()) {
2544             if (curr->isBox()) {
2545                 if (curr != containerBlock)
2546                     staticPosition -= toRenderBox(curr)->logicalLeft();
2547                 if (curr == enclosingBox)
2548                     staticPosition -= enclosingBox->logicalWidth();
2549                 if (region && curr->isRenderBlock()) {
2550                      const RenderBlock* cb = toRenderBlock(curr);
2551                      region = cb->clampToStartAndEndRegions(region);
2552                      RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region, region->offsetFromLogicalTopOfFirstPage());
2553                      if (boxInfo) {
2554                         if (curr != containerBlock)
2555                             staticPosition -= cb->logicalWidth() - (boxInfo->logicalLeft() + boxInfo->logicalWidth());
2556                         if (curr == enclosingBox)
2557                             staticPosition += enclosingBox->logicalWidth() - boxInfo->logicalWidth();
2558                     }
2559                 }
2560             }
2561             if (curr == containerBlock)
2562                 break;
2563         }
2564         logicalRight.setValue(Fixed, staticPosition);
2565     }
2566 }
2567
2568 void RenderBox::computePositionedLogicalWidth(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
2569 {
2570     if (isReplaced()) {
2571         computePositionedLogicalWidthReplaced(); // FIXME: Patch for regions when we add replaced element support.
2572         return;
2573     }
2574
2575     // QUESTIONS
2576     // FIXME 1: Should we still deal with these the cases of 'left' or 'right' having
2577     // the type 'static' in determining whether to calculate the static distance?
2578     // NOTE: 'static' is not a legal value for 'left' or 'right' as of CSS 2.1.
2579
2580     // FIXME 2: Can perhaps optimize out cases when max-width/min-width are greater
2581     // than or less than the computed width().  Be careful of box-sizing and
2582     // percentage issues.
2583
2584     // The following is based off of the W3C Working Draft from April 11, 2006 of
2585     // CSS 2.1: Section 10.3.7 "Absolutely positioned, non-replaced elements"
2586     // <http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width>
2587     // (block-style-comments in this function and in computePositionedLogicalWidthUsing()
2588     // correspond to text from the spec)
2589
2590
2591     // We don't use containingBlock(), since we may be positioned by an enclosing
2592     // relative positioned inline.
2593     const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
2594     
2595     const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, region, offsetFromLogicalTopOfFirstPage);
2596
2597     // Use the container block's direction except when calculating the static distance
2598     // This conforms with the reference results for abspos-replaced-width-margin-000.htm
2599     // of the CSS 2.1 test suite
2600     TextDirection containerDirection = containerBlock->style()->direction();
2601
2602     bool isHorizontal = isHorizontalWritingMode();
2603     const LayoutUnit bordersPlusPadding = borderAndPaddingLogicalWidth();
2604     const Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop();
2605     const Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom();
2606     LayoutUnit& marginLogicalLeftAlias = isHorizontal ? m_marginLeft : m_marginTop;
2607     LayoutUnit& marginLogicalRightAlias = isHorizontal ? m_marginRight : m_marginBottom;
2608
2609     Length logicalLeftLength = style()->logicalLeft();
2610     Length logicalRightLength = style()->logicalRight();
2611
2612     /*---------------------------------------------------------------------------*\
2613      * For the purposes of this section and the next, the term "static position"
2614      * (of an element) refers, roughly, to the position an element would have had
2615      * in the normal flow. More precisely:
2616      *
2617      * * The static position for 'left' is the distance from the left edge of the
2618      *   containing block to the left margin edge of a hypothetical box that would
2619      *   have been the first box of the element if its 'position' property had
2620      *   been 'static' and 'float' had been 'none'. The value is negative if the
2621      *   hypothetical box is to the left of the containing block.
2622      * * The static position for 'right' is the distance from the right edge of the
2623      *   containing block to the right margin edge of the same hypothetical box as
2624      *   above. The value is positive if the hypothetical box is to the left of the
2625      *   containing block's edge.
2626      *
2627      * But rather than actually calculating the dimensions of that hypothetical box,
2628      * user agents are free to make a guess at its probable position.
2629      *
2630      * For the purposes of calculating the static position, the containing block of
2631      * fixed positioned elements is the initial containing block instead of the
2632      * viewport, and all scrollable boxes should be assumed to be scrolled to their
2633      * origin.
2634     \*---------------------------------------------------------------------------*/
2635
2636     // see FIXME 1
2637     // Calculate the static distance if needed.
2638     computeInlineStaticDistance(logicalLeftLength, logicalRightLength, this, containerBlock, containerLogicalWidth, region);
2639     
2640     // Calculate constraint equation values for 'width' case.
2641     LayoutUnit logicalWidthResult;
2642     LayoutUnit logicalLeftResult;
2643     computePositionedLogicalWidthUsing(style()->logicalWidth(), containerBlock, containerDirection,
2644                                        containerLogicalWidth, bordersPlusPadding,
2645                                        logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
2646                                        logicalWidthResult, marginLogicalLeftAlias, marginLogicalRightAlias, logicalLeftResult);
2647     setLogicalWidth(logicalWidthResult);
2648     setLogicalLeft(logicalLeftResult);
2649
2650     // Calculate constraint equation values for 'max-width' case.
2651     if (!style()->logicalMaxWidth().isUndefined()) {
2652         LayoutUnit maxLogicalWidth;
2653         LayoutUnit maxMarginLogicalLeft;
2654         LayoutUnit maxMarginLogicalRight;
2655         LayoutUnit maxLogicalLeftPos;
2656
2657         computePositionedLogicalWidthUsing(style()->logicalMaxWidth(), containerBlock, containerDirection,
2658                                            containerLogicalWidth, bordersPlusPadding,
2659                                            logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
2660                                            maxLogicalWidth, maxMarginLogicalLeft, maxMarginLogicalRight, maxLogicalLeftPos);
2661
2662         if (logicalWidth() > maxLogicalWidth) {
2663             setLogicalWidth(maxLogicalWidth);
2664             marginLogicalLeftAlias = maxMarginLogicalLeft;
2665             marginLogicalRightAlias = maxMarginLogicalRight;
2666             setLogicalLeft(maxLogicalLeftPos);
2667         }
2668     }
2669
2670     // Calculate constraint equation values for 'min-width' case.
2671     if (!style()->logicalMinWidth().isZero()) {
2672         LayoutUnit minLogicalWidth;
2673         LayoutUnit minMarginLogicalLeft;
2674         LayoutUnit minMarginLogicalRight;
2675         LayoutUnit minLogicalLeftPos;
2676
2677         computePositionedLogicalWidthUsing(style()->logicalMinWidth(), containerBlock, containerDirection,
2678                                            containerLogicalWidth, bordersPlusPadding,
2679                                            logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
2680                                            minLogicalWidth, minMarginLogicalLeft, minMarginLogicalRight, minLogicalLeftPos);
2681
2682         if (logicalWidth() < minLogicalWidth) {
2683             setLogicalWidth(minLogicalWidth);
2684             marginLogicalLeftAlias = minMarginLogicalLeft;
2685             marginLogicalRightAlias = minMarginLogicalRight;
2686             setLogicalLeft(minLogicalLeftPos);
2687         }
2688     }
2689
2690     if (stretchesToMinIntrinsicLogicalWidth() && logicalWidth() < minPreferredLogicalWidth() - bordersPlusPadding) {
2691         computePositionedLogicalWidthUsing(Length(minPreferredLogicalWidth() - bordersPlusPadding, Fixed), containerBlock, containerDirection,
2692                                            containerLogicalWidth, bordersPlusPadding,
2693                                            logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
2694                                            logicalWidthResult, marginLogicalLeftAlias, marginLogicalRightAlias, logicalLeftResult);
2695         setLogicalWidth(logicalWidthResult);
2696         setLogicalLeft(logicalLeftResult);
2697     }
2698
2699     // Put logicalWidth() into correct form.
2700     setLogicalWidth(logicalWidth() + bordersPlusPadding);
2701     
2702     // Adjust logicalLeft if we need to for the flipped version of our writing mode in regions.
2703     if (inRenderFlowThread() && !region && isWritingModeRoot() && isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()) {
2704         LayoutUnit logicalLeftPos = logicalLeft();
2705         const RenderBlock* cb = toRenderBlock(containerBlock);
2706         LayoutUnit cbPageOffset = offsetFromLogicalTopOfFirstPage - logicalTop();
2707         RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
2708         cbRegion = cb->clampToStartAndEndRegions(cbRegion);
2709         RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion, cbPageOffset);
2710         if (boxInfo) {
2711             logicalLeftPos += boxInfo->logicalLeft();
2712             setLogicalLeft(logicalLeftPos);
2713         }
2714     }
2715 }
2716
2717 static void computeLogicalLeftPositionedOffset(LayoutUnit& logicalLeftPos, const RenderBox* child, LayoutUnit logicalWidthValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth)
2718 {
2719     // Deal with differing writing modes here.  Our offset needs to be in the containing block's coordinate space. If the containing block is flipped
2720     // 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.
2721     if (containerBlock->isHorizontalWritingMode() != child->isHorizontalWritingMode() && containerBlock->style()->isFlippedBlocksWritingMode()) {
2722         logicalLeftPos = containerLogicalWidth - logicalWidthValue - logicalLeftPos;
2723         logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderRight() : containerBlock->borderBottom());
2724     } else
2725         logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderLeft() : containerBlock->borderTop());
2726 }
2727
2728 void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const RenderBoxModelObject* containerBlock, TextDirection containerDirection,
2729                                                    LayoutUnit containerLogicalWidth, LayoutUnit bordersPlusPadding,
2730                                                    Length logicalLeft, Length logicalRight, Length marginLogicalLeft, Length marginLogicalRight,
2731                                                    LayoutUnit& logicalWidthValue, LayoutUnit& marginLogicalLeftValue, LayoutUnit& marginLogicalRightValue, LayoutUnit& logicalLeftPos)
2732 {
2733     // 'left' and 'right' cannot both be 'auto' because one would of been
2734     // converted to the static position already
2735     ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));
2736
2737     LayoutUnit logicalLeftValue = 0;
2738
2739     bool logicalWidthIsAuto = logicalWidth.isIntrinsicOrAuto();
2740     bool logicalLeftIsAuto = logicalLeft.isAuto();
2741     bool logicalRightIsAuto = logicalRight.isAuto();
2742
2743     if (!logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
2744         /*-----------------------------------------------------------------------*\
2745          * If none of the three is 'auto': If both 'margin-left' and 'margin-
2746          * right' are 'auto', solve the equation under the extra constraint that
2747          * the two margins get equal values, unless this would make them negative,
2748          * in which case when direction of the containing block is 'ltr' ('rtl'),
2749          * set 'margin-left' ('margin-right') to zero and solve for 'margin-right'
2750          * ('margin-left'). If one of 'margin-left' or 'margin-right' is 'auto',
2751          * solve the equation for that value. If the values are over-constrained,
2752          * ignore the value for 'left' (in case the 'direction' property of the
2753          * containing block is 'rtl') or 'right' (in case 'direction' is 'ltr')
2754          * and solve for that value.
2755         \*-----------------------------------------------------------------------*/
2756         // NOTE:  It is not necessary to solve for 'right' in the over constrained
2757         // case because the value is not used for any further calculations.
2758
2759         logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
2760         logicalWidthValue = computeContentBoxLogicalWidth(logicalWidth.calcValue(containerLogicalWidth));
2761
2762         const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + logicalWidthValue + logicalRight.calcValue(containerLogicalWidth) + bordersPlusPadding);
2763
2764         // Margins are now the only unknown
2765         if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
2766             // Both margins auto, solve for equality
2767             if (availableSpace >= 0) {
2768                 marginLogicalLeftValue = availableSpace / 2; // split the difference
2769                 marginLogicalRightValue = availableSpace - marginLogicalLeftValue; // account for odd valued differences
2770             } else {
2771                 // Use the containing block's direction rather than the parent block's
2772                 // per CSS 2.1 reference test abspos-non-replaced-width-margin-000.
2773                 if (containerDirection == LTR) {
2774                     marginLogicalLeftValue = 0;
2775                     marginLogicalRightValue = availableSpace; // will be negative
2776                 } else {
2777                     marginLogicalLeftValue = availableSpace; // will be negative
2778                     marginLogicalRightValue = 0;
2779                 }
2780             }
2781         } else if (marginLogicalLeft.isAuto()) {
2782             // Solve for left margin
2783             marginLogicalRightValue = marginLogicalRight.calcValue(containerLogicalWidth);
2784             marginLogicalLeftValue = availableSpace - marginLogicalRightValue;
2785         } else if (marginLogicalRight.isAuto()) {
2786             // Solve for right margin
2787             marginLogicalLeftValue = marginLogicalLeft.calcValue(containerLogicalWidth);
2788             marginLogicalRightValue = availableSpace - marginLogicalLeftValue;
2789         } else {
2790             // Over-constrained, solve for left if direction is RTL
2791             marginLogicalLeftValue = marginLogicalLeft.calcValue(containerLogicalWidth);
2792             marginLogicalRightValue = marginLogicalRight.calcValue(containerLogicalWidth);
2793
2794             // Use the containing block's direction rather than the parent block's
2795             // per CSS 2.1 reference test abspos-non-replaced-width-margin-000.
2796             if (containerDirection == RTL)
2797                 logicalLeftValue = (availableSpace + logicalLeftValue) - marginLogicalLeftValue - marginLogicalRightValue;
2798         }
2799     } else {
2800         /*--------------------------------------------------------------------*\
2801          * Otherwise, set 'auto' values for 'margin-left' and 'margin-right'
2802          * to 0, and pick the one of the following six rules that applies.
2803          *
2804          * 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the
2805          *    width is shrink-to-fit. Then solve for 'left'
2806          *
2807          *              OMIT RULE 2 AS IT SHOULD NEVER BE HIT
2808          * ------------------------------------------------------------------
2809          * 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if
2810          *    the 'direction' property of the containing block is 'ltr' set
2811          *    'left' to the static position, otherwise set 'right' to the
2812          *    static position. Then solve for 'left' (if 'direction is 'rtl')
2813          *    or 'right' (if 'direction' is 'ltr').
2814          * ------------------------------------------------------------------
2815          *
2816          * 3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the
2817          *    width is shrink-to-fit . Then solve for 'right'
2818          * 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve
2819          *    for 'left'
2820          * 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve
2821          *    for 'width'
2822          * 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve
2823          *    for 'right'
2824          *
2825          * Calculation of the shrink-to-fit width is similar to calculating the
2826          * width of a table cell using the automatic table layout algorithm.
2827          * Roughly: calculate the preferred width by formatting the content
2828          * without breaking lines other than where explicit line breaks occur,
2829          * and also calculate the preferred minimum width, e.g., by trying all
2830          * possible line breaks. CSS 2.1 does not define the exact algorithm.
2831          * Thirdly, calculate the available width: this is found by solving
2832          * for 'width' after setting 'left' (in case 1) or 'right' (in case 3)
2833          * to 0.
2834          *
2835          * Then the shrink-to-fit width is:
2836          * min(max(preferred minimum width, available width), preferred width).
2837         \*--------------------------------------------------------------------*/
2838         // NOTE: For rules 3 and 6 it is not necessary to solve for 'right'
2839         // because the value is not used for any further calculations.
2840
2841         // Calculate margins, 'auto' margins are ignored.
2842         marginLogicalLeftValue = marginLogicalLeft.calcMinValue(containerLogicalWidth);
2843         marginLogicalRightValue = marginLogicalRight.calcMinValue(containerLogicalWidth);
2844
2845         const LayoutUnit availableSpace = containerLogicalWidth - (marginLogicalLeftValue + marginLogicalRightValue + bordersPlusPadding);
2846
2847         // FIXME: Is there a faster way to find the correct case?
2848         // Use rule/case that applies.
2849         if (logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
2850             // RULE 1: (use shrink-to-fit for width, and solve of left)
2851             LayoutUnit logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
2852
2853             // FIXME: would it be better to have shrink-to-fit in one step?
2854             LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
2855             LayoutUnit preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding;
2856             LayoutUnit availableWidth = availableSpace - logicalRightValue;
2857             logicalWidthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
2858             logicalLeftValue = availableSpace - (logicalWidthValue + logicalRightValue);
2859         } else if (!logicalLeftIsAuto && logicalWidthIsAuto && logicalRightIsAuto) {
2860             // RULE 3: (use shrink-to-fit for width, and no need solve of right)
2861             logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
2862
2863             // FIXME: would it be better to have shrink-to-fit in one step?
2864             LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
2865             LayoutUnit preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding;
2866             LayoutUnit availableWidth = availableSpace - logicalLeftValue;
2867             logicalWidthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
2868         } else if (logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
2869             // RULE 4: (solve for left)
2870             logicalWidthValue = computeContentBoxLogicalWidth(logicalWidth.calcValue(containerLogicalWidth));
2871             logicalLeftValue = availableSpace - (logicalWidthValue + logicalRight.calcValue(containerLogicalWidth));
2872         } else if (!logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
2873             // RULE 5: (solve for width)
2874             logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
2875             logicalWidthValue = availableSpace - (logicalLeftValue + logicalRight.calcValue(containerLogicalWidth));
2876         } else if (!logicalLeftIsAuto && !logicalWidthIsAuto && logicalRightIsAuto) {
2877             // RULE 6: (no need solve for right)
2878             logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
2879             logicalWidthValue = computeContentBoxLogicalWidth(logicalWidth.calcValue(containerLogicalWidth));
2880         }
2881     }
2882
2883     // Use computed values to calculate the horizontal position.
2884
2885     // FIXME: This hack is needed to calculate the  logical left position for a 'rtl' relatively
2886     // positioned, inline because right now, it is using the logical left position
2887     // of the first line box when really it should use the last line box.  When
2888     // this is fixed elsewhere, this block should be removed.
2889     if (containerBlock->isRenderInline() && !containerBlock->style()->isLeftToRightDirection()) {
2890         const RenderInline* flow = toRenderInline(containerBlock);
2891         InlineFlowBox* firstLine = flow->firstLineBox();
2892         InlineFlowBox* lastLine = flow->lastLineBox();
2893         if (firstLine && lastLine && firstLine != lastLine) {
2894             logicalLeftPos = logicalLeftValue + marginLogicalLeftValue + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft());
2895             return;
2896         }
2897     }
2898
2899     logicalLeftPos = logicalLeftValue + marginLogicalLeftValue;
2900     computeLogicalLeftPositionedOffset(logicalLeftPos, this, logicalWidthValue, containerBlock, containerLogicalWidth);
2901 }
2902
2903 static void computeBlockStaticDistance(Length& logicalTop, Length& logicalBottom, const RenderBox* child, const RenderBoxModelObject* containerBlock)
2904 {
2905     if (!logicalTop.isAuto() || !logicalBottom.isAuto())
2906         return;
2907     
2908     // FIXME: The static distance computation has not been patched for mixed writing modes.
2909     LayoutUnit staticLogicalTop = child->layer()->staticBlockPosition() - containerBlock->borderBefore();
2910     for (RenderObject* curr = child->parent(); curr && curr != containerBlock; curr = curr->container()) {
2911         if (curr->isBox() && !curr->isTableRow())
2912             staticLogicalTop += toRenderBox(curr)->logicalTop();
2913     }
2914     logicalTop.setValue(Fixed, staticLogicalTop);
2915 }
2916
2917 void RenderBox::computePositionedLogicalHeight()
2918 {
2919     if (isReplaced()) {
2920         computePositionedLogicalHeightReplaced();
2921         return;
2922     }
2923
2924     // The following is based off of the W3C Working Draft from April 11, 2006 of
2925     // CSS 2.1: Section 10.6.4 "Absolutely positioned, non-replaced elements"
2926     // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-non-replaced-height>
2927     // (block-style-comments in this function and in computePositionedLogicalHeightUsing()
2928     // correspond to text from the spec)
2929
2930
2931     // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
2932     const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
2933
2934     const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock);
2935
2936     bool isHorizontal = isHorizontalWritingMode();
2937     RenderStyle* styleToUse = style();
2938     bool isFlipped = styleToUse->isFlippedBlocksWritingMode();
2939     const LayoutUnit bordersPlusPadding = borderAndPaddingLogicalHeight();
2940     const Length marginBefore = styleToUse->marginBefore();
2941     const Length marginAfter = styleToUse->marginAfter();
2942     LayoutUnit& marginBeforeAlias = isHorizontal ? (isFlipped ? m_marginBottom : m_marginTop) : (isFlipped ? m_marginRight: m_marginLeft);
2943     LayoutUnit& marginAfterAlias = isHorizontal ? (isFlipped ? m_marginTop : m_marginBottom) : (isFlipped ? m_marginLeft: m_marginRight);
2944
2945     Length logicalTopLength = styleToUse->logicalTop();
2946     Length logicalBottomLength = styleToUse->logicalBottom();
2947         
2948     /*---------------------------------------------------------------------------*\
2949      * For the purposes of this section and the next, the term "static position"
2950      * (of an element) refers, roughly, to the position an element would have had
2951      * in the normal flow. More precisely, the static position for 'top' is the
2952      * distance from the top edge of the containing block to the top margin edge
2953      * of a hypothetical box that would have been the first box of the element if
2954      * its 'position' property had been 'static' and 'float' had been 'none'. The
2955      * value is negative if the hypothetical box is above the containing block.
2956      *
2957      * But rather than actually calculating the dimensions of that hypothetical
2958      * box, user agents are free to make a guess at its probable position.
2959      *
2960      * For the purposes of calculating the static position, the containing block
2961      * of fixed positioned elements is the initial containing block instead of
2962      * the viewport.
2963     \*---------------------------------------------------------------------------*/
2964
2965     // see FIXME 1
2966     // Calculate the static distance if needed.
2967     computeBlockStaticDistance(logicalTopLength, logicalBottomLength, this, containerBlock);
2968
2969     LayoutUnit logicalHeightResult; // Needed to compute overflow.
2970     LayoutUnit logicalTopPos;
2971
2972     // Calculate constraint equation values for 'height' case.
2973     computePositionedLogicalHeightUsing(styleToUse->logicalHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding,
2974                                         logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
2975                                         logicalHeightResult, marginBeforeAlias, marginAfterAlias, logicalTopPos);
2976     setLogicalTop(logicalTopPos);
2977
2978     // Avoid doing any work in the common case (where the values of min-height and max-height are their defaults).
2979     // see FIXME 2
2980
2981     // Calculate constraint equation values for 'max-height' case.
2982     if (!styleToUse->logicalMaxHeight().isUndefined()) {
2983         LayoutUnit maxLogicalHeight;
2984         LayoutUnit maxMarginBefore;
2985         LayoutUnit maxMarginAfter;
2986         LayoutUnit maxLogicalTopPos;
2987
2988         computePositionedLogicalHeightUsing(styleToUse->logicalMaxHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding,
2989                                             logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
2990                                             maxLogicalHeight, maxMarginBefore, maxMarginAfter, maxLogicalTopPos);
2991
2992         if (logicalHeightResult > maxLogicalHeight) {
2993             logicalHeightResult = maxLogicalHeight;
2994             marginBeforeAlias = maxMarginBefore;
2995             marginAfterAlias = maxMarginAfter;
2996             setLogicalTop(maxLogicalTopPos);
2997         }
2998     }
2999
3000     // Calculate constraint equation values for 'min-height' case.
3001     if (!styleToUse->logicalMinHeight().isZero()) {
3002         LayoutUnit minLogicalHeight;
3003         LayoutUnit minMarginBefore;
3004         LayoutUnit minMarginAfter;
3005         LayoutUnit minLogicalTopPos;
3006
3007         computePositionedLogicalHeightUsing(styleToUse->logicalMinHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding,
3008                                             logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
3009                                             minLogicalHeight, minMarginBefore, minMarginAfter, minLogicalTopPos);
3010
3011         if (logicalHeightResult < minLogicalHeight) {
3012             logicalHeightResult = minLogicalHeight;
3013             marginBeforeAlias = minMarginBefore;
3014             marginAfterAlias = minMarginAfter;
3015             setLogicalTop(minLogicalTopPos);
3016         }
3017     }
3018
3019     // Set final height value.
3020     setLogicalHeight(logicalHeightResult + bordersPlusPadding);
3021     
3022     // Adjust logicalTop if we need to for perpendicular writing modes in regions.
3023     if (inRenderFlowThread() && isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode()) {
3024         LayoutUnit logicalTopPos = logicalTop();
3025         const RenderBlock* cb = toRenderBlock(containerBlock);
3026         LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage() - logicalLeft();
3027         RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
3028         cbRegion = cb->clampToStartAndEndRegions(cbRegion);
3029         RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion, cbPageOffset);
3030         if (boxInfo) {
3031             logicalTopPos += boxInfo->logicalLeft();
3032             setLogicalTop(logicalTopPos);
3033         }
3034     }
3035 }
3036
3037 static void computeLogicalTopPositionedOffset(LayoutUnit& logicalTopPos, const RenderBox* child, LayoutUnit logicalHeightValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalHeight)
3038 {
3039     // Deal with differing writing modes here.  Our offset needs to be in the containing block's coordinate space. If the containing block is flipped
3040     // 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.
3041     if ((child->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode())
3042         || (child->style()->isFlippedBlocksWritingMode() != containerBlock->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()))
3043         logicalTopPos = containerLogicalHeight - logicalHeightValue - logicalTopPos;
3044
3045     // Our offset is from the logical bottom edge in a flipped environment, e.g., right for vertical-rl and bottom for horizontal-bt.
3046     if (containerBlock->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()) {
3047         if (child->isHorizontalWritingMode())
3048             logicalTopPos += containerBlock->borderBottom();
3049         else
3050             logicalTopPos += containerBlock->borderRight();
3051     } else {
3052         if (child->isHorizontalWritingMode())
3053             logicalTopPos += containerBlock->borderTop();
3054         else
3055             logicalTopPos += containerBlock->borderLeft();
3056     }
3057 }
3058
3059 void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength, const RenderBoxModelObject* containerBlock,
3060                                                     LayoutUnit containerLogicalHeight, LayoutUnit bordersPlusPadding,
3061                                                     Length logicalTop, Length logicalBottom, Length marginBefore, Length marginAfter,
3062                                                     LayoutUnit& logicalHeightValue, LayoutUnit& marginBeforeValue, LayoutUnit& marginAfterValue, LayoutUnit& logicalTopPos)
3063 {
3064     // 'top' and 'bottom' cannot both be 'auto' because 'top would of been
3065     // converted to the static position in computePositionedLogicalHeight()
3066     ASSERT(!(logicalTop.isAuto() && logicalBottom.isAuto()));
3067
3068     LayoutUnit contentLogicalHeight = logicalHeight() - bordersPlusPadding;
3069
3070     LayoutUnit logicalTopValue = 0;
3071
3072     bool logicalHeightIsAuto = logicalHeightLength.isAuto();
3073     bool logicalTopIsAuto = logicalTop.isAuto();
3074     bool logicalBottomIsAuto = logicalBottom.isAuto();
3075
3076     // Height is never unsolved for tables.
3077     if (isTable()) {
3078         logicalHeightLength.setValue(Fixed, contentLogicalHeight);
3079         logicalHeightIsAuto = false;
3080     }
3081
3082     if (!logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
3083         /*-----------------------------------------------------------------------*\
3084          * If none of the three are 'auto': If both 'margin-top' and 'margin-
3085          * bottom' are 'auto', solve the equation under the extra constraint that
3086          * the two margins get equal values. If one of 'margin-top' or 'margin-
3087          * bottom' is 'auto', solve the equation for that value. If the values
3088          * are over-constrained, ignore the value for 'bottom' and solve for that
3089          * value.
3090         \*-----------------------------------------------------------------------*/
3091         // NOTE:  It is not necessary to solve for 'bottom' in the over constrained
3092         // case because the value is not used for any further calculations.
3093
3094         logicalHeightValue = computeContentBoxLogicalHeight(logicalHeightLength.calcValue(containerLogicalHeight));
3095         logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
3096
3097         const LayoutUnit availableSpace = containerLogicalHeight - (logicalTopValue + logicalHeightValue + logicalBottom.calcValue(containerLogicalHeight) + bordersPlusPadding);
3098
3099         // Margins are now the only unknown
3100         if (marginBefore.isAuto() && marginAfter.isAuto()) {
3101             // Both margins auto, solve for equality
3102             // NOTE: This may result in negative values.
3103             marginBeforeValue = availableSpace / 2; // split the difference
3104             marginAfterValue = availableSpace - marginBeforeValue; // account for odd valued differences
3105         } else if (marginBefore.isAuto()) {
3106             // Solve for top margin
3107             marginAfterValue = marginAfter.calcValue(containerLogicalHeight);
3108             marginBeforeValue = availableSpace - marginAfterValue;
3109         } else if (marginAfter.isAuto()) {
3110             // Solve for bottom margin
3111             marginBeforeValue = marginBefore.calcValue(containerLogicalHeight);
3112             marginAfterValue = availableSpace - marginBeforeValue;
3113         } else {
3114             // Over-constrained, (no need solve for bottom)
3115             marginBeforeValue = marginBefore.calcValue(containerLogicalHeight);
3116             marginAfterValue = marginAfter.calcValue(containerLogicalHeight);
3117         }
3118     } else {
3119         /*--------------------------------------------------------------------*\
3120          * Otherwise, set 'auto' values for 'margin-top' and 'margin-bottom'
3121          * to 0, and pick the one of the following six rules that applies.
3122          *
3123          * 1. 'top' and 'height' are 'auto' and 'bottom' is not 'auto', then
3124          *    the height is based on the content, and solve for 'top'.
3125          *
3126          *              OMIT RULE 2 AS IT SHOULD NEVER BE HIT
3127          * ------------------------------------------------------------------
3128          * 2. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then
3129          *    set 'top' to the static position, and solve for 'bottom'.
3130          * ------------------------------------------------------------------
3131          *
3132          * 3. 'height' and 'bottom' are 'auto' and 'top' is not 'auto', then
3133          *    the height is based on the content, and solve for 'bottom'.
3134          * 4. 'top' is 'auto', 'height' and 'bottom' are not 'auto', and
3135          *    solve for 'top'.
3136          * 5. 'height' is 'auto', 'top' and 'bottom' are not 'auto', and
3137          *    solve for 'height'.
3138          * 6. 'bottom' is 'auto', 'top' and 'height' are not 'auto', and
3139          *    solve for 'bottom'.
3140         \*--------------------------------------------------------------------*/
3141         // NOTE: For rules 3 and 6 it is not necessary to solve for 'bottom'
3142         // because the value is not used for any further calculations.
3143
3144         // Calculate margins, 'auto' margins are ignored.
3145         marginBeforeValue = marginBefore.calcMinValue(containerLogicalHeight);
3146         marginAfterValue = marginAfter.calcMinValue(containerLogicalHeight);
3147
3148         const LayoutUnit availableSpace = containerLogicalHeight - (marginBeforeValue + marginAfterValue + bordersPlusPadding);
3149
3150         // Use rule/case that applies.
3151         if (logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
3152             // RULE 1: (height is content based, solve of top)
3153             logicalHeightValue = contentLogicalHeight;
3154             logicalTopValue = availableSpace - (logicalHeightValue + logicalBottom.calcValue(containerLogicalHeight));
3155         } else if (!logicalTopIsAuto && logicalHeightIsAuto && logicalBottomIsAuto) {
3156             // RULE 3: (height is content based, no need solve of bottom)
3157             logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
3158             logicalHeightValue = contentLogicalHeight;
3159         } else if (logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
3160             // RULE 4: (solve of top)
3161             logicalHeightValue = computeContentBoxLogicalHeight(logicalHeightLength.calcValue(containerLogicalHeight));
3162             logicalTopValue = availableSpace - (logicalHeightValue + logicalBottom.calcValue(containerLogicalHeight));
3163         } else if (!logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
3164             // RULE 5: (solve of height)
3165             logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
3166             logicalHeightValue = max<LayoutUnit>(0, availableSpace - (logicalTopValue + logicalBottom.calcValue(containerLogicalHeight)));
3167         } else if (!logicalTopIsAuto && !logicalHeightIsAuto && logicalBottomIsAuto) {
3168             // RULE 6: (no need solve of bottom)
3169             logicalHeightValue = computeContentBoxLogicalHeight(logicalHeightLength.calcValue(containerLogicalHeight));
3170             logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
3171         }
3172     }
3173
3174     // Use computed values to calculate the vertical position.
3175     logicalTopPos = logicalTopValue + marginBeforeValue;
3176     computeLogicalTopPositionedOffset(logicalTopPos, this, logicalHeightValue, containerBlock, containerLogicalHeight);
3177 }
3178
3179 void RenderBox::computePositionedLogicalWidthReplaced()
3180 {
3181     // The following is based off of the W3C Working Draft from April 11, 2006 of
3182     // CSS 2.1: Section 10.3.8 "Absolutely positioned, replaced elements"
3183     // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-width>
3184     // (block-style-comments in this function correspond to text from the spec and
3185     // the numbers correspond to numbers in spec)
3186
3187     // We don't use containingBlock(), since we may be positioned by an enclosing
3188     // relative positioned inline.
3189     const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
3190
3191     const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock);
3192
3193     // To match WinIE, in quirks mode use the parent's 'direction' property
3194     // instead of the the container block's.
3195     TextDirection containerDirection = containerBlock->style()->direction();
3196
3197     // Variables to solve.
3198     bool isHorizontal = isHorizontalWritingMode();
3199     Length logicalLeft = style()->logicalLeft();
3200     Length logicalRight = style()->logicalRight();
3201     Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop();
3202     Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom();
3203     LayoutUnit& marginLogicalLeftAlias = isHorizontal ? m_marginLeft : m_marginTop;
3204     LayoutUnit& marginLogicalRightAlias = isHorizontal ? m_marginRight : m_marginBottom;
3205
3206     /*-----------------------------------------------------------------------*\
3207      * 1. The used value of 'width' is determined as for inline replaced
3208      *    elements.
3209     \*-----------------------------------------------------------------------*/
3210     // NOTE: This value of width is FINAL in that the min/max width calculations
3211     // are dealt with in computeReplacedWidth().  This means that the steps to produce
3212     // correct max/min in the non-replaced version, are not necessary.
3213     setLogicalWidth(computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth());
3214
3215     const LayoutUnit availableSpace = containerLogicalWidth - logicalWidth();
3216
3217     /*-----------------------------------------------------------------------*\
3218      * 2. If both 'left' and 'right' have the value 'auto', then if 'direction'
3219      *    of the containing block is 'ltr', set 'left' to the static position;
3220      *    else if 'direction' is 'rtl', set 'right' to the static position.
3221     \*-----------------------------------------------------------------------*/
3222     // see FIXME 1
3223     computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, containerLogicalWidth, 0); // FIXME: Pass the region.
3224
3225     /*-----------------------------------------------------------------------*\
3226      * 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left'
3227      *    or 'margin-right' with '0'.
3228     \*-----------------------------------------------------------------------*/
3229     if (logicalLeft.isAuto() || logicalRight.isAuto()) {
3230         if (marginLogicalLeft.isAuto())
3231             marginLogicalLeft.setValue(Fixed, 0);
3232         if (marginLogicalRight.isAuto())
3233             marginLogicalRight.setValue(Fixed, 0);
3234     }
3235
3236     /*-----------------------------------------------------------------------*\
3237      * 4. If at this point both 'margin-left' and 'margin-right' are still
3238      *    'auto', solve the equation under the extra constraint that the two
3239      *    margins must get equal values, unless this would make them negative,
3240      *    in which case when the direction of the containing block is 'ltr'
3241      *    ('rtl'), set 'margin-left' ('margin-right') to zero and solve for
3242      *    'margin-right' ('margin-left').
3243     \*-----------------------------------------------------------------------*/
3244     LayoutUnit logicalLeftValue = 0;
3245     LayoutUnit logicalRightValue = 0;
3246
3247     if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
3248         // 'left' and 'right' cannot be 'auto' due to step 3
3249         ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));
3250
3251         logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
3252         logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
3253
3254         LayoutUnit difference = availableSpace - (logicalLeftValue + logicalRightValue);
3255         if (difference > 0) {
3256             marginLogicalLeftAlias = difference / 2; // split the difference
3257             marginLogicalRightAlias = difference - marginLogicalLeftAlias; // account for odd valued differences
3258         } else {
3259             // Use the containing block's direction rather than the parent block's
3260             // per CSS 2.1 reference test abspos-replaced-width-margin-000.
3261             if (containerDirection == LTR) {
3262                 marginLogicalLeftAlias = 0;
3263                 marginLogicalRightAlias = difference; // will be negative
3264             } else {
3265                 marginLogicalLeftAlias = difference; // will be negative
3266                 marginLogicalRightAlias = 0;
3267             }
3268         }
3269
3270     /*-----------------------------------------------------------------------*\
3271      * 5. If at this point there is an 'auto' left, solve the equation for
3272      *    that value.
3273     \*-----------------------------------------------------------------------*/
3274     } else if (logicalLeft.isAuto()) {
3275         marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth);
3276         marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth);
3277         logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
3278
3279         // Solve for 'left'
3280         logicalLeftValue = availableSpace - (logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias);
3281     } else if (logicalRight.isAuto()) {
3282         marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth);
3283         marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth);
3284         logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
3285
3286         // Solve for 'right'
3287         logicalRightValue = availableSpace - (logicalLeftValue + marginLogicalLeftAlias + marginLogicalRightAlias);
3288     } else if (marginLogicalLeft.isAuto()) {
3289         marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth);
3290         logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
3291         logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
3292
3293         // Solve for 'margin-left'
3294         marginLogicalLeftAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalRightAlias);
3295     } else if (marginLogicalRight.isAuto()) {
3296         marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth);
3297         logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
3298         logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
3299
3300         // Solve for 'margin-right'
3301         marginLogicalRightAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias);
3302     } else {
3303         // Nothing is 'auto', just calculate the values.
3304         marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth);
3305         marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth);
3306         logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
3307         logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
3308         // If the containing block is right-to-left, then push the left position as far to the right as possible
3309         if (containerDirection == RTL) {
3310             int totalLogicalWidth = logicalWidth() + logicalLeftValue + logicalRightValue +  marginLogicalLeftAlias + marginLogicalRightAlias;
3311             logicalLeftValue = containerLogicalWidth - (totalLogicalWidth - logicalLeftValue);
3312         }
3313     }
3314
3315     /*-----------------------------------------------------------------------*\
3316      * 6. If at this point the values are over-constrained, ignore the value
3317      *    for either 'left' (in case the 'direction' property of the
3318      *    containing block is 'rtl') or 'right' (in case 'direction' is
3319      *    'ltr') and solve for that value.
3320     \*-----------------------------------------------------------------------*/
3321     // NOTE: Constraints imposed by the width of the containing block and its content have already been accounted for above.
3322
3323     // FIXME: Deal with differing writing modes here.  Our offset needs to be in the containing block's coordinate space, so that
3324     // can make the result here rather complicated to compute.
3325
3326     // Use computed values to calculate the horizontal position.
3327
3328     // FIXME: This hack is needed to calculate the logical left position for a 'rtl' relatively
3329     // positioned, inline containing block because right now, it is using the logical left position
3330     // of the first line box when really it should use the last line box.  When
3331     // this is fixed elsewhere, this block should be removed.
3332     if (containerBlock->isRenderInline() && !containerBlock->style()->isLeftToRightDirection()) {
3333         const RenderInline* flow = toRenderInline(containerBlock);
3334         InlineFlowBox* firstLine = flow->firstLineBox();
3335         InlineFlowBox* lastLine = flow->lastLineBox();
3336         if (firstLine && lastLine && firstLine != lastLine) {
3337             setLogicalLeft(logicalLeftValue + marginLogicalLeftAlias + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft()));
3338             return;
3339         }
3340     }
3341
3342     LayoutUnit logicalLeftPos = logicalLeftValue + marginLogicalLeftAlias;
3343     computeLogicalLeftPositionedOffset(logicalLeftPos, this, logicalWidth(), containerBlock, containerLogicalWidth);
3344     setLogicalLeft(logicalLeftPos);
3345 }
3346
3347 void RenderBox::computePositionedLogicalHeightReplaced()
3348 {
3349     // The following is based off of the W3C Working Draft from April 11, 2006 of
3350     // CSS 2.1: Section 10.6.5 "Absolutely positioned, replaced elements"
3351     // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-height>
3352     // (block-style-comments in this function correspond to text from the spec and
3353     // the numbers correspond to numbers in spec)
3354
3355     // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
3356     const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
3357
3358     const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock);
3359
3360     // Variables to solve.
3361     bool isHorizontal = isHorizontalWritingMode();
3362     bool isFlipped = style()->isFlippedBlocksWritingMode();
3363     Length marginBefore = style()->marginBefore();
3364     Length marginAfter = style()->marginAfter();
3365     LayoutUnit& marginBeforeAlias = isHorizontal ? (isFlipped ? m_marginBottom : m_marginTop) : (isFlipped ? m_marginRight: m_marginLeft);
3366     LayoutUnit& marginAfterAlias = isHorizontal ? (isFlipped ? m_marginTop : m_marginBottom) : (isFlipped ? m_marginLeft: m_marginRight);
3367
3368     Length logicalTop = style()->logicalTop();
3369     Length logicalBottom = style()->logicalBottom();
3370
3371     /*-----------------------------------------------------------------------*\
3372      * 1. The used value of 'height' is determined as for inline replaced
3373      *    elements.
3374     \*-----------------------------------------------------------------------*/
3375     // NOTE: This value of height is FINAL in that the min/max height calculations
3376     // are dealt with in computeReplacedHeight().  This means that the steps to produce
3377     // correct max/min in the non-replaced version, are not necessary.
3378     setLogicalHeight(computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight());
3379     const LayoutUnit availableSpace = containerLogicalHeight - logicalHeight();
3380
3381     /*-----------------------------------------------------------------------*\
3382      * 2. If both 'top' and 'bottom' have the value 'auto', replace 'top'
3383      *    with the element's static position.
3384     \*-----------------------------------------------------------------------*/
3385     // see FIXME 1
3386     computeBlockStaticDistance(logicalTop, logicalBottom, this, containerBlock);
3387
3388     /*-----------------------------------------------------------------------*\
3389      * 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or
3390      *    'margin-bottom' with '0'.
3391     \*-----------------------------------------------------------------------*/
3392     // FIXME: The spec. says that this step should only be taken when bottom is
3393     // auto, but if only top is auto, this makes step 4 impossible.
3394     if (logicalTop.isAuto() || logicalBottom.isAuto()) {
3395         if (marginBefore.isAuto())
3396             marginBefore.setValue(Fixed, 0);
3397         if (marginAfter.isAuto())
3398             marginAfter.setValue(Fixed, 0);
3399     }
3400
3401     /*-----------------------------------------------------------------------*\
3402      * 4. If at this point both 'margin-top' and 'margin-bottom' are still
3403      *    'auto', solve the equation under the extra constraint that the two
3404      *    margins must get equal values.
3405     \*-----------------------------------------------------------------------*/
3406     LayoutUnit logicalTopValue = 0;
3407     LayoutUnit logicalBottomValue = 0;
3408
3409     if (marginBefore.isAuto() && marginAfter.isAuto()) {
3410         // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined.
3411         ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto()));
3412
3413         logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
3414         logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight);
3415
3416         LayoutUnit difference = availableSpace - (logicalTopValue + logicalBottomValue);
3417         // NOTE: This may result in negative values.
3418         marginBeforeAlias =  difference / 2; // split the difference
3419         marginAfterAlias = difference - marginBeforeAlias; // account for odd valued differences
3420
3421     /*-----------------------------------------------------------------------*\
3422      * 5. If at this point there is only one 'auto' left, solve the equation
3423      *    for that value.
3424     \*-----------------------------------------------------------------------*/
3425     } else if (logicalTop.isAuto()) {
3426         marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight);
3427         marginAfterAlias = marginAfter.calcValue(containerLogicalHeight);
3428         logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight);
3429
3430         // Solve for 'top'
3431         logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias + marginAfterAlias);
3432     } else if (logicalBottom.isAuto()) {
3433         marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight);
3434         marginAfterAlias = marginAfter.calcValue(containerLogicalHeight);
3435         logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
3436
3437         // Solve for 'bottom'
3438         // NOTE: It is not necessary to solve for 'bottom' because we don't ever
3439         // use the value.
3440     } else if (marginBefore.isAuto()) {
3441         marginAfterAlias = marginAfter.calcValue(containerLogicalHeight);
3442         logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
3443         logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight);
3444
3445         // Solve for 'margin-top'
3446         marginBeforeAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginAfterAlias);
3447     } else if (marginAfter.isAuto()) {
3448         marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight);
3449         logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
3450         logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight);
3451
3452         // Solve for 'margin-bottom'
3453         marginAfterAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginBeforeAlias);
3454     } else {
3455         // Nothing is 'auto', just calculate the values.
3456         marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight);
3457         marginAfterAlias = marginAfter.calcValue(containerLogicalHeight);
3458         logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
3459         // NOTE: It is not necessary to solve for 'bottom' because we don't ever
3460         // use the value.
3461      }
3462
3463     /*-----------------------------------------------------------------------*\
3464      * 6. If at this point the values are over-constrained, ignore the value
3465      *    for 'bottom' and solve for that value.
3466     \*-----------------------------------------------------------------------*/
3467     // NOTE: It is not necessary to do this step because we don't end up using
3468     // the value of 'bottom' regardless of whether the values are over-constrained
3469     // or not.
3470
3471     // Use computed values to calculate the vertical position.
3472     LayoutUnit logicalTopPos = logicalTopValue + marginBeforeAlias;
3473     computeLogicalTopPositionedOffset(logicalTopPos, this, logicalHeight(), containerBlock, containerLogicalHeight);
3474     setLogicalTop(logicalTopPos);
3475 }
3476
3477 LayoutRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, LayoutUnit* extraWidthToEndOfLine)
3478 {
3479     // VisiblePositions at offsets inside containers either a) refer to the positions before/after
3480     // those containers (tables and select elements) or b) refer to the position inside an empty block.
3481     // They never refer to children.
3482     // FIXME: Paint the carets inside empty blocks differently than the carets before/after elements.
3483
3484     // FIXME: What about border and padding?
3485     LayoutRect rect(x(), y(), caretWidth, height());
3486     bool ltr = box ? box->isLeftToRightDirection() : style()->isLeftToRightDirection();
3487
3488     if ((!caretOffset) ^ ltr)
3489         rect.move(LayoutSize(width() - caretWidth, 0));
3490
3491     if (box) {
3492         RootInlineBox* rootBox = box->root();
3493         LayoutUnit top = rootBox->lineTop();
3494         rect.setY(top);
3495         rect.setHeight(rootBox->lineBottom() - top);
3496     }
3497
3498     // If height of box is smaller than font height, use the latter one,
3499     // otherwise the caret might become invisible.
3500     //
3501     // Also, if the box is not a replaced element, always use the font height.
3502     // This prevents the "big caret" bug described in:
3503     // <rdar://problem/3777804> Deleting all content in a document can result in giant tall-as-window insertion point
3504     //
3505     // FIXME: ignoring :first-line, missing good reason to take care of
3506     LayoutUnit fontHeight = style()->fontMetrics().height();
3507     if (fontHeight > rect.height() || (!isReplaced() && !isTable()))
3508         rect.setHeight(fontHeight);
3509
3510     if (extraWidthToEndOfLine)
3511         *extraWidthToEndOfLine = x() + width() - rect.maxX();
3512
3513     // Move to local coords
3514     rect.moveBy(-location());
3515     return rect;
3516 }
3517
3518 VisiblePosition RenderBox::positionForPoint(const LayoutPoint& point)
3519 {
3520     // no children...return this render object's element, if there is one, and offset 0
3521     if (!firstChild())
3522         return createVisiblePosition(node() ? firstPositionInOrBeforeNode(node()) : Position());
3523
3524     if (isTable() && node()) {
3525         LayoutUnit right = contentWidth() + borderAndPaddingWidth();
3526         LayoutUnit bottom = contentHeight() + borderAndPaddingHeight();
3527         
3528         if (point.x() < 0 || point.x() > right || point.y() < 0 || point.y() > bottom) {
3529             if (point.x() <= right / 2)
3530                 return createVisiblePosition(firstPositionInOrBeforeNode(node()));
3531             return createVisiblePosition(lastPositionInOrAfterNode(node()));
3532         }
3533     }
3534
3535     // Pass off to the closest child.
3536     LayoutUnit minDist = numeric_limits<LayoutUnit>::max();
3537     RenderBox* closestRenderer = 0;
3538     LayoutPoint adjustedPoint = point;
3539     if (isTableRow())
3540         adjustedPoint.moveBy(location());
3541
3542     for (RenderObject* renderObject = firstChild(); renderObject; renderObject = renderObject->nextSibling()) {
3543         if ((!renderObject->firstChild() && !renderObject->isInline() && !renderObject->isBlockFlow() )
3544             || renderObject->style()->visibility() != VISIBLE)
3545             continue;
3546         
3547         if (!renderObject->isBox())
3548             continue;
3549         
3550         RenderBox* renderer = toRenderBox(renderObject);
3551
3552         LayoutUnit top = renderer->borderTop() + renderer->paddingTop() + (isTableRow() ? zeroLayoutUnit : renderer->y());
3553         LayoutUnit bottom = top + renderer->contentHeight();
3554         LayoutUnit left = renderer->borderLeft() + renderer->paddingLeft() + (isTableRow() ? zeroLayoutUnit : renderer->x());
3555         LayoutUnit right = left + renderer->contentWidth();
3556         
3557         if (point.x() <= right && point.x() >= left && point.y() <= top && point.y() >= bottom) {
3558             if (renderer->isTableRow())
3559                 return renderer->positionForPoint(point + adjustedPoint - renderer->locationOffset());
3560             return renderer->positionForPoint(point - renderer->locationOffset());
3561         }
3562
3563         // Find the distance from (x, y) to the box.  Split the space around the box into 8 pieces
3564         // and use a different compare depending on which piece (x, y) is in.
3565         LayoutPoint cmp;
3566         if (point.x() > right) {
3567             if (point.y() < top)
3568                 cmp = LayoutPoint(right, top);
3569             else if (point.y() > bottom)
3570                 cmp = LayoutPoint(right, bottom);
3571             else
3572                 cmp = LayoutPoint(right, point.y());
3573         } else if (point.x() < left) {
3574             if (point.y() < top)
3575                 cmp = LayoutPoint(left, top);
3576             else if (point.y() > bottom)
3577                 cmp = LayoutPoint(left, bottom);
3578             else
3579                 cmp = LayoutPoint(left, point.y());
3580         } else {
3581             if (point.y() < top)
3582                 cmp = LayoutPoint(point.x(), top);
3583             else
3584                 cmp = LayoutPoint(point.x(), bottom);
3585         }
3586
3587         LayoutSize difference = cmp - point;
3588
3589         LayoutUnit dist = difference.width() * difference.width() + difference.height() * difference.height();
3590         if (dist < minDist) {
3591             closestRenderer = renderer;
3592             minDist = dist;
3593         }
3594     }
3595     
3596     if (closestRenderer)
3597         return closestRenderer->positionForPoint(adjustedPoint - closestRenderer->locationOffset());
3598     
3599     return createVisiblePosition(firstPositionInOrBeforeNode(node()));
3600 }
3601
3602 bool RenderBox::shrinkToAvoidFloats() const
3603 {
3604     // Floating objects don't shrink.  Objects that don't avoid floats don't shrink.  Marquees don't shrink.
3605     if ((isInline() && !isHTMLMarquee()) || !avoidsFloats() || isFloating())
3606         return false;
3607
3608     // All auto-width objects that avoid floats should always use lineWidth.
3609     return style()->width().isAuto(); 
3610 }
3611
3612 bool RenderBox::avoidsFloats() const
3613 {
3614     return isReplaced() || hasOverflowClip() || isHR() || isLegend() || isWritingModeRoot() || isDeprecatedFlexItem();
3615 }
3616
3617 void RenderBox::addVisualEffectOverflow()
3618 {
3619     if (!style()->boxShadow() && !style()->hasBorderImageOutsets() && !style()->hasFilterOutsets())
3620         return;
3621
3622     bool isFlipped = style()->isFlippedBlocksWritingMode();
3623     bool isHorizontal = isHorizontalWritingMode();
3624     
3625     LayoutRect borderBox = borderBoxRect();
3626     LayoutUnit overflowMinX = borderBox.x();
3627     LayoutUnit overflowMaxX = borderBox.maxX();
3628     LayoutUnit overflowMinY = borderBox.y();
3629     LayoutUnit overflowMaxY = borderBox.maxY();
3630     
3631     // Compute box-shadow overflow first.
3632     if (style()->boxShadow()) {
3633         LayoutUnit shadowLeft;
3634         LayoutUnit shadowRight;
3635         LayoutUnit shadowTop;
3636         LayoutUnit shadowBottom;
3637         style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft);
3638
3639         // In flipped blocks writing modes such as vertical-rl, the physical right shadow value is actually at the lower x-coordinate.
3640         overflowMinX = borderBox.x() + ((!isFlipped || isHorizontal) ? shadowLeft : -shadowRight);
3641         overflowMaxX = borderBox.maxX() + ((!isFlipped || isHorizontal) ? shadowRight : -shadowLeft);
3642         overflowMinY = borderBox.y() + ((!isFlipped || !isHorizontal) ? shadowTop : -shadowBottom);
3643         overflowMaxY = borderBox.maxY() + ((!isFlipped || !isHorizontal) ? shadowBottom : -shadowTop);
3644     }
3645
3646     // Now compute border-image-outset overflow.
3647     if (style()->hasBorderImageOutsets()) {
3648         LayoutUnit borderOutsetLeft;
3649         LayoutUnit borderOutsetRight;
3650         LayoutUnit borderOutsetTop;
3651         LayoutUnit borderOutsetBottom;
3652         style()->getBorderImageOutsets(borderOutsetTop, borderOutsetRight, borderOutsetBottom, borderOutsetLeft);
3653         
3654         // In flipped blocks writing modes, the physical sides are inverted. For example in vertical-rl, the right
3655         // border is at the lower x coordinate value.
3656         overflowMinX = min(overflowMinX, borderBox.x() - ((!isFlipped || isHorizontal) ? borderOutsetLeft : borderOutsetRight));
3657         overflowMaxX = max(overflowMaxX, borderBox.maxX() + ((!isFlipped || isHorizontal) ? borderOutsetRight : borderOutsetLeft));
3658         overflowMinY = min(overflowMinY, borderBox.y() - ((!isFlipped || !isHorizontal) ? borderOutsetTop : borderOutsetBottom));
3659         overflowMaxY = max(overflowMaxY, borderBox.maxY() + ((!isFlipped || !isHorizontal) ? borderOutsetBottom : borderOutsetTop));
3660     }
3661
3662 #if ENABLE(CSS_FILTERS)
3663     // Compute any filter outset overflow.
3664     if (style()->hasFilterOutsets()) {
3665         LayoutUnit filterOutsetLeft;
3666         LayoutUnit filterOutsetRight;
3667         LayoutUnit filterOutsetTop;
3668         LayoutUnit filterOutsetBottom;
3669         style()->getFilterOutsets(filterOutsetTop, filterOutsetRight, filterOutsetBottom, filterOutsetLeft);
3670         
3671         overflowMinX = min(overflowMinX, borderBox.x() - filterOutsetLeft);
3672         overflowMaxX = max(overflowMaxX, borderBox.maxX() + filterOutsetRight);
3673         overflowMinY = min(overflowMinY, borderBox.y() - filterOutsetTop);
3674         overflowMaxY = max(overflowMaxY, borderBox.maxY() + filterOutsetBottom);
3675     }
3676 #endif
3677     // Add in the final overflow with shadows and outsets combined.
3678     addVisualOverflow(LayoutRect(overflowMinX, overflowMinY, overflowMaxX - overflowMinX, overflowMaxY - overflowMinY));
3679 }
3680
3681 void RenderBox::addOverflowFromChild(RenderBox* child, const LayoutSize& delta)
3682 {
3683     // Only propagate layout overflow from the child if the child isn't clipping its overflow.  If it is, then
3684     // its overflow is internal to it, and we don't care about it.  layoutOverflowRectForPropagation takes care of this
3685     // and just propagates the border box rect instead.
3686     LayoutRect childLayoutOverflowRect = child->layoutOverflowRectForPropagation(style());
3687     childLayoutOverflowRect.move(delta);
3688     addLayoutOverflow(childLayoutOverflowRect);
3689             
3690     // Add in visual overflow from the child.  Even if the child clips its overflow, it may still
3691     // have visual overflow of its own set from box shadows or reflections.  It is unnecessary to propagate this
3692     // overflow if we are clipping our own overflow.
3693     if (child->hasSelfPaintingLayer() || hasOverflowClip())
3694         return;
3695     LayoutRect childVisualOverflowRect = child->visualOverflowRectForPropagation(style());
3696     childVisualOverflowRect.move(delta);
3697     addVisualOverflow(childVisualOverflowRect);
3698 }
3699
3700 void RenderBox::addLayoutOverflow(const LayoutRect& rect)
3701 {
3702     LayoutRect clientBox = clientBoxRect();
3703     if (clientBox.contains(rect) || rect.isEmpty())
3704         return;
3705     
3706     // For overflow clip objects, we don't want to propagate overflow into unreachable areas.
3707     LayoutRect overflowRect(rect);
3708     if (hasOverflowClip() || isRenderView()) {
3709         // Overflow is in the block's coordinate space and thus is flipped for horizontal-bt and vertical-rl 
3710         // writing modes.  At this stage that is actually a simplification, since we can treat horizontal-tb/bt as the same
3711         // and vertical-lr/rl as the same.
3712         bool hasTopOverflow = !style()->isLeftToRightDirection() && !isHorizontalWritingMode();
3713         bool hasLeftOverflow = !style()->isLeftToRightDirection() && isHorizontalWritingMode();
3714         if (isFlexibleBox() && style()->isReverseFlexDirection()) {
3715             RenderFlexibleBox* flexibleBox = static_cast<RenderFlexibleBox*>(this);
3716             if (flexibleBox->isHorizontalFlow())
3717                 hasLeftOverflow = true;
3718             else
3719                 hasTopOverflow = true;
3720         }
3721         
3722         if (!hasTopOverflow)
3723             overflowRect.shiftYEdgeTo(max(overflowRect.y(), clientBox.y()));
3724         else
3725             overflowRect.shiftMaxYEdgeTo(min(overflowRect.maxY(), clientBox.maxY()));
3726         if (!hasLeftOverflow)
3727             overflowRect.shiftXEdgeTo(max(overflowRect.x(), clientBox.x()));
3728         else
3729             overflowRect.shiftMaxXEdgeTo(min(overflowRect.maxX(), clientBox.maxX()));
3730         
3731         // Now re-test with the adjusted rectangle and&n