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