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