function position(AbstractFrameDecorator $frame) { $style = $frame->get_style(); $cb = $frame->get_containing_block(); $p = $frame->find_block_parent(); if ($p) { $float = $style->float; if (!$float || $float === "none") { $p->add_line(true); } $y = $p->get_current_line_box()->y; } else { $y = $cb["y"]; } $x = $cb["x"]; // Relative positionning if ($style->position === "relative") { $top = $style->length_in_pt($style->top, $cb["h"]); //$right = $style->length_in_pt($style->right, $cb["w"]); //$bottom = $style->length_in_pt($style->bottom, $cb["h"]); $left = $style->length_in_pt($style->left, $cb["w"]); $x += $left; $y += $top; } $frame->set_position($x, $y); }
function move(AbstractFrameDecorator $frame, $offset_x, $offset_y, $ignore_self = false) { list($x, $y) = $frame->get_position(); if (!$ignore_self) { $frame->set_position($x + $offset_x, $y + $offset_y); } foreach ($frame->get_children() as $child) { $child->move($offset_x, $offset_y); } }
function move($offset_x, $offset_y, $ignore_self = false) { list($x, $y) = $this->_frame->get_position(); if (!$ignore_self) { $this->_frame->set_position($x + $offset_x, $y + $offset_y); } foreach ($this->_frame->get_children() as $child) { $child->move($offset_x, $offset_y); } }
function position(AbstractFrameDecorator $frame) { $cb = $frame->get_containing_block(); $p = $frame->get_prev_sibling(); if ($p) { $y = $p->get_position("y") + $p->get_margin_height(); } else { $y = $cb["y"]; } $frame->set_position($cb["x"], $y); }
function position(AbstractFrameDecorator $frame) { $style = $frame->get_original_style(); $root = $frame->get_root(); $initialcb = $root->get_containing_block(); $initialcb_style = $root->get_style(); $p = $frame->find_block_parent(); if ($p) { $p->add_line(); } // Compute the margins of the @page style $margin_top = $initialcb_style->length_in_pt($initialcb_style->margin_top, $initialcb["h"]); $margin_right = $initialcb_style->length_in_pt($initialcb_style->margin_right, $initialcb["w"]); $margin_bottom = $initialcb_style->length_in_pt($initialcb_style->margin_bottom, $initialcb["h"]); $margin_left = $initialcb_style->length_in_pt($initialcb_style->margin_left, $initialcb["w"]); // The needed computed style of the element $height = $style->length_in_pt($style->height, $initialcb["h"]); $width = $style->length_in_pt($style->width, $initialcb["w"]); $top = $style->length_in_pt($style->top, $initialcb["h"]); $right = $style->length_in_pt($style->right, $initialcb["w"]); $bottom = $style->length_in_pt($style->bottom, $initialcb["h"]); $left = $style->length_in_pt($style->left, $initialcb["w"]); $y = $margin_top; if (isset($top)) { $y = $top + $margin_top; if ($top === "auto") { $y = $margin_top; if (isset($bottom) && $bottom !== "auto") { $y = $initialcb["h"] - $bottom - $margin_bottom; $margin_height = $frame->get_margin_height(); if ($margin_height !== "auto") { $y -= $margin_height; } else { $y -= $height; } } } } $x = $margin_left; if (isset($left)) { $x = $left + $margin_left; if ($left === "auto") { $x = $margin_left; if (isset($right) && $right !== "auto") { $x = $initialcb["w"] - $right - $margin_right; $margin_width = $frame->get_margin_width(); if ($margin_width !== "auto") { $x -= $margin_width; } else { $x -= $width; } } } } $frame->set_position($x, $y); $children = $frame->get_children(); foreach ($children as $child) { $child->set_position($x, $y); } }
/** * Class constructor * * @param Frame $frame the bullet frame to decorate * @param Dompdf $dompdf the document's dompdf object */ function __construct(Frame $frame, Dompdf $dompdf) { $style = $frame->get_style(); $url = $style->list_style_image; $frame->get_node()->setAttribute("src", $url); $this->_img = new Image($frame, $dompdf); parent::__construct($this->_img, $dompdf); list($width, $height) = Helpers::dompdf_getimagesize($this->_img->get_image_url()); // Resample the bullet image to be consistent with 'auto' sized images // See also Image::get_min_max_width // Tested php ver: value measured in px, suffix "px" not in value: rtrim unnecessary. $dpi = $this->_dompdf->get_option("dpi"); $this->_width = (double) rtrim($width, "px") * 72 / $dpi; $this->_height = (double) rtrim($height, "px") * 72 / $dpi; //If an image is taller as the containing block/box, the box should be extended. //Neighbour elements are overwriting the overlapping image areas. //Todo: Where can the box size be extended? //Code below has no effect. //See block_frame_reflower _calculate_restricted_height //See generated_frame_reflower, Dompdf:render() "list-item", "-dompdf-list-bullet"S. //Leave for now //if ($style->min_height < $this->_height ) { // $style->min_height = $this->_height; //} //$style->height = "auto"; }
function __construct(Frame $frame, Dompdf $dompdf) { parent::__construct($frame, $dompdf); $style = $this->_frame->get_style(); $style->width = 0; $style->height = 0; $style->margin = 0; $style->padding = 0; }
/** * Class constructor * * @param Frame $frame the frame to decorate * @param DOMPDF $dompdf the document's dompdf object (required to resolve relative & remote urls) */ function __construct(Frame $frame, Dompdf $dompdf) { parent::__construct($frame, $dompdf); $url = $frame->get_node()->getAttribute("src"); $debug_png = $dompdf->get_option("debug_png"); if ($debug_png) { print '[__construct ' . $url . ']'; } list($this->_image_url, , $this->_image_msg) = Cache::resolve_url($url, $dompdf->get_protocol(), $dompdf->get_host(), $dompdf->get_base_path(), $dompdf); if (Cache::is_broken($this->_image_url) && ($alt = $frame->get_node()->getAttribute("alt"))) { $style = $frame->get_style(); $style->width = 4 / 3 * $dompdf->getFontMetrics()->getTextWidth($alt, $style->font_family, $style->font_size, $style->word_spacing); $style->height = $dompdf->getFontMetrics()->getFontHeight($style->font_family, $style->font_size); } }
function position(AbstractFrameDecorator $frame) { /** * Find our nearest block level parent and access its lines property. * @var BlockFrameDecorator */ $p = $frame->find_block_parent(); // Debugging code: // Helpers::pre_r("\nPositioning:"); // Helpers::pre_r("Me: " . $frame->get_node()->nodeName . " (" . spl_object_hash($frame->get_node()) . ")"); // Helpers::pre_r("Parent: " . $p->get_node()->nodeName . " (" . spl_object_hash($p->get_node()) . ")"); // End debugging if (!$p) { throw new Exception("No block-level parent found. Not good."); } $f = $frame; $cb = $f->get_containing_block(); $line = $p->get_current_line_box(); // Skip the page break if in a fixed position element $is_fixed = false; while ($f = $f->get_parent()) { if ($f->get_style()->position === "fixed") { $is_fixed = true; break; } } $f = $frame; if (!$is_fixed && $f->get_parent() && $f->get_parent() instanceof InlineFrameDecorator && $f->is_text_node()) { $min_max = $f->get_reflower()->get_min_max_width(); // If the frame doesn't fit in the current line, a line break occurs if ($min_max["min"] > $cb["w"] - $line->left - $line->w - $line->right) { $p->add_line(); } } $f->set_position($cb["x"] + $line->w, $line->y); }
function position(AbstractFrameDecorator $frame) { // Bullets & friends are positioned an absolute distance to the left of // the content edge of their parent element $cb = $frame->get_containing_block(); // Note: this differs from most frames in that we must position // ourselves after determining our width $x = $cb["x"] - $frame->get_width(); $p = $frame->find_block_parent(); $y = $p->get_current_line_box()->y; // This is a bit of a hack... $n = $frame->get_next_sibling(); if ($n) { $style = $n->get_style(); $line_height = $style->length_in_pt($style->line_height, $style->get_font_size()); $offset = $style->length_in_pt($line_height, $n->get_containing_block("h")) - $frame->get_height(); $y += $offset / 2; } // Now the position is the left top of the block which should be marked with the bullet. // We tried to find out the y of the start of the first text character within the block. // But the top margin/padding does not fit, neither from this nor from the next sibling // The "bit of a hack" above does not work also. // Instead let's position the bullet vertically centered to the block which should be marked. // But for get_next_sibling() the get_containing_block is all zero, and for find_block_parent() // the get_containing_block is paper width and the entire list as height. // if ($p) { // //$cb = $n->get_containing_block(); // $cb = $p->get_containing_block(); // $y += $cb["h"]/2; // print 'cb:'.$cb["x"].':'.$cb["y"].':'.$cb["w"].':'.$cb["h"].':'; // } // Todo: // For now give up on the above. Use Guesswork with font y-pos in the middle of the line spacing /*$style = $p->get_style(); $font_size = $style->get_font_size(); $line_height = $style->length_in_pt($style->line_height, $font_size); $y += ($line_height - $font_size) / 2; */ //Position is x-end y-top of character position of the bullet. $frame->set_position($x, $y); }
/** * Override split() to remove all child rows and this element from the cellmap * * @param Frame $child * @param bool $force_pagebreak * * @return void */ function split(Frame $child = null, $force_pagebreak = false) { if (is_null($child)) { parent::split(); return; } // Remove child & all subsequent rows from the cellmap $cellmap = $this->get_parent()->get_cellmap(); $iter = $child; while ($iter) { $cellmap->remove_row($iter); $iter = $iter->get_next_sibling(); } // If we are splitting at the first child remove the // table-row-group from the cellmap as well if ($child === $this->get_first_child()) { $cellmap->remove_row_group($this); parent::split(); return; } $cellmap->update_row_group($this, $child->get_prev_sibling()); parent::split($child); }
/** * Return a copy of this frame with $node as its node * * @param DOMNode $node * * @return Frame */ public function copy(DOMNode $node) { $deco = parent::copy($node); // In order to keep columns' widths through pages $deco->_cellmap->set_columns($this->_cellmap->get_columns()); $deco->_cellmap->lock_columns(); return $deco; }
protected function _render_outline(AbstractFrameDecorator $frame, $border_box = null, $corner_style = "bevel") { $style = $frame->get_style(); $props = array("width" => $style->outline_width, "style" => $style->outline_style, "color" => $style->outline_color); if (!$props["style"] || $props["style"] === "none" || $props["width"] <= 0) { return; } if (empty($border_box)) { $border_box = $frame->get_border_box(); } $offset = $style->length_in_pt($props["width"]); $pattern = $this->_get_dash_pattern($props["style"], $offset); // If the outline style is "solid" we'd better draw a rectangle if (in_array($props["style"], array("solid", "dashed", "dotted"))) { $border_box[0] -= $offset / 2; $border_box[1] -= $offset / 2; $border_box[2] += $offset; $border_box[3] += $offset; list($x, $y, $w, $h) = $border_box; $this->_canvas->rectangle($x, $y, $w, $h, $props["color"], $offset, $pattern); return; } $border_box[0] -= $offset; $border_box[1] -= $offset; $border_box[2] += $offset * 2; $border_box[3] += $offset * 2; $method = "_border_" . $props["style"]; $widths = array_fill(0, 4, $props["width"]); $sides = array("top", "right", "left", "bottom"); $length = 0; foreach ($sides as $side) { list($x, $y, $w, $h) = $border_box; switch ($side) { case "top": $length = $w; break; case "bottom": $length = $w; $y += $h; break; case "left": $length = $h; break; case "right": $length = $h; $x += $w; break; default: break; } $this->{$method}($x, $y, $length, $props["color"], $widths, $side, $corner_style); } }
function __construct(Frame $frame, Dompdf $dompdf) { parent::__construct($frame, $dompdf); }
function reset() { parent::reset(); $this->_text_spacing = null; }
function position(AbstractFrameDecorator $frame) { $style = $frame->get_style(); $p = $frame->find_positionned_parent(); list($x, $y, $w, $h) = $frame->get_containing_block(); $top = $style->length_in_pt($style->top, $h); $right = $style->length_in_pt($style->right, $w); $bottom = $style->length_in_pt($style->bottom, $h); $left = $style->length_in_pt($style->left, $w); if ($p && !($left === "auto" && $right === "auto")) { // Get the parent's padding box (see http://www.w3.org/TR/CSS21/visuren.html#propdef-top) list($x, $y, $w, $h) = $p->get_padding_box(); } list($width, $height) = array($frame->get_margin_width(), $frame->get_margin_height()); $orig_style = $frame->get_original_style(); $orig_width = $orig_style->width; $orig_height = $orig_style->height; /**************************** * * Width auto: * ____________| left=auto | left=fixed | * right=auto | A | B | * right=fixed | C | D | * * Width fixed: * ____________| left=auto | left=fixed | * right=auto | E | F | * right=fixed | G | H | *****************************/ if ($left === "auto") { if ($right === "auto") { // A or E - Keep the frame at the same position $x = $x + $frame->find_block_parent()->get_current_line_box()->w; } else { if ($orig_width === "auto") { // C $x += $w - $width - $right; } else { // G $x += $w - $width - $right; } } } else { if ($right === "auto") { // B or F $x += $left; } else { if ($orig_width === "auto") { // D - TODO change width $x += $left; } else { // H - Everything is fixed: left + width win $x += $left; } } } // The same vertically if ($top === "auto") { if ($bottom === "auto") { // A or E - Keep the frame at the same position $y = $frame->find_block_parent()->get_current_line_box()->y; } else { if ($orig_height === "auto") { // C $y += $h - $height - $bottom; } else { // G $y += $h - $height - $bottom; } } } else { if ($bottom === "auto") { // B or F $y += $top; } else { if ($orig_height === "auto") { // D - TODO change height $y += $top; } else { // H - Everything is fixed: top + height win $y += $top; } } } $frame->set_position($x, $y); }
/** * Set the frame's containing block. Overridden to set $this->_bottom_page_margin. * * @param float $x * @param float $y * @param float $w * @param float $h */ function set_containing_block($x = null, $y = null, $w = null, $h = null) { parent::set_containing_block($x, $y, $w, $h); //$w = $this->get_containing_block("w"); if (isset($h)) { $this->_bottom_page_margin = $h; } // - $this->_frame->get_style()->length_in_pt($this->_frame->get_style()->margin_bottom, $w); }
function reset() { parent::reset(); $this->_line_boxes = array(new LineBox($this)); $this->_cl = 0; }
/** * @return string */ public function __toString() { // Skip empty text frames // if ( $this->is_text_node() && // preg_replace("/\s/", "", $this->_node->data) === "" ) // return ""; $str = "<b>" . $this->_node->nodeName . ":</b><br/>"; //$str .= spl_object_hash($this->_node) . "<br/>"; $str .= "Id: " . $this->get_id() . "<br/>"; $str .= "Class: " . get_class($this) . "<br/>"; if ($this->is_text_node()) { $tmp = htmlspecialchars($this->_node->nodeValue); $str .= "<pre>'" . mb_substr($tmp, 0, 70) . (mb_strlen($tmp) > 70 ? "..." : "") . "'</pre>"; } elseif ($css_class = $this->_node->getAttribute("class")) { $str .= "CSS class: '{$css_class}'<br/>"; } if ($this->_parent) { $str .= "\nParent:" . $this->_parent->_node->nodeName . " (" . spl_object_hash($this->_parent->_node) . ") " . "<br/>"; } if ($this->_prev_sibling) { $str .= "Prev: " . $this->_prev_sibling->_node->nodeName . " (" . spl_object_hash($this->_prev_sibling->_node) . ") " . "<br/>"; } if ($this->_next_sibling) { $str .= "Next: " . $this->_next_sibling->_node->nodeName . " (" . spl_object_hash($this->_next_sibling->_node) . ") " . "<br/>"; } $d = $this->get_decorator(); while ($d && $d != $d->get_decorator()) { $str .= "Decorator: " . get_class($d) . "<br/>"; $d = $d->get_decorator(); } $str .= "Position: " . Helpers::pre_r($this->_position, true); $str .= "\nContaining block: " . Helpers::pre_r($this->_containing_block, true); $str .= "\nMargin width: " . Helpers::pre_r($this->get_margin_width(), true); $str .= "\nMargin height: " . Helpers::pre_r($this->get_margin_height(), true); $str .= "\nStyle: <pre>" . $this->_style->__toString() . "</pre>"; if ($this->_decorator instanceof FrameDecorator\Block) { $str .= "Lines:<pre>"; foreach ($this->_decorator->get_line_boxes() as $line) { foreach ($line->get_frames() as $frame) { if ($frame instanceof FrameDecorator\Text) { $str .= "\ntext: "; $str .= "'" . htmlspecialchars($frame->get_text()) . "'"; } else { $str .= "\nBlock: " . $frame->get_node()->nodeName . " (" . spl_object_hash($frame->get_node()) . ")"; } } $str .= "\ny => " . $line->y . "\n" . "w => " . $line->w . "\n" . "h => " . $line->h . "\n" . "left => " . $line->left . "\n" . "right => " . $line->right . "\n"; } $str .= "</pre>"; } $str .= "\n"; if (php_sapi_name() === "cli") { $str = strip_tags(str_replace(array("<br/>", "<b>", "</b>"), array("\n", "", ""), $str)); } return $str; }