From a61c12539fceb351ca60c8d5ffb9284c3f9ee6d6 Mon Sep 17 00:00:00 2001 From: ap Date: Sat, 13 May 2006 14:58:24 +0000 Subject: [PATCH] 2006-05-13 Sam Weinig 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. git-svn-id: https://svn.webkit.org/repository/webkit/trunk@14351 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- LayoutTests/ChangeLog | 12 + ...ute-length-of-neg-666666-expected.checksum | 1 + ...absolute-length-of-neg-666666-expected.png | Bin 0 -> 9999 bytes ...absolute-length-of-neg-666666-expected.txt | 13 + .../absolute-length-of-neg-666666.html | 20 + ...sitioned-overconstrained-expected.checksum | 1 + ...te-positioned-overconstrained-expected.png | Bin 0 -> 7176 bytes ...te-positioned-overconstrained-expected.txt | 19 + .../absolute-positioned-overconstrained.html | 39 + .../fast/block/positioning/auto/006.html | 6 +- ...bsolute-poition-in-rtl-parent-expected.txt | 19 +- .../css/absolute-poition-in-rtl-parent.html | 68 +- WebCore/ChangeLog | 23 + WebCore/rendering/RenderBox.cpp | 1075 ++++++++++++----- WebCore/rendering/RenderBox.h | 17 +- 15 files changed, 969 insertions(+), 344 deletions(-) create mode 100644 LayoutTests/fast/block/positioning/absolute-length-of-neg-666666-expected.checksum create mode 100644 LayoutTests/fast/block/positioning/absolute-length-of-neg-666666-expected.png create mode 100644 LayoutTests/fast/block/positioning/absolute-length-of-neg-666666-expected.txt create mode 100644 LayoutTests/fast/block/positioning/absolute-length-of-neg-666666.html create mode 100644 LayoutTests/fast/block/positioning/absolute-positioned-overconstrained-expected.checksum create mode 100644 LayoutTests/fast/block/positioning/absolute-positioned-overconstrained-expected.png create mode 100644 LayoutTests/fast/block/positioning/absolute-positioned-overconstrained-expected.txt create mode 100644 LayoutTests/fast/block/positioning/absolute-positioned-overconstrained.html diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog index f21f4a881990..9e27f41b9b3f 100644 --- a/LayoutTests/ChangeLog +++ b/LayoutTests/ChangeLog @@ -1,3 +1,15 @@ +2006-05-13 Sam Weinig + + Reviewed by Hyatt, landed by ap. + + - tests for http://bugzilla.opendarwin.org/show_bug.cgi?id=7604 + + * 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. + 2006-05-12 Mitz Pettel Reviewed by Darin. diff --git a/LayoutTests/fast/block/positioning/absolute-length-of-neg-666666-expected.checksum b/LayoutTests/fast/block/positioning/absolute-length-of-neg-666666-expected.checksum new file mode 100644 index 000000000000..fff673897823 --- /dev/null +++ b/LayoutTests/fast/block/positioning/absolute-length-of-neg-666666-expected.checksum @@ -0,0 +1 @@ +5855bbcbb6a2ec7c75e5406af7def470 \ No newline at end of file diff --git a/LayoutTests/fast/block/positioning/absolute-length-of-neg-666666-expected.png b/LayoutTests/fast/block/positioning/absolute-length-of-neg-666666-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..012aef2c54f1565147fb020de3b2a378f9b0fe4c GIT binary patch literal 9999 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 + + + Test case for lengths of magic number '-666666' + + + +

In this test case you should only see one line green text. If there is any red the test has failed.

+
+
You should see this.
+
You should not see this!
+
You should not see this!
+
+ + diff --git a/LayoutTests/fast/block/positioning/absolute-positioned-overconstrained-expected.checksum b/LayoutTests/fast/block/positioning/absolute-positioned-overconstrained-expected.checksum new file mode 100644 index 000000000000..002b301b83e1 --- /dev/null +++ b/LayoutTests/fast/block/positioning/absolute-positioned-overconstrained-expected.checksum @@ -0,0 +1 @@ +b8f18ee9e15bb5290fbab889ccba6512 \ No newline at end of file diff --git a/LayoutTests/fast/block/positioning/absolute-positioned-overconstrained-expected.png b/LayoutTests/fast/block/positioning/absolute-positioned-overconstrained-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..ec7fe56c7f32a89f14446799d097dd4e89b19af2 GIT binary patch literal 7176 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 + + Over-constrained dimensions test for absolutely positioned elements + + + +

The two boxes below should look identical.

+
+
+
+
+
+
+ + +\ No newline at end of file diff --git a/LayoutTests/fast/block/positioning/auto/006.html b/LayoutTests/fast/block/positioning/auto/006.html index d600012b1789..9e0a326d27a8 100644 --- a/LayoutTests/fast/block/positioning/auto/006.html +++ b/LayoutTests/fast/block/positioning/auto/006.html @@ -2,10 +2,10 @@ In this test, you should see three blocks that are aligned right within a black box. They should be stacked vertically with the green box in between two olive boxes. The olive boxes and the green box -should be 100x100, and there should be 100 pixels of padding on the right side of the box stack. +should be 100x100, and there should be 100 pixels of padding on the left side of the box stack. -

The -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. +

The +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.

diff --git a/LayoutTests/fast/css/absolute-poition-in-rtl-parent-expected.txt b/LayoutTests/fast/css/absolute-poition-in-rtl-parent-expected.txt index 011cb9d21680..f4b5afeac20d 100644 --- a/LayoutTests/fast/css/absolute-poition-in-rtl-parent-expected.txt +++ b/LayoutTests/fast/css/absolute-poition-in-rtl-parent-expected.txt @@ -6,15 +6,19 @@ layer at (0,0) size 800x600 RenderBlock {P} at (0,0) size 784x54 RenderText {#text} at (0,0) size 768x54 text run at (0,0) width 502: "On the left, you should see three blocks that are aligned left within a black box. " - text run at (502,0) width 266: "They should be stacked vertically with the" + text run at (502,0) width 83: "They should " + text run at (585,0) width 183: "be stacked vertically with the" text run at (0,18) width 248: "green box in between two olive boxes. " - text run at (248,18) width 502: "The olive boxes and the green box should be 100x100, and there should be 100" + text run at (248,18) width 194: "The olive boxes and the green " + text run at (442,18) width 308: "box should be 100x100, and there should be 100" text run at (0,36) width 322: "pixels of padding on the right side of the box stack." RenderBlock {P} at (0,70) size 784x54 RenderText {#text} at (0,0) size 753x54 text run at (0,0) width 487: "On the right, you should see two blocks that are centered within a black box. " - text run at (487,0) width 266: "They should be stacked vertically with the" - 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" + text run at (487,0) width 102: "They should be " + text run at (589,0) width 164: "stacked vertically with the" + text run at (0,18) width 455: "green box below the olive box. The olive box and the green box should " + text run at (455,18) width 292: "be 100x100, and there should be 100 pixels of" text run at (0,36) width 247: "padding on either side of the box stack." layer at (8,148) size 240x340 RenderBlock (positioned) {DIV} at (8,148) size 240x340 [border: (20px solid #000000)] @@ -29,7 +33,8 @@ layer at (28,368) size 100x100 RenderBlock (positioned) {DIV} at (20,220) size 100x100 [bgcolor=#808000] layer at (300,148) size 340x240 RenderBlock (positioned) {DIV} at (300,148) size 340x240 [border: (20px solid #000000)] - RenderBlock {DIV} at (20,20) size 200x100 - RenderBlock {DIV} at (100,0) size 100x100 [bgcolor=#808000] +layer at (320,168) size 200x100 + RenderBlock (relative positioned) {DIV} at (20,20) size 200x100 + RenderBlock {DIV} at (100,0) size 100x100 [bgcolor=#808000] layer at (420,268) size 100x100 - RenderBlock (positioned) {DIV} at (120,120) size 100x100 [bgcolor=#008000] + RenderBlock (positioned) {DIV} at (100,100) size 100x100 [bgcolor=#008000] diff --git a/LayoutTests/fast/css/absolute-poition-in-rtl-parent.html b/LayoutTests/fast/css/absolute-poition-in-rtl-parent.html index 8f55c32c779a..8bf3ef49ee8f 100644 --- a/LayoutTests/fast/css/absolute-poition-in-rtl-parent.html +++ b/LayoutTests/fast/css/absolute-poition-in-rtl-parent.html @@ -1,32 +1,44 @@ - -

-On the left, you should see three blocks that are aligned left within a black box. They should -be stacked vertically with the green box in between two olive boxes. The olive boxes and the green box -should be 100x100, and there should be 100 pixels of padding on the right side of the box stack. -

-

-On the right, you should see two blocks that are centered within a black box. They should be -stacked vertically with the green box below the olive box. The olive box and the green box should -be 100x100, and there should be 100 pixels of padding on either side of the box stack. -

-
- - - - -
-
-
-
-
-
-
-
-
-
-
-
+ + Absolute Position in RTL parent + + + +

On the left, you should see three blocks that are aligned left within a black box. They should + be stacked vertically with the green box in between two olive boxes. The olive boxes and the green + box should be 100x100, and there should be 100 pixels of padding on the right side of the box stack. +

+

On the right, you should see two blocks that are centered within a black box. They should be + stacked vertically with the green box below the olive box. The olive box and the green box should + be 100x100, and there should be 100 pixels of padding on either side of the box stack. +

+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog index 730d6a18cd0a..b8fb31f6c6a5 100644 --- a/WebCore/ChangeLog +++ b/WebCore/ChangeLog @@ -1,3 +1,26 @@ +2006-05-13 Sam Weinig + + Reviewed by Hyatt, landed by ap. + + 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: + 2006-05-12 David Hyatt Bug 8880, remove the remaining drawing/hit testing code from diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index 9a43de1e7d9f..80ceceeea8b4 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -4,7 +4,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) - * (C) 2005 Samuel Weinig (sam.weinig@gmail.com) + * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) * Copyright (C) 2005 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or @@ -32,13 +32,14 @@ #include "FrameView.h" #include "GraphicsContext.h" #include "HTMLElement.h" -#include "RenderTableCell.h" #include "HTMLNames.h" #include "RenderArena.h" #include "RenderCanvas.h" #include "RenderFlexibleBox.h" +#include "RenderTableCell.h" #include "RenderTheme.h" #include +#include #include using namespace std; @@ -1414,361 +1415,833 @@ void RenderBox::setStaticY(int staticY) void RenderBox::calcAbsoluteHorizontal() { - const int AUTO = -666666; - int l, r, cw; + if (isReplaced()) { + calcAbsoluteHorizontalReplaced(); + return; + } - int pab = borderLeft()+ borderRight()+ paddingLeft()+ paddingRight(); - l = r = AUTO; - - // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline. - RenderObject* cb = container(); - cw = containingBlockWidth() + cb->paddingLeft() + cb->paddingRight(); + // QUESTIONS + // FIXME 1: Which RenderObject's 'direction' property should used: the + // containing block (cb) as the spec seems to imply, the parent (parent()) as + // was previously done in calculating the static distances, or ourself, which + // was also previously done for deciding what to override when you had + // over-constrained margins? Also note that the container block is used + // in similar situations in other parts of the RenderBox class (see calcWidth() + // and calcHorizontalMargins()). - if (!style()->left().isAuto()) - l = style()->left().calcValue(cw); - if (!style()->right().isAuto()) - r = style()->right().calcValue(cw); + // FIXME 2: Should we still deal with these the cases of 'left' or 'right' having + // the type 'static' in determining whether to calculate the static distance? + // NOTE: 'static' is not a legal value for 'left' or 'right' as of CSS 2.1. - int static_distance=0; - if ((parent()->style()->direction()==LTR && (l == AUTO && r == AUTO)) - || style()->left().isStatic()) - { - static_distance = m_staticX - cb->borderLeft(); // Should already have been set through layout of the parent(). - RenderObject* po = parent(); - for (; po && po != cb; po = po->parent()) - static_distance += po->xPos(); + // FIXME 3: Can perhaps optimize out cases when max-width/min-width are greater + // than or less than the computed m_width. Be careful of box-sizing and + // percentage issues. - l = static_distance; - } + // The following is based off of the W3C Working Draft from April 11, 2006 of + // CSS 2.1: Section 10.3.7 "Absolutely positioned, non-replaced elements" + // + // (block-style-comments in this function and in calcAbsoluteHorizontalValues() + // correspond to text from the spec) - else if ((parent()->style()->direction()==RTL && (l==AUTO && r==AUTO )) - || style()->right().isStatic()) - { - RenderObject* po = parent(); - static_distance = m_staticX + cw + cb->borderRight() - po->width(); // Should already have been set through layout of the parent(). - while (po && po!=containingBlock()) { - static_distance -= po->xPos(); - po=po->parent(); - } - r = static_distance; + // We don't use containingBlock(), since we may be positioned by an enclosing + // relative positioned inline. + const RenderObject* containerBlock = container(); + + // FIXME: This is incorrect for cases where the container block is a relatively + // positioned inline. + const int containerWidth = containingBlockWidth() + containerBlock->paddingLeft() + containerBlock->paddingRight(); + + const int bordersPlusPadding = borderLeft() + borderRight() + paddingLeft() + paddingRight(); + const Length marginLeft = style()->marginLeft(); + const Length marginRight = style()->marginRight(); + Length left = style()->left(); + Length right = style()->right(); + + /*---------------------------------------------------------------------------*\ + * For the purposes of this section and the next, the term "static position" + * (of an element) refers, roughly, to the position an element would have had + * in the normal flow. More precisely: + * + * * The static position for 'left' is the distance from the left edge of the + * containing block to the left margin edge of a hypothetical box that would + * have been the first box of the element if its 'position' property had + * been 'static' and 'float' had been 'none'. The value is negative if the + * hypothetical box is to the left of the containing block. + * * The static position for 'right' is the distance from the right edge of the + * containing block to the right margin edge of the same hypothetical box as + * above. The value is positive if the hypothetical box is to the left of the + * containing block's edge. + * + * But rather than actually calculating the dimensions of that hypothetical box, + * user agents are free to make a guess at its probable position. + * + * For the purposes of calculating the static position, the containing block of + * fixed positioned elements is the initial containing block instead of the + * viewport, and all scrollable boxes should be assumed to be scrolled to their + * origin. + \*---------------------------------------------------------------------------*/ + + // see FIXME 2 + // Calculate the static distance if needed. + if (left.isAuto() && right.isAuto()) { + if (containerBlock->style()->direction() == LTR) { + // 'm_staticX' should already have been set through layout of the parent. + int staticPosition = m_staticX - containerBlock->borderLeft(); + for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) + staticPosition += po->xPos(); + left.setValue(Fixed, staticPosition); + } else { + RenderObject* po = parent(); + // 'm_staticX' should already have been set through layout of the parent. + int staticPosition = m_staticX + containerWidth + containerBlock->borderRight() - po->width(); + for (; po && po != containerBlock; po = po->parent()) + staticPosition -= po->xPos(); + right.setValue(Fixed, staticPosition); + } } - calcAbsoluteHorizontalValues(Width, cb, cw, pab, static_distance, l, r, m_width, m_marginLeft, m_marginRight, m_x); + // Calculate constraint equation values for 'width' case. + calcAbsoluteHorizontalValues(style()->width(), containerBlock, containerWidth, bordersPlusPadding, + left, right, marginLeft, marginRight, + m_width, m_marginLeft, m_marginRight, m_x); - // Avoid doing any work in the common case (where the values of min-width and max-width are their defaults). - int minW = m_width, minML, minMR, minX; - calcAbsoluteHorizontalValues(MinWidth, cb, cw, pab, static_distance, l, r, minW, minML, minMR, minX); + // Calculate constraint equation values for 'max-width' case.calcContentBoxWidth(width.calcValue(containerWidth)); + if (style()->maxWidth().value() != undefinedLength) { + int maxWidth; + int maxMarginLeft; + int maxMarginRight; + int maxXPos; - int maxW = m_width, maxML, maxMR, maxX; - if (style()->maxWidth().value() != undefinedLength) - calcAbsoluteHorizontalValues(MaxWidth, cb, cw, static_distance, pab, l, r, maxW, maxML, maxMR, maxX); + calcAbsoluteHorizontalValues(style()->maxWidth(), containerBlock, containerWidth, bordersPlusPadding, + left, right, marginLeft, marginRight, + maxWidth, maxMarginLeft, maxMarginRight, maxXPos); - if (m_width > maxW) { - m_width = maxW; - m_marginLeft = maxML; - m_marginRight = maxMR; - m_x = maxX; - } - - if (m_width < minW) { - m_width = minW; - m_marginLeft = minML; - m_marginRight = minMR; - m_x = minX; + if (m_width > maxWidth) { + m_width = maxWidth; + m_marginLeft = maxMarginLeft; + m_marginRight = maxMarginRight; + m_x = maxXPos; + } } -} -void RenderBox::calcAbsoluteHorizontalValues(WidthType widthType, RenderObject* cb, int cw, int pab, int static_distance, - int l, int r, int& w, int& ml, int& mr, int& x) -{ - const int AUTO = -666666; - w = ml = mr = AUTO; + // Calculate constraint equation values for 'min-width' case. + if (style()->minWidth().value()) { + int minWidth; + int minMarginLeft; + int minMarginRight; + int minXPos; - if (!style()->marginLeft().isAuto()) - ml = style()->marginLeft().calcValue(cw); - if (!style()->marginRight().isAuto()) - mr = style()->marginRight().calcValue(cw); + calcAbsoluteHorizontalValues(style()->minWidth(), containerBlock, containerWidth, bordersPlusPadding, + left, right, marginLeft, marginRight, + minWidth, minMarginLeft, minMarginRight, minXPos); - Length width; - if (widthType == Width) - width = style()->width(); - else if (widthType == MinWidth) - width = style()->minWidth(); - else - width = style()->maxWidth(); - - if (!width.isIntrinsicOrAuto()) - w = calcContentBoxWidth(width.calcValue(cw)); - else if (isReplaced()) - w = calcReplacedWidth(); - - if (l != AUTO && w != AUTO && r != AUTO) { - // left, width, right all given, play with margins - int ot = l + w + r + pab; - - if (ml==AUTO && mr==AUTO) { - // both margins auto, solve for equality - ml = (cw - ot)/2; - mr = cw - ot - ml; - } - else if (ml==AUTO) - // solve for left margin - ml = cw - ot - mr; - else if (mr==AUTO) - // solve for right margin - mr = cw - ot - ml; - else { - // overconstrained, solve according to dir - if (style()->direction() == LTR) - r = cw - ( l + w + ml + mr + pab); - else - l = cw - ( r + w + ml + mr + pab); + if (m_width < minWidth) { + m_width = minWidth; + m_marginLeft = minMarginLeft; + m_marginRight = minMarginRight; + m_x = minXPos; } } - else - { - // one or two of (left, width, right) missing, solve - - // auto margins are ignored - if (ml==AUTO) ml = 0; - if (mr==AUTO) mr = 0; - - //1. solve left & width. - if (l == AUTO && w == AUTO && r != AUTO) { - // From section 10.3.7 of the CSS2.1 specification. - // "The shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width)." - w = min(max(m_minWidth - pab, cw - (r + ml + mr + pab)), m_maxWidth - pab); - l = cw - (r + w + ml + mr + pab); - } - else - //2. solve left & right. use static positioning. - if (l == AUTO && w != AUTO && r == AUTO) { - if (style()->direction()==RTL) { - r = static_distance; - l = cw - (r + w + ml + mr + pab); - } - else { - l = static_distance; - r = cw - (l + w + ml + mr + pab); + // Put m_width into correct form. + m_width += bordersPlusPadding; +} + +void RenderBox::calcAbsoluteHorizontalValues(Length width, const RenderObject* containerBlock, + const int containerWidth, const int bordersPlusPadding, + const Length left, const Length right, const Length marginLeft, const Length marginRight, + int& widthValue, int& marginLeftValue, int& marginRightValue, int& xPos) +{ + // 'left' and 'right' cannot both be 'auto' because one would of been + // converted to the static postion already + ASSERT(!(left.isAuto() && right.isAuto())); + + int leftValue; + + bool widthIsAuto = width.isIntrinsicOrAuto(); + bool leftIsAuto = left.isAuto(); + bool rightIsAuto = right.isAuto(); + + if (!leftIsAuto && !widthIsAuto && !rightIsAuto) { + /*-----------------------------------------------------------------------*\ + * If none of the three is 'auto': If both 'margin-left' and 'margin- + * right' are 'auto', solve the equation under the extra constraint that + * the two margins get equal values, unless this would make them negative, + * in which case when direction of the containing block is 'ltr' ('rtl'), + * set 'margin-left' ('margin-right') to zero and solve for 'margin-right' + * ('margin-left'). If one of 'margin-left' or 'margin-right' is 'auto', + * solve the equation for that value. If the values are over-constrained, + * ignore the value for 'left' (in case the 'direction' property of the + * containing block is 'rtl') or 'right' (in case 'direction' is 'ltr') + * and solve for that value. + \*-----------------------------------------------------------------------*/ + // NOTE: It is not necessary to solve for 'right' in the over constrained + // case because the value is not used for any further calculations. + + leftValue = left.calcValue(containerWidth); + widthValue = calcContentBoxWidth(width.calcValue(containerWidth)); + + const int availableSpace = containerWidth - (leftValue + widthValue + right.calcValue(containerWidth) + bordersPlusPadding); + + // Margins are now the only unknown + if (marginLeft.isAuto() && marginRight.isAuto()) { + // Both margins auto, solve for equality + if (availableSpace >= 0) { + marginLeftValue = availableSpace / 2; // split the diference + marginRightValue = availableSpace - marginLeftValue; // account for odd valued differences + } else { + // see FIXME 1 + if (containerBlock->style()->direction() == LTR) { + marginLeftValue = 0; + marginRightValue = availableSpace; // will be negative + } else { + marginLeftValue = availableSpace; // will be negative + marginRightValue = 0; + } } + } else if (marginLeft.isAuto()) { + // Solve for left margin + marginRightValue = marginRight.calcValue(containerWidth); + marginLeftValue = availableSpace - marginRightValue; + } else if (marginRight.isAuto()) { + // Solve for right margin + marginLeftValue = marginLeft.calcValue(containerWidth); + marginRightValue = availableSpace - marginLeftValue; + } else { + // Over-constrained, solve for left if direction is RTL + marginLeftValue = marginLeft.calcValue(containerWidth); + marginRightValue = marginRight.calcValue(containerWidth); - } //3. solve width & right. - else if (l != AUTO && w == AUTO && r == AUTO) { - // From section 10.3.7 of the CSS2.1 specification. - // "The shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width)." - w = min(max(m_minWidth - pab, cw - (l + ml + mr + pab)), m_maxWidth - pab); - r = cw - (l + w + ml + mr + pab); + // see FIXME 1 -- used to be "this->style()->direction()" + if (containerBlock->style()->direction() == RTL) + leftValue = (availableSpace + leftValue) - marginLeftValue - marginRightValue; + } + } else { + /*--------------------------------------------------------------------*\ + * Otherwise, set 'auto' values for 'margin-left' and 'margin-right' + * to 0, and pick the one of the following six rules that applies. + * + * 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the + * width is shrink-to-fit. Then solve for 'left' + * + * OMIT RULE 2 AS IT SHOULD NEVER BE HIT + * ------------------------------------------------------------------ + * 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if + * the 'direction' property of the containing block is 'ltr' set + * 'left' to the static position, otherwise set 'right' to the + * static position. Then solve for 'left' (if 'direction is 'rtl') + * or 'right' (if 'direction' is 'ltr'). + * ------------------------------------------------------------------ + * + * 3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the + * width is shrink-to-fit . Then solve for 'right' + * 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve + * for 'left' + * 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve + * for 'width' + * 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve + * for 'right' + * + * Calculation of the shrink-to-fit width is similar to calculating the + * width of a table cell using the automatic table layout algorithm. + * Roughly: calculate the preferred width by formatting the content + * without breaking lines other than where explicit line breaks occur, + * and also calculate the preferred minimum width, e.g., by trying all + * possible line breaks. CSS 2.1 does not define the exact algorithm. + * Thirdly, calculate the available width: this is found by solving + * for 'width' after setting 'left' (in case 1) or 'right' (in case 3) + * to 0. + * + * Then the shrink-to-fit width is: + * min(max(preferred minimum width, available width), preferred width). + \*--------------------------------------------------------------------*/ + // NOTE: For rules 3 and 6 it is not necessary to solve for 'right' + // because the value is not used for any further calculations. + + // Calculate margins, 'auto' margins are ignored. + marginLeftValue = marginLeft.calcMinValue(containerWidth); + marginRightValue = marginRight.calcMinValue(containerWidth); + + const int availableSpace = containerWidth - (marginLeftValue + marginRightValue + bordersPlusPadding); + + // FIXME: Is there a faster way to find the correct case? + // Use rule/case that applies. + if (leftIsAuto && widthIsAuto && !rightIsAuto) { + // RULE 1: (use shrink-to-fit for width, and solve of left) + int rightValue = right.calcValue(containerWidth); + + // FIXME: would it be better to have shrink-to-fit in one step? + int preferredWidth = m_maxWidth - bordersPlusPadding; + int preferredMinWidth = m_minWidth - bordersPlusPadding; + int availableWidth = availableSpace - rightValue; + widthValue = min(max(preferredMinWidth, availableWidth), preferredWidth); + leftValue = availableSpace - (widthValue + rightValue); + } else if (!leftIsAuto && widthIsAuto && rightIsAuto) { + // RULE 3: (use shrink-to-fit for width, and no need solve of right) + leftValue = left.calcValue(containerWidth); + + // FIXME: would it be better to have shrink-to-fit in one step? + int preferredWidth = m_maxWidth - bordersPlusPadding; + int preferredMinWidth = m_minWidth - bordersPlusPadding; + int availableWidth = availableSpace - leftValue; + widthValue = min(max(preferredMinWidth, availableWidth), preferredWidth); + } else if (leftIsAuto && !width.isAuto() && !rightIsAuto) { + // RULE 4: (solve for left) + widthValue = calcContentBoxWidth(width.calcValue(containerWidth)); + leftValue = availableSpace - (widthValue + right.calcValue(containerWidth)); + } else if (!leftIsAuto && widthIsAuto && !rightIsAuto) { + // RULE 5: (solve for width) + leftValue = left.calcValue(containerWidth); + widthValue = availableSpace - (leftValue + right.calcValue(containerWidth)); + } else if (!leftIsAuto&& !widthIsAuto && rightIsAuto) { + // RULE 6: (no need solve for right) + leftValue = left.calcValue(containerWidth); + widthValue = calcContentBoxWidth(width.calcValue(containerWidth)); } - else - - //4. solve left - if (l==AUTO && w!=AUTO && r!=AUTO) - l = cw - (r + w + ml + mr + pab); - else - //5. solve width - if (l!=AUTO && w==AUTO && r!=AUTO) - w = cw - (r + l + ml + mr + pab); - else - - //6. solve right - if (l!=AUTO && w!=AUTO && r==AUTO) - r = cw - (l + w + ml + mr + pab); } - w += pab; - x = l + ml + cb->borderLeft(); + // Use computed values to calculate the horizontal position. + xPos = leftValue + marginLeftValue + containerBlock->borderLeft(); } void RenderBox::calcAbsoluteVertical() { - // css2 spec 10.6.4 & 10.6.5 + if (isReplaced()) { + calcAbsoluteVerticalReplaced(); + return; + } + + // The following is based off of the W3C Working Draft from April 11, 2006 of + // CSS 2.1: Section 10.6.4 "Absolutely positioned, non-replaced elements" + // + // (block-style-comments in this function and in calcAbsoluteVerticalValues() + // correspond to text from the spec) - // based on - // http://www.w3.org/Style/css2-updates/REC-CSS2-19980512-errata - // (actually updated 2000-10-24) - // that introduces static-position value for top, left & right - const int AUTO = -666666; - int t, b, ch; + // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline. + const RenderObject* containerBlock = container(); - t = b = AUTO; + // Even in strict mode (where we don't grow the root to fill the viewport) other browsers + // position as though the root fills the viewport. + const int containerHeight = containerBlock->isRoot() ? containerBlock->availableHeight() : (containerBlock->height() - containerBlock->borderTop() - containerBlock->borderBottom()); + + const int bordersPlusPadding = borderTop() + borderBottom() + paddingTop() + paddingBottom(); + const Length marginTop = style()->marginTop(); + const Length marginBottom = style()->marginBottom(); + Length top = style()->top(); + Length bottom = style()->bottom(); + + /*---------------------------------------------------------------------------*\ + * For the purposes of this section and the next, the term "static position" + * (of an element) refers, roughly, to the position an element would have had + * in the normal flow. More precisely, the static position for 'top' is the + * distance from the top edge of the containing block to the top margin edge + * of a hypothetical box that would have been the first box of the element if + * its 'position' property had been 'static' and 'float' had been 'none'. The + * value is negative if the hypothetical box is above the containing block. + * + * But rather than actually calculating the dimensions of that hypothetical + * box, user agents are free to make a guess at its probable position. + * + * For the purposes of calculating the static position, the containing block + * of fixed positioned elements is the initial containing block instead of + * the viewport. + \*---------------------------------------------------------------------------*/ + + // see FIXME 2 + // Calculate the static distance if needed. + if (top.isAuto() && bottom.isAuto()) { + // m_staticY should already have been set through layout of the parent() + int staticTop = m_staticY - containerBlock->borderTop(); + for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) { + if (!po->isTableRow()) + staticTop += po->yPos(); + } + top.setValue(Fixed, staticTop); + } - int pab = borderTop()+borderBottom()+paddingTop()+paddingBottom(); - // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline. - RenderObject* cb = container(); - if (cb->isRoot()) // Even in strict mode (where we don't grow the root to fill the viewport) other browsers - // position as though the root fills the viewport. - ch = cb->availableHeight(); - else - ch = cb->height() - cb->borderTop() - cb->borderBottom(); + int height; // Needed to compute overflow. - if (!style()->top().isAuto()) - t = style()->top().calcValue(ch); - if (!style()->bottom().isAuto()) - b = style()->bottom().calcValue(ch); + // Calculate constraint equation values for 'height' case. + calcAbsoluteVerticalValues(style()->height(), containerBlock, containerHeight, bordersPlusPadding, + top, bottom, marginTop, marginBottom, + height, m_marginTop, m_marginBottom, m_y); - int h, mt, mb, y; - calcAbsoluteVerticalValues(Height, cb, ch, pab, t, b, h, mt, mb, y); + // Avoid doing any work in the common case (where the values of min-height and max-height are their defaults). + // see FIXME 3 - // Avoid doing any work in the common case (where the values of min-height and max-height are their defaults). - int minH = h, minMT, minMB, minY; - calcAbsoluteVerticalValues(MinHeight, cb, ch, pab, t, b, minH, minMT, minMB, minY); + // Calculate constraint equation values for 'max-height' case. + if (style()->maxHeight().value() != undefinedLength) { + int maxHeight; + int maxMarginTop; + int maxMarginBottom; + int maxYPos; - int maxH = h, maxMT, maxMB, maxY; - if (style()->maxHeight().value() != undefinedLength) - calcAbsoluteVerticalValues(MaxHeight, cb, ch, pab, t, b, maxH, maxMT, maxMB, maxY); + calcAbsoluteVerticalValues(style()->maxHeight(), containerBlock, containerHeight, bordersPlusPadding, + top, bottom, marginTop, marginBottom, + maxHeight, maxMarginTop, maxMarginBottom, maxYPos); - if (h > maxH) { - h = maxH; - mt = maxMT; - mb = maxMB; - y = maxY; + if (height > maxHeight) { + height = maxHeight; + m_marginTop = maxMarginTop; + m_marginBottom = maxMarginBottom; + m_y = maxYPos; + } } - - if (h < minH) { - h = minH; - mt = minMT; - mb = minMB; - y = minY; + + // Calculate constraint equation values for 'min-height' case. + if (style()->minHeight().value()) { + int minHeight; + int minMarginTop; + int minMarginBottom; + int minYPos; + + calcAbsoluteVerticalValues(style()->minHeight(), containerBlock, containerHeight, bordersPlusPadding, + top, bottom, marginTop, marginBottom, + minHeight, minMarginTop, minMarginBottom, minYPos); + + if (height < minHeight) { + height = minHeight; + m_marginTop = minMarginTop; + m_marginBottom = minMarginBottom; + m_y = minYPos; + } } - - // If our natural height exceeds the new height once we've set it, then we need to make sure to update - // overflow to track the spillout. - if (m_height > h) + + // If our natural height exceeds the new height once we've set it, then we + // need to make sure to update overflow to track the spillout. + if (m_height > height) setOverflowHeight(m_height); - - // Set our final values. - m_height = h; - m_marginTop = mt; - m_marginBottom = mb; - m_y = y; + + // Set final height value. + m_height = height; } -void RenderBox::calcAbsoluteVerticalValues(HeightType heightType, RenderObject* cb, int ch, int pab, - int t, int b, int& h, int& mt, int& mb, int& y) +void RenderBox::calcAbsoluteVerticalValues(Length height, const RenderObject* containerBlock, + const int containerHeight, const int bordersPlusPadding, + const Length top, const Length bottom, const Length marginTop, const Length marginBottom, + int& heightValue, int& marginTopValue, int& marginBottomValue, int& yPos) { - const int AUTO = -666666; - h = mt = mb = AUTO; - - if (!style()->marginTop().isAuto()) - mt = style()->marginTop().calcValue(ch); - if (!style()->marginBottom().isAuto()) - mb = style()->marginBottom().calcValue(ch); - - Length height; - if (heightType == Height) - height = style()->height(); - else if (heightType == MinHeight) - height = style()->minHeight(); - else - height = style()->maxHeight(); + // 'top' and 'bottom' cannot both be 'auto' because 'top would of been + // converted to the static position in calcAbsoluteVertical() + ASSERT(!(top.isAuto() && bottom.isAuto())); + + int contentHeight = m_height - bordersPlusPadding; + + int topValue; + + bool heightIsAuto = height.isAuto(); + bool topIsAuto = top.isAuto(); + bool bottomIsAuto = bottom.isAuto(); + + // Height is never unsolved for tables. + if (isTable() && heightIsAuto) { + height.setValue(Fixed, contentHeight); + heightIsAuto = false; + } else if (!heightIsAuto) + contentHeight = min(contentHeight, calcContentBoxHeight(height.calcValue(containerHeight))); + + if (!topIsAuto && !heightIsAuto && !bottomIsAuto) { + /*-----------------------------------------------------------------------*\ + * If none of the three are 'auto': If both 'margin-top' and 'margin- + * bottom' are 'auto', solve the equation under the extra constraint that + * the two margins get equal values. If one of 'margin-top' or 'margin- + * bottom' is 'auto', solve the equation for that value. If the values + * are over-constrained, ignore the value for 'bottom' and solve for that + * value. + \*-----------------------------------------------------------------------*/ + // NOTE: It is not necessary to solve for 'bottom' in the over constrained + // case because the value is not used for any further calculations. + + heightValue = calcContentBoxHeight(height.calcValue(containerHeight)); + topValue = top.calcValue(containerHeight); + + const int availableSpace = containerHeight - (topValue + heightValue + bottom.calcValue(containerHeight) + bordersPlusPadding); + + // Margins are now the only unknown + if (marginTop.isAuto() && marginBottom.isAuto()) { + // Both margins auto, solve for equality + // NOTE: This may result in negative values. + marginTopValue = availableSpace / 2; // split the diference + marginBottomValue = availableSpace - marginTopValue; // account for odd valued differences + } else if (marginTop.isAuto()) { + // Solve for top margin + marginBottomValue = marginBottom.calcValue(containerHeight); + marginTopValue = availableSpace - marginBottomValue; + } else if (marginBottom.isAuto()) { + // Solve for bottom margin + marginTopValue = marginTop.calcValue(containerHeight); + marginBottomValue = availableSpace - marginTopValue; + } else { + // Over-constrained, (no need solve for bottom) + marginTopValue = marginTop.calcValue(containerHeight); + marginBottomValue = marginBottom.calcValue(containerHeight); + } + } else { + /*--------------------------------------------------------------------*\ + * Otherwise, set 'auto' values for 'margin-top' and 'margin-bottom' + * to 0, and pick the one of the following six rules that applies. + * + * 1. 'top' and 'height' are 'auto' and 'bottom' is not 'auto', then + * the height is based on the content, and solve for 'top'. + * + * OMIT RULE 2 AS IT SHOULD NEVER BE HIT + * ------------------------------------------------------------------ + * 2. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then + * set 'top' to the static position, and solve for 'bottom'. + * ------------------------------------------------------------------ + * + * 3. 'height' and 'bottom' are 'auto' and 'top' is not 'auto', then + * the height is based on the content, and solve for 'bottom'. + * 4. 'top' is 'auto', 'height' and 'bottom' are not 'auto', and + * solve for 'top'. + * 5. 'height' is 'auto', 'top' and 'bottom' are not 'auto', and + * solve for 'height'. + * 6. 'bottom' is 'auto', 'top' and 'height' are not 'auto', and + * solve for 'bottom'. + \*--------------------------------------------------------------------*/ + // NOTE: For rules 3 and 6 it is not necessary to solve for 'bottom' + // because the value is not used for any further calculations. + + // Calculate margins, 'auto' margins are ignored. + marginTopValue = marginTop.calcMinValue(containerHeight); + marginBottomValue = marginBottom.calcMinValue(containerHeight); + + const int availableSpace = containerHeight - (marginTopValue + marginBottomValue + bordersPlusPadding); + + // Use rule/case that applies. + if (topIsAuto && heightIsAuto && !bottomIsAuto) { + // RULE 1: (height is content based, solve of top) + heightValue = contentHeight; + topValue = availableSpace - (heightValue + bottom.calcValue(containerHeight)); + } else if (!topIsAuto && heightIsAuto && bottomIsAuto) { + // RULE 3: (height is content based, no need solve of bottom) + topValue = top.calcValue(containerHeight); + heightValue = contentHeight; + } else if (topIsAuto && !heightIsAuto && !bottomIsAuto) { + // RULE 4: (solve of top) + heightValue = calcContentBoxHeight(height.calcValue(containerHeight)); + topValue = availableSpace - (heightValue + bottom.calcValue(containerHeight)); + } else if (!topIsAuto && heightIsAuto && !bottomIsAuto) { + // RULE 5: (solve of height) + topValue = top.calcValue(containerHeight); + heightValue = availableSpace - (topValue + bottom.calcValue(containerHeight)); + } else if (!topIsAuto && !heightIsAuto && bottomIsAuto) { + // RULE 6: (no need solve of bottom) + heightValue = calcContentBoxHeight(height.calcValue(containerHeight)); + topValue = top.calcValue(containerHeight); + } + } - int ourHeight = m_height; + // Make final adjustments to height. + if (!(contentHeight < heightValue) && !(hasOverflowClip() && contentHeight > heightValue)) + heightValue = contentHeight; - if (isTable() && height.isAuto()) - // Height is never unsolved for tables. "auto" means shrink to fit. Use our - // height instead. - h = ourHeight - pab; - else if (!height.isAuto()) - { - h = calcContentBoxHeight(height.calcValue(ch)); - if (ourHeight - pab > h) - ourHeight = h + pab; - } - else if (isReplaced()) - h = calcReplacedHeight(); - - int static_top=0; - if ((t == AUTO && b == AUTO) || style()->top().isStatic()) { - // calc hypothetical location in the normal flow - // used for 1) top=static-position - // 2) top, bottom, height are all auto -> calc top -> 3. - // 3) precalc for case 2 below - static_top = m_staticY - cb->borderTop(); // Should already have been set through layout of the parent(). - RenderObject* po = parent(); - for (; po && po != cb; po = po->parent()) - if (!po->isTableRow()) - static_top += po->yPos(); + // Do not allow the height to be negative. This can happen when someone + // specifies both top and bottom but the containing block height is less + // than top, e.g., top: 20px, bottom: 0, containing block height 16. + heightValue = max(0, heightValue + bordersPlusPadding); - if (h == AUTO || style()->top().isStatic()) - t = static_top; - } + // Use computed values to calculate the vertical position. + yPos = topValue + marginTopValue + containerBlock->borderTop(); +} - if (t != AUTO && h != AUTO && b != AUTO) { - // top, height, bottom all given, play with margins - int ot = h + t + b + pab; +void RenderBox::calcAbsoluteHorizontalReplaced() +{ + // The following is based off of the W3C Working Draft from April 11, 2006 of + // CSS 2.1: Section 10.3.8 "Absolutly positioned, replaced elements" + // + // (block-style-comments in this function correspond to text from the spec and + // the numbers correspond to numbers in spec) - if (mt == AUTO && mb == AUTO) { - // both margins auto, solve for equality - mt = (ch - ot)/2; - mb = ch - ot - mt; + // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline. + const RenderObject* containerBlock = container(); + const int containerWidth = containingBlockWidth() + containerBlock->paddingLeft() + containerBlock->paddingRight(); + + // Variables to solve. + Length left = style()->left(); + Length right = style()->right(); + Length marginLeft = style()->marginLeft(); + Length marginRight = style()->marginRight(); + + + /*-----------------------------------------------------------------------*\ + * 1. The used value of 'width' is determined as for inline replaced + * elements. + \*-----------------------------------------------------------------------*/ + // NOTE: This value of width is FINAL in that the min/max width calculations + // are dealt with in calcReplacedWidth(). This means that the steps to produce + // correct max/min in the non-replaced version, are not necessary. + m_width = calcReplacedWidth() + borderLeft() + borderRight() + paddingLeft() + paddingRight(); + const int availableSpace = containerWidth - m_width; + + /*-----------------------------------------------------------------------*\ + * 2. If both 'left' and 'right' have the value 'auto', then if 'direction' + * of the containing block is 'ltr', set 'left' to the static position; + * else if 'direction' is 'rtl', set 'right' to the static position. + \*-----------------------------------------------------------------------*/ + // see FIXME 2 + if (left.isAuto() && right.isAuto()) { + // see FIXME 1 + if (containerBlock->style()->direction() == LTR) { + // 'm_staticX' should already have been set through layout of the parent. + int staticPosition = m_staticX - containerBlock->borderLeft(); + for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) + staticPosition += po->xPos(); + left.setValue(Fixed, staticPosition); + } else { + RenderObject* po = parent(); + // 'm_staticX' should already have been set through layout of the parent. + int staticPosition = m_staticX + containerWidth + containerBlock->borderRight() - po->width(); + for (; po && po != containerBlock; po = po->parent()) + staticPosition -= po->xPos(); + right.setValue(Fixed, staticPosition); } - else if (mt==AUTO) - // solve for top margin - mt = ch - ot - mb; - else if (mb==AUTO) - // solve for bottom margin - mb = ch - ot - mt; - else - // overconstrained, solve for bottom - b = ch - (h + t + mt + mb + pab); } - else { - // one or two of (top, height, bottom) missing, solve - - // auto margins are ignored - if (mt == AUTO) - mt = 0; - if (mb == AUTO) - mb = 0; - - //1. solve top & height. use content height. - if (t == AUTO && h == AUTO && b != AUTO) { - h = ourHeight - pab; - t = ch - (h + b + mt + mb + pab); - } - else if (t == AUTO && h != AUTO && b == AUTO) //2. solve top & bottom. use static positioning. - { - t = static_top; - b = ch - (h + t + mt + mb + pab); - } - else if (t != AUTO && h == AUTO && b == AUTO) //3. solve height & bottom. use content height. - { - h = ourHeight - pab; - b = ch - (h + t + mt + mb + pab); + + /*-----------------------------------------------------------------------*\ + * 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left' + * or 'margin-right' with '0'. + \*-----------------------------------------------------------------------*/ + if (left.isAuto() || right.isAuto()) { + if (marginLeft.isAuto()) + marginLeft.setValue(Fixed, 0); + if (marginRight.isAuto()) + marginRight.setValue(Fixed, 0); + } + + /*-----------------------------------------------------------------------*\ + * 4. If at this point both 'margin-left' and 'margin-right' are still + * 'auto', solve the equation under the extra constraint that the two + * margins must get equal values, unless this would make them negative, + * in which case when the direction of the containing block is 'ltr' + * ('rtl'), set 'margin-left' ('margin-right') to zero and solve for + * 'margin-right' ('margin-left'). + \*-----------------------------------------------------------------------*/ + int leftValue; + int rightValue; + + if (marginLeft.isAuto() && marginRight.isAuto()) { + // 'left' and 'right' cannot be 'auto' due to step 3 + ASSERT(!(left.isAuto() && right.isAuto())); + + leftValue = left.calcValue(containerWidth); + rightValue = right.calcValue(containerWidth); + + int difference = availableSpace - (leftValue + rightValue); + if (difference > 0) { + m_marginLeft = difference / 2; // split the diference + m_marginRight = difference - m_marginLeft; // account for odd valued differences + } else { + // see FIXME 1 + if (containerBlock->style()->direction() == LTR) { + m_marginLeft = 0; + m_marginRight = difference; // will be negative + } else { + m_marginLeft = difference; // will be negative + m_marginRight = 0; + } } - else - //4. solve top - if (t == AUTO && h != AUTO && b != AUTO) - t = ch - (h + b + mt + mb + pab); - else - //5. solve height - if (t != AUTO && h == AUTO && b != AUTO) - h = ch - (t + b + mt + mb + pab); - else + /*-----------------------------------------------------------------------*\ + * 5. If at this point there is an 'auto' left, solve the equation for + * that value. + \*-----------------------------------------------------------------------*/ + } else if (left.isAuto()) { + m_marginLeft = marginLeft.calcValue(containerWidth); + m_marginRight = marginRight.calcValue(containerWidth); + rightValue = right.calcValue(containerWidth); + + // Solve for 'left' + leftValue = availableSpace - (rightValue + m_marginLeft + m_marginRight); + } else if (right.isAuto()) { + m_marginLeft = marginLeft.calcValue(containerWidth); + m_marginRight = marginRight.calcValue(containerWidth); + leftValue = left.calcValue(containerWidth); + + // Solve for 'right' + rightValue = availableSpace - (leftValue + m_marginLeft + m_marginRight); + } else if (marginLeft.isAuto()) { + m_marginRight = marginRight.calcValue(containerWidth); + leftValue = left.calcValue(containerWidth); + rightValue = right.calcValue(containerWidth); + + // Solve for 'margin-left' + m_marginLeft = availableSpace - (leftValue + rightValue + m_marginRight); + } else if (marginRight.isAuto()) { + m_marginLeft = marginLeft.calcValue(containerWidth); + leftValue = left.calcValue(containerWidth); + rightValue = right.calcValue(containerWidth); + + // Solve for 'margin-right' + m_marginRight = availableSpace - (leftValue + rightValue + m_marginLeft); + } + + /*-----------------------------------------------------------------------*\ + * 6. If at this point the values are over-constrained, ignore the value + * for either 'left' (in case the 'direction' property of the + * containing block is 'rtl') or 'right' (in case 'direction' is + * 'ltr') and solve for that value. + \*-----------------------------------------------------------------------*/ + // NOTE: It is not necessary to solve for 'right' when the direction is + // LTR because the value is not used. + int totalWidth = m_width + leftValue + rightValue + m_marginLeft + m_marginRight; + // see FIXME 1 + if (totalWidth > containerWidth && (containerBlock->style()->direction() == RTL)) + leftValue = containerWidth - (totalWidth - leftValue); + + + // Use computed values to caluculate the horizontal position. + m_x = leftValue + m_marginLeft + containerBlock->borderLeft(); +} - //6. solve bottom - if (t != AUTO && h != AUTO && b == AUTO) - b = ch - (h + t + mt + mb + pab); - } +void RenderBox::calcAbsoluteVerticalReplaced() +{ + // The following is based off of the W3C Working Draft from April 11, 2006 of + // CSS 2.1: Section 10.6.5 "Absolutly positioned, replaced elements" + // + // (block-style-comments in this function correspond to text from the spec and + // the numbers correspond to numbers in spec) - if (ourHeight < h + pab) //content must still fit - ourHeight = h + pab; + // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline. + const RenderObject* containerBlock = container(); + + // Even in strict mode (where we don't grow the root to fill the viewport) + // other browsers position as though the root fills the viewport. + const int containerHeight = containerBlock->isRoot() ? containerBlock->availableHeight() : (containerBlock->height() - containerBlock->borderTop() - containerBlock->borderBottom()); + + // Variables to solve. + Length top = style()->top(); + Length bottom = style()->bottom(); + Length marginTop = style()->marginTop(); + Length marginBottom = style()->marginBottom(); + + + /*-----------------------------------------------------------------------*\ + * 1. The used value of 'height' is determined as for inline replaced + * elements. + \*-----------------------------------------------------------------------*/ + // NOTE: This value of height is FINAL in that the min/max height calculations + // are dealt with in calcReplacedHeight(). This means that the steps to produce + // correct max/min in the non-replaced version, are not necessary. + int heightValue = calcReplacedHeight() + borderTop() + borderBottom() + paddingTop() + paddingBottom(); + int availableSpace = containerHeight - heightValue; + + /*-----------------------------------------------------------------------*\ + * 2. If both 'top' and 'bottom' have the value 'auto', replace 'top' + * with the element's static position. + \*-----------------------------------------------------------------------*/ + // see FIXME 2 + if (top.isAuto() && bottom.isAuto()) { + // m_staticY should already have been set through layout of the parent(). + int staticTop = m_staticY - containerBlock->borderTop(); + for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) { + if (!po->isTableRow()) + staticTop += po->yPos(); + } + top.setValue(Fixed, staticTop); + } + + /*-----------------------------------------------------------------------*\ + * 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or + * 'margin-bottom' with '0'. + \*-----------------------------------------------------------------------*/ + // FIXME: The spec. says that this step should only be taken when bottom is + // auto, but if only top is auto, this makes step 4 impossible. + if (top.isAuto() || bottom.isAuto()) { + if (marginTop.isAuto()) + marginTop.setValue(Fixed, 0); + if (marginBottom.isAuto()) + marginBottom.setValue(Fixed, 0); + } + + /*-----------------------------------------------------------------------*\ + * 4. If at this point both 'margin-top' and 'margin-bottom' are still + * 'auto', solve the equation under the extra constraint that the two + * margins must get equal values. + \*-----------------------------------------------------------------------*/ + int topValue; + int bottomValue; + + if (marginTop.isAuto() && marginBottom.isAuto()) { + // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combinded. + ASSERT(!(top.isAuto() && bottom.isAuto())); + + topValue = top.calcValue(containerHeight); + bottomValue = bottom.calcValue(containerHeight); + + int difference = availableSpace - (topValue + bottomValue); + // NOTE: This may result in negative values. + m_marginTop = difference / 2; // split the difference + m_marginBottom = difference - m_marginTop; // account for odd valued differences + + /*-----------------------------------------------------------------------*\ + * 5. If at this point there is only one 'auto' left, solve the equation + * for that value. + \*-----------------------------------------------------------------------*/ + } else if (top.isAuto()) { + m_marginTop = marginTop.calcValue(containerHeight); + m_marginBottom = marginBottom.calcValue(containerHeight); + bottomValue = bottom.calcValue(containerHeight); + + // Solve for 'top' + topValue = availableSpace - (bottomValue + m_marginTop + m_marginBottom); + } else if (bottom.isAuto()) { + m_marginTop = marginTop.calcValue(containerHeight); + m_marginBottom = marginBottom.calcValue(containerHeight); + topValue = top.calcValue(containerHeight); + + // Solve for 'bottom' + // NOTE: It is not necessary to solve for 'bottom' because we don't ever + // use the value. + } else if (marginTop.isAuto()) { + m_marginBottom = marginBottom.calcValue(containerHeight); + topValue = top.calcValue(containerHeight); + bottomValue = bottom.calcValue(containerHeight); + + // Solve for 'margin-top' + m_marginTop = availableSpace - (topValue + bottomValue + m_marginBottom); + } else if (marginBottom.isAuto()) { + m_marginTop = marginTop.calcValue(containerHeight); + topValue = top.calcValue(containerHeight); + bottomValue = bottom.calcValue(containerHeight); + + // Solve for 'margin-bottom' + m_marginBottom = availableSpace - (topValue + bottomValue + m_marginTop); + } + + /*-----------------------------------------------------------------------*\ + * 6. If at this point the values are over-constrained, ignore the value + * for 'bottom' and solve for that value. + \*-----------------------------------------------------------------------*/ + // NOTE: It is not necessary to do this step because we don't end up using + // the value of 'bottom' regardless of whether the values are over-constrained + // or not. + + + // Make final adjustments to height. + int contentHeight = m_height; + if ((contentHeight < heightValue) || (hasOverflowClip() && contentHeight > heightValue)) + contentHeight = heightValue; + + // Do not allow the height to be negative. This can happen when someone + // specifies both top and bottom but the containing block height is less + // than top, e.g., top: 20px, bottom: 0, containing block height 16. + heightValue = max(0, contentHeight); + + // If our content height exceeds the new height once we've set it, then we + // need to make sure to update overflow to track the spillout. + if (m_height > heightValue) + setOverflowHeight(m_height); - if (hasOverflowClip() && ourHeight > h + pab) - ourHeight = h + pab; - - // Do not allow the height to be negative. This can happen when someone specifies both top and bottom - // but the containing block height is less than top, e.g., top:20px, bottom:0, containing block height 16. - ourHeight = max(0, ourHeight); - - h = ourHeight; - y = t + mt + cb->borderTop(); + // Set final values. + m_height = heightValue; + + // Use computed values to caluculate the vertical position. + m_y = topValue + m_marginTop + containerBlock->borderTop(); } IntRect RenderBox::caretRect(int offset, EAffinity affinity, int* extraWidthToEndOfLine) diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h index 8958a6dae96d..b3a5648270b7 100644 --- a/WebCore/rendering/RenderBox.h +++ b/WebCore/rendering/RenderBox.h @@ -158,11 +158,18 @@ protected: void calcAbsoluteHorizontal(); void calcAbsoluteVertical(); - void calcAbsoluteHorizontalValues(WidthType widthType, RenderObject* cb, int cw, int pab, int static_distance, - int l, int r, int& w, int& ml, int& mr, int& x); - void calcAbsoluteVerticalValues(HeightType heightType, RenderObject* cb, int ch, int pab, - int t, int b, int& h, int& mt, int& mb, int& y); - + void calcAbsoluteHorizontalValues(Length width, const RenderObject* cb, + const int containerWidth, const int bordersPlusPadding, + const Length left, const Length right, const Length marginLeft, const Length marginRight, + int& widthValue, int& marginLeftValue, int& marginRightValue, int& xPos); + void calcAbsoluteVerticalValues(Length height, const RenderObject* cb, + const int containerHeight, const int bordersPlusPadding, + const Length top, const Length bottom, const Length marginTop, const Length marginBottom, + int& heightValue, int& marginTopValue, int& marginBottomValue, int& yPos); + + void calcAbsoluteVerticalReplaced(); + void calcAbsoluteHorizontalReplaced(); + virtual IntRect getOverflowClipRect(int tx, int ty); virtual IntRect getClipRect(int tx, int ty); -- 2.36.0