Render frames recursively

@param Frame $frame the frame to render
546336
public function render(Frame $frame)
    {
        global $_dompdf_debug;

        $this->_check_callbacks("begin_frame", $frame);

        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 + (float)$style->length_in_pt($origin[0], (float)$style->length_in_pt($style->width));
                $values[] = $y + (float)$style->length_in_pt($origin[1], (float)$style->length_in_pt($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, (float)$w, (float)$h, $tl, $tr, $br, $bl);
            } else {
                $this->_canvas->clipping_rectangle($x, $y, (float)$w, (float)$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);
    }
608364
public function render()
    {
        if (empty($this->_rows) || empty($this->_columns)) {
            return;
        }

        $stream = $this->getRtf()->getWriter();
        $stream->write('\pard');

        foreach ($this->_rows as $row) {
            $this->renderRowDefinition($row);
            $stream->write("\r\n");
            $this->renderRowCells($row);
            $stream->write("\r\n" . '\row' . "\r\n");
        }

        $stream->write('\pard\itap0' . "\r\n");
    }
502094
function reset()
    {
        $this->_frame->reset();

        $this->_counters = array();

        $this->_cached_parent = null; //clear get_parent() cache

        // Reset all children
        foreach ($this->get_children() as $child) {
            $child->reset();
        }
    }
726635
def _render_frame(self):
        
        frame = self.frame()
        output = '\r{0}'.format(frame)
        self.clear()
        try:
            self._stream.write(output)
        except UnicodeEncodeError:
            self._stream.write(encode_utf_8_text(output))
542611
protected function frame($text)
    {
        $line   = '+'.str_repeat('-', strlen($text) + 4).'+';
        $this->info($line);
        $this->info("|  $text  |");
        $this->info($line);
    }
495240
protected function _validateFrame($frame) {
    if(!is_array($frame) || count($frame) !== 1 || !is_object($frame[0])) {
      throw new JsonLdException(
        'Invalid JSON-LD syntax; a JSON-LD frame must be a single object.',
        'jsonld.SyntaxError', null, array('frame' => $frame));
    }
  }
1289160
public void processFrame(Frame frame) {
        synchronized (frameListeners) {
            Iterator<FrameListener> it = frameListeners.iterator();
            while (it.hasNext()) {
                FrameListener listener = it.next();
                listener.processFrame(frame);
            }
        }
    }
666145
public static function binarize($frame)
    {
        $len = count($frame);
        foreach ($frame as &$frameLine) {

            for($i=0; $i<$len; $i++) {
                $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0';
            }
        }

        return $frame;
    }
226955
public function addFrame($frameName, IdFrame $frame)
    {
        $this->loadFrames();

        $this->frames[$frameName] = $frame;
        return $this;
    }
205678
function dispose($recursive = false) {
    
    if ( $recursive ) {
      while ( $child = $this->get_first_child() )
        $child->dispose(true);
    }
    
    $this->_root = null;
    unset($this->_root);
    
    $this->_frame->dispose(true);
    $this->_frame = null;
    unset($this->_frame);
    
    $this->_positioner = null;
    unset($this->_positioner);
    
    $this->_reflower = null;
    unset($this->_reflower);
  }
12507
function get_spanned_cells($frame) {
    $key = $frame->get_id();

    if ( !isset($this->_frames[$key]) ) {
      throw new DOMPDF_Exception("Frame not found in cellmap");
    }

    return $this->_frames[$key];

  }
396062
public function sendFrame($frame)
    {
        $this->outputFrame("<script>\np(" . htmlspecialchars(json_encode($frame, JSON_UNESCAPED_SLASHES),
                ENT_NOQUOTES | ENT_HTML401) . ");\n</script>\r\n");
        parent::sendFrame($frame);
    }
235553
static function decorate_root(Frame $root, Dompdf $dompdf)
    {
        $frame = new PageFrameDecorator($root, $dompdf);
        $frame->set_reflower(new PageFrameReflower($frame));
        $root->set_decorator($frame);

        return $frame;
    }
792422
function render(Frame $frame) {
    $style = $frame->get_style();

    if ( !$frame->get_first_child() )
      return; // No children, no service
    
    // Draw the left border if applicable
    $bp = $style->get_border_properties();
    $widths = array($style->length_in_pt($bp["top"]["width"]),
                    $style->length_in_pt($bp["right"]["width"]),
                    $style->length_in_pt($bp["bottom"]["width"]),
                    $style->length_in_pt($bp["left"]["width"]));

    // Draw the background & border behind each child.  To do this we need
    // to figure out just how much space each child takes:
    list($x, $y) = $frame->get_first_child()->get_position();
    $w = null;
    $h = 0;
//     $x += $widths[3];
//     $y += $widths[0];
    
    $this->_set_opacity( $frame->get_opacity( $style->opacity ) );
    
    $first_row = true;

    foreach ($frame->get_children() as $child) {
      list($child_x, $child_y, $child_w, $child_h) = $child->get_padding_box();
      
      if ( !is_null($w) && $child_x < $x + $w ) {
        //This branch seems to be supposed to being called on the first part
        //of an inline html element, and the part after the if clause for the
        //parts after a line break.
        //But because $w initially mostly is 0, and gets updated only on the next
        //round, this seem to be never executed and the common close always.

        // The next child is on another line.  Draw the background &
        // borders on this line.

        // Background:
        if ( ($bg = $style->background_color) !== "transparent" )
          $this->_canvas->filled_rectangle( $x, $y, $w, $h, $bg);

        if ( ($url = $style->background_image) && $url !== "none" ) {
          $this->_background_image($url, $x, $y, $w, $h, $style);
        }

        // If this is the first row, draw the left border
        if ( $first_row ) {

          if ( $bp["left"]["style"] !== "none" && $bp["left"]["color"] !== "transparent" && $bp["left"]["width"] > 0 ) {
            $method = "_border_" . $bp["left"]["style"];            
            $this->$method($x, $y, $h + $widths[0] + $widths[2], $bp["left"]["color"], $widths, "left");
          }
          $first_row = false;
        }

        // Draw the top & bottom borders
        if ( $bp["top"]["style"] !== "none" && $bp["top"]["color"] !== "transparent" && $bp["top"]["width"] > 0 ) {
          $method = "_border_" . $bp["top"]["style"];
          $this->$method($x, $y, $w + $widths[1] + $widths[3], $bp["top"]["color"], $widths, "top");
        }
        
        if ( $bp["bottom"]["style"] !== "none" && $bp["bottom"]["color"] !== "transparent" && $bp["bottom"]["width"] > 0 ) {
          $method = "_border_" . $bp["bottom"]["style"];
          $this->$method($x, $y + $h + $widths[0] + $widths[2], $w + $widths[1] + $widths[3], $bp["bottom"]["color"], $widths, "bottom");
        }

        // Handle anchors & links
        $link_node = null;
        if ( $frame->get_node()->nodeName === "a" ) {
          $link_node = $frame->get_node();
        }
        else if ( $frame->get_parent()->get_node()->nodeName === "a" ){
          $link_node = $frame->get_parent()->get_node();
        }
        
        if ( $link_node && $href = $link_node->getAttribute("href") ) {
          $this->_canvas->add_link($href, $x, $y, $w, $h);
        }

        $x = $child_x;
        $y = $child_y;
        $w = $child_w;
        $h = $child_h;
        continue;
      }

      if ( is_null($w) )
        $w = $child_w;
      else
        $w += $child_w;
      
      $h = max($h, $child_h);
    }

    
    // Handle the last child
    if ( ($bg = $style->background_color) !== "transparent" ) 
      $this->_canvas->filled_rectangle( $x + $widths[3], $y + $widths[0], $w, $h, $bg);

    //On continuation lines (after line break) of inline elements, the style got copied.
    //But a non repeatable background image should not be repeated on the next line.
    //But removing the background image above has never an effect, and removing it below
    //removes it always, even on the initial line.
    //Need to handle it elsewhere, e.g. on certain ...clone()... usages.    
    // Repeat not given: default is Style::__construct
    // ... && (!($repeat = $style->background_repeat) || $repeat === "repeat" ...
    //different position? $this->_background_image($url, $x, $y, $w, $h, $style);
    if ( ($url = $style->background_image) && $url !== "none" )           
      $this->_background_image($url, $x + $widths[3], $y + $widths[0], $w, $h, $style);
        
    // Add the border widths
    $w += $widths[1] + $widths[3];
    $h += $widths[0] + $widths[2];

    // make sure the border and background start inside the left margin
    $left_margin = $style->length_in_pt($style->margin_left);
    $x += $left_margin;

    // If this is the first row, draw the left border too
    if ( $first_row && $bp["left"]["style"] !== "none" && $bp["left"]["color"] !== "transparent" && $widths[3] > 0 ) {
      $method = "_border_" . $bp["left"]["style"];
      $this->$method($x, $y, $h, $bp["left"]["color"], $widths, "left");
    }
    
    // Draw the top & bottom borders
    if ( $bp["top"]["style"] !== "none" && $bp["top"]["color"] !== "transparent" && $widths[0] > 0 ) {
      $method = "_border_" . $bp["top"]["style"];
      $this->$method($x, $y, $w, $bp["top"]["color"], $widths, "top");
    }
    
    if ( $bp["bottom"]["style"] !== "none" && $bp["bottom"]["color"] !== "transparent" && $widths[2] > 0 ) {
      $method = "_border_" . $bp["bottom"]["style"];
      $this->$method($x, $y + $h, $w, $bp["bottom"]["color"], $widths, "bottom");
    }

    //    pre_var_dump(get_class($frame->get_next_sibling()));
    //    $last_row = get_class($frame->get_next_sibling()) !== 'Inline_Frame_Decorator';
    // Draw the right border if this is the last row
    if ( $bp["right"]["style"] !== "none" && $bp["right"]["color"] !== "transparent" && $widths[1] > 0 ) {
      $method = "_border_" . $bp["right"]["style"];
      $this->$method($x + $w, $y, $h, $bp["right"]["color"], $widths, "right");
    }

    // Only two levels of links frames
    $link_node = null;
    if ( $frame->get_node()->nodeName === "a" ) {
      $link_node = $frame->get_node();
      
      if ( ($name = $link_node->getAttribute("name")) || ($name = $link_node->getAttribute("id")) ) {
        $this->_canvas->add_named_dest($name);
      }
    }
    
    if ( $frame->get_parent() && $frame->get_parent()->get_node()->nodeName === "a" ){
      $link_node = $frame->get_parent()->get_node();
    }
    
    // Handle anchors & links
    if ( $link_node ) {
      if ( $href = $link_node->getAttribute("href") )
        $this->_canvas->add_link($href, $x, $y, $w, $h);
    }
    
    if (DEBUG_LAYOUT && DEBUG_LAYOUT_INLINE) {
      $this->_debug_layout($child->get_border_box(), "blue");
      if (DEBUG_LAYOUT_PADDINGBOX) {
        $this->_debug_layout($child->get_padding_box(), "blue", array(0.5, 0.5));
      }
    }
  }
1036140
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;
    
  }
291543
function renderHeader(&$header)
    {
        $this->_ary['sections'][$this->_sectionCount] = array(
            'header' => $header->toHtml(),
            'name'   => $header->getName()
        );
        $this->_currentSection = $this->_sectionCount++;
    }
1150680
protected function _render_frame($type, $frame)
    {

        if (!isset($this->_renderers[$type])) {

            switch ($type) {
                case "block":
                    $this->_renderers[$type] = new Block($this->_dompdf);
                    break;

                case "inline":
                    $this->_renderers[$type] = new Renderer\Inline($this->_dompdf);
                    break;

                case "text":
                    $this->_renderers[$type] = new Text($this->_dompdf);
                    break;

                case "image":
                    $this->_renderers[$type] = new Image($this->_dompdf);
                    break;

                case "table-cell":
                    $this->_renderers[$type] = new TableCell($this->_dompdf);
                    break;

                case "table-row-group":
                    $this->_renderers[$type] = new TableRowGroup($this->_dompdf);
                    break;

                case "list-bullet":
                    $this->_renderers[$type] = new ListBullet($this->_dompdf);
                    break;

                case "php":
                    $this->_renderers[$type] = new PhpEvaluator($this->_canvas);
                    break;

                case "javascript":
                    $this->_renderers[$type] = new JavascriptEmbedder($this->_dompdf);
                    break;

            }
        }

        $this->_renderers[$type]->render($frame);
    }