function render(Frame $frame) { $style = $frame->get_style(); $bullet_style = $style->list_style_type; $bullet_size = List_Bullet_Frame_Decorator::BULLET_SIZE; $line_height = $style->length_in_pt($style->line_height, $frame->get_containing_block("w")); $fill = false; switch ($bullet_style) { default: case "disc": $fill = true; case "circle": if (!$fill) { $fill = false; } list($x, $y) = $frame->get_position(); $x += $bullet_size / 2; $y += $line_height / 2 + $bullet_size / 4; $r = $bullet_size / 4; $this->_canvas->circle($x, $y, $r, $style->color, null, null, $fill); break; case "square": list($x, $y) = $frame->get_position(); $w = $bullet_size / 2; $x += $bullet_size / 2 - $w / 2; $y += $line_height / 2; $this->_canvas->filled_rectangle($x, $y, $w, $w, $style->color); break; } }
function render(Frame $frame) { $style = $frame->get_style(); $font_size = $style->get_font_size(); $line_height = $style->length_in_pt($style->line_height, $frame->get_containing_block("w")); // Handle list-style-image // If list style image is requested but missing, fall back to predefined types if ($style->list_style_image !== "none" && strcmp($img = $frame->get_image_url(), DOMPDF_LIB_DIR . "/res/broken_image.png") != 0) { list($x, $y) = $frame->get_position(); //For expected size and aspect, instead of box size, use image natural size scaled to DPI. // Resample the bullet image to be consistent with 'auto' sized images // See also Image_Frame_Reflower::get_min_max_width // Tested php ver: value measured in px, suffix "px" not in value: rtrim unnecessary. //$w = $frame->get_width(); //$h = $frame->get_height(); list($width, $height) = getimagesize($img); $w = (double) rtrim($width, "px") * 72 / DOMPDF_DPI; $h = (double) rtrim($height, "px") * 72 / DOMPDF_DPI; $x -= $w; $y -= ($line_height - $font_size) / 2; //Reverse hinting of list_bullet_positioner $this->_canvas->image($img, $frame->get_image_ext(), $x, $y, $w, $h); } else { $bullet_style = $style->list_style_type; $fill = false; switch ($bullet_style) { default: case "disc": $fill = true; case "circle": list($x, $y) = $frame->get_position(); $r = $font_size * List_Bullet_Frame_Decorator::BULLET_SIZE / 2; $x -= $font_size * (List_Bullet_Frame_Decorator::BULLET_SIZE / 2); $y += $font_size * (1 - List_Bullet_Frame_Decorator::BULLET_DESCENT) / 2; $o = $font_size * List_Bullet_Frame_Decorator::BULLET_THICKNESS; $this->_canvas->circle($x, $y, $r, $style->color, $o, null, $fill); break; case "square": list($x, $y) = $frame->get_position(); $w = $font_size * List_Bullet_Frame_Decorator::BULLET_SIZE; $x -= $w; $y += $font_size * (1 - List_Bullet_Frame_Decorator::BULLET_DESCENT - List_Bullet_Frame_Decorator::BULLET_SIZE) / 2; $this->_canvas->filled_rectangle($x, $y, $w, $w, $style->color); break; case "none": break; } } }
function render(Frame $frame) { $style = $frame->get_style(); list($x, $y) = $frame->get_position(); $cb = $frame->get_containing_block(); if (($ml = $style->margin_left) == "auto" || $ml == "none") { $ml = 0; } if (($pl = $style->padding_left) == "auto" || $pl == "none") { $pl = 0; } if (($bl = $style->border_left_width) == "auto" || $bl == "none") { $bl = 0; } $x += $style->length_in_pt(array($ml, $pl, $bl), $cb["w"]); $text = $frame->get_text(); $font = $style->font_family; $size = $style->font_size; $height = $style->height; $spacing = $frame->get_text_spacing() + $style->word_spacing; if (preg_replace("/[\\s]+/", "", $text) == "") { return; } $this->_canvas->text($x, $y, $text, $font, $size, $style->color, $spacing); // Handle text decoration: // http://www.w3.org/TR/CSS21/text.html#propdef-text-decoration // Draw all applicable text-decorations. Start with the root and work // our way down. $p = $frame; $stack = array(); while ($p = $p->get_parent()) { $stack[] = $p; } while (count($stack) > 0) { $f = array_pop($stack); $deco_y = $y; if (($text_deco = $f->get_style()->text_decoration) === "none") { continue; } $color = $f->get_style()->color; switch ($text_deco) { default: continue; case "underline": $deco_y += $height * (1 + self::UNDERLINE_OFFSET); break; case "overline": $deco_y += $height * self::OVERLINE_OFFSET; break; case "line-through": $deco_y -= $height * (0.25 + self::LINETHROUGH_OFFSET); break; } $dx = 0; $x1 = $x - self::DECO_EXTENSION; $x2 = $x + $style->width + $dx + self::DECO_EXTENSION; $this->_canvas->line($x1, $deco_y, $x2, $deco_y, $color, 0.5); } }
protected function _check_new_page() { $y = $this->_frame->get_position("y"); $h = $style->length_in_pt($style->height); // Check if we need to move to a new page if ($y + $h >= $this->_frame->get_root()->get_page_height()) { return true; } }
function render(Frame $frame) { $style = $frame->get_style(); $line_height = $style->length_in_pt($style->line_height, $frame->get_containing_block("w")); // Handle list-style-image if ($style->list_style_image != "none") { list($x, $y) = $frame->get_position(); $w = $frame->get_width(); $h = $frame->get_height(); $x += $w / 2; $y += $line_height / 2 - $h / 2; $this->_canvas->image($frame->get_image_url(), $frame->get_image_ext(), $x, $y, $w, $h); } else { $bullet_style = $style->list_style_type; $bullet_size = List_Bullet_Frame_Decorator::BULLET_SIZE; $fill = false; switch ($bullet_style) { default: case "disc": $fill = true; case "circle": if (!$fill) { $fill = false; } list($x, $y) = $frame->get_position(); $x += $bullet_size / 2 + List_Bullet_Frame_Decorator::BULLET_PADDING; $y += $line_height - $bullet_size; $r = $bullet_size / 2; $this->_canvas->circle($x, $y, $r, $style->color, 0.2, null, $fill); break; case "square": list($x, $y) = $frame->get_position(); $w = $bullet_size; $x += List_Bullet_Frame_Decorator::BULLET_PADDING; $y += $line_height - $w - List_Bullet_Frame_Decorator::BULLET_PADDING; $this->_canvas->filled_rectangle($x, $y, $w, $w, $style->color); break; } } }
/** * 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_position($i = null) { return $this->_frame->get_position($i); }
function render(Frame $frame) { $text = $frame->get_text(); if (trim($text) === "") { return; } $style = $frame->get_style(); list($x, $y) = $frame->get_position(); $cb = $frame->get_containing_block(); if (($ml = $style->margin_left) === "auto" || $ml === "none") { $ml = 0; } if (($pl = $style->padding_left) === "auto" || $pl === "none") { $pl = 0; } if (($bl = $style->border_left_width) === "auto" || $bl === "none") { $bl = 0; } $x += $style->length_in_pt(array($ml, $pl, $bl), $cb["w"]); $font = $style->font_family; $size = $frame_font_size = $style->font_size; $height = $style->height; $word_spacing = $frame->get_text_spacing() + $style->length_in_pt($style->word_spacing); $char_spacing = $style->length_in_pt($style->letter_spacing); $width = $style->width; /* * $text = str_replace( array("{PAGE_NUM}"), array($this->_canvas->get_page_number()), $text ); */ $this->_canvas->text($x, $y, $text, $font, $size, $style->color, $word_spacing, $char_spacing); $line = $frame->get_containing_line(); // FIXME Instead of using the tallest frame to position, // the decoration, the text should be well placed if (false && $line->tallest_frame) { $base_frame = $line->tallest_frame; $style = $base_frame->get_style(); $size = $style->font_size; $height = $line->h * ($size / $style->line_height); } if (method_exists($this->_canvas, "get_cpdf")) { $cpdf = $this->_canvas->get_cpdf(); // $cpdf_font = $cpdf->fonts[$style->font_family]; // $base = ($cpdf_font["UnderlinePosition"]*$size)/1000; // $descent = (($cpdf_font["Ascender"]-$cpdf_font["Descender"])*$size)/1000; $fontBBox = $cpdf->fonts[$style->font_family]['FontBBox']; $base = $fontBBox[3] * $size / 1000 * 0.9; $descent = $fontBBox[1] * $size / 1000; // print '<pre>Text_Renderer cpdf:'.$base.' '.$descent.' '.$size.'</pre>'; } else { // Descent is font part below baseline, typically negative. $height is about full height of font box. // $descent = -$size/6; is less accurate, depends on font family. // @todo Could we get font info for PDFlib adapter and others ? $base = $size * 1.08; $descent = $size - $height; // print '<pre>Text_Renderer other than cpdf:'.$base.' '.$descent.' '.$size.'</pre>'; } // Handle text decoration: // http://www.w3.org/TR/CSS21/text.html#propdef-text-decoration // Draw all applicable text-decorations. Start with the root and work our way down. $p = $frame; $stack = array(); while ($p = $p->get_parent()) { $stack[] = $p; } while (isset($stack[0])) { $f = array_pop($stack); if (($text_deco = $f->get_style()->text_decoration) === "none") { continue; } $deco_y = $y; // $line->y; $color = $f->get_style()->color; switch ($text_deco) { default: continue; case "underline": $deco_y += $base - $descent + $size * (self::UNDERLINE_OFFSET - self::DECO_THICKNESS / 2); break; case "overline": $deco_y += $size * (self::OVERLINE_OFFSET + self::DECO_THICKNESS / 2); break; case "line-through": $deco_y += $base * 0.7 + $size * self::LINETHROUGH_OFFSET; break; } $dx = 0; $x1 = $x - self::DECO_EXTENSION; $x2 = $x + $width + $dx + self::DECO_EXTENSION; $this->_canvas->line($x1, $deco_y, $x2, $deco_y, $color, $size * self::DECO_THICKNESS); } if (DEBUG_LAYOUT && DEBUG_LAYOUT_LINES) { $text_width = Font_Metrics::get_text_width($text, $font, $frame_font_size); $this->_debug_layout(array($x, $y, $text_width + ($line->wc - 1) * $word_spacing, $frame_font_size), "orange", array(0.5, 0.5)); } }
function render(Frame $frame) { $style = $frame->get_style(); $font_size = $style->get_font_size(); $line_height = $style->length_in_pt($style->line_height, $frame->get_containing_block("w")); $this->_set_opacity($frame->get_opacity($style->opacity)); // Handle list-style-image // If list style image is requested but missing, fall back to predefined types if ($style->list_style_image !== "none" && strcmp($img = $frame->get_image_url(), DOMPDF_LIB_DIR . "/res/broken_image.png") != 0) { list($x, $y) = $frame->get_position(); //For expected size and aspect, instead of box size, use image natural size scaled to DPI. // Resample the bullet image to be consistent with 'auto' sized images // See also Image_Frame_Reflower::get_min_max_width // Tested php ver: value measured in px, suffix "px" not in value: rtrim unnecessary. //$w = $frame->get_width(); //$h = $frame->get_height(); list($width, $height) = dompdf_getimagesize($img); $w = (double) rtrim($width, "px") * 72 / DOMPDF_DPI; $h = (double) rtrim($height, "px") * 72 / DOMPDF_DPI; $x -= $w; $y -= ($line_height - $font_size) / 2; //Reverse hinting of list_bullet_positioner $this->_canvas->image($img, $frame->get_image_ext(), $x, $y, $w, $h); } else { $bullet_style = $style->list_style_type; $fill = false; switch ($bullet_style) { default: case "disc": $fill = true; case "circle": list($x, $y) = $frame->get_position(); $r = $font_size * List_Bullet_Frame_Decorator::BULLET_SIZE / 2; $x -= $font_size * (List_Bullet_Frame_Decorator::BULLET_SIZE / 2); $y += $font_size * (1 - List_Bullet_Frame_Decorator::BULLET_DESCENT) / 2; $o = $font_size * List_Bullet_Frame_Decorator::BULLET_THICKNESS; $this->_canvas->circle($x, $y, $r, $style->color, $o, null, $fill); break; case "square": list($x, $y) = $frame->get_position(); $w = $font_size * List_Bullet_Frame_Decorator::BULLET_SIZE; $x -= $w; $y += $font_size * (1 - List_Bullet_Frame_Decorator::BULLET_DESCENT - List_Bullet_Frame_Decorator::BULLET_SIZE) / 2; $this->_canvas->filled_rectangle($x, $y, $w, $w, $style->color); break; case "decimal-leading-zero": case "decimal": case "lower-alpha": case "lower-latin": case "lower-roman": case "lower-greek": case "upper-alpha": case "upper-latin": case "upper-roman": case "1": // HTML 4.0 compatibility // HTML 4.0 compatibility case "a": case "i": case "A": case "I": list($x, $y) = $frame->get_position(); $pad = null; if ($bullet_style === "decimal-leading-zero") { $pad = strlen($frame->get_parent()->get_parent()->get_node()->getAttribute("dompdf-children-count")); } $index = $frame->get_node()->getAttribute("dompdf-counter"); $text = $this->make_counter($index, $bullet_style, $pad); $font_family = $style->font_family; $spacing = 0; //$frame->get_text_spacing() + $style->word_spacing; if (trim($text) == "") { return; } $x -= Font_Metrics::get_text_width($text, $font_family, $font_size, $spacing); $this->_canvas->text($x, $y, $text, $font_family, $font_size, $style->color, $spacing); case "none": break; } } }
/** * @param Text_Frame_Decorator $frame */ function render(Frame $frame) { $text = $frame->get_text(); if (trim($text) === "") { return; } $style = $frame->get_style(); list($x, $y) = $frame->get_position(); $cb = $frame->get_containing_block(); if (($ml = $style->margin_left) === "auto" || $ml === "none") { $ml = 0; } if (($pl = $style->padding_left) === "auto" || $pl === "none") { $pl = 0; } if (($bl = $style->border_left_width) === "auto" || $bl === "none") { $bl = 0; } $x += $style->length_in_pt(array($ml, $pl, $bl), $cb["w"]); $font = $style->font_family; $size = $frame_font_size = $style->font_size; $height = $style->height; $word_spacing = $frame->get_text_spacing() + $style->length_in_pt($style->word_spacing); $char_spacing = $style->length_in_pt($style->letter_spacing); $width = $style->width; /*$text = str_replace( array("{PAGE_NUM}"), array($this->_canvas->get_page_number()), $text );*/ $this->_canvas->text($x, $y, $text, $font, $size, $style->color, $word_spacing, $char_spacing); $line = $frame->get_containing_line(); // FIXME Instead of using the tallest frame to position, // the decoration, the text should be well placed if (false && $line->tallest_frame) { $base_frame = $line->tallest_frame; $style = $base_frame->get_style(); $size = $style->font_size; $height = $line->h * ($size / $style->line_height); } $line_thickness = $size * self::DECO_THICKNESS; $underline_offset = $size * self::UNDERLINE_OFFSET; $overline_offset = $size * self::OVERLINE_OFFSET; $linethrough_offset = $size * self::LINETHROUGH_OFFSET; $underline_position = -0.08; if ($this->_canvas instanceof CPDF_Adapter) { $cpdf_font = $this->_canvas->get_cpdf()->fonts[$style->font_family]; if (isset($cpdf_font["UnderlinePosition"])) { $underline_position = $cpdf_font["UnderlinePosition"] / 1000; } if (isset($cpdf_font["UnderlineThickness"])) { $line_thickness = $size * ($cpdf_font["UnderlineThickness"] / 1000); } } $descent = $size * $underline_position; $base = $size; // Handle text decoration: // http://www.w3.org/TR/CSS21/text.html#propdef-text-decoration // Draw all applicable text-decorations. Start with the root and work our way down. $p = $frame; $stack = array(); while ($p = $p->get_parent()) { $stack[] = $p; } while (isset($stack[0])) { $f = array_pop($stack); if (($text_deco = $f->get_style()->text_decoration) === "none") { continue; } $deco_y = $y; //$line->y; $color = $f->get_style()->color; switch ($text_deco) { default: continue; case "underline": $deco_y += $base - $descent + $underline_offset + $line_thickness / 2; break; case "overline": $deco_y += $overline_offset + $line_thickness / 2; break; case "line-through": $deco_y += $base * 0.7 + $linethrough_offset; break; } $dx = 0; $x1 = $x - self::DECO_EXTENSION; $x2 = $x + $width + $dx + self::DECO_EXTENSION; $this->_canvas->line($x1, $deco_y, $x2, $deco_y, $color, $line_thickness); } if (DEBUG_LAYOUT && DEBUG_LAYOUT_LINES) { $text_width = Font_Metrics::get_text_width($text, $font, $frame_font_size); $this->_debug_layout(array($x, $y, $text_width + ($line->wc - 1) * $word_spacing, $frame_font_size), "orange", array(0.5, 0.5)); } }
/** * 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 render(Frame $frame) { $style = $frame->get_style(); list($x, $y) = $frame->get_position(); $cb = $frame->get_containing_block(); if (($ml = $style->margin_left) === "auto" || $ml === "none") { $ml = 0; } if (($pl = $style->padding_left) === "auto" || $pl === "none") { $pl = 0; } if (($bl = $style->border_left_width) === "auto" || $bl === "none") { $bl = 0; } $x += $style->length_in_pt(array($ml, $pl, $bl), $cb["w"]); $text = $frame->get_text(); $font = $style->font_family; $size = $style->font_size; $height = $style->height; $spacing = $frame->get_text_spacing() + $style->word_spacing; // if ( preg_replace("/[\s]+/", "", $text) == "" ) // return; $this->_canvas->text($x, $y, $text, $font, $size, $style->color, $spacing); if (method_exists($this->_canvas, "get_cpdf")) { $base = $this->_canvas->get_cpdf()->fonts[$this->_canvas->get_cpdf()->currentFont]['FontBBox'][3] * $size / 1000; $descent = $this->_canvas->get_cpdf()->fonts[$this->_canvas->get_cpdf()->currentFont]['FontBBox'][1] * $size / 1000; //print '<pre>Text_Renderer cpdf:'.$base.' '.$descent.' '.$size.'</pre>'; } else { //Descent is font part below baseline, typically negative. $height is about full height of font box. //$descent = -$size/6; is less accurate, depends on font family. $base = $size; $descent = $size - $height; //print '<pre>Text_Renderer other than cpdf:'.$base.' '.$descent.' '.$size.'</pre>'; } // Handle text decoration: // http://www.w3.org/TR/CSS21/text.html#propdef-text-decoration // Draw all applicable text-decorations. Start with the root and work // our way down. $p = $frame; $stack = array(); while ($p = $p->get_parent()) { $stack[] = $p; } while (count($stack) > 0) { $f = array_pop($stack); $deco_y = $y; if (($text_deco = $f->get_style()->text_decoration) === "none") { continue; } $color = $f->get_style()->color; switch ($text_deco) { default: continue; case "underline": $deco_y += $base - $descent + $size * (self::UNDERLINE_OFFSET - self::DECO_THICKNESS / 2); break; case "overline": $deco_y += $size * (self::OVERLINE_OFFSET + self::DECO_THICKNESS / 2); break; case "line-through": $deco_y += $base * 0.7 + $size * self::LINETHROUGH_OFFSET; break; } $dx = 0; $x1 = $x - self::DECO_EXTENSION; $x2 = $x + $style->width + $dx + self::DECO_EXTENSION; $this->_canvas->line($x1, $deco_y, $x2, $deco_y, $color, $size * self::DECO_THICKNESS); } }
function render(Frame $frame) { $style = $frame->get_style(); $font_size = $style->get_font_size(); $line_height = $style->length_in_pt($style->line_height, $frame->get_containing_block("w")); $this->_set_opacity( $frame->get_opacity( $style->opacity ) ); $li = $frame->get_parent(); // Don't render bullets twice if if was split if ($li->_splitted) { return; } // Handle list-style-image // If list style image is requested but missing, fall back to predefined types if ( $style->list_style_image !== "none" && !Image_Cache::is_broken($img = $frame->get_image_url())) { list($x,$y) = $frame->get_position(); //For expected size and aspect, instead of box size, use image natural size scaled to DPI. // Resample the bullet image to be consistent with 'auto' sized images // See also Image_Frame_Reflower::get_min_max_width // Tested php ver: value measured in px, suffix "px" not in value: rtrim unnecessary. //$w = $frame->get_width(); //$h = $frame->get_height(); list($width, $height) = dompdf_getimagesize($img); $dpi = $this->_dompdf->get_option("dpi"); $w = ((float)rtrim($width, "px") * 72) / $dpi; $h = ((float)rtrim($height, "px") * 72) / $dpi; $x -= $w; $y -= ($line_height - $font_size)/2; //Reverse hinting of list_bullet_positioner $this->_canvas->image( $img, $x, $y, $w, $h); } else { $bullet_style = $style->list_style_type; $fill = false; switch ($bullet_style) { default: case "disc": $fill = true; case "circle": list($x,$y) = $frame->get_position(); $r = ($font_size*(List_Bullet_Frame_Decorator::BULLET_SIZE /*-List_Bullet_Frame_Decorator::BULLET_THICKNESS*/ ))/2; $x -= $font_size*(List_Bullet_Frame_Decorator::BULLET_SIZE/2); $y += ($font_size*(1-List_Bullet_Frame_Decorator::BULLET_DESCENT))/2; $o = $font_size*List_Bullet_Frame_Decorator::BULLET_THICKNESS; $this->_canvas->circle($x, $y, $r, $style->color, $o, null, $fill); break; case "square": list($x, $y) = $frame->get_position(); $w = $font_size*List_Bullet_Frame_Decorator::BULLET_SIZE; $x -= $w; $y += ($font_size*(1-List_Bullet_Frame_Decorator::BULLET_DESCENT-List_Bullet_Frame_Decorator::BULLET_SIZE))/2; $this->_canvas->filled_rectangle($x, $y, $w, $w, $style->color); break; case "decimal-leading-zero": case "decimal": case "lower-alpha": case "lower-latin": case "lower-roman": case "lower-greek": case "upper-alpha": case "upper-latin": case "upper-roman": case "1": // HTML 4.0 compatibility case "a": case "i": case "A": case "I": $pad = null; if ( $bullet_style === "decimal-leading-zero" ) { $pad = strlen($li->get_parent()->get_node()->getAttribute("dompdf-children-count")); } $node = $frame->get_node(); if ( !$node->hasAttribute("dompdf-counter") ) { return; } $index = $node->getAttribute("dompdf-counter"); $text = $this->make_counter($index, $bullet_style, $pad); if ( trim($text) == "" ) { return; } $spacing = 0; $font_family = $style->font_family; $line = $li->get_containing_line(); list($x, $y) = array($frame->get_position("x"), $line->y); $x -= Font_Metrics::get_text_width($text, $font_family, $font_size, $spacing); // Take line-height into account $line_height = $style->line_height; $y += ($line_height - $font_size) / 4; // FIXME I thought it should be 2, but 4 gives better results $this->_canvas->text($x, $y, $text, $font_family, $font_size, $style->color, $spacing); case "none": break; } } }
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; }
function render(Frame $frame) { $style = $frame->get_style(); $font_size = $style->get_font_size(); $line_height = $style->length_in_pt($style->line_height, $frame->get_containing_block("w")); $this->_set_opacity($frame->get_opacity($style->opacity)); if ($style->list_style_image !== "none" && !Image_Cache::is_broken($img = $frame->get_image_url())) { list($x, $y) = $frame->get_position(); list($width, $height) = dompdf_getimagesize($img); $w = (double) rtrim($width, "px") * 72 / DOMPDF_DPI; $h = (double) rtrim($height, "px") * 72 / DOMPDF_DPI; $x -= $w; $y -= ($line_height - $font_size) / 2; $this->_canvas->image($img, $x, $y, $w, $h); } else { $bullet_style = $style->list_style_type; $fill = false; switch ($bullet_style) { default: case "disc": $fill = true; case "circle": list($x, $y) = $frame->get_position(); $r = $font_size * List_Bullet_Frame_Decorator::BULLET_SIZE / 2; $x -= $font_size * (List_Bullet_Frame_Decorator::BULLET_SIZE / 2); $y += $font_size * (1 - List_Bullet_Frame_Decorator::BULLET_DESCENT) / 2; $o = $font_size * List_Bullet_Frame_Decorator::BULLET_THICKNESS; $this->_canvas->circle($x, $y, $r, $style->color, $o, null, $fill); break; case "square": list($x, $y) = $frame->get_position(); $w = $font_size * List_Bullet_Frame_Decorator::BULLET_SIZE; $x -= $w; $y += $font_size * (1 - List_Bullet_Frame_Decorator::BULLET_DESCENT - List_Bullet_Frame_Decorator::BULLET_SIZE) / 2; $this->_canvas->filled_rectangle($x, $y, $w, $w, $style->color); break; case "decimal-leading-zero": case "decimal": case "lower-alpha": case "lower-latin": case "lower-roman": case "lower-greek": case "upper-alpha": case "upper-latin": case "upper-roman": case "1": case "a": case "i": case "A": case "I": $li = $frame->get_parent(); $pad = null; if ($bullet_style === "decimal-leading-zero") { $pad = strlen($li->get_parent()->get_node()->getAttribute("dompdf-children-count")); } $index = $frame->get_node()->getAttribute("dompdf-counter"); $text = $this->make_counter($index, $bullet_style, $pad); if (trim($text) == "") { return; } $spacing = 0; $font_family = $style->font_family; $line = $li->get_containing_line(); list($x, $y) = array($frame->get_position("x"), $line->y); $x -= Font_Metrics::get_text_width($text, $font_family, $font_size, $spacing); $line_height = $style->line_height; $y += ($line_height - $font_size) / 4; $this->_canvas->text($x, $y, $text, $font_family, $font_size, $style->color, $spacing); case "none": break; } } }
function render(Frame $frame) { $text = $frame->get_text(); if (trim($text) === "") { return; } $style = $frame->get_style(); list($x, $y) = $frame->get_position(); $cb = $frame->get_containing_block(); if (($ml = $style->margin_left) === "auto" || $ml === "none") { $ml = 0; } if (($pl = $style->padding_left) === "auto" || $pl === "none") { $pl = 0; } if (($bl = $style->border_left_width) === "auto" || $bl === "none") { $bl = 0; } $x += $style->length_in_pt(array($ml, $pl, $bl), $cb["w"]); $font = $style->font_family; $size = $frame_font_size = $style->font_size; $height = $style->height; $word_spacing = $frame->get_text_spacing() + $style->length_in_pt($style->word_spacing); $char_spacing = $style->length_in_pt($style->letter_spacing); $width = $style->width; $this->_canvas->text($x, $y, $text, $font, $size, $style->color, $word_spacing, $char_spacing); $line = $frame->get_containing_line(); if (false && $line->tallest_frame) { $base_frame = $line->tallest_frame; $style = $base_frame->get_style(); $size = $style->font_size; $height = $line->h * ($size / $style->line_height); } if (method_exists($this->_canvas, "get_cpdf")) { $cpdf = $this->_canvas->get_cpdf(); $fontBBox = $cpdf->fonts[$style->font_family]['FontBBox']; $base = $fontBBox[3] * $size / 1000 * 0.9; $descent = $fontBBox[1] * $size / 1000; } else { $base = $size * 1.08; $descent = $size - $height; } $p = $frame; $stack = array(); while ($p = $p->get_parent()) { $stack[] = $p; } while (isset($stack[0])) { $f = array_pop($stack); if (($text_deco = $f->get_style()->text_decoration) === "none") { continue; } $deco_y = $y; $color = $f->get_style()->color; switch ($text_deco) { default: continue; case "underline": $deco_y += $base - $descent + $size * (self::UNDERLINE_OFFSET - self::DECO_THICKNESS / 2); break; case "overline": $deco_y += $size * (self::OVERLINE_OFFSET + self::DECO_THICKNESS / 2); break; case "line-through": $deco_y += $base * 0.7 + $size * self::LINETHROUGH_OFFSET; break; } $dx = 0; $x1 = $x - self::DECO_EXTENSION; $x2 = $x + $width + $dx + self::DECO_EXTENSION; $this->_canvas->line($x1, $deco_y, $x2, $deco_y, $color, $size * self::DECO_THICKNESS); } if (DEBUG_LAYOUT && DEBUG_LAYOUT_LINES) { $text_width = Font_Metrics::get_text_width($text, $font, $frame_font_size); $this->_debug_layout(array($x, $y, $text_width + ($line->wc - 1) * $word_spacing, $frame_font_size), "orange", array(0.5, 0.5)); } }