123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- <?php
- /**
- * @package dompdf
- * @link http://dompdf.github.com/
- * @author Benj Carson <benjcarson@digitaljunkies.ca>
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
- /**
- * Concrete renderer
- *
- * Instantiates several specific renderers in order to render any given
- * frame.
- *
- * @access private
- * @package dompdf
- */
- class Renderer extends Abstract_Renderer {
- /**
- * Array of renderers for specific frame types
- *
- * @var Abstract_Renderer[]
- */
- protected $_renderers;
-
- /**
- * Cache of the callbacks array
- *
- * @var array
- */
- private $_callbacks;
-
- /**
- * Class destructor
- */
- function __destruct() {
- clear_object($this);
- }
-
- /**
- * Advance the canvas to the next page
- */
- function new_page() {
- $this->_canvas->new_page();
- }
- /**
- * Render frames recursively
- *
- * @param Frame $frame the frame to render
- */
- function render(Frame $frame) {
- global $_dompdf_debug;
- if ( $_dompdf_debug ) {
- echo $frame;
- flush();
- }
-
- $style = $frame->get_style();
-
- if ( in_array($style->visibility, array("hidden", "collapse")) ) {
- return;
- }
-
- $display = $style->display;
-
- // Starts the CSS transformation
- if ( $style->transform && is_array($style->transform) ) {
- $this->_canvas->save();
- list($x, $y) = $frame->get_padding_box();
- $origin = $style->transform_origin;
-
- foreach($style->transform as $transform) {
- list($function, $values) = $transform;
- if ( $function === "matrix" ) {
- $function = "transform";
- }
-
- $values = array_map("floatval", $values);
- $values[] = $x + $style->length_in_pt($origin[0], $style->width);
- $values[] = $y + $style->length_in_pt($origin[1], $style->height);
-
- call_user_func_array(array($this->_canvas, $function), $values);
- }
- }
-
- switch ($display) {
-
- case "block":
- case "list-item":
- case "inline-block":
- case "table":
- case "inline-table":
- $this->_render_frame("block", $frame);
- break;
- case "inline":
- if ( $frame->is_text_node() )
- $this->_render_frame("text", $frame);
- else
- $this->_render_frame("inline", $frame);
- break;
- case "table-cell":
- $this->_render_frame("table-cell", $frame);
- break;
- case "table-row-group":
- case "table-header-group":
- case "table-footer-group":
- $this->_render_frame("table-row-group", $frame);
- break;
- case "-dompdf-list-bullet":
- $this->_render_frame("list-bullet", $frame);
- break;
- case "-dompdf-image":
- $this->_render_frame("image", $frame);
- break;
-
- case "none":
- $node = $frame->get_node();
-
- if ( $node->nodeName === "script" ) {
- if ( $node->getAttribute("type") === "text/php" ||
- $node->getAttribute("language") === "php" ) {
- // Evaluate embedded php scripts
- $this->_render_frame("php", $frame);
- }
-
- elseif ( $node->getAttribute("type") === "text/javascript" ||
- $node->getAttribute("language") === "javascript" ) {
- // Insert JavaScript
- $this->_render_frame("javascript", $frame);
- }
- }
- // Don't render children, so skip to next iter
- return;
-
- default:
- break;
- }
- // Starts the overflow: hidden box
- if ( $style->overflow === "hidden" ) {
- list($x, $y, $w, $h) = $frame->get_padding_box();
-
- // get border radii
- $style = $frame->get_style();
- list($tl, $tr, $br, $bl) = $style->get_computed_border_radius($w, $h);
-
- if ( $tl + $tr + $br + $bl > 0 ) {
- $this->_canvas->clipping_roundrectangle($x, $y, $w, $h, $tl, $tr, $br, $bl);
- }
- else {
- $this->_canvas->clipping_rectangle($x, $y, $w, $h);
- }
- }
- $stack = array();
-
- foreach ($frame->get_children() as $child) {
- // < 0 : nagative z-index
- // = 0 : no z-index, no stacking context
- // = 1 : stacking context without z-index
- // > 1 : z-index
- $child_style = $child->get_style();
- $child_z_index = $child_style->z_index;
- $z_index = 0;
-
- if ( $child_z_index !== "auto" ) {
- $z_index = intval($child_z_index) + 1;
- }
- elseif ( $child_style->float !== "none" || $child->is_positionned()) {
- $z_index = 1;
- }
-
- $stack[$z_index][] = $child;
- }
-
- ksort($stack);
-
- foreach ($stack as $by_index) {
- foreach($by_index as $child) {
- $this->render($child);
- }
- }
-
- // Ends the overflow: hidden box
- if ( $style->overflow === "hidden" ) {
- $this->_canvas->clipping_end();
- }
- if ( $style->transform && is_array($style->transform) ) {
- $this->_canvas->restore();
- }
- // Check for end frame callback
- $this->_check_callbacks("end_frame", $frame);
- }
-
- /**
- * Check for callbacks that need to be performed when a given event
- * gets triggered on a frame
- *
- * @param string $event the type of event
- * @param Frame $frame the frame that event is triggered on
- */
- protected function _check_callbacks($event, $frame) {
- if (!isset($this->_callbacks)) {
- $this->_callbacks = $this->_dompdf->get_callbacks();
- }
-
- if (is_array($this->_callbacks) && isset($this->_callbacks[$event])) {
- $info = array(0 => $this->_canvas, "canvas" => $this->_canvas,
- 1 => $frame, "frame" => $frame);
- $fs = $this->_callbacks[$event];
- foreach ($fs as $f) {
- if (is_callable($f)) {
- if (is_array($f)) {
- $f[0]->$f[1]($info);
- } else {
- $f($info);
- }
- }
- }
- }
- }
- /**
- * Render a single frame
- *
- * Creates Renderer objects on demand
- *
- * @param string $type type of renderer to use
- * @param Frame $frame the frame to render
- */
- protected function _render_frame($type, $frame) {
- if ( !isset($this->_renderers[$type]) ) {
-
- switch ($type) {
- case "block":
- $this->_renderers[$type] = new Block_Renderer($this->_dompdf);
- break;
- case "inline":
- $this->_renderers[$type] = new Inline_Renderer($this->_dompdf);
- break;
- case "text":
- $this->_renderers[$type] = new Text_Renderer($this->_dompdf);
- break;
- case "image":
- $this->_renderers[$type] = new Image_Renderer($this->_dompdf);
- break;
-
- case "table-cell":
- $this->_renderers[$type] = new Table_Cell_Renderer($this->_dompdf);
- break;
-
- case "table-row-group":
- $this->_renderers[$type] = new Table_Row_Group_Renderer($this->_dompdf);
- break;
- case "list-bullet":
- $this->_renderers[$type] = new List_Bullet_Renderer($this->_dompdf);
- break;
- case "php":
- $this->_renderers[$type] = new PHP_Evaluator($this->_canvas);
- break;
- case "javascript":
- $this->_renderers[$type] = new Javascript_Embedder($this->_dompdf);
- break;
-
- }
- }
-
- $this->_renderers[$type]->render($frame);
- }
- }
|