| 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);  }}
 |