function pdf_create($html, $filename, $stream = TRUE)
 {
     $dompdf = new DOMPDF();
     $dompdf->set_paper("A4");
     $dompdf->load_html($html);
     $dompdf->render();
     $canvas = $dompdf->get_canvas();
     // get height and width of page
     $w = $canvas->get_width();
     $h = $canvas->get_height();
     // get font
     $font = Font_Metrics::get_font("helvetica", "normal");
     $txtHeight = Font_Metrics::get_font_height($font, 7);
     //draw line for signature manager
     $mnline = $h - 10 * $txtHeight - 24;
     $colormn = array(0, 0, 0);
     $canvas->line(20, $mnline, $w - 470, $mnline, $colormn, 1);
     //text for signature Requestor/HOD
     $textmn = "Requestor/HOD";
     $widthmn = Font_Metrics::get_text_width($textmn, $font, 12);
     $canvas->text($w - $widthmn - 480, $mnline, $textmn, $font, 12);
     // draw a line along the bottom
     $y = $h - 2 * $txtHeight - 24;
     $color = array(0, 0, 0);
     $canvas->line(16, $y, $w - 16, $y, $color, 1);
     //draw line for GM/Manager
     //$canvas->line(270, $mnline, $w - 240, $mnline, $colormn, 1);
     $canvas->line(330, $mnline, $w - 170, $mnline, $colormn, 1);
     $texthr = "GM/Manager";
     $widthhr = Font_Metrics::get_text_width($texthr, $font, 12);
     $canvas->text($w - $widthmn - 160, $mnline, $texthr, $font, 12);
     //draw line for HR
     //$canvas->line(270, $mnline, $w - 240, $mnline, $colormn, 1);
     $canvas->line(180, $mnline, $w - 310, $mnline, $colormn, 1);
     $texthr = "HR";
     $widthhr = Font_Metrics::get_text_width($texthr, $font, 12);
     $canvas->text($w - $widthmn - 325, $mnline, $texthr, $font, 12);
     //draw line for IT Officer
     $canvas->line(470, $mnline, $w - 20, $mnline, $colormn, 1);
     $textIT = "IT Officer";
     $canvas->text($w - $widthmn - 30, $mnline, $textIT, $font, 12);
     // set page number on the left side
     //$canvas->page_text(16, $y, "Page: {PAGE_NUM} of {PAGE_COUNT}", $font, 8, $color);
     $canvas->page_text($w - 324, $y, "Page: {PAGE_NUM} of {PAGE_COUNT}", $font, 8, $color);
     // set additional text
     $text = "ESRNL PORTAL";
     $width = Font_Metrics::get_text_width($text, $font, 8);
     $canvas->text($w - $width - 16, $y, $text, $font, 8);
     if ($stream) {
         $dompdf->stream($filename . ".pdf");
     } else {
         $CI =& get_instance();
         $CI->load->helper('file');
         write_file($filename, $dompdf->output());
     }
 }
 function recalculate_width()
 {
     $style = $this->get_style();
     $text = $this->get_text();
     $size = $style->font_size;
     $font = $style->font_family;
     $word_spacing = $style->length_in_pt($style->word_spacing);
     $char_spacing = $style->length_in_pt($style->letter_spacing);
     return $style->width = Font_Metrics::get_text_width($text, $font, $size, $word_spacing, $char_spacing);
 }
 /**
  * Class constructor
  *
  * @param Frame  $frame  the frame to decorate
  * @param DOMPDF $dompdf the document's dompdf object (required to resolve relative & remote urls)
  */
 function __construct(Frame $frame, DOMPDF $dompdf)
 {
     parent::__construct($frame, $dompdf);
     $url = $frame->get_node()->getAttribute("src");
     $debug_png = $dompdf->get_option("debug_png");
     if ($debug_png) {
         print '[__construct ' . $url . ']';
     }
     list($this->_image_url, , $this->_image_msg) = Image_Cache::resolve_url($url, $dompdf->get_protocol(), $dompdf->get_host(), $dompdf->get_base_path(), $dompdf);
     if (Image_Cache::is_broken($this->_image_url) && ($alt = $frame->get_node()->getAttribute("alt"))) {
         $style = $frame->get_style();
         $style->width = 4 / 3 * Font_Metrics::get_text_width($alt, $style->font_family, $style->font_size, $style->word_spacing);
         $style->height = Font_Metrics::get_font_height($style->font_family, $style->font_size);
     }
 }
 /**
  * Class constructor
  *
  * @param Frame $frame the frame to decorate
  * @param DOMPDF $dompdf the document's dompdf object (required to resolve relative & remote urls)
  */
 function __construct(Frame $frame, DOMPDF $dompdf)
 {
     global $_dompdf_warnings;
     parent::__construct($frame, $dompdf);
     $url = $frame->get_node()->getAttribute("src");
     //debugpng
     if (DEBUGPNG) {
         print '[__construct ' . $url . ']';
     }
     list($this->_image_url, $this->_image_ext) = Image_Cache::resolve_url($url, $dompdf->get_protocol(), $dompdf->get_host(), $dompdf->get_base_path());
     if (strrpos($this->_image_url, DOMPDF_LIB_DIR . "/res/broken_image.png", 0) !== false && ($alt = $frame->get_node()->getAttribute("alt"))) {
         $style = $frame->get_style();
         $style->width = 4 / 3 * Font_Metrics::get_text_width($alt, $style->font_family, $style->font_size, $style->word_spacing);
         $style->height = Font_Metrics::get_font_height($style->font_family, $style->font_size);
     }
 }
    /**
     * Class constructor
     *
     * @param Frame $frame the frame to decorate
     * @param DOMPDF $dompdf the document's dompdf object (required to resolve relative & remote urls)
     */
    function __construct(Frame $frame, DOMPDF $dompdf)
    {
        global $_dompdf_warnings;

        parent::__construct($frame, $dompdf);
        $url = $frame->get_node()->getAttribute("src");

        //debugpng
        if (DEBUGPNG) print '[__construct ' . $url . ']';

        list($this->_image_url, $type, $this->_image_msg) = Image_Cache::resolve_url($url,
            $dompdf->get_protocol(),
            $dompdf->get_host(),
            $dompdf->get_base_path());

        if (Image_Cache::is_broken($this->_image_url) &&
            $alt = $frame->get_node()->getAttribute("alt")
        ) {
            $style = $frame->get_style();
            $style->width = (4 / 3) * Font_Metrics::get_text_width($alt, $style->font_family, $style->font_size, $style->word_spacing);
            $style->height = Font_Metrics::get_font_height($style->font_family, $style->font_size);
        }
    }
 /**
  * Adjust the justification of each of our lines.
  * http://www.w3.org/TR/CSS21/text.html#propdef-text-align
  */
 protected function _text_align()
 {
     $style = $this->_frame->get_style();
     $w = $this->_frame->get_containing_block("w");
     $width = $style->length_in_pt($style->width, $w);
     switch ($style->text_align) {
         default:
         case "left":
             foreach ($this->_frame->get_line_boxes() as $line) {
                 if (!$line->left) {
                     continue;
                 }
                 foreach ($line->get_frames() as $frame) {
                     if ($frame instanceof Block_Frame_Decorator) {
                         continue;
                     }
                     $frame->set_position($frame->get_position("x") + $line->left);
                 }
             }
             return;
         case "right":
             foreach ($this->_frame->get_line_boxes() as $line) {
                 // Move each child over by $dx
                 $dx = $width - $line->w - $line->right;
                 foreach ($line->get_frames() as $frame) {
                     // Block frames are not aligned by text-align
                     if ($frame instanceof Block_Frame_Decorator) {
                         continue;
                     }
                     $frame->set_position($frame->get_position("x") + $dx);
                 }
             }
             break;
         case "justify":
             // We justify all lines except the last one
             $lines = $this->_frame->get_line_boxes();
             // needs to be a variable (strict standards)
             $lines = array_splice($lines, 0, -1);
             foreach ($lines as $i => $line) {
                 if ($line->br) {
                     unset($lines[$i]);
                 }
             }
             // One space character's width. Will be used to get a more accurate spacing
             $space_width = Font_Metrics::get_text_width(" ", $style->font_family, $style->font_size);
             foreach ($lines as $i => $line) {
                 if ($line->left) {
                     foreach ($line->get_frames() as $frame) {
                         if (!$frame instanceof Text_Frame_Decorator) {
                             continue;
                         }
                         $frame->set_position($frame->get_position("x") + $line->left);
                     }
                 }
                 // Only set the spacing if the line is long enough.  This is really
                 // just an aesthetic choice ;)
                 //if ( $line["left"] + $line["w"] + $line["right"] > self::MIN_JUSTIFY_WIDTH * $width ) {
                 // Set the spacing for each child
                 if ($line->wc > 1) {
                     $spacing = ($width - ($line->left + $line->w + $line->right) + $space_width) / ($line->wc - 1);
                 } else {
                     $spacing = 0;
                 }
                 $dx = 0;
                 foreach ($line->get_frames() as $frame) {
                     if (!$frame instanceof Text_Frame_Decorator) {
                         continue;
                     }
                     $text = $frame->get_text();
                     $spaces = mb_substr_count($text, " ");
                     $char_spacing = $style->length_in_pt($style->letter_spacing);
                     $_spacing = $spacing + $char_spacing;
                     $frame->set_position($frame->get_position("x") + $dx);
                     $frame->set_text_spacing($_spacing);
                     $dx += $spaces * $_spacing;
                 }
                 // The line (should) now occupy the entire width
                 $this->_frame->set_line($i, null, $width);
                 //}
             }
             break;
         case "center":
         case "centre":
             foreach ($this->_frame->get_line_boxes() as $line) {
                 // Centre each line by moving each frame in the line by:
                 $dx = ($width + $line->left - $line->w - $line->right) / 2;
                 foreach ($line->get_frames() as $frame) {
                     // Block frames are not aligned by text-align
                     if ($frame instanceof Block_Frame_Decorator) {
                         continue;
                     }
                     $frame->set_position($frame->get_position("x") + $dx);
                 }
             }
             break;
     }
 }
 function get_min_max_width()
 {
     $style = $this->_frame->get_style();
     $this->_block_parent = $this->_frame->find_block_parent();
     $line_width = $this->_frame->get_containing_block("w");
     $str = $text = $this->_frame->get_text();
     $size = $style->font_size;
     $font = $style->font_family;
     $word_spacing = $style->length_in_pt($style->word_spacing);
     $char_spacing = $style->length_in_pt($style->letter_spacing);
     switch ($style->white_space) {
         default:
         case "normal":
             $str = preg_replace(self::$_whitespace_pattern, " ", $str);
         case "pre-wrap":
         case "pre-line":
             // Find the longest word (i.e. minimum length)
             // This technique (using arrays & an anonymous function) is actually
             // faster than doing a single-pass character by character scan.  Heh,
             // yes I took the time to bench it ;)
             $words = array_flip(preg_split("/[\\s-]+/u", $str, -1, PREG_SPLIT_DELIM_CAPTURE));
             array_walk($words, create_function('&$val,$str', '$val = Font_Metrics::get_text_width($str, "' . addslashes($font) . '", ' . $size . ', ' . $word_spacing . ', ' . $char_spacing . ');'));
             arsort($words);
             $min = reset($words);
             break;
         case "pre":
             $lines = array_flip(preg_split("/\n/u", $str));
             array_walk($lines, create_function('&$val,$str', '$val = Font_Metrics::get_text_width($str, "' . addslashes($font) . '", ' . $size . ', ' . $word_spacing . ', ' . $char_spacing . ');'));
             arsort($lines);
             $min = reset($lines);
             break;
         case "nowrap":
             $min = Font_Metrics::get_text_width($this->_collapse_white_space($str), $font, $size, $word_spacing, $char_spacing);
             break;
     }
     switch ($style->white_space) {
         default:
         case "normal":
         case "nowrap":
             $str = preg_replace(self::$_whitespace_pattern, " ", $text);
             break;
         case "pre-line":
             //XXX: Is this correct?
             $str = preg_replace("/[ \t]+/u", " ", $text);
         case "pre-wrap":
             // Find the longest word (i.e. minimum length)
             $lines = array_flip(preg_split("/\n/", $text));
             array_walk($lines, create_function('&$val,$str', '$val = Font_Metrics::get_text_width($str, "' . $font . '", ' . $size . ', ' . $word_spacing . ', ' . $char_spacing . ');'));
             arsort($lines);
             reset($lines);
             $str = key($lines);
             break;
     }
     $max = Font_Metrics::get_text_width($str, $font, $size, $word_spacing, $char_spacing);
     $delta = $style->length_in_pt(array($style->margin_left, $style->border_left_width, $style->padding_left, $style->padding_right, $style->border_right_width, $style->margin_right), $line_width);
     $min += $delta;
     $max += $delta;
     return array($min, $max, "min" => $min, "max" => $max);
 }
Exemple #8
0
 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);
     }
     if (method_exists($this->_canvas, "get_cpdf")) {
         $cpdf = $this->_canvas->get_cpdf();
         // $cpdf_font = $cpdf->fonts[$style->font_family];
         // $base = ($cpdf_font["UnderlinePosition"]*$size)/1000;
         // $descent = (($cpdf_font["Ascender"]-$cpdf_font["Descender"])*$size)/1000;
         $fontBBox = $cpdf->fonts[$style->font_family]['FontBBox'];
         $base = $fontBBox[3] * $size / 1000 * 0.9;
         $descent = $fontBBox[1] * $size / 1000;
         // print '<pre>Text_Renderer cpdf:'.$base.' '.$descent.' '.$size.'</pre>';
     } else {
         // Descent is font part below baseline, typically negative. $height is about full height of font box.
         // $descent = -$size/6; is less accurate, depends on font family.
         // @todo Could we get font info for PDFlib adapter and others ?
         $base = $size * 1.08;
         $descent = $size - $height;
         // print '<pre>Text_Renderer other than cpdf:'.$base.' '.$descent.' '.$size.'</pre>';
     }
     // 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 + $size * (self::UNDERLINE_OFFSET - self::DECO_THICKNESS / 2);
                 break;
             case "overline":
                 $deco_y += $size * (self::OVERLINE_OFFSET + self::DECO_THICKNESS / 2);
                 break;
             case "line-through":
                 $deco_y += $base * 0.7 + $size * self::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, $size * self::DECO_THICKNESS);
     }
     if (DEBUG_LAYOUT && DEBUG_LAYOUT_LINES) {
         $text_width = Font_Metrics::get_text_width($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));
     }
 }
 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));
     // 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) = dompdf_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 "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":
                 list($x, $y) = $frame->get_position();
                 $pad = null;
                 if ($bullet_style === "decimal-leading-zero") {
                     $pad = strlen($frame->get_parent()->get_parent()->get_node()->getAttribute("dompdf-children-count"));
                 }
                 $index = $frame->get_node()->getAttribute("dompdf-counter");
                 $text = $this->make_counter($index, $bullet_style, $pad);
                 $font_family = $style->font_family;
                 $spacing = 0;
                 //$frame->get_text_spacing() + $style->word_spacing;
                 if (trim($text) == "") {
                     return;
                 }
                 $x -= Font_Metrics::get_text_width($text, $font_family, $font_size, $spacing);
                 $this->_canvas->text($x, $y, $text, $font_family, $font_size, $style->color, $spacing);
             case "none":
                 break;
         }
     }
 }
 /**
  * @param Text_Frame_Decorator $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_Adapter) {
         $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 (DEBUG_LAYOUT && DEBUG_LAYOUT_LINES) {
         $text_width = Font_Metrics::get_text_width($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));
     }
 }
 function get_min_max_width()
 {
     $frame = $this->_frame;
     $style = $frame->get_style();
     $this->_block_parent = $frame->find_block_parent();
     $line_width = $frame->get_containing_block("w");
     $str = $text = $frame->get_text();
     $size = $style->font_size;
     $font = $style->font_family;
     $word_spacing = $style->length_in_pt($style->word_spacing);
     $char_spacing = $style->length_in_pt($style->letter_spacing);
     switch ($style->white_space) {
         default:
         case "normal":
             $str = preg_replace(self::$_whitespace_pattern, " ", $str);
         case "pre-wrap":
         case "pre-line":
             $words = array_flip(preg_split("/[\\s-]+/u", $str, -1, PREG_SPLIT_DELIM_CAPTURE));
             array_walk($words, create_function('&$val,$str', '$val = Font_Metrics::get_text_width($str, "' . addslashes($font) . '", ' . $size . ', ' . $word_spacing . ', ' . $char_spacing . ');'));
             arsort($words);
             $min = reset($words);
             break;
         case "pre":
             $lines = array_flip(preg_split("/\n/u", $str));
             array_walk($lines, create_function('&$val,$str', '$val = Font_Metrics::get_text_width($str, "' . addslashes($font) . '", ' . $size . ', ' . $word_spacing . ', ' . $char_spacing . ');'));
             arsort($lines);
             $min = reset($lines);
             break;
         case "nowrap":
             $min = Font_Metrics::get_text_width($this->_collapse_white_space($str), $font, $size, $word_spacing, $char_spacing);
             break;
     }
     switch ($style->white_space) {
         default:
         case "normal":
         case "nowrap":
             $str = preg_replace(self::$_whitespace_pattern, " ", $text);
             break;
         case "pre-line":
             $str = preg_replace("/[ \t]+/u", " ", $text);
         case "pre-wrap":
             $lines = array_flip(preg_split("/\n/", $text));
             array_walk($lines, create_function('&$val,$str', '$val = Font_Metrics::get_text_width($str, "' . $font . '", ' . $size . ', ' . $word_spacing . ', ' . $char_spacing . ');'));
             arsort($lines);
             reset($lines);
             $str = key($lines);
             break;
     }
     $max = Font_Metrics::get_text_width($str, $font, $size, $word_spacing, $char_spacing);
     $delta = $style->length_in_pt(array($style->margin_left, $style->border_left_width, $style->padding_left, $style->padding_right, $style->border_right_width, $style->margin_right), $line_width);
     $min += $delta;
     $max += $delta;
     return $this->_min_max_cache = array($min, $max, "min" => $min, "max" => $max);
 }
 protected function _text_align()
 {
     $style = $this->_frame->get_style();
     $w = $this->_frame->get_containing_block("w");
     $width = $style->length_in_pt($style->width, $w);
     switch ($style->text_align) {
         default:
         case "left":
             foreach ($this->_frame->get_line_boxes() as $line) {
                 if (!$line->left) {
                     continue;
                 }
                 foreach ($line->get_frames() as $frame) {
                     if ($frame instanceof Block_Frame_Decorator) {
                         continue;
                     }
                     $frame->set_position($frame->get_position("x") + $line->left);
                 }
             }
             return;
         case "right":
             foreach ($this->_frame->get_line_boxes() as $line) {
                 $dx = $width - $line->w - $line->right;
                 foreach ($line->get_frames() as $frame) {
                     if ($frame instanceof Block_Frame_Decorator) {
                         continue;
                     }
                     $frame->set_position($frame->get_position("x") + $dx);
                 }
             }
             break;
         case "justify":
             $lines = $this->_frame->get_line_boxes();
             $lines = array_splice($lines, 0, -1);
             foreach ($lines as $i => $line) {
                 if ($line->br) {
                     unset($lines[$i]);
                 }
             }
             $space_width = Font_Metrics::get_text_width(" ", $style->font_family, $style->font_size);
             foreach ($lines as $i => $line) {
                 if ($line->left) {
                     foreach ($line->get_frames() as $frame) {
                         if (!$frame instanceof Text_Frame_Decorator) {
                             continue;
                         }
                         $frame->set_position($frame->get_position("x") + $line->left);
                     }
                 }
                 if ($line->wc > 1) {
                     $spacing = ($width - ($line->left + $line->w + $line->right) + $space_width) / ($line->wc - 1);
                 } else {
                     $spacing = 0;
                 }
                 $dx = 0;
                 foreach ($line->get_frames() as $frame) {
                     if (!$frame instanceof Text_Frame_Decorator) {
                         continue;
                     }
                     $text = $frame->get_text();
                     $spaces = mb_substr_count($text, " ");
                     $char_spacing = $style->length_in_pt($style->letter_spacing);
                     $_spacing = $spacing + $char_spacing;
                     $frame->set_position($frame->get_position("x") + $dx);
                     $frame->set_text_spacing($_spacing);
                     $dx += $spaces * $_spacing;
                 }
                 $this->_frame->set_line($i, null, $width);
             }
             break;
         case "center":
         case "centre":
             foreach ($this->_frame->get_line_boxes() as $line) {
                 $dx = ($width + $line->left - $line->w - $line->right) / 2;
                 foreach ($line->get_frames() as $frame) {
                     if ($frame instanceof Block_Frame_Decorator) {
                         continue;
                     }
                     $frame->set_position($frame->get_position("x") + $dx);
                 }
             }
             break;
     }
 }
 function set_text_spacing($spacing)
 {
     $this->_text_spacing = $spacing;
     $style = $this->_frame->get_style();
     // Re-adjust our width to account for the change in spacing
     $style->width = Font_Metrics::get_text_width($this->get_text(), $style->font_family, $style->font_size, $spacing);
 }
  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" &&
         !Image_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_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) = dompdf_getimagesize($img);
      $dpi = $this->_dompdf->get_option("dpi");
      $w = ((float)rtrim($width, "px") * 72) / $dpi;
      $h = ((float)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*(List_Bullet_Frame_Decorator::BULLET_SIZE /*-List_Bullet_Frame_Decorator::BULLET_THICKNESS*/ ))/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 "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
      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 -= Font_Metrics::get_text_width($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;
      }
    }
  }
 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));
     if ($style->list_style_image !== "none" && !Image_Cache::is_broken($img = $frame->get_image_url())) {
         list($x, $y) = $frame->get_position();
         list($width, $height) = dompdf_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;
         $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 * 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 "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":
             case "a":
             case "i":
             case "A":
             case "I":
                 $li = $frame->get_parent();
                 $pad = null;
                 if ($bullet_style === "decimal-leading-zero") {
                     $pad = strlen($li->get_parent()->get_node()->getAttribute("dompdf-children-count"));
                 }
                 $index = $frame->get_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 -= Font_Metrics::get_text_width($text, $font_family, $font_size, $spacing);
                 $line_height = $style->line_height;
                 $y += ($line_height - $font_size) / 4;
                 $this->_canvas->text($x, $y, $text, $font_family, $font_size, $style->color, $spacing);
             case "none":
                 break;
         }
     }
 }
 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;
     $this->_canvas->text($x, $y, $text, $font, $size, $style->color, $word_spacing, $char_spacing);
     $line = $frame->get_containing_line();
     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);
     }
     if (method_exists($this->_canvas, "get_cpdf")) {
         $cpdf = $this->_canvas->get_cpdf();
         $fontBBox = $cpdf->fonts[$style->font_family]['FontBBox'];
         $base = $fontBBox[3] * $size / 1000 * 0.9;
         $descent = $fontBBox[1] * $size / 1000;
     } else {
         $base = $size * 1.08;
         $descent = $size - $height;
     }
     $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;
         $color = $f->get_style()->color;
         switch ($text_deco) {
             default:
                 continue;
             case "underline":
                 $deco_y += $base - $descent + $size * (self::UNDERLINE_OFFSET - self::DECO_THICKNESS / 2);
                 break;
             case "overline":
                 $deco_y += $size * (self::OVERLINE_OFFSET + self::DECO_THICKNESS / 2);
                 break;
             case "line-through":
                 $deco_y += $base * 0.7 + $size * self::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, $size * self::DECO_THICKNESS);
     }
     if (DEBUG_LAYOUT && DEBUG_LAYOUT_LINES) {
         $text_width = Font_Metrics::get_text_width($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));
     }
 }