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