Changeset 14351 in webkit


Ignore:
Timestamp:
May 13, 2006, 7:58:24 AM (19 years ago)
Author:
ap
Message:

2006-05-13 Sam Weinig <sam.weinig@gmail.com>

Reviewed by Hyatt, landed by ap.

WebCore:

Patch for http://bugzilla.opendarwin.org/show_bug.cgi?id=7604
calcAbsoluteHorizontalValues() is being getting passed arguments
in the wrong order in calcAbsoluteHorizontal()

Cleans up the RenderBox code for absolutely positioned elements
and adds new functions for replaced absolutely positioned
elements. Now uses Length so that magic number -666666 for
auto lengths is no longer used.

  • rendering/RenderBox.cpp: (WebCore::RenderBox::calcAbsoluteHorizontal): (WebCore::RenderBox::calcAbsoluteHorizontalValues): (WebCore::RenderBox::calcAbsoluteVertical): (WebCore::RenderBox::calcAbsoluteVerticalValues): (WebCore::RenderBox::calcAbsoluteHorizontalReplaced): Handle replaced case separately. (WebCore::RenderBox::calcAbsoluteVerticalReplaced): ditto.
  • rendering/RenderBox.h:

LayoutTests:

  • fast/block/positioning/absolute-length-of-neg-666666.html: Added.
  • fast/block/positioning/absolute-positioned-overconstrained.html: Added.
  • fast/block/positioning/auto/006.html: Updated to reflect that the containing block's direction, not the parent's is used.
  • fast/css/absolute-poition-in-rtl-parent.html: Updated and cleaned up.
Location:
trunk
Files:
8 added
7 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/LayoutTests/ChangeLog

    r14347 r14351  
     12006-05-13  Sam Weinig  <sam.weinig@gmail.com>
     2
     3        Reviewed by Hyatt, landed by ap.
     4
     5        - tests for http://bugzilla.opendarwin.org/show_bug.cgi?id=7604
     6       
     7        * fast/block/positioning/absolute-length-of-neg-666666.html: Added.
     8        * fast/block/positioning/absolute-positioned-overconstrained.html: Added.
     9        * fast/block/positioning/auto/006.html: Updated to reflect that the containing
     10        block's direction, not the parent's is used.
     11        * fast/css/absolute-poition-in-rtl-parent.html: Updated and cleaned up.
     12
    1132006-05-12  Mitz Pettel  <opendarwin.org@mitzpettel.com>
    214
  • TabularUnified trunk/LayoutTests/fast/block/positioning/auto/006.html

    r11995 r14351  
    33In this test, you should see three blocks that are aligned right within a black box.  They should
    44be stacked vertically with the green box in between two olive boxes.  The olive boxes and the green box
    5 should be 100x100, and there should be 100 pixels of padding on the right side of the box stack. 
     5should be 100x100, and there should be 100 pixels of padding on the left side of the box stack. 
    66
    7 <p style="direction:rtl">The
    8 black box's top should be aligned with the end of the last line in this parargaph and its left side should begin right after the end of this sentence.
     7<p style="position: relative; direction:rtl">The
     8black box's top should be aligned with the end of the last line in this parargaph and its right side should begin right after the end of this sentence.
    99
    1010 <span style="direction:rtl; position:absolute;width:100px;height:200px;border:20px solid black;padding-top:50px;padding-bottom:50px;padding-left:100px;padding-right:0px">
  • TabularUnified trunk/LayoutTests/fast/css/absolute-poition-in-rtl-parent-expected.txt

    r13869 r14351  
    77        RenderText {#text} at (0,0) size 768x54
    88          text run at (0,0) width 502: "On the left, you should see three blocks that are aligned left within a black box. "
    9           text run at (502,0) width 266: "They should be stacked vertically with the"
     9          text run at (502,0) width 83: "They should "
     10          text run at (585,0) width 183: "be stacked vertically with the"
    1011          text run at (0,18) width 248: "green box in between two olive boxes. "
    11           text run at (248,18) width 502: "The olive boxes and the green box should be 100x100, and there should be 100"
     12          text run at (248,18) width 194: "The olive boxes and the green "
     13          text run at (442,18) width 308: "box should be 100x100, and there should be 100"
    1214          text run at (0,36) width 322: "pixels of padding on the right side of the box stack."
    1315      RenderBlock {P} at (0,70) size 784x54
    1416        RenderText {#text} at (0,0) size 753x54
    1517          text run at (0,0) width 487: "On the right, you should see two blocks that are centered within a black box. "
    16           text run at (487,0) width 266: "They should be stacked vertically with the"
    17           text run at (0,18) width 747: "green box below the olive box. The olive box and the green box should be 100x100, and there should be 100 pixels of"
     18          text run at (487,0) width 102: "They should be "
     19          text run at (589,0) width 164: "stacked vertically with the"
     20          text run at (0,18) width 455: "green box below the olive box. The olive box and the green box should "
     21          text run at (455,18) width 292: "be 100x100, and there should be 100 pixels of"
    1822          text run at (0,36) width 247: "padding on either side of the box stack."
    1923layer at (8,148) size 240x340
     
    3034layer at (300,148) size 340x240
    3135  RenderBlock (positioned) {DIV} at (300,148) size 340x240 [border: (20px solid #000000)]
    32     RenderBlock {DIV} at (20,20) size 200x100
    33       RenderBlock {DIV} at (100,0) size 100x100 [bgcolor=#808000]
     36layer at (320,168) size 200x100
     37  RenderBlock (relative positioned) {DIV} at (20,20) size 200x100
     38    RenderBlock {DIV} at (100,0) size 100x100 [bgcolor=#808000]
    3439layer at (420,268) size 100x100
    35   RenderBlock (positioned) {DIV} at (120,120) size 100x100 [bgcolor=#008000]
     40  RenderBlock (positioned) {DIV} at (100,100) size 100x100 [bgcolor=#008000]
  • TabularUnified trunk/LayoutTests/fast/css/absolute-poition-in-rtl-parent.html

    r11995 r14351  
    11<html>
     2<head>
     3  <title>Absolute Position in RTL parent</title>
     4  <style>
     5    .containingBlock { position: fixed; border: 20px solid black; }
     6    #cbOne { width: 200px; height: 300px; }
     7    #cbOne > table { direction: rtl; width: 100px; }
     8    #cbTwo { width: 300px; height: 200px; left: 300px; }
     9    #cbTwo > div { position: relative; direction: rtl; width: 200px; }
     10
     11    .box { width: 100px; height: 100px; }
     12    #test1 { background: olive; }
     13    #test2 { position: absolute; background: green; }
     14    #test3 { position: absolute; bottom: 0; right: 100px; background: olive; }   
     15  </style>
     16</head>
    217<body>
    3 <p>
    4 On the left, you should see three blocks that are aligned left within a black box.  They should
    5 be stacked vertically with the green box in between two olive boxes.  The olive boxes and the green box
    6 should be 100x100, and there should be 100 pixels of padding on the right side of the box stack.
    7 </p>
    8 <p>
    9 On the right, you should see two blocks that are centered within a black box.  They should be
    10 stacked vertically with the green box below the olive box. The olive box and the green box should
    11 be 100x100, and there should be 100 pixels of padding on either side of the box stack.
    12 </p>
    13 <div style="position:fixed;width:200px;height:300px;border:20px solid black;">
    14 <table style="direction:rtl; width:100px;" cellspacing="0" cellpadding="0">
    15 <tr>
    16 <td>
    17 <div style="width:100px; height:100px; background:olive;"></div>
    18 <div style="position:absolute; width:100px; height:100px; background:green;"></div>
    19 <div style="position:absolute; width:100px; height:100px; background:olive; bottom:0; right:100px;"></div>
    20 </td>
    21 </tr>
    22 </table>
    23 </div>
    24 <div style="position:fixed;width:300px;height:200px;border:20px solid black; left:300px;">
    25 <div style="direction:rtl; width:200px;">
    26 <div style="width:100px; height:100px; background:olive;"></div>
    27 <div style="position:absolute; width:100px; height:100px; background:green;"></div>
    28 </div>
    29 </div>
    30 
     18  <p>On the left, you should see three blocks that are aligned left within a black box.  They should
     19    be stacked vertically with the green box in between two olive boxes.  The olive boxes and the green
     20    box should be 100x100, and there should be 100 pixels of padding on the right side of the box stack.
     21  </p>
     22  <p>On the right, you should see two blocks that are centered within a black box.  They should be
     23    stacked vertically with the green box below the olive box. The olive box and the green box should
     24    be 100x100, and there should be 100 pixels of padding on either side of the box stack.
     25  </p>
     26  <div id="cbOne" class="containingBlock">
     27    <table cellspacing="0" cellpadding="0">
     28      <tr>
     29        <td>
     30          <div id="test1" class="box"></div>
     31          <div id="test2" class="box"></div>
     32          <div id="test3" class="box"></div>
     33        </td>
     34      </tr>
     35    </table>
     36  </div>
     37  <div id="cbTwo" class="containingBlock">
     38    <div>
     39      <div id="test1" class="box"></div>
     40      <div id="test2" class="box"></div>
     41    </div>
     42  </div>
    3143</body>
    3244</html>
  • TabularUnified trunk/WebCore/ChangeLog

    r14350 r14351  
     12006-05-13  Sam Weinig  <sam.weinig@gmail.com>
     2
     3        Reviewed by Hyatt, landed by ap.
     4
     5        Patch for http://bugzilla.opendarwin.org/show_bug.cgi?id=7604
     6        calcAbsoluteHorizontalValues() is being getting passed arguments
     7        in the wrong order in calcAbsoluteHorizontal()
     8
     9        Cleans up the RenderBox code for absolutely positioned elements
     10        and adds new functions for replaced absolutely positioned
     11        elements. Now uses Length so that magic number -666666 for
     12        auto lengths is no longer used.
     13
     14        * rendering/RenderBox.cpp:
     15        (WebCore::RenderBox::calcAbsoluteHorizontal):
     16        (WebCore::RenderBox::calcAbsoluteHorizontalValues):
     17        (WebCore::RenderBox::calcAbsoluteVertical):
     18        (WebCore::RenderBox::calcAbsoluteVerticalValues):
     19        (WebCore::RenderBox::calcAbsoluteHorizontalReplaced): Handle replaced
     20        case separately.
     21        (WebCore::RenderBox::calcAbsoluteVerticalReplaced): ditto.
     22        * rendering/RenderBox.h:
     23
    1242006-05-12  David Hyatt  <hyatt@apple.com>
    225
  • TabularUnified trunk/WebCore/rendering/RenderBox.cpp

    r14336 r14351  
    55 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
    66 *           (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
    7  *           (C) 2005 Samuel Weinig (sam.weinig@gmail.com)
     7 *           (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
    88 * Copyright (C) 2005 Apple Computer, Inc.
    99 *
     
    3333#include "GraphicsContext.h"
    3434#include "HTMLElement.h"
    35 #include "RenderTableCell.h"
    3635#include "HTMLNames.h"
    3736#include "RenderArena.h"
    3837#include "RenderCanvas.h"
    3938#include "RenderFlexibleBox.h"
     39#include "RenderTableCell.h"
    4040#include "RenderTheme.h"
    4141#include <assert.h>
     42#include <algorithm>
    4243#include <math.h>
    4344
     
    14151416void RenderBox::calcAbsoluteHorizontal()
    14161417{
    1417     const int AUTO = -666666;
    1418     int l, r, cw;
    1419 
    1420     int pab = borderLeft()+ borderRight()+ paddingLeft()+ paddingRight();
    1421 
    1422     l = r = AUTO;
    1423  
     1418    if (isReplaced()) {
     1419        calcAbsoluteHorizontalReplaced();
     1420        return;
     1421    }
     1422
     1423
     1424    // QUESTIONS
     1425    // FIXME 1: Which RenderObject's 'direction' property should used: the
     1426    // containing block (cb) as the spec seems to imply, the parent (parent()) as
     1427    // was previously done in calculating the static distances, or ourself, which
     1428    // was also previously done for deciding what to override when you had
     1429    // over-constrained margins?  Also note that the container block is used
     1430    // in similar situations in other parts of the RenderBox class (see calcWidth()
     1431    // and calcHorizontalMargins()).
     1432
     1433    // FIXME 2: Should we still deal with these the cases of 'left' or 'right' having
     1434    // the type 'static' in determining whether to calculate the static distance?
     1435    // NOTE: 'static' is not a legal value for 'left' or 'right' as of CSS 2.1.
     1436
     1437    // FIXME 3: Can perhaps optimize out cases when max-width/min-width are greater
     1438    // than or less than the computed m_width.  Be careful of box-sizing and
     1439    // percentage issues.
     1440
     1441    // The following is based off of the W3C Working Draft from April 11, 2006 of
     1442    // CSS 2.1: Section 10.3.7 "Absolutely positioned, non-replaced elements"
     1443    // <http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width>
     1444    // (block-style-comments in this function and in calcAbsoluteHorizontalValues()
     1445    // correspond to text from the spec)
     1446
     1447
     1448    // We don't use containingBlock(), since we may be positioned by an enclosing
     1449    // relative positioned inline.
     1450    const RenderObject* containerBlock = container();
     1451   
     1452    // FIXME: This is incorrect for cases where the container block is a relatively
     1453    // positioned inline.
     1454    const int containerWidth = containingBlockWidth() + containerBlock->paddingLeft() + containerBlock->paddingRight();
     1455   
     1456    const int bordersPlusPadding = borderLeft() + borderRight() + paddingLeft() + paddingRight();
     1457    const Length marginLeft = style()->marginLeft();
     1458    const Length marginRight = style()->marginRight();
     1459    Length left = style()->left();
     1460    Length right = style()->right();
     1461
     1462    /*---------------------------------------------------------------------------*\
     1463     * For the purposes of this section and the next, the term "static position"
     1464     * (of an element) refers, roughly, to the position an element would have had
     1465     * in the normal flow. More precisely:
     1466     *
     1467     * * The static position for 'left' is the distance from the left edge of the
     1468     *   containing block to the left margin edge of a hypothetical box that would
     1469     *   have been the first box of the element if its 'position' property had
     1470     *   been 'static' and 'float' had been 'none'. The value is negative if the
     1471     *   hypothetical box is to the left of the containing block.
     1472     * * The static position for 'right' is the distance from the right edge of the
     1473     *   containing block to the right margin edge of the same hypothetical box as
     1474     *   above. The value is positive if the hypothetical box is to the left of the
     1475     *   containing block's edge.
     1476     *
     1477     * But rather than actually calculating the dimensions of that hypothetical box,
     1478     * user agents are free to make a guess at its probable position.
     1479     *
     1480     * For the purposes of calculating the static position, the containing block of
     1481     * fixed positioned elements is the initial containing block instead of the
     1482     * viewport, and all scrollable boxes should be assumed to be scrolled to their
     1483     * origin.
     1484    \*---------------------------------------------------------------------------*/
     1485
     1486    // see FIXME 2
     1487    // Calculate the static distance if needed.
     1488    if (left.isAuto() && right.isAuto()) {
     1489        if (containerBlock->style()->direction() == LTR) {
     1490            // 'm_staticX' should already have been set through layout of the parent.
     1491            int staticPosition = m_staticX - containerBlock->borderLeft();
     1492            for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent())
     1493                staticPosition += po->xPos();
     1494            left.setValue(Fixed, staticPosition);
     1495        } else {
     1496            RenderObject* po = parent();
     1497            // 'm_staticX' should already have been set through layout of the parent.
     1498            int staticPosition = m_staticX + containerWidth + containerBlock->borderRight() - po->width();
     1499            for (; po && po != containerBlock; po = po->parent())
     1500                staticPosition -= po->xPos();
     1501            right.setValue(Fixed, staticPosition);
     1502        }
     1503    }
     1504
     1505    // Calculate constraint equation values for 'width' case.
     1506    calcAbsoluteHorizontalValues(style()->width(), containerBlock, containerWidth, bordersPlusPadding,
     1507                                 left, right, marginLeft, marginRight,
     1508                                 m_width, m_marginLeft, m_marginRight, m_x);
     1509
     1510    // Calculate constraint equation values for 'max-width' case.calcContentBoxWidth(width.calcValue(containerWidth));
     1511    if (style()->maxWidth().value() != undefinedLength) {
     1512        int maxWidth;
     1513        int maxMarginLeft;
     1514        int maxMarginRight;
     1515        int maxXPos;
     1516
     1517        calcAbsoluteHorizontalValues(style()->maxWidth(), containerBlock, containerWidth, bordersPlusPadding,
     1518                                     left, right, marginLeft, marginRight,
     1519                                     maxWidth, maxMarginLeft, maxMarginRight, maxXPos);
     1520
     1521        if (m_width > maxWidth) {
     1522            m_width = maxWidth;
     1523            m_marginLeft = maxMarginLeft;
     1524            m_marginRight = maxMarginRight;
     1525            m_x = maxXPos;
     1526        }
     1527    }
     1528
     1529    // Calculate constraint equation values for 'min-width' case.
     1530    if (style()->minWidth().value()) {
     1531        int minWidth;
     1532        int minMarginLeft;
     1533        int minMarginRight;
     1534        int minXPos;
     1535
     1536        calcAbsoluteHorizontalValues(style()->minWidth(), containerBlock, containerWidth, bordersPlusPadding,
     1537                                     left, right, marginLeft, marginRight,
     1538                                     minWidth, minMarginLeft, minMarginRight, minXPos);
     1539
     1540        if (m_width < minWidth) {
     1541            m_width = minWidth;
     1542            m_marginLeft = minMarginLeft;
     1543            m_marginRight = minMarginRight;
     1544            m_x = minXPos;
     1545        }
     1546    }
     1547
     1548    // Put m_width into correct form.
     1549    m_width += bordersPlusPadding;
     1550}
     1551
     1552void RenderBox::calcAbsoluteHorizontalValues(Length width, const RenderObject* containerBlock,
     1553                                             const int containerWidth, const int bordersPlusPadding,
     1554                                             const Length left, const Length right, const Length marginLeft, const Length marginRight,
     1555                                             int& widthValue, int& marginLeftValue, int& marginRightValue, int& xPos)
     1556{
     1557    // 'left' and 'right' cannot both be 'auto' because one would of been
     1558    // converted to the static postion already
     1559    ASSERT(!(left.isAuto() && right.isAuto()));
     1560
     1561    int leftValue;
     1562
     1563    bool widthIsAuto = width.isIntrinsicOrAuto();
     1564    bool leftIsAuto = left.isAuto();
     1565    bool rightIsAuto = right.isAuto();
     1566
     1567    if (!leftIsAuto && !widthIsAuto && !rightIsAuto) {
     1568        /*-----------------------------------------------------------------------*\
     1569         * If none of the three is 'auto': If both 'margin-left' and 'margin-
     1570         * right' are 'auto', solve the equation under the extra constraint that
     1571         * the two margins get equal values, unless this would make them negative,
     1572         * in which case when direction of the containing block is 'ltr' ('rtl'),
     1573         * set 'margin-left' ('margin-right') to zero and solve for 'margin-right'
     1574         * ('margin-left'). If one of 'margin-left' or 'margin-right' is 'auto',
     1575         * solve the equation for that value. If the values are over-constrained,
     1576         * ignore the value for 'left' (in case the 'direction' property of the
     1577         * containing block is 'rtl') or 'right' (in case 'direction' is 'ltr')
     1578         * and solve for that value.
     1579        \*-----------------------------------------------------------------------*/
     1580        // NOTE:  It is not necessary to solve for 'right' in the over constrained
     1581        // case because the value is not used for any further calculations.
     1582
     1583        leftValue = left.calcValue(containerWidth);
     1584        widthValue = calcContentBoxWidth(width.calcValue(containerWidth));
     1585
     1586        const int availableSpace = containerWidth - (leftValue + widthValue + right.calcValue(containerWidth) + bordersPlusPadding);
     1587
     1588        // Margins are now the only unknown
     1589        if (marginLeft.isAuto() && marginRight.isAuto()) {
     1590            // Both margins auto, solve for equality
     1591            if (availableSpace >= 0) {
     1592                marginLeftValue = availableSpace / 2; // split the diference
     1593                marginRightValue = availableSpace - marginLeftValue;  // account for odd valued differences
     1594            } else {
     1595                // see FIXME 1
     1596                if (containerBlock->style()->direction() == LTR) {
     1597                    marginLeftValue = 0;
     1598                    marginRightValue = availableSpace; // will be negative
     1599                } else {
     1600                    marginLeftValue = availableSpace; // will be negative
     1601                    marginRightValue = 0;
     1602                }
     1603            }
     1604        } else if (marginLeft.isAuto()) {
     1605            // Solve for left margin
     1606            marginRightValue = marginRight.calcValue(containerWidth);
     1607            marginLeftValue = availableSpace - marginRightValue;
     1608        } else if (marginRight.isAuto()) {
     1609            // Solve for right margin
     1610            marginLeftValue = marginLeft.calcValue(containerWidth);
     1611            marginRightValue = availableSpace - marginLeftValue;
     1612        } else {
     1613            // Over-constrained, solve for left if direction is RTL
     1614            marginLeftValue = marginLeft.calcValue(containerWidth);
     1615            marginRightValue = marginRight.calcValue(containerWidth);
     1616
     1617            // see FIXME 1 -- used to be "this->style()->direction()"
     1618            if (containerBlock->style()->direction() == RTL)
     1619                leftValue = (availableSpace + leftValue) - marginLeftValue - marginRightValue;
     1620        }
     1621    } else {
     1622        /*--------------------------------------------------------------------*\
     1623         * Otherwise, set 'auto' values for 'margin-left' and 'margin-right'
     1624         * to 0, and pick the one of the following six rules that applies.
     1625         *
     1626         * 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the
     1627         *    width is shrink-to-fit. Then solve for 'left'
     1628         *
     1629         *              OMIT RULE 2 AS IT SHOULD NEVER BE HIT
     1630         * ------------------------------------------------------------------
     1631         * 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if
     1632         *    the 'direction' property of the containing block is 'ltr' set
     1633         *    'left' to the static position, otherwise set 'right' to the
     1634         *    static position. Then solve for 'left' (if 'direction is 'rtl')
     1635         *    or 'right' (if 'direction' is 'ltr').
     1636         * ------------------------------------------------------------------
     1637         *
     1638         * 3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the
     1639         *    width is shrink-to-fit . Then solve for 'right'
     1640         * 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve
     1641         *    for 'left'
     1642         * 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve
     1643         *    for 'width'
     1644         * 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve
     1645         *    for 'right'
     1646         *
     1647         * Calculation of the shrink-to-fit width is similar to calculating the
     1648         * width of a table cell using the automatic table layout algorithm.
     1649         * Roughly: calculate the preferred width by formatting the content
     1650         * without breaking lines other than where explicit line breaks occur,
     1651         * and also calculate the preferred minimum width, e.g., by trying all
     1652         * possible line breaks. CSS 2.1 does not define the exact algorithm.
     1653         * Thirdly, calculate the available width: this is found by solving
     1654         * for 'width' after setting 'left' (in case 1) or 'right' (in case 3)
     1655         * to 0.
     1656         *
     1657         * Then the shrink-to-fit width is:
     1658         * min(max(preferred minimum width, available width), preferred width).
     1659        \*--------------------------------------------------------------------*/
     1660        // NOTE: For rules 3 and 6 it is not necessary to solve for 'right'
     1661        // because the value is not used for any further calculations.
     1662
     1663        // Calculate margins, 'auto' margins are ignored.
     1664        marginLeftValue = marginLeft.calcMinValue(containerWidth);
     1665        marginRightValue = marginRight.calcMinValue(containerWidth);
     1666
     1667        const int availableSpace = containerWidth - (marginLeftValue + marginRightValue + bordersPlusPadding);
     1668
     1669        // FIXME: Is there a faster way to find the correct case?
     1670        // Use rule/case that applies.
     1671        if (leftIsAuto && widthIsAuto && !rightIsAuto) {
     1672            // RULE 1: (use shrink-to-fit for width, and solve of left)
     1673            int rightValue = right.calcValue(containerWidth);
     1674
     1675            // FIXME: would it be better to have shrink-to-fit in one step?
     1676            int preferredWidth = m_maxWidth - bordersPlusPadding;
     1677            int preferredMinWidth = m_minWidth - bordersPlusPadding;
     1678            int availableWidth = availableSpace - rightValue;
     1679            widthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
     1680            leftValue = availableSpace - (widthValue + rightValue);
     1681        } else if (!leftIsAuto && widthIsAuto && rightIsAuto) {
     1682            // RULE 3: (use shrink-to-fit for width, and no need solve of right)
     1683            leftValue = left.calcValue(containerWidth);
     1684
     1685            // FIXME: would it be better to have shrink-to-fit in one step?
     1686            int preferredWidth = m_maxWidth - bordersPlusPadding;
     1687            int preferredMinWidth = m_minWidth - bordersPlusPadding;
     1688            int availableWidth = availableSpace - leftValue;
     1689            widthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
     1690        } else if (leftIsAuto && !width.isAuto() && !rightIsAuto) {
     1691            // RULE 4: (solve for left)
     1692            widthValue = calcContentBoxWidth(width.calcValue(containerWidth));
     1693            leftValue = availableSpace - (widthValue + right.calcValue(containerWidth));
     1694        } else if (!leftIsAuto && widthIsAuto && !rightIsAuto) {
     1695            // RULE 5: (solve for width)
     1696            leftValue = left.calcValue(containerWidth);
     1697            widthValue = availableSpace - (leftValue + right.calcValue(containerWidth));
     1698        } else if (!leftIsAuto&& !widthIsAuto && rightIsAuto) {
     1699            // RULE 6: (no need solve for right)
     1700            leftValue = left.calcValue(containerWidth);
     1701            widthValue = calcContentBoxWidth(width.calcValue(containerWidth));
     1702        }
     1703    }
     1704
     1705    // Use computed values to calculate the horizontal position.
     1706    xPos = leftValue + marginLeftValue + containerBlock->borderLeft();
     1707}
     1708
     1709void RenderBox::calcAbsoluteVertical()
     1710{
     1711    if (isReplaced()) {
     1712        calcAbsoluteVerticalReplaced();
     1713        return;
     1714    }
     1715
     1716    // The following is based off of the W3C Working Draft from April 11, 2006 of
     1717    // CSS 2.1: Section 10.6.4 "Absolutely positioned, non-replaced elements"
     1718    // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-non-replaced-height>
     1719    // (block-style-comments in this function and in calcAbsoluteVerticalValues()
     1720    // correspond to text from the spec)
     1721
     1722
    14241723    // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
    1425     RenderObject* cb = container();
    1426     cw = containingBlockWidth() + cb->paddingLeft() + cb->paddingRight();
    1427 
    1428     if (!style()->left().isAuto())
    1429         l = style()->left().calcValue(cw);
    1430     if (!style()->right().isAuto())
    1431         r = style()->right().calcValue(cw);
    1432 
    1433     int static_distance=0;
    1434     if ((parent()->style()->direction()==LTR && (l == AUTO && r == AUTO))
    1435             || style()->left().isStatic())
    1436     {
    1437         static_distance = m_staticX - cb->borderLeft(); // Should already have been set through layout of the parent().
    1438         RenderObject* po = parent();
    1439         for (; po && po != cb; po = po->parent())
    1440             static_distance += po->xPos();
    1441 
    1442         l = static_distance;
    1443     }
    1444 
    1445     else if ((parent()->style()->direction()==RTL && (l==AUTO && r==AUTO ))
    1446             || style()->right().isStatic())
    1447     {
    1448         RenderObject* po = parent();
    1449         static_distance = m_staticX + cw + cb->borderRight() - po->width(); // Should already have been set through layout of the parent().
    1450         while (po && po!=containingBlock()) {
    1451             static_distance -= po->xPos();
    1452             po=po->parent();
    1453         }
    1454 
    1455         r = static_distance;
    1456     }
    1457 
    1458     calcAbsoluteHorizontalValues(Width, cb, cw, pab, static_distance, l, r, m_width, m_marginLeft, m_marginRight, m_x);
    1459 
    1460     // Avoid doing any work in the common case (where the values of min-width and max-width are their defaults).
    1461     int minW = m_width, minML, minMR, minX;
    1462     calcAbsoluteHorizontalValues(MinWidth, cb, cw, pab, static_distance, l, r, minW, minML, minMR, minX);
    1463 
    1464     int maxW = m_width, maxML, maxMR, maxX;
    1465     if (style()->maxWidth().value() != undefinedLength)
    1466         calcAbsoluteHorizontalValues(MaxWidth, cb, cw, static_distance, pab, l, r, maxW, maxML, maxMR, maxX);
    1467 
    1468     if (m_width > maxW) {
    1469         m_width = maxW;
    1470         m_marginLeft = maxML;
    1471         m_marginRight = maxMR;
    1472         m_x = maxX;
    1473     }
    1474    
    1475     if (m_width < minW) {
    1476         m_width = minW;
    1477         m_marginLeft = minML;
    1478         m_marginRight = minMR;
    1479         m_x = minX;
    1480     }
    1481 }
    1482 
    1483 void RenderBox::calcAbsoluteHorizontalValues(WidthType widthType, RenderObject* cb, int cw, int pab, int static_distance,
    1484                                              int l, int r, int& w, int& ml, int& mr, int& x)
    1485 {
    1486     const int AUTO = -666666;
    1487     w = ml = mr = AUTO;
    1488 
    1489     if (!style()->marginLeft().isAuto())
    1490         ml = style()->marginLeft().calcValue(cw);
    1491     if (!style()->marginRight().isAuto())
    1492         mr = style()->marginRight().calcValue(cw);
    1493 
    1494     Length width;
    1495     if (widthType == Width)
    1496         width = style()->width();
    1497     else if (widthType == MinWidth)
    1498         width = style()->minWidth();
    1499     else
    1500         width = style()->maxWidth();
    1501 
    1502     if (!width.isIntrinsicOrAuto())
    1503         w = calcContentBoxWidth(width.calcValue(cw));
    1504     else if (isReplaced())
    1505         w = calcReplacedWidth();
    1506 
    1507     if (l != AUTO && w != AUTO && r != AUTO) {
    1508         // left, width, right all given, play with margins
    1509         int ot = l + w + r + pab;
    1510 
    1511         if (ml==AUTO && mr==AUTO) {
    1512             // both margins auto, solve for equality
    1513             ml = (cw - ot)/2;
    1514             mr = cw - ot - ml;
    1515         }
    1516         else if (ml==AUTO)
    1517             // solve for left margin
    1518             ml = cw - ot - mr;
    1519         else if (mr==AUTO)
    1520             // solve for right margin
    1521             mr = cw - ot - ml;
    1522         else {
    1523             // overconstrained, solve according to dir
    1524             if (style()->direction() == LTR)
    1525                 r = cw - ( l + w + ml + mr + pab);
    1526             else
    1527                 l = cw - ( r + w + ml + mr + pab);
    1528         }
    1529     }
    1530     else
    1531     {
    1532         // one or two of (left, width, right) missing, solve
    1533 
    1534         // auto margins are ignored
    1535         if (ml==AUTO) ml = 0;
    1536         if (mr==AUTO) mr = 0;
    1537 
    1538         //1. solve left & width.
    1539         if (l == AUTO && w == AUTO && r != AUTO) {
    1540             // From section 10.3.7 of the CSS2.1 specification.
    1541             // "The shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width)."
    1542             w = min(max(m_minWidth - pab, cw - (r + ml + mr + pab)), m_maxWidth - pab);
    1543             l = cw - (r + w + ml + mr + pab);
    1544         }
    1545         else
    1546 
    1547         //2. solve left & right. use static positioning.
    1548         if (l == AUTO && w != AUTO && r == AUTO) {
    1549             if (style()->direction()==RTL) {
    1550                 r = static_distance;
    1551                 l = cw - (r + w + ml + mr + pab);
     1724    const RenderObject* containerBlock = container();
     1725
     1726    // Even in strict mode (where we don't grow the root to fill the viewport) other browsers
     1727    // position as though the root fills the viewport.
     1728    const int containerHeight = containerBlock->isRoot() ? containerBlock->availableHeight() : (containerBlock->height() - containerBlock->borderTop() - containerBlock->borderBottom());
     1729   
     1730    const int bordersPlusPadding = borderTop() + borderBottom() + paddingTop() + paddingBottom();
     1731    const Length marginTop = style()->marginTop();
     1732    const Length marginBottom = style()->marginBottom();
     1733    Length top = style()->top();
     1734    Length bottom = style()->bottom();
     1735
     1736    /*---------------------------------------------------------------------------*\
     1737     * For the purposes of this section and the next, the term "static position"
     1738     * (of an element) refers, roughly, to the position an element would have had
     1739     * in the normal flow. More precisely, the static position for 'top' is the
     1740     * distance from the top edge of the containing block to the top margin edge
     1741     * of a hypothetical box that would have been the first box of the element if
     1742     * its 'position' property had been 'static' and 'float' had been 'none'. The
     1743     * value is negative if the hypothetical box is above the containing block.
     1744     *
     1745     * But rather than actually calculating the dimensions of that hypothetical
     1746     * box, user agents are free to make a guess at its probable position.
     1747     *
     1748     * For the purposes of calculating the static position, the containing block
     1749     * of fixed positioned elements is the initial containing block instead of
     1750     * the viewport.
     1751    \*---------------------------------------------------------------------------*/
     1752
     1753    // see FIXME 2
     1754    // Calculate the static distance if needed.
     1755    if (top.isAuto() && bottom.isAuto()) {
     1756        // m_staticY should already have been set through layout of the parent()
     1757        int staticTop = m_staticY - containerBlock->borderTop();
     1758        for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
     1759            if (!po->isTableRow())
     1760                staticTop += po->yPos();
     1761        }
     1762        top.setValue(Fixed, staticTop);
     1763    }
     1764
     1765
     1766    int height; // Needed to compute overflow.
     1767
     1768    // Calculate constraint equation values for 'height' case.
     1769    calcAbsoluteVerticalValues(style()->height(), containerBlock, containerHeight, bordersPlusPadding,
     1770                               top, bottom, marginTop, marginBottom,
     1771                               height, m_marginTop, m_marginBottom, m_y);
     1772
     1773    // Avoid doing any work in the common case (where the values of min-height and max-height are their defaults).   
     1774    // see FIXME 3
     1775
     1776    // Calculate constraint equation values for 'max-height' case.
     1777    if (style()->maxHeight().value() != undefinedLength) {
     1778        int maxHeight;
     1779        int maxMarginTop;
     1780        int maxMarginBottom;
     1781        int maxYPos;
     1782
     1783        calcAbsoluteVerticalValues(style()->maxHeight(), containerBlock, containerHeight, bordersPlusPadding,
     1784                                   top, bottom, marginTop, marginBottom,
     1785                                   maxHeight, maxMarginTop, maxMarginBottom, maxYPos);
     1786
     1787        if (height > maxHeight) {
     1788            height = maxHeight;
     1789            m_marginTop = maxMarginTop;
     1790            m_marginBottom = maxMarginBottom;
     1791            m_y = maxYPos;
     1792        }
     1793    }
     1794
     1795    // Calculate constraint equation values for 'min-height' case.
     1796    if (style()->minHeight().value()) {
     1797        int minHeight;
     1798        int minMarginTop;
     1799        int minMarginBottom;
     1800        int minYPos;
     1801
     1802        calcAbsoluteVerticalValues(style()->minHeight(), containerBlock, containerHeight, bordersPlusPadding,
     1803                                   top, bottom, marginTop, marginBottom,
     1804                                   minHeight, minMarginTop, minMarginBottom, minYPos);
     1805
     1806        if (height < minHeight) {
     1807            height = minHeight;
     1808            m_marginTop = minMarginTop;
     1809            m_marginBottom = minMarginBottom;
     1810            m_y = minYPos;
     1811        }
     1812    }
     1813
     1814    // If our natural height exceeds the new height once we've set it, then we
     1815    // need to make sure to update overflow to track the spillout.
     1816    if (m_height > height)
     1817        setOverflowHeight(m_height);
     1818
     1819    // Set final height value.
     1820    m_height = height;
     1821}
     1822
     1823void RenderBox::calcAbsoluteVerticalValues(Length height, const RenderObject* containerBlock,
     1824                                           const int containerHeight, const int bordersPlusPadding,
     1825                                           const Length top, const Length bottom, const Length marginTop, const Length marginBottom,
     1826                                           int& heightValue, int& marginTopValue, int& marginBottomValue, int& yPos)
     1827{
     1828    // 'top' and 'bottom' cannot both be 'auto' because 'top would of been
     1829    // converted to the static position in calcAbsoluteVertical()
     1830    ASSERT(!(top.isAuto() && bottom.isAuto()));
     1831
     1832    int contentHeight = m_height - bordersPlusPadding;   
     1833
     1834    int topValue;
     1835
     1836    bool heightIsAuto = height.isAuto();
     1837    bool topIsAuto = top.isAuto();
     1838    bool bottomIsAuto = bottom.isAuto();
     1839
     1840    // Height is never unsolved for tables.
     1841    if (isTable() && heightIsAuto) {
     1842        height.setValue(Fixed, contentHeight);
     1843        heightIsAuto = false;
     1844    } else if (!heightIsAuto)
     1845        contentHeight = min(contentHeight, calcContentBoxHeight(height.calcValue(containerHeight)));
     1846
     1847    if (!topIsAuto && !heightIsAuto && !bottomIsAuto) {
     1848        /*-----------------------------------------------------------------------*\
     1849         * If none of the three are 'auto': If both 'margin-top' and 'margin-
     1850         * bottom' are 'auto', solve the equation under the extra constraint that
     1851         * the two margins get equal values. If one of 'margin-top' or 'margin-
     1852         * bottom' is 'auto', solve the equation for that value. If the values
     1853         * are over-constrained, ignore the value for 'bottom' and solve for that
     1854         * value.
     1855        \*-----------------------------------------------------------------------*/
     1856        // NOTE:  It is not necessary to solve for 'bottom' in the over constrained
     1857        // case because the value is not used for any further calculations.
     1858
     1859        heightValue = calcContentBoxHeight(height.calcValue(containerHeight));
     1860        topValue = top.calcValue(containerHeight);
     1861
     1862        const int availableSpace = containerHeight - (topValue + heightValue + bottom.calcValue(containerHeight) + bordersPlusPadding);
     1863
     1864        // Margins are now the only unknown
     1865        if (marginTop.isAuto() && marginBottom.isAuto()) {
     1866            // Both margins auto, solve for equality
     1867            // NOTE: This may result in negative values.
     1868            marginTopValue = availableSpace / 2; // split the diference
     1869            marginBottomValue = availableSpace - marginTopValue; // account for odd valued differences
     1870        } else if (marginTop.isAuto()) {
     1871            // Solve for top margin
     1872            marginBottomValue = marginBottom.calcValue(containerHeight);
     1873            marginTopValue = availableSpace - marginBottomValue;
     1874        } else if (marginBottom.isAuto()) {
     1875            // Solve for bottom margin
     1876            marginTopValue = marginTop.calcValue(containerHeight);
     1877            marginBottomValue = availableSpace - marginTopValue;
     1878        } else {
     1879            // Over-constrained, (no need solve for bottom)
     1880            marginTopValue = marginTop.calcValue(containerHeight);
     1881            marginBottomValue = marginBottom.calcValue(containerHeight);
     1882        }
     1883    } else {
     1884        /*--------------------------------------------------------------------*\
     1885         * Otherwise, set 'auto' values for 'margin-top' and 'margin-bottom'
     1886         * to 0, and pick the one of the following six rules that applies.
     1887         *
     1888         * 1. 'top' and 'height' are 'auto' and 'bottom' is not 'auto', then
     1889         *    the height is based on the content, and solve for 'top'.
     1890         *
     1891         *              OMIT RULE 2 AS IT SHOULD NEVER BE HIT
     1892         * ------------------------------------------------------------------
     1893         * 2. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then
     1894         *    set 'top' to the static position, and solve for 'bottom'.
     1895         * ------------------------------------------------------------------
     1896         *
     1897         * 3. 'height' and 'bottom' are 'auto' and 'top' is not 'auto', then
     1898         *    the height is based on the content, and solve for 'bottom'.
     1899         * 4. 'top' is 'auto', 'height' and 'bottom' are not 'auto', and
     1900         *    solve for 'top'.
     1901         * 5. 'height' is 'auto', 'top' and 'bottom' are not 'auto', and
     1902         *    solve for 'height'.
     1903         * 6. 'bottom' is 'auto', 'top' and 'height' are not 'auto', and
     1904         *    solve for 'bottom'.
     1905        \*--------------------------------------------------------------------*/
     1906        // NOTE: For rules 3 and 6 it is not necessary to solve for 'bottom'
     1907        // because the value is not used for any further calculations.
     1908
     1909        // Calculate margins, 'auto' margins are ignored.
     1910        marginTopValue = marginTop.calcMinValue(containerHeight);
     1911        marginBottomValue = marginBottom.calcMinValue(containerHeight);
     1912
     1913        const int availableSpace = containerHeight - (marginTopValue + marginBottomValue + bordersPlusPadding);
     1914
     1915        // Use rule/case that applies.
     1916        if (topIsAuto && heightIsAuto && !bottomIsAuto) {
     1917            // RULE 1: (height is content based, solve of top)
     1918            heightValue = contentHeight;
     1919            topValue = availableSpace - (heightValue + bottom.calcValue(containerHeight));
     1920        } else if (!topIsAuto && heightIsAuto && bottomIsAuto) {
     1921            // RULE 3: (height is content based, no need solve of bottom)
     1922            topValue = top.calcValue(containerHeight);
     1923            heightValue = contentHeight;
     1924        } else if (topIsAuto && !heightIsAuto && !bottomIsAuto) {
     1925            // RULE 4: (solve of top)
     1926            heightValue = calcContentBoxHeight(height.calcValue(containerHeight));
     1927            topValue = availableSpace - (heightValue + bottom.calcValue(containerHeight));
     1928        } else if (!topIsAuto && heightIsAuto && !bottomIsAuto) {
     1929            // RULE 5: (solve of height)
     1930            topValue = top.calcValue(containerHeight);
     1931            heightValue = availableSpace - (topValue + bottom.calcValue(containerHeight));
     1932        } else if (!topIsAuto && !heightIsAuto && bottomIsAuto) {
     1933            // RULE 6: (no need solve of bottom)
     1934            heightValue = calcContentBoxHeight(height.calcValue(containerHeight));
     1935            topValue = top.calcValue(containerHeight);
     1936        }
     1937    }
     1938
     1939    // Make final adjustments to height.
     1940    if (!(contentHeight < heightValue) && !(hasOverflowClip() && contentHeight > heightValue))
     1941        heightValue = contentHeight;
     1942
     1943    // Do not allow the height to be negative.  This can happen when someone
     1944    // specifies both top and bottom but the containing block height is less
     1945    // than top, e.g., top: 20px, bottom: 0, containing block height 16.
     1946    heightValue = max(0, heightValue + bordersPlusPadding);
     1947
     1948    // Use computed values to calculate the vertical position.
     1949    yPos = topValue + marginTopValue + containerBlock->borderTop();
     1950}
     1951
     1952void RenderBox::calcAbsoluteHorizontalReplaced()
     1953{   
     1954    // The following is based off of the W3C Working Draft from April 11, 2006 of
     1955    // CSS 2.1: Section 10.3.8 "Absolutly positioned, replaced elements"
     1956    // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-width>
     1957    // (block-style-comments in this function correspond to text from the spec and
     1958    // the numbers correspond to numbers in spec)
     1959
     1960    // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
     1961    const RenderObject* containerBlock = container();
     1962    const int containerWidth = containingBlockWidth() + containerBlock->paddingLeft() + containerBlock->paddingRight();
     1963
     1964    // Variables to solve.
     1965    Length left = style()->left();
     1966    Length right = style()->right();
     1967    Length marginLeft = style()->marginLeft();
     1968    Length marginRight = style()->marginRight();
     1969
     1970
     1971    /*-----------------------------------------------------------------------*\
     1972     * 1. The used value of 'width' is determined as for inline replaced
     1973     *    elements.
     1974    \*-----------------------------------------------------------------------*/
     1975    // NOTE: This value of width is FINAL in that the min/max width calculations
     1976    // are dealt with in calcReplacedWidth().  This means that the steps to produce
     1977    // correct max/min in the non-replaced version, are not necessary.
     1978    m_width = calcReplacedWidth() + borderLeft() + borderRight() + paddingLeft() + paddingRight();
     1979    const int availableSpace = containerWidth - m_width;
     1980
     1981    /*-----------------------------------------------------------------------*\
     1982     * 2. If both 'left' and 'right' have the value 'auto', then if 'direction'
     1983     *    of the containing block is 'ltr', set 'left' to the static position;
     1984     *    else if 'direction' is 'rtl', set 'right' to the static position.
     1985    \*-----------------------------------------------------------------------*/
     1986    // see FIXME 2
     1987    if (left.isAuto() && right.isAuto()) {
     1988        // see FIXME 1
     1989        if (containerBlock->style()->direction() == LTR) {
     1990            // 'm_staticX' should already have been set through layout of the parent.
     1991            int staticPosition = m_staticX - containerBlock->borderLeft();
     1992            for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent())
     1993                staticPosition += po->xPos();
     1994            left.setValue(Fixed, staticPosition);
     1995        } else {
     1996            RenderObject* po = parent();
     1997            // 'm_staticX' should already have been set through layout of the parent.
     1998            int staticPosition = m_staticX + containerWidth + containerBlock->borderRight() - po->width();
     1999            for (; po && po != containerBlock; po = po->parent())
     2000                staticPosition -= po->xPos();
     2001            right.setValue(Fixed, staticPosition);
     2002        }
     2003    }
     2004
     2005    /*-----------------------------------------------------------------------*\
     2006     * 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left'
     2007     *    or 'margin-right' with '0'.
     2008    \*-----------------------------------------------------------------------*/
     2009    if (left.isAuto() || right.isAuto()) {
     2010        if (marginLeft.isAuto())
     2011            marginLeft.setValue(Fixed, 0);
     2012        if (marginRight.isAuto())
     2013            marginRight.setValue(Fixed, 0);
     2014    }
     2015
     2016    /*-----------------------------------------------------------------------*\
     2017     * 4. If at this point both 'margin-left' and 'margin-right' are still
     2018     *    'auto', solve the equation under the extra constraint that the two
     2019     *    margins must get equal values, unless this would make them negative,
     2020     *    in which case when the direction of the containing block is 'ltr'
     2021     *    ('rtl'), set 'margin-left' ('margin-right') to zero and solve for
     2022     *    'margin-right' ('margin-left').
     2023    \*-----------------------------------------------------------------------*/
     2024    int leftValue;
     2025    int rightValue;
     2026
     2027    if (marginLeft.isAuto() && marginRight.isAuto()) {
     2028        // 'left' and 'right' cannot be 'auto' due to step 3
     2029        ASSERT(!(left.isAuto() && right.isAuto()));
     2030
     2031        leftValue = left.calcValue(containerWidth);
     2032        rightValue = right.calcValue(containerWidth);
     2033
     2034        int difference = availableSpace - (leftValue + rightValue);
     2035        if (difference > 0) {
     2036            m_marginLeft = difference / 2; // split the diference
     2037            m_marginRight = difference - m_marginLeft; // account for odd valued differences
     2038        } else {
     2039            // see FIXME 1
     2040            if (containerBlock->style()->direction() == LTR) {
     2041                m_marginLeft = 0;
     2042                m_marginRight = difference;  // will be negative
     2043            } else {
     2044                m_marginLeft = difference;  // will be negative
     2045                m_marginRight = 0;
    15522046            }
    1553             else {
    1554                 l = static_distance;
    1555                 r = cw - (l + w + ml + mr + pab);
    1556             }
    1557 
    1558         } //3. solve width & right.
    1559         else if (l != AUTO && w == AUTO && r == AUTO) {
    1560             // From section 10.3.7 of the CSS2.1 specification.
    1561             // "The shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width)."
    1562             w = min(max(m_minWidth - pab, cw - (l + ml + mr + pab)), m_maxWidth - pab);
    1563             r = cw - (l + w + ml + mr + pab);
    1564         }
    1565         else
    1566 
    1567         //4. solve left
    1568         if (l==AUTO && w!=AUTO && r!=AUTO)
    1569             l = cw - (r + w + ml + mr + pab);
    1570         else
    1571         //5. solve width
    1572         if (l!=AUTO && w==AUTO && r!=AUTO)
    1573             w = cw - (r + l + ml + mr + pab);
    1574         else
    1575 
    1576         //6. solve right
    1577         if (l!=AUTO && w!=AUTO && r==AUTO)
    1578             r = cw - (l + w + ml + mr + pab);
    1579     }
    1580 
    1581     w += pab;
    1582     x = l + ml + cb->borderLeft();
    1583 }
    1584 
    1585 void RenderBox::calcAbsoluteVertical()
    1586 {
    1587     // css2 spec 10.6.4 & 10.6.5
    1588 
    1589     // based on
    1590     // http://www.w3.org/Style/css2-updates/REC-CSS2-19980512-errata
    1591     // (actually updated 2000-10-24)
    1592     // that introduces static-position value for top, left & right
    1593 
    1594     const int AUTO = -666666;
    1595     int t, b, ch;
    1596 
    1597     t = b = AUTO;
    1598 
    1599     int pab = borderTop()+borderBottom()+paddingTop()+paddingBottom();
     2047        }
     2048
     2049    /*-----------------------------------------------------------------------*\
     2050     * 5. If at this point there is an 'auto' left, solve the equation for
     2051     *    that value.
     2052    \*-----------------------------------------------------------------------*/
     2053    } else if (left.isAuto()) {
     2054        m_marginLeft = marginLeft.calcValue(containerWidth);
     2055        m_marginRight = marginRight.calcValue(containerWidth);
     2056        rightValue = right.calcValue(containerWidth);
     2057
     2058        // Solve for 'left'
     2059        leftValue = availableSpace - (rightValue + m_marginLeft + m_marginRight);
     2060    } else if (right.isAuto()) {
     2061        m_marginLeft = marginLeft.calcValue(containerWidth);
     2062        m_marginRight = marginRight.calcValue(containerWidth);
     2063        leftValue = left.calcValue(containerWidth);
     2064
     2065        // Solve for 'right'
     2066        rightValue = availableSpace - (leftValue + m_marginLeft + m_marginRight);
     2067    } else if (marginLeft.isAuto()) {
     2068        m_marginRight = marginRight.calcValue(containerWidth);
     2069        leftValue = left.calcValue(containerWidth);
     2070        rightValue = right.calcValue(containerWidth);
     2071
     2072        // Solve for 'margin-left'
     2073        m_marginLeft = availableSpace - (leftValue + rightValue + m_marginRight);
     2074    } else if (marginRight.isAuto()) {
     2075        m_marginLeft = marginLeft.calcValue(containerWidth);
     2076        leftValue = left.calcValue(containerWidth);
     2077        rightValue = right.calcValue(containerWidth);
     2078
     2079        // Solve for 'margin-right'
     2080        m_marginRight = availableSpace - (leftValue + rightValue + m_marginLeft);
     2081    }
     2082
     2083    /*-----------------------------------------------------------------------*\
     2084     * 6. If at this point the values are over-constrained, ignore the value
     2085     *    for either 'left' (in case the 'direction' property of the
     2086     *    containing block is 'rtl') or 'right' (in case 'direction' is
     2087     *    'ltr') and solve for that value.
     2088    \*-----------------------------------------------------------------------*/
     2089    // NOTE:  It is not necessary to solve for 'right' when the direction is
     2090    // LTR because the value is not used.
     2091    int totalWidth = m_width + leftValue + rightValue +  m_marginLeft + m_marginRight;
     2092    // see FIXME 1
     2093    if (totalWidth > containerWidth && (containerBlock->style()->direction() == RTL))
     2094        leftValue = containerWidth - (totalWidth - leftValue);
     2095
     2096
     2097    // Use computed values to caluculate the horizontal position.
     2098    m_x = leftValue + m_marginLeft + containerBlock->borderLeft();
     2099}
     2100
     2101void RenderBox::calcAbsoluteVerticalReplaced()
     2102{
     2103    // The following is based off of the W3C Working Draft from April 11, 2006 of
     2104    // CSS 2.1: Section 10.6.5 "Absolutly positioned, replaced elements"
     2105    // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-height>
     2106    // (block-style-comments in this function correspond to text from the spec and
     2107    // the numbers correspond to numbers in spec)
    16002108
    16012109    // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
    1602     RenderObject* cb = container();
    1603     if (cb->isRoot()) // Even in strict mode (where we don't grow the root to fill the viewport) other browsers
    1604                       // position as though the root fills the viewport.
    1605         ch = cb->availableHeight();
    1606     else
    1607         ch = cb->height() - cb->borderTop() - cb->borderBottom();
    1608 
    1609     if (!style()->top().isAuto())
    1610         t = style()->top().calcValue(ch);
    1611     if (!style()->bottom().isAuto())
    1612         b = style()->bottom().calcValue(ch);
    1613 
    1614     int h, mt, mb, y;
    1615     calcAbsoluteVerticalValues(Height, cb, ch, pab, t, b, h, mt, mb, y);
    1616 
    1617     // Avoid doing any work in the common case (where the values of min-height and max-height are their defaults).
    1618     int minH = h, minMT, minMB, minY;
    1619     calcAbsoluteVerticalValues(MinHeight, cb, ch, pab, t, b, minH, minMT, minMB, minY);
    1620 
    1621     int maxH = h, maxMT, maxMB, maxY;
    1622     if (style()->maxHeight().value() != undefinedLength)
    1623         calcAbsoluteVerticalValues(MaxHeight, cb, ch, pab, t, b, maxH, maxMT, maxMB, maxY);
    1624 
    1625     if (h > maxH) {
    1626         h = maxH;
    1627         mt = maxMT;
    1628         mb = maxMB;
    1629         y = maxY;
    1630     }
    1631    
    1632     if (h < minH) {
    1633         h = minH;
    1634         mt = minMT;
    1635         mb = minMB;
    1636         y = minY;
    1637     }
    1638    
    1639     // If our natural height exceeds the new height once we've set it, then we need to make sure to update
    1640     // overflow to track the spillout.
    1641     if (m_height > h)
     2110    const RenderObject* containerBlock = container();
     2111
     2112    // Even in strict mode (where we don't grow the root to fill the viewport)
     2113    // other browsers position as though the root fills the viewport.
     2114    const int containerHeight = containerBlock->isRoot() ? containerBlock->availableHeight() : (containerBlock->height() - containerBlock->borderTop() - containerBlock->borderBottom());
     2115
     2116    // Variables to solve.
     2117    Length top = style()->top();
     2118    Length bottom = style()->bottom();
     2119    Length marginTop = style()->marginTop();
     2120    Length marginBottom = style()->marginBottom();
     2121
     2122
     2123    /*-----------------------------------------------------------------------*\
     2124     * 1. The used value of 'height' is determined as for inline replaced
     2125     *    elements.
     2126    \*-----------------------------------------------------------------------*/
     2127    // NOTE: This value of height is FINAL in that the min/max height calculations
     2128    // are dealt with in calcReplacedHeight().  This means that the steps to produce
     2129    // correct max/min in the non-replaced version, are not necessary.
     2130    int heightValue = calcReplacedHeight() + borderTop() + borderBottom() + paddingTop() + paddingBottom();
     2131    int availableSpace = containerHeight - heightValue;
     2132
     2133    /*-----------------------------------------------------------------------*\
     2134     * 2. If both 'top' and 'bottom' have the value 'auto', replace 'top'
     2135     *    with the element's static position.
     2136    \*-----------------------------------------------------------------------*/
     2137    // see FIXME 2
     2138    if (top.isAuto() && bottom.isAuto()) {
     2139        // m_staticY should already have been set through layout of the parent().
     2140        int staticTop = m_staticY - containerBlock->borderTop();
     2141        for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
     2142            if (!po->isTableRow())
     2143                staticTop += po->yPos();
     2144        }
     2145        top.setValue(Fixed, staticTop);
     2146    }
     2147
     2148    /*-----------------------------------------------------------------------*\
     2149     * 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or
     2150     *    'margin-bottom' with '0'.
     2151    \*-----------------------------------------------------------------------*/
     2152    // FIXME: The spec. says that this step should only be taken when bottom is
     2153    // auto, but if only top is auto, this makes step 4 impossible.
     2154    if (top.isAuto() || bottom.isAuto()) {
     2155        if (marginTop.isAuto())
     2156            marginTop.setValue(Fixed, 0);
     2157        if (marginBottom.isAuto())
     2158            marginBottom.setValue(Fixed, 0);
     2159    }
     2160
     2161    /*-----------------------------------------------------------------------*\
     2162     * 4. If at this point both 'margin-top' and 'margin-bottom' are still
     2163     *    'auto', solve the equation under the extra constraint that the two
     2164     *    margins must get equal values.
     2165    \*-----------------------------------------------------------------------*/
     2166    int topValue;
     2167    int bottomValue;
     2168
     2169    if (marginTop.isAuto() && marginBottom.isAuto()) {
     2170        // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combinded.
     2171        ASSERT(!(top.isAuto() && bottom.isAuto()));
     2172
     2173        topValue = top.calcValue(containerHeight);
     2174        bottomValue = bottom.calcValue(containerHeight);
     2175
     2176        int difference = availableSpace - (topValue + bottomValue);
     2177        // NOTE: This may result in negative values.
     2178        m_marginTop =  difference / 2; // split the difference
     2179        m_marginBottom = difference - m_marginTop; // account for odd valued differences
     2180
     2181    /*-----------------------------------------------------------------------*\
     2182     * 5. If at this point there is only one 'auto' left, solve the equation
     2183     *    for that value.
     2184    \*-----------------------------------------------------------------------*/
     2185    } else if (top.isAuto()) {
     2186        m_marginTop = marginTop.calcValue(containerHeight);
     2187        m_marginBottom = marginBottom.calcValue(containerHeight);
     2188        bottomValue = bottom.calcValue(containerHeight);
     2189
     2190        // Solve for 'top'
     2191        topValue = availableSpace - (bottomValue + m_marginTop + m_marginBottom);
     2192    } else if (bottom.isAuto()) {
     2193        m_marginTop = marginTop.calcValue(containerHeight);
     2194        m_marginBottom = marginBottom.calcValue(containerHeight);
     2195        topValue = top.calcValue(containerHeight);
     2196
     2197        // Solve for 'bottom'
     2198        // NOTE: It is not necessary to solve for 'bottom' because we don't ever
     2199        // use the value.
     2200    } else if (marginTop.isAuto()) {
     2201        m_marginBottom = marginBottom.calcValue(containerHeight);
     2202        topValue = top.calcValue(containerHeight);
     2203        bottomValue = bottom.calcValue(containerHeight);
     2204
     2205        // Solve for 'margin-top'
     2206        m_marginTop = availableSpace - (topValue + bottomValue + m_marginBottom);
     2207    } else if (marginBottom.isAuto()) {
     2208        m_marginTop = marginTop.calcValue(containerHeight);
     2209        topValue = top.calcValue(containerHeight);
     2210        bottomValue = bottom.calcValue(containerHeight);
     2211
     2212        // Solve for 'margin-bottom'
     2213        m_marginBottom = availableSpace - (topValue + bottomValue + m_marginTop);
     2214    }
     2215
     2216    /*-----------------------------------------------------------------------*\
     2217     * 6. If at this point the values are over-constrained, ignore the value
     2218     *    for 'bottom' and solve for that value.
     2219    \*-----------------------------------------------------------------------*/
     2220    // NOTE: It is not necessary to do this step because we don't end up using
     2221    // the value of 'bottom' regardless of whether the values are over-constrained
     2222    // or not.
     2223
     2224
     2225    // Make final adjustments to height.
     2226    int contentHeight = m_height;
     2227    if ((contentHeight < heightValue) || (hasOverflowClip() && contentHeight > heightValue))
     2228        contentHeight = heightValue;
     2229
     2230    // Do not allow the height to be negative.  This can happen when someone
     2231    // specifies both top and bottom but the containing block height is less
     2232    // than top, e.g., top: 20px, bottom: 0, containing block height 16.
     2233    heightValue = max(0, contentHeight);
     2234
     2235    // If our content height exceeds the new height once we've set it, then we
     2236    // need to make sure to update overflow to track the spillout.
     2237    if (m_height > heightValue)
    16422238        setOverflowHeight(m_height);
    1643        
    1644     // Set our final values.
    1645     m_height = h;
    1646     m_marginTop = mt;
    1647     m_marginBottom = mb;
    1648     m_y = y;
    1649 }
    1650 
    1651 void RenderBox::calcAbsoluteVerticalValues(HeightType heightType, RenderObject* cb, int ch, int pab,
    1652                                            int t, int b, int& h, int& mt, int& mb, int& y)
    1653 {
    1654     const int AUTO = -666666;
    1655     h = mt = mb = AUTO;
    1656 
    1657     if (!style()->marginTop().isAuto())
    1658         mt = style()->marginTop().calcValue(ch);
    1659     if (!style()->marginBottom().isAuto())
    1660         mb = style()->marginBottom().calcValue(ch);
    1661 
    1662     Length height;
    1663     if (heightType == Height)
    1664         height = style()->height();
    1665     else if (heightType == MinHeight)
    1666         height = style()->minHeight();
    1667     else
    1668         height = style()->maxHeight();
    1669 
    1670     int ourHeight = m_height;
    1671 
    1672     if (isTable() && height.isAuto())
    1673         // Height is never unsolved for tables. "auto" means shrink to fit.  Use our
    1674         // height instead.
    1675         h = ourHeight - pab;
    1676     else if (!height.isAuto())
    1677     {
    1678         h = calcContentBoxHeight(height.calcValue(ch));
    1679         if (ourHeight - pab > h)
    1680             ourHeight = h + pab;
    1681     }
    1682     else if (isReplaced())
    1683         h = calcReplacedHeight();
    1684 
    1685     int static_top=0;
    1686     if ((t == AUTO && b == AUTO) || style()->top().isStatic()) {
    1687         // calc hypothetical location in the normal flow
    1688         // used for 1) top=static-position
    1689         //          2) top, bottom, height are all auto -> calc top -> 3.
    1690         //          3) precalc for case 2 below
    1691         static_top = m_staticY - cb->borderTop(); // Should already have been set through layout of the parent().
    1692         RenderObject* po = parent();
    1693         for (; po && po != cb; po = po->parent())
    1694             if (!po->isTableRow())
    1695                 static_top += po->yPos();
    1696 
    1697         if (h == AUTO || style()->top().isStatic())
    1698             t = static_top;
    1699     }
    1700 
    1701     if (t != AUTO && h != AUTO && b != AUTO) {
    1702         // top, height, bottom all given, play with margins
    1703         int ot = h + t + b + pab;
    1704 
    1705         if (mt == AUTO && mb == AUTO) {
    1706             // both margins auto, solve for equality
    1707             mt = (ch - ot)/2;
    1708             mb = ch - ot - mt;
    1709         }
    1710         else if (mt==AUTO)
    1711             // solve for top margin
    1712             mt = ch - ot - mb;
    1713         else if (mb==AUTO)
    1714             // solve for bottom margin
    1715             mb = ch - ot - mt;
    1716         else
    1717             // overconstrained, solve for bottom
    1718             b = ch - (h + t + mt + mb + pab);
    1719     }
    1720     else {
    1721         // one or two of (top, height, bottom) missing, solve
    1722 
    1723         // auto margins are ignored
    1724         if (mt == AUTO)
    1725             mt = 0;
    1726         if (mb == AUTO)
    1727             mb = 0;
    1728 
    1729         //1. solve top & height. use content height.
    1730         if (t == AUTO && h == AUTO && b != AUTO) {
    1731             h = ourHeight - pab;
    1732             t = ch - (h + b + mt + mb + pab);
    1733         }
    1734         else if (t == AUTO && h != AUTO && b == AUTO) //2. solve top & bottom. use static positioning.
    1735         {
    1736             t = static_top;
    1737             b = ch - (h + t + mt + mb + pab);
    1738         }
    1739         else if (t != AUTO && h == AUTO && b == AUTO) //3. solve height & bottom. use content height.
    1740         {
    1741             h = ourHeight - pab;
    1742             b = ch - (h + t + mt + mb + pab);
    1743         }
    1744         else
    1745         //4. solve top
    1746         if (t == AUTO && h != AUTO && b != AUTO)
    1747             t = ch - (h + b + mt + mb + pab);
    1748         else
    1749 
    1750         //5. solve height
    1751         if (t != AUTO && h == AUTO && b != AUTO)
    1752             h = ch - (t + b + mt + mb + pab);
    1753         else
    1754 
    1755         //6. solve bottom
    1756         if (t != AUTO && h != AUTO && b == AUTO)
    1757             b = ch - (h + t + mt + mb + pab);
    1758     }
    1759 
    1760     if (ourHeight < h + pab) //content must still fit
    1761         ourHeight = h + pab;
    1762 
    1763     if (hasOverflowClip() && ourHeight > h + pab)
    1764         ourHeight = h + pab;
    1765    
    1766     // Do not allow the height to be negative.  This can happen when someone specifies both top and bottom
    1767     // but the containing block height is less than top, e.g., top:20px, bottom:0, containing block height 16.
    1768     ourHeight = max(0, ourHeight);
    1769    
    1770     h = ourHeight;
    1771     y = t + mt + cb->borderTop();
     2239
     2240    // Set final values.
     2241    m_height = heightValue;
     2242
     2243    // Use computed values to caluculate the vertical position.
     2244    m_y = topValue + m_marginTop + containerBlock->borderTop();
    17722245}
    17732246
  • TabularUnified trunk/WebCore/rendering/RenderBox.h

    r14232 r14351  
    159159    void calcAbsoluteHorizontal();
    160160    void calcAbsoluteVertical();
    161     void calcAbsoluteHorizontalValues(WidthType widthType, RenderObject* cb, int cw, int pab, int static_distance,
    162                                       int l, int r, int& w, int& ml, int& mr, int& x);
    163     void calcAbsoluteVerticalValues(HeightType heightType, RenderObject* cb, int ch, int pab,
    164                                     int t, int b, int& h, int& mt, int& mb, int& y);
    165    
     161    void calcAbsoluteHorizontalValues(Length width, const RenderObject* cb,
     162                                      const int containerWidth, const int bordersPlusPadding,
     163                                      const Length left, const Length right, const Length marginLeft, const Length marginRight,
     164                                      int& widthValue, int& marginLeftValue, int& marginRightValue, int& xPos);
     165    void calcAbsoluteVerticalValues(Length height, const RenderObject* cb,
     166                                    const int containerHeight, const int bordersPlusPadding,
     167                                    const Length top, const Length bottom, const Length marginTop, const Length marginBottom,
     168                                    int& heightValue, int& marginTopValue, int& marginBottomValue, int& yPos);
     169
     170    void calcAbsoluteVerticalReplaced();
     171    void calcAbsoluteHorizontalReplaced();
     172
    166173    virtual IntRect getOverflowClipRect(int tx, int ty);
    167174    virtual IntRect getClipRect(int tx, int ty);
Note: See TracChangeset for help on using the changeset viewer.