_get_containing_block(); $containing_block_width = $containing_block['right'] - $containing_block['left']; $right =& $box->get_css_property(CSS_RIGHT); $left =& $box->get_css_property(CSS_LEFT); $wc =& $box->get_css_property(CSS_WIDTH); // 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. // // 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. // // @todo: implement $static_left = 0; $static_right = 0; // 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). $preferred_minimum_width = $box->get_preferred_minimum_width($context); $available_width = $containing_block_width - ($left->isAuto() ? 0 : $left->getPoints($containing_block_width)) - ($right->isAuto() ? 0 : $right->getPoints($containing_block_width)) - $box->_get_hor_extra(); $preferred_width = $box->get_preferred_width($context); $shrink_to_fit_width = min(max($preferred_minimum_width, $available_width), $preferred_width); // The constraint that determines the used values for these // elements is: // // 'left' + 'margin-left' + 'border-left-width' + 'padding-left' + // 'width' + 'padding-right' + 'border-right-width' + // 'margin-right' + 'right' + scrollbar width (if any) = width of // containing block // If all three of 'left', 'width', and 'right' are 'auto': First // set any 'auto' values for 'margin-left' and 'margin-right' to // 0. Then, if the 'direction' property of the containing block is // 'ltr' set 'left' to the static position and apply rule number // three below; otherwise, set 'right' to the static position and // apply rule number one below. if ($left->isAuto() && $right->isAuto() && $wc->isNull()) { // @todo: support 'direction' property for the containing block $box->setCSSProperty(CSS_LEFT, ValueLeft::fromString('0')); }; // 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. if (!$left->isAuto() && !$right->isAuto() && !$wc->isNull()) { // @todo: implement $box->put_width($wc->apply($box->get_width(), $containing_block_width)); }; // Otherwise, set 'auto' values for 'margin-left' and // 'margin-right' to 0, and pick the one of the following six // rules that applies. // Case 1 ('left' and 'width' are 'auto' and 'right' is not // 'auto', then the width is shrink-to-fit. Then solve for 'left') if ($left->isAuto() && !$right->isAuto() && $wc->isNull()) { $box->put_width($shrink_to_fit_width); }; // Case 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').) if ($left->isAuto() && $right->isAuto() && !$wc->isNull()) { // @todo: implement 'direction' support $box->put_width($wc->apply($box->get_width(), $containing_block_width)); }; // Case 3 ('width' and 'right' are 'auto' and 'left' is not // 'auto', then the width is shrink-to-fit . Then solve for // 'right') if (!$left->isAuto() && $right->isAuto() && $wc->isNull()) { $box->put_width($shrink_to_fit_width); }; // Case 4 ('left' is 'auto', 'width' and 'right' are not 'auto', // then solve for 'left') if ($left->isAuto() && !$right->isAuto() && !$wc->isNull()) { $box->put_width($wc->apply($box->get_width(), $containing_block_width)); }; // Case 5 ('width' is 'auto', 'left' and 'right' are not 'auto', // then solve for 'width') if (!$left->isAuto() && !$right->isAuto() && $wc->isNull()) { $box->put_width($containing_block_width - $left->getPoints($containing_block_width) - $right->getPoints($containing_block_width)); }; // Case 6 ('right' is 'auto', 'left' and 'width' are not 'auto', // then solve for 'right') if (!$left->isAuto() && $right->isAuto() && !$wc->isNull()) { $box->put_width($wc->apply($box->get_width(), $containing_block_width)); }; /** * After this we should remove width constraints or we may encounter problem * in future when we'll try to call get_..._width functions for this box * * @todo Update the family of get_..._width function so that they would apply constraint * using the containing block width, not "real" parent width */ $box->setCSSProperty(CSS_WIDTH, new WCConstant($box->get_width())); } } ?>