Skip to content

Commit 241bb9a

Browse files
Mellthasbsweeney
authored andcommitted
Properly take negative margins into account when collapsing margins
See https://www.w3.org/TR/CSS2/box.html#collapsing-margins. Addresses dompdf#1546
1 parent 7fa44db commit 241bb9a

File tree

1 file changed

+32
-4
lines changed

1 file changed

+32
-4
lines changed

src/FrameReflower/AbstractFrameReflower.php

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,11 @@ protected function _collapse_margins()
108108

109109
if ($n) {
110110
$n_style = $n->get_style();
111-
$b = max($b, (float)$n_style->length_in_pt($n_style->margin_top, $cb["h"]));
112-
$n_style->margin_top = "0pt";
111+
$n_t = (float)$n_style->length_in_pt($n_style->margin_top, $cb["h"]);
112+
113+
$b = $this->_get_collapsed_margin_length($b, $n_t);
113114
$style->margin_bottom = $b . "pt";
115+
$n_style->margin_top = "0pt";
114116
}
115117

116118
// Collapse our first child's margin, if there is no border or padding
@@ -132,7 +134,9 @@ protected function _collapse_margins()
132134
// Margin are collapsed only between block-level boxes
133135
if ($f) {
134136
$f_style = $f->get_style();
135-
$t = max($t, (float)$f_style->length_in_pt($f_style->margin_top, $cb["h"]));
137+
$f_t = (float)$f_style->length_in_pt($f_style->margin_top, $cb["h"]);
138+
139+
$t = $this->_get_collapsed_margin_length($t, $f_t);
136140
$style->margin_top = $t."pt";
137141
$f_style->margin_top = "0pt";
138142
}
@@ -157,13 +161,37 @@ protected function _collapse_margins()
157161
// Margin are collapsed only between block-level boxes
158162
if ($l) {
159163
$l_style = $l->get_style();
160-
$b = max($b, (float)$l_style->length_in_pt($l_style->margin_bottom, $cb["h"]));
164+
$l_b = (float)$l_style->length_in_pt($l_style->margin_bottom, $cb["h"]);
165+
166+
$b = $this->_get_collapsed_margin_length($b, $l_b);
161167
$style->margin_bottom = $b."pt";
162168
$l_style->margin_bottom = "0pt";
163169
}
164170
}
165171
}
166172

173+
/**
174+
* Get the combined (collapsed) length of two adjoining margins.
175+
*
176+
* See http://www.w3.org/TR/CSS2/box.html#collapsing-margins.
177+
*
178+
* @param number $length1
179+
* @param number $length2
180+
* @return number
181+
*/
182+
private function _get_collapsed_margin_length($length1, $length2)
183+
{
184+
if ($length1 < 0 && $length2 < 0) {
185+
return min($length1, $length2); // min(x, y) = - max(abs(x), abs(y)), if x < 0 && y < 0
186+
}
187+
188+
if ($length1 < 0 || $length2 < 0) {
189+
return $length1 + $length2; // x + y = x - abs(y), if y < 0
190+
}
191+
192+
return max($length1, $length2);
193+
}
194+
167195
/**
168196
* @param Block|null $block
169197
* @return mixed

0 commit comments

Comments
 (0)