/** * @return AbstractFrameDecorator */ function get_prev_sibling() { $s = $this->_frame->get_prev_sibling(); if ($s && ($deco = $s->get_decorator())) { while ($tmp = $deco->get_decorator()) { $deco = $tmp; } return $deco; } else { if ($s) { return $s; } } return null; }
/** * Check if $frame will fit on the page. If the frame does not fit, * the frame tree is modified so that a page break occurs in the * correct location. * * @param Frame $frame the frame to check * * @return Frame the frame following the page break */ function check_page_break(Frame $frame) { // Do not split if we have already or if the frame was already // pushed to the next page (prevents infinite loops) if ($this->_page_full || $frame->_already_pushed) { return false; } // If the frame is absolute of fixed it shouldn't break $p = $frame; do { if ($p->is_absolute()) { return false; } } while ($p = $p->get_parent()); $margin_height = $frame->get_margin_height(); // FIXME If the row is taller than the page and // if it the first of the page, we don't break if ($frame->get_style()->display === "table-row" && !$frame->get_prev_sibling() && $margin_height > $this->get_margin_height()) { return false; } // Determine the frame's maximum y value $max_y = $frame->get_position("y") + $margin_height; // If a split is to occur here, then the bottom margins & paddings of all // parents of $frame must fit on the page as well: $p = $frame->get_parent(); while ($p) { $max_y += $p->get_style()->computed_bottom_spacing(); $p = $p->get_parent(); } // Check if $frame flows off the page if ($max_y <= $this->_bottom_page_margin) { // no: do nothing return false; } Helpers::dompdf_debug("page-break", "check_page_break"); Helpers::dompdf_debug("page-break", "in_table: " . $this->_in_table); // yes: determine page break location $iter = $frame; $flg = false; $in_table = $this->_in_table; Helpers::dompdf_debug("page-break", "Starting search"); while ($iter) { // echo "\nbacktrack: " .$iter->get_node()->nodeName ." ".spl_object_hash($iter->get_node()). ""; if ($iter === $this) { Helpers::dompdf_debug("page-break", "reached root."); // We've reached the root in our search. Just split at $frame. break; } if ($this->_page_break_allowed($iter)) { Helpers::dompdf_debug("page-break", "break allowed, splitting."); $iter->split(null, true); $this->_page_full = true; $this->_in_table = $in_table; $frame->_already_pushed = true; return true; } if (!$flg && ($next = $iter->get_last_child())) { Helpers::dompdf_debug("page-break", "following last child."); if ($next->is_table()) { $this->_in_table++; } $iter = $next; continue; } if ($next = $iter->get_prev_sibling()) { Helpers::dompdf_debug("page-break", "following prev sibling."); if ($next->is_table() && !$iter->is_table()) { $this->_in_table++; } else { if (!$next->is_table() && $iter->is_table()) { $this->_in_table--; } } $iter = $next; $flg = false; continue; } if ($next = $iter->get_parent()) { Helpers::dompdf_debug("page-break", "following parent."); if ($iter->is_table()) { $this->_in_table--; } $iter = $next; $flg = true; continue; } break; } $this->_in_table = $in_table; // No valid page break found. Just break at $frame. Helpers::dompdf_debug("page-break", "no valid break found, just splitting."); // If we are in a table, backtrack to the nearest top-level table row if ($this->_in_table) { $iter = $frame; while ($iter && $iter->get_style()->display !== "table-row" && $iter->get_style()->display !== 'table-row-group') { $iter = $iter->get_parent(); } $iter->split(null, true); } else { $frame->split(null, true); } $this->_page_full = true; $frame->_already_pushed = true; return true; }