@@ -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