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" && !Helpers::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);
 }
Beispiel #2
0
 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"))) {
         $href = Helpers::build_url($this->_dompdf->getProtocol(), $this->_dompdf->getBaseHost(), $this->_dompdf->getBasePath(), $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 ($this->_dompdf->getOptions()->getDebugLayout() && $this->_dompdf->getOptions()->getDebugLayoutBlocks()) {
         $this->_debug_layout($frame->get_border_box(), "red");
         if ($this->_dompdf->getOptions()->getDebugLayoutPaddingBox()) {
             $this->_debug_layout($frame->get_padding_box(), "red", array(0.5, 0.5));
         }
     }
     if ($this->_dompdf->getOptions()->getDebugLayout() && $this->_dompdf->getOptions()->getDebugLayoutLines() && $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");
         }
     }
 }
Beispiel #3
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));
     list($tl, $tr, $br, $bl) = $style->get_computed_border_radius($w, $h);
     $has_border_radius = $tl + $tr + $br + $bl > 0;
     if ($has_border_radius) {
         $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 ($has_border_radius) {
         $this->_canvas->clipping_end();
     }
     $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 ($has_border_radius) {
         list($wt, $wr, $wb, $wl) = array($style->border_top_width, $style->border_right_width, $style->border_bottom_width, $style->border_left_width);
         // we have to get the "inner" radius
         if ($tl > 0) {
             $tl -= ($wt + $wl) / 2;
         }
         if ($tr > 0) {
             $tr -= ($wt + $wr) / 2;
         }
         if ($br > 0) {
             $br -= ($wb + $wr) / 2;
         }
         if ($bl > 0) {
             $bl -= ($wb + $wl) / 2;
         }
         $this->_canvas->clipping_roundrectangle($x, $y, $w, $h, $tl, $tr, $br, $bl);
     }
     $src = $frame->get_image_url();
     $alt = null;
     if (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 ($has_border_radius) {
         $this->_canvas->clipping_end();
     }
     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 ($this->_dompdf->getOptions()->getDebugLayout() && $this->_dompdf->getOptions()->getDebugLayoutBlocks()) {
         $this->_debug_layout($frame->get_border_box(), "blue");
         if ($this->_dompdf->getOptions()->getDebugLayoutPaddingBox()) {
             $this->_debug_layout($frame->get_padding_box(), "blue", array(0.5, 0.5));
         }
     }
 }
Beispiel #4
0
 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"));
     $this->_set_opacity($frame->get_opacity($style->opacity));
     $li = $frame->get_parent();
     // Don't render bullets twice if if was split
     if ($li->_splitted) {
         return;
     }
     // Handle list-style-image
     // If list style image is requested but missing, fall back to predefined types
     if ($style->list_style_image !== "none" && !Cache::is_broken($img = $frame->get_image_url())) {
         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::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) = Helpers::dompdf_getimagesize($img, $this->_dompdf->getHttpContext());
         $dpi = $this->_dompdf->getOptions()->getDpi();
         $w = (double) rtrim($width, "px") * 72 / $dpi;
         $h = (double) rtrim($height, "px") * 72 / $dpi;
         $x -= $w;
         $y -= ($line_height - $font_size) / 2;
         //Reverse hinting of list_bullet_positioner
         $this->_canvas->image($img, $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 * ListBulletFrameDecorator::BULLET_SIZE / 2;
                 $x -= $font_size * (ListBulletFrameDecorator::BULLET_SIZE / 2);
                 $y += $font_size * (1 - ListBulletFrameDecorator::BULLET_DESCENT) / 2;
                 $o = $font_size * ListBulletFrameDecorator::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 * ListBulletFrameDecorator::BULLET_SIZE;
                 $x -= $w;
                 $y += $font_size * (1 - ListBulletFrameDecorator::BULLET_DESCENT - ListBulletFrameDecorator::BULLET_SIZE) / 2;
                 $this->_canvas->filled_rectangle($x, $y, $w, $w, $style->color);
                 break;
             case "decimal-leading-zero":
             case "decimal":
             case "lower-alpha":
             case "lower-latin":
             case "lower-roman":
             case "lower-greek":
             case "upper-alpha":
             case "upper-latin":
             case "upper-roman":
             case "1":
                 // HTML 4.0 compatibility
             // HTML 4.0 compatibility
             case "a":
             case "i":
             case "A":
             case "I":
                 $pad = null;
                 if ($bullet_style === "decimal-leading-zero") {
                     $pad = strlen($li->get_parent()->get_node()->getAttribute("dompdf-children-count"));
                 }
                 $node = $frame->get_node();
                 if (!$node->hasAttribute("dompdf-counter")) {
                     return;
                 }
                 $index = $node->getAttribute("dompdf-counter");
                 $text = $this->make_counter($index, $bullet_style, $pad);
                 if (trim($text) == "") {
                     return;
                 }
                 $spacing = 0;
                 $font_family = $style->font_family;
                 $line = $li->get_containing_line();
                 list($x, $y) = array($frame->get_position("x"), $line->y);
                 $x -= $this->_dompdf->getFontMetrics()->getTextWidth($text, $font_family, $font_size, $spacing);
                 // Take line-height into account
                 $line_height = $style->line_height;
                 $y += ($line_height - $font_size) / 4;
                 // FIXME I thought it should be 2, but 4 gives better results
                 $this->_canvas->text($x, $y, $text, $font_family, $font_size, $style->color, $spacing);
             case "none":
                 break;
         }
     }
 }
 /**
  * @param integer $i
  *
  * @return array|float
  */
 function get_containing_block($i = null)
 {
     return $this->_frame->get_containing_block($i);
 }
Beispiel #6
0
 /**
  * @param \Dompdf\FrameDecorator\Text $frame
  */
 function render(Frame $frame)
 {
     $text = $frame->get_text();
     if (trim($text) === "") {
         return;
     }
     $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"]);
     $font = $style->font_family;
     $size = $frame_font_size = $style->font_size;
     $height = $style->height;
     $word_spacing = $frame->get_text_spacing() + $style->length_in_pt($style->word_spacing);
     $char_spacing = $style->length_in_pt($style->letter_spacing);
     $width = $style->width;
     /*$text = str_replace(
         array("{PAGE_NUM}"),
         array($this->_canvas->get_page_number()),
         $text
       );*/
     $this->_canvas->text($x, $y, $text, $font, $size, $style->color, $word_spacing, $char_spacing);
     $line = $frame->get_containing_line();
     // FIXME Instead of using the tallest frame to position,
     // the decoration, the text should be well placed
     if (false && $line->tallest_frame) {
         $base_frame = $line->tallest_frame;
         $style = $base_frame->get_style();
         $size = $style->font_size;
         $height = $line->h * ($size / $style->line_height);
     }
     $line_thickness = $size * self::DECO_THICKNESS;
     $underline_offset = $size * self::UNDERLINE_OFFSET;
     $overline_offset = $size * self::OVERLINE_OFFSET;
     $linethrough_offset = $size * self::LINETHROUGH_OFFSET;
     $underline_position = -0.08;
     if ($this->_canvas instanceof CPDF) {
         $cpdf_font = $this->_canvas->get_cpdf()->fonts[$style->font_family];
         if (isset($cpdf_font["UnderlinePosition"])) {
             $underline_position = $cpdf_font["UnderlinePosition"] / 1000;
         }
         if (isset($cpdf_font["UnderlineThickness"])) {
             $line_thickness = $size * ($cpdf_font["UnderlineThickness"] / 1000);
         }
     }
     $descent = $size * $underline_position;
     $base = $size;
     // 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 (isset($stack[0])) {
         $f = array_pop($stack);
         if (($text_deco = $f->get_style()->text_decoration) === "none") {
             continue;
         }
         $deco_y = $y;
         //$line->y;
         $color = $f->get_style()->color;
         switch ($text_deco) {
             default:
                 continue;
             case "underline":
                 $deco_y += $base - $descent + $underline_offset + $line_thickness / 2;
                 break;
             case "overline":
                 $deco_y += $overline_offset + $line_thickness / 2;
                 break;
             case "line-through":
                 $deco_y += $base * 0.7 + $linethrough_offset;
                 break;
         }
         $dx = 0;
         $x1 = $x - self::DECO_EXTENSION;
         $x2 = $x + $width + $dx + self::DECO_EXTENSION;
         $this->_canvas->line($x1, $deco_y, $x2, $deco_y, $color, $line_thickness);
     }
     if ($this->_dompdf->getOptions()->getDebugLayout() && $this->_dompdf->getOptions()->getDebugLayoutLines()) {
         $text_width = $this->_dompdf->getFontMetrics()->getTextWidth($text, $font, $frame_font_size);
         $this->_debug_layout(array($x, $y, $text_width + ($line->wc - 1) * $word_spacing, $frame_font_size), "orange", array(0.5, 0.5));
     }
 }