protected static function _resolve_target($node, $target, $value)
 {
     if ($target[0] === "!") {
         $func = "_" . m_mb_substr($target, 1);
         return self::$func($node, $value);
     }
     return $value ? sprintf($target, $value) : "";
 }
 static function getArray($colour)
 {
     $c = array(null, null, null, null, "hex" => null);
     if (is_array($colour)) {
         $c = $colour;
         $c["c"] = $c[0];
         $c["m"] = $c[1];
         $c["y"] = $c[2];
         $c["k"] = $c[3];
         $c["hex"] = "cmyk({$c['0']},{$c['1']},{$c['2']},{$c['3']})";
     } else {
         $c[0] = hexdec(m_mb_substr($colour, 0, 2)) / 0xff;
         $c[1] = hexdec(m_mb_substr($colour, 2, 2)) / 0xff;
         $c[2] = hexdec(m_mb_substr($colour, 4, 2)) / 0xff;
         $c["r"] = $c[0];
         $c["g"] = $c[1];
         $c["b"] = $c[2];
         $c["hex"] = "#{$colour}";
     }
     return $c;
 }
 protected function _layout_line()
 {
     $frame = $this->_frame;
     $style = $frame->get_style();
     $text = $frame->get_text();
     $size = $style->font_size;
     $font = $style->font_family;
     $style->height = Font_Metrics::get_font_height($font, $size);
     $split = false;
     $add_line = false;
     switch (strtolower($style->text_transform)) {
         default:
             break;
         case "capitalize":
             $text = mb_convert_case($text, MB_CASE_TITLE);
             break;
         case "uppercase":
             $text = mb_convert_case($text, MB_CASE_UPPER);
             break;
         case "lowercase":
             $text = mb_convert_case($text, MB_CASE_LOWER);
             break;
     }
     switch ($style->white_space) {
         default:
         case "normal":
             $frame->set_text($text = $this->_collapse_white_space($text));
             if ($text == "") {
                 break;
             }
             $split = $this->_line_break($text);
             break;
         case "pre":
             $split = $this->_newline_break($text);
             $add_line = $split !== false;
             break;
         case "nowrap":
             $frame->set_text($text = $this->_collapse_white_space($text));
             break;
         case "pre-wrap":
             $split = $this->_newline_break($text);
             if (($tmp = $this->_line_break($text)) !== false) {
                 $add_line = $split < $tmp;
                 $split = min($tmp, $split);
             } else {
                 $add_line = true;
             }
             break;
         case "pre-line":
             $frame->set_text($text = preg_replace("/[ \t]+/u", " ", $text));
             if ($text == "") {
                 break;
             }
             $split = $this->_newline_break($text);
             if (($tmp = $this->_line_break($text)) !== false) {
                 $add_line = $split < $tmp;
                 $split = min($tmp, $split);
             } else {
                 $add_line = true;
             }
             break;
     }
     if ($text === "") {
         return;
     }
     if ($split !== false) {
         if ($split == 0 && $text === " ") {
             $frame->set_text("");
             return;
         }
         if ($split == 0) {
             $this->_block_parent->add_line();
             $frame->position();
             $this->_layout_line();
         } else {
             if ($split < mb_strlen($frame->get_text())) {
                 $frame->split_text($split);
                 $t = $frame->get_text();
                 if ($split > 1 && $t[$split - 1] === "\n" && !$frame->is_pre()) {
                     $frame->set_text(m_mb_substr($t, 0, -1));
                 }
             }
         }
         if ($add_line) {
             $this->_block_parent->add_line();
             $frame->position();
         }
     } else {
         $t = $frame->get_text();
         $parent = $frame->get_parent();
         $is_inline_frame = get_class($parent) === 'Inline_Frame_Decorator';
         if (!$is_inline_frame && !$frame->get_next_sibling() || $is_inline_frame && !$parent->get_next_sibling()) {
             $t = rtrim($t);
         }
         if (!$is_inline_frame && !$frame->get_prev_sibling()) {
             $t = ltrim($t);
         }
         $frame->set_text($t);
     }
     $width = $frame->recalculate_width();
 }
function install_font_family($fontname, $normal, $bold = null, $italic = null, $bold_italic = null)
{
    Font_Metrics::init();
    if (!is_readable($normal)) {
        throw new DOMPDF_Exception("Unable to read '{$normal}'.");
    }
    $dir = dirname($normal);
    $basename = basename($normal);
    $last_dot = strrpos($basename, '.');
    if ($last_dot !== false) {
        $file = substr($basename, 0, $last_dot);
        $ext = strtolower(substr($basename, $last_dot));
    } else {
        $file = $basename;
        $ext = '';
    }
    if (!in_array($ext, array(".ttf", ".otf"))) {
        throw new DOMPDF_Exception("Unable to process fonts of type '{$ext}'.");
    }
    $path = "{$dir}/{$file}";
    $patterns = array("bold" => array("_Bold", "b", "B", "bd", "BD"), "italic" => array("_Italic", "i", "I"), "bold_italic" => array("_Bold_Italic", "bi", "BI", "ib", "IB"));
    foreach ($patterns as $type => $_patterns) {
        if (!isset(${$type}) || !is_readable(${$type})) {
            foreach ($_patterns as $_pattern) {
                if (is_readable("{$path}{$_pattern}{$ext}")) {
                    ${$type} = "{$path}{$_pattern}{$ext}";
                    break;
                }
            }
            if (is_null(${$type})) {
                echo "Unable to find {$type} face file.\n";
            }
        }
    }
    $fonts = compact("normal", "bold", "italic", "bold_italic");
    $entry = array();
    foreach ($fonts as $var => $src) {
        if (is_null($src)) {
            $entry[$var] = DOMPDF_FONT_DIR . m_mb_substr(basename($normal), 0, -4);
            continue;
        }
        if (!is_readable($src)) {
            throw new DOMPDF_Exception("Requested font '{$src}' is not readable");
        }
        $dest = DOMPDF_FONT_DIR . basename($src);
        if (!is_writeable(dirname($dest))) {
            throw new DOMPDF_Exception("Unable to write to destination '{$dest}'.");
        }
        echo "Copying {$src} to {$dest}...\n";
        if (!copy($src, $dest)) {
            throw new DOMPDF_Exception("Unable to copy '{$src}' to '{$dest}'");
        }
        $entry_name = m_mb_substr($dest, 0, -4);
        echo "Generating Adobe Font Metrics for {$entry_name}...\n";
        $font_obj = Font::load($dest);
        $font_obj->saveAdobeFontMetrics("{$entry_name}.ufm");
        $entry[$var] = $entry_name;
    }
    Font_Metrics::set_font_family($fontname, $entry);
    Font_Metrics::save_font_families();
}
 function addPngFromBuf($file, $x, $y, $w = 0, $h = 0, &$data, $is_mask = false, $mask = null)
 {
     if (isset($this->imagelist[$file])) {
         $data = null;
         $info['width'] = $this->imagelist[$file]['w'];
         $info['height'] = $this->imagelist[$file]['h'];
         $label = $this->imagelist[$file]['label'];
     } else {
         if ($data == null) {
             $this->addMessage('addPngFromBuf error - (' . $imgname . ') data not present!');
             return;
         }
         $error = 0;
         if (!$error) {
             $header = chr(137) . chr(80) . chr(78) . chr(71) . chr(13) . chr(10) . chr(26) . chr(10);
             if (m_mb_substr($data, 0, 8, '8bit') != $header) {
                 $error = 1;
                 if (DEBUGPNG) {
                     print '[addPngFromFile this file does not have a valid header ' . $file . ']';
                 }
                 $errormsg = 'this file does not have a valid header';
             }
         }
         if (!$error) {
             $p = 8;
             $len = mb_strlen($data, '8bit');
             $haveHeader = 0;
             $info = array();
             $idata = '';
             $pdata = '';
             while ($p < $len) {
                 $chunkLen = $this->PRVT_getBytes($data, $p, 4);
                 $chunkType = m_mb_substr($data, $p + 4, 4, '8bit');
                 switch ($chunkType) {
                     case 'IHDR':
                         $info['width'] = $this->PRVT_getBytes($data, $p + 8, 4);
                         $info['height'] = $this->PRVT_getBytes($data, $p + 12, 4);
                         $info['bitDepth'] = ord($data[$p + 16]);
                         $info['colorType'] = ord($data[$p + 17]);
                         $info['compressionMethod'] = ord($data[$p + 18]);
                         $info['filterMethod'] = ord($data[$p + 19]);
                         $info['interlaceMethod'] = ord($data[$p + 20]);
                         $haveHeader = 1;
                         if ($info['compressionMethod'] != 0) {
                             $error = 1;
                             if (DEBUGPNG) {
                                 print '[addPngFromFile unsupported compression method ' . $file . ']';
                             }
                             $errormsg = 'unsupported compression method';
                         }
                         if ($info['filterMethod'] != 0) {
                             $error = 1;
                             if (DEBUGPNG) {
                                 print '[addPngFromFile unsupported filter method ' . $file . ']';
                             }
                             $errormsg = 'unsupported filter method';
                         }
                         break;
                     case 'PLTE':
                         $pdata .= m_mb_substr($data, $p + 8, $chunkLen, '8bit');
                         break;
                     case 'IDAT':
                         $idata .= m_mb_substr($data, $p + 8, $chunkLen, '8bit');
                         break;
                     case 'tRNS':
                         $transparency = array();
                         switch ($info['colorType']) {
                             case 3:
                                 $transparency['type'] = 'indexed';
                                 $numPalette = mb_strlen($pdata, '8bit') / 3;
                                 $trans = 0;
                                 for ($i = $chunkLen; $i >= 0; $i--) {
                                     if (ord($data[$p + 8 + $i]) == 0) {
                                         $trans = $i;
                                     }
                                 }
                                 $transparency['data'] = $trans;
                                 break;
                             case 0:
                                 $transparency['type'] = 'indexed';
                                 $transparency['data'] = ord($data[$p + 8 + 1]);
                                 break;
                             case 2:
                                 $transparency['r'] = $this->PRVT_getBytes($data, $p + 8, 2);
                                 $transparency['g'] = $this->PRVT_getBytes($data, $p + 10, 2);
                                 $transparency['b'] = $this->PRVT_getBytes($data, $p + 12, 2);
                                 $transparency['type'] = 'color-key';
                                 break;
                             default:
                                 if (DEBUGPNG) {
                                     print '[addPngFromFile unsupported transparency type ' . $file . ']';
                                 }
                                 break;
                         }
                         break;
                     default:
                         break;
                 }
                 $p += $chunkLen + 12;
             }
             if (!$haveHeader) {
                 $error = 1;
                 if (DEBUGPNG) {
                     print '[addPngFromFile information header is missing ' . $file . ']';
                 }
                 $errormsg = 'information header is missing';
             }
             if (isset($info['interlaceMethod']) && $info['interlaceMethod']) {
                 $error = 1;
                 if (DEBUGPNG) {
                     print '[addPngFromFile no support for interlaced images in pdf ' . $file . ']';
                 }
                 $errormsg = 'There appears to be no support for interlaced images in pdf.';
             }
         }
         if (!$error && $info['bitDepth'] > 8) {
             $error = 1;
             if (DEBUGPNG) {
                 print '[addPngFromFile bit depth of 8 or less is supported ' . $file . ']';
             }
             $errormsg = 'only bit depth of 8 or less is supported';
         }
         if (!$error) {
             switch ($info['colorType']) {
                 case 3:
                     $color = 'DeviceRGB';
                     $ncolor = 1;
                     break;
                 case 2:
                     $color = 'DeviceRGB';
                     $ncolor = 3;
                     break;
                 case 0:
                     $color = 'DeviceGray';
                     $ncolor = 1;
                     break;
                 default:
                     $error = 1;
                     if (DEBUGPNG) {
                         print '[addPngFromFile alpha channel not supported: ' . $info['colorType'] . ' ' . $file . ']';
                     }
                     $errormsg = 'transparancey alpha channel not supported, transparency only supported for palette images.';
             }
         }
         if ($error) {
             $this->addMessage('PNG error - (' . $file . ') ' . $errormsg);
             return;
         }
         $this->numImages++;
         $im = $this->numImages;
         $label = "I{$im}";
         $this->numObj++;
         $options = array('label' => $label, 'data' => $idata, 'bitsPerComponent' => $info['bitDepth'], 'pdata' => $pdata, 'iw' => $info['width'], 'ih' => $info['height'], 'type' => 'png', 'color' => $color, 'ncolor' => $ncolor, 'masked' => $mask, 'isMask' => $is_mask);
         if (isset($transparency)) {
             $options['transparency'] = $transparency;
         }
         $this->o_image($this->numObj, 'new', $options);
         $this->imagelist[$file] = array('label' => $label, 'w' => $info['width'], 'h' => $info['height']);
     }
     if ($is_mask) {
         return;
     }
     if ($w <= 0 && $h <= 0) {
         $w = $info['width'];
         $h = $info['height'];
     }
     if ($w <= 0) {
         $w = $h / $info['height'] * $info['width'];
     }
     if ($h <= 0) {
         $h = $w * $info['height'] / $info['width'];
     }
     $this->objects[$this->currentContents]['c'] .= sprintf("\nq\n%.3F 0 0 %.3F %.3F %.3F cm /%s Do\nQ", $w, $h, $x, $y, $label);
 }
function explode_url($url)
{
    $protocol = "";
    $host = "";
    $path = "";
    $file = "";
    $arr = parse_url($url);
    if (isset($arr["scheme"]) && $arr["scheme"] !== "file" && strlen($arr["scheme"]) > 1) {
        $protocol = $arr["scheme"] . "://";
        if (isset($arr["user"])) {
            $host .= $arr["user"];
            if (isset($arr["pass"])) {
                $host .= "@" . $arr["pass"];
            }
            $host .= ":";
        }
        if (isset($arr["host"])) {
            $host .= $arr["host"];
        }
        if (isset($arr["port"])) {
            $host .= ":" . $arr["port"];
        }
        if (isset($arr["path"]) && $arr["path"] !== "") {
            if ($arr["path"][mb_strlen($arr["path"]) - 1] === "/") {
                $path = $arr["path"];
                $file = "";
            } else {
                $path = rtrim(dirname($arr["path"]), '/\\') . "/";
                $file = basename($arr["path"]);
            }
        }
        if (isset($arr["query"])) {
            $file .= "?" . $arr["query"];
        }
        if (isset($arr["fragment"])) {
            $file .= "#" . $arr["fragment"];
        }
    } else {
        $i = mb_strpos($url, "file://");
        if ($i !== false) {
            $url = m_mb_substr($url, $i + 7);
        }
        $protocol = "";
        $host = "";
        $file = basename($url);
        $path = dirname($url);
        if ($path !== false) {
            $path .= '/';
        } else {
            $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://';
            $host = isset($_SERVER["HTTP_HOST"]) ? $_SERVER["HTTP_HOST"] : php_uname("n");
            if (substr($arr["path"], 0, 1) === '/') {
                $path = dirname($arr["path"]);
            } else {
                $path = '/' . rtrim(dirname($_SERVER["SCRIPT_NAME"]), '/') . '/' . $arr["path"];
            }
        }
    }
    $ret = array($protocol, $host, $path, $file, "protocol" => $protocol, "host" => $host, "path" => $path, "file" => $file);
    return $ret;
}
 protected function _parse_content()
 {
     $re = "/\n" . "\\s(counters?\\([^)]*\\))|\n" . "\\A(counters?\\([^)]*\\))|\n" . "\\s([\"']) ( (?:[^\"']|\\\\[\"'])+ )(?<!\\\\)\\3|\n" . "\\A([\"']) ( (?:[^\"']|\\\\[\"'])+ )(?<!\\\\)\\5|\n" . "\\s([^\\s\"']+)|\n" . "\\A([^\\s\"']+)\n" . "/xi";
     $content = $this->_frame->get_style()->content;
     $quotes = $this->_parse_quotes();
     if (!preg_match_all($re, $content, $matches, PREG_SET_ORDER)) {
         return;
     }
     $text = "";
     foreach ($matches as $match) {
         if (isset($match[2]) && $match[2] !== "") {
             $match[1] = $match[2];
         }
         if (isset($match[6]) && $match[6] !== "") {
             $match[4] = $match[6];
         }
         if (isset($match[8]) && $match[8] !== "") {
             $match[7] = $match[8];
         }
         if (isset($match[1]) && $match[1] !== "") {
             $match[1] = mb_strtolower(trim($match[1]));
             $i = mb_strpos($match[1], ")");
             if ($i === false) {
                 continue;
             }
             $args = explode(",", m_mb_substr($match[1], 8, $i - 8));
             $counter_id = $args[0];
             if ($match[1][7] === "(") {
                 if (isset($args[1])) {
                     $type = trim($args[1]);
                 } else {
                     $type = null;
                 }
                 $p = $this->_frame->lookup_counter_frame($counter_id);
                 $text .= $p->counter_value($counter_id, $type);
             } else {
                 if ($match[1][7] === "s") {
                     if (isset($args[1])) {
                         $string = $this->_parse_string(trim($args[1]));
                     } else {
                         $string = "";
                     }
                     if (isset($args[2])) {
                         $type = $args[2];
                     } else {
                         $type = null;
                     }
                     $p = $this->_frame->lookup_counter_frame($counter_id);
                     $tmp = "";
                     while ($p) {
                         $tmp = $p->counter_value($counter_id, $type) . $string . $tmp;
                         $p = $p->lookup_counter_frame($counter_id);
                     }
                     $text .= $tmp;
                 } else {
                     continue;
                 }
             }
         } else {
             if (isset($match[4]) && $match[4] !== "") {
                 $text .= $this->_parse_string($match[4]);
             } else {
                 if (isset($match[7]) && $match[7] !== "") {
                     if ($match[7] === "open-quote") {
                         $text .= $quotes[0][0];
                     } else {
                         if ($match[7] === "close-quote") {
                             $text .= $quotes[0][1];
                         } else {
                             if ($match[7] === "no-open-quote") {
                             } else {
                                 if ($match[7] === "no-close-quote") {
                                 } else {
                                     if (mb_strpos($match[7], "attr(") === 0) {
                                         $i = mb_strpos($match[7], ")");
                                         if ($i === false) {
                                             continue;
                                         }
                                         $attr = m_mb_substr($match[7], 5, $i - 5);
                                         if ($attr == "") {
                                             continue;
                                         }
                                         $text .= $this->_frame->get_parent()->get_node()->getAttribute($attr);
                                     } else {
                                         continue;
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     return $text;
 }
 function set_list_style($val)
 {
     $important = isset($this->_important_props["list_style"]);
     $arr = explode(" ", str_replace(",", " ", $val));
     static $types = array("disc", "circle", "square", "decimal-leading-zero", "decimal", "1", "lower-roman", "upper-roman", "a", "A", "lower-greek", "lower-latin", "upper-latin", "lower-alpha", "upper-alpha", "armenian", "georgian", "hebrew", "cjk-ideographic", "hiragana", "katakana", "hiragana-iroha", "katakana-iroha", "none");
     static $positions = array("inside", "outside");
     foreach ($arr as $value) {
         if ($value === "none") {
             $this->_set_style("list_style_type", $value, $important);
             $this->_set_style("list_style_image", $value, $important);
             continue;
         }
         if (m_mb_substr($value, 0, 3) === "url") {
             $this->_set_style("list_style_image", $this->_image($value), $important);
             continue;
         }
         if (in_array($value, $types)) {
             $this->_set_style("list_style_type", $value, $important);
         } else {
             if (in_array($value, $positions)) {
                 $this->_set_style("list_style_position", $value, $important);
             }
         }
     }
     $this->_prop_cache["list_style"] = null;
     $this->_props["list_style"] = $val;
 }
 private function _parse_sections($str)
 {
     $patterns = array("/[\\s\n]+/", "/\\s+([>.:+#])\\s+/");
     $replacements = array(" ", "\\1");
     $str = preg_replace($patterns, $replacements, $str);
     $sections = explode("}", $str);
     if (DEBUGCSS) {
         print '[_parse_sections';
     }
     foreach ($sections as $sect) {
         $i = mb_strpos($sect, "{");
         $selectors = explode(",", m_mb_substr($sect, 0, $i));
         if (DEBUGCSS) {
             print '[section';
         }
         $style = $this->_parse_properties(trim(m_mb_substr($sect, $i + 1)));
         foreach ($selectors as $selector) {
             $selector = trim($selector);
             if ($selector == "") {
                 if (DEBUGCSS) {
                     print '#empty#';
                 }
                 continue;
             }
             if (DEBUGCSS) {
                 print '#' . $selector . '#';
             }
             $this->add_style($selector, $style);
         }
         if (DEBUGCSS) {
             print 'section]';
         }
     }
     if (DEBUGCSS) {
         print '_parse_sections]';
     }
 }
 function __toString()
 {
     $str = "<b>" . $this->_node->nodeName . ":</b><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>'" . m_mb_substr($tmp, 0, 70) . (mb_strlen($tmp) > 70 ? "..." : "") . "'</pre>";
     } elseif ($css_class = $this->_node->getAttribute("class")) {
         $tmp = htmlspecialchars($css_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: " . pre_r($this->_position, true);
     $str .= "\nContaining block: " . pre_r($this->_containing_block, true);
     $str .= "\nMargin width: " . pre_r($this->get_margin_width(), true);
     $str .= "\nMargin height: " . pre_r($this->get_margin_height(), true);
     $str .= "\nStyle: <pre>" . $this->_style->__toString() . "</pre>";
     if ($this->_decorator instanceof Block_Frame_Decorator) {
         $str .= "Lines:<pre>";
         foreach ($this->_decorator->get_line_boxes() as $line) {
             foreach ($line->get_frames() as $frame) {
                 if ($frame instanceof Text_Frame_Decorator) {
                     $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;
 }