Changeset 14351 in webkit
- Timestamp:
- May 13, 2006, 7:58:24 AM (19 years ago)
- Location:
- trunk
- Files:
-
- 8 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/LayoutTests/ChangeLog ¶
r14347 r14351 1 2006-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 1 13 2006-05-12 Mitz Pettel <opendarwin.org@mitzpettel.com> 2 14 -
TabularUnified trunk/LayoutTests/fast/block/positioning/auto/006.html ¶
r11995 r14351 3 3 In this test, you should see three blocks that are aligned right within a black box. They should 4 4 be 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.5 should be 100x100, and there should be 100 pixels of padding on the left side of the box stack. 6 6 7 <p style=" direction:rtl">The8 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 8 black 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. 9 9 10 10 <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 7 7 RenderText {#text} at (0,0) size 768x54 8 8 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" 10 11 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" 12 14 text run at (0,36) width 322: "pixels of padding on the right side of the box stack." 13 15 RenderBlock {P} at (0,70) size 784x54 14 16 RenderText {#text} at (0,0) size 753x54 15 17 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" 18 22 text run at (0,36) width 247: "padding on either side of the box stack." 19 23 layer at (8,148) size 240x340 … … 30 34 layer at (300,148) size 340x240 31 35 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] 36 layer 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] 34 39 layer at (420,268) size 100x100 35 RenderBlock (positioned) {DIV} at (1 20,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 1 1 <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> 2 17 <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> 31 43 </body> 32 44 </html> -
TabularUnified trunk/WebCore/ChangeLog ¶
r14350 r14351 1 2006-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 1 24 2006-05-12 David Hyatt <hyatt@apple.com> 2 25 -
TabularUnified trunk/WebCore/rendering/RenderBox.cpp ¶
r14336 r14351 5 5 * (C) 1999 Antti Koivisto (koivisto@kde.org) 6 6 * (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) 8 8 * Copyright (C) 2005 Apple Computer, Inc. 9 9 * … … 33 33 #include "GraphicsContext.h" 34 34 #include "HTMLElement.h" 35 #include "RenderTableCell.h"36 35 #include "HTMLNames.h" 37 36 #include "RenderArena.h" 38 37 #include "RenderCanvas.h" 39 38 #include "RenderFlexibleBox.h" 39 #include "RenderTableCell.h" 40 40 #include "RenderTheme.h" 41 41 #include <assert.h> 42 #include <algorithm> 42 43 #include <math.h> 43 44 … … 1415 1416 void RenderBox::calcAbsoluteHorizontal() 1416 1417 { 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 1552 void 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 1709 void 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 1424 1723 // 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 1823 void 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 1952 void 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; 1552 2046 } 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 2101 void 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) 1600 2108 1601 2109 // 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) 1642 2238 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(); 1772 2245 } 1773 2246 -
TabularUnified trunk/WebCore/rendering/RenderBox.h ¶
r14232 r14351 159 159 void calcAbsoluteHorizontal(); 160 160 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 166 173 virtual IntRect getOverflowClipRect(int tx, int ty); 167 174 virtual IntRect getClipRect(int tx, int ty);
Note:
See TracChangeset
for help on using the changeset viewer.