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