| 1 |
lars |
1 |
<?php
|
|
|
2 |
|
|
|
3 |
class StrategyWidthAbsolutePositioned {
|
|
|
4 |
function StrategyWidthAbsolutePositioned() {
|
|
|
5 |
}
|
|
|
6 |
|
|
|
7 |
/**
|
|
|
8 |
* See also CSS 2.1, p 10.3.7 Absolutely positioned, non-replaced
|
|
|
9 |
* elements
|
|
|
10 |
*/
|
|
|
11 |
function apply(&$box, &$context) {
|
|
|
12 |
$containing_block =& $box->_get_containing_block();
|
|
|
13 |
$containing_block_width = $containing_block['right'] - $containing_block['left'];
|
|
|
14 |
|
|
|
15 |
$right =& $box->get_css_property(CSS_RIGHT);
|
|
|
16 |
$left =& $box->get_css_property(CSS_LEFT);
|
|
|
17 |
$wc =& $box->get_css_property(CSS_WIDTH);
|
|
|
18 |
|
|
|
19 |
// For the purposes of this section and the next, the term "static
|
|
|
20 |
// position" (of an element) refers, roughly, to the position an
|
|
|
21 |
// element would have had in the normal flow. More precisely:
|
|
|
22 |
//
|
|
|
23 |
// * The static position for 'left' is the distance from the left
|
|
|
24 |
// edge of the containing block to the left margin edge of a
|
|
|
25 |
// hypothetical box that would have been the first box of the
|
|
|
26 |
// element if its 'position' property had been 'static' and
|
|
|
27 |
// 'float' had been 'none'. The value is negative if the
|
|
|
28 |
// hypothetical box is to the left of the containing block.
|
|
|
29 |
//
|
|
|
30 |
// * The static position for 'right' is the distance from the
|
|
|
31 |
// right edge of the containing block to the right margin edge
|
|
|
32 |
// of the same hypothetical box as above. The value is positive
|
|
|
33 |
// if the hypothetical box is to the left of the containing
|
|
|
34 |
// block's edge.
|
|
|
35 |
//
|
|
|
36 |
// For the purposes of calculating the static position, the
|
|
|
37 |
// containing block of fixed positioned elements is the initial
|
|
|
38 |
// containing block instead of the viewport, and all scrollable
|
|
|
39 |
// boxes should be assumed to be scrolled to their origin.
|
|
|
40 |
//
|
|
|
41 |
// @todo: implement
|
|
|
42 |
$static_left = 0;
|
|
|
43 |
$static_right = 0;
|
|
|
44 |
|
|
|
45 |
// Calculation of the shrink-to-fit width is similar to
|
|
|
46 |
// calculating the width of a table cell using the automatic table
|
|
|
47 |
// layout algorithm. Roughly: calculate the preferred width by
|
|
|
48 |
// formatting the content without breaking lines other than where
|
|
|
49 |
// explicit line breaks occur, and also calculate the preferred
|
|
|
50 |
// minimum width, e.g., by trying all possible line breaks. CSS
|
|
|
51 |
// 2.1 does not define the exact algorithm. Thirdly, calculate the
|
|
|
52 |
// available width: this is found by solving for 'width' after
|
|
|
53 |
// setting 'left' (in case 1) or 'right' (in case 3) to 0.
|
|
|
54 |
//
|
|
|
55 |
// Then the shrink-to-fit width is: min(max(preferred minimum
|
|
|
56 |
// width, available width), preferred width).
|
|
|
57 |
$preferred_minimum_width = $box->get_preferred_minimum_width($context);
|
|
|
58 |
$available_width = $containing_block_width -
|
|
|
59 |
($left->isAuto() ? 0 : $left->getPoints($containing_block_width)) -
|
|
|
60 |
($right->isAuto() ? 0 : $right->getPoints($containing_block_width)) -
|
|
|
61 |
$box->_get_hor_extra();
|
|
|
62 |
$preferred_width = $box->get_preferred_width($context);
|
|
|
63 |
|
|
|
64 |
$shrink_to_fit_width = min(max($preferred_minimum_width,
|
|
|
65 |
$available_width),
|
|
|
66 |
$preferred_width);
|
|
|
67 |
|
|
|
68 |
// The constraint that determines the used values for these
|
|
|
69 |
// elements is:
|
|
|
70 |
//
|
|
|
71 |
// 'left' + 'margin-left' + 'border-left-width' + 'padding-left' +
|
|
|
72 |
// 'width' + 'padding-right' + 'border-right-width' +
|
|
|
73 |
// 'margin-right' + 'right' + scrollbar width (if any) = width of
|
|
|
74 |
// containing block
|
|
|
75 |
|
|
|
76 |
// If all three of 'left', 'width', and 'right' are 'auto': First
|
|
|
77 |
// set any 'auto' values for 'margin-left' and 'margin-right' to
|
|
|
78 |
// 0. Then, if the 'direction' property of the containing block is
|
|
|
79 |
// 'ltr' set 'left' to the static position and apply rule number
|
|
|
80 |
// three below; otherwise, set 'right' to the static position and
|
|
|
81 |
// apply rule number one below.
|
|
|
82 |
if ($left->isAuto() && $right->isAuto() && $wc->isNull()) {
|
|
|
83 |
// @todo: support 'direction' property for the containing block
|
|
|
84 |
$box->setCSSProperty(CSS_LEFT, ValueLeft::fromString('0'));
|
|
|
85 |
};
|
|
|
86 |
|
|
|
87 |
// If none of the three is 'auto': If both 'margin-left' and
|
|
|
88 |
// 'margin-right' are 'auto', solve the equation under the extra
|
|
|
89 |
// constraint that the two margins get equal values, unless this
|
|
|
90 |
// would make them negative, in which case when direction of the
|
|
|
91 |
// containing block is 'ltr' ('rtl'), set 'margin-left'
|
|
|
92 |
// ('margin-right') to zero and solve for 'margin-right'
|
|
|
93 |
// ('margin-left'). If one of 'margin-left' or 'margin-right' is
|
|
|
94 |
// 'auto', solve the equation for that value. If the values are
|
|
|
95 |
// over-constrained, ignore the value for 'left' (in case the
|
|
|
96 |
// 'direction' property of the containing block is 'rtl') or
|
|
|
97 |
// 'right' (in case 'direction' is 'ltr') and solve for that
|
|
|
98 |
// value.
|
|
|
99 |
if (!$left->isAuto() && !$right->isAuto() && !$wc->isNull()) {
|
|
|
100 |
// @todo: implement
|
|
|
101 |
$box->put_width($wc->apply($box->get_width(),
|
|
|
102 |
$containing_block_width));
|
|
|
103 |
};
|
|
|
104 |
|
|
|
105 |
// Otherwise, set 'auto' values for 'margin-left' and
|
|
|
106 |
// 'margin-right' to 0, and pick the one of the following six
|
|
|
107 |
// rules that applies.
|
|
|
108 |
|
|
|
109 |
// Case 1 ('left' and 'width' are 'auto' and 'right' is not
|
|
|
110 |
// 'auto', then the width is shrink-to-fit. Then solve for 'left')
|
|
|
111 |
if ($left->isAuto() && !$right->isAuto() && $wc->isNull()) {
|
|
|
112 |
$box->put_width($shrink_to_fit_width);
|
|
|
113 |
};
|
|
|
114 |
|
|
|
115 |
// Case 2 ('left' and 'right' are 'auto' and 'width' is not
|
|
|
116 |
// 'auto', then if the 'direction' property of the containing
|
|
|
117 |
// block is 'ltr' set 'left' to the static position, otherwise set
|
|
|
118 |
// 'right' to the static position. Then solve for 'left' (if
|
|
|
119 |
// 'direction is 'rtl') or 'right' (if 'direction' is 'ltr').)
|
|
|
120 |
if ($left->isAuto() && $right->isAuto() && !$wc->isNull()) {
|
|
|
121 |
// @todo: implement 'direction' support
|
|
|
122 |
$box->put_width($wc->apply($box->get_width(),
|
|
|
123 |
$containing_block_width));
|
|
|
124 |
};
|
|
|
125 |
|
|
|
126 |
// Case 3 ('width' and 'right' are 'auto' and 'left' is not
|
|
|
127 |
// 'auto', then the width is shrink-to-fit . Then solve for
|
|
|
128 |
// 'right')
|
|
|
129 |
if (!$left->isAuto() && $right->isAuto() && $wc->isNull()) {
|
|
|
130 |
$box->put_width($shrink_to_fit_width);
|
|
|
131 |
};
|
|
|
132 |
|
|
|
133 |
// Case 4 ('left' is 'auto', 'width' and 'right' are not 'auto',
|
|
|
134 |
// then solve for 'left')
|
|
|
135 |
if ($left->isAuto() && !$right->isAuto() && !$wc->isNull()) {
|
|
|
136 |
$box->put_width($wc->apply($box->get_width(),
|
|
|
137 |
$containing_block_width));
|
|
|
138 |
};
|
|
|
139 |
|
|
|
140 |
// Case 5 ('width' is 'auto', 'left' and 'right' are not 'auto',
|
|
|
141 |
// then solve for 'width')
|
|
|
142 |
if (!$left->isAuto() && !$right->isAuto() && $wc->isNull()) {
|
|
|
143 |
$box->put_width($containing_block_width -
|
|
|
144 |
$left->getPoints($containing_block_width) -
|
|
|
145 |
$right->getPoints($containing_block_width));
|
|
|
146 |
};
|
|
|
147 |
|
|
|
148 |
// Case 6 ('right' is 'auto', 'left' and 'width' are not 'auto',
|
|
|
149 |
// then solve for 'right')
|
|
|
150 |
if (!$left->isAuto() && $right->isAuto() && !$wc->isNull()) {
|
|
|
151 |
$box->put_width($wc->apply($box->get_width(),
|
|
|
152 |
$containing_block_width));
|
|
|
153 |
};
|
|
|
154 |
|
|
|
155 |
/**
|
|
|
156 |
* After this we should remove width constraints or we may encounter problem
|
|
|
157 |
* in future when we'll try to call get_..._width functions for this box
|
|
|
158 |
*
|
|
|
159 |
* @todo Update the family of get_..._width function so that they would apply constraint
|
|
|
160 |
* using the containing block width, not "real" parent width
|
|
|
161 |
*/
|
|
|
162 |
$box->setCSSProperty(CSS_WIDTH, new WCConstant($box->get_width()));
|
|
|
163 |
}
|
|
|
164 |
}
|
|
|
165 |
|
|
|
166 |
?>
|