Example #1
0
 function render(Frame $frame)
 {
     $style = $frame->get_style();
     list($x, $y, $w, $h) = $frame->get_padding_box();
     $this->_set_opacity($frame->get_opacity($style->opacity));
     // Draw our background, border and content
     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);
     }
     $this->_render_border($frame);
     $this->_render_outline($frame);
     if (DEBUG_LAYOUT && DEBUG_LAYOUT_BLOCKS) {
         $this->_debug_layout($frame->get_border_box(), "red");
         if (DEBUG_LAYOUT_PADDINGBOX) {
             $this->_debug_layout($frame->get_padding_box(), "red", array(0.5, 0.5));
         }
     }
     if (DEBUG_LAYOUT && DEBUG_LAYOUT_LINES && $frame->get_decorator()) {
         foreach ($frame->get_decorator()->get_lines() as $line) {
             $frame->_debug_layout(array($line["x"], $line["y"], $line["w"], $line["h"]), "orange");
         }
     }
 }
 function render(Frame $frame)
 {
     $style = $frame->get_style();
     list($x, $y, $w, $h) = $frame->get_border_box();
     $this->_set_opacity($frame->get_opacity($style->opacity));
     if ($frame->get_node()->nodeName === "body") {
         $h = $frame->get_containing_block("h") - $style->length_in_pt(array($style->margin_top, $style->padding_top, $style->border_top_width, $style->border_bottom_width, $style->padding_bottom, $style->margin_bottom), $style->width);
     }
     // Draw our background, border and content
     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);
     }
     $this->_render_border($frame);
     $this->_render_outline($frame);
     if (DEBUG_LAYOUT && DEBUG_LAYOUT_BLOCKS) {
         $this->_debug_layout($frame->get_border_box(), "red");
         if (DEBUG_LAYOUT_PADDINGBOX) {
             $this->_debug_layout($frame->get_padding_box(), "red", array(0.5, 0.5));
         }
     }
     if (DEBUG_LAYOUT && DEBUG_LAYOUT_LINES && $frame->get_decorator()) {
         foreach ($frame->get_decorator()->get_line_boxes() as $line) {
             $frame->_debug_layout(array($line->x, $line->y, $line->w, $line->h), "orange");
         }
     }
 }
 function apply_page_style(Frame $frame, $page_number)
 {
     $style = $frame->get_style();
     $page_styles = $style->get_stylesheet()->get_page_styles();
     if (count($page_styles) > 1) {
         $odd = $page_number % 2 == 1;
         $first = $page_number == 1;
         $style = clone $page_styles["base"];
         if ($odd && isset($page_styles[":right"])) {
             $style->merge($page_styles[":right"]);
         }
         if ($odd && isset($page_styles[":odd"])) {
             $style->merge($page_styles[":odd"]);
         }
         if (!$odd && isset($page_styles[":left"])) {
             $style->merge($page_styles[":left"]);
         }
         if (!$odd && isset($page_styles[":even"])) {
             $style->merge($page_styles[":even"]);
         }
         if ($first && isset($page_styles[":first"])) {
             $style->merge($page_styles[":first"]);
         }
         $frame->set_style($style);
     }
 }
 /**
  * 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_Decorator($frame, $dompdf);
     parent::__construct($this->_img, $dompdf);
     list($width, $height) = dompdf_getimagesize($this->_img->get_image_url());
     // 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.
     $this->_width = (double) rtrim($width, "px") * 72 / DOMPDF_DPI;
     $this->_height = (double) rtrim($height, "px") * 72 / DOMPDF_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 get_min_max_width()
 {
     if (!is_null($this->_min_max_cache)) {
         return $this->_min_max_cache;
     }
     $style = $this->_frame->get_style();
     // Account for margins & padding
     $dims = array($style->padding_left, $style->padding_right, $style->border_left_width, $style->border_right_width, $style->margin_left, $style->margin_right);
     $cb_w = $this->_frame->get_containing_block("w");
     $delta = $style->length_in_pt($dims, $cb_w);
     // Handle degenerate case
     if (!$this->_frame->get_first_child()) {
         return $this->_min_max_cache = array($delta, $delta, "min" => $delta, "max" => $delta);
     }
     $low = array();
     $high = array();
     for ($iter = $this->_frame->get_children()->getIterator(); $iter->valid(); $iter->next()) {
         $inline_min = 0;
         $inline_max = 0;
         // Add all adjacent inline widths together to calculate max width
         while ($iter->valid() && in_array($iter->current()->get_style()->display, Style::$INLINE_TYPES)) {
             $child = $iter->current();
             $minmax = $child->get_min_max_width();
             if (in_array($iter->current()->get_style()->white_space, array("pre", "nowrap"))) {
                 $inline_min += $minmax["min"];
             } else {
                 $low[] = $minmax["min"];
             }
             $inline_max += $minmax["max"];
             $iter->next();
         }
         if ($inline_max > 0) {
             $high[] = $inline_max;
         }
         if ($inline_min > 0) {
             $low[] = $inline_min;
         }
         if ($iter->valid()) {
             list($low[], $high[]) = $iter->current()->get_min_max_width();
             continue;
         }
     }
     $min = count($low) ? max($low) : 0;
     $max = count($high) ? max($high) : 0;
     // Use specified width if it is greater than the minimum defined by the
     // content.  If the width is a percentage ignore it for now.
     $width = $style->width;
     if ($width !== "auto" && !is_percent($width)) {
         $width = $style->length_in_pt($width, $cb_w);
         if ($min < $width) {
             $min = $width;
         }
         if ($max < $width) {
             $max = $width;
         }
     }
     $min += $delta;
     $max += $delta;
     return $this->_min_max_cache = array($min, $max, "min" => $min, "max" => $max);
 }
 function add_frame_to_line(Frame $frame)
 {
     if (!$frame->is_in_flow()) {
         return;
     }
     $style = $frame->get_style();
     $frame->set_containing_line($this->_line_boxes[$this->_cl]);
     if ($frame instanceof Inline_Frame_Decorator) {
         if ($frame->get_node()->nodeName === "br") {
             $this->maximize_line_height($style->length_in_pt($style->line_height), $frame);
             $this->add_line(true);
         }
         return;
     }
     if ($this->get_current_line_box()->w == 0 && $frame->is_text_node() && !$frame->is_pre()) {
         $frame->set_text(ltrim($frame->get_text()));
         $frame->recalculate_width();
     }
     $w = $frame->get_margin_width();
     if ($w == 0) {
         return;
     }
     $line = $this->_line_boxes[$this->_cl];
     if ($line->left + $line->w + $line->right + $w > $this->get_containing_block("w")) {
         $this->add_line();
     }
     $frame->position();
     $current_line = $this->_line_boxes[$this->_cl];
     $current_line->add_frame($frame);
     if ($frame->is_text_node()) {
         $current_line->wc += count(preg_split("/\\s+/", trim($frame->get_text())));
     }
     $this->increase_line_width($w);
     $this->maximize_line_height($frame->get_margin_height(), $frame);
 }
 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 apply_page_style(Frame $frame, $page_number)
 {
     $style = $frame->get_style();
     $page_styles = $style->get_stylesheet()->get_page_styles();
     // http://www.w3.org/TR/CSS21/page.html#page-selectors
     if (count($page_styles) > 1) {
         $odd = $page_number % 2 == 1;
         $first = $page_number == 1;
         $style = clone $page_styles["base"];
         // FIXME RTL
         if ($odd && isset($page_styles[":right"])) {
             $style->merge($page_styles[":right"]);
         }
         if ($odd && isset($page_styles[":odd"])) {
             $style->merge($page_styles[":odd"]);
         }
         // FIXME RTL
         if (!$odd && isset($page_styles[":left"])) {
             $style->merge($page_styles[":left"]);
         }
         if (!$odd && isset($page_styles[":even"])) {
             $style->merge($page_styles[":even"]);
         }
         if ($first && isset($page_styles[":first"])) {
             $style->merge($page_styles[":first"]);
         }
         $frame->set_style($style);
     }
 }
Example #9
0
 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);
     }
 }
Example #10
0
 /**
  * Render frames recursively
  *
  * @param Frame $frame the frame to render
  */
 function render(Frame $frame)
 {
     global $_dompdf_debug;
     if ($_dompdf_debug) {
         echo $frame;
         flush();
     }
     $display = $frame->get_style()->display;
     switch ($display) {
         case "block":
         case "list-item":
         case "inline-block":
         case "table":
         case "table-row-group":
         case "table-header-group":
         case "table-footer-group":
         case "inline-table":
             $this->_render_frame("block", $frame);
             break;
         case "inline":
             if ($frame->get_node()->nodeName === "#text") {
                 $this->_render_frame("text", $frame);
             } else {
                 $this->_render_frame("inline", $frame);
             }
             break;
         case "table-cell":
             $this->_render_frame("table-cell", $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;
     }
     // Check for begin frame callback
     $this->_check_callbacks("begin_frame", $frame);
     foreach ($frame->get_children() as $child) {
         $this->render($child);
     }
     // Check for end frame callback
     $this->_check_callbacks("end_frame", $frame);
 }
  function render(Frame $frame) {
    $style = $frame->get_style();
    $node = $frame->get_node();

    list($x, $y, $w, $h) = $frame->get_border_box();

    $this->_set_opacity( $frame->get_opacity( $style->opacity ) );

    if ( $node->nodeName === "body" ) {
      $h = $frame->get_containing_block("h") - $style->length_in_pt(array(
        $style->margin_top,
        $style->border_top_width,
        $style->border_bottom_width,
        $style->margin_bottom),
      $style->width);
    }

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

    // Draw our background, border and content
    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 );
    }

    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 ( $tl + $tr + $br + $bl > 0 ) {
      $this->_canvas->clipping_end();
    }

    $border_box = array($x, $y, $w, $h);
    $this->_render_border($frame, $border_box);
    $this->_render_outline($frame, $border_box);

    if (DEBUG_LAYOUT && DEBUG_LAYOUT_BLOCKS) {
      $this->_debug_layout($frame->get_border_box(), "red");
      if (DEBUG_LAYOUT_PADDINGBOX) {
        $this->_debug_layout($frame->get_padding_box(), "red", array(0.5, 0.5));
      }
    }

    if (DEBUG_LAYOUT && DEBUG_LAYOUT_LINES && $frame->get_decorator()) {
      foreach ($frame->get_decorator()->get_line_boxes() as $line) {
        $frame->_debug_layout(array($line->x, $line->y, $line->w, $line->h), "orange");
      }
    }
  }
 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_Decorator($frame, $dompdf);
     parent::__construct($this->_img, $dompdf);
     list($width, $height) = dompdf_getimagesize($this->_img->get_image_url());
     $this->_width = (double) rtrim($width, "px") * 72 / DOMPDF_DPI;
     $this->_height = (double) rtrim($height, "px") * 72 / DOMPDF_DPI;
 }
 /**
  * Class constructor
  *
  * @param Frame $frame the bullet frame to decorate
  * @param DOMPDF $dompdf the document's dompdf object
  */
 function __construct(Frame $frame, DOMPDF $dompdf)
 {
     $url = $frame->get_style()->list_style_image;
     $frame->get_node()->setAttribute("src", $url);
     $this->_img = new Image_Frame_Decorator($frame, $dompdf);
     parent::__construct($this->_img, $dompdf);
     list($width, $height) = getimagesize($this->_img->get_image_url());
     // Resample the bullet image to be consistent with 'auto' sized images
     $this->_width = (double) rtrim($width, "px") * 72 / DOMPDF_DPI;
     $this->_height = (double) rtrim($height, "px") * 72 / DOMPDF_DPI;
 }
 function render(Frame $frame)
 {
     $style = $frame->get_style();
     list($x, $y, $w, $h) = $frame->get_padding_box();
     // Draw our background, border and content
     if (($bg = $style->background_color) !== "transparent") {
         $this->_canvas->filled_rectangle($x, $y, $w, $h, $style->background_color);
     }
     if (($url = $style->background_image) && $url !== "none") {
         $this->_background_image($url, $x, $y, $w, $h, $style);
     }
     $this->_render_border($frame);
 }
Example #15
0
 function render(Frame $frame)
 {
     // Render background & borders
     //parent::render($frame);
     $p = $frame->get_parent();
     $style = $frame->get_style();
     $cb = $frame->get_containing_block();
     list($x, $y) = $frame->get_padding_box();
     $x += $style->length_in_pt($style->padding_left, $cb["w"]);
     $y += $style->length_in_pt($style->padding_top, $cb["h"]);
     $w = $style->length_in_pt($style->width, $cb["w"]);
     $h = $style->length_in_pt($style->height, $cb["h"]);
     $this->_canvas->image($frame->get_image_url(), $frame->get_image_ext(), $x, $y, $w, $h);
 }
 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;
         }
     }
 }
Example #17
0
    /**
     * split this frame at $child.
     *
     * The current frame is cloned and $child and all children following
     * $child are added to the clone.  The clone is then passed to the
     * current frame's parent->split() method.
     *
     * @param Frame $child
     * @param boolean $force_pagebreak
     */
    function split($child = null, $force_pagebreak = false)
    {
        if (is_null($child)) {
            $this->get_parent()->split($this, $force_pagebreak);
            return;
        }

        if ($child->get_parent() !== $this)
            throw new DOMPDF_Exception("Unable to split: frame is not a child of this one.");

        $node = $this->_frame->get_node();

        // mark the frame as splitted (don't use the find_***_parent cache)
        //$this->_splitted = true;

        $split = $this->copy($node->cloneNode());
        $split->reset();
        $split->get_original_style()->text_indent = 0;

        // The body's properties must be kept
        if ($node->nodeName !== "body") {
            // Style reset on the first and second parts
            $style = $this->_frame->get_style();
            $style->margin_bottom = 0;
            $style->padding_bottom = 0;
            $style->border_bottom = 0;

            // second
            $orig_style = $split->get_original_style();
            $orig_style->text_indent = 0;
            $orig_style->margin_top = 0;
            $orig_style->padding_top = 0;
            $orig_style->border_top = 0;
        }

        $this->get_parent()->insert_child_after($split, $this);

        // Add $frame and all following siblings to the new split node
        $iter = $child;
        while ($iter) {
            $frame = $iter;
            $iter = $iter->get_next_sibling();
            $frame->reset();
            $split->append_child($frame);
        }

        $this->get_parent()->split($split, $force_pagebreak);
    }
 function render(Frame $frame)
 {
     $style = $frame->get_style();
     // Draw our background, border and content
     if (($bg = $style->background_color) !== "transparent") {
         list($x, $y, $w, $h) = $frame->get_padding_box();
         $this->_canvas->filled_rectangle($x, $y, $w, $h, $style->background_color);
     }
     // FIXME: need to enable & test this eventually
     //     if ( ($img = $style->background_image) !== "none" ) {
     //       list($x, $y, $w, $h) = $frame->get_padding_box();
     //       list($bx, $by) = $style->background_position;
     //       $bx = $style->length_in_pt($bx, $w);
     //       $by = $style->length_in_pt($by, $h);
     //       $this->_canvas->image($img, $x + $bx, $y + $by);
     //     }
     $this->_render_border($frame);
 }
 /**
  * Parses a CSS "quotes" property
  *
  * @return array|null An array of pairs of quotes
  */
 protected function _parse_quotes()
 {
     // Matches quote types
     $re = '/(\'[^\']*\')|(\\"[^\\"]*\\")/';
     $quotes = $this->_frame->get_style()->quotes;
     // split on spaces, except within quotes
     if (!preg_match_all($re, "{$quotes}", $matches, PREG_SET_ORDER)) {
         return null;
     }
     $quotes_array = array();
     foreach ($matches as &$_quote) {
         $quotes_array[] = $this->_parse_string($_quote[0], true);
     }
     if (empty($quotes_array)) {
         $quotes_array = array('"', '"');
     }
     return array_chunk($quotes_array, 2);
 }
 function render(Frame $frame)
 {
     $style = $frame->get_style();
     $this->_set_opacity($frame->get_opacity($style->opacity));
     $this->_render_border($frame);
     $this->_render_outline($frame);
     if (DEBUG_LAYOUT && DEBUG_LAYOUT_BLOCKS) {
         $this->_debug_layout($frame->get_border_box(), "red");
         if (DEBUG_LAYOUT_PADDINGBOX) {
             $this->_debug_layout($frame->get_padding_box(), "red", array(0.5, 0.5));
         }
     }
     if (DEBUG_LAYOUT && DEBUG_LAYOUT_LINES && $frame->get_decorator()) {
         foreach ($frame->get_decorator()->get_line_boxes() as $line) {
             $frame->_debug_layout(array($line->x, $line->y, $line->w, $line->h), "orange");
         }
     }
 }
 function render(Frame $frame)
 {
     // Render background & borders
     $style = $frame->get_style();
     $cb = $frame->get_containing_block();
     list($x, $y, $w, $h) = $frame->get_border_box();
     $this->_set_opacity($frame->get_opacity($style->opacity));
     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);
     }
     $this->_render_border($frame);
     $this->_render_outline($frame);
     list($x, $y) = $frame->get_padding_box();
     $x += $style->length_in_pt($style->padding_left, $cb["w"]);
     $y += $style->length_in_pt($style->padding_top, $cb["h"]);
     $w = $style->length_in_pt($style->width, $cb["w"]);
     $h = $style->length_in_pt($style->height, $cb["h"]);
     $src = $frame->get_image_url();
     if (Image_Cache::is_broken($src) && ($alt = $frame->get_node()->getAttribute("alt"))) {
         $font = $style->font_family;
         $size = $style->font_size;
         $spacing = $style->word_spacing;
         $this->_canvas->text($x, $y, $alt, $font, $size, $style->color, $spacing);
     } else {
         $this->_canvas->image($src, $x, $y, $w, $h, $style->image_resolution);
     }
     if ($msg = $frame->get_image_msg()) {
         $parts = preg_split("/\\s*\n\\s*/", $msg);
         $height = 10;
         $_y = $alt ? $y + $h - count($parts) * $height : $y;
         foreach ($parts as $i => $_part) {
             $this->_canvas->text($x, $_y + $i * $height, $_part, "times", $height * 0.8, array(0.5, 0.5, 0.5));
         }
     }
     if (DEBUG_LAYOUT && DEBUG_LAYOUT_BLOCKS) {
         $this->_debug_layout($frame->get_border_box(), "blue");
         if (DEBUG_LAYOUT_PADDINGBOX) {
             $this->_debug_layout($frame->get_padding_box(), "blue", array(0.5, 0.5));
         }
     }
 }
 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;
         }
     }
 }
Example #23
0
 function render(Frame $frame)
 {
     // Render background & borders
     $style = $frame->get_style();
     $cb = $frame->get_containing_block();
     list($x, $y, $w, $h) = $frame->get_border_box();
     $this->_set_opacity($frame->get_opacity($style->opacity));
     // Handle the last child
     if (($bg = $style->background_color) !== "transparent") {
         $this->_canvas->filled_rectangle($x + $widths[3], $y + $widths[0], $w, $h, $bg);
     }
     if (($url = $style->background_image) && $url !== "none") {
         $this->_background_image($url, $x + $widths[3], $y + $widths[0], $w, $h, $style);
     }
     $this->_render_border($frame);
     $this->_render_outline($frame);
     list($x, $y) = $frame->get_padding_box();
     $x += $style->length_in_pt($style->padding_left, $cb["w"]);
     $y += $style->length_in_pt($style->padding_top, $cb["h"]);
     $w = $style->length_in_pt($style->width, $cb["w"]);
     $h = $style->length_in_pt($style->height, $cb["h"]);
     if (strrpos($frame->get_image_url(), DOMPDF_LIB_DIR . "/res/broken_image.png", 0) !== false && ($alt = $frame->get_node()->getAttribute("alt"))) {
         $font = $style->font_family;
         $size = $style->font_size;
         $spacing = $style->word_spacing;
         $this->_canvas->text($x, $y, $alt, $font, $size, $style->color, $spacing);
     } else {
         $this->_canvas->image($frame->get_image_url(), $frame->get_image_ext(), $x, $y, $w, $h);
     }
     if (DEBUG_LAYOUT && DEBUG_LAYOUT_BLOCKS) {
         $this->_debug_layout($frame->get_border_box(), "blue");
         if (DEBUG_LAYOUT_PADDINGBOX) {
             $this->_debug_layout($frame->get_padding_box(), "blue", array(0.5, 0.5));
         }
     }
 }
 /**
  * Decorate a Frame
  *
  * @param Frame  $frame  The frame to decorate
  * @param DOMPDF $dompdf The dompdf instance
  * @param Frame  $root   The frame to decorate
  *
  * @throws DOMPDF_Exception
  * @return Frame_Decorator
  * FIXME: this is admittedly a little smelly...
  */
 static function decorate_frame(Frame $frame, DOMPDF $dompdf, Frame $root = null)
 {
     if (is_null($dompdf)) {
         throw new DOMPDF_Exception("The DOMPDF argument is required");
     }
     $style = $frame->get_style();
     // Floating (and more generally out-of-flow) elements are blocks
     // http://coding.smashingmagazine.com/2007/05/01/css-float-theory-things-you-should-know/
     if (!$frame->is_in_flow() && in_array($style->display, Style::$INLINE_TYPES)) {
         $style->display = "block";
     }
     $display = $style->display;
     switch ($display) {
         case "block":
             $positioner = "Block";
             $decorator = "Block";
             $reflower = "Block";
             break;
         case "inline-block":
             $positioner = "Inline";
             $decorator = "Block";
             $reflower = "Block";
             break;
         case "inline":
             $positioner = "Inline";
             if ($frame->is_text_node()) {
                 $decorator = "Text";
                 $reflower = "Text";
             } else {
                 $enable_css_float = $dompdf->get_option("enable_css_float");
                 if ($enable_css_float && $style->float !== "none") {
                     $decorator = "Block";
                     $reflower = "Block";
                 } else {
                     $decorator = "Inline";
                     $reflower = "Inline";
                 }
             }
             break;
         case "table":
             $positioner = "Block";
             $decorator = "Table";
             $reflower = "Table";
             break;
         case "inline-table":
             $positioner = "Inline";
             $decorator = "Table";
             $reflower = "Table";
             break;
         case "table-row-group":
         case "table-header-group":
         case "table-footer-group":
             $positioner = "Null";
             $decorator = "Table_Row_Group";
             $reflower = "Table_Row_Group";
             break;
         case "table-row":
             $positioner = "Null";
             $decorator = "Table_Row";
             $reflower = "Table_Row";
             break;
         case "table-cell":
             $positioner = "Table_Cell";
             $decorator = "Table_Cell";
             $reflower = "Table_Cell";
             break;
         case "list-item":
             $positioner = "Block";
             $decorator = "Block";
             $reflower = "Block";
             break;
         case "-dompdf-list-bullet":
             if ($style->list_style_position === "inside") {
                 $positioner = "Inline";
             } else {
                 $positioner = "List_Bullet";
             }
             if ($style->list_style_image !== "none") {
                 $decorator = "List_Bullet_Image";
             } else {
                 $decorator = "List_Bullet";
             }
             $reflower = "List_Bullet";
             break;
         case "-dompdf-image":
             $positioner = "Inline";
             $decorator = "Image";
             $reflower = "Image";
             break;
         case "-dompdf-br":
             $positioner = "Inline";
             $decorator = "Inline";
             $reflower = "Inline";
             break;
         default:
             // FIXME: should throw some sort of warning or something?
         // FIXME: should throw some sort of warning or something?
         case "none":
             if ($style->_dompdf_keep !== "yes") {
                 // Remove the node and the frame
                 $frame->get_parent()->remove_child($frame);
                 return;
             }
             $positioner = "Null";
             $decorator = "Null";
             $reflower = "Null";
             break;
     }
     // Handle CSS position
     $position = $style->position;
     if ($position === "absolute") {
         $positioner = "Absolute";
     } else {
         if ($position === "fixed") {
             $positioner = "Fixed";
         }
     }
     $node = $frame->get_node();
     // Handle nodeName
     if ($node->nodeName === "img") {
         $style->display = "-dompdf-image";
         $decorator = "Image";
         $reflower = "Image";
     }
     $positioner .= "_Positioner";
     $decorator .= "_Frame_Decorator";
     $reflower .= "_Frame_Reflower";
     $deco = new $decorator($frame, $dompdf);
     $deco->set_positioner(new $positioner($deco));
     $deco->set_reflower(new $reflower($deco));
     if ($root) {
         $deco->set_root($root);
     }
     if ($display === "list-item") {
         // Insert a list-bullet frame
         $xml = $dompdf->get_dom();
         $bullet_node = $xml->createElement("bullet");
         // arbitrary choice
         $b_f = new Frame($bullet_node);
         $node = $frame->get_node();
         $parent_node = $node->parentNode;
         if ($parent_node) {
             if (!$parent_node->hasAttribute("dompdf-children-count")) {
                 $xpath = new DOMXPath($xml);
                 $count = $xpath->query("li", $parent_node)->length;
                 $parent_node->setAttribute("dompdf-children-count", $count);
             }
             if (is_numeric($node->getAttribute("value"))) {
                 $index = intval($node->getAttribute("value"));
             } else {
                 if (!$parent_node->hasAttribute("dompdf-counter")) {
                     $index = $parent_node->hasAttribute("start") ? $parent_node->getAttribute("start") : 1;
                 } else {
                     $index = $parent_node->getAttribute("dompdf-counter") + 1;
                 }
             }
             $parent_node->setAttribute("dompdf-counter", $index);
             $bullet_node->setAttribute("dompdf-counter", $index);
         }
         $new_style = $dompdf->get_css()->create_style();
         $new_style->display = "-dompdf-list-bullet";
         $new_style->inherit($style);
         $b_f->set_style($new_style);
         $deco->prepend_child(Frame_Factory::decorate_frame($b_f, $dompdf, $root));
     }
     return $deco;
 }
 public function get_lowest_float_offset(Frame $child)
 {
     $style = $child->get_style();
     $side = $style->clear;
     $float = $style->float;
     $y = 0;
     foreach ($this->_floating_frames as $key => $frame) {
         if ($side === "both" || $frame->get_style()->float === $side) {
             $y = max($y, $frame->get_position("y") + $frame->get_margin_height());
             if ($float !== "none") {
                 $this->remove_floating_frame($key);
             }
         }
     }
     return $y;
 }
 function render(Frame $frame)
 {
     $style = $frame->get_style();
     if (trim($frame->get_node()->nodeValue) === "" && $style->empty_cells === "hide") {
         return;
     }
     $this->_set_opacity($frame->get_opacity($style->opacity));
     list($x, $y, $w, $h) = $frame->get_border_box();
     // Draw our background, border and content
     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);
     }
     $table = Table_Frame_Decorator::find_parent_table($frame);
     if ($table->get_style()->border_collapse !== "collapse") {
         $this->_render_border($frame);
         $this->_render_outline($frame);
         return;
     }
     // The collapsed case is slightly complicated...
     // @todo Add support for outlines here
     $cellmap = $table->get_cellmap();
     $cells = $cellmap->get_spanned_cells($frame);
     $num_rows = $cellmap->get_num_rows();
     $num_cols = $cellmap->get_num_cols();
     // Determine the top row spanned by this cell
     $i = $cells["rows"][0];
     $top_row = $cellmap->get_row($i);
     // Determine if this cell borders on the bottom of the table.  If so,
     // then we draw its bottom border.  Otherwise the next row down will
     // draw its top border instead.
     if (in_array($num_rows - 1, $cells["rows"])) {
         $draw_bottom = true;
         $bottom_row = $cellmap->get_row($num_rows - 1);
     } else {
         $draw_bottom = false;
     }
     // Draw the horizontal borders
     foreach ($cells["columns"] as $j) {
         $bp = $cellmap->get_border_properties($i, $j);
         $y = $top_row["y"] - $bp["top"]["width"] / 2;
         $col = $cellmap->get_column($j);
         $x = $col["x"] - $bp["left"]["width"] / 2;
         $w = $col["used-width"] + ($bp["left"]["width"] + $bp["right"]["width"]) / 2;
         if ($bp["top"]["style"] !== "none" && $bp["top"]["width"] > 0) {
             $widths = array($bp["top"]["width"], $bp["right"]["width"], $bp["bottom"]["width"], $bp["left"]["width"]);
             $method = "_border_" . $bp["top"]["style"];
             $this->{$method}($x, $y, $w, $bp["top"]["color"], $widths, "top", "square");
         }
         if ($draw_bottom) {
             $bp = $cellmap->get_border_properties($num_rows - 1, $j);
             if ($bp["bottom"]["style"] === "none" || $bp["bottom"]["width"] <= 0) {
                 continue;
             }
             $y = $bottom_row["y"] + $bottom_row["height"] + $bp["bottom"]["width"] / 2;
             $widths = array($bp["top"]["width"], $bp["right"]["width"], $bp["bottom"]["width"], $bp["left"]["width"]);
             $method = "_border_" . $bp["bottom"]["style"];
             $this->{$method}($x, $y, $w, $bp["bottom"]["color"], $widths, "bottom", "square");
         }
     }
     $j = $cells["columns"][0];
     $left_col = $cellmap->get_column($j);
     if (in_array($num_cols - 1, $cells["columns"])) {
         $draw_right = true;
         $right_col = $cellmap->get_column($num_cols - 1);
     } else {
         $draw_right = false;
     }
     // Draw the vertical borders
     foreach ($cells["rows"] as $i) {
         $bp = $cellmap->get_border_properties($i, $j);
         $x = $left_col["x"] - $bp["left"]["width"] / 2;
         $row = $cellmap->get_row($i);
         $y = $row["y"] - $bp["top"]["width"] / 2;
         $h = $row["height"] + ($bp["top"]["width"] + $bp["bottom"]["width"]) / 2;
         if ($bp["left"]["style"] !== "none" && $bp["left"]["width"] > 0) {
             $widths = array($bp["top"]["width"], $bp["right"]["width"], $bp["bottom"]["width"], $bp["left"]["width"]);
             $method = "_border_" . $bp["left"]["style"];
             $this->{$method}($x, $y, $h, $bp["left"]["color"], $widths, "left", "square");
         }
         if ($draw_right) {
             $bp = $cellmap->get_border_properties($i, $num_cols - 1);
             if ($bp["right"]["style"] === "none" || $bp["right"]["width"] <= 0) {
                 continue;
             }
             $x = $right_col["x"] + $right_col["used-width"] + $bp["right"]["width"] / 2;
             $widths = array($bp["top"]["width"], $bp["right"]["width"], $bp["bottom"]["width"], $bp["left"]["width"]);
             $method = "_border_" . $bp["right"]["style"];
             $this->{$method}($x, $y, $h, $bp["right"]["color"], $widths, "right", "square");
         }
     }
 }
 function process_float(Frame $child, $cb_x, $cb_w)
 {
     if (!DOMPDF_ENABLE_CSS_FLOAT) {
         return;
     }
     $child_style = $child->get_style();
     $root = $this->_frame->get_root();
     // Handle "float"
     if ($child_style->float !== "none") {
         $root->add_floating_frame($child);
         // Remove next frame's beginning whitespace
         $next = $child->get_next_sibling();
         if ($next && $next instanceof Text_Frame_Decorator) {
             $next->set_text(ltrim($next->get_text()));
         }
         $line_box = $this->_frame->get_current_line_box();
         list($old_x, $old_y) = $child->get_position();
         $float_x = $cb_x;
         $float_y = $old_y;
         $float_w = $child->get_margin_width();
         if ($child_style->clear === "none") {
             switch ($child_style->float) {
                 case "left":
                     $float_x += $line_box->left;
                     break;
                 case "right":
                     $float_x += $cb_w - $line_box->right - $float_w;
                     break;
             }
         } else {
             if ($child_style->float === "right") {
                 $float_x += $cb_w - $float_w;
             }
         }
         $line_box->get_float_offsets();
         if ($child->_float_next_line) {
             $float_y += $line_box->h;
         }
         $child->set_position($float_x, $float_y);
         $child->move($float_x - $old_x, $float_y - $old_y, true);
     }
 }
 /**
  * Parses the CSS "content" property
  * 
  * @return string The resulting string
  */
 protected function _parse_content()
 {
     // Matches generated content
     $re = "/\n" . "\\s(counters?\\([^)]*\\))|\n" . "\\A(counters?\\([^)]*\\))|\n" . "\\s([\"']) ( (?:[^\"']|\\\\[\"'])+ )(?<!\\\\)\\3|\n" . "\\A([\"']) ( (?:[^\"']|\\\\[\"'])+ )(?<!\\\\)\\5|\n" . "\\s([^\\s\"']+)|\n" . "\\A([^\\s\"']+)\n" . "/xi";
     $content = $this->_frame->get_style()->content;
     $quotes = $this->_parse_quotes();
     // split on spaces, except within quotes
     if (!preg_match_all($re, $content, $matches, PREG_SET_ORDER)) {
         return;
     }
     $text = "";
     foreach ($matches as $match) {
         if (isset($match[2]) && $match[2] !== "") {
             $match[1] = $match[2];
         }
         if (isset($match[6]) && $match[6] !== "") {
             $match[4] = $match[6];
         }
         if (isset($match[8]) && $match[8] !== "") {
             $match[7] = $match[8];
         }
         if (isset($match[1]) && $match[1] !== "") {
             // counters?(...)
             $match[1] = mb_strtolower(trim($match[1]));
             // Handle counter() references:
             // http://www.w3.org/TR/CSS21/generate.html#content
             $i = mb_strpos($match[1], ")");
             if ($i === false) {
                 continue;
             }
             $args = explode(",", mb_substr($match[1], 8, $i - 8));
             $counter_id = $args[0];
             if ($match[1][7] === "(") {
                 // counter(name [,style])
                 if (isset($args[1])) {
                     $type = trim($args[1]);
                 } else {
                     $type = null;
                 }
                 $p = $this->_frame->find_block_parent();
                 $text .= $p->counter_value($counter_id, $type);
             } else {
                 if ($match[1][7] === "s") {
                     // counters(name, string [,style])
                     if (isset($args[1])) {
                         $string = $this->_parse_string(trim($args[1]));
                     } else {
                         $string = "";
                     }
                     if (isset($args[2])) {
                         $type = $args[2];
                     } else {
                         $type = null;
                     }
                     $p = $this->_frame->find_block_parent();
                     $tmp = "";
                     while ($p) {
                         $tmp = $p->counter_value($counter_id, $type) . $string . $tmp;
                         $p = $p->find_block_parent();
                     }
                     $text .= $tmp;
                 } else {
                     // countertops?
                     continue;
                 }
             }
         } else {
             if (isset($match[4]) && $match[4] !== "") {
                 // String match
                 $text .= $this->_parse_string($match[4]);
             } else {
                 if (isset($match[7]) && $match[7] !== "") {
                     // Directive match
                     if ($match[7] === "open-quote") {
                         // FIXME: do something here
                         $text .= $quotes[0][0];
                     } else {
                         if ($match[7] === "close-quote") {
                             // FIXME: do something else here
                             $text .= $quotes[0][1];
                         } else {
                             if ($match[7] === "no-open-quote") {
                                 // FIXME:
                             } else {
                                 if ($match[7] === "no-close-quote") {
                                     // FIXME:
                                 } else {
                                     if (mb_strpos($match[7], "attr(") === 0) {
                                         $i = mb_strpos($match[7], ")");
                                         if ($i === false) {
                                             continue;
                                         }
                                         $attr = mb_substr($match[7], 5, $i - 5);
                                         if ($attr == "") {
                                             continue;
                                         }
                                         $text .= $this->_frame->get_parent()->get_node()->getAttribute($attr);
                                     } else {
                                         continue;
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     return $text;
 }
 static function decorate_frame(Frame $frame, $dompdf)
 {
     if (is_null($dompdf)) {
         throw new Exception("foo");
     }
     switch ($frame->get_style()->display) {
         case "block":
             $positioner = "Block";
             $decorator = "Block";
             $reflower = "Block";
             break;
         case "inline-block":
             $positioner = "Inline";
             $decorator = "Block";
             $reflower = "Block";
             break;
         case "inline":
             $positioner = "Inline";
             if ($frame->get_node()->nodeName == "#text") {
                 $decorator = "Text";
                 $reflower = "Text";
             } else {
                 $decorator = "Inline";
                 $reflower = "Inline";
             }
             break;
         case "table":
             $positioner = "Block";
             $decorator = "Table";
             $reflower = "Table";
             break;
         case "inline-table":
             $positioner = "Inline";
             $decorator = "Table";
             $reflower = "Table";
             break;
         case "table-row-group":
         case "table-header-group":
         case "table-footer-group":
             $positioner = "Null";
             $decorator = "Table_Row_Group";
             $reflower = "Table_Row_Group";
             break;
         case "table-row":
             $positioner = "Null";
             $decorator = "Table_Row";
             $reflower = "Table_Row";
             break;
         case "table-cell":
             $positioner = "Table_Cell";
             $decorator = "Table_Cell";
             $reflower = "Table_Cell";
             break;
         case "list-item":
             $positioner = "Block";
             $decorator = "Block";
             $reflower = "Block";
             break;
         case "-dompdf-list-bullet":
             if ($frame->get_style()->list_style_position == "inside") {
                 $positioner = "Inline";
             } else {
                 $positioner = "List_Bullet";
             }
             if ($frame->get_style()->list_style_image != "none") {
                 $decorator = "List_Bullet_Image";
             } else {
                 $decorator = "List_Bullet";
             }
             $reflower = "List_Bullet";
             break;
         case "-dompdf-image":
             $positioner = "Inline";
             $decorator = "Image";
             $reflower = "Image";
             break;
         case "-dompdf-br":
             $positioner = "Inline";
             $decorator = "Inline";
             $reflower = "Inline";
             break;
         default:
             // FIXME: should throw some sort of warning or something?
         // FIXME: should throw some sort of warning or something?
         case "none":
             $positioner = "Null";
             $decorator = "Null";
             $reflower = "Null";
             break;
     }
     $positioner .= "_Positioner";
     $decorator .= "_Frame_Decorator";
     $reflower .= "_Frame_Reflower";
     $deco = new $decorator($frame, $dompdf);
     $deco->set_positioner(new $positioner($deco));
     $reflow = new $reflower($deco);
     // Generated content is a special case
     if ($frame->get_node()->nodeName == "_dompdf_generated") {
         // Decorate the reflower
         $gen = new Generated_Frame_Reflower($deco);
         $gen->set_reflower($reflow);
         $reflow = $gen;
     }
     $deco->set_reflower($reflow);
     // Images are a special case
     //    if ( $frame->get_node()->nodeName == "img" ) {
     //       // FIXME: This is a hack
     //       $node =$frame->get_node()->ownerDocument->createElement("img_sub");
     //       $node->setAttribute("src", $frame->get_node()->getAttribute("src"));
     //       $img_frame = new Frame( $node );
     //       $style = $frame->get_style()->get_stylesheet()->create_style();
     //       $style->inherit($frame->get_style());
     //       $img_frame->set_style( $style );
     //       $img_deco = new Image_Frame_Decorator($img_frame, $dompdf);
     //       $img_deco->set_reflower( new Image_Frame_Reflower($img_deco) );
     //       $deco->append_child($img_deco);
     //     }
     return $deco;
 }
 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);
         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));
             }
         }
     }
     // 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);
         }
     }
 }