/** * 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) { $style = $p->get_style(); $max_y += $style->length_in_pt(array($style->margin_bottom, $style->padding_bottom, $style->border_bottom_width)); $p = $p->get_parent(); } // Check if $frame flows off the page if ($max_y <= $this->_bottom_page_margin) { // no: do nothing return false; } dompdf_debug("page-break", "check_page_break"); dompdf_debug("page-break", "in_table: " . $this->_in_table); // yes: determine page break location $iter = $frame; $flg = false; $in_table = $this->_in_table; dompdf_debug("page-break", "Starting search"); while ($iter) { // echo "\nbacktrack: " .$iter->get_node()->nodeName ." ".spl_object_hash($iter->get_node()). ""; if ($iter === $this) { 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)) { 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())) { dompdf_debug("page-break", "following last child."); if ($next->is_table()) { $this->_in_table++; } $iter = $next; continue; } if ($next = $iter->get_prev_sibling()) { 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()) { 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. 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) { $num_tables = $this->_in_table - 1; $iter = $frame; while ($iter && $num_tables && $iter->get_style()->display !== "table") { $iter = $iter->get_parent(); $num_tables--; } $iter = $frame; while ($iter && $iter->get_style()->display !== "table-row") { $iter = $iter->get_parent(); } } $frame->split(null, true); $this->_page_full = true; $frame->_already_pushed = true; return true; }
function get_margin_height() { return $this->_frame->get_margin_height(); }
function add_frame_to_line(Frame $frame) { // Handle inline frames (which are effectively wrappers) if ($frame instanceof Inline_Frame_Decorator) { // Handle line breaks if ($frame->get_node()->nodeName == "br") { $this->maximize_line_height($frame->get_style()->length_in_pt($frame->get_style()->line_height)); $this->add_line(); return; } // Add each child of the inline frame to the line individually foreach ($frame->get_children() as $child) { $this->add_frame_to_line($child); } return; } // Trim leading text if this is an empty line. Kinda a hack to put it here, // but what can you do... if ($this->_lines[$this->_cl]["w"] == 0 && $frame->get_node()->nodeName == "#text" && ($frame->get_style()->white_space != "pre" || $frame->get_style()->white_space != "pre-wrap")) { $frame->set_text(ltrim($frame->get_text())); $frame->recalculate_width(); } $w = $frame->get_margin_width(); if ($w == 0) { return; } // Debugging code: /* pre_r("\nAdding frame to line:"); // pre_r("Me: " . $this->get_node()->nodeName . " (" . (string)$this->get_node() . ")"); // pre_r("Node: " . $frame->get_node()->nodeName . " (" . (string)$frame->get_node() . ")"); if ( $frame->get_node()->nodeName == "#text" ) pre_r($frame->get_node()->nodeValue); pre_r("Line width: " . $this->_lines[$this->_cl]["w"]); pre_r("Frame: " . get_class($frame)); pre_r("Frame width: " . $w); pre_r("Frame height: " . $frame->get_margin_height()); pre_r("Containing block width: " . $this->get_containing_block("w")); */ // End debugging if ($this->_lines[$this->_cl]["w"] + $w > $this->get_containing_block("w")) { $this->add_line(); } $frame->position(); $this->_lines[$this->_cl]["frames"][] = $frame; if ($frame->get_node()->nodeName == "#text") { $this->_lines[$this->_cl]["wc"] += count(preg_split("/\\s+/", $frame->get_text())); } $this->_lines[$this->_cl]["w"] += $w; $this->_lines[$this->_cl]["h"] = max($this->_lines[$this->_cl]["h"], $frame->get_margin_height()); }
/** * 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 if ($this->_page_full) { return false; } // Determine the frame's maximum y value $max_y = $frame->get_position("y") + $frame->get_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) { $style = $p->get_style(); $max_y += $style->length_in_pt(array($style->margin_bottom, $style->padding_bottom, $style->border_bottom_width)); $p = $p->get_parent(); } // Check if $frame flows off the page if ($max_y <= $this->_bottom_page_margin) { // no: do nothing (?) return false; } // echo "check_page_break\n"; // yes: determine page break location $iter = $frame; $flg = false; $in_table = $this->_in_table; // echo "Starting search\n"; while ($iter) { // echo "\nbacktrack: " .$iter->get_node()->nodeName ." ".(string)$iter->get_node(). "\n"; if ($iter === $this) { // echo "reached root.\n"; // We've reached the root in our search. Just split at $frame. break; } if ($this->_page_break_allowed($iter)) { // echo "break allowed, splitting.\n"; $iter->split(); $this->_page_full = true; $this->_in_table = $in_table; return true; } if (!$flg && ($next = $iter->get_last_child())) { // echo "following last child.\n"; if (in_array($next->get_style()->display, Style::$TABLE_TYPES)) { $this->_in_table++; } $iter = $next; continue; } if ($next = $iter->get_prev_sibling()) { // echo "following prev sibling.\n"; if (in_array($next->get_style()->display, Style::$TABLE_TYPES) && !in_array($iter->get_style()->display, Style::$TABLE_TYPES)) { $this->_in_table++; } else { if (!in_array($next->get_style()->display, Style::$TABLE_TYPES) && in_array($iter->get_style()->display, Style::$TABLE_TYPES)) { $this->_in_table--; } } $iter = $next; $flg = false; continue; } if ($next = $iter->get_parent()) { // echo "following parent.\n"; if (in_array($iter->get_style()->display, Style::$TABLE_TYPES)) { $this->_in_table--; } $iter = $next; $flg = true; continue; } break; } $this->_in_table = $in_table; // No valid page break found. Just break at $frame. // echo "no valid break found, just splitting.\n"; // If we are in a table, backtrack to the nearest table row if ($this->_in_table) { $tr = $frame; while ($tr && $tr->get_style()->display != "table-row") { $tr = $tr->get_parent(); } $tr->split(); $this->_page_full = true; return true; } $frame->split(); $this->_page_full = true; return true; }
function add_frame_to_line(Frame $frame) { // Handle inline frames (which are effectively wrappers) if ($frame instanceof Inline_Frame_Decorator) { // Add each child of the inline frame to the line individually foreach ($frame->get_children() as $child) { $this->add_frame_to_line($child); } return; } if ($frame->get_margin_width() == 0) { return; } $w = $frame->get_margin_width(); // Debugging code: // pre_r("\nAdding frame to line:"); // pre_r("Me: " . $this->get_node()->nodeName . " (" . (string)$this->get_node() . ")"); // pre_r("Node: " . $frame->get_node()->nodeName . " (" . (string)$frame->get_node() . ")"); // if ( $frame->get_node()->nodeName == "#text" ) // pre_r($frame->get_node()->nodeValue); // pre_r("Line width: " . $this->_lines[$this->_cl]["w"]); // pre_r("Frame width: " . $w); // pre_r("Frame height: " . $frame->get_margin_height()); // pre_r("Containing block width: " . $this->get_containing_block("w")); // End debugging if ($this->_lines[$this->_cl]["w"] + $w >= $this->get_containing_block("w")) { $this->add_line(); } $frame->position(); $this->_lines[$this->_cl]["frames"][] = $frame; if ($frame->get_node()->nodeName == "#text") { $this->_lines[$this->_cl]["wc"] += count(preg_split("/\\s+/", $frame->get_text())); } $this->_lines[$this->_cl]["w"] += $w; $this->_lines[$this->_cl]["h"] = max($this->_lines[$this->_cl]["h"], $frame->get_margin_height()); }
function check_page_break(Frame $frame) { if ($this->_page_full || $frame->_already_pushed) { return false; } $p = $frame; do { if ($p->is_absolute()) { return false; } } while ($p = $p->get_parent()); $margin_height = $frame->get_margin_height(); if ($frame->get_style()->display === "table-row" && !$frame->get_prev_sibling() && $margin_height > $this->get_margin_height()) { return false; } $max_y = $frame->get_position("y") + $margin_height; $p = $frame->get_parent(); while ($p) { $style = $p->get_style(); $max_y += $style->length_in_pt(array($style->margin_bottom, $style->padding_bottom, $style->border_bottom_width)); $p = $p->get_parent(); } if ($max_y <= $this->_bottom_page_margin) { return false; } dompdf_debug("page-break", "check_page_break"); dompdf_debug("page-break", "in_table: " . $this->_in_table); $iter = $frame; $flg = false; $in_table = $this->_in_table; dompdf_debug("page-break", "Starting search"); while ($iter) { if ($iter === $this) { dompdf_debug("page-break", "reached root."); break; } if ($this->_page_break_allowed($iter)) { 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())) { dompdf_debug("page-break", "following last child."); if ($next->is_table()) { $this->_in_table++; } $iter = $next; continue; } if ($next = $iter->get_prev_sibling()) { 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()) { dompdf_debug("page-break", "following parent."); if ($iter->is_table()) { $this->_in_table--; } $iter = $next; $flg = true; continue; } break; } $this->_in_table = $in_table; dompdf_debug("page-break", "no valid break found, just splitting."); if ($this->_in_table) { $num_tables = $this->_in_table - 1; $iter = $frame; while ($iter && $num_tables && $iter->get_style()->display !== "table") { $iter = $iter->get_parent(); $num_tables--; } $iter = $frame; while ($iter && $iter->get_style()->display !== "table-row") { $iter = $iter->get_parent(); } } $frame->split(null, true); $this->_page_full = true; $frame->_already_pushed = true; return true; }