/** * Calculate the ideal used value for the width property as per: * http://www.w3.org/TR/CSS21/visudet.html#Computing_widths_and_margins * * @param float $width * @return array */ protected function _calculate_width($width) { $style = $this->_frame->get_style(); $w = $this->_frame->get_containing_block("w"); if ($style->position === "fixed") { $w = $this->_frame->get_parent()->get_containing_block("w"); } $rm = $style->length_in_pt($style->margin_right, $w); $lm = $style->length_in_pt($style->margin_left, $w); $left = $style->length_in_pt($style->left, $w); $right = $style->length_in_pt($style->right, $w); // Handle 'auto' values $dims = array($style->border_left_width, $style->border_right_width, $style->padding_left, $style->padding_right, $width !== "auto" ? $width : 0, $rm !== "auto" ? $rm : 0, $lm !== "auto" ? $lm : 0); // absolutely positioned boxes take the 'left' and 'right' properties into account if ($style->position === "absolute" || $style->position === "fixed") { $absolute = true; $dims[] = $left !== "auto" ? $left : 0; $dims[] = $right !== "auto" ? $right : 0; } else { $absolute = false; } $sum = $style->length_in_pt($dims, $w); // Compare to the containing block $diff = $w - $sum; if ($diff > 0) { if ($absolute) { // resolve auto properties: see // http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width if ($width === "auto" && $left === "auto" && $right === "auto") { if ($lm === "auto") { $lm = 0; } if ($rm === "auto") { $rm = 0; } // Technically, the width should be "shrink-to-fit" i.e. based on the // preferred width of the content... a little too costly here as a // special case. Just get the width to take up the slack: $left = 0; $right = 0; $width = $diff; } else { if ($width === "auto") { if ($lm === "auto") { $lm = 0; } if ($rm === "auto") { $rm = 0; } if ($left === "auto") { $left = 0; } if ($right === "auto") { $right = 0; } $width = $diff; } else { if ($left === "auto") { if ($lm === "auto") { $lm = 0; } if ($rm === "auto") { $rm = 0; } if ($right === "auto") { $right = 0; } $left = $diff; } else { if ($right === "auto") { if ($lm === "auto") { $lm = 0; } if ($rm === "auto") { $rm = 0; } $right = $diff; } } } } } else { // Find auto properties and get them to take up the slack if ($width === "auto") { $width = $diff; } else { if ($lm === "auto" && $rm === "auto") { $lm = $rm = round($diff / 2); } else { if ($lm === "auto") { $lm = $diff; } else { if ($rm === "auto") { $rm = $diff; } } } } } } else { if ($diff < 0) { // We are over constrained--set margin-right to the difference $rm = $diff; } } return array("width" => $width, "margin_left" => $lm, "margin_right" => $rm, "left" => $left, "right" => $right); }