Ejemplo n.º 1
1
 /**
  * Render a background image over a rectangular area
  *
  * @param string $url   The background image to load
  * @param float $x      The left edge of the rectangular area
  * @param float $y      The top edge of the rectangular area
  * @param float $width  The width of the rectangular area
  * @param float $height The height of the rectangular area
  * @param Style $style  The associated Style object
  *
  * @throws \Exception
  */
 protected function _background_image($url, $x, $y, $width, $height, $style)
 {
     if (!function_exists("imagecreatetruecolor")) {
         throw new \Exception("The PHP GD extension is required, but is not installed.");
     }
     $sheet = $style->get_stylesheet();
     // Skip degenerate cases
     if ($width == 0 || $height == 0) {
         return;
     }
     $box_width = $width;
     $box_height = $height;
     //debugpng
     if ($this->_dompdf->get_option("debugPng")) {
         print '[_background_image ' . $url . ']';
     }
     list($img, $type, ) = Cache::resolve_url($url, $sheet->get_protocol(), $sheet->get_host(), $sheet->get_base_path(), $this->_dompdf);
     // Bail if the image is no good
     if (Cache::is_broken($img)) {
         return;
     }
     //Try to optimize away reading and composing of same background multiple times
     //Postponing read with imagecreatefrom   ...()
     //final composition parameters and name not known yet
     //Therefore read dimension directly from file, instead of creating gd object first.
     //$img_w = imagesx($src); $img_h = imagesy($src);
     list($img_w, $img_h) = Helpers::dompdf_getimagesize($img);
     if (!isset($img_w) || $img_w == 0 || !isset($img_h) || $img_h == 0) {
         return;
     }
     $repeat = $style->background_repeat;
     $dpi = $this->_dompdf->get_option("dpi");
     //Increase background resolution and dependent box size according to image resolution to be placed in
     //Then image can be copied in without resize
     $bg_width = round((double) ($width * $dpi) / 72);
     $bg_height = round((double) ($height * $dpi) / 72);
     //Need %bg_x, $bg_y as background pos, where img starts, converted to pixel
     list($bg_x, $bg_y) = $style->background_position;
     if (Helpers::is_percent($bg_x)) {
         // The point $bg_x % from the left edge of the image is placed
         // $bg_x % from the left edge of the background rectangle
         $p = (double) $bg_x / 100.0;
         $x1 = $p * $img_w;
         $x2 = $p * $bg_width;
         $bg_x = $x2 - $x1;
     } else {
         $bg_x = (double) ($style->length_in_pt($bg_x) * $dpi) / 72;
     }
     $bg_x = round($bg_x + $style->length_in_pt($style->border_left_width) * $dpi / 72);
     if (Helpers::is_percent($bg_y)) {
         // The point $bg_y % from the left edge of the image is placed
         // $bg_y % from the left edge of the background rectangle
         $p = (double) $bg_y / 100.0;
         $y1 = $p * $img_h;
         $y2 = $p * $bg_height;
         $bg_y = $y2 - $y1;
     } else {
         $bg_y = (double) ($style->length_in_pt($bg_y) * $dpi) / 72;
     }
     $bg_y = round($bg_y + $style->length_in_pt($style->border_top_width) * $dpi / 72);
     //clip background to the image area on partial repeat. Nothing to do if img off area
     //On repeat, normalize start position to the tile at immediate left/top or 0/0 of area
     //On no repeat with positive offset: move size/start to have offset==0
     //Handle x/y Dimensions separately
     if ($repeat !== "repeat" && $repeat !== "repeat-x") {
         //No repeat x
         if ($bg_x < 0) {
             $bg_width = $img_w + $bg_x;
         } else {
             $x += $bg_x * 72 / $dpi;
             $bg_width = $bg_width - $bg_x;
             if ($bg_width > $img_w) {
                 $bg_width = $img_w;
             }
             $bg_x = 0;
         }
         if ($bg_width <= 0) {
             return;
         }
         $width = (double) ($bg_width * 72) / $dpi;
     } else {
         //repeat x
         if ($bg_x < 0) {
             $bg_x = -(-$bg_x % $img_w);
         } else {
             $bg_x = $bg_x % $img_w;
             if ($bg_x > 0) {
                 $bg_x -= $img_w;
             }
         }
     }
     if ($repeat !== "repeat" && $repeat !== "repeat-y") {
         //no repeat y
         if ($bg_y < 0) {
             $bg_height = $img_h + $bg_y;
         } else {
             $y += $bg_y * 72 / $dpi;
             $bg_height = $bg_height - $bg_y;
             if ($bg_height > $img_h) {
                 $bg_height = $img_h;
             }
             $bg_y = 0;
         }
         if ($bg_height <= 0) {
             return;
         }
         $height = (double) ($bg_height * 72) / $dpi;
     } else {
         //repeat y
         if ($bg_y < 0) {
             $bg_y = -(-$bg_y % $img_h);
         } else {
             $bg_y = $bg_y % $img_h;
             if ($bg_y > 0) {
                 $bg_y -= $img_h;
             }
         }
     }
     //Optimization, if repeat has no effect
     if ($repeat === "repeat" && $bg_y <= 0 && $img_h + $bg_y >= $bg_height) {
         $repeat = "repeat-x";
     }
     if ($repeat === "repeat" && $bg_x <= 0 && $img_w + $bg_x >= $bg_width) {
         $repeat = "repeat-y";
     }
     if ($repeat === "repeat-x" && $bg_x <= 0 && $img_w + $bg_x >= $bg_width || $repeat === "repeat-y" && $bg_y <= 0 && $img_h + $bg_y >= $bg_height) {
         $repeat = "no-repeat";
     }
     //Use filename as indicator only
     //different names for different variants to have different copies in the pdf
     //This is not dependent of background color of box! .'_'.(is_array($bg_color) ? $bg_color["hex"] : $bg_color)
     //Note: Here, bg_* are the start values, not end values after going through the tile loops!
     $filedummy = $img;
     $is_png = false;
     $filedummy .= '_' . $bg_width . '_' . $bg_height . '_' . $bg_x . '_' . $bg_y . '_' . $repeat;
     //Optimization to avoid multiple times rendering the same image.
     //If check functions are existing and identical image already cached,
     //then skip creation of duplicate, because it is not needed by addImagePng
     if ($this->_canvas instanceof CPDF && $this->_canvas->get_cpdf()->image_iscached($filedummy)) {
         $bg = null;
     } else {
         // Create a new image to fit over the background rectangle
         $bg = imagecreatetruecolor($bg_width, $bg_height);
         switch (strtolower($type)) {
             case "png":
                 $is_png = true;
                 imagesavealpha($bg, true);
                 imagealphablending($bg, false);
                 $src = imagecreatefrompng($img);
                 break;
             case "jpeg":
                 $src = imagecreatefromjpeg($img);
                 break;
             case "gif":
                 $src = imagecreatefromgif($img);
                 break;
             case "bmp":
                 $src = Helpers::imagecreatefrombmp($img);
                 break;
             default:
                 return;
                 // Unsupported image type
         }
         if ($src == null) {
             return;
         }
         //Background color if box is not relevant here
         //Non transparent image: box clipped to real size. Background non relevant.
         //Transparent image: The image controls the transparency and lets shine through whatever background.
         //However on transparent image preset the composed image with the transparency color,
         //to keep the transparency when copying over the non transparent parts of the tiles.
         $ti = imagecolortransparent($src);
         if ($ti >= 0) {
             $tc = imagecolorsforindex($src, $ti);
             $ti = imagecolorallocate($bg, $tc['red'], $tc['green'], $tc['blue']);
             imagefill($bg, 0, 0, $ti);
             imagecolortransparent($bg, $ti);
         }
         //This has only an effect for the non repeatable dimension.
         //compute start of src and dest coordinates of the single copy
         if ($bg_x < 0) {
             $dst_x = 0;
             $src_x = -$bg_x;
         } else {
             $src_x = 0;
             $dst_x = $bg_x;
         }
         if ($bg_y < 0) {
             $dst_y = 0;
             $src_y = -$bg_y;
         } else {
             $src_y = 0;
             $dst_y = $bg_y;
         }
         //For historical reasons exchange meanings of variables:
         //start_* will be the start values, while bg_* will be the temporary start values in the loops
         $start_x = $bg_x;
         $start_y = $bg_y;
         // Copy regions from the source image to the background
         if ($repeat === "no-repeat") {
             // Simply place the image on the background
             imagecopy($bg, $src, $dst_x, $dst_y, $src_x, $src_y, $img_w, $img_h);
         } else {
             if ($repeat === "repeat-x") {
                 for ($bg_x = $start_x; $bg_x < $bg_width; $bg_x += $img_w) {
                     if ($bg_x < 0) {
                         $dst_x = 0;
                         $src_x = -$bg_x;
                         $w = $img_w + $bg_x;
                     } else {
                         $dst_x = $bg_x;
                         $src_x = 0;
                         $w = $img_w;
                     }
                     imagecopy($bg, $src, $dst_x, $dst_y, $src_x, $src_y, $w, $img_h);
                 }
             } else {
                 if ($repeat === "repeat-y") {
                     for ($bg_y = $start_y; $bg_y < $bg_height; $bg_y += $img_h) {
                         if ($bg_y < 0) {
                             $dst_y = 0;
                             $src_y = -$bg_y;
                             $h = $img_h + $bg_y;
                         } else {
                             $dst_y = $bg_y;
                             $src_y = 0;
                             $h = $img_h;
                         }
                         imagecopy($bg, $src, $dst_x, $dst_y, $src_x, $src_y, $img_w, $h);
                     }
                 } else {
                     if ($repeat === "repeat") {
                         for ($bg_y = $start_y; $bg_y < $bg_height; $bg_y += $img_h) {
                             for ($bg_x = $start_x; $bg_x < $bg_width; $bg_x += $img_w) {
                                 if ($bg_x < 0) {
                                     $dst_x = 0;
                                     $src_x = -$bg_x;
                                     $w = $img_w + $bg_x;
                                 } else {
                                     $dst_x = $bg_x;
                                     $src_x = 0;
                                     $w = $img_w;
                                 }
                                 if ($bg_y < 0) {
                                     $dst_y = 0;
                                     $src_y = -$bg_y;
                                     $h = $img_h + $bg_y;
                                 } else {
                                     $dst_y = $bg_y;
                                     $src_y = 0;
                                     $h = $img_h;
                                 }
                                 imagecopy($bg, $src, $dst_x, $dst_y, $src_x, $src_y, $w, $h);
                             }
                         }
                     } else {
                         print 'Unknown repeat!';
                     }
                 }
             }
         }
         imagedestroy($src);
     }
     /* End optimize away creation of duplicates */
     $this->_canvas->clipping_rectangle($x, $y, $box_width, $box_height);
     //img: image url string
     //img_w, img_h: original image size in px
     //width, height: box size in pt
     //bg_width, bg_height: box size in px
     //x, y: left/top edge of box on page in pt
     //start_x, start_y: placement of image relative to pattern
     //$repeat: repeat mode
     //$bg: GD object of result image
     //$src: GD object of original image
     //When using cpdf and optimization to direct png creation from gd object is available,
     //don't create temp file, but place gd object directly into the pdf
     if (!$is_png && $this->_canvas instanceof CPDF) {
         // Note: CPDF_Adapter image converts y position
         $this->_canvas->get_cpdf()->addImagePng($filedummy, $x, $this->_canvas->get_height() - $y - $height, $width, $height, $bg);
     } else {
         $tmp_dir = $this->_dompdf->get_option("temp_dir");
         $tmp_name = tempnam($tmp_dir, "bg_dompdf_img_");
         @unlink($tmp_name);
         $tmp_file = "{$tmp_name}.png";
         //debugpng
         if ($this->_dompdf->get_option("debugPng")) {
             print '[_background_image ' . $tmp_file . ']';
         }
         imagepng($bg, $tmp_file);
         $this->_canvas->image($tmp_file, $x, $y, $width, $height);
         imagedestroy($bg);
         //debugpng
         if ($this->_dompdf->get_option("debugPng")) {
             print '[_background_image unlink ' . $tmp_file . ']';
         }
         if (!$this->_dompdf->get_option("debugKeepTemp")) {
             unlink($tmp_file);
         }
     }
     $this->_canvas->clipping_end();
 }
Ejemplo n.º 2
0
    public function testParseDataUriBase64Image()
    {
        $imageParts = array('mime' => 'data:image/png;base64,', 'data' => 'iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==');
        $helpers = new Helpers();
        $result = $helpers->parse_data_uri(implode('', $imageParts));
        $this->assertEquals($result['data'], base64_decode($imageParts['data']));
    }
Ejemplo n.º 3
0
 /**
  * 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, $dompdf);
     parent::__construct($this->_img, $dompdf);
     list($width, $height) = Helpers::dompdf_getimagesize($this->_img->get_image_url());
     // 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.
     $dpi = $this->_dompdf->get_option("dpi");
     $this->_width = (double) rtrim($width, "px") * 72 / $dpi;
     $this->_height = (double) rtrim($height, "px") * 72 / $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";
 }
Ejemplo n.º 4
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");
         }
     }
 }
Ejemplo n.º 5
0
 /**
  * Builds the {@link FrameTree}, loads any CSS and applies the styles to
  * the {@link FrameTree}
  */
 private function processHtml()
 {
     $this->tree->build_tree();
     $this->css->load_css_file(Stylesheet::getDefaultStylesheet(), Stylesheet::ORIG_UA);
     $acceptedmedia = Stylesheet::$ACCEPTED_GENERIC_MEDIA_TYPES;
     $acceptedmedia[] = $this->options->getDefaultMediaType();
     // <base href="" />
     $base_nodes = $this->dom->getElementsByTagName("base");
     if ($base_nodes->length && ($href = $base_nodes->item(0)->getAttribute("href"))) {
         list($this->protocol, $this->baseHost, $this->basePath) = Helpers::explode_url($href);
     }
     // Set the base path of the Stylesheet to that of the file being processed
     $this->css->set_protocol($this->protocol);
     $this->css->set_host($this->baseHost);
     $this->css->set_base_path($this->basePath);
     // Get all the stylesheets so that they are processed in document order
     $xpath = new DOMXPath($this->dom);
     $stylesheets = $xpath->query("//*[name() = 'link' or name() = 'style']");
     foreach ($stylesheets as $tag) {
         switch (strtolower($tag->nodeName)) {
             // load <link rel="STYLESHEET" ... /> tags
             case "link":
                 if (mb_strtolower(stripos($tag->getAttribute("rel"), "stylesheet") !== false) || mb_strtolower($tag->getAttribute("type")) === "text/css") {
                     //Check if the css file is for an accepted media type
                     //media not given then always valid
                     $formedialist = preg_split("/[\\s\n,]/", $tag->getAttribute("media"), -1, PREG_SPLIT_NO_EMPTY);
                     if (count($formedialist) > 0) {
                         $accept = false;
                         foreach ($formedialist as $type) {
                             if (in_array(mb_strtolower(trim($type)), $acceptedmedia)) {
                                 $accept = true;
                                 break;
                             }
                         }
                         if (!$accept) {
                             //found at least one mediatype, but none of the accepted ones
                             //Skip this css file.
                             continue;
                         }
                     }
                     $url = $tag->getAttribute("href");
                     $url = Helpers::build_url($this->protocol, $this->baseHost, $this->basePath, $url);
                     $this->css->load_css_file($url, Stylesheet::ORIG_AUTHOR);
                 }
                 break;
                 // load <style> tags
             // load <style> tags
             case "style":
                 // Accept all <style> tags by default (note this is contrary to W3C
                 // HTML 4.0 spec:
                 // http://www.w3.org/TR/REC-html40/present/styles.html#adef-media
                 // which states that the default media type is 'screen'
                 if ($tag->hasAttributes() && ($media = $tag->getAttribute("media")) && !in_array($media, $acceptedmedia)) {
                     continue;
                 }
                 $css = "";
                 if ($tag->hasChildNodes()) {
                     $child = $tag->firstChild;
                     while ($child) {
                         $css .= $child->nodeValue;
                         // Handle <style><!-- blah --></style>
                         $child = $child->nextSibling;
                     }
                 } else {
                     $css = $tag->nodeValue;
                 }
                 $this->css->load_css($css);
                 break;
         }
     }
 }
Ejemplo n.º 6
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;
         }
     }
 }
Ejemplo n.º 7
0
 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);
 }
Ejemplo n.º 8
0
 function get_min_max_width()
 {
     if ($this->get_dompdf()->getOptions()->getDebugPng()) {
         // Determine the image's size. Time consuming. Only when really needed?
         list($img_width, $img_height) = Helpers::dompdf_getimagesize($this->_frame->get_image_url(), $this->get_dompdf()->getHttpContext());
         print "get_min_max_width() " . $this->_frame->get_style()->width . ' ' . $this->_frame->get_style()->height . ';' . $this->_frame->get_parent()->get_style()->width . " " . $this->_frame->get_parent()->get_style()->height . ";" . $this->_frame->get_parent()->get_parent()->get_style()->width . ' ' . $this->_frame->get_parent()->get_parent()->get_style()->height . ';' . $img_width . ' ' . $img_height . '|';
     }
     $style = $this->_frame->get_style();
     $width_forced = true;
     $height_forced = true;
     //own style auto or invalid value: use natural size in px
     //own style value: ignore suffix text including unit, use given number as px
     //own style %: walk up parent chain until found available space in pt; fill available space
     //
     //special ignored unit: e.g. 10ex: e treated as exponent; x ignored; 10e completely invalid ->like auto
     $width = $style->width > 0 ? $style->width : 0;
     if (Helpers::is_percent($width)) {
         $t = 0.0;
         for ($f = $this->_frame->get_parent(); $f; $f = $f->get_parent()) {
             $f_style = $f->get_style();
             $t = $f_style->length_in_pt($f_style->width);
             if ($t != 0) {
                 break;
             }
         }
         $width = (double) rtrim($width, "%") * $t / 100;
         //maybe 0
     } elseif (!mb_strpos($width, 'pt')) {
         // Don't set image original size if "%" branch was 0 or size not given.
         // Otherwise aspect changed on %/auto combination for width/height
         // Resample according to px per inch
         // See also ListBulletImage::__construct
         $width = $style->length_in_pt($width);
     }
     $height = $style->height > 0 ? $style->height : 0;
     if (Helpers::is_percent($height)) {
         $t = 0.0;
         for ($f = $this->_frame->get_parent(); $f; $f = $f->get_parent()) {
             $f_style = $f->get_style();
             $t = $f_style->length_in_pt($f_style->height);
             if ($t != 0) {
                 break;
             }
         }
         $height = (double) rtrim($height, "%") * $t / 100;
         //maybe 0
     } elseif (!mb_strpos($height, 'pt')) {
         // Don't set image original size if "%" branch was 0 or size not given.
         // Otherwise aspect changed on %/auto combination for width/height
         // Resample according to px per inch
         // See also ListBulletImage::__construct
         $height = $style->length_in_pt($height);
     }
     if ($width == 0 || $height == 0) {
         // Determine the image's size. Time consuming. Only when really needed!
         list($img_width, $img_height) = Helpers::dompdf_getimagesize($this->_frame->get_image_url(), $this->get_dompdf()->getHttpContext());
         // don't treat 0 as error. Can be downscaled or can be catched elsewhere if image not readable.
         // Resample according to px per inch
         // See also ListBulletImage::__construct
         if ($width == 0 && $height == 0) {
             $dpi = $this->_frame->get_dompdf()->getOptions()->getDpi();
             $width = (double) ($img_width * 72) / $dpi;
             $height = (double) ($img_height * 72) / $dpi;
             $width_forced = false;
             $height_forced = false;
         } elseif ($height == 0 && $width != 0) {
             $height_forced = false;
             $height = $width / $img_width * $img_height;
             //keep aspect ratio
         } elseif ($width == 0 && $height != 0) {
             $width_forced = false;
             $width = $height / $img_height * $img_width;
             //keep aspect ratio
         }
     }
     // Handle min/max width/height
     if ($style->min_width !== "none" || $style->max_width !== "none" || $style->min_height !== "none" || $style->max_height !== "none") {
         list(, , $w, $h) = $this->_frame->get_containing_block();
         $min_width = $style->length_in_pt($style->min_width, $w);
         $max_width = $style->length_in_pt($style->max_width, $w);
         $min_height = $style->length_in_pt($style->min_height, $h);
         $max_height = $style->length_in_pt($style->max_height, $h);
         if ($max_width !== "none" && $width > $max_width) {
             if (!$height_forced) {
                 $height *= $max_width / $width;
             }
             $width = $max_width;
         }
         if ($min_width !== "none" && $width < $min_width) {
             if (!$height_forced) {
                 $height *= $min_width / $width;
             }
             $width = $min_width;
         }
         if ($max_height !== "none" && $height > $max_height) {
             if (!$width_forced) {
                 $width *= $max_height / $height;
             }
             $height = $max_height;
         }
         if ($min_height !== "none" && $height < $min_height) {
             if (!$width_forced) {
                 $width *= $min_height / $height;
             }
             $height = $min_height;
         }
     }
     if ($this->get_dompdf()->getOptions()->getDebugPng()) {
         print $width . ' ' . $height . ';';
     }
     $style->width = $width . "pt";
     $style->height = $height . "pt";
     $style->min_width = "none";
     $style->max_width = "none";
     $style->min_height = "none";
     $style->max_height = "none";
     return array($width, $width, "min" => $width, "max" => $width);
 }
Ejemplo n.º 9
0
 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"))) {
                 $href = Helpers::build_url($this->_dompdf->getProtocol(), $this->_dompdf->getBaseHost(), $this->_dompdf->getBasePath(), $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 ($this->_dompdf->get_option("debugLayout") && $this->_dompdf->get_option("debugLayoutInline")) {
             $this->_debug_layout($child->get_border_box(), "blue");
             if ($this->_dompdf->get_option("debugLayoutPaddingBox")) {
                 $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");
     }
     //    Helpers::var_dump(get_class($frame->get_next_sibling()));
     //    $last_row = get_class($frame->get_next_sibling()) !== 'Inline';
     // 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")) {
             $href = Helpers::build_url($this->_dompdf->getProtocol(), $this->_dompdf->getBaseHost(), $this->_dompdf->getBasePath(), $href);
             $this->_canvas->add_link($href, $x, $y, $w, $h);
         }
     }
 }
Ejemplo n.º 10
0
 /**
  * Add a link to the pdf
  *
  * @param string $url The url to link to
  * @param float $x The x position of the link
  * @param float $y The y position of the link
  * @param float $width The width of the link
  * @param float $height The height of the link
  */
 function add_link($url, $x, $y, $width, $height)
 {
     $y = $this->y($y) - $height;
     if (strpos($url, '#') === 0) {
         // Local link
         $name = substr($url, 1);
         if ($name) {
             $this->_pdf->create_annotation($x, $y, $x + $width, $y + $height, 'Link', "contents={$url} destname=" . substr($url, 1) . " linewidth=0");
         }
     } else {
         list($proto, $host, $path, $file) = Helpers::explode_url($url);
         if ($proto == "" || $proto === "file://") {
             return;
         }
         // Local links are not allowed
         $url = Helpers::build_url($proto, $host, $path, $file);
         $url = '{' . rawurldecode($url) . '}';
         $action = $this->_pdf->create_action("URI", "url=" . $url);
         $this->_pdf->create_annotation($x, $y, $x + $width, $y + $height, 'Link', "contents={$url} action={activate={$action}} linewidth=0");
     }
 }
Ejemplo n.º 11
0
 function image($img, $x, $y, $w, $h, $resolution = "normal")
 {
     list($width, $height, $type) = Helpers::dompdf_getimagesize($img);
     $debug_png = $this->_dompdf->get_option("debug_png");
     if ($debug_png) {
         print "[image:{$img}|{$width}|{$height}|{$type}]";
     }
     switch ($type) {
         case "jpeg":
             if ($debug_png) {
                 print '!!!jpg!!!';
             }
             $this->_pdf->addJpegFromFile($img, $x, $this->y($y) - $h, $w, $h);
             break;
         case "gif":
         case "bmp":
             if ($debug_png) {
                 print '!!!bmp or gif!!!';
             }
             // @todo use cache for BMP and GIF
             $img = $this->_convert_gif_bmp_to_png($img, $type);
         case "png":
             if ($debug_png) {
                 print '!!!png!!!';
             }
             $this->_pdf->addPngFromFile($img, $x, $this->y($y) - $h, $w, $h);
             break;
         case "svg":
             if ($debug_png) {
                 print '!!!SVG!!!';
             }
             $this->_pdf->addSvgFromFile($img, $x, $this->y($y) - $h, $w, $h);
             break;
         default:
             if ($debug_png) {
                 print '!!!unknown!!!';
             }
     }
 }
Ejemplo n.º 12
0
 /**
  * Check if $frame will fit on the page.  If the frame does not fit,
  * the frame tree is modified so that a page break occurs in the
  * correct location.
  *
  * @param Frame $frame the frame to check
  *
  * @return Frame the frame following the page break
  */
 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) {
         $max_y += $p->get_style()->computed_bottom_spacing();
         $p = $p->get_parent();
     }
     // Check if $frame flows off the page
     if ($max_y <= $this->_bottom_page_margin) {
         // no: do nothing
         return false;
     }
     Helpers::dompdf_debug("page-break", "check_page_break");
     Helpers::dompdf_debug("page-break", "in_table: " . $this->_in_table);
     // yes: determine page break location
     $iter = $frame;
     $flg = false;
     $in_table = $this->_in_table;
     Helpers::dompdf_debug("page-break", "Starting search");
     while ($iter) {
         // echo "\nbacktrack: " .$iter->get_node()->nodeName ." ".spl_object_hash($iter->get_node()). "";
         if ($iter === $this) {
             Helpers::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)) {
             Helpers::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())) {
             Helpers::dompdf_debug("page-break", "following last child.");
             if ($next->is_table()) {
                 $this->_in_table++;
             }
             $iter = $next;
             continue;
         }
         if ($next = $iter->get_prev_sibling()) {
             Helpers::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()) {
             Helpers::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.
     Helpers::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) {
         $iter = $frame;
         while ($iter && $iter->get_style()->display !== "table-row" && $iter->get_style()->display !== 'table-row-group') {
             $iter = $iter->get_parent();
         }
         $iter->split(null, true);
     } else {
         $frame->split(null, true);
     }
     $this->_page_full = true;
     $frame->_already_pushed = true;
     return true;
 }
Ejemplo n.º 13
0
 /**
  * Writes the output buffer in the log file
  *
  * @return void
  */
 private function write_log()
 {
     $log_output_file = $this->get_option("log_output_file");
     if (!$log_output_file || !is_writable($log_output_file)) {
         return;
     }
     $frames = Frame::$ID_COUNTER;
     $memory = Helpers::DOMPDF_memory_usage() / 1024;
     $time = (microtime(true) - $this->startTime) * 1000;
     $out = sprintf("<span style='color: #000' title='Frames'>%6d</span>" . "<span style='color: #009' title='Memory'>%10.2f KB</span>" . "<span style='color: #900' title='Time'>%10.2f ms</span>" . "<span  title='Quirksmode'>  " . ($this->quirksmode ? "<span style='color: #d00'> ON</span>" : "<span style='color: #0d0'>OFF</span>") . "</span><br />", $frames, $memory, $time);
     $out .= ob_get_clean();
     $log_output_file = $this->get_option("log_output_file");
     file_put_contents($log_output_file, $out);
 }
Ejemplo n.º 14
0
 /**
  * Credit goes to mgutt
  * http://www.programmierer-forum.de/function-imagecreatefrombmp-welche-variante-laeuft-t143137.htm
  * Modified by Fabien Menager to support RGB555 BMP format
  */
 function imagecreatefrombmp($filename)
 {
     if (!function_exists("imagecreatetruecolor")) {
         trigger_error("The PHP GD extension is required, but is not installed.", E_ERROR);
         return false;
     }
     // version 1.00
     if (!($fh = fopen($filename, 'rb'))) {
         trigger_error('imagecreatefrombmp: Can not open ' . $filename, E_USER_WARNING);
         return false;
     }
     $bytes_read = 0;
     // read file header
     $meta = unpack('vtype/Vfilesize/Vreserved/Voffset', fread($fh, 14));
     // check for bitmap
     if ($meta['type'] != 19778) {
         trigger_error('imagecreatefrombmp: ' . $filename . ' is not a bitmap!', E_USER_WARNING);
         return false;
     }
     // read image header
     $meta += unpack('Vheadersize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vcolors/Vimportant', fread($fh, 40));
     $bytes_read += 40;
     // read additional bitfield header
     if ($meta['compression'] == 3) {
         $meta += unpack('VrMask/VgMask/VbMask', fread($fh, 12));
         $bytes_read += 12;
     }
     // set bytes and padding
     $meta['bytes'] = $meta['bits'] / 8;
     $meta['decal'] = 4 - 4 * ($meta['width'] * $meta['bytes'] / 4 - floor($meta['width'] * $meta['bytes'] / 4));
     if ($meta['decal'] == 4) {
         $meta['decal'] = 0;
     }
     // obtain imagesize
     if ($meta['imagesize'] < 1) {
         $meta['imagesize'] = $meta['filesize'] - $meta['offset'];
         // in rare cases filesize is equal to offset so we need to read physical size
         if ($meta['imagesize'] < 1) {
             $meta['imagesize'] = @filesize($filename) - $meta['offset'];
             if ($meta['imagesize'] < 1) {
                 trigger_error('imagecreatefrombmp: Can not obtain filesize of ' . $filename . '!', E_USER_WARNING);
                 return false;
             }
         }
     }
     // calculate colors
     $meta['colors'] = !$meta['colors'] ? pow(2, $meta['bits']) : $meta['colors'];
     // read color palette
     $palette = array();
     if ($meta['bits'] < 16) {
         $palette = unpack('l' . $meta['colors'], fread($fh, $meta['colors'] * 4));
         // in rare cases the color value is signed
         if ($palette[1] < 0) {
             foreach ($palette as $i => $color) {
                 $palette[$i] = $color + 16777216;
             }
         }
     }
     // ignore extra bitmap headers
     if ($meta['headersize'] > $bytes_read) {
         fread($fh, $meta['headersize'] - $bytes_read);
     }
     // create gd image
     $im = imagecreatetruecolor($meta['width'], $meta['height']);
     $data = fread($fh, $meta['imagesize']);
     // uncompress data
     switch ($meta['compression']) {
         case 1:
             $data = Helpers::rle8_decode($data, $meta['width']);
             break;
         case 2:
             $data = Helpers::rle4_decode($data, $meta['width']);
             break;
     }
     $p = 0;
     $vide = chr(0);
     $y = $meta['height'] - 1;
     $error = 'imagecreatefrombmp: ' . $filename . ' has not enough data!';
     // loop through the image data beginning with the lower left corner
     while ($y >= 0) {
         $x = 0;
         while ($x < $meta['width']) {
             switch ($meta['bits']) {
                 case 32:
                 case 24:
                     if (!($part = substr($data, $p, 3))) {
                         trigger_error($error, E_USER_WARNING);
                         return $im;
                     }
                     $color = unpack('V', $part . $vide);
                     break;
                 case 16:
                     if (!($part = substr($data, $p, 2))) {
                         trigger_error($error, E_USER_WARNING);
                         return $im;
                     }
                     $color = unpack('v', $part);
                     if (empty($meta['rMask']) || $meta['rMask'] != 0xf800) {
                         $color[1] = (($color[1] & 0x7c00) >> 7) * 65536 + (($color[1] & 0x3e0) >> 2) * 256 + (($color[1] & 0x1f) << 3);
                         // 555
                     } else {
                         $color[1] = (($color[1] & 0xf800) >> 8) * 65536 + (($color[1] & 0x7e0) >> 3) * 256 + (($color[1] & 0x1f) << 3);
                         // 565
                     }
                     break;
                 case 8:
                     $color = unpack('n', $vide . substr($data, $p, 1));
                     $color[1] = $palette[$color[1] + 1];
                     break;
                 case 4:
                     $color = unpack('n', $vide . substr($data, floor($p), 1));
                     $color[1] = $p * 2 % 2 == 0 ? $color[1] >> 4 : $color[1] & 0xf;
                     $color[1] = $palette[$color[1] + 1];
                     break;
                 case 1:
                     $color = unpack('n', $vide . substr($data, floor($p), 1));
                     switch ($p * 8 % 8) {
                         case 0:
                             $color[1] = $color[1] >> 7;
                             break;
                         case 1:
                             $color[1] = ($color[1] & 0x40) >> 6;
                             break;
                         case 2:
                             $color[1] = ($color[1] & 0x20) >> 5;
                             break;
                         case 3:
                             $color[1] = ($color[1] & 0x10) >> 4;
                             break;
                         case 4:
                             $color[1] = ($color[1] & 0x8) >> 3;
                             break;
                         case 5:
                             $color[1] = ($color[1] & 0x4) >> 2;
                             break;
                         case 6:
                             $color[1] = ($color[1] & 0x2) >> 1;
                             break;
                         case 7:
                             $color[1] = $color[1] & 0x1;
                             break;
                     }
                     $color[1] = $palette[$color[1] + 1];
                     break;
                 default:
                     trigger_error('imagecreatefrombmp: ' . $filename . ' has ' . $meta['bits'] . ' bits and this is not supported!', E_USER_WARNING);
                     return false;
             }
             imagesetpixel($im, $x, $y, $color[1]);
             $x++;
             $p += $meta['bytes'];
         }
         $y--;
         $p += $meta['decal'];
     }
     fclose($fh);
     return $im;
 }
Ejemplo n.º 15
0
 /**
  * @param array $style
  * @param string $remoteFile
  * @param resource $context
  * @return bool
  */
 public function registerFont($style, $remoteFile, $context = null)
 {
     $fontDir = $this->getOptions()->getFontDir();
     $fontname = mb_strtolower($style["family"]);
     $families = $this->getFontFamilies();
     $entry = array();
     if (isset($families[$fontname])) {
         $entry = $families[$fontname];
     }
     $localFile = $fontDir . DIRECTORY_SEPARATOR . md5($remoteFile);
     $localTempFile = $this->options->get('tempDir') . "/" . md5($remoteFile);
     $cacheEntry = $localFile;
     $localFile .= "." . strtolower(pathinfo($remoteFile, PATHINFO_EXTENSION));
     $styleString = $this->getType("{$style['weight']} {$style['style']}");
     if (!isset($entry[$styleString])) {
         $entry[$styleString] = $cacheEntry;
         // Download the remote file
         $remoteFileContent = @Helpers::getFileContent($remoteFile, null, $context);
         if (false === $remoteFileContent) {
             return false;
         }
         file_put_contents($localTempFile, $remoteFileContent);
         $font = Font::load($localTempFile);
         if (!$font) {
             unlink($localTempFile);
             return false;
         }
         $font->parse();
         $font->saveAdobeFontMetrics("{$cacheEntry}.ufm");
         $font->close();
         if (file_exists($localTempFile)) {
             unlink($localTempFile);
         }
         if (!file_exists("{$cacheEntry}.ufm")) {
             return false;
         }
         // Save the changes
         file_put_contents($localFile, $remoteFileContent);
         if (!file_exists($localFile)) {
             unlink("{$cacheEntry}.ufm");
             return false;
         }
         $this->setFontFamily($fontname, $entry);
         $this->saveFontFamilies();
     }
     return true;
 }
Ejemplo n.º 16
0
 static function detect_type($file)
 {
     list(, , $type) = Helpers::dompdf_getimagesize($file);
     return $type;
 }
Ejemplo n.º 17
0
 /**
  * parse @font-face{} sections
  * http://www.w3.org/TR/css3-fonts/#the-font-face-rule
  *
  * @param string $str CSS @font-face rules
  * @return Style
  */
 private function _parse_font_face($str)
 {
     $descriptors = $this->_parse_properties($str);
     preg_match_all("/(url|local)\\s*\\([\"\\']?([^\"\\'\\)]+)[\"\\']?\\)\\s*(format\\s*\\([\"\\']?([^\"\\'\\)]+)[\"\\']?\\))?/i", $descriptors->src, $src);
     $sources = array();
     $valid_sources = array();
     foreach ($src[0] as $i => $value) {
         $source = array("local" => strtolower($src[1][$i]) === "local", "uri" => $src[2][$i], "format" => $src[4][$i], "path" => Helpers::build_url($this->_protocol, $this->_base_host, $this->_base_path, $src[2][$i]));
         if (!$source["local"] && in_array($source["format"], array("", "woff", "opentype", "truetype"))) {
             $valid_sources[] = $source;
         }
         $sources[] = $source;
     }
     // No valid sources
     if (empty($valid_sources)) {
         return;
     }
     $style = array("family" => $descriptors->get_font_family_raw(), "weight" => $descriptors->font_weight, "style" => $descriptors->font_style);
     $this->getFontMetrics()->registerFont($style, $valid_sources[0]["path"]);
 }
Ejemplo n.º 18
0
 /**
  * @return string
  */
 public function __toString()
 {
     // Skip empty text frames
     //     if ( $this->is_text_node() &&
     //          preg_replace("/\s/", "", $this->_node->data) === "" )
     //       return "";
     $str = "<b>" . $this->_node->nodeName . ":</b><br/>";
     //$str .= spl_object_hash($this->_node) . "<br/>";
     $str .= "Id: " . $this->get_id() . "<br/>";
     $str .= "Class: " . get_class($this) . "<br/>";
     if ($this->is_text_node()) {
         $tmp = htmlspecialchars($this->_node->nodeValue);
         $str .= "<pre>'" . mb_substr($tmp, 0, 70) . (mb_strlen($tmp) > 70 ? "..." : "") . "'</pre>";
     } elseif ($css_class = $this->_node->getAttribute("class")) {
         $str .= "CSS class: '{$css_class}'<br/>";
     }
     if ($this->_parent) {
         $str .= "\nParent:" . $this->_parent->_node->nodeName . " (" . spl_object_hash($this->_parent->_node) . ") " . "<br/>";
     }
     if ($this->_prev_sibling) {
         $str .= "Prev: " . $this->_prev_sibling->_node->nodeName . " (" . spl_object_hash($this->_prev_sibling->_node) . ") " . "<br/>";
     }
     if ($this->_next_sibling) {
         $str .= "Next: " . $this->_next_sibling->_node->nodeName . " (" . spl_object_hash($this->_next_sibling->_node) . ") " . "<br/>";
     }
     $d = $this->get_decorator();
     while ($d && $d != $d->get_decorator()) {
         $str .= "Decorator: " . get_class($d) . "<br/>";
         $d = $d->get_decorator();
     }
     $str .= "Position: " . Helpers::pre_r($this->_position, true);
     $str .= "\nContaining block: " . Helpers::pre_r($this->_containing_block, true);
     $str .= "\nMargin width: " . Helpers::pre_r($this->get_margin_width(), true);
     $str .= "\nMargin height: " . Helpers::pre_r($this->get_margin_height(), true);
     $str .= "\nStyle: <pre>" . $this->_style->__toString() . "</pre>";
     if ($this->_decorator instanceof FrameDecorator\Block) {
         $str .= "Lines:<pre>";
         foreach ($this->_decorator->get_line_boxes() as $line) {
             foreach ($line->get_frames() as $frame) {
                 if ($frame instanceof FrameDecorator\Text) {
                     $str .= "\ntext: ";
                     $str .= "'" . htmlspecialchars($frame->get_text()) . "'";
                 } else {
                     $str .= "\nBlock: " . $frame->get_node()->nodeName . " (" . spl_object_hash($frame->get_node()) . ")";
                 }
             }
             $str .= "\ny => " . $line->y . "\n" . "w => " . $line->w . "\n" . "h => " . $line->h . "\n" . "left => " . $line->left . "\n" . "right => " . $line->right . "\n";
         }
         $str .= "</pre>";
     }
     $str .= "\n";
     if (php_sapi_name() === "cli") {
         $str = strip_tags(str_replace(array("<br/>", "<b>", "</b>"), array("\n", "", ""), $str));
     }
     return $str;
 }
Ejemplo n.º 19
0
 protected function _image($val)
 {
     $DEBUGCSS = $this->_stylesheet->get_dompdf()->getOptions()->getDebugCss();
     $parsed_url = "none";
     if (mb_strpos($val, "url") === false) {
         $path = "none";
         //Don't resolve no image -> otherwise would prefix path and no longer recognize as none
     } else {
         $val = preg_replace("/url\\(['\"]?([^'\")]+)['\"]?\\)/", "\\1", trim($val));
         // Resolve the url now in the context of the current stylesheet
         $parsed_url = Helpers::explode_url($val);
         if ($parsed_url["protocol"] == "" && $this->_stylesheet->get_protocol() == "") {
             if ($parsed_url["path"][0] === '/' || $parsed_url["path"][0] === '\\') {
                 $path = $_SERVER["DOCUMENT_ROOT"] . '/';
             } else {
                 $path = $this->_stylesheet->get_base_path();
             }
             $path .= $parsed_url["path"] . $parsed_url["file"];
             $path = realpath($path);
             // If realpath returns FALSE then specifically state that there is no background image
             if (!$path) {
                 $path = 'none';
             }
         } else {
             $path = Helpers::build_url($this->_stylesheet->get_protocol(), $this->_stylesheet->get_host(), $this->_stylesheet->get_base_path(), $val);
         }
     }
     if ($DEBUGCSS) {
         print "<pre>[_image\n";
         print_r($parsed_url);
         print $this->_stylesheet->get_protocol() . "\n" . $this->_stylesheet->get_base_path() . "\n" . $path . "\n";
         print "_image]</pre>";
     }
     return $path;
 }
 function counter_value($id = self::DEFAULT_COUNTER, $type = "decimal")
 {
     $type = mb_strtolower($type);
     if (!isset($this->_counters[$id])) {
         $this->_counters[$id] = 0;
     }
     $value = $this->_counters[$id];
     switch ($type) {
         default:
         case "decimal":
             return $value;
         case "decimal-leading-zero":
             return str_pad($value, 2, "0", STR_PAD_LEFT);
         case "lower-roman":
             return Helpers::dec2roman($value);
         case "upper-roman":
             return mb_strtoupper(Helpers::dec2roman($value));
         case "lower-latin":
         case "lower-alpha":
             return chr($value % 26 + ord('a') - 1);
         case "upper-latin":
         case "upper-alpha":
             return chr($value % 26 + ord('A') - 1);
         case "lower-greek":
             return Helpers::unichr($value + 944);
         case "upper-greek":
             return Helpers::unichr($value + 912);
     }
 }
Ejemplo n.º 21
0
 /**
  * Allocate a new color.  Allocate with GD as needed and store
  * previously allocated colors in $this->_colors.
  *
  * @param array $color The new current color
  * @return int           The allocated color
  */
 private function _allocate_color($color)
 {
     if (isset($color["c"])) {
         $color = Helpers::cmyk_to_rgb($color);
     }
     // Full opacity if no alpha set
     if (!isset($color[3])) {
         $color[3] = 0;
     }
     list($r, $g, $b, $a) = $color;
     $r *= 255;
     $g *= 255;
     $b *= 255;
     $a *= 127;
     // Clip values
     $r = $r > 255 ? 255 : $r;
     $g = $g > 255 ? 255 : $g;
     $b = $b > 255 ? 255 : $b;
     $a = $a > 127 ? 127 : $a;
     $r = $r < 0 ? 0 : $r;
     $g = $g < 0 ? 0 : $g;
     $b = $b < 0 ? 0 : $b;
     $a = $a < 0 ? 0 : $a;
     $key = sprintf("#%02X%02X%02X%02X", $r, $g, $b, $a);
     if (isset($this->_colors[$key])) {
         return $this->_colors[$key];
     }
     if ($a != 0) {
         $this->_colors[$key] = imagecolorallocatealpha($this->get_image(), $r, $g, $b, $a);
     } else {
         $this->_colors[$key] = imagecolorallocate($this->get_image(), $r, $g, $b);
     }
     return $this->_colors[$key];
 }
Ejemplo n.º 22
0
 /**
  * Used for debugging:
  *
  * @return string
  */
 public function __toString()
 {
     $str = "";
     $str .= "Columns:<br/>";
     $str .= Helpers::pre_r($this->_columns, true);
     $str .= "Rows:<br/>";
     $str .= Helpers::pre_r($this->_rows, true);
     $str .= "Frames:<br/>";
     $arr = array();
     foreach ($this->_frames as $key => $val) {
         $arr[$key] = array("columns" => $val["columns"], "rows" => $val["rows"]);
     }
     $str .= Helpers::pre_r($arr, true);
     if (php_sapi_name() == "cli") {
         $str = strip_tags(str_replace(array("<br/>", "<b>", "</b>"), array("\n", chr(27) . "[01;33m", chr(27) . "[0m"), $str));
     }
     return $str;
 }
Ejemplo n.º 23
0
 static function detect_type($file, $context = null)
 {
     list(, , $type) = Helpers::dompdf_getimagesize($file, $context);
     return $type;
 }
Ejemplo n.º 24
0
 /**
  * Parses a CSS string containing quotes and escaped hex characters
  *
  * @param $string string The CSS string to parse
  * @param $single_trim
  * @return string
  */
 protected function _parse_string($string, $single_trim = false)
 {
     if ($single_trim) {
         $string = preg_replace('/^[\\"\']/', "", $string);
         $string = preg_replace('/[\\"\']$/', "", $string);
     } else {
         $string = trim($string, "'\"");
     }
     $string = str_replace(array("\\\n", '\\"', "\\'"), array("", '"', "'"), $string);
     // Convert escaped hex characters into ascii characters (e.g. \A => newline)
     $string = preg_replace_callback("/\\\\([0-9a-fA-F]{0,6})/", function ($matches) {
         return \Dompdf\Helpers::unichr(hexdec($matches[1]));
     }, $string);
     return $string;
 }