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