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