Fix the issue that Web Audio test case fails on PR3.
[framework/web/webkit-efl.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(pointInContainer.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 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1590         if (containerBox->hasOverflowClip() && !containerBox->layer()->hasAcceleratedTouchScrolling()) {
1591 #endif
1592         LayoutRect repaintRect(topLeft, rect.size());
1593         LayoutRect boxRect(LayoutPoint(), containerBox->cachedSizeForOverflowClip());
1594         rect = intersection(repaintRect, boxRect);
1595         if (rect.isEmpty())
1596             return;
1597 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1598         } else
1599             rect.setLocation(topLeft);
1600 #endif
1601     } else
1602         rect.setLocation(topLeft);
1603
1604     if (containerSkipped) {
1605         // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
1606         LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
1607         rect.move(-containerOffset);
1608         return;
1609     }
1610
1611     o->computeRectForRepaint(repaintContainer, rect, fixed);
1612 }
1613
1614 void RenderBox::repaintDuringLayoutIfMoved(const LayoutRect& oldRect)
1615 {
1616     if (oldRect.location() != m_frameRect.location()) {
1617         LayoutRect newRect = m_frameRect;
1618         // The child moved.  Invalidate the object's old and new positions.  We have to do this
1619         // since the object may not have gotten a layout.
1620         m_frameRect = oldRect;
1621         repaint();
1622         repaintOverhangingFloats(true);
1623         m_frameRect = newRect;
1624         repaint();
1625         repaintOverhangingFloats(true);
1626     }
1627 }
1628
1629 void RenderBox::computeLogicalWidth()
1630 {
1631     computeLogicalWidthInRegion();
1632 }
1633
1634 void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
1635 {
1636     if (isOutOfFlowPositioned()) {
1637         // FIXME: This calculation is not patched for block-flow yet.
1638         // https://bugs.webkit.org/show_bug.cgi?id=46500
1639         computePositionedLogicalWidth(region, offsetFromLogicalTopOfFirstPage);
1640         return;
1641     }
1642
1643     // If layout is limited to a subtree, the subtree root's logical width does not change.
1644     if (node() && view()->frameView() && view()->frameView()->layoutRoot(true) == this)
1645         return;
1646
1647     // The parent box is flexing us, so it has increased or decreased our
1648     // width.  Use the width from the style context.
1649     // FIXME: Account for block-flow in flexible boxes.
1650     // https://bugs.webkit.org/show_bug.cgi?id=46418
1651     if (hasOverrideWidth() && parent()->isFlexibleBoxIncludingDeprecated()) {
1652         setLogicalWidth(overrideLogicalContentWidth() + borderAndPaddingLogicalWidth());
1653         return;
1654     }
1655
1656     // FIXME: Account for block-flow in flexible boxes.
1657     // https://bugs.webkit.org/show_bug.cgi?id=46418
1658     bool inVerticalBox = parent()->isDeprecatedFlexibleBox() && (parent()->style()->boxOrient() == VERTICAL);
1659     bool stretching = (parent()->style()->boxAlign() == BSTRETCH);
1660     bool treatAsReplaced = shouldComputeSizeAsReplaced() && (!inVerticalBox || !stretching);
1661
1662     RenderStyle* styleToUse = style();
1663     Length logicalWidthLength = (treatAsReplaced) ? Length(computeReplacedLogicalWidth(), Fixed) : styleToUse->logicalWidth();
1664
1665     RenderBlock* cb = containingBlock();
1666     LayoutUnit containerLogicalWidth = max<LayoutUnit>(0, containingBlockLogicalWidthForContentInRegion(region, offsetFromLogicalTopOfFirstPage));
1667     bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
1668     LayoutUnit containerWidthInInlineDirection = containerLogicalWidth;
1669     if (hasPerpendicularContainingBlock)
1670         containerWidthInInlineDirection = perpendicularContainingBlockLogicalHeight();
1671     
1672     if (isInline() && !isInlineBlockOrInlineTable()) {
1673         // just calculate margins
1674         RenderView* renderView = view();
1675         setMarginStart(minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView));
1676         setMarginEnd(minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView));
1677         if (treatAsReplaced)
1678             setLogicalWidth(max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth()));
1679         return;
1680     }
1681
1682     // Width calculations
1683     if (treatAsReplaced)
1684         setLogicalWidth(logicalWidthLength.value() + borderAndPaddingLogicalWidth());
1685     else {
1686         // Calculate LogicalWidth
1687         setLogicalWidth(computeLogicalWidthInRegionUsing(MainOrPreferredSize, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage));
1688
1689         // Calculate MaxLogicalWidth
1690         if (!styleToUse->logicalMaxWidth().isUndefined()) {
1691             LayoutUnit maxLogicalWidth = computeLogicalWidthInRegionUsing(MaxSize, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage);
1692             if (logicalWidth() > maxLogicalWidth)
1693                 setLogicalWidth(maxLogicalWidth);
1694         }
1695
1696         // Calculate MinLogicalWidth
1697         LayoutUnit minLogicalWidth = computeLogicalWidthInRegionUsing(MinSize, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage);
1698         if (logicalWidth() < minLogicalWidth)
1699             setLogicalWidth(minLogicalWidth);
1700     }
1701
1702     // Fieldsets are currently the only objects that stretch to their minimum width.
1703     if (stretchesToMinIntrinsicLogicalWidth())
1704         setLogicalWidth(max(logicalWidth(), minPreferredLogicalWidth()));
1705
1706     // Margin calculations.
1707     if (hasPerpendicularContainingBlock || isFloating() || isInline()) {
1708         RenderView* renderView = view();
1709         setMarginStart(minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView));
1710         setMarginEnd(minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView));
1711     } else {
1712         LayoutUnit containerLogicalWidthForAutoMargins = containerLogicalWidth;
1713         if (avoidsFloats() && cb->containsFloats())
1714             containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(region, offsetFromLogicalTopOfFirstPage);
1715         computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, logicalWidth());
1716     }
1717     
1718     if (!hasPerpendicularContainingBlock && containerLogicalWidth && containerLogicalWidth != (logicalWidth() + marginStart() + marginEnd())
1719             && !isFloating() && !isInline() && !cb->isFlexibleBoxIncludingDeprecated())
1720         cb->setMarginEndForChild(this, containerLogicalWidth - logicalWidth() - cb->marginStartForChild(this));
1721 }
1722
1723 LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(SizeType widthType, LayoutUnit availableLogicalWidth,
1724     const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
1725 {
1726     RenderStyle* styleToUse = style();
1727     Length logicalWidth;
1728     if (widthType == MainOrPreferredSize)
1729         logicalWidth = styleToUse->logicalWidth();
1730     else if (widthType == MinSize)
1731         logicalWidth = styleToUse->logicalMinWidth();
1732     else
1733         logicalWidth = styleToUse->logicalMaxWidth();
1734
1735     ASSERT(!logicalWidth.isUndefined());
1736
1737     if (widthType == MinSize && logicalWidth.isAuto())
1738         return computeBorderBoxLogicalWidth(0);
1739     
1740     if (!logicalWidth.isIntrinsicOrAuto()) {
1741         // FIXME: If the containing block flow is perpendicular to our direction we need to use the available logical height instead.
1742         return computeBorderBoxLogicalWidth(valueForLength(logicalWidth, availableLogicalWidth, view()));
1743     }
1744
1745     if (logicalWidth.type() == MinContent)
1746         return minPreferredLogicalWidth();
1747     if (logicalWidth.type() == MaxContent)
1748         return maxPreferredLogicalWidth();
1749
1750     RenderView* renderView = view();
1751     LayoutUnit marginStart = minimumValueForLength(styleToUse->marginStart(), availableLogicalWidth, renderView);
1752     LayoutUnit marginEnd = minimumValueForLength(styleToUse->marginEnd(), availableLogicalWidth, renderView);
1753     LayoutUnit logicalWidthResult = availableLogicalWidth - marginStart - marginEnd;
1754
1755     // shrinkToAvoidFloats() is only true for width: auto so the below code works correctly for
1756     // width: fill-available since no case matches and it returns the logicalWidthResult from above.
1757     if (shrinkToAvoidFloats() && cb->containsFloats())
1758         logicalWidthResult = min(logicalWidthResult, shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, region, offsetFromLogicalTopOfFirstPage));
1759
1760 #if ENABLE(TIZEN_ELEMENTS_NESTED_IN_FLATTENED_FRAME_FIX)
1761     if (!logicalWidth.isIntrinsicOrAuto()) {
1762         RenderBlock* cb = containingBlock();
1763         if (cb && cb->view() && cb->view()->frameView() && cb->view()->frameView()->inFlattenFrame() && logicalWidth.isPercent() && (logicalWidthResult > availableLogicalWidth))
1764             logicalWidthResult = availableLogicalWidth;
1765     }
1766 #endif
1767
1768     if (logicalWidth.type() == FitContent || (logicalWidth.type() != FillAvailable && sizesLogicalWidthToFitContent(widthType)))
1769         return max(minPreferredLogicalWidth(), min(maxPreferredLogicalWidth(), logicalWidthResult));
1770     return logicalWidthResult;
1771 }
1772
1773 bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const
1774 {
1775     // Marquees in WinIE are like a mixture of blocks and inline-blocks.  They size as though they're blocks,
1776     // but they allow text to sit on the same line as the marquee.
1777     if (isFloating() || (isInlineBlockOrInlineTable() && !isHTMLMarquee()))
1778         return true;
1779
1780     // This code may look a bit strange.  Basically width:intrinsic should clamp the size when testing both
1781     // min-width and width.  max-width is only clamped if it is also intrinsic.
1782     Length logicalWidth = (widthType == MaxSize) ? style()->logicalMaxWidth() : style()->logicalWidth();
1783     if (logicalWidth.type() == Intrinsic)
1784         return true;
1785
1786     // Children of a horizontal marquee do not fill the container by default.
1787     // FIXME: Need to deal with MAUTO value properly.  It could be vertical.
1788     // FIXME: Think about block-flow here.  Need to find out how marquee direction relates to
1789     // block-flow (as well as how marquee overflow should relate to block flow).
1790     // https://bugs.webkit.org/show_bug.cgi?id=46472
1791     if (parent()->style()->overflowX() == OMARQUEE) {
1792         EMarqueeDirection dir = parent()->style()->marqueeDirection();
1793         if (dir == MAUTO || dir == MFORWARD || dir == MBACKWARD || dir == MLEFT || dir == MRIGHT)
1794             return true;
1795     }
1796
1797     // Flexible box items should shrink wrap, so we lay them out at their intrinsic widths.
1798     // In the case of columns that have a stretch alignment, we go ahead and layout at the
1799     // stretched size to avoid an extra layout when applying alignment.
1800     if (parent()->isFlexibleBox()) {
1801         // For multiline columns, we need to apply align-content first, so we can't stretch now.
1802         if (!parent()->style()->isColumnFlexDirection() || parent()->style()->flexWrap() != FlexNoWrap)
1803             return true;
1804         EAlignItems itemAlign = style()->alignSelf();
1805         if (itemAlign != AlignStretch && (itemAlign != AlignAuto || parent()->style()->alignItems() != AlignStretch))
1806             return true;
1807     }
1808
1809     // Flexible horizontal boxes lay out children at their intrinsic widths.  Also vertical boxes
1810     // that don't stretch their kids lay out their children at their intrinsic widths.
1811     // FIXME: Think about block-flow here.
1812     // https://bugs.webkit.org/show_bug.cgi?id=46473
1813     if (parent()->isDeprecatedFlexibleBox()
1814             && (parent()->style()->boxOrient() == HORIZONTAL || parent()->style()->boxAlign() != BSTRETCH))
1815         return true;
1816
1817     // Button, input, select, textarea, and legend treat
1818     // width value of 'auto' as 'intrinsic' unless it's in a
1819     // stretching vertical flexbox.
1820     // FIXME: Think about block-flow here.
1821     // https://bugs.webkit.org/show_bug.cgi?id=46473
1822     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)))
1823         return true;
1824
1825     if (isHorizontalWritingMode() != containingBlock()->isHorizontalWritingMode())
1826         return true;
1827
1828     return false;
1829 }
1830
1831 void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth)
1832 {
1833     const RenderStyle* containingBlockStyle = containingBlock->style();
1834     Length marginStartLength = style()->marginStartUsing(containingBlockStyle);
1835     Length marginEndLength = style()->marginEndUsing(containingBlockStyle);
1836     RenderView* renderView = view();
1837
1838     if (isFloating() || isInline()) {
1839         // Inline blocks/tables and floats don't have their margins increased.
1840         containingBlock->setMarginStartForChild(this, minimumValueForLength(marginStartLength, containerWidth, renderView));
1841         containingBlock->setMarginEndForChild(this, minimumValueForLength(marginEndLength, containerWidth, renderView));
1842         return;
1843     }
1844
1845     // Case One: The object is being centered in the containing block's available logical width.
1846     if ((marginStartLength.isAuto() && marginEndLength.isAuto() && childWidth < containerWidth)
1847         || (!marginStartLength.isAuto() && !marginEndLength.isAuto() && containingBlock->style()->textAlign() == WEBKIT_CENTER)) {
1848         // Other browsers center the margin box for align=center elements so we match them here.
1849         LayoutUnit marginStartWidth = minimumValueForLength(marginStartLength, containerWidth, renderView);
1850         LayoutUnit marginEndWidth = minimumValueForLength(marginEndLength, containerWidth, renderView);
1851         LayoutUnit centeredMarginBoxStart = max<LayoutUnit>(0, (containerWidth - childWidth - marginStartWidth - marginEndWidth) / 2);
1852         containingBlock->setMarginStartForChild(this, centeredMarginBoxStart + marginStartWidth);
1853         containingBlock->setMarginEndForChild(this, containerWidth - childWidth - containingBlock->marginStartForChild(this) + marginEndWidth);
1854         return;
1855     } 
1856     
1857     // Case Two: The object is being pushed to the start of the containing block's available logical width.
1858     if (marginEndLength.isAuto() && childWidth < containerWidth) {
1859         containingBlock->setMarginStartForChild(this, valueForLength(marginStartLength, containerWidth, renderView));
1860         containingBlock->setMarginEndForChild(this, containerWidth - childWidth - containingBlock->marginStartForChild(this));
1861         return;
1862     } 
1863     
1864     // Case Three: The object is being pushed to the end of the containing block's available logical width.
1865     bool pushToEndFromTextAlign = !marginEndLength.isAuto() && ((!containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_LEFT)
1866         || (containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_RIGHT));
1867     if ((marginStartLength.isAuto() && childWidth < containerWidth) || pushToEndFromTextAlign) {
1868         containingBlock->setMarginEndForChild(this, valueForLength(marginEndLength, containerWidth, renderView));
1869         containingBlock->setMarginStartForChild(this, containerWidth - childWidth - containingBlock->marginEndForChild(this));
1870         return;
1871     } 
1872     
1873     // Case Four: Either no auto margins, or our width is >= the container width (css2.1, 10.3.3).  In that case
1874     // auto margins will just turn into 0.
1875     containingBlock->setMarginStartForChild(this, minimumValueForLength(marginStartLength, containerWidth, renderView));
1876     containingBlock->setMarginEndForChild(this, minimumValueForLength(marginEndLength, containerWidth, renderView));
1877 }
1878
1879 RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, RenderBoxRegionInfoFlags cacheFlag) const
1880 {
1881     // Make sure nobody is trying to call this with a null region.
1882     if (!region)
1883         return 0;
1884
1885     // If we have computed our width in this region already, it will be cached, and we can
1886     // just return it.
1887     RenderBoxRegionInfo* boxInfo = region->renderBoxRegionInfo(this);
1888     if (boxInfo && cacheFlag == CacheRenderBoxRegionInfo)
1889         return boxInfo;
1890
1891     // No cached value was found, so we have to compute our insets in this region.
1892     // FIXME: For now we limit this computation to normal RenderBlocks. Future patches will expand
1893     // support to cover all boxes.
1894     if (!inRenderFlowThread() || isFloating() || isReplaced() || isInline() || hasColumns()
1895         || isTableCell() || !isBlockFlow() || isRenderFlowThread())
1896         return 0;
1897
1898     // FIXME: It's gross to cast away the const, but it would be a huge refactoring to
1899     // change all width computation to avoid updating any member variables, and it would be pretty lame to
1900     // make all the variables mutable as well.
1901     RenderFlowThread* flowThread = enclosingRenderFlowThread();
1902     if (flowThread->style()->writingMode() != style()->writingMode())
1903         return 0;
1904
1905     LayoutUnit oldLogicalWidth = logicalWidth();
1906     LayoutUnit oldLogicalLeft = logicalLeft();
1907     LayoutUnit oldMarginStart = marginStart();
1908     LayoutUnit oldMarginEnd = marginEnd();
1909
1910     RenderBox* mutableBox = const_cast<RenderBox*>(this);
1911     
1912     mutableBox->computeLogicalWidthInRegion(region, offsetFromLogicalTopOfFirstPage);
1913
1914     // Now determine the insets based off where this object is supposed to be positioned.
1915     RenderBlock* cb = containingBlock();
1916     RenderRegion* clampedContainingBlockRegion = cb->clampToStartAndEndRegions(region);
1917     RenderBoxRegionInfo* containingBlockInfo = cb->renderBoxRegionInfo(clampedContainingBlockRegion,
1918         offsetFromLogicalTopOfFirstPage - logicalTop());
1919     LayoutUnit containingBlockLogicalWidth = cb->logicalWidth();
1920     LayoutUnit containingBlockLogicalWidthInRegion = containingBlockInfo ? containingBlockInfo->logicalWidth() : containingBlockLogicalWidth;
1921     
1922     LayoutUnit marginStartInRegion = marginStart();
1923     LayoutUnit startMarginDelta = marginStartInRegion - oldMarginStart;
1924     LayoutUnit logicalWidthInRegion = logicalWidth();
1925     LayoutUnit logicalLeftInRegion = logicalLeft();
1926     LayoutUnit widthDelta = logicalWidthInRegion - oldLogicalWidth;
1927     LayoutUnit logicalLeftDelta = isOutOfFlowPositioned() ? logicalLeftInRegion - oldLogicalLeft : startMarginDelta;
1928     LayoutUnit logicalRightInRegion = containingBlockLogicalWidthInRegion - (logicalLeftInRegion + logicalWidthInRegion);
1929     LayoutUnit oldLogicalRight = containingBlockLogicalWidth - (oldLogicalLeft + oldLogicalWidth);
1930     LayoutUnit logicalRightDelta = isOutOfFlowPositioned() ? logicalRightInRegion - oldLogicalRight : startMarginDelta;
1931
1932     // Set our values back.
1933     mutableBox->setLogicalWidth(oldLogicalWidth);
1934     mutableBox->setLogicalLeft(oldLogicalLeft);
1935     mutableBox->setMarginStart(oldMarginStart);
1936     mutableBox->setMarginEnd(oldMarginEnd);
1937
1938     LayoutUnit logicalLeftOffset = 0;
1939     
1940     if (!isOutOfFlowPositioned() && avoidsFloats() && cb->containsFloats()) {
1941         LayoutUnit startPositionDelta = cb->computeStartPositionDeltaForChildAvoidingFloats(this, marginStartInRegion, region, offsetFromLogicalTopOfFirstPage);
1942         if (cb->style()->isLeftToRightDirection())
1943             logicalLeftDelta += startPositionDelta;
1944         else
1945             logicalRightDelta += startPositionDelta;
1946     }
1947
1948     if (cb->style()->isLeftToRightDirection())
1949         logicalLeftOffset += logicalLeftDelta;
1950     else
1951         logicalLeftOffset -= (widthDelta + logicalRightDelta);
1952     
1953     LayoutUnit logicalRightOffset = logicalWidth() - (logicalLeftOffset + logicalWidthInRegion);
1954     bool isShifted = (containingBlockInfo && containingBlockInfo->isShifted())
1955             || (style()->isLeftToRightDirection() && logicalLeftOffset)
1956             || (!style()->isLeftToRightDirection() && logicalRightOffset);
1957
1958     // FIXME: Although it's unlikely, these boxes can go outside our bounds, and so we will need to incorporate them into overflow.
1959     if (cacheFlag == CacheRenderBoxRegionInfo)
1960         return region->setRenderBoxRegionInfo(this, logicalLeftOffset, logicalWidthInRegion, isShifted);
1961     return new RenderBoxRegionInfo(logicalLeftOffset, logicalWidthInRegion, isShifted);
1962 }
1963
1964 void RenderBox::computeLogicalHeight()
1965 {
1966     // Cell height is managed by the table and inline non-replaced elements do not support a height property.
1967     if (isTableCell() || (isInline() && !isReplaced()))
1968         return;
1969
1970     Length h;
1971     if (isOutOfFlowPositioned())
1972         computePositionedLogicalHeight();
1973     else {
1974         RenderBlock* cb = containingBlock();
1975         bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
1976     
1977         if (!hasPerpendicularContainingBlock)
1978             computeBlockDirectionMargins(cb);
1979
1980         // For tables, calculate margins only.
1981         if (isTable()) {
1982             if (hasPerpendicularContainingBlock)
1983                 computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), logicalHeight());
1984             return;
1985         }
1986
1987         // FIXME: Account for block-flow in flexible boxes.
1988         // https://bugs.webkit.org/show_bug.cgi?id=46418
1989         bool inHorizontalBox = parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL;
1990         bool stretching = parent()->style()->boxAlign() == BSTRETCH;
1991         bool treatAsReplaced = shouldComputeSizeAsReplaced() && (!inHorizontalBox || !stretching);
1992         bool checkMinMaxHeight = false;
1993
1994         // The parent box is flexing us, so it has increased or decreased our height.  We have to
1995         // grab our cached flexible height.
1996         // FIXME: Account for block-flow in flexible boxes.
1997         // https://bugs.webkit.org/show_bug.cgi?id=46418
1998         RenderStyle* styleToUse = style();
1999         if (hasOverrideHeight() && parent()->isFlexibleBoxIncludingDeprecated())
2000             h = Length(overrideLogicalContentHeight(), Fixed);
2001         else if (treatAsReplaced)
2002             h = Length(computeReplacedLogicalHeight(), Fixed);
2003         else {
2004             h = styleToUse->logicalHeight();
2005             checkMinMaxHeight = true;
2006         }
2007
2008         // Block children of horizontal flexible boxes fill the height of the box.
2009         // FIXME: Account for block-flow in flexible boxes.
2010         // https://bugs.webkit.org/show_bug.cgi?id=46418
2011         if (h.isAuto() && parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
2012                 && parent()->isStretchingChildren()) {
2013             h = Length(parentBox()->contentLogicalHeight() - marginBefore() - marginAfter() - borderAndPaddingLogicalHeight(), Fixed);
2014             checkMinMaxHeight = false;
2015         }
2016
2017         LayoutUnit heightResult;
2018         if (checkMinMaxHeight) {
2019             heightResult = computeLogicalHeightUsing(MainOrPreferredSize, styleToUse->logicalHeight());
2020             if (heightResult == -1)
2021                 heightResult = logicalHeight();
2022             LayoutUnit minH = computeLogicalHeightUsing(MinSize, styleToUse->logicalMinHeight()); // Leave as -1 if unset.
2023             LayoutUnit maxH = styleToUse->logicalMaxHeight().isUndefined() ? heightResult : computeLogicalHeightUsing(MaxSize, styleToUse->logicalMaxHeight());
2024             if (maxH == -1)
2025                 maxH = heightResult;
2026             heightResult = min(maxH, heightResult);
2027             heightResult = max(minH, heightResult);
2028         } else {
2029             // The only times we don't check min/max height are when a fixed length has
2030             // been given as an override.  Just use that.  The value has already been adjusted
2031             // for box-sizing.
2032             heightResult = h.value() + borderAndPaddingLogicalHeight();
2033         }
2034
2035         setLogicalHeight(heightResult);
2036         
2037         if (hasPerpendicularContainingBlock)
2038             computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), heightResult);
2039     }
2040
2041     // WinIE quirk: The <html> block always fills the entire canvas in quirks mode.  The <body> always fills the
2042     // <html> block in quirks mode.  Only apply this quirk if the block is normal flow and no height
2043     // is specified. When we're printing, we also need this quirk if the body or root has a percentage 
2044     // height since we don't set a height in RenderView when we're printing. So without this quirk, the 
2045     // height has nothing to be a percentage of, and it ends up being 0. That is bad.
2046     bool paginatedContentNeedsBaseHeight = document()->printing() && h.isPercent()
2047         && (isRoot() || (isBody() && document()->documentElement()->renderer()->style()->logicalHeight().isPercent()));
2048     if (stretchesToViewport() || paginatedContentNeedsBaseHeight) {
2049         // FIXME: Finish accounting for block flow here.
2050         // https://bugs.webkit.org/show_bug.cgi?id=46603
2051         LayoutUnit margins = collapsedMarginBefore() + collapsedMarginAfter();
2052         LayoutUnit visHeight;
2053         if (document()->printing())
2054             visHeight = static_cast<LayoutUnit>(view()->pageLogicalHeight());
2055         else  {
2056             if (isHorizontalWritingMode())
2057                 visHeight = view()->viewHeight();
2058             else
2059                 visHeight = view()->viewWidth();
2060         }
2061         if (isRoot())
2062             setLogicalHeight(max(logicalHeight(), visHeight - margins));
2063         else {
2064             LayoutUnit marginsBordersPadding = margins + parentBox()->marginBefore() + parentBox()->marginAfter() + parentBox()->borderAndPaddingLogicalHeight();
2065             setLogicalHeight(max(logicalHeight(), visHeight - marginsBordersPadding));
2066         }
2067     }
2068 }
2069
2070 LayoutUnit RenderBox::computeLogicalHeightUsing(SizeType heightType, const Length& height)
2071 {
2072     LayoutUnit logicalHeight = computeContentLogicalHeightUsing(heightType, height);
2073     if (logicalHeight != -1)
2074         logicalHeight = computeBorderBoxLogicalHeight(logicalHeight);
2075     return logicalHeight;
2076 }
2077
2078 LayoutUnit RenderBox::computeContentLogicalHeightUsing(SizeType heightType, const Length& height)
2079 {
2080     if (height.isAuto())
2081         return heightType == MinSize ? 0 : -1;
2082     if (height.isFixed())
2083         return height.value();
2084     if (height.isPercent())
2085         return computePercentageLogicalHeight(height);
2086     if (height.isViewportPercentage())
2087         return valueForLength(height, 0, view());
2088     return -1;
2089 }
2090
2091 LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height)
2092 {
2093     LayoutUnit result = -1;
2094     
2095     // In quirks mode, blocks with auto height are skipped, and we keep looking for an enclosing
2096     // block that may have a specified height and then use it. In strict mode, this violates the
2097     // specification, which states that percentage heights just revert to auto if the containing
2098     // block has an auto height. We still skip anonymous containing blocks in both modes, though, and look
2099     // only at explicit containers.
2100     bool skippedAutoHeightContainingBlock = false;
2101     RenderBlock* cb = containingBlock();
2102     while (!cb->isRenderView() && !cb->isBody() && !cb->isTableCell() && !cb->isOutOfFlowPositioned() && cb->style()->logicalHeight().isAuto()) {
2103         if (!document()->inQuirksMode() && !cb->isAnonymousBlock())
2104             break;
2105         skippedAutoHeightContainingBlock = true;
2106         cb = cb->containingBlock();
2107         cb->addPercentHeightDescendant(this);
2108     }
2109
2110     RenderStyle* cbstyle = cb->style();
2111
2112     // A positioned element that specified both top/bottom or that specifies height should be treated as though it has a height
2113     // explicitly specified that can be used for any percentage computations.
2114     // FIXME: We can't just check top/bottom here.
2115     // https://bugs.webkit.org/show_bug.cgi?id=46500
2116     bool isOutOfFlowPositionedWithSpecifiedHeight = cb->isOutOfFlowPositioned() && (!cbstyle->logicalHeight().isAuto() || (!cbstyle->top().isAuto() && !cbstyle->bottom().isAuto()));
2117
2118     bool includeBorderPadding = isTable();
2119
2120     // Table cells violate what the CSS spec says to do with heights.  Basically we
2121     // don't care if the cell specified a height or not.  We just always make ourselves
2122     // be a percentage of the cell's current content height.
2123     if (cb->isTableCell()) {
2124         if (!skippedAutoHeightContainingBlock) {
2125             if (!cb->hasOverrideHeight()) {
2126                 // Normally we would let the cell size intrinsically, but scrolling overflow has to be
2127                 // treated differently, since WinIE lets scrolled overflow regions shrink as needed.
2128                 // While we can't get all cases right, we can at least detect when the cell has a specified
2129                 // height or when the table has a specified height.  In these cases we want to initially have
2130                 // no size and allow the flexing of the table or the cell to its specified height to cause us
2131                 // to grow to fill the space.  This could end up being wrong in some cases, but it is
2132                 // preferable to the alternative (sizing intrinsically and making the row end up too big).
2133                 RenderTableCell* cell = toRenderTableCell(cb);
2134                 if (scrollsOverflowY() && (!cell->style()->logicalHeight().isAuto() || !cell->table()->style()->logicalHeight().isAuto()))
2135                     return 0;
2136                 return -1;
2137             }
2138             result = cb->overrideLogicalContentHeight();
2139             includeBorderPadding = true;
2140         }
2141     } else if (cbstyle->logicalHeight().isFixed()) {
2142         // Otherwise we only use our percentage height if our containing block had a specified height.
2143         LayoutUnit contentBoxHeightWithScrollbar = cb->computeContentBoxLogicalHeight(cbstyle->logicalHeight().value());
2144         result = max<LayoutUnit>(0, contentBoxHeightWithScrollbar - cb->scrollbarLogicalHeight());
2145     } else if (cbstyle->logicalHeight().isPercent() && !isOutOfFlowPositionedWithSpecifiedHeight) {
2146         // We need to recur and compute the percentage height for our containing block.
2147         result = cb->computePercentageLogicalHeight(cbstyle->logicalHeight());
2148         if (result != -1)
2149             result = cb->computeContentBoxLogicalHeight(result);
2150     } else if (cb->isRenderView() || (cb->isBody() && document()->inQuirksMode()) || isOutOfFlowPositionedWithSpecifiedHeight) {
2151         // Don't allow this to affect the block' height() member variable, since this
2152         // can get called while the block is still laying out its kids.
2153         LayoutUnit oldHeight = cb->logicalHeight();
2154         cb->computeLogicalHeight();
2155         result = cb->contentLogicalHeight();
2156         cb->setLogicalHeight(oldHeight);
2157     } else if (cb->isRoot() && isOutOfFlowPositioned())
2158         // Match the positioned objects behavior, which is that positioned objects will fill their viewport
2159         // always.  Note we could only hit this case by recurring into computePercentageLogicalHeight on a positioned containing block.
2160         result = cb->computeContentBoxLogicalHeight(cb->availableLogicalHeight());
2161
2162     if (result != -1) {
2163         result = valueForLength(height, result);
2164         if (includeBorderPadding) {
2165             // It is necessary to use the border-box to match WinIE's broken
2166             // box model.  This is essential for sizing inside
2167             // table cells using percentage heights.
2168             result -= borderAndPaddingLogicalHeight();
2169             result = max<LayoutUnit>(0, result);
2170         }
2171     }
2172     return result;
2173 }
2174
2175 LayoutUnit RenderBox::computeReplacedLogicalWidth(bool includeMaxWidth) const
2176 {
2177     return computeReplacedLogicalWidthRespectingMinMaxWidth(computeReplacedLogicalWidthUsing(MainOrPreferredSize, style()->logicalWidth()), includeMaxWidth);
2178 }
2179
2180 LayoutUnit RenderBox::computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit logicalWidth, bool includeMaxWidth) const
2181 {
2182     LayoutUnit minLogicalWidth = computeReplacedLogicalWidthUsing(MinSize, style()->logicalMinWidth());
2183     LayoutUnit maxLogicalWidth = !includeMaxWidth || style()->logicalMaxWidth().isUndefined() ? logicalWidth : computeReplacedLogicalWidthUsing(MaxSize, style()->logicalMaxWidth());
2184     return max(minLogicalWidth, min(logicalWidth, maxLogicalWidth));
2185 }
2186
2187 LayoutUnit RenderBox::computeReplacedLogicalWidthUsing(SizeType sizeType, Length logicalWidth) const
2188 {
2189     if (sizeType == MinSize && logicalWidth.isAuto())
2190         return computeContentBoxLogicalWidth(0);
2191
2192     switch (logicalWidth.type()) {
2193         case Fixed:
2194             return computeContentBoxLogicalWidth(logicalWidth.value());
2195         case ViewportPercentageWidth:
2196         case ViewportPercentageHeight:
2197         case ViewportPercentageMin:
2198             return computeContentBoxLogicalWidth(valueForLength(logicalWidth, 0, view()));
2199         case Percent: 
2200         case Calculated: {
2201             // FIXME: containingBlockLogicalWidthForContent() is wrong if the replaced element's block-flow is perpendicular to the
2202             // containing block's block-flow.
2203             // https://bugs.webkit.org/show_bug.cgi?id=46496
2204             const LayoutUnit cw = isOutOfFlowPositioned() ? containingBlockLogicalWidthForPositioned(toRenderBoxModelObject(container())) : containingBlockLogicalWidthForContent();
2205             Length containerLogicalWidth = containingBlock()->style()->logicalWidth();
2206             // FIXME: Handle cases when containing block width is calculated or viewport percent.
2207             // https://bugs.webkit.org/show_bug.cgi?id=91071
2208             if (cw > 0 || (!cw && (containerLogicalWidth.isFixed() || containerLogicalWidth.isPercent())))
2209                 return computeContentBoxLogicalWidth(minimumValueForLength(logicalWidth, cw));
2210         }
2211         // fall through
2212         default:
2213             return intrinsicLogicalWidth();
2214      }
2215 }
2216
2217 LayoutUnit RenderBox::computeReplacedLogicalHeight() const
2218 {
2219     return computeReplacedLogicalHeightRespectingMinMaxHeight(computeReplacedLogicalHeightUsing(MainOrPreferredSize, style()->logicalHeight()));
2220 }
2221
2222 LayoutUnit RenderBox::computeReplacedLogicalHeightRespectingMinMaxHeight(LayoutUnit logicalHeight) const
2223 {
2224     LayoutUnit minLogicalHeight = computeReplacedLogicalHeightUsing(MinSize, style()->logicalMinHeight());
2225     LayoutUnit maxLogicalHeight = style()->logicalMaxHeight().isUndefined() ? logicalHeight : computeReplacedLogicalHeightUsing(MaxSize, style()->logicalMaxHeight());
2226     return max(minLogicalHeight, min(logicalHeight, maxLogicalHeight));
2227 }
2228
2229 LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(SizeType sizeType, Length logicalHeight) const
2230 {
2231     if (sizeType == MinSize && logicalHeight.isAuto())
2232         return computeContentBoxLogicalHeight(0);
2233
2234     switch (logicalHeight.type()) {
2235         case Fixed:
2236             return computeContentBoxLogicalHeight(logicalHeight.value());
2237         case Percent:
2238         case Calculated:
2239         {
2240             RenderObject* cb = isOutOfFlowPositioned() ? container() : containingBlock();
2241             while (cb->isAnonymous()) {
2242                 cb = cb->containingBlock();
2243                 toRenderBlock(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this));
2244             }
2245
2246             // FIXME: This calculation is not patched for block-flow yet.
2247             // https://bugs.webkit.org/show_bug.cgi?id=46500
2248             if (cb->isOutOfFlowPositioned() && cb->style()->height().isAuto() && !(cb->style()->top().isAuto() || cb->style()->bottom().isAuto())) {
2249                 ASSERT(cb->isRenderBlock());
2250                 RenderBlock* block = toRenderBlock(cb);
2251                 LayoutUnit oldHeight = block->height();
2252                 block->computeLogicalHeight();
2253                 LayoutUnit newHeight = block->computeContentBoxLogicalHeight(block->contentHeight());
2254                 block->setHeight(oldHeight);
2255                 return computeContentBoxLogicalHeight(valueForLength(logicalHeight, newHeight));
2256             }
2257             
2258             // FIXME: availableLogicalHeight() is wrong if the replaced element's block-flow is perpendicular to the
2259             // containing block's block-flow.
2260             // https://bugs.webkit.org/show_bug.cgi?id=46496
2261             LayoutUnit availableHeight;
2262             if (isOutOfFlowPositioned())
2263                 availableHeight = containingBlockLogicalHeightForPositioned(toRenderBoxModelObject(cb));
2264             else {
2265                 availableHeight =  toRenderBox(cb)->availableLogicalHeight();
2266                 // It is necessary to use the border-box to match WinIE's broken
2267                 // box model.  This is essential for sizing inside
2268                 // table cells using percentage heights.
2269                 // FIXME: This needs to be made block-flow-aware.  If the cell and image are perpendicular block-flows, this isn't right.
2270                 // https://bugs.webkit.org/show_bug.cgi?id=46997
2271                 while (cb && !cb->isRenderView() && (cb->style()->logicalHeight().isAuto() || cb->style()->logicalHeight().isPercent())) {
2272                     if (cb->isTableCell()) {
2273                         // Don't let table cells squeeze percent-height replaced elements
2274                         // <http://bugs.webkit.org/show_bug.cgi?id=15359>
2275                         availableHeight = max(availableHeight, intrinsicLogicalHeight());
2276                         return valueForLength(logicalHeight, availableHeight - borderAndPaddingLogicalHeight());
2277                     }
2278                     toRenderBlock(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this));
2279                     cb = cb->containingBlock();
2280                 }
2281             }
2282             availableHeight = computeContentBoxLogicalHeight(valueForLength(logicalHeight, availableHeight));
2283             if (cb->style()->logicalHeight().isFixed())
2284                 availableHeight = max<LayoutUnit>(0, availableHeight - toRenderBox(cb)->scrollbarLogicalHeight());
2285             return availableHeight;
2286         }
2287         case ViewportPercentageWidth:
2288         case ViewportPercentageHeight:
2289         case ViewportPercentageMin:
2290             return computeContentBoxLogicalHeight(valueForLength(logicalHeight, 0, view()));
2291         default:
2292             return intrinsicLogicalHeight();
2293     }
2294 }
2295
2296 LayoutUnit RenderBox::availableLogicalHeight() const
2297 {
2298     return availableLogicalHeightUsing(style()->logicalHeight());
2299 }
2300
2301 LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h) const
2302 {
2303     if (h.isFixed())
2304         return computeContentBoxLogicalHeight(h.value());
2305
2306     if (isRenderView())
2307         return isHorizontalWritingMode() ? toRenderView(this)->frameView()->visibleHeight() : toRenderView(this)->frameView()->visibleWidth();
2308
2309     // We need to stop here, since we don't want to increase the height of the table
2310     // artificially.  We're going to rely on this cell getting expanded to some new
2311     // height, and then when we lay out again we'll use the calculation below.
2312     if (isTableCell() && (h.isAuto() || h.isPercent()))
2313         return overrideLogicalContentHeight();
2314
2315     if (h.isPercent()) {
2316         LayoutUnit availableHeight;
2317         // https://bugs.webkit.org/show_bug.cgi?id=64046
2318         // For absolutely positioned elements whose containing block is based on a block-level element,
2319         // the percentage is calculated with respect to the height of the padding box of that element
2320         if (isOutOfFlowPositioned())
2321             availableHeight = containingBlockLogicalHeightForPositioned(containingBlock());
2322         else
2323             availableHeight = containingBlock()->availableLogicalHeight();
2324         return computeContentBoxLogicalHeight(valueForLength(h, availableHeight));
2325     }
2326
2327     // FIXME: We can't just check top/bottom here.
2328     // https://bugs.webkit.org/show_bug.cgi?id=46500
2329     if (isRenderBlock() && isOutOfFlowPositioned() && style()->height().isAuto() && !(style()->top().isAuto() || style()->bottom().isAuto())) {
2330         RenderBlock* block = const_cast<RenderBlock*>(toRenderBlock(this));
2331         LayoutUnit oldHeight = block->logicalHeight();
2332         block->computeLogicalHeight();
2333         LayoutUnit newHeight = block->computeContentBoxLogicalHeight(block->contentLogicalHeight());
2334         block->setLogicalHeight(oldHeight);
2335         return computeContentBoxLogicalHeight(newHeight);
2336     }
2337
2338     return containingBlock()->availableLogicalHeight();
2339 }
2340
2341 void RenderBox::computeBlockDirectionMargins(const RenderBlock* containingBlock)
2342 {
2343     if (isTableCell()) {
2344         // FIXME: Not right if we allow cells to have different directionality than the table.  If we do allow this, though,
2345         // we may just do it with an extra anonymous block inside the cell.
2346         setMarginBefore(0);
2347         setMarginAfter(0);
2348         return;
2349     }
2350
2351     // Margins are calculated with respect to the logical width of
2352     // the containing block (8.3)
2353     LayoutUnit cw = containingBlockLogicalWidthForContent();
2354     RenderView* renderView = view();
2355     RenderStyle* containingBlockStyle = containingBlock->style();
2356     containingBlock->setMarginBeforeForChild(this, minimumValueForLength(style()->marginBeforeUsing(containingBlockStyle), cw, renderView));
2357     containingBlock->setMarginAfterForChild(this, minimumValueForLength(style()->marginAfterUsing(containingBlockStyle), cw, renderView));
2358 }
2359
2360 LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* region,
2361     LayoutUnit offsetFromLogicalTopOfFirstPage, bool checkForPerpendicularWritingMode) const
2362 {
2363     // Container for position:fixed is the frame.
2364     Frame* frame = view() ? view()->frame(): 0;
2365     FrameView* frameView = view() ? view()->frameView() : 0;
2366     if (fixedElementLaysOutRelativeToFrame(frame, frameView))
2367         return (view()->isHorizontalWritingMode() ? frameView->visibleWidth() : frameView->visibleHeight()) / frame->frameScaleFactor();
2368
2369     if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
2370         return containingBlockLogicalHeightForPositioned(containingBlock, false);
2371
2372     if (containingBlock->isBox()) {
2373         const RenderBlock* cb = toRenderBlock(containingBlock);
2374         LayoutUnit result = cb->clientLogicalWidth();
2375         if (inRenderFlowThread()) {
2376             RenderBoxRegionInfo* boxInfo = 0;
2377             if (!region) {
2378                 if (containingBlock->isRenderFlowThread() && !checkForPerpendicularWritingMode)
2379                     return toRenderFlowThread(containingBlock)->contentLogicalWidthOfFirstRegion();
2380                 if (isWritingModeRoot()) {
2381                     LayoutUnit cbPageOffset = offsetFromLogicalTopOfFirstPage - logicalTop();
2382                     RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
2383                     if (cbRegion) {
2384                         cbRegion = cb->clampToStartAndEndRegions(cbRegion);
2385                         boxInfo = cb->renderBoxRegionInfo(cbRegion, cbPageOffset);
2386                     }
2387                 }
2388             } else if (region && enclosingRenderFlowThread()->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode()) {
2389                 RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region);
2390                 boxInfo = cb->renderBoxRegionInfo(containingBlockRegion, offsetFromLogicalTopOfFirstPage - logicalTop());
2391             }
2392             if (boxInfo)
2393                 return max<LayoutUnit>(0, result - (cb->logicalWidth() - boxInfo->logicalWidth()));
2394         }
2395         return result;
2396     }
2397
2398     ASSERT(containingBlock->isRenderInline() && containingBlock->isRelPositioned());
2399
2400     const RenderInline* flow = toRenderInline(containingBlock);
2401     InlineFlowBox* first = flow->firstLineBox();
2402     InlineFlowBox* last = flow->lastLineBox();
2403
2404     // If the containing block is empty, return a width of 0.
2405     if (!first || !last)
2406         return 0;
2407
2408     LayoutUnit fromLeft;
2409     LayoutUnit fromRight;
2410     if (containingBlock->style()->isLeftToRightDirection()) {
2411         fromLeft = first->logicalLeft() + first->borderLogicalLeft();
2412         fromRight = last->logicalLeft() + last->logicalWidth() - last->borderLogicalRight();
2413     } else {
2414         fromRight = first->logicalLeft() + first->logicalWidth() - first->borderLogicalRight();
2415         fromLeft = last->logicalLeft() + last->borderLogicalLeft();
2416     }
2417
2418     return max<LayoutUnit>(0, fromRight - fromLeft);
2419 }
2420
2421 LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode) const
2422 {
2423     Frame* frame = view() ? view()->frame(): 0;
2424     FrameView* frameView = view() ? view()->frameView() : 0;
2425     if (fixedElementLaysOutRelativeToFrame(frame, frameView))
2426         return (view()->isHorizontalWritingMode() ? frameView->visibleHeight() : frameView->visibleWidth()) / frame->frameScaleFactor();
2427
2428     if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
2429         return containingBlockLogicalWidthForPositioned(containingBlock, 0, 0, false);
2430
2431     if (containingBlock->isBox()) {
2432         const RenderBlock* cb = toRenderBlock(containingBlock);
2433         LayoutUnit result = cb->clientLogicalHeight();
2434         if (inRenderFlowThread() && containingBlock->isRenderFlowThread() && enclosingRenderFlowThread()->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode())
2435             return toRenderFlowThread(containingBlock)->contentLogicalHeightOfFirstRegion();
2436         return result;
2437     }
2438         
2439     ASSERT(containingBlock->isRenderInline() && containingBlock->isRelPositioned());
2440
2441     const RenderInline* flow = toRenderInline(containingBlock);
2442     InlineFlowBox* first = flow->firstLineBox();
2443     InlineFlowBox* last = flow->lastLineBox();
2444
2445     // If the containing block is empty, return a height of 0.
2446     if (!first || !last)
2447         return 0;
2448
2449     LayoutUnit heightResult;
2450     LayoutRect boundingBox = flow->linesBoundingBox();
2451     if (containingBlock->isHorizontalWritingMode())
2452         heightResult = boundingBox.height();
2453     else
2454         heightResult = boundingBox.width();
2455     heightResult -= (containingBlock->borderBefore() + containingBlock->borderAfter());
2456     return heightResult;
2457 }
2458
2459 static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRight, const RenderBox* child, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth, RenderRegion* region)
2460 {
2461     if (!logicalLeft.isAuto() || !logicalRight.isAuto())
2462         return;
2463
2464     // FIXME: The static distance computation has not been patched for mixed writing modes yet.
2465     if (child->parent()->style()->direction() == LTR) {
2466         LayoutUnit staticPosition = child->layer()->staticInlinePosition() - containerBlock->borderLogicalLeft();
2467         for (RenderObject* curr = child->parent(); curr && curr != containerBlock; curr = curr->container()) {
2468             if (curr->isBox()) {
2469                 staticPosition += toRenderBox(curr)->logicalLeft();
2470                 if (region && curr->isRenderBlock()) {
2471                     const RenderBlock* cb = toRenderBlock(curr);
2472                     region = cb->clampToStartAndEndRegions(region);
2473                     RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region, region->offsetFromLogicalTopOfFirstPage());
2474                     if (boxInfo)
2475                         staticPosition += boxInfo->logicalLeft();
2476                 }
2477             }
2478         }
2479         logicalLeft.setValue(Fixed, staticPosition);
2480     } else {
2481         RenderBox* enclosingBox = child->parent()->enclosingBox();
2482         LayoutUnit staticPosition = child->layer()->staticInlinePosition() + containerLogicalWidth + containerBlock->borderLogicalLeft();
2483         for (RenderObject* curr = enclosingBox; curr; curr = curr->container()) {
2484             if (curr->isBox()) {
2485                 if (curr != containerBlock)
2486                     staticPosition -= toRenderBox(curr)->logicalLeft();
2487                 if (curr == enclosingBox)
2488                     staticPosition -= enclosingBox->logicalWidth();
2489                 if (region && curr->isRenderBlock()) {
2490                      const RenderBlock* cb = toRenderBlock(curr);
2491                      region = cb->clampToStartAndEndRegions(region);
2492                      RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region, region->offsetFromLogicalTopOfFirstPage());
2493                      if (boxInfo) {
2494                         if (curr != containerBlock)
2495                             staticPosition -= cb->logicalWidth() - (boxInfo->logicalLeft() + boxInfo->logicalWidth());
2496                         if (curr == enclosingBox)
2497                             staticPosition += enclosingBox->logicalWidth() - boxInfo->logicalWidth();
2498                     }
2499                 }
2500             }
2501             if (curr == containerBlock)
2502                 break;
2503         }
2504         logicalRight.setValue(Fixed, staticPosition);
2505     }
2506 }
2507
2508 void RenderBox::computePositionedLogicalWidth(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
2509 {
2510     if (isReplaced()) {
2511         computePositionedLogicalWidthReplaced(); // FIXME: Patch for regions when we add replaced element support.
2512         return;
2513     }
2514
2515     // QUESTIONS
2516     // FIXME 1: Should we still deal with these the cases of 'left' or 'right' having
2517     // the type 'static' in determining whether to calculate the static distance?
2518     // NOTE: 'static' is not a legal value for 'left' or 'right' as of CSS 2.1.
2519
2520     // FIXME 2: Can perhaps optimize out cases when max-width/min-width are greater
2521     // than or less than the computed width().  Be careful of box-sizing and
2522     // percentage issues.
2523
2524     // The following is based off of the W3C Working Draft from April 11, 2006 of
2525     // CSS 2.1: Section 10.3.7 "Absolutely positioned, non-replaced elements"
2526     // <http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width>
2527     // (block-style-comments in this function and in computePositionedLogicalWidthUsing()
2528     // correspond to text from the spec)
2529
2530
2531     // We don't use containingBlock(), since we may be positioned by an enclosing
2532     // relative positioned inline.
2533     const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
2534     
2535     const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, region, offsetFromLogicalTopOfFirstPage);
2536
2537     // Use the container block's direction except when calculating the static distance
2538     // This conforms with the reference results for abspos-replaced-width-margin-000.htm
2539     // of the CSS 2.1 test suite
2540     TextDirection containerDirection = containerBlock->style()->direction();
2541
2542     bool isHorizontal = isHorizontalWritingMode();
2543     const LayoutUnit bordersPlusPadding = borderAndPaddingLogicalWidth();
2544     const Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop();
2545     const Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom();
2546     LayoutUnit& marginLogicalLeftAlias = m_marginBox.mutableLogicalLeft(style()->writingMode());
2547     LayoutUnit& marginLogicalRightAlias = m_marginBox.mutableLogicalRight(style()->writingMode());
2548
2549     Length logicalLeftLength = style()->logicalLeft();
2550     Length logicalRightLength = style()->logicalRight();
2551
2552     /*---------------------------------------------------------------------------*\
2553      * For the purposes of this section and the next, the term "static position"
2554      * (of an element) refers, roughly, to the position an element would have had
2555      * in the normal flow. More precisely:
2556      *
2557      * * The static position for 'left' is the distance from the left edge of the
2558      *   containing block to the left margin edge of a hypothetical box that would
2559      *   have been the first box of the element if its 'position' property had
2560      *   been 'static' and 'float' had been 'none'. The value is negative if the
2561      *   hypothetical box is to the left of the containing block.
2562      * * The static position for 'right' is the distance from the right edge of the
2563      *   containing block to the right margin edge of the same hypothetical box as
2564      *   above. The value is positive if the hypothetical box is to the left of the
2565      *   containing block's edge.
2566      *
2567      * But rather than actually calculating the dimensions of that hypothetical box,
2568      * user agents are free to make a guess at its probable position.
2569      *
2570      * For the purposes of calculating the static position, the containing block of
2571      * fixed positioned elements is the initial containing block instead of the
2572      * viewport, and all scrollable boxes should be assumed to be scrolled to their
2573      * origin.
2574     \*---------------------------------------------------------------------------*/
2575
2576     // see FIXME 1
2577     // Calculate the static distance if needed.
2578     computeInlineStaticDistance(logicalLeftLength, logicalRightLength, this, containerBlock, containerLogicalWidth, region);
2579     
2580     // Calculate constraint equation values for 'width' case.
2581     LayoutUnit logicalWidthResult;
2582     LayoutUnit logicalLeftResult;
2583     computePositionedLogicalWidthUsing(MainOrPreferredSize, style()->logicalWidth(), containerBlock, containerDirection,
2584                                        containerLogicalWidth, bordersPlusPadding,
2585                                        logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
2586                                        logicalWidthResult, marginLogicalLeftAlias, marginLogicalRightAlias, logicalLeftResult);
2587     setLogicalWidth(logicalWidthResult);
2588     setLogicalLeft(logicalLeftResult);
2589
2590     // Calculate constraint equation values for 'max-width' case.
2591     if (!style()->logicalMaxWidth().isUndefined()) {
2592         LayoutUnit maxLogicalWidth;
2593         LayoutUnit maxMarginLogicalLeft;
2594         LayoutUnit maxMarginLogicalRight;
2595         LayoutUnit maxLogicalLeftPos;
2596
2597         computePositionedLogicalWidthUsing(MaxSize, style()->logicalMaxWidth(), containerBlock, containerDirection,
2598                                            containerLogicalWidth, bordersPlusPadding,
2599                                            logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
2600                                            maxLogicalWidth, maxMarginLogicalLeft, maxMarginLogicalRight, maxLogicalLeftPos);
2601
2602         if (logicalWidth() > maxLogicalWidth) {
2603             setLogicalWidth(maxLogicalWidth);
2604             marginLogicalLeftAlias = maxMarginLogicalLeft;
2605             marginLogicalRightAlias = maxMarginLogicalRight;
2606             setLogicalLeft(maxLogicalLeftPos);
2607         }
2608     }
2609
2610     // Calculate constraint equation values for 'min-width' case.
2611     if (!style()->logicalMinWidth().isZero()) {
2612         LayoutUnit minLogicalWidth;
2613         LayoutUnit minMarginLogicalLeft;
2614         LayoutUnit minMarginLogicalRight;
2615         LayoutUnit minLogicalLeftPos;
2616
2617         computePositionedLogicalWidthUsing(MinSize, style()->logicalMinWidth(), containerBlock, containerDirection,
2618                                            containerLogicalWidth, bordersPlusPadding,
2619                                            logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
2620                                            minLogicalWidth, minMarginLogicalLeft, minMarginLogicalRight, minLogicalLeftPos);
2621
2622         if (logicalWidth() < minLogicalWidth) {
2623             setLogicalWidth(minLogicalWidth);
2624             marginLogicalLeftAlias = minMarginLogicalLeft;
2625             marginLogicalRightAlias = minMarginLogicalRight;
2626             setLogicalLeft(minLogicalLeftPos);
2627         }
2628     }
2629
2630     if (stretchesToMinIntrinsicLogicalWidth() && logicalWidth() < minPreferredLogicalWidth() - bordersPlusPadding) {
2631         computePositionedLogicalWidthUsing(MainOrPreferredSize, Length(minPreferredLogicalWidth() - bordersPlusPadding, Fixed), containerBlock, containerDirection,
2632                                            containerLogicalWidth, bordersPlusPadding,
2633                                            logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
2634                                            logicalWidthResult, marginLogicalLeftAlias, marginLogicalRightAlias, logicalLeftResult);
2635         setLogicalWidth(logicalWidthResult);
2636         setLogicalLeft(logicalLeftResult);
2637     }
2638
2639     // Put logicalWidth() into correct form.
2640     setLogicalWidth(logicalWidth() + bordersPlusPadding);
2641     
2642     // Adjust logicalLeft if we need to for the flipped version of our writing mode in regions.
2643     if (inRenderFlowThread() && !region && isWritingModeRoot() && isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()) {
2644         LayoutUnit logicalLeftPos = logicalLeft();
2645         const RenderBlock* cb = toRenderBlock(containerBlock);
2646         LayoutUnit cbPageOffset = offsetFromLogicalTopOfFirstPage - logicalTop();
2647         RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
2648         if (cbRegion) {
2649             cbRegion = cb->clampToStartAndEndRegions(cbRegion);
2650             RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion, cbPageOffset);
2651             if (boxInfo) {
2652                 logicalLeftPos += boxInfo->logicalLeft();
2653                 setLogicalLeft(logicalLeftPos);
2654             }
2655         }
2656     }
2657 }
2658
2659 static void computeLogicalLeftPositionedOffset(LayoutUnit& logicalLeftPos, const RenderBox* child, LayoutUnit logicalWidthValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth)
2660 {
2661     // Deal with differing writing modes here.  Our offset needs to be in the containing block's coordinate space. If the containing block is flipped
2662     // 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.
2663     if (containerBlock->isHorizontalWritingMode() != child->isHorizontalWritingMode() && containerBlock->style()->isFlippedBlocksWritingMode()) {
2664         logicalLeftPos = containerLogicalWidth - logicalWidthValue - logicalLeftPos;
2665         logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderRight() : containerBlock->borderBottom());
2666     } else
2667         logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderLeft() : containerBlock->borderTop());
2668 }
2669
2670 void RenderBox::computePositionedLogicalWidthUsing(SizeType widthSizeType, Length logicalWidth, const RenderBoxModelObject* containerBlock, TextDirection containerDirection,
2671                                                    LayoutUnit containerLogicalWidth, LayoutUnit bordersPlusPadding,
2672                                                    Length logicalLeft, Length logicalRight, Length marginLogicalLeft, Length marginLogicalRight,
2673                                                    LayoutUnit& logicalWidthValue, LayoutUnit& marginLogicalLeftValue, LayoutUnit& marginLogicalRightValue, LayoutUnit& logicalLeftPos)
2674 {
2675     if (widthSizeType == MinSize && logicalWidth.isAuto())
2676         logicalWidth = Length(0, Fixed);
2677
2678     // 'left' and 'right' cannot both be 'auto' because one would of been
2679     // converted to the static position already
2680     ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));
2681
2682     LayoutUnit logicalLeftValue = 0;
2683
2684     bool logicalWidthIsAuto = logicalWidth.isIntrinsicOrAuto();
2685     bool logicalLeftIsAuto = logicalLeft.isAuto();
2686     bool logicalRightIsAuto = logicalRight.isAuto();
2687     RenderView* renderView = view();
2688
2689     if (!logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
2690         /*-----------------------------------------------------------------------*\
2691          * If none of the three is 'auto': If both 'margin-left' and 'margin-
2692          * right' are 'auto', solve the equation under the extra constraint that
2693          * the two margins get equal values, unless this would make them negative,
2694          * in which case when direction of the containing block is 'ltr' ('rtl'),
2695          * set 'margin-left' ('margin-right') to zero and solve for 'margin-right'
2696          * ('margin-left'). If one of 'margin-left' or 'margin-right' is 'auto',
2697          * solve the equation for that value. If the values are over-constrained,
2698          * ignore the value for 'left' (in case the 'direction' property of the
2699          * containing block is 'rtl') or 'right' (in case 'direction' is 'ltr')
2700          * and solve for that value.
2701         \*-----------------------------------------------------------------------*/
2702         // NOTE:  It is not necessary to solve for 'right' in the over constrained
2703         // case because the value is not used for any further calculations.
2704
2705         logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
2706         logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView));
2707
2708         const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + logicalWidthValue + valueForLength(logicalRight, containerLogicalWidth, renderView) + bordersPlusPadding);
2709
2710         // Margins are now the only unknown
2711         if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
2712             // Both margins auto, solve for equality
2713             if (availableSpace >= 0) {
2714                 marginLogicalLeftValue = availableSpace / 2; // split the difference
2715                 marginLogicalRightValue = availableSpace - marginLogicalLeftValue; // account for odd valued differences
2716             } else {
2717                 // Use the containing block's direction rather than the parent block's
2718                 // per CSS 2.1 reference test abspos-non-replaced-width-margin-000.
2719                 if (containerDirection == LTR) {
2720                     marginLogicalLeftValue = 0;
2721                     marginLogicalRightValue = availableSpace; // will be negative
2722                 } else {
2723                     marginLogicalLeftValue = availableSpace; // will be negative
2724                     marginLogicalRightValue = 0;
2725                 }
2726             }
2727         } else if (marginLogicalLeft.isAuto()) {
2728             // Solve for left margin
2729             marginLogicalRightValue = valueForLength(marginLogicalRight, containerLogicalWidth, renderView);
2730             marginLogicalLeftValue = availableSpace - marginLogicalRightValue;
2731         } else if (marginLogicalRight.isAuto()) {
2732             // Solve for right margin
2733             marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
2734             marginLogicalRightValue = availableSpace - marginLogicalLeftValue;
2735         } else {
2736             // Over-constrained, solve for left if direction is RTL
2737             marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
2738             marginLogicalRightValue = valueForLength(marginLogicalRight, containerLogicalWidth, renderView);
2739
2740             // Use the containing block's direction rather than the parent block's
2741             // per CSS 2.1 reference test abspos-non-replaced-width-margin-000.
2742             if (containerDirection == RTL)
2743                 logicalLeftValue = (availableSpace + logicalLeftValue) - marginLogicalLeftValue - marginLogicalRightValue;
2744         }
2745     } else {
2746         /*--------------------------------------------------------------------*\
2747          * Otherwise, set 'auto' values for 'margin-left' and 'margin-right'
2748          * to 0, and pick the one of the following six rules that applies.
2749          *
2750          * 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the
2751          *    width is shrink-to-fit. Then solve for 'left'
2752          *
2753          *              OMIT RULE 2 AS IT SHOULD NEVER BE HIT
2754          * ------------------------------------------------------------------
2755          * 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if
2756          *    the 'direction' property of the containing block is 'ltr' set
2757          *    'left' to the static position, otherwise set 'right' to the
2758          *    static position. Then solve for 'left' (if 'direction is 'rtl')
2759          *    or 'right' (if 'direction' is 'ltr').
2760          * ------------------------------------------------------------------
2761          *
2762          * 3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the
2763          *    width is shrink-to-fit . Then solve for 'right'
2764          * 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve
2765          *    for 'left'
2766          * 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve
2767          *    for 'width'
2768          * 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve
2769          *    for 'right'
2770          *
2771          * Calculation of the shrink-to-fit width is similar to calculating the
2772          * width of a table cell using the automatic table layout algorithm.
2773          * Roughly: calculate the preferred width by formatting the content
2774          * without breaking lines other than where explicit line breaks occur,
2775          * and also calculate the preferred minimum width, e.g., by trying all
2776          * possible line breaks. CSS 2.1 does not define the exact algorithm.
2777          * Thirdly, calculate the available width: this is found by solving
2778          * for 'width' after setting 'left' (in case 1) or 'right' (in case 3)
2779          * to 0.
2780          *
2781          * Then the shrink-to-fit width is:
2782          * min(max(preferred minimum width, available width), preferred width).
2783         \*--------------------------------------------------------------------*/
2784         // NOTE: For rules 3 and 6 it is not necessary to solve for 'right'
2785         // because the value is not used for any further calculations.
2786
2787         // Calculate margins, 'auto' margins are ignored.
2788         marginLogicalLeftValue = minimumValueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
2789         marginLogicalRightValue = minimumValueForLength(marginLogicalRight, containerLogicalWidth, renderView);
2790
2791         const LayoutUnit availableSpace = containerLogicalWidth - (marginLogicalLeftValue + marginLogicalRightValue + bordersPlusPadding);
2792
2793         // FIXME: Is there a faster way to find the correct case?
2794         // Use rule/case that applies.
2795         if (logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
2796             // RULE 1: (use shrink-to-fit for width, and solve of left)
2797             LayoutUnit logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
2798
2799             // FIXME: would it be better to have shrink-to-fit in one step?
2800             LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
2801             LayoutUnit preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding;
2802             LayoutUnit availableWidth = availableSpace - logicalRightValue;
2803             logicalWidthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
2804             logicalLeftValue = availableSpace - (logicalWidthValue + logicalRightValue);
2805         } else if (!logicalLeftIsAuto && logicalWidthIsAuto && logicalRightIsAuto) {
2806             // RULE 3: (use shrink-to-fit for width, and no need solve of right)
2807             logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
2808
2809             // FIXME: would it be better to have shrink-to-fit in one step?
2810             LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
2811             LayoutUnit preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding;
2812             LayoutUnit availableWidth = availableSpace - logicalLeftValue;
2813             logicalWidthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
2814         } else if (logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
2815             // RULE 4: (solve for left)
2816             logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView));
2817             logicalLeftValue = availableSpace - (logicalWidthValue + valueForLength(logicalRight, containerLogicalWidth, renderView));
2818         } else if (!logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
2819             // RULE 5: (solve for width)
2820             logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
2821             logicalWidthValue = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth, renderView));
2822         } else if (!logicalLeftIsAuto && !logicalWidthIsAuto && logicalRightIsAuto) {
2823             // RULE 6: (no need solve for right)
2824             logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
2825             logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView));
2826         }
2827     }
2828
2829     // Use computed values to calculate the horizontal position.
2830
2831     // FIXME: This hack is needed to calculate the  logical left position for a 'rtl' relatively
2832     // positioned, inline because right now, it is using the logical left position
2833     // of the first line box when really it should use the last line box.  When
2834     // this is fixed elsewhere, this block should be removed.
2835     if (containerBlock->isRenderInline() && !containerBlock->style()->isLeftToRightDirection()) {
2836         const RenderInline* flow = toRenderInline(containerBlock);
2837         InlineFlowBox* firstLine = flow->firstLineBox();
2838         InlineFlowBox* lastLine = flow->lastLineBox();
2839         if (firstLine && lastLine && firstLine != lastLine) {
2840             logicalLeftPos = logicalLeftValue + marginLogicalLeftValue + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft());
2841             return;
2842         }
2843     }
2844
2845     logicalLeftPos = logicalLeftValue + marginLogicalLeftValue;
2846     computeLogicalLeftPositionedOffset(logicalLeftPos, this, logicalWidthValue, containerBlock, containerLogicalWidth);
2847 }
2848
2849 static void computeBlockStaticDistance(Length& logicalTop, Length& logicalBottom, const RenderBox* child, const RenderBoxModelObject* containerBlock)
2850 {
2851     if (!logicalTop.isAuto() || !logicalBottom.isAuto())
2852         return;
2853     
2854     // FIXME: The static distance computation has not been patched for mixed writing modes.
2855     LayoutUnit staticLogicalTop = child->layer()->staticBlockPosition() - containerBlock->borderBefore();
2856     for (RenderObject* curr = child->parent(); curr && curr != containerBlock; curr = curr->container()) {
2857         if (curr->isBox() && !curr->isTableRow())
2858             staticLogicalTop += toRenderBox(curr)->logicalTop();
2859     }
2860     logicalTop.setValue(Fixed, staticLogicalTop);
2861 }
2862
2863 void RenderBox::computePositionedLogicalHeight()
2864 {
2865     if (isReplaced()) {
2866         computePositionedLogicalHeightReplaced();
2867         return;
2868     }
2869
2870     // The following is based off of the W3C Working Draft from April 11, 2006 of
2871     // CSS 2.1: Section 10.6.4 "Absolutely positioned, non-replaced elements"
2872     // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-non-replaced-height>
2873     // (block-style-comments in this function and in computePositionedLogicalHeightUsing()
2874     // correspond to text from the spec)
2875
2876
2877     // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
2878     const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
2879
2880     const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock);
2881
2882     RenderStyle* styleToUse = style();
2883     const LayoutUnit bordersPlusPadding = borderAndPaddingLogicalHeight();
2884     const Length marginBefore = styleToUse->marginBefore();
2885     const Length marginAfter = styleToUse->marginAfter();
2886     LayoutUnit& marginBeforeAlias = m_marginBox.mutableBefore(styleToUse->writingMode());
2887     LayoutUnit& marginAfterAlias = m_marginBox.mutableAfter(styleToUse->writingMode());
2888
2889     Length logicalTopLength = styleToUse->logicalTop();
2890     Length logicalBottomLength = styleToUse->logicalBottom();
2891
2892     /*---------------------------------------------------------------------------*\
2893      * For the purposes of this section and the next, the term "static position"
2894      * (of an element) refers, roughly, to the position an element would have had
2895      * in the normal flow. More precisely, the static position for 'top' is the
2896      * distance from the top edge of the containing block to the top margin edge
2897      * of a hypothetical box that would have been the first box of the element if
2898      * its 'position' property had been 'static' and 'float' had been 'none'. The
2899      * value is negative if the hypothetical box is above the containing block.
2900      *
2901      * But rather than actually calculating the dimensions of that hypothetical
2902      * box, user agents are free to make a guess at its probable position.
2903      *
2904      * For the purposes of calculating the static position, the containing block
2905      * of fixed positioned elements is the initial containing block instead of
2906      * the viewport.
2907     \*---------------------------------------------------------------------------*/
2908
2909     // see FIXME 1
2910     // Calculate the static distance if needed.
2911     computeBlockStaticDistance(logicalTopLength, logicalBottomLength, this, containerBlock);
2912
2913     LayoutUnit logicalHeightResult; // Needed to compute overflow.
2914     LayoutUnit logicalTopPos;
2915
2916     // Calculate constraint equation values for 'height' case.
2917     computePositionedLogicalHeightUsing(MainOrPreferredSize, styleToUse->logicalHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding,
2918                                         logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
2919                                         logicalHeightResult, marginBeforeAlias, marginAfterAlias, logicalTopPos);
2920     setLogicalTop(logicalTopPos);
2921
2922     // Avoid doing any work in the common case (where the values of min-height and max-height are their defaults).
2923     // see FIXME 2
2924
2925     // Calculate constraint equation values for 'max-height' case.
2926     if (!styleToUse->logicalMaxHeight().isUndefined()) {
2927         LayoutUnit maxLogicalHeight;
2928         LayoutUnit maxMarginBefore;
2929         LayoutUnit maxMarginAfter;
2930         LayoutUnit maxLogicalTopPos;
2931
2932         computePositionedLogicalHeightUsing(MaxSize, styleToUse->logicalMaxHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding,
2933                                             logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
2934                                             maxLogicalHeight, maxMarginBefore, maxMarginAfter, maxLogicalTopPos);
2935
2936         if (logicalHeightResult > maxLogicalHeight) {
2937             logicalHeightResult = maxLogicalHeight;
2938             marginBeforeAlias = maxMarginBefore;
2939             marginAfterAlias = maxMarginAfter;
2940             setLogicalTop(maxLogicalTopPos);
2941         }
2942     }
2943
2944     // Calculate constraint equation values for 'min-height' case.
2945     if (!styleToUse->logicalMinHeight().isZero()) {
2946         LayoutUnit minLogicalHeight;
2947         LayoutUnit minMarginBefore;
2948         LayoutUnit minMarginAfter;
2949         LayoutUnit minLogicalTopPos;
2950
2951         computePositionedLogicalHeightUsing(MinSize, styleToUse->logicalMinHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding,
2952                                             logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
2953                                             minLogicalHeight, minMarginBefore, minMarginAfter, minLogicalTopPos);
2954
2955         if (logicalHeightResult < minLogicalHeight) {
2956             logicalHeightResult = minLogicalHeight;
2957             marginBeforeAlias = minMarginBefore;
2958             marginAfterAlias = minMarginAfter;
2959             setLogicalTop(minLogicalTopPos);
2960         }
2961     }
2962
2963     // Set final height value.
2964     setLogicalHeight(logicalHeightResult + bordersPlusPadding);
2965     
2966     // Adjust logicalTop if we need to for perpendicular writing modes in regions.
2967     if (inRenderFlowThread() && isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode()) {
2968         LayoutUnit logicalTopPos = logicalTop();
2969         const RenderBlock* cb = toRenderBlock(containerBlock);
2970         LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage() - logicalLeft();
2971         RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
2972         if (cbRegion) {
2973             cbRegion = cb->clampToStartAndEndRegions(cbRegion);
2974             RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion, cbPageOffset);
2975             if (boxInfo) {
2976                 logicalTopPos += boxInfo->logicalLeft();
2977                 setLogicalTop(logicalTopPos);
2978             }
2979         }
2980     }
2981 }
2982
2983 static void computeLogicalTopPositionedOffset(LayoutUnit& logicalTopPos, const RenderBox* child, LayoutUnit logicalHeightValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalHeight)
2984 {
2985     // Deal with differing writing modes here.  Our offset needs to be in the containing block's coordinate space. If the containing block is flipped
2986     // 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.
2987     if ((child->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode())
2988         || (child->style()->isFlippedBlocksWritingMode() != containerBlock->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()))
2989         logicalTopPos = containerLogicalHeight - logicalHeightValue - logicalTopPos;
2990
2991     // Our offset is from the logical bottom edge in a flipped environment, e.g., right for vertical-rl and bottom for horizontal-bt.
2992     if (containerBlock->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()) {
2993         if (child->isHorizontalWritingMode())
2994             logicalTopPos += containerBlock->borderBottom();
2995         else
2996             logicalTopPos += containerBlock->borderRight();
2997     } else {
2998         if (child->isHorizontalWritingMode())
2999             logicalTopPos += containerBlock->borderTop();
3000         else
3001             logicalTopPos += containerBlock->borderLeft();
3002     }
3003 }
3004
3005 void RenderBox::computePositionedLogicalHeightUsing(SizeType heightSizeType, Length logicalHeightLength, const RenderBoxModelObject* containerBlock,
3006                                                     LayoutUnit containerLogicalHeight, LayoutUnit bordersPlusPadding,
3007                                                     Length logicalTop, Length logicalBottom, Length marginBefore, Length marginAfter,
3008                                                     LayoutUnit& logicalHeightValue, LayoutUnit& marginBeforeValue, LayoutUnit& marginAfterValue, LayoutUnit& logicalTopPos)
3009 {
3010     if (heightSizeType == MinSize && logicalHeightLength.isAuto())
3011         logicalHeightLength = Length(0, Fixed);
3012
3013     // 'top' and 'bottom' cannot both be 'auto' because 'top would of been
3014     // converted to the static position in computePositionedLogicalHeight()
3015     ASSERT(!(logicalTop.isAuto() && logicalBottom.isAuto()));
3016
3017     LayoutUnit contentLogicalHeight = logicalHeight() - bordersPlusPadding;
3018
3019     LayoutUnit logicalTopValue = 0;
3020
3021     bool logicalHeightIsAuto = logicalHeightLength.isAuto();
3022     bool logicalTopIsAuto = logicalTop.isAuto();
3023     bool logicalBottomIsAuto = logicalBottom.isAuto();
3024     RenderView* renderView = view();
3025
3026     // Height is never unsolved for tables.
3027     if (isTable()) {
3028         logicalHeightLength.setValue(Fixed, contentLogicalHeight);
3029         logicalHeightIsAuto = false;
3030     }
3031
3032     if (!logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
3033         /*-----------------------------------------------------------------------*\
3034          * If none of the three are 'auto': If both 'margin-top' and 'margin-
3035          * bottom' are 'auto', solve the equation under the extra constraint that
3036          * the two margins get equal values. If one of 'margin-top' or 'margin-
3037          * bottom' is 'auto', solve the equation for that value. If the values
3038          * are over-constrained, ignore the value for 'bottom' and solve for that
3039          * value.
3040         \*-----------------------------------------------------------------------*/
3041         // NOTE:  It is not necessary to solve for 'bottom' in the over constrained
3042         // case because the value is not used for any further calculations.
3043
3044         logicalHeightValue = computeContentBoxLogicalHeight(valueForLength(logicalHeightLength, containerLogicalHeight, renderView));
3045         logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
3046
3047         const LayoutUnit availableSpace = containerLogicalHeight - (logicalTopValue + logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView) + bordersPlusPadding);
3048
3049         // Margins are now the only unknown
3050         if (marginBefore.isAuto() && marginAfter.isAuto()) {
3051             // Both margins auto, solve for equality
3052             // NOTE: This may result in negative values.
3053             marginBeforeValue = availableSpace / 2; // split the difference
3054             marginAfterValue = availableSpace - marginBeforeValue; // account for odd valued differences
3055         } else if (marginBefore.isAuto()) {
3056             // Solve for top margin
3057             marginAfterValue = valueForLength(marginAfter, containerLogicalHeight, renderView);
3058             marginBeforeValue = availableSpace - marginAfterValue;
3059         } else if (marginAfter.isAuto()) {
3060             // Solve for bottom margin
3061             marginBeforeValue = valueForLength(marginBefore, containerLogicalHeight, renderView);
3062             marginAfterValue = availableSpace - marginBeforeValue;
3063         } else {
3064             // Over-constrained, (no need solve for bottom)
3065             marginBeforeValue = valueForLength(marginBefore, containerLogicalHeight, renderView);
3066             marginAfterValue = valueForLength(marginAfter, containerLogicalHeight, renderView);
3067         }
3068     } else {
3069         /*--------------------------------------------------------------------*\
3070          * Otherwise, set 'auto' values for 'margin-top' and 'margin-bottom'
3071          * to 0, and pick the one of the following six rules that applies.
3072          *
3073          * 1. 'top' and 'height' are 'auto' and 'bottom' is not 'auto', then
3074          *    the height is based on the content, and solve for 'top'.
3075          *
3076          *              OMIT RULE 2 AS IT SHOULD NEVER BE HIT
3077          * ------------------------------------------------------------------
3078          * 2. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then
3079          *    set 'top' to the static position, and solve for 'bottom'.
3080          * ------------------------------------------------------------------
3081          *
3082          * 3. 'height' and 'bottom' are 'auto' and 'top' is not 'auto', then
3083          *    the height is based on the content, and solve for 'bottom'.
3084          * 4. 'top' is 'auto', 'height' and 'bottom' are not 'auto', and
3085          *    solve for 'top'.
3086          * 5. 'height' is 'auto', 'top' and 'bottom' are not 'auto', and
3087          *    solve for 'height'.
3088          * 6. 'bottom' is 'auto', 'top' and 'height' are not 'auto', and
3089          *    solve for 'bottom'.
3090         \*--------------------------------------------------------------------*/
3091         // NOTE: For rules 3 and 6 it is not necessary to solve for 'bottom'
3092         // because the value is not used for any further calculations.
3093
3094         // Calculate margins, 'auto' margins are ignored.
3095         marginBeforeValue = minimumValueForLength(marginBefore, containerLogicalHeight, renderView);
3096         marginAfterValue = minimumValueForLength(marginAfter, containerLogicalHeight, renderView);
3097
3098         const LayoutUnit availableSpace = containerLogicalHeight - (marginBeforeValue + marginAfterValue + bordersPlusPadding);
3099
3100         // Use rule/case that applies.
3101         if (logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
3102             // RULE 1: (height is content based, solve of top)
3103             logicalHeightValue = contentLogicalHeight;
3104             logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView));
3105         } else if (!logicalTopIsAuto && logicalHeightIsAuto && logicalBottomIsAuto) {
3106             // RULE 3: (height is content based, no need solve of bottom)
3107             logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
3108             logicalHeightValue = contentLogicalHeight;
3109         } else if (logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
3110             // RULE 4: (solve of top)
3111             logicalHeightValue = computeContentBoxLogicalHeight(valueForLength(logicalHeightLength, containerLogicalHeight, renderView));
3112             logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView));
3113         } else if (!logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
3114             // RULE 5: (solve of height)
3115             logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
3116             logicalHeightValue = max<LayoutUnit>(0, availableSpace - (logicalTopValue + valueForLength(logicalBottom, containerLogicalHeight, renderView)));
3117         } else if (!logicalTopIsAuto && !logicalHeightIsAuto && logicalBottomIsAuto) {
3118             // RULE 6: (no need solve of bottom)
3119             logicalHeightValue = computeContentBoxLogicalHeight(valueForLength(logicalHeightLength, containerLogicalHeight, renderView));
3120             logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
3121         }
3122     }
3123
3124     // Use computed values to calculate the vertical position.
3125     logicalTopPos = logicalTopValue + marginBeforeValue;
3126     computeLogicalTopPositionedOffset(logicalTopPos, this, logicalHeightValue, containerBlock, containerLogicalHeight);
3127 }
3128
3129 void RenderBox::computePositionedLogicalWidthReplaced()
3130 {
3131     // The following is based off of the W3C Working Draft from April 11, 2006 of
3132     // CSS 2.1: Section 10.3.8 "Absolutely positioned, replaced elements"
3133     // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-width>
3134     // (block-style-comments in this function correspond to text from the spec and
3135     // the numbers correspond to numbers in spec)
3136
3137     // We don't use containingBlock(), since we may be positioned by an enclosing
3138     // relative positioned inline.
3139     const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
3140
3141     const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock);
3142
3143     // To match WinIE, in quirks mode use the parent's 'direction' property
3144     // instead of the the container block's.
3145     TextDirection containerDirection = containerBlock->style()->direction();
3146
3147     // Variables to solve.
3148     bool isHorizontal = isHorizontalWritingMode();
3149     Length logicalLeft = style()->logicalLeft();
3150     Length logicalRight = style()->logicalRight();
3151     Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop();
3152     Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom();
3153     LayoutUnit& marginLogicalLeftAlias = m_marginBox.mutableLogicalLeft(style()->writingMode());
3154     LayoutUnit& marginLogicalRightAlias = m_marginBox.mutableLogicalRight(style()->writingMode());
3155
3156     /*-----------------------------------------------------------------------*\
3157      * 1. The used value of 'width' is determined as for inline replaced
3158      *    elements.
3159     \*-----------------------------------------------------------------------*/
3160     // NOTE: This value of width is FINAL in that the min/max width calculations
3161     // are dealt with in computeReplacedWidth().  This means that the steps to produce
3162     // correct max/min in the non-replaced version, are not necessary.
3163     setLogicalWidth(computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth());
3164
3165     const LayoutUnit availableSpace = containerLogicalWidth - logicalWidth();
3166
3167     /*-----------------------------------------------------------------------*\
3168      * 2. If both 'left' and 'right' have the value 'auto', then if 'direction'
3169      *    of the containing block is 'ltr', set 'left' to the static position;
3170      *    else if 'direction' is 'rtl', set 'right' to the static position.
3171     \*-----------------------------------------------------------------------*/
3172     // see FIXME 1
3173     computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, containerLogicalWidth, 0); // FIXME: Pass the region.
3174
3175     /*-----------------------------------------------------------------------*\
3176      * 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left'
3177      *    or 'margin-right' with '0'.
3178     \*-----------------------------------------------------------------------*/
3179     if (logicalLeft.isAuto() || logicalRight.isAuto()) {
3180         if (marginLogicalLeft.isAuto())
3181             marginLogicalLeft.setValue(Fixed, 0);
3182         if (marginLogicalRight.isAuto())
3183             marginLogicalRight.setValue(Fixed, 0);
3184     }
3185
3186     /*-----------------------------------------------------------------------*\
3187      * 4. If at this point both 'margin-left' and 'margin-right' are still
3188      *    'auto', solve the equation under the extra constraint that the two
3189      *    margins must get equal values, unless this would make them negative,
3190      *    in which case when the direction of the containing block is 'ltr'
3191      *    ('rtl'), set 'margin-left' ('margin-right') to zero and solve for
3192      *    'margin-right' ('margin-left').
3193     \*-----------------------------------------------------------------------*/
3194     LayoutUnit logicalLeftValue = 0;
3195     LayoutUnit logicalRightValue = 0;
3196     RenderView* renderView = view();
3197
3198     if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
3199         // 'left' and 'right' cannot be 'auto' due to step 3
3200         ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));
3201
3202         logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
3203         logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
3204
3205         LayoutUnit difference = availableSpace - (logicalLeftValue + logicalRightValue);
3206         if (difference > 0) {
3207             marginLogicalLeftAlias = difference / 2; // split the difference
3208             marginLogicalRightAlias = difference - marginLogicalLeftAlias; // account for odd valued differences
3209         } else {
3210             // Use the containing block's direction rather than the parent block's
3211             // per CSS 2.1 reference test abspos-replaced-width-margin-000.
3212             if (containerDirection == LTR) {
3213                 marginLogicalLeftAlias = 0;
3214                 marginLogicalRightAlias = difference; // will be negative
3215             } else {
3216                 marginLogicalLeftAlias = difference; // will be negative
3217                 marginLogicalRightAlias = 0;
3218             }
3219         }
3220
3221     /*-----------------------------------------------------------------------*\
3222      * 5. If at this point there is an 'auto' left, solve the equation for
3223      *    that value.
3224     \*-----------------------------------------------------------------------*/
3225     } else if (logicalLeft.isAuto()) {
3226         marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
3227         marginLogicalRightAlias = valueForLength(marginLogicalRight, containerLogicalWidth, renderView);
3228         logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
3229
3230         // Solve for 'left'
3231         logicalLeftValue = availableSpace - (logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias);
3232     } else if (logicalRight.isAuto()) {
3233         marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
3234         marginLogicalRightAlias = valueForLength(marginLogicalRight, containerLogicalWidth, renderView);
3235         logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
3236
3237         // Solve for 'right'
3238         logicalRightValue = availableSpace - (logicalLeftValue + marginLogicalLeftAlias + marginLogicalRightAlias);
3239     } else if (marginLogicalLeft.isAuto()) {
3240         marginLogicalRightAlias = valueForLength(marginLogicalRight, containerLogicalWidth, renderView);
3241         logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
3242         logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
3243
3244         // Solve for 'margin-left'
3245         marginLogicalLeftAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalRightAlias);
3246     } else if (marginLogicalRight.isAuto()) {
3247         marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
3248         logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
3249         logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
3250
3251         // Solve for 'margin-right'
3252         marginLogicalRightAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias);
3253     } else {
3254         // Nothing is 'auto', just calculate the values.
3255         marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
3256         marginLogicalRightAlias = valueForLength(marginLogicalRight, containerLogicalWidth, renderView);
3257         logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
3258         logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
3259         // If the containing block is right-to-left, then push the left position as far to the right as possible
3260         if (containerDirection == RTL) {
3261             int totalLogicalWidth = logicalWidth() + logicalLeftValue + logicalRightValue +  marginLogicalLeftAlias + marginLogicalRightAlias;
3262             logicalLeftValue = containerLogicalWidth - (totalLogicalWidth - logicalLeftValue);
3263         }
3264     }
3265
3266     /*-----------------------------------------------------------------------*\
3267      * 6. If at this point the values are over-constrained, ignore the value
3268      *    for either 'left' (in case the 'direction' property of the
3269      *    containing block is 'rtl') or 'right' (in case 'direction' is
3270      *    'ltr') and solve for that value.
3271     \*-----------------------------------------------------------------------*/
3272     // NOTE: Constraints imposed by the width of the containing block and its content have already been accounted for above.
3273
3274     // FIXME: Deal with differing writing modes here.  Our offset needs to be in the containing block's coordinate space, so that
3275     // can make the result here rather complicated to compute.
3276
3277     // Use computed values to calculate the horizontal position.
3278
3279     // FIXME: This hack is needed to calculate the logical left position for a 'rtl' relatively
3280     // positioned, inline containing block because right now, it is using the logical left position
3281     // of the first line box when really it should use the last line box.  When
3282     // this is fixed elsewhere, this block should be removed.
3283     if (containerBlock->isRenderInline() && !containerBlock->style()->isLeftToRightDirection()) {
3284         const RenderInline* flow = toRenderInline(containerBlock);
3285         InlineFlowBox* firstLine = flow->firstLineBox();
3286         InlineFlowBox* lastLine = flow->lastLineBox();
3287         if (firstLine && lastLine && firstLine != lastLine) {
3288             setLogicalLeft(logicalLeftValue + marginLogicalLeftAlias + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft()));
3289             return;
3290         }
3291     }
3292
3293     LayoutUnit logicalLeftPos = logicalLeftValue + marginLogicalLeftAlias;
3294     computeLogicalLeftPositionedOffset(logicalLeftPos, this, logicalWidth(), containerBlock, containerLogicalWidth);
3295     setLogicalLeft(logicalLeftPos.round());
3296 }
3297
3298 void RenderBox::computePositionedLogicalHeightReplaced()
3299 {
3300     // The following is based off of the W3C Working Draft from April 11, 2006 of
3301     // CSS 2.1: Section 10.6.5 "Absolutely positioned, replaced elements"
3302     // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-height>
3303     // (block-style-comments in this function correspond to text from the spec and
3304     // the numbers correspond to numbers in spec)
3305
3306     // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
3307     const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
3308
3309     const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock);
3310
3311     // Variables to solve.
3312     Length marginBefore = style()->marginBefore();
3313     Length marginAfter = style()->marginAfter();
3314     LayoutUnit& marginBeforeAlias = m_marginBox.mutableBefore(style()->writingMode());
3315     LayoutUnit& marginAfterAlias = m_marginBox.mutableAfter(style()->writingMode());
3316
3317     Length logicalTop = style()->logicalTop();
3318     Length logicalBottom = style()->logicalBottom();
3319     RenderView* renderView = view();
3320
3321     /*-----------------------------------------------------------------------*\
3322      * 1. The used value of 'height' is determined as for inline replaced
3323      *    elements.
3324     \*-----------------------------------------------------------------------*/
3325     // NOTE: This value of height is FINAL in that the min/max height calculations
3326     // are dealt with in computeReplacedHeight().  This means that the steps to produce
3327     // correct max/min in the non-replaced version, are not necessary.
3328     setLogicalHeight(computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight());
3329     const LayoutUnit availableSpace = containerLogicalHeight - logicalHeight();
3330
3331     /*-----------------------------------------------------------------------*\
3332      * 2. If both 'top' and 'bottom' have the value 'auto', replace 'top'
3333      *    with the element's static position.
3334     \*-----------------------------------------------------------------------*/
3335     // see FIXME 1
3336     computeBlockStaticDistance(logicalTop, logicalBottom, this, containerBlock);
3337
3338     /*-----------------------------------------------------------------------*\
3339      * 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or
3340      *    'margin-bottom' with '0'.
3341     \*-----------------------------------------------------------------------*/
3342     // FIXME: The spec. says that this step should only be taken when bottom is
3343     // auto, but if only top is auto, this makes step 4 impossible.
3344     if (logicalTop.isAuto() || logicalBottom.isAuto()) {
3345         if (marginBefore.isAuto())
3346             marginBefore.setValue(Fixed, 0);
3347         if (marginAfter.isAuto())
3348             marginAfter.setValue(Fixed, 0);
3349     }
3350
3351     /*-----------------------------------------------------------------------*\
3352      * 4. If at this point both 'margin-top' and 'margin-bottom' are still
3353      *    'auto', solve the equation under the extra constraint that the two
3354      *    margins must get equal values.
3355     \*-----------------------------------------------------------------------*/
3356     LayoutUnit logicalTopValue = 0;
3357     LayoutUnit logicalBottomValue = 0;
3358
3359     if (marginBefore.isAuto() && marginAfter.isAuto()) {
3360         // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined.
3361         ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto()));
3362
3363         logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
3364         logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
3365
3366         LayoutUnit difference = availableSpace - (logicalTopValue + logicalBottomValue);
3367         // NOTE: This may result in negative values.
3368         marginBeforeAlias =  difference / 2; // split the difference
3369         marginAfterAlias = difference - marginBeforeAlias; // account for odd valued differences
3370
3371     /*-----------------------------------------------------------------------*\
3372      * 5. If at this point there is only one 'auto' left, solve the equation
3373      *    for that value.
3374     \*-----------------------------------------------------------------------*/
3375     } else if (logicalTop.isAuto()) {
3376         marginBeforeAlias = valueForLength(marginBefore, containerLogicalHeight, renderView);
3377         marginAfterAlias = valueForLength(marginAfter, containerLogicalHeight, renderView);
3378         logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
3379
3380         // Solve for 'top'
3381         logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias + marginAfterAlias);
3382     } else if (logicalBottom.isAuto()) {
3383         marginBeforeAlias = valueForLength(marginBefore, containerLogicalHeight, renderView);
3384         marginAfterAlias = valueForLength(marginAfter, containerLogicalHeight, renderView);
3385         logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
3386
3387         // Solve for 'bottom'
3388         // NOTE: It is not necessary to solve for 'bottom' because we don't ever
3389         // use the value.
3390     } else if (marginBefore.isAuto()) {
3391         marginAfterAlias = valueForLength(marginAfter, containerLogicalHeight, renderView);
3392         logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
3393         logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
3394
3395         // Solve for 'margin-top'
3396         marginBeforeAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginAfterAlias);
3397     } else if (marginAfter.isAuto()) {
3398         marginBeforeAlias = valueForLength(marginBefore, containerLogicalHeight, renderView);
3399         logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
3400         logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
3401
3402         // Solve for 'margin-bottom'
3403         marginAfterAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginBeforeAlias);
3404     } else {
3405         // Nothing is 'auto', just calculate the values.
3406         marginBeforeAlias = valueForLength(marginBefore, containerLogicalHeight, renderView);
3407         marginAfterAlias = valueForLength(marginAfter, containerLogicalHeight, renderView);
3408         logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
3409         // NOTE: It is not necessary to solve for 'bottom' because we don't ever
3410         // use the value.
3411      }
3412
3413     /*-----------------------------------------------------------------------*\
3414      * 6. If at this point the values are over-constrained, ignore the value
3415      *    for 'bottom' and solve for that value.
3416     \*-----------------------------------------------------------------------*/
3417     // NOTE: It is not necessary to do this step because we don't end up using
3418     // the value of 'bottom' regardless of whether the values are over-constrained
3419     // or not.
3420
3421     // Use computed values to calculate the vertical position.
3422     LayoutUnit logicalTopPos = logicalTopValue + marginBeforeAlias;
3423     computeLogicalTopPositionedOffset(logicalTopPos, this, logicalHeight(), containerBlock, containerLogicalHeight);
3424     setLogicalTop(logicalTopPos.round());
3425 }
3426
3427 LayoutRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, LayoutUnit* extraWidthToEndOfLine)
3428 {
3429     // VisiblePositions at offsets inside containers either a) refer to the positions before/after
3430     // those containers (tables and select elements) or b) refer to the position inside an empty block.
3431     // They never refer to children.
3432     // FIXME: Paint the carets inside empty blocks differently than the carets before/after elements.
3433
3434     // FIXME: What about border and padding?
3435     LayoutRect rect(location(), LayoutSize(caretWidth, height()));
3436     bool ltr = box ? box->isLeftToRightDirection() : style()->isLeftToRightDirection();
3437
3438     if ((!caretOffset) ^ ltr)
3439         rect.move(LayoutSize(width() - caretWidth, 0));
3440
3441     if (box) {
3442         RootInlineBox* rootBox = box->root();
3443         LayoutUnit top = rootBox->lineTop();
3444         rect.setY(top);
3445         rect.setHeight(rootBox->lineBottom() - top);
3446     }
3447
3448     // If height of box is smaller than font height, use the latter one,
3449     // otherwise the caret might become invisible.
3450     //
3451     // Also, if the box is not a replaced element, always use the font height.
3452     // This prevents the "big caret" bug described in:
3453     // <rdar://problem/3777804> Deleting all content in a document can result in giant tall-as-window insertion point
3454     //
3455     // FIXME: ignoring :first-line, missing good reason to take care of
3456     LayoutUnit fontHeight = style()->fontMetrics().height();
3457     if (fontHeight > rect.height() || (!isReplaced() && !isTable()))
3458         rect.setHeight(fontHeight);
3459
3460     if (extraWidthToEndOfLine)
3461         *extraWidthToEndOfLine = x() + width() - rect.maxX();
3462
3463     // Move to local coords
3464     rect.moveBy(-location());
3465     return rect;
3466 }
3467
3468 VisiblePosition RenderBox::positionForPoint(const LayoutPoint& point)
3469 {
3470     // no children...return this render object's element, if there is one, and offset 0
3471     if (!firstChild())
3472         return createVisiblePosition(node() ? firstPositionInOrBeforeNode(node()) : Position());
3473
3474     if (isTable() && node()) {
3475         LayoutUnit right = contentWidth() + borderAndPaddingWidth();
3476         LayoutUnit bottom = contentHeight() + borderAndPaddingHeight();
3477         
3478         if (point.x() < 0 || point.x() > right || point.y() < 0 || point.y() > bottom) {
3479             if (point.x() <= right / 2)
3480                 return createVisiblePosition(firstPositionInOrBeforeNode(node()));
3481             return createVisiblePosition(lastPositionInOrAfterNode(node()));
3482         }
3483     }
3484
3485     // Pass off to the closest child.
3486     LayoutUnit minDist = MAX_LAYOUT_UNIT;
3487     RenderBox* closestRenderer = 0;
3488     LayoutPoint adjustedPoint = point;
3489     if (isTableRow())
3490         adjustedPoint.moveBy(location());
3491
3492     for (RenderObject* renderObject = firstChild(); renderObject; renderObject = renderObject->nextSibling()) {
3493         if ((!renderObject->firstChild() && !renderObject->isInline() && !renderObject->isBlockFlow() )
3494             || renderObject->style()->visibility() != VISIBLE)
3495             continue;
3496         
3497         if (!renderObject->isBox())
3498             continue;
3499         
3500         RenderBox* renderer = toRenderBox(renderObject);
3501
3502         LayoutUnit top = renderer->borderTop() + renderer->paddingTop() + (isTableRow() ? ZERO_LAYOUT_UNIT : renderer->y());
3503         LayoutUnit bottom = top + renderer->contentHeight();
3504         LayoutUnit left = renderer->borderLeft() + renderer->paddingLeft() + (isTableRow() ? ZERO_LAYOUT_UNIT : renderer->x());
3505         LayoutUnit right = left + renderer->contentWidth();
3506         
3507         if (point.x() <= right && point.x() >= left && point.y() <= top && point.y() >= bottom) {
3508             if (renderer->isTableRow())
3509                 return renderer->positionForPoint(point + adjustedPoint - renderer->locationOffset());
3510             return renderer->positionForPoint(point - renderer->locationOffset());
3511         }
3512
3513         // Find the distance from (x, y) to the box.  Split the space around the box into 8 pieces
3514         // and use a different compare depending on which piece (x, y) is in.
3515         LayoutPoint cmp;
3516         if (point.x() > right) {
3517             if (point.y() < top)
3518                 cmp = LayoutPoint(right, top);
3519             else if (point.y() > bottom)
3520                 cmp = LayoutPoint(right, bottom);
3521             else
3522                 cmp = LayoutPoint(right, point.y());
3523         } else if (point.x() < left) {
3524             if (point.y() < top)
3525                 cmp = LayoutPoint(left, top);
3526             else if (point.y() > bottom)
3527                 cmp = LayoutPoint(left, bottom);
3528             else
3529                 cmp = LayoutPoint(left, point.y());
3530         } else {
3531             if (point.y() < top)
3532                 cmp = LayoutPoint(point.x(), top);
3533             else
3534                 cmp = LayoutPoint(point.x(), bottom);
3535         }
3536
3537         LayoutSize difference = cmp - point;
3538
3539         LayoutUnit dist = difference.width() * difference.width() + difference.height() * difference.height();
3540         if (dist < minDist) {
3541             closestRenderer = renderer;
3542             minDist = dist;
3543         }
3544     }
3545     
3546     if (closestRenderer)
3547         return closestRenderer->positionForPoint(adjustedPoint - closestRenderer->locationOffset());
3548     
3549     return createVisiblePosition(firstPositionInOrBeforeNode(node()));
3550 }
3551
3552 bool RenderBox::shrinkToAvoidFloats() const
3553 {
3554     // Floating objects don't shrink.  Objects that don't avoid floats don't shrink.  Marquees don't shrink.
3555     if ((isInline() && !isHTMLMarquee()) || !avoidsFloats() || isFloating())
3556         return false;
3557     
3558     // Only auto width objects can possibly shrink to avoid floats.
3559     return style()->width().isAuto();
3560 }
3561
3562 bool RenderBox::avoidsFloats() const
3563 {
3564     return isReplaced() || hasOverflowClip() || isHR() || isLegend() || isWritingModeRoot() || isDeprecatedFlexItem();
3565 }
3566
3567 void RenderBox::addVisualEffectOverflow()
3568 {
3569     if (!style()->boxShadow() && !style()->hasBorderImageOutsets())
3570         return;
3571
3572     bool isFlipped = style()->isFlippedBlocksWritingMode();
3573     bool isHorizontal = isHorizontalWritingMode();
3574     
3575     LayoutRect borderBox = borderBoxRect();
3576     LayoutUnit overflowMinX = borderBox.x();
3577     LayoutUnit overflowMaxX = borderBox.maxX();
3578     LayoutUnit overflowMinY = borderBox.y();
3579     LayoutUnit overflowMaxY = borderBox.maxY();
3580     
3581     // Compute box-shadow overflow first.
3582     if (style()->boxShadow()) {
3583         LayoutUnit shadowLeft;
3584         LayoutUnit shadowRight;
3585         LayoutUnit shadowTop;
3586         LayoutUnit shadowBottom;
3587         style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft);
3588
3589         // In flipped blocks writing modes such as vertical-rl, the physical right shadow value is actually at the lower x-coordinate.
3590         overflowMinX = borderBox.x() + ((!isFlipped || isHorizontal) ? shadowLeft : -shadowRight);
3591         overflowMaxX = borderBox.maxX() + ((!isFlipped || isHorizontal) ? shadowRight : -shadowLeft);
3592         overflowMinY = borderBox.y() + ((!isFlipped || !isHorizontal) ? shadowTop : -shadowBottom);
3593         overflowMaxY = borderBox.maxY() + ((!isFlipped || !isHorizontal) ? shadowBottom : -shadowTop);
3594     }
3595
3596     // Now compute border-image-outset overflow.
3597     if (style()->hasBorderImageOutsets()) {
3598         LayoutBoxExtent borderOutsets = style()->borderImageOutsets();
3599         
3600         // In flipped blocks writing modes, the physical sides are inverted. For example in vertical-rl, the right
3601         // border is at the lower x coordinate value.
3602         overflowMinX = min(overflowMinX, borderBox.x() - ((!isFlipped || isHorizontal) ? borderOutsets.left() : borderOutsets.right()));
3603         overflowMaxX = max(overflowMaxX, borderBox.maxX() + ((!isFlipped || isHorizontal) ? borderOutsets.right() : borderOutsets.left()));
3604         overflowMinY = min(overflowMinY, borderBox.y() - ((!isFlipped || !isHorizontal) ? borderOutsets.top() : borderOutsets.bottom()));
3605         overflowMaxY = max(overflowMaxY, borderBox.maxY() + ((!isFlipped || !isHorizontal) ? borderOutsets.bottom() : borderOutsets.top()));
3606     }
3607
3608     // Add in the final overflow with shadows and outsets combined.
3609     addVisualOverflow(LayoutRect(overflowMinX, overflowMinY, overflowMaxX - overflowMinX, overflowMaxY - overflowMinY));
3610 }
3611
3612 void RenderBox::addOverflowFromChild(RenderBox* child, const LayoutSize& delta)
3613 {
3614     // Only propagate layout overflow from the child if the child isn't clipping its overflow.  If it is, then
3615     // its overflow is internal to it, and we don't care about it.  layoutOverflowRectForPropagation takes care of this
3616     // and just propagates the border box rect instead.
3617     LayoutRect childLayoutOverflowRect = child->layoutOverflowRectForPropagation(style());
3618     childLayoutOverflowRect.move(delta);
3619     addLayoutOverflow(childLayoutOverflowRect);
3620             
3621     // Add in visual overflow from the child.  Even if the child clips its overflow, it may still
3622     // have visual overflow of its own set from box shadows or reflections.  It is unnecessary to propagate this
3623     // overflow if we are clipping our own overflow.
3624     if (child->hasSelfPaintingLayer() || hasOverflowClip())
3625         return;
3626     LayoutRect childVisualOverflowRect = child->visualOverflowRectForPropagation(style());
3627     childVisualOverflowRect.move(delta);
3628     addVisualOverflow(childVisualOverflowRect);
3629 }
3630
3631 void RenderBox::addLayoutOverflow(const LayoutRect& rect)
3632 {
3633     LayoutRect clientBox = clientBoxRect();
3634     if (clientBox.contains(rect) || rect.isEmpty())
3635         return;
3636     
3637     // For overflow clip objects, we don't want to propagate overflow into unreachable areas.
3638     LayoutRect overflowRect(rect);
3639     if (hasOverflowClip() || isRenderView()) {
3640         // Overflow is in the block's coordinate space and thus is flipped for horizontal-bt and vertical-rl 
3641         // writing modes.  At this stage that is actually a simplification, since we can treat horizontal-tb/bt as the same
3642         // and vertical-lr/rl as the same.
3643         bool hasTopOverflow = !style()->isLeftToRightDirection() && !isHorizontalWritingMode();
3644         bool hasLeftOverflow = !style()->isLeftToRightDirection() && isHorizontalWritingMode();
3645         if (isFlexibleBox() && style()->isReverseFlexDirection()) {
3646             RenderFlexibleBox* flexibleBox = static_cast<RenderFlexibleBox*>(this);
3647             if (flexibleBox->isHorizontalFlow())
3648                 hasLeftOverflow = true;
3649             else
3650                 hasTopOverflow = true;
3651         }
3652
3653         if (hasColumns() && style()->columnProgression() == ReverseColumnProgression) {
3654             if (isHorizontalWritingMode() ^ !style()->hasInlineColumnAxis())
3655                 hasLeftOverflow = !hasLeftOverflow;
3656             else
3657                 hasTopOverflow = !hasTopOverflow;
3658         }
3659
3660         if (!hasTopOverflow)
3661             overflowRect.shiftYEdgeTo(max(overflowRect.y(), clientBox.y()));
3662         else
3663             overflowRect.shiftMaxYEdgeTo(min(overflowRect.maxY(), clientBox.maxY()));
3664         if (!hasLeftOverflow)
3665             overflowRect.shiftXEdgeTo(max(overflowRect.x(), clientBox.x()));
3666         else
3667             overflowRect.shiftMaxXEdgeTo(min(overflowRect.maxX(), clientBox.maxX()));
3668         
3669         // Now re-test with the adjusted rectangle and see if it has become unreachable or fully
3670         // contained.
3671         if (clientBox.contains(overflowRect) || overflowRect.isEmpty())
3672             return;
3673     }
3674
3675     if (!m_overflow)
3676         m_overflow = adoptPtr(new RenderOverflow(clientBox, borderBoxRect()));
3677     
3678     m_overflow->addLayoutOverflow(overflowRect);
3679 }
3680
3681 void RenderBox::addVisualOverflow(const LayoutRect& rect)
3682 {
3683     LayoutRect borderBox = borderBoxRect();
3684     if (borderBox.contains(rect) || rect.isEmpty())
3685         return;
3686         
3687     if (!m_overflow)
3688         m_overflow = adoptPtr(new RenderOverflow(clientBoxRect(), borderBox));
3689     
3690     m_overflow->addVisualOverflow(rect);
3691 }
3692
3693 void RenderBox::clearLayoutOverflow()
3694 {
3695     if (!m_overflow)
3696         return;
3697     
3698     if (visualOverflowRect() == borderBoxRect()) {
3699         m_overflow.clear();
3700         return;
3701     }
3702     
3703     m_overflow->setLayoutOverflow(borderBoxRect());
3704 }
3705
3706 static bool percentageLogicalHeightIsResolvable(const RenderBox* box)
3707 {
3708     // In quirks mode, blocks with auto height are skipped, and we keep looking for an enclosing
3709     // block that may have a specified height and then use it. In strict mode, this violates the
3710     // specification, which states that percentage heights just revert to auto if the containing
3711     // block has an auto height. We still skip anonymous containing blocks in both modes, though, and look
3712     // only at explicit containers.
3713     const RenderBlock* cb = box->containingBlock();
3714     while (!cb->isRenderView() && !cb->isBody() && !cb->isTableCell() && !cb->isOutOfFlowPositioned() && cb->style()->logicalHeight().isAuto()) {
3715         if (!box->document()->inQuirksMode() && !cb->isAnonymousBlock())
3716             break;
3717         cb = cb->containingBlock();
3718     }
3719
3720     // A positioned element that specified both top/bottom or that specifies height should be treated as though it has a height
3721     // explicitly specified that can be used for any percentage computations.
3722     // FIXME: We can't just check top/bottom here.
3723     // https://bugs.webkit.org/show_bug.cgi?id=46500
3724     bool isOutOfFlowPositionedWithSpecifiedHeight = cb->isOutOfFlowPositioned() && (!cb->style()->logicalHeight().isAuto() || (!cb->style()->top().isAuto() && !cb->style()->bottom().isAuto()));
3725
3726     // Table cells violate what the CSS spec says to do with heights.  Basically we
3727     // don't care if the cell specified a height or not.  We just always make ourselves
3728     // be a percentage of the cell's current content height.
3729     if (cb->isTableCell())
3730         return true;
3731
3732     // Otherwise we only use our percentage height if our containing block had a specified
3733     // height.
3734     if (cb->style()->logicalHeight().isFixed())
3735         return true;
3736     if (cb->style()->logicalHeight().isPercent() && !isOutOfFlowPositionedWithSpecifiedHeight)
3737         return percentageLogicalHeightIsResolvable(cb);
3738     if (cb->isRenderView() || (cb->isBody() && box->document()->inQuirksMode()) || isOutOfFlowPositionedWithSpecifiedHeight)
3739         return true;
3740     if (cb->isRoot() && box->isOutOfFlowPositioned()) {
3741         // Match the positioned objects behavior, which is that positioned objects will fill their viewport
3742         // always.  Note we could only hit this case by recurring into computePercentageLogicalHeight on a positioned containing block.
3743         return true;
3744     }
3745
3746     return false;
3747 }
3748
3749 bool RenderBox::hasUnsplittableScrollingOverflow() const
3750 {
3751     // We will paginate as long as we don't scroll overflow in the pagination direction.
3752     bool isHorizontal = isHorizontalWritingMode();
3753     if ((isHorizontal && !scrollsOverflowY()) || (!isHorizontal && !scrollsOverflowX()))
3754         return false;
3755     
3756     // We do have overflow. We'll still be willing to paginate as long as the block
3757     // has auto logical height, auto or undefined max-logical-height and a zero or auto min-logical-height.
3758     // Note this is just a heuristic, and it's still possible to have overflow under these
3759     // conditions, but it should work out to be good enough for common cases. Paginating overflow
3760     // with scrollbars present is not the end of the world and is what we used to do in the old model anyway.
3761     return !style()->logicalHeight().isIntrinsicOrAuto()
3762         || (!style()->logicalMaxHeight().isIntrinsicOrAuto() && !style()->logicalMaxHeight().isUndefined() && (!style()->logicalMaxHeight().isPercent() || percentageLogicalHeightIsResolvable(this)))
3763         || (!style()->logicalMinHeight().isIntrinsicOrAuto() && style()->logicalMinHeight().isPositive() && (!style()->logicalMinHeight().isPercent() || percentageLogicalHeightIsResolvable(this)));
3764 }
3765
3766 bool RenderBox::isUnsplittableForPagination() const
3767 {
3768     return isReplaced() || hasUnsplittableScrollingOverflow() || (parent() && isWritingModeRoot());
3769 }
3770
3771 LayoutUnit RenderBox::lineHeight(bool /*firstLine*/, LineDirectionMode direction, LinePositionMode /*linePositionMode*/) const
3772 {
3773     if (isReplaced())
3774         return direction == HorizontalLine ? m_marginBox.top() + height() + m_marginBox.bottom() : m_marginBox.right() + width() + m_marginBox.left();
3775     return 0;
3776 }
3777
3778 LayoutUnit RenderBox::baselinePosition(FontBaseline baselineType, bool /*firstLine*/, LineDirectionMode direction, LinePositionMode /*linePositionMode*/) const
3779 {
3780     if (isReplaced()) {
3781         LayoutUnit result = direction == HorizontalLine ? m_marginBox.top() + height() + m_marginBox.bottom() : m_marginBox.right() + width() + m_marginBox.left();
3782         if (baselineType == AlphabeticBaseline)
3783             return result;
3784         return result - result / 2;
3785     }
3786     return 0;
3787 }
3788
3789
3790 RenderLayer* RenderBox::enclosingFloatPaintingLayer() const
3791 {
3792     const RenderObject* curr = this;
3793     while (curr) {
3794         RenderLayer* layer = curr->hasLayer() && curr->isBox() ? toRenderBoxModelObject(curr)->layer() : 0;
3795         if (layer && layer->isSelfPaintingLayer())
3796             return layer;
3797         curr = curr->parent();
3798     }
3799     return 0;
3800 }
3801
3802 LayoutRect RenderBox::logicalVisualOverflowRectForPropagation(RenderStyle* parentStyle) const
3803 {
3804     LayoutRect rect = visualOverflowRectForPropagation(parentStyle);
3805     if (!parentStyle->isHorizontalWritingMode())
3806         return rect.transposedRect();
3807     return rect;
3808 }
3809
3810 LayoutRect RenderBox::visualOverflowRectForPropagation(RenderStyle* parentStyle) const
3811 {
3812     // If the writing modes of the child and parent match, then we don't have to 
3813     // do anything fancy. Just return the result.
3814     LayoutRect rect = visualOverflowRect();
3815     if (parentStyle->writingMode() == style()->writingMode())
3816         return rect;
3817     
3818     // We are putting ourselves into our parent's coordinate space.  If there is a flipped block mismatch
3819     // in a particular axis, then we have to flip the rect along that axis.
3820     if (style()->writingMode() == RightToLeftWritingMode || parentStyle->writingMode() == RightToLeftWritingMode)
3821         rect.setX(width() - rect.maxX());
3822     else if (style()->writingMode() == BottomToTopWritingMode || parentStyle->writingMode() == BottomToTopWritingMode)
3823         rect.setY(height() - rect.maxY());
3824
3825     return rect;
3826 }
3827
3828 LayoutRect RenderBox::logicalLayoutOverflowRectForPropagation(RenderStyle* parentStyle) const
3829 {
3830     LayoutRect rect = layoutOverflowRectForPropagation(parentStyle);
3831     if (!parentStyle->isHorizontalWritingMode())
3832         return rect.transposedRect();
3833     return rect;
3834 }
3835
3836 LayoutRect RenderBox::layoutOverflowRectForPropagation(RenderStyle* parentStyle) const
3837 {
3838     // Only propagate interior layout overflow if we don't clip it.
3839     LayoutRect rect = borderBoxRect();
3840     if (!hasOverflowClip())
3841         rect.unite(layoutOverflowRect());
3842
3843     bool hasTransform = hasLayer() && layer()->transform();
3844     if (isRelPositioned() || hasTransform) {
3845         // If we are relatively positioned or if we have a transform, then we have to convert
3846         // this rectangle into physical coordinates, apply relative positioning and transforms
3847         // to it, and then convert it back.
3848         flipForWritingMode(rect);
3849         
3850         if (hasTransform)
3851             rect = layer()->currentTransform().mapRect(rect);
3852
3853         if (isRelPositioned())
3854             rect.move(relativePositionOffset());
3855         
3856         // Now we need to flip back.
3857         flipForWritingMode(rect);
3858     }
3859     
3860     // If the writing modes of the child and parent match, then we don't have to 
3861     // do anything fancy. Just return the result.
3862     if (parentStyle->writingMode() == style()->writingMode())
3863         return rect;
3864     
3865     // We are putting ourselves into our parent's coordinate space.  If there is a flipped block mismatch
3866     // in a particular axis, then we have to flip the rect along that axis.
3867     if (style()->writingMode() == RightToLeftWritingMode || parentStyle->writingMode() == RightToLeftWritingMode)
3868         rect.setX(width() - rect.maxX());
3869     else if (style()->writingMode() == BottomToTopWritingMode || parentStyle->writingMode() == BottomToTopWritingMode)
3870         rect.setY(height() - rect.maxY());
3871
3872     return rect;
3873 }
3874
3875 LayoutUnit RenderBox::offsetLeft() const
3876 {
3877     return adjustedPositionRelativeToOffsetParent(topLeftLocation()).x();
3878 }
3879
3880 LayoutUnit RenderBox::offsetTop() const
3881 {
3882     return adjustedPositionRelativeToOffsetParent(topLeftLocation()).y();
3883 }
3884
3885 LayoutPoint RenderBox::flipForWritingModeForChild(const RenderBox* child, const LayoutPoint& point) const
3886 {
3887     if (!style()->isFlippedBlocksWritingMode())
3888         return point;
3889     
3890     // The child is going to add in its x() and y(), so we have to make sure it ends up in
3891     // the right place.
3892     if (isHorizontalWritingMode())
3893         return LayoutPoint(point.x(), point.y() + height() - child->height() - (2 * child->y()));
3894     return LayoutPoint(point.x() + width() - child->width() - (2 * child->x()), point.y());
3895 }
3896
3897 void RenderBox::flipForWritingMode(LayoutRect& rect) const
3898 {
3899     if (!style()->isFlippedBlocksWritingMode())
3900         return;
3901
3902     if (isHorizontalWritingMode())
3903         rect.setY(height() - rect.maxY());
3904     else
3905         rect.setX(width() - rect.maxX());
3906 }
3907
3908 LayoutUnit RenderBox::flipForWritingMode(LayoutUnit position) const
3909 {
3910     if (!style()->isFlippedBlocksWritingMode())
3911         return position;
3912     return logicalHeight() - position;
3913 }
3914
3915 LayoutPoint RenderBox::flipForWritingMode(const LayoutPoint& position) const
3916 {
3917     if (!style()->isFlippedBlocksWritingMode())
3918         return position;
3919     return isHorizontalWritingMode() ? LayoutPoint(position.x(), height() - position.y()) : LayoutPoint(width() - position.x(), position.y());
3920 }
3921
3922 LayoutPoint RenderBox::flipForWritingModeIncludingColumns(const LayoutPoint& point) const
3923 {
3924     if (!hasColumns() || !style()->isFlippedBlocksWritingMode())
3925         return flipForWritingMode(point);
3926     return toRenderBlock(this)->flipForWritingModeIncludingColumns(point);
3927 }
3928
3929 LayoutSize RenderBox::flipForWritingMode(const LayoutSize& offset) const
3930 {
3931     if (!style()->isFlippedBlocksWritingMode())
3932         return offset;
3933     return isHorizontalWritingMode() ? LayoutSize(offset.width(), height() - offset.height()) : LayoutSize(width() - offset.width(), offset.height());
3934 }
3935
3936 FloatPoint RenderBox::flipForWritingMode(const FloatPoint& position) const
3937 {
3938     if (!style()->isFlippedBlocksWritingMode())
3939         return position;
3940     return isHorizontalWritingMode() ? FloatPoint(position.x(), height() - position.y()) : FloatPoint(width() - position.x(), position.y());
3941 }
3942
3943 void RenderBox::flipForWritingMode(FloatRect& rect) const
3944 {
3945     if (!style()->isFlippedBlocksWritingMode())
3946         return;
3947
3948     if (isHorizontalWritingMode())
3949         rect.setY(height() - rect.maxY());
3950     else
3951         rect.setX(width() - rect.maxX());
3952 }
3953
3954 LayoutPoint RenderBox::topLeftLocation() const
3955 {
3956     RenderBlock* containerBlock = containingBlock();
3957     if (!containerBlock || containerBlock == this)
3958         return location();
3959     return containerBlock->flipForWritingModeForChild(this, location());
3960 }
3961
3962 LayoutSize RenderBox::topLeftLocationOffset() const
3963 {
3964     RenderBlock* containerBlock = containingBlock();
3965     if (!containerBlock || containerBlock == this)
3966         return locationOffset();
3967     
3968     LayoutRect rect(frameRect());
3969     if (containerBlock->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
3970         rect.move(containerBlock->verticalScrollbarWidth(), 0);
3971     containerBlock->flipForWritingMode(rect); // FIXME: This is wrong if we are an absolutely positioned object enclosed by a relative-positioned inline.
3972     return LayoutSize(rect.x(), rect.y());
3973 }
3974
3975 bool RenderBox::hasRelativeDimensions() const
3976 {
3977     return style()->height().isPercent() || style()->width().isPercent()
3978             || style()->maxHeight().isPercent() || style()->maxWidth().isPercent()
3979             || style()->minHeight().isPercent() || style()->minWidth().isPercent();
3980 }
3981
3982 bool RenderBox::hasRelativeLogicalHeight() const
3983 {
3984     return style()->logicalHeight().isPercent()
3985             || style()->logicalMinHeight().isPercent()
3986             || style()->logicalMaxHeight().isPercent();
3987 }
3988
3989 static void markBoxForRelayoutAfterSplit(RenderBox* box)
3990 {
3991     // FIXME: The table code should handle that automatically. If not,
3992     // we should fix it and remove the table part checks.
3993     if (box->isTable()) {
3994         // Because we may have added some sections with already computed column structures, we need to
3995         // sync the table structure with them now. This avoids crashes when adding new cells to the table.
3996         toRenderTable(box)->forceSectionsRecalc();
3997     } else if (box->isTableSection())
3998         toRenderTableSection(box)->setNeedsCellRecalc();
3999
4000     box->setNeedsLayoutAndPrefWidthsRecalc();
4001 }
4002
4003 RenderObject* RenderBox::splitAnonymousBoxesAroundChild(RenderObject* beforeChild)
4004 {
4005     bool didSplitParentAnonymousBoxes = false;
4006
4007     while (beforeChild->parent() != this) {
4008         RenderBox* boxToSplit = toRenderBox(beforeChild->parent());
4009         if (boxToSplit->firstChild() != beforeChild && boxToSplit->isAnonymous()) {
4010             didSplitParentAnonymousBoxes = true;
4011
4012             // We have to split the parent box into two boxes and move children
4013             // from |beforeChild| to end into the new post box.
4014             RenderBox* postBox = boxToSplit->createAnonymousBoxWithSameTypeAs(this);
4015             postBox->setChildrenInline(boxToSplit->childrenInline());
4016             RenderBox* parentBox = toRenderBox(boxToSplit->parent());
4017             parentBox->virtualChildren()->insertChildNode(parentBox, postBox, boxToSplit->nextSibling());
4018             boxToSplit->moveChildrenTo(postBox, beforeChild, 0, true);
4019
4020             markBoxForRelayoutAfterSplit(boxToSplit);
4021             markBoxForRelayoutAfterSplit(postBox);
4022
4023             beforeChild = postBox;
4024         } else
4025             beforeChild = boxToSplit;
4026     }
4027
4028     if (didSplitParentAnonymousBoxes)
4029         markBoxForRelayoutAfterSplit(this);
4030
4031     ASSERT(beforeChild->parent() == this);
4032     return beforeChild;
4033 }
4034
4035 } // namespace WebCore