diff --git a/application/config/autoload.php b/application/config/autoload.php old mode 100755 new mode 100644 index e6c5a553..cb7fa5e4 --- a/application/config/autoload.php +++ b/application/config/autoload.php @@ -64,7 +64,7 @@ $autoload['libraries'] = array('database', 'session'); | $autoload['helper'] = array('url', 'file'); */ -$autoload['helper'] = array('url', 'file','cias_helper'); +$autoload['helper'] = array('url', 'file','cias_helper','cookie'); /* diff --git a/application/config/database.php b/application/config/database.php old mode 100755 new mode 100644 index dd1c19de..e6e6d301 --- a/application/config/database.php +++ b/application/config/database.php @@ -48,7 +48,10 @@ $active_group = 'default'; $active_record = TRUE; -$db['default']['hostname'] = 'sidharthindustries.com'; +$db['default']['hostname'] = '35.213.153.5'; +// $db['default']['username'] = 'kasiram9_prod'; +// $db['default']['password'] = 'sia!1234'; +// $db['default']['database'] = 'kasiram9_SIAPROD'; $db['default']['username'] = 'kasiram9_Siddh'; $db['default']['password'] = 'sidh@1234'; $db['default']['database'] = 'kasiram9_SIADEV'; diff --git a/application/controllers/Report_consolidate.php b/application/controllers/Report_consolidate.php new file mode 100644 index 00000000..c9794025 --- /dev/null +++ b/application/controllers/Report_consolidate.php @@ -0,0 +1,718 @@ + + + + + + +
Report - Consolidate
+ input->post('client_name')){
+ $cl=$this->input->post('client_name');
+ echo $cl;
+ }
+ if($this->input->post('financialyear')){
+ $ab=$this->input->post('financialyear');
+ echo '('.$ab.')';
+ }
+
+ ?>
+
| Supplier Name | +Material Name | +Apr | +May | +Jun | +Jul | +Aug | +Sep | +Oct | +Nov | +Dec | +Jan | +Feb | +Mar | +Total | + +
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| + supplier_name;?> + | +material_name)) { echo $result->material_name ; } else {echo "-";} + ?> | +April); + if(!empty($result->April)) { echo round($result->April); } else {echo "-";} + ?> | +May); + if(!empty($result->May)) { echo round($result->May); } else {echo "-";} + ?> | +June); + if(!empty($result->June)) { echo round($result->June); } else {echo "-";} + ?> | +July); + if(!empty($result->July)) { echo round($result->July); } else {echo "-";} + ?> | +August); + if(!empty($result->August)) { echo round($result->August); } else {echo "-";} + + ?> | +September; + if(!empty($result->September)) { echo round($result->September); } else {echo "-";} + ?> | +October); + if(!empty($result->October)) { echo round($result->October); } else {echo "-";} + ?> | +November); + if(!empty($result->November)) { echo round($result->November); } else {echo "-";} + ?> | +December); + if(!empty($result->December)) { echo round($result->December); } else {echo "-";} + ?> | +January); + if(!empty($result->January)) { echo round($result->January); } else {echo "-";} + ?> | +February); + if(!empty($result->February)) { echo round($result->February); } else {echo "-";} + ?> | +March); + if(!empty($result->March)) { echo round($result->March); } else {echo "-";} + ?> | +qtotal); + if(!empty($result->qtotal)) { echo round($result->qtotal); } else {echo "-";} + ?> | +
| Total | ++ | ++ | ++ + | ++ + | ++ + | ++ + | ++ + + | ++ + + | ++ + + + | ++ + + + | ++ + + + | ++ + + + | ++ + + | ++ + + | + + + +
Report - Consolidate-Inward(input->get('m'); + echo $m; + ?>)
| Supplier Name | +Material Name | ++ | |
|---|---|---|---|
| Quantity | +Value () | + + +||
| + supplier_name;?> + | +material_name;?> | +quantity); + echo round($rel->quantity);?> | +total,2,'.',''); + echo number_format($rel->total,2,'.','');?> | + + +
| Total | + + ++ + + | ++ + + + | ++ + + + | + + + +
Report - Consolidate (Category-Wise)
+ input->post('client_name')){
+ $cl=$this->input->post('client_name');
+ echo $cl;
+ }
+ if($this->input->post('financialyear')){
+ $ab=$this->input->post('financialyear');
+ echo '('.$ab.')';
+ }
+
+ ?>
| Category | +Apr | +May | +Jun | +Jul | +Aug | +Sep | +Oct | +Nov | +Dec | +Jan | +Feb | +Mar | +Total | + +
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| + category;?> + | ++ April); + ?> + April);?> + | ++ May); + ?> + May);?> + | ++ June); + ?> + June);?> + | ++ July); + ?> + July);?> + | ++ August); + ?> + August);?> + | ++ September; + ?> + September);?> + | ++ October); + ?> + October);?> + | ++ November); + ?> + November);?> + | ++ December); + ?> + December);?> + | ++ January); + ?> + January);?> + | ++ February); + ?> + February);?> + | ++ March); + ?> + March);?> + | ++ qtotal); + ?> + qtotal);?> + | +
| Total | + ++ | ++ + | ++ + | ++ + | ++ + | ++ + + | ++ + + | ++ + + + | ++ + + + | ++ + + + | ++ + + + | ++ + + | ++ + + | + + + +
YEAR REPORTS()
| Month | + +Receipt | +Payment | +Total | + + + +
|---|---|---|---|
| month?> | + +inc,2,'.',''); + echo number_format($yr->inc,2,'.','');?> | +exp,2,'.',''); + echo number_format($yr->exp,2,'.','');?> | +total,2,'.','');?> | + + + + +
Month Report()
| Account Name | + + +Paid Type | + +Receipt | +Payment | + + + + +
|---|---|---|---|
| name?> | + +type?> | + + + +income,2,'.',''); + echo number_format($ym->income,2,'.','');?> | +expense,2,'.',''); + echo number_format($ym->expense,2,'.','');?> | + + + + +
| Total | ++ + + | + + + | ++ + + | + + + + + + +
[_background_image name '.$filedummy.']'; + + //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 ( method_exists( $this->_canvas, "get_cpdf" ) && + method_exists( $this->_canvas->get_cpdf(), "addImagePng" ) && + method_exists( $this->_canvas->get_cpdf(), "image_iscached" ) && + $this->_canvas->get_cpdf()->image_iscached($filedummy) ) { + $bg = null; + + //debugpng + //if (DEBUGPNG) print '[_background_image skip]'; + } + + else { + + // Create a new image to fit over the background rectangle + $bg = imagecreatetruecolor($bg_width, $bg_height); + + //anyway default + //imagealphablending($img, true); + + switch (strtolower($ext)) { + case "png": + $src = imagecreatefrompng($img); + break; + + case "jpg": + case "jpeg": + $src = imagecreatefromjpeg($img); + break; + + case "gif": + $src = imagecreatefromgif($img); + break; + + case "bmp": + $src = 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 imaage 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 */ + + //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 relativ 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 ( method_exists( $this->_canvas, "get_cpdf" ) && + method_exists( $this->_canvas->get_cpdf(), "addImagePng" ) ) { + // 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_file = tempnam(DOMPDF_TEMP_DIR, "bg_dompdf_img_").'.png'; + //debugpng + if (DEBUGPNG) print '[_background_image '.$tmp_file.']'; + + imagepng($bg, $tmp_file); + $this->_canvas->image($tmp_file, "png", $x, $y, $width, $height); + imagedestroy($bg); + + //debugpng + if (DEBUGPNG) print '[_background_image unlink '.$tmp_file.']'; + + if (!DEBUGKEEPTEMP) + unlink($tmp_file); + } + } + + protected function _get_dash_pattern($style, $width) { + $pattern = array(); + + switch ($style) { + default: + /*case "solid": + case "double": + case "groove": + case "inset": + case "outset": + case "ridge":*/ + case "none": break; + + case "dotted": + if ( $width < 2 ) + $pattern = array($width, 2); + else + $pattern = array($width); + break; + + case "dashed": + $pattern = array(3 * $width); + break; + } + + return $pattern; + } + + protected function _border_none($x, $y, $length, $color, $widths, $side, $corner_style = "bevel") { + return; + } + + // Border rendering functions + protected function _border_dotted($x, $y, $length, $color, $widths, $side, $corner_style = "bevel") { + list($top, $right, $bottom, $left) = $widths; + + $pattern = $this->_get_dash_pattern("dotted", $$side); + + switch ($side) { + + case "top": + $delta = $top / 2; + case "bottom": + $delta = isset($delta) ? $delta : -$bottom / 2; + $this->_canvas->line($x, $y + $delta, $x + $length, $y + $delta, $color, $$side, $pattern); + break; + + case "left": + $delta = $left / 2; + case "right": + $delta = isset($delta) ? $delta : - $right / 2; + $this->_canvas->line($x + $delta, $y, $x + $delta, $y + $length, $color, $$side, $pattern); + break; + + default: + return; + + } + } + + + protected function _border_dashed($x, $y, $length, $color, $widths, $side, $corner_style = "bevel") { + list($top, $right, $bottom, $left) = $widths; + + $pattern = $this->_get_dash_pattern("dashed", $$side); + + switch ($side) { + + case "top": + $delta = $top / 2; + case "bottom": + $delta = isset($delta) ? $delta : -$bottom / 2; + $this->_canvas->line($x, $y + $delta, $x + $length, $y + $delta, $color, $$side, $pattern); + break; + + case "left": + $delta = $left / 2; + case "right": + $delta = isset($delta) ? $delta : - $right / 2; + $this->_canvas->line($x + $delta, $y, $x + $delta, $y + $length, $color, $$side, $pattern); + break; + + default: + return; + } + + } + + + protected function _border_solid($x, $y, $length, $color, $widths, $side, $corner_style = "bevel") { + list($top, $right, $bottom, $left) = $widths; + + // All this polygon business is for beveled corners... + switch ($side) { + + case "top": + if ( $corner_style === "bevel" ) { + + $points = array($x, $y, + $x + $length, $y, + $x + $length - $right, $y + $top, + $x + $left, $y + $top); + $this->_canvas->polygon($points, $color, null, null, true); + } else + $this->_canvas->filled_rectangle($x, $y, $length, $top, $color); + + break; + + case "bottom": + if ( $corner_style === "bevel" ) { + $points = array($x, $y, + $x + $length, $y, + $x + $length - $right, $y - $bottom, + $x + $left, $y - $bottom); + $this->_canvas->polygon($points, $color, null, null, true); + } else + $this->_canvas->filled_rectangle($x, $y - $bottom, $length, $bottom, $color); + + break; + + case "left": + if ( $corner_style === "bevel" ) { + $points = array($x, $y, + $x, $y + $length, + $x + $left, $y + $length - $bottom, + $x + $left, $y + $top); + $this->_canvas->polygon($points, $color, null, null, true); + } else + $this->_canvas->filled_rectangle($x, $y, $left, $length, $color); + + break; + + case "right": + if ( $corner_style === "bevel" ) { + $points = array($x, $y, + $x, $y + $length, + $x - $right, $y + $length - $bottom, + $x - $right, $y + $top); + $this->_canvas->polygon($points, $color, null, null, true); + } else + $this->_canvas->filled_rectangle($x - $right, $y, $right, $length, $color); + + break; + + default: + return; + + } + + } + + + protected function _border_double($x, $y, $length, $color, $widths, $side, $corner_style = "bevel") { + list($top, $right, $bottom, $left) = $widths; + + $line_width = $$side / 4; + + // We draw the outermost edge first. Points are ordered: outer left, + // outer right, inner right, inner left, or outer top, outer bottom, + // inner bottom, inner top. + switch ($side) { + + case "top": + if ( $corner_style === "bevel" ) { + $left_line_width = $left / 4; + $right_line_width = $right / 4; + + $points = array($x, $y, + $x + $length, $y, + $x + $length - $right_line_width, $y + $line_width, + $x + $left_line_width, $y + $line_width,); + $this->_canvas->polygon($points, $color, null, null, true); + + $points = array($x + $left - $left_line_width, $y + $top - $line_width, + $x + $length - $right + $right_line_width, $y + $top - $line_width, + $x + $length - $right, $y + $top, + $x + $left, $y + $top); + $this->_canvas->polygon($points, $color, null, null, true); + + } else { + $this->_canvas->filled_rectangle($x, $y, $length, $line_width, $color); + $this->_canvas->filled_rectangle($x, $y + $top - $line_width, $length, $line_width, $color); + + } + break; + + case "bottom": + if ( $corner_style === "bevel" ) { + $left_line_width = $left / 4; + $right_line_width = $right / 4; + + $points = array($x, $y, + $x + $length, $y, + $x + $length - $right_line_width, $y - $line_width, + $x + $left_line_width, $y - $line_width); + $this->_canvas->polygon($points, $color, null, null, true); + + $points = array($x + $left - $left_line_width, $y - $bottom + $line_width, + $x + $length - $right + $right_line_width, $y - $bottom + $line_width, + $x + $length - $right, $y - $bottom, + $x + $left, $y - $bottom); + $this->_canvas->polygon($points, $color, null, null, true); + + } else { + $this->_canvas->filled_rectangle($x, $y - $line_width, $length, $line_width, $color); + $this->_canvas->filled_rectangle($x, $y - $bottom, $length, $line_width, $color); + } + + break; + + case "left": + if ( $corner_style === "bevel" ) { + $top_line_width = $top / 4; + $bottom_line_width = $bottom / 4; + + $points = array($x, $y, + $x, $y + $length, + $x + $line_width, $y + $length - $bottom_line_width, + $x + $line_width, $y + $top_line_width); + $this->_canvas->polygon($points, $color, null, null, true); + + $points = array($x + $left - $line_width, $y + $top - $top_line_width, + $x + $left - $line_width, $y + $length - $bottom + $bottom_line_width, + $x + $left, $y + $length - $bottom, + $x + $left, $y + $top); + $this->_canvas->polygon($points, $color, null, null, true); + + } else { + $this->_canvas->filled_rectangle($x, $y, $line_width, $length, $color); + $this->_canvas->filled_rectangle($x + $left - $line_width, $y, $line_width, $length, $color); + } + + break; + + case "right": + if ( $corner_style === "bevel" ) { + $top_line_width = $top / 4; + $bottom_line_width = $bottom / 4; + + + $points = array($x, $y, + $x, $y + $length, + $x - $line_width, $y + $length - $bottom_line_width, + $x - $line_width, $y + $top_line_width); + $this->_canvas->polygon($points, $color, null, null, true); + + $points = array($x - $right + $line_width, $y + $top - $top_line_width, + $x - $right + $line_width, $y + $length - $bottom + $bottom_line_width, + $x - $right, $y + $length - $bottom, + $x - $right, $y + $top); + $this->_canvas->polygon($points, $color, null, null, true); + + } else { + $this->_canvas->filled_rectangle($x - $line_width, $y, $line_width, $length, $color); + $this->_canvas->filled_rectangle($x - $right, $y, $line_width, $length, $color); + } + + break; + + default: + return; + + } + + } + + protected function _border_groove($x, $y, $length, $color, $widths, $side, $corner_style = "bevel") { + list($top, $right, $bottom, $left) = $widths; + + $half_widths = array($top / 2, $right / 2, $bottom / 2, $left / 2); + + $this->_border_inset($x, $y, $length, $color, $half_widths, $side); + + switch ($side) { + + case "top": + $x += $left / 2; + $y += $top / 2; + $length -= $left / 2 + $right / 2; + break; + + case "bottom": + $x += $left / 2; + $y -= $bottom / 2; + $length -= $left / 2 + $right / 2; + break; + + case "left": + $x += $left / 2; + $y += $top / 2; + $length -= $top / 2 + $bottom / 2; + break; + + case "right": + $x -= $right / 2; + $y += $top / 2; + $length -= $top / 2 + $bottom / 2; + break; + + default: + return; + + } + + $this->_border_outset($x, $y, $length, $color, $half_widths, $side); + + } + + protected function _border_ridge($x, $y, $length, $color, $widths, $side, $corner_style = "bevel") { + list($top, $right, $bottom, $left) = $widths; + + $half_widths = array($top / 2, $right / 2, $bottom / 2, $left / 2); + + $this->_border_outset($x, $y, $length, $color, $half_widths, $side); + + switch ($side) { + + case "top": + $x += $left / 2; + $y += $top / 2; + $length -= $left / 2 + $right / 2; + break; + + case "bottom": + $x += $left / 2; + $y -= $bottom / 2; + $length -= $left / 2 + $right / 2; + break; + + case "left": + $x += $left / 2; + $y += $top / 2; + $length -= $top / 2 + $bottom / 2; + break; + + case "right": + $x -= $right / 2; + $y += $top / 2; + $length -= $top / 2 + $bottom / 2; + break; + + default: + return; + + } + + $this->_border_inset($x, $y, $length, $color, $half_widths, $side); + + } + + protected function _tint($c) { + if ( !is_numeric($c) ) + return $c; + + return min(1, $c + 0.16); + } + + protected function _shade($c) { + if ( !is_numeric($c) ) + return $c; + + return max(0, $c - 0.33); + } + + protected function _border_inset($x, $y, $length, $color, $widths, $side, $corner_style = "bevel") { + list($top, $right, $bottom, $left) = $widths; + + switch ($side) { + + case "top": + case "left": + $shade = array_map(array($this, "_shade"), $color); + $this->_border_solid($x, $y, $length, $shade, $widths, $side); + break; + + case "bottom": + case "right": + $tint = array_map(array($this, "_tint"), $color); + $this->_border_solid($x, $y, $length, $tint, $widths, $side); + break; + + default: + return; + } + } + + protected function _border_outset($x, $y, $length, $color, $widths, $side, $corner_style = "bevel") { + list($top, $right, $bottom, $left) = $widths; + + switch ($side) { + case "top": + case "left": + $tint = array_map(array($this, "_tint"), $color); + $this->_border_solid($x, $y, $length, $tint, $widths, $side); + break; + + case "bottom": + case "right": + $shade = array_map(array($this, "_shade"), $color); + $this->_border_solid($x, $y, $length, $shade, $widths, $side); + break; + + default: + return; + + } + } + + protected function _set_opacity($opacity) { + if ( is_numeric($opacity) && $opacity <= 1.0 && $opacity >= 0.0 ) { + $this->_canvas->set_opacity( $opacity ); + } + } + + protected function _debug_layout($box, $color = "red", $style = array()) { + $this->_canvas->rectangle($box[0], $box[1], $box[2], $box[3], CSS_Color::parse($color), 0.1, $style); + } + //........................................................................ +} diff --git a/application/third_party/dompdf/include/attribute_translator.cls.php b/application/third_party/dompdf/include/attribute_translator.cls.php new file mode 100644 index 00000000..87503fea --- /dev/null +++ b/application/third_party/dompdf/include/attribute_translator.cls.php @@ -0,0 +1,481 @@ + + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library in the file LICENSE.LGPL; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + * + * Alternatively, you may distribute this software under the terms of the + * PHP License, version 3.0 or later. A copy of this license should have + * been distributed with this file in the file LICENSE.PHP . If this is not + * the case, you can obtain a copy at http://www.php.net/license/3_0.txt. + * + * The latest version of DOMPDF might be available at: + * http://www.dompdf.com/ + * + * @link http://www.dompdf.com/ + * @copyright 2004 Benj Carson + * @author Benj Carson
+ * array(0 => x1,
+ * 1 => y1,
+ * 2 => x2,
+ * 3 => y2,
+ * ...
+ * );
+ *
+ *
+ * See {@link Style::munge_colour()} for the format of the colour array.
+ * See {@link Cpdf::setLineStyle()} for a description of the $style
+ * parameter (aka dash)
+ *
+ * @param array $points
+ * @param array $color
+ * @param float $width
+ * @param array $style
+ * @param bool $fill Fills the polygon if true
+ */
+ function polygon($points, $color, $width = null, $style = null, $fill = false);
+
+ /**
+ * Draws a circle at $x,$y with radius $r
+ *
+ * See {@link Style::munge_colour()} for the format of the colour array.
+ * See {@link Cpdf::setLineStyle()} for a description of the $style
+ * parameter (aka dash)
+ *
+ * @param float $x
+ * @param float $y
+ * @param float $r
+ * @param array $color
+ * @param float $width
+ * @param array $style
+ * @param bool $fill Fills the circle if true
+ */
+ function circle($x, $y, $r, $color, $width = null, $style = null, $fill = false);
+
+ /**
+ * Add an image to the pdf.
+ *
+ * The image is placed at the specified x and y coordinates with the
+ * given width and height.
+ *
+ * @param string $img_url the path to the image
+ * @param string $img_type the type (e.g. extension) of the image
+ * @param float $x x position
+ * @param float $y y position
+ * @param int $w width (in pixels)
+ * @param int $h height (in pixels)
+ */
+ function image($img_url, $img_type, $x, $y, $w, $h);
+
+ /**
+ * Writes text at the specified x and y coordinates
+ *
+ * See {@link Style::munge_colour()} for the format of the colour array.
+ *
+ * @param float $x
+ * @param float $y
+ * @param string $text the text to write
+ * @param string $font the font file to use
+ * @param float $size the font size, in points
+ * @param array $color
+ * @param float $word_space word spacing adjustment
+ * @param float $char_space whar spacing adjustment
+ * @param float $angle angle
+ */
+ function text($x, $y, $text, $font, $size, $color = array(0,0,0), $word_space = 0, $char_space = 0, $angle = 0);
+
+ /**
+ * Add a named destination (similar to ... in html)
+ *
+ * @param string $anchorname The name of the named destination
+ */
+ function add_named_dest($anchorname);
+
+ /**
+ * 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);
+
+ /**
+ * Add meta information to the pdf
+ *
+ * @param string $label label of the value (Creator, Producer, etc.)
+ * @param string $value the text to set
+ */
+ function add_info($name, $value);
+
+ /**
+ * Calculates text size, in points
+ *
+ * @param string $text the text to be sized
+ * @param string $font the desired font
+ * @param float $size the desired font size
+ * @param float $spacing word spacing, if any
+ * @return float
+ */
+ function get_text_width($text, $font, $size, $word_spacing = 0, $char_spacing = 0);
+
+ /**
+ * Calculates font height, in points
+ *
+ * @param string $font
+ * @param float $size
+ * @return float
+ */
+ function get_font_height($font, $size);
+
+ /**
+ * Sets the opacity
+ *
+ * @param float $opacity
+ * @param string $mode
+ * @return float
+ */
+ function set_opacity($opacity, $mode = "Normal");
+
+ /**
+ * Starts a new page
+ *
+ * Subsequent drawing operations will appear on the new page.
+ */
+ function new_page();
+
+ /**
+ * Streams the PDF directly to the browser
+ *
+ * @param string $filename the name of the PDF file
+ * @param array $options associative array, 'Attachment' => 0 or 1, 'compress' => 1 or 0
+ */
+ function stream($filename, $options = null);
+
+ /**
+ * Returns the PDF as a string
+ *
+ * @param array $options associative array: 'compress' => 1 or 0
+ * @return string
+ */
+ function output($options = null);
+
+}
diff --git a/application/third_party/dompdf/include/canvas_factory.cls.php b/application/third_party/dompdf/include/canvas_factory.cls.php
new file mode 100644
index 00000000..4dc4070a
--- /dev/null
+++ b/application/third_party/dompdf/include/canvas_factory.cls.php
@@ -0,0 +1,83 @@
+
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library in the file LICENSE.LGPL; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * Alternatively, you may distribute this software under the terms of the
+ * PHP License, version 3.0 or later. A copy of this license should have
+ * been distributed with this file in the file LICENSE.PHP . If this is not
+ * the case, you can obtain a copy at http://www.php.net/license/3_0.txt.
+ *
+ * The latest version of DOMPDF might be available at:
+ * http://www.dompdf.com/
+ *
+ * @link http://www.dompdf.com/
+ * @copyright 2004 Benj Carson
+ * @author Benj Carson ['.$font.','.$size.','.$pdf->getFontHeight($size).','.$pdf->getFontDescender($size).','.$pdf->fonts[$pdf->currentFont]['FontBBox'][3].','.$pdf->fonts[$pdf->currentFont]['FontBBox'][1].','.$pdf->fonts[$pdf->currentFont]['FontHeightOffset'].','.$pdf->fonts[$pdf->currentFont]['Ascender'].','.$pdf->fonts[$pdf->currentFont]['Descender'].']'; + // + //$pdf->addText($x, $this->y($y) - Font_Metrics::get_font_height($font, $size), $size, $text, $angle, $word_space, $char_space); + //$pdf->addText($x, $this->y($y) - $size, $size, $text, $angle, $word_space, $char_space); + //$pdf->addText($x, $this->y($y) - $pdf->getFontHeight($size)-$pdf->getFontDescender($size), $size, $text, $angle, $word_space, $char_space); + $pdf->addText($x, $this->y($y) - ($pdf->fonts[$pdf->currentFont]['FontBBox'][3]*$size)/1000, $size, $text, $angle, $word_space, $char_space); + } + + //........................................................................ + + function javascript($code) { + $this->_pdf->addJavascript($code); + } + + //........................................................................ + + /** + * Add a named destination (similar to ... in html) + * + * @param string $anchorname The name of the named destination + */ + function add_named_dest($anchorname) { + $this->_pdf->addDestination($anchorname, "Fit"); + } + + //........................................................................ + + /** + * 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->addInternalLink($name, $x, $y, $x + $width, $y + $height); + + } else { + $this->_pdf->addLink(rawurldecode($url), $x, $y, $x + $width, $y + $height); + } + } + + //........................................................................ + + function get_text_width($text, $font, $size, $word_spacing = 0, $char_spacing = 0) { + $this->_pdf->selectFont($font); + if (!DOMPDF_UNICODE_ENABLED) { + $text = mb_convert_encoding($text, 'Windows-1252', 'UTF-8'); + } + return $this->_pdf->getTextWidth($size, $text, $word_spacing, $char_spacing); + } + + //........................................................................ + + function get_font_height($font, $size) { + $this->_pdf->selectFont($font); + return $this->_pdf->getFontHeight($size) * DOMPDF_FONT_HEIGHT_RATIO; + } + + //........................................................................ + + /** + * Writes text at the specified x and y coordinates on every page + * + * The strings '{PAGE_NUM}' and '{PAGE_COUNT}' are automatically replaced + * with their current values. + * + * See {@link Style::munge_colour()} for the format of the colour array. + * + * @param float $x + * @param float $y + * @param string $text the text to write + * @param string $font the font file to use + * @param float $size the font size, in points + * @param array $color + * @param float $adjust word spacing adjustment + * @param float $angle angle to write the text at, measured CW starting from the x-axis + */ + function page_text($x, $y, $text, $font, $size, $color = array(0,0,0), $adjust = 0, $angle = 0) { + $_t = "text"; + $this->_page_text[] = compact("_t", "x", "y", "text", "font", "size", "color", "adjust", "angle"); + } + + //........................................................................ + + /** + * Processes a script on every page + * + * The variables $pdf, $PAGE_NUM, and $PAGE_COUNT are available. + * + * This function can be used to add page numbers to all pages + * after the first one, for example. + * + * @param string $code the script code + * @param string $type the language type for script + */ + function page_script($code, $type = "text/php") { + $_t = "script"; + $this->_page_text[] = compact("_t", "code", "type"); + } + + //........................................................................ + + function new_page() { + $this->_page_number++; + $this->_page_count++; + + $ret = $this->_pdf->newPage(); + $this->_pages[] = $ret; + return $ret; + } + + //........................................................................ + + /** + * Add text to each page after rendering is complete + */ + protected function _add_page_text() { + + if ( !count($this->_page_text) ) + return; + + $page_number = 1; + $eval = null; + + foreach ($this->_pages as $pid) { + $this->reopen_object($pid); + + foreach ($this->_page_text as $pt) { + extract($pt); + + switch ($_t) { + + case "text": + $text = str_replace(array("{PAGE_NUM}","{PAGE_COUNT}"), + array($page_number, $this->_page_count), $text); + $this->text($x, $y, $text, $font, $size, $color, $adjust, $angle); + break; + + case "script": + if (!$eval) { + $eval = new PHP_Evaluator($this); + } + $eval->evaluate($code, array('PAGE_NUM' => $page_number, 'PAGE_COUNT' => $this->_page_count)); + break; + } + } + + $this->close_object(); + $page_number++; + } + } + + /** + * Streams the PDF directly to the browser + * + * @param string $filename the name of the PDF file + * @param array $options associative array, 'Attachment' => 0 or 1, 'compress' => 1 or 0 + */ + function stream($filename, $options = null) { + // Add page text + $this->_add_page_text(); + + $options["Content-Disposition"] = $filename; + $this->_pdf->stream($options); + } + + //........................................................................ + + /** + * Returns the PDF as a string + * + * @param array $options Output options + * @return string + */ + function output($options = null) { + // Add page text + $this->_add_page_text(); + + $debug = isset($options["compress"]) && $options["compress"] != 1; + + return $this->_pdf->output($debug); + } + + //........................................................................ + + /** + * Returns logging messages generated by the Cpdf class + * + * @return string + */ + function get_messages() { return $this->_pdf->messages; } + +} diff --git a/application/third_party/dompdf/include/css_color.cls.php b/application/third_party/dompdf/include/css_color.cls.php new file mode 100644 index 00000000..f6f003a7 --- /dev/null +++ b/application/third_party/dompdf/include/css_color.cls.php @@ -0,0 +1,287 @@ + + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library in the file LICENSE.LGPL; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + * + * Alternatively, you may distribute this software under the terms of the + * PHP License, version 3.0 or later. A copy of this license should have + * been distributed with this file in the file LICENSE.PHP . If this is not + * the case, you can obtain a copy at http://www.php.net/license/3_0.txt. + * + * The latest version of DOMPDF might be available at: + * http://www.dompdf.com/ + * + * @link http://www.dompdf.com/ + * @copyright 2004 Benj Carson + * @author Fabien M�nager + * @package dompdf + */ + +/* $Id: css_color.cls.php 300 2010-08-11 22:01:09Z fabien.menager $ */ + +class CSS_Color { + static $cssColorNames = array( + "aliceblue" => "F0F8FF", + "antiquewhite" => "FAEBD7", + "aqua" => "00FFFF", + "aquamarine" => "7FFFD4", + "azure" => "F0FFFF", + "beige" => "F5F5DC", + "bisque" => "FFE4C4", + "black" => "000000", + "blanchedalmond" => "FFEBCD", + "blue" => "0000FF", + "blueviolet" => "8A2BE2", + "brown" => "A52A2A", + "burlywood" => "DEB887", + "cadetblue" => "5F9EA0", + "chartreuse" => "7FFF00", + "chocolate" => "D2691E", + "coral" => "FF7F50", + "cornflowerblue" => "6495ED", + "cornsilk" => "FFF8DC", + "crimson" => "DC143C", + "cyan" => "00FFFF", + "darkblue" => "00008B", + "darkcyan" => "008B8B", + "darkgoldenrod" => "B8860B", + "darkgray" => "A9A9A9", + "darkgreen" => "006400", + "darkgrey" => "A9A9A9", + "darkkhaki" => "BDB76B", + "darkmagenta" => "8B008B", + "darkolivegreen" => "556B2F", + "darkorange" => "FF8C00", + "darkorchid" => "9932CC", + "darkred" => "8B0000", + "darksalmon" => "E9967A", + "darkseagreen" => "8FBC8F", + "darkslateblue" => "483D8B", + "darkslategray" => "2F4F4F", + "darkslategrey" => "2F4F4F", + "darkturquoise" => "00CED1", + "darkviolet" => "9400D3", + "deeppink" => "FF1493", + "deepskyblue" => "00BFFF", + "dimgray" => "696969", + "dimgrey" => "696969", + "dodgerblue" => "1E90FF", + "firebrick" => "B22222", + "floralwhite" => "FFFAF0", + "forestgreen" => "228B22", + "fuchsia" => "FF00FF", + "gainsboro" => "DCDCDC", + "ghostwhite" => "F8F8FF", + "gold" => "FFD700", + "goldenrod" => "DAA520", + "gray" => "808080", + "green" => "008000", + "greenyellow" => "ADFF2F", + "grey" => "808080", + "honeydew" => "F0FFF0", + "hotpink" => "FF69B4", + "indianred" => "CD5C5C", + "indigo" => "4B0082", + "ivory" => "FFFFF0", + "khaki" => "F0E68C", + "lavender" => "E6E6FA", + "lavenderblush" => "FFF0F5", + "lawngreen" => "7CFC00", + "lemonchiffon" => "FFFACD", + "lightblue" => "ADD8E6", + "lightcoral" => "F08080", + "lightcyan" => "E0FFFF", + "lightgoldenrodyellow" => "FAFAD2", + "lightgray" => "D3D3D3", + "lightgreen" => "90EE90", + "lightgrey" => "D3D3D3", + "lightpink" => "FFB6C1", + "lightsalmon" => "FFA07A", + "lightseagreen" => "20B2AA", + "lightskyblue" => "87CEFA", + "lightslategray" => "778899", + "lightslategrey" => "778899", + "lightsteelblue" => "B0C4DE", + "lightyellow" => "FFFFE0", + "lime" => "00FF00", + "limegreen" => "32CD32", + "linen" => "FAF0E6", + "magenta" => "FF00FF", + "maroon" => "800000", + "mediumaquamarine" => "66CDAA", + "mediumblue" => "0000CD", + "mediumorchid" => "BA55D3", + "mediumpurple" => "9370DB", + "mediumseagreen" => "3CB371", + "mediumslateblue" => "7B68EE", + "mediumspringgreen" => "00FA9A", + "mediumturquoise" => "48D1CC", + "mediumvioletred" => "C71585", + "midnightblue" => "191970", + "mintcream" => "F5FFFA", + "mistyrose" => "FFE4E1", + "moccasin" => "FFE4B5", + "navajowhite" => "FFDEAD", + "navy" => "000080", + "oldlace" => "FDF5E6", + "olive" => "808000", + "olivedrab" => "6B8E23", + "orange" => "FFA500", + "orangered" => "FF4500", + "orchid" => "DA70D6", + "palegoldenrod" => "EEE8AA", + "palegreen" => "98FB98", + "paleturquoise" => "AFEEEE", + "palevioletred" => "DB7093", + "papayawhip" => "FFEFD5", + "peachpuff" => "FFDAB9", + "peru" => "CD853F", + "pink" => "FFC0CB", + "plum" => "DDA0DD", + "powderblue" => "B0E0E6", + "purple" => "800080", + "red" => "FF0000", + "rosybrown" => "BC8F8F", + "royalblue" => "4169E1", + "saddlebrown" => "8B4513", + "salmon" => "FA8072", + "sandybrown" => "F4A460", + "seagreen" => "2E8B57", + "seashell" => "FFF5EE", + "sienna" => "A0522D", + "silver" => "C0C0C0", + "skyblue" => "87CEEB", + "slateblue" => "6A5ACD", + "slategray" => "708090", + "slategrey" => "708090", + "snow" => "FFFAFA", + "springgreen" => "00FF7F", + "steelblue" => "4682B4", + "tan" => "D2B48C", + "teal" => "008080", + "thistle" => "D8BFD8", + "tomato" => "FF6347", + "turquoise" => "40E0D0", + "violet" => "EE82EE", + "wheat" => "F5DEB3", + "white" => "FFFFFF", + "whitesmoke" => "F5F5F5", + "yellow" => "FFFF00", + "yellowgreen" => "9ACD32", + ); + + static function parse($colour) { + if ( is_array($colour) ) + // Assume the array has the right format... + // FIXME: should/could verify this. + return $colour; + + $colour = strtolower($colour); + + if (isset(self::$cssColorNames[$colour])) + return self::getArray(self::$cssColorNames[$colour]); + + if ($colour === "transparent") + return "transparent"; + + $length = mb_strlen($colour); + + // #rgb format + if ( $length == 4 && $colour[0] === "#" ) { + return self::getArray($colour[1].$colour[1].$colour[2].$colour[2].$colour[3].$colour[3]); + + // #rrggbb format + } else if ( $length == 7 && $colour[0] === "#" ) { + return self::getArray(mb_substr($colour, 1, 6)); + + // rgb( r,g,b ) format + } else if ( mb_strpos($colour, "rgb") !== false ) { + $i = mb_strpos($colour, "("); + $j = mb_strpos($colour, ")"); + + // Bad colour value + if ($i === false || $j === false) + return null; + + $triplet = explode(",", mb_substr($colour, $i+1, $j-$i-1)); + + if (count($triplet) != 3) + return null; + + foreach (array_keys($triplet) as $c) { + $triplet[$c] = trim($triplet[$c]); + + if ( $triplet[$c][mb_strlen($triplet[$c]) - 1] === "%" ) + $triplet[$c] = round($triplet[$c] * 2.55); + } + + return self::getArray(vsprintf("%02X%02X%02X", $triplet)); + + // cmyk( c,m,y,k ) format + // http://www.w3.org/TR/css3-gcpm/#cmyk-colors + } else if ( mb_strpos($colour, "cmyk") !== false ) { + $i = mb_strpos($colour, "("); + $j = mb_strpos($colour, ")"); + + // Bad colour value + if ($i === false || $j === false) + return null; + + $values = explode(",", mb_substr($colour, $i+1, $j-$i-1)); + + if (count($values) != 4) + return null; + + foreach ($values as &$c) { + $c = floatval(trim($c)); + if ($c > 1.0) $c = 1.0; + if ($c < 0.0) $c = 0.0; + } + + return self::getArray($values); + } + } + + 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(mb_substr($colour, 0, 2)) / 0xff; + $c[1] = hexdec(mb_substr($colour, 2, 2)) / 0xff; + $c[2] = hexdec(mb_substr($colour, 4, 2)) / 0xff; + $c["r"] = $c[0]; + $c["g"] = $c[1]; + $c["b"] = $c[2]; + $c["hex"] = "#$colour"; + } + + return $c; + } +} diff --git a/application/third_party/dompdf/include/dompdf.cls.php b/application/third_party/dompdf/include/dompdf.cls.php new file mode 100644 index 00000000..7cff2491 --- /dev/null +++ b/application/third_party/dompdf/include/dompdf.cls.php @@ -0,0 +1,792 @@ + + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library in the file LICENSE.LGPL; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + * + * Alternatively, you may distribute this software under the terms of the + * PHP License, version 3.0 or later. A copy of this license should have + * been distributed with this file in the file LICENSE.PHP . If this is not + * the case, you can obtain a copy at http://www.php.net/license/3_0.txt. + * + * The latest version of DOMPDF might be available at: + * http://www.dompdf.com/ + * + * @link http://www.dompdf.com/ + * @copyright 2004 Benj Carson + * @author Benj Carson
'; + foreach ($_dompdf_warnings as $msg) + echo $msg . "\n"; + echo $this->get_canvas()->get_cpdf()->messages; + echo ''; + flush(); + } + + $this->restore_locale(); + } + + /** + * Add meta information to the PDF after rendering + */ + function add_info($label, $value) { + if (!is_null($this->_pdf)) + $this->_pdf->add_info($label, $value); + } + + /** + * Writes the output buffer in the log file + * @return void + */ + private function write_log() { + if ( !DOMPDF_LOG_OUTPUT_FILE || !is_writable(DOMPDF_LOG_OUTPUT_FILE) ) return; + + $memory = DOMPDF_memory_usage(); + $memory = number_format($memory/1024); + $time = number_format((microtime(true) - $this->_start_time) * 1000, 4); + + $out = "$memory KB ". + "$time ms
'" . mb_substr($tmp,0,70) . + (mb_strlen($tmp) > 70 ? "..." : "") . "'"; + } elseif ( $css_class = $this->_node->getAttribute("class") ) { + $tmp = htmlspecialchars($css_class); + $str .= "CSS class: '$css_class'
". $this->_style->__toString() . ""; + + if ( $this->_decorator instanceof Block_Frame_Decorator ) { + $str .= "Lines:
";
+ foreach ($this->_decorator->get_lines() as $line) {
+ foreach ($line["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 .=
+ //"\ncount => " . $line["count"] . "\n".
+ "\ny => " . $line["y"] . "\n" .
+ "w => " . $line["w"] . "\n" .
+ "h => " . $line["h"] . "\n" .
+ "left => " . $line["left"] . "\n" .
+ "right => " . $line["right"] . "\n";
+ }
+ $str .= "";
+ }
+ $str .= "\n";
+ if ( php_sapi_name() === "cli" )
+ $str = strip_tags(str_replace(array("" . print_r($mixed, true) . ""; + + if ( php_sapi_name() !== "cli") + echo ("
");
+ print_r($mixed);
+
+ if ( php_sapi_name() !== "cli")
+ echo("");
+ else
+ echo ("\n");
+ flush();
+
+}
+}
+
+if ( !function_exists("pre_var_dump") ) {
+/**
+ * var_dump wrapper for html/cli output
+ *
+ * Wraps var_dump() output in < pre > tags if the current sapi is not
+ * 'cli'.
+ *
+ * @param mixed $mixed variable or expression to display.
+ */
+function pre_var_dump($mixed) {
+ if ( php_sapi_name() !== "cli")
+ echo("");
+
+ var_dump($mixed);
+
+ if ( php_sapi_name() !== "cli")
+ echo("");
+}
+}
+
+if ( !function_exists("d") ) {
+/**
+ * generic debug function
+ *
+ * Takes everything and does its best to give a good debug output
+ *
+ * @param mixed $mixed variable or expression to display.
+ */
+function d($mixed) {
+ if ( php_sapi_name() !== "cli")
+ echo("");
+
+ // line
+ if (is_array($mixed) && array_key_exists("tallest_frame", $mixed)) {
+ echo "LINE:\n";
+ foreach($mixed as $key => $value) {
+ if (is_array($value) || is_object($value)) continue;
+ echo " $key:\t".var_export($value,true)."\n";
+ }
+ }
+
+ // other
+ else {
+ var_export($mixed);
+ }
+
+ if ( php_sapi_name() !== "cli")
+ echo("");
+}
+}
+
+/**
+ * builds a full url given a protocol, hostname, base path and url
+ *
+ * @param string $protocol
+ * @param string $host
+ * @param string $base_path
+ * @param string $url
+ * @return string
+ *
+ * Initially the trailing slash of $base_path was optional, and conditionally appended.
+ * However on dynamically created sites, where the page is given as url parameter,
+ * the base path might not end with an url.
+ * Therefore do not append a slash, and **require** the $base_url to ending in a slash
+ * when needed.
+ * Vice versa, on using the local file system path of a file, make sure that the slash
+ * is appended (o.k. also for Windows)
+ */
+function build_url($protocol, $host, $base_path, $url) {
+ if ( mb_strlen($url) == 0 ) {
+ //return $protocol . $host . rtrim($base_path, "/\\") . "/";
+ return $protocol . $host . $base_path;
+ }
+
+ // Is the url already fully qualified or a Data URI?
+ if ( mb_strpos($url, "://") !== false || mb_strpos($url, "data:") === 0 )
+ return $url;
+
+ $ret = $protocol;
+
+ if (!in_array(mb_strtolower($protocol), array("http://", "https://", "ftp://", "ftps://"))) {
+ //On Windows local file, an abs path can begin also with a '\' or a drive letter and colon
+ //drive: followed by a relative path would be a drive specific default folder.
+ //not known in php app code, treat as abs path
+ //($url[1] !== ':' || ($url[2]!=='\\' && $url[2]!=='/'))
+ if ($url[0] !== '/' && (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' || ($url[0] !== '\\' && $url[1] !== ':'))) {
+ // For rel path and local acess we ignore the host, and run the path through realpath()
+ $ret .= realpath($base_path).'/';
+ }
+ $ret .= $url;
+ $ret = preg_replace("/\?(.*)$/", "", $ret);
+ return $ret;
+ }
+
+ //remote urls with backslash in html/css are not really correct, but lets be genereous
+ if ( $url[0] === '/' || $url[0] === '\\' ) {
+ // Absolute path
+ $ret .= $host . $url;
+ } else {
+ // Relative path
+ //$base_path = $base_path !== "" ? rtrim($base_path, "/\\") . "/" : "";
+ $ret .= $host . $base_path . $url;
+ }
+
+ return $ret;
+
+}
+
+/**
+ * parse a full url or pathname and return an array(protocol, host, path,
+ * file + query + fragment)
+ *
+ * @param string $url
+ * @return array
+ */
+function explode_url($url) {
+ $protocol = "";
+ $host = "";
+ $path = "";
+ $file = "";
+
+ $arr = parse_url($url);
+
+ if ( isset($arr["scheme"]) &&
+ $arr["scheme"] !== "file" &&
+ mb_strlen($arr["scheme"]) > 1 ) // Exclude windows drive letters...
+ {
+ $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"] !== "" ) {
+ // Do we have a trailing slash?
+ if ( $arr["path"][ mb_strlen($arr["path"]) - 1 ] === "/" ) {
+ $path = $arr["path"];
+ $file = "";
+ } else {
+ $path = 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 = mb_substr($url, $i + 7);
+
+ $protocol = ""; // "file://"; ? why doesn't this work... It's because of
+ // network filenames like //COMPU/SHARENAME
+
+ $host = ""; // localhost, really
+ $file = basename($url);
+
+ $path = dirname($url);
+
+ // Check that the path exists
+ if ( $path !== false ) {
+ $path .= '/';
+
+ } else {
+ // generate a url to access the file if no real path found.
+ $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;
+}
+
+/**
+ * converts decimal numbers to roman numerals
+ *
+ * @param int $num
+ * @return string
+ */
+function dec2roman($num) {
+
+ static $ones = array("", "i", "ii", "iii", "iv", "v",
+ "vi", "vii", "viii", "ix");
+ static $tens = array("", "x", "xx", "xxx", "xl", "l",
+ "lx", "lxx", "lxxx", "xc");
+ static $hund = array("", "c", "cc", "ccc", "cd", "d",
+ "dc", "dcc", "dccc", "cm");
+ static $thou = array("", "m", "mm", "mmm");
+
+ if ( !is_numeric($num) )
+ throw new DOMPDF_Exception("dec2roman() requires a numeric argument.");
+
+ if ( $num > 4000 || $num < 0 )
+ return "(out of range)";
+
+ $num = strrev((string)$num);
+
+ $ret = "";
+ switch (mb_strlen($num)) {
+ case 4: $ret .= $thou[$num[3]];
+ case 3: $ret .= $hund[$num[2]];
+ case 2: $ret .= $tens[$num[1]];
+ case 1: $ret .= $ones[$num[0]];
+ default: break;
+ }
+ return $ret;
+
+}
+
+/**
+ * Determines whether $value is a percentage or not
+ *
+ * @param float $value
+ * @return bool
+ */
+function is_percent($value) { return false !== mb_strpos($value, "%"); }
+
+/**
+ * Parses a data URI scheme
+ * http://en.wikipedia.org/wiki/Data_URI_scheme
+ * @param string $data_uri The data URI to parse
+ * @return array The result with charset, mime type and decoded data
+ */
+function parse_data_uri($data_uri) {
+ if (!preg_match('/^data:(?P");
+
+ $bt = debug_backtrace();
+
+ array_shift($bt); // remove actual bt() call
+ echo "\n";
+
+ $i = 0;
+ foreach ($bt as $call) {
+ $file = basename($call["file"]) . " (" . $call["line"] . ")";
+ if ( isset($call["class"]) ) {
+ $func = $call["class"] . "->" . $call["function"] . "()";
+ } else {
+ $func = $call["function"] . "()";
+ }
+
+ echo "#" . str_pad($i, 2, " ", STR_PAD_RIGHT) . ": " . str_pad($file.":", 42) . " $func\n";
+ $i++;
+ }
+ echo "\n";
+
+ if ( php_sapi_name() !== "cli")
+ echo("");
+}
+
+/**
+ * Print debug messages
+ *
+ * @param string $type The type of debug messages to print
+ */
+function dompdf_debug($type, $msg) {
+ global $_DOMPDF_DEBUG_TYPES, $_dompdf_show_warnings, $_dompdf_debug;
+ if ( isset($_DOMPDF_DEBUG_TYPES[$type]) && ($_dompdf_show_warnings || $_dompdf_debug) ) {
+ $arr = debug_backtrace();
+
+ echo basename($arr[0]["file"]) . " (" . $arr[0]["line"] ."): " . $arr[1]["function"] . ": ";
+ pre_r($msg);
+ }
+}
+
+if ( !function_exists("print_memusage") ) {
+/**
+ * Dump memory usage
+ */
+function print_memusage() {
+ global $memusage;
+ echo ("Memory Usage\n");
+ $prev = 0;
+ $initial = reset($memusage);
+ echo (str_pad("Initial:", 40) . $initial . "\n\n");
+
+ foreach ($memusage as $key=>$mem) {
+ $mem -= $initial;
+ echo (str_pad("$key:" , 40));
+ echo (str_pad("$mem", 12) . "(diff: " . ($mem - $prev) . ")\n");
+ $prev = $mem;
+ }
+
+ echo ("\n" . str_pad("Total:", 40) . memory_get_usage()) . "\n";
+}
+}
+
+if ( !function_exists("enable_mem_profile") ) {
+/**
+ * Initialize memory profiling code
+ */
+function enable_mem_profile() {
+ global $memusage;
+ $memusage = array("Startup" => memory_get_usage());
+ register_shutdown_function("print_memusage");
+}
+}
+
+if ( !function_exists("mark_memusage") ) {
+/**
+ * Record the current memory usage
+ *
+ * @param string $location a meaningful location
+ */
+function mark_memusage($location) {
+ global $memusage;
+ if ( isset($memusage) )
+ $memusage[$location] = memory_get_usage();
+}
+}
+
+if ( !function_exists('sys_get_temp_dir')) {
+/**
+ * Find the current system temporary directory
+ *
+ * @link http://us.php.net/manual/en/function.sys-get-temp-dir.php#85261
+ */
+function sys_get_temp_dir() {
+ if (!empty($_ENV['TMP'])) { return realpath($_ENV['TMP']); }
+ if (!empty($_ENV['TMPDIR'])) { return realpath( $_ENV['TMPDIR']); }
+ if (!empty($_ENV['TEMP'])) { return realpath( $_ENV['TEMP']); }
+ $tempfile=tempnam(uniqid(rand(),TRUE),'');
+ if (file_exists($tempfile)) {
+ unlink($tempfile);
+ return realpath(dirname($tempfile));
+ }
+}
+}
+
+if ( function_exists("memory_get_peak_usage") ) {
+ function DOMPDF_memory_usage(){
+ return memory_get_peak_usage(true);
+ }
+}
+else if ( function_exists("memory_get_peak_usage") ) {
+ function DOMPDF_memory_usage(){
+ return memory_get_usage(true);
+ }
+}
+else {
+ function DOMPDF_memory_usage(){
+ return "N/A";
+ }
+}
+
+/**
+ * Affect null to the unused objects
+ * @param unknown_type $object
+ */
+function clear_object(&$object) {
+ if ( is_object($object) ) {
+ foreach (array_keys((array)$object) as $key) {
+ clear_object($property);
+ }
+ foreach(get_class_vars(get_class($object)) as $property => $value) {
+ clear_object($property);
+ }
+ }
+ $object = null;
+ unset($object);
+}
diff --git a/application/third_party/dompdf/include/gd_adapter.cls.php b/application/third_party/dompdf/include/gd_adapter.cls.php
new file mode 100644
index 00000000..58dde2da
--- /dev/null
+++ b/application/third_party/dompdf/include/gd_adapter.cls.php
@@ -0,0 +1,840 @@
+
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library in the file LICENSE.LGPL; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * Alternatively, you may distribute this software under the terms of the
+ * PHP License, version 3.0 or later. A copy of this license should have
+ * been distributed with this file in the file LICENSE.PHP . If this is not
+ * the case, you can obtain a copy at http://www.php.net/license/3_0.txt.
+ *
+ * The latest version of DOMPDF might be available at:
+ * http://www.dompdf.com/
+ *
+ * @link http://www.dompdf.com/
+ * @copyright 2004 Benj Carson
+ * @author Benj Carson
+ * array(0 => x1,
+ * 1 => y1,
+ * 2 => x2,
+ * 3 => y2,
+ * ...
+ * );
+ *
+ *
+ * See {@link Style::munge_color()} for the format of the color array.
+ * See {@link Cpdf::setLineStyle()} for a description of the $style
+ * parameter (aka dash)
+ *
+ * @param array $points
+ * @param array $color
+ * @param float $width
+ * @param array $style
+ * @param bool $fill Fills the polygon if true
+ */
+ function polygon($points, $color, $width = null, $style = null, $fill = false) {
+
+ // Scale each point by the AA factor
+ foreach (array_keys($points) as $i)
+ $points[$i] *= $this->_aa_factor;
+
+ $c = $this->_allocate_color($color);
+
+ // Convert the style array if required
+ if ( !is_null($style) && !$fill ) {
+ $gd_style = array();
+
+ foreach ($style as $length) {
+ for ($i = 0; $i < $length; $i++) {
+ $gd_style[] = $c;
+ }
+ }
+
+ imagesetstyle($this->_img, $gd_style);
+ $c = IMG_COLOR_STYLED;
+ }
+
+ imagesetthickness($this->_img, $width);
+
+ if ( $fill )
+ imagefilledpolygon($this->_img, $points, count($points) / 2, $c);
+ else
+ imagepolygon($this->_img, $points, count($points) / 2, $c);
+
+ }
+
+ /**
+ * Draws a circle at $x,$y with radius $r
+ *
+ * See {@link Style::munge_color()} for the format of the color array.
+ * See {@link Cpdf::setLineStyle()} for a description of the $style
+ * parameter (aka dash)
+ *
+ * @param float $x
+ * @param float $y
+ * @param float $r
+ * @param array $color
+ * @param float $width
+ * @param array $style
+ * @param bool $fill Fills the circle if true
+ */
+ function circle($x, $y, $r, $color, $width = null, $style = null, $fill = false) {
+
+ // Scale by the AA factor
+ $x *= $this->_aa_factor;
+ $y *= $this->_aa_factor;
+ $r *= $this->_aa_factor;
+
+ $c = $this->_allocate_color($color);
+
+ // Convert the style array if required
+ if ( !is_null($style) && !$fill ) {
+ $gd_style = array();
+
+ foreach ($style as $length) {
+ for ($i = 0; $i < $length; $i++) {
+ $gd_style[] = $c;
+ }
+ }
+
+ imagesetstyle($this->_img, $gd_style);
+ $c = IMG_COLOR_STYLED;
+ }
+
+ imagesetthickness($this->_img, $width);
+
+ if ( $fill )
+ imagefilledellipse($this->_img, $x, $y, $r, $r, $c);
+ else
+ imageellipse($this->_img, $x, $y, $r, $r, $c);
+
+ }
+
+ /**
+ * Add an image to the pdf.
+ *
+ * The image is placed at the specified x and y coordinates with the
+ * given width and height.
+ *
+ * @param string $img_url the path to the image
+ * @param string $img_type the type (e.g. extension) of the image
+ * @param float $x x position
+ * @param float $y y position
+ * @param int $w width (in pixels)
+ * @param int $h height (in pixels)
+ */
+ function image($img_url, $img_type, $x, $y, $w, $h) {
+
+ switch ($img_type) {
+ case "png":
+ $src = @imagecreatefrompng($img_url);
+ break;
+
+ case "gif":
+ $src = @imagecreatefromgif($img_url);
+ break;
+
+ case "bmp":
+ $src = @imagecreatefrombmp($img_url);
+ break;
+
+ case "jpg":
+ case "jpeg":
+ $src = @imagecreatefromjpeg($img_url);
+ break;
+
+ default:
+ break;
+
+ }
+
+ if ( !$src )
+ return; // Probably should add to $_dompdf_errors or whatever here
+
+ // Scale by the AA factor
+ $x *= $this->_aa_factor;
+ $y *= $this->_aa_factor;
+
+ $w *= $this->_aa_factor;
+ $h *= $this->_aa_factor;
+
+ $img_w = imagesx($src);
+ $img_h = imagesy($src);
+
+
+ imagecopyresampled($this->_img, $src, $x, $y, 0, 0, $w, $h, $img_w, $img_h);
+
+ }
+
+ /**
+ * Writes text at the specified x and y coordinates
+ *
+ * See {@link Style::munge_color()} for the format of the color array.
+ *
+ * @param float $x
+ * @param float $y
+ * @param string $text the text to write
+ * @param string $font the font file to use
+ * @param float $size the font size, in points
+ * @param array $color
+ * @param float $adjust word spacing adjustment
+ * @param float $angle Text angle
+ */
+ function text($x, $y, $text, $font, $size, $color = array(0,0,0), $word_spacing = 0, $char_spacing = 0, $angle = 0) {
+
+ // Scale by the AA factor
+ $x *= $this->_aa_factor;
+ $y *= $this->_aa_factor;
+ $size *= $this->_aa_factor;
+
+ $h = $this->get_font_height($font, $size);
+ $c = $this->_allocate_color($color);
+
+ $text = mb_encode_numericentity($text, array(0x0080, 0xff, 0, 0xff), 'UTF-8');
+
+ if ( strpos($font, '.ttf') === false )
+ $font .= ".ttf";
+
+ // FIXME: word spacing
+ @imagettftext($this->_img, $size, $angle, $x, $y + $h, $c, $font, $text);
+
+ }
+
+ function javascript($code) {
+ // Not implemented
+ }
+
+ /**
+ * Add a named destination (similar to ... in html)
+ *
+ * @param string $anchorname The name of the named destination
+ */
+ function add_named_dest($anchorname) {
+ // Not implemented
+ }
+
+ /**
+ * 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) {
+ // Not implemented
+ }
+
+ /**
+ * Add meta information to the PDF
+ *
+ * @param string $label label of the value (Creator, Producer, etc.)
+ * @param string $value the text to set
+ */
+ function add_info($label, $value) {
+ // N/A
+ }
+
+ /**
+ * Calculates text size, in points
+ *
+ * @param string $text the text to be sized
+ * @param string $font the desired font
+ * @param float $size the desired font size
+ * @param float $spacing word spacing, if any
+ * @return float
+ */
+ function get_text_width($text, $font, $size, $word_spacing = 0, $char_spacing = 0) {
+
+ if ( strpos($font, '.ttf') === false )
+ $font .= ".ttf";
+
+ $text = mb_encode_numericentity($text, array(0x0080, 0xffff, 0, 0xffff), 'UTF-8');
+
+ // FIXME: word spacing
+ list($x1,,$x2) = @imagettfbbox($size, 0, $font, $text);
+ return $x2 - $x1;
+ }
+
+ /**
+ * Calculates font height, in points
+ *
+ * @param string $font
+ * @param float $size
+ * @return float
+ */
+ function get_font_height($font, $size) {
+ if ( strpos($font, '.ttf') === false )
+ $font .= ".ttf";
+
+ // FIXME: word spacing
+ list(,$y2,,,,$y1) = imagettfbbox($size, 0, $font, "MXjpqytfhl"); // Test string with ascenders, descenders and caps
+ return ($y2 - $y1) * DOMPDF_FONT_HEIGHT_RATIO;
+ }
+
+
+ /**
+ * Starts a new page
+ *
+ * Subsequent drawing operations will appear on the new page.
+ */
+ function new_page() {
+ $this->_page_number++;
+ $this->_page_count++;
+ }
+
+ function open_object(){
+ // N/A
+ }
+
+ function close_object(){
+ // N/A
+ }
+
+ function add_object(){
+ // N/A
+ }
+
+ function page_text(){
+ // N/A
+ }
+
+ /**
+ * Streams the image directly to the browser
+ *
+ * @param string $filename the name of the image file (ignored)
+ * @param array $options associative array, 'type' => jpeg|jpg|png, 'quality' => 0 - 100 (jpeg only)
+ */
+ function stream($filename, $options = null) {
+
+ // Perform any antialiasing
+ if ( $this->_aa_factor != 1 ) {
+ $dst_w = $this->_width / $this->_aa_factor;
+ $dst_h = $this->_height / $this->_aa_factor;
+ $dst = imagecreatetruecolor($dst_w, $dst_h);
+ imagecopyresampled($dst, $this->_img, 0, 0, 0, 0,
+ $dst_w, $dst_h,
+ $this->_width, $this->_height);
+ } else {
+ $dst = $this->_img;
+ }
+
+ if ( !isset($options["type"]) )
+ $options["type"] = "png";
+
+ $type = strtolower($options["type"]);
+
+ header("Cache-Control: private");
+
+ switch ($type) {
+
+ case "jpg":
+ case "jpeg":
+ if ( !isset($options["quality"]) )
+ $options["quality"] = 75;
+
+ header("Content-type: image/jpeg");
+ imagejpeg($dst, '', $options["quality"]);
+ break;
+
+ case "png":
+ default:
+ header("Content-type: image/png");
+ imagepng($dst);
+ break;
+ }
+
+ if ( $this->_aa_factor != 1 )
+ imagedestroy($dst);
+ }
+
+ /**
+ * Returns the PNG as a string
+ *
+ * @param array $options associative array, 'type' => jpeg|jpg|png, 'quality' => 0 - 100 (jpeg only)
+ * @return string
+ */
+ function output($options = null) {
+
+ if ( $this->_aa_factor != 1 ) {
+ $dst_w = $this->_width / $this->_aa_factor;
+ $dst_h = $this->_height / $this->_aa_factor;
+ $dst = imagecreatetruecolor($dst_w, $dst_h);
+ imagecopyresampled($dst, $this->_img, 0, 0, 0, 0,
+ $dst_w, $dst_h,
+ $this->_width, $this->_height);
+ } else {
+ $dst = $this->_img;
+ }
+
+ if ( !isset($options["type"]) )
+ $options["type"] = "png";
+
+ $type = $options["type"];
+
+ ob_start();
+
+ switch ($type) {
+
+ case "jpg":
+ case "jpeg":
+ if ( !isset($options["quality"]) )
+ $options["quality"] = 75;
+
+ imagejpeg($dst, '', $options["quality"]);
+ break;
+
+ case "png":
+ default:
+ imagepng($dst);
+ break;
+ }
+
+ $image = ob_get_clean();
+
+ if ( $this->_aa_factor != 1 )
+ imagedestroy($dst);
+
+ return $image;
+ }
+
+
+}
diff --git a/application/third_party/dompdf/include/image_cache.cls.php b/application/third_party/dompdf/include/image_cache.cls.php
new file mode 100644
index 00000000..46dc0c66
--- /dev/null
+++ b/application/third_party/dompdf/include/image_cache.cls.php
@@ -0,0 +1,231 @@
+
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library in the file LICENSE.LGPL; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * Alternatively, you may distribute this software under the terms of the
+ * PHP License, version 3.0 or later. A copy of this license should have
+ * been distributed with this file in the file LICENSE.PHP . If this is not
+ * the case, you can obtain a copy at http://www.php.net/license/3_0.txt.
+ *
+ * The latest version of DOMPDF might be available at:
+ * http://www.dompdf.com/
+ *
+ * @link http://www.dompdf.com/
+ * @copyright 2004 Benj Carson
+ * @author Benj Carson
+ * Style->margin_top = "1em";
+ * echo (Style->margin_top);
+ *
+ *
+ * __set() automatically calls the provided set function, if one exists,
+ * otherwise it sets the property directly. Typically, __set() is not
+ * called directly from outside of this class.
+ *
+ * On each modification clear cache to return accurate setting.
+ * Also affects direct settings not using __set
+ * For easier finding all assignments, attempted to allowing only explicite assignment:
+ * Very many uses, e.g. frame_reflower.cls.php -> for now leave as it is
+ * function __set($prop, $val) {
+ * throw new DOMPDF_Exception("Implicite replacement of assignment by __set. Not good.");
+ * }
+ * function props_set($prop, $val) { ... }
+ *
+ * @param string $prop the property to set
+ * @param mixed $val the value of the property
+ *
+ */
+ function __set($prop, $val) {
+ $prop = str_replace("-", "_", $prop);
+ $this->_prop_cache[$prop] = null;
+
+ if ( !isset(self::$_defaults[$prop]) ) {
+ global $_dompdf_warnings;
+ $_dompdf_warnings[] = "'$prop' is not a valid CSS2 property.";
+ return;
+ }
+
+ if ( $prop !== "content" && is_string($val) && strlen($val) > 5 && mb_strpos($val, "url") === false ) {
+ $val = mb_strtolower(trim(str_replace(array("\n", "\t"), array(" "), $val)));
+ $val = preg_replace("/([0-9]+) (pt|px|pc|em|ex|in|cm|mm|%)/S", "\\1\\2", $val);
+ }
+
+ $method = "set_$prop";
+
+ if ( method_exists($this, $method) )
+ $this->$method($val);
+ else
+ $this->_props[$prop] = $val;
+ }
+
+ /**
+ * PHP5 overloaded getter
+ *
+ * Along with {@link Style::__set()} __get() provides access to all CSS
+ * properties directly. Typically __get() is not called directly outside
+ * of this class.
+ *
+ * On each modification clear cache to return accurate setting.
+ * Also affects direct settings not using __set
+ *
+ * @param string $prop
+ * @return mixed
+ */
+ function __get($prop) {
+ if ( !isset(self::$_defaults[$prop]) )
+ throw new DOMPDF_Exception("'$prop' is not a valid CSS2 property.");
+
+ if ( isset($this->_prop_cache[$prop]) && $this->_prop_cache[$prop] != null )
+ return $this->_prop_cache[$prop];
+
+ $method = "get_$prop";
+
+ // Fall back on defaults if property is not set
+ if ( !isset($this->_props[$prop]) )
+ $this->_props[$prop] = self::$_defaults[$prop];
+
+ if ( method_exists($this, $method) )
+ return $this->_prop_cache[$prop] = $this->$method();
+
+ return $this->_prop_cache[$prop] = $this->_props[$prop];
+ }
+
+
+ /**
+ * Getter for the 'font-family' CSS property.
+ *
+ * Uses the {@link Font_Metrics} class to resolve the font family into an
+ * actual font file.
+ *
+ * @link http://www.w3.org/TR/CSS21/fonts.html#propdef-font-family
+ * @return string
+ */
+ function get_font_family() {
+
+ $DEBUGCSS=DEBUGCSS; //=DEBUGCSS; Allow override of global setting for ad hoc debug
+
+ // Select the appropriate font. First determine the subtype, then check
+ // the specified font-families for a candidate.
+
+ // Resolve font-weight
+ $weight = $this->__get("font_weight");
+
+ if ( is_numeric($weight) ) {
+
+ if ( $weight < 600 )
+ $weight = "normal";
+ else
+ $weight = "bold";
+
+ } else if ( $weight === "bold" || $weight === "bolder" ) {
+ $weight = "bold";
+
+ } else {
+ $weight = "normal";
+
+ }
+
+ // Resolve font-style
+ $font_style = $this->__get("font_style");
+
+ if ( $weight === "bold" && ($font_style === "italic" || $font_style === "oblique") )
+ $subtype = "bold_italic";
+ else if ( $weight === "bold" && $font_style !== "italic" && $font_style !== "oblique" )
+ $subtype = "bold";
+ else if ( $weight !== "bold" && ($font_style === "italic" || $font_style === "oblique") )
+ $subtype = "italic";
+ else
+ $subtype = "normal";
+
+ // Resolve the font family
+ if ($DEBUGCSS) {
+ print "[get_font_family:";
+ print '('.$this->_props["font_family"].'.'.$font_style.'.'.$this->__get("font_weight").'.'.$weight.'.'.$subtype.')';
+ }
+ $families = explode(",", $this->_props["font_family"]);
+ $families = array_map('trim',$families);
+ reset($families);
+
+ $font = null;
+ while ( current($families) ) {
+ list(,$family) = each($families);
+ //remove leading and trailing string delimiters, e.g. on font names with spaces;
+ //remove leading and trailing whitespace
+ $family=trim($family," \t\n\r\x0B\"'");
+ if ($DEBUGCSS) print '('.$family.')';
+ $font = Font_Metrics::get_font($family, $subtype);
+
+ if ( $font ) {
+ if ($DEBUGCSS) print '('.$font.")get_font_family]\n";
+ return $font;
+ }
+ }
+
+ $family = null;
+ if ($DEBUGCSS) print '(default)';
+ $font = Font_Metrics::get_font($family, $subtype);
+
+ if ( $font ) {
+ if ($DEBUGCSS) print '('.$font.")get_font_family]\n";
+ return $font;
+ }
+ throw new DOMPDF_Exception("Unable to find a suitable font replacement for: '" . $this->_props["font_family"] ."'");
+
+ }
+
+ /**
+ * Returns the resolved font size, in points
+ *
+ * @link http://www.w3.org/TR/CSS21/fonts.html#propdef-font-size
+ * @return float
+ */
+ function get_font_size() {
+
+ if ( $this->__font_size_calculated )
+ return $this->_props["font_size"];
+
+ if ( !isset($this->_props["font_size"]) )
+ $fs = self::$_defaults["font_size"];
+ else
+ $fs = $this->_props["font_size"];
+
+ if ( !isset($this->_parent_font_size) )
+ $this->_parent_font_size = self::$default_font_size;
+
+ switch ($fs) {
+ case "xx-small":
+ case "x-small":
+ case "small":
+ case "medium":
+ case "large":
+ case "x-large":
+ case "xx-large":
+ $fs = self::$default_font_size * self::$font_size_keywords[$fs];
+ break;
+
+ case "smaller":
+ $fs = 8/9 * $this->_parent_font_size;
+ break;
+
+ case "larger":
+ $fs = 6/5 * $this->_parent_font_size;
+ break;
+
+ default:
+ break;
+ }
+
+ // Ensure relative sizes resolve to something
+ if ( ($i = mb_strpos($fs, "em")) !== false )
+ $fs = mb_substr($fs, 0, $i) * $this->_parent_font_size;
+
+ else if ( ($i = mb_strpos($fs, "ex")) !== false )
+ $fs = mb_substr($fs, 0, $i) * $this->_parent_font_size;
+
+ else
+ $fs = $this->length_in_pt($fs);
+
+ //see __set and __get, on all assignments clear cache!
+ $this->_prop_cache["font_size"] = null;
+ $this->_props["font_size"] = $fs;
+ $this->__font_size_calculated = true;
+ return $this->_props["font_size"];
+
+ }
+
+ /**
+ * @link http://www.w3.org/TR/CSS21/text.html#propdef-word-spacing
+ * @return float
+ */
+ function get_word_spacing() {
+ if ( $this->_props["word_spacing"] === "normal" )
+ return 0;
+
+ return $this->_props["word_spacing"];
+ }
+
+ /**
+ * @link http://www.w3.org/TR/CSS21/text.html#propdef-letter-spacing
+ * @return float
+ */
+ function get_letter_spacing() {
+ if ( $this->_props["letter_spacing"] === "normal" )
+ return 0;
+
+ return $this->_props["letter_spacing"];
+ }
+
+ /**
+ * @link http://www.w3.org/TR/CSS21/visudet.html#propdef-line-height
+ * @return float
+ */
+ function get_line_height() {
+ $line_height = $this->_props["line_height"];
+
+ if ( $line_height === "normal" )
+ return self::$default_line_height * $this->get_font_size();
+
+ if ( is_numeric($line_height) )
+ return $this->length_in_pt( $line_height . "em", $this->get_font_size());
+
+ return $this->length_in_pt( $line_height, $this->get_font_size() );
+ }
+
+ /**
+ * Returns the colour as an array
+ *
+ * The array has the following format:
+ * array(r,g,b, "r" => r, "g" => g, "b" => b, "hex" => "#rrggbb")
+ *
+ * @link http://www.w3.org/TR/CSS21/colors.html#propdef-color
+ * @return array
+ */
+ function get_color() {
+ return $this->munge_color( $this->_props["color"] );
+ }
+
+ /**
+ * Returns the background colour as an array
+ *
+ * The returned array has the same format as {@link Style::get_color()}
+ *
+ * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-color
+ * @return array
+ */
+ function get_background_color() {
+ return $this->munge_color( $this->_props["background_color"] );
+ }
+
+ /**
+ * Returns the background position as an array
+ *
+ * The returned array has the following format:
+ * array(x,y, "x" => x, "y" => y)
+ *
+ * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-position
+ * @return array
+ */
+ function get_background_position() {
+ $tmp = explode(" ", $this->_props["background_position"]);
+
+ switch ($tmp[0]) {
+
+ case "left":
+ $x = "0%";
+ break;
+
+ case "right":
+ $x = "100%";
+ break;
+
+ case "top":
+ $y = "0%";
+ break;
+
+ case "bottom":
+ $y = "100%";
+ break;
+
+ case "center":
+ $x = "50%";
+ $y = "50%";
+ break;
+
+ default:
+ $x = $tmp[0];
+ break;
+ }
+
+ if ( isset($tmp[1]) ) {
+
+ switch ($tmp[1]) {
+ case "left":
+ $x = "0%";
+ break;
+
+ case "right":
+ $x = "100%";
+ break;
+
+ case "top":
+ $y = "0%";
+ break;
+
+ case "bottom":
+ $y = "100%";
+ break;
+
+ case "center":
+ if ( $tmp[0] === "left" || $tmp[0] === "right" || $tmp[0] === "center" )
+ $y = "50%";
+ else
+ $x = "50%";
+ break;
+
+ default:
+ $y = $tmp[1];
+ break;
+ }
+
+ } else {
+ $y = "50%";
+ }
+
+ if ( !isset($x) )
+ $x = "0%";
+
+ if ( !isset($y) )
+ $y = "0%";
+
+ return array( 0 => $x, "x" => $x,
+ 1 => $y, "y" => $y );
+ }
+
+
+ /**
+ * Returns the background as it is currently stored
+ *
+ * (currently anyway only for completeness.
+ * not used for further processing)
+ *
+ * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-attachment
+ * @return string
+ */
+ function get_background_attachment() {
+ return $this->_props["background_attachment"];
+ }
+
+
+ /**
+ * Returns the background_repeat as it is currently stored
+ *
+ * (currently anyway only for completeness.
+ * not used for further processing)
+ *
+ * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-repeat
+ * @return string
+ */
+ function get_background_repeat() {
+ return $this->_props["background_repeat"];
+ }
+
+
+ /**
+ * Returns the background as it is currently stored
+ *
+ * (currently anyway only for completeness.
+ * not used for further processing, but the individual get_background_xxx)
+ *
+ * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background
+ * @return string
+ */
+ function get_background() {
+ return $this->_props["background"];
+ }
+
+
+ /**#@+
+ * Returns the border colour as an array
+ *
+ * See {@link Style::get_color()}
+ *
+ * @link http://www.w3.org/TR/CSS21/box.html#border-color-properties
+ * @return array
+ */
+ function get_border_top_color() {
+ if ( $this->_props["border_top_color"] === "" ) {
+ //see __set and __get, on all assignments clear cache!
+ $this->_prop_cache["border_top_color"] = null;
+ $this->_props["border_top_color"] = $this->__get("color");
+ }
+ return $this->munge_color($this->_props["border_top_color"]);
+ }
+
+ function get_border_right_color() {
+ if ( $this->_props["border_right_color"] === "" ) {
+ //see __set and __get, on all assignments clear cache!
+ $this->_prop_cache["border_right_color"] = null;
+ $this->_props["border_right_color"] = $this->__get("color");
+ }
+ return $this->munge_color($this->_props["border_right_color"]);
+ }
+
+ function get_border_bottom_color() {
+ if ( $this->_props["border_bottom_color"] === "" ) {
+ //see __set and __get, on all assignments clear cache!
+ $this->_prop_cache["border_bottom_color"] = null;
+ $this->_props["border_bottom_color"] = $this->__get("color");
+ }
+ return $this->munge_color($this->_props["border_bottom_color"]);
+ }
+
+ function get_border_left_color() {
+ if ( $this->_props["border_left_color"] === "" ) {
+ //see __set and __get, on all assignments clear cache!
+ $this->_prop_cache["border_left_color"] = null;
+ $this->_props["border_left_color"] = $this->__get("color");
+ }
+ return $this->munge_color($this->_props["border_left_color"]);
+ }
+
+ /**#@-*/
+
+ /**#@+
+ * Returns the border width, as it is currently stored
+ *
+ * @link http://www.w3.org/TR/CSS21/box.html#border-width-properties
+ * @return float|string
+ */
+ function get_border_top_width() {
+ $style = $this->__get("border_top_style");
+ return $style !== "none" && $style !== "hidden" ? $this->length_in_pt($this->_props["border_top_width"]) : 0;
+ }
+
+ function get_border_right_width() {
+ $style = $this->__get("border_right_style");
+ return $style !== "none" && $style !== "hidden" ? $this->length_in_pt($this->_props["border_right_width"]) : 0;
+ }
+
+ function get_border_bottom_width() {
+ $style = $this->__get("border_bottom_style");
+ return $style !== "none" && $style !== "hidden" ? $this->length_in_pt($this->_props["border_bottom_width"]) : 0;
+ }
+
+ function get_border_left_width() {
+ $style = $this->__get("border_left_style");
+ return $style !== "none" && $style !== "hidden" ? $this->length_in_pt($this->_props["border_left_width"]) : 0;
+ }
+ /**#@-*/
+
+ /**
+ * Return an array of all border properties.
+ *
+ * The returned array has the following structure:
+ *
+ * array("top" => array("width" => [border-width],
+ * "style" => [border-style],
+ * "color" => [border-color (array)]),
+ * "bottom" ... )
+ *
+ *
+ * @return array
+ */
+ function get_border_properties() {
+ return array("top" => array("width" => $this->__get("border_top_width"),
+ "style" => $this->__get("border_top_style"),
+ "color" => $this->__get("border_top_color")),
+ "bottom" => array("width" => $this->__get("border_bottom_width"),
+ "style" => $this->__get("border_bottom_style"),
+ "color" => $this->__get("border_bottom_color")),
+ "right" => array("width" => $this->__get("border_right_width"),
+ "style" => $this->__get("border_right_style"),
+ "color" => $this->__get("border_right_color")),
+ "left" => array("width" => $this->__get("border_left_width"),
+ "style" => $this->__get("border_left_style"),
+ "color" => $this->__get("border_left_color")));
+ }
+
+ /**
+ * Return a single border property
+ *
+ * @return mixed
+ */
+ protected function _get_border($side) {
+ $color = $this->__get("border_" . $side . "_color");
+
+ return $this->__get("border_" . $side . "_width") . " " .
+ $this->__get("border_" . $side . "_style") . " " . $color["hex"];
+ }
+
+ /**#@+
+ * Return full border properties as a string
+ *
+ * Border properties are returned just as specified in CSS:
+ * [width] [style] [color]+ * e.g. "1px solid blue" + * + * @link http://www.w3.org/TR/CSS21/box.html#border-shorthand-properties + * @return string + */ + function get_border_top() { return $this->_get_border("top"); } + function get_border_right() { return $this->_get_border("right"); } + function get_border_bottom() { return $this->_get_border("bottom"); } + function get_border_left() { return $this->_get_border("left"); } + /**#@-*/ + + /** + * Returns the outline colour as an array + * + * See {@link Style::get_color()} + * + * @link http://www.w3.org/TR/CSS21/box.html#border-color-properties + * @return array + */ + function get_outline_color() { + if ( $this->_props["outline_color"] === "" ) { + //see __set and __get, on all assignments clear cache! + $this->_prop_cache["outline_color"] = null; + $this->_props["outline_color"] = $this->__get("color"); + } + return $this->munge_color($this->_props["outline_color"]); + } + + /**#@+ + * Returns the outline width, as it is currently stored + * @return float|string + */ + function get_outline_width() { + $style = $this->__get("outline_style"); + return $style !== "none" && $style !== "hidden" ? $this->length_in_pt($this->_props["outline_width"]) : 0; + } + + /**#@+ + * Return full outline properties as a string + * + * Outline properties are returned just as specified in CSS: + *
[width] [style] [color]+ * e.g. "1px solid blue" + * + * @link http://www.w3.org/TR/CSS21/box.html#border-shorthand-properties + * @return string + */ + function get_outline() { + $color = $this->__get("outline_color"); + return + $this->__get("outline_width") . " " . + $this->__get("outline_style") . " " . + $color["hex"]; + } + /**#@-*/ + + /** + * Returns border spacing as an array + * + * The array has the format (h_space,v_space) + * + * @link http://www.w3.org/TR/CSS21/tables.html#propdef-border-spacing + * @return array + */ + function get_border_spacing() { + return explode(" ", $this->_props["border_spacing"]); + } + +/*==============================*/ + + /* + !important attribute + For basic functionality of the !important attribute with overloading + of several styles of an element, changes in inherit(), merge() and _parse_properties() + are sufficient [helpers var $_important_props, __construct(), important_set(), important_get()] + + Only for combined attributes extra treatment needed. See below. + + div { border: 1px red; } + div { border: solid; } // Not combined! Only one occurence of same style per context + // + div { border: 1px red; } + div a { border: solid; } // Adding to border style ok by inheritance + // + div { border-style: solid; } // Adding to border style ok because of different styles + div { border: 1px red; } + // + div { border-style: solid; !important} // border: overrides, even though not !important + div { border: 1px dashed red; } + // + div { border: 1px red; !important } + div a { border-style: solid; } // Need to override because not set + + Special treatment: + At individual property like border-top-width need to check whether overriding value is also !important. + Also store the !important condition for later overrides. + Since not known who is initiating the override, need to get passed !importan as parameter. + !important Paramter taken as in the original style in the css file. + When poperty border !important given, do not mark subsets like border_style as important. Only + individual properties. + + Note: + Setting individual property directly from css with e.g. set_border_top_style() is not needed, because + missing set funcions handled by a generic handler __set(), including the !important. + Setting individual property of as sub-property is handled below. + + Implementation see at _set_style_side_type() + Callers _set_style_sides_type(), _set_style_type, _set_style_type_important() + + Related functionality for background, padding, margin, font, list_style + */ + + /* Generalized set function for individual attribute of combined style. + * With check for !important + * Applicable for background, border, padding, margin, font, list_style + * Note: $type has a leading underscore (or is empty), the others not. + */ + protected function _set_style_side_type($style,$side,$type,$val,$important) { + $prop = $style.'_'.$side.$type; + + if ( !isset($this->_important_props[$prop]) || $important) { + //see __set and __get, on all assignments clear cache! + $this->_prop_cache[$prop] = null; + if ($important) { + $this->_important_props[$prop] = true; + } + $this->_props[$prop] = $val; + } + } + + protected function _set_style_sides_type($style,$top,$right,$bottom,$left,$type,$important) { + $this->_set_style_side_type($style,'top',$type,$top,$important); + $this->_set_style_side_type($style,'right',$type,$right,$important); + $this->_set_style_side_type($style,'bottom',$type,$bottom,$important); + $this->_set_style_side_type($style,'left',$type,$left,$important); + } + + protected function _set_style_type($style,$type,$val,$important) { + $arr = explode(" ", $val); + switch (count($arr)) { + case 1: + $this->_set_style_sides_type($style,$arr[0],$arr[0],$arr[0],$arr[0],$type,$important); + break; + case 2: + $this->_set_style_sides_type($style,$arr[0],$arr[1],$arr[0],$arr[1],$type,$important); + break; + case 3: + $this->_set_style_sides_type($style,$arr[0],$arr[1],$arr[2],$arr[1],$type,$important); + break; + case 4: + $this->_set_style_sides_type($style,$arr[0],$arr[1],$arr[2],$arr[3],$type,$important); + break; + default: + break; + } + //see __set and __get, on all assignments clear cache! + $this->_prop_cache[$style.$type] = null; + $this->_props[$style.$type] = $val; + } + + protected function _set_style_type_important($style,$type,$val) { + $this->_set_style_type($style,$type,$val,isset($this->_important_props[$style.$type])); + } + + /* Anyway only called if _important matches and is assigned + * E.g. _set_style_side_type($style,$side,'',str_replace("none", "0px", $val),isset($this->_important_props[$style.'_'.$side])); + */ + protected function _set_style_side_width_important($style,$side,$val) { + //see __set and __get, on all assignments clear cache! + $this->_prop_cache[$style.'_'.$side] = null; + $this->_props[$style.'_'.$side] = str_replace("none", "0px", $val); + } + + protected function _set_style($style,$val,$important) { + if ( !isset($this->_important_props[$style]) || $important) { + if ($important) { + $this->_important_props[$style] = true; + } + //see __set and __get, on all assignments clear cache! + $this->_prop_cache[$style] = null; + $this->_props[$style] = $val; + } + } + + protected function _image($val) { + $DEBUGCSS=DEBUGCSS; + + 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 = 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 = build_url($this->_stylesheet->get_protocol(), + $this->_stylesheet->get_host(), + $this->_stylesheet->get_base_path(), + $val); + } + } + if ($DEBUGCSS) { + print "
[_image\n"; + print_r($parsed_url); + print $this->_stylesheet->get_protocol()."\n".$this->_stylesheet->get_base_path()."\n".$path."\n"; + print "_image]";; + } + return $path; + } + +/*======================*/ + + /** + * Sets colour + * + * The colour parameter can be any valid CSS colour value + * + * @link http://www.w3.org/TR/CSS21/colors.html#propdef-color + * @param string $colour + */ + function set_color($colour) { + $col = $this->munge_colour($colour); + + if ( is_null($col) ) + $col = self::$_defaults["color"]; + + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["color"] = null; + $this->_props["color"] = $col["hex"]; + } + + /** + * Sets the background colour + * + * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-color + * @param string $colour + */ + function set_background_color($colour) { + $col = $this->munge_colour($colour); + if ( is_null($col) ) + $col = self::$_defaults["background_color"]; + + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["background_color"] = null; + $this->_props["background_color"] = is_array($col) ? $col["hex"] : $col; + } + + /** + * Set the background image url + * + * @link http://www.w3.org/TR/CSS21/colors.html#background-properties + * @param string $url + */ + function set_background_image($val) { + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["background_image"] = null; + $this->_props["background_image"] = $this->_image($val); + } + + /** + * Sets the background repeat + * + * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-repeat + * @param string $val + */ + function set_background_repeat($val) { + if ( is_null($val) ) + $val = self::$_defaults["background_repeat"]; + + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["background_repeat"] = null; + $this->_props["background_repeat"] = $val; + } + + /** + * Sets the background attachment + * + * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-attachment + * @param string $val + */ + function set_background_attachment($val) { + if ( is_null($val) ) + $val = self::$_defaults["background_attachment"]; + + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["background_attachment"] = null; + $this->_props["background_attachment"] = $val; + } + + /** + * Sets the background position + * + * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-position + * @param string $val + */ + function set_background_position($val) { + if ( is_null($val) ) + $val = self::$_defaults["background_position"]; + + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["background_position"] = null; + $this->_props["background_position"] = $val; + } + + /** + * Sets the background - combined options + * + * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background + * @param string $val + */ + function set_background($val) { + $col = null; + $pos = array(); + $tmp = preg_replace("/\s*\,\s*/", ",", $val); // when rgb() has spaces + $tmp = explode(" ", $tmp); + $important = isset($this->_important_props["background"]); + + foreach($tmp as $attr) { + if (mb_substr($attr, 0, 3) === "url" || $attr === "none") { + $this->_set_style("background_image", $this->_image($attr), $important); + } else if ($attr === "fixed" || $attr === "scroll") { + $this->_set_style("background_attachment", $attr, $important); + } else if ($attr === "repeat" || $attr === "repeat-x" || $attr === "repeat-y" || $attr === "no-repeat") { + $this->_set_style("background_repeat", $attr, $important); + } else if (($col = $this->munge_color($attr)) != null ) { + $this->_set_style("background_color", is_array($col) ? $col["hex"] : $col, $important); + } else { + $pos[] = $attr; + } + } + + if (count($pos)) { + $this->_set_style("background_position",implode(' ',$pos), $important); + } + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["background"] = null; + $this->_props["background"] = $val; + } + + /** + * Sets the font size + * + * $size can be any acceptable CSS size + * + * @link http://www.w3.org/TR/CSS21/fonts.html#propdef-font-size + * @param string|float $size + */ + function set_font_size($size) { + $this->__font_size_calculated = false; + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["font_size"] = null; + $this->_props["font_size"] = $size; + } + + /** + * Sets the font style + * + * combined attributes + * set individual attributes also, respecting !important mark + * exactly this order, separate by space. Multiple fonts separated by comma: + * font-style, font-variant, font-weight, font-size, line-height, font-family + * + * Other than with border and list, existing partial attributes should + * reset when starting here, even when not mentioned. + * If individual attribute is !important and explicite or implicite replacement is not, + * keep individual attribute + * + * require whitespace as delimiters for single value attributes + * On delimiter "/" treat first as font height, second as line height + * treat all remaining at the end of line as font + * font-style, font-variant, font-weight, font-size, line-height, font-family + * + * missing font-size and font-family might be not allowed, but accept it here and + * use default (medium size, enpty font name) + * + * @link http://www.w3.org/TR/CSS21/generate.html#propdef-list-style + * @param $val + */ + function set_font($val) { + $this->__font_size_calculated = false; + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["font"] = null; + $this->_props["font"] = $val; + + $important = isset($this->_important_props["font"]); + + if ( preg_match("/^(italic|oblique|normal)\s*(.*)$/i",$val,$match) ) { + $this->_set_style("font_style", $match[1], $important); + $val = $match[2]; + } else { + $this->_set_style("font_style", self::$_defaults["font_style"], $important); + } + + if ( preg_match("/^(small-caps|normal)\s*(.*)$/i",$val,$match) ) { + $this->_set_style("font_variant", $match[1], $important); + $val = $match[2]; + } else { + $this->_set_style("font_variant", self::$_defaults["font_variant"], $important); + } + + //matching numeric value followed by unit -> this is indeed a subsequent font size. Skip! + if ( preg_match("/^(bold|bolder|lighter|100|200|300|400|500|600|700|800|900|normal)\s*(.*)$/i",$val,$match) && + !preg_match("/^(?:pt|px|pc|em|ex|in|cm|mm|%)/",$match[2]) + ) { + $this->_set_style("font_weight", $match[1], $important); + $val = $match[2]; + } else { + $this->_set_style("font_weight", self::$_defaults["font_weight"], $important); + } + + if ( preg_match("/^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger|\d+\s*(?:pt|px|pc|em|ex|in|cm|mm|%))\s*(.*)$/i",$val,$match) ) { + $this->_set_style("font_size", $match[1], $important); + $val = $match[2]; + if (preg_match("/^\/\s*(\d+\s*(?:pt|px|pc|em|ex|in|cm|mm|%))\s*(.*)$/i",$val,$match) ) { + $this->_set_style("line_height", $match[1], $important); + $val = $match[2]; + } else { + $this->_set_style("line_height", self::$_defaults["line_height"], $important); + } + } else { + $this->_set_style("font_size", self::$_defaults["font_size"], $important); + $this->_set_style("line_height", self::$_defaults["line_height"], $important); + } + + if(strlen($val) != 0) { + $this->_set_style("font_family", $val, $important); + } else { + $this->_set_style("font_family", self::$_defaults["font_family"], $important); + } + } + + /**#@+ + * Sets page break properties + * + * @link http://www.w3.org/TR/CSS21/page.html#page-breaks + * @param string $break + */ + function set_page_break_before($break) { + if ($break === "left" || $break === "right") + $break = "always"; + + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["page_break_before"] = null; + $this->_props["page_break_before"] = $break; + } + + function set_page_break_after($break) { + if ($break === "left" || $break === "right") + $break = "always"; + + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["page_break_after"] = null; + $this->_props["page_break_after"] = $break; + } + /**#@-*/ + + //........................................................................ + + /**#@+ + * Sets the margin size + * + * @link http://www.w3.org/TR/CSS21/box.html#margin-properties + * @param $val + */ + function set_margin_top($val) { + $this->_set_style_side_width_important('margin','top',$val); + } + + function set_margin_right($val) { + $this->_set_style_side_width_important('margin','right',$val); + } + + function set_margin_bottom($val) { + $this->_set_style_side_width_important('margin','bottom',$val); + } + + function set_margin_left($val) { + $this->_set_style_side_width_important('margin','left',$val); + } + + function set_margin($val) { + $val = str_replace("none", "0px", $val); + $this->_set_style_type_important('margin','',$val); + } + /**#@-*/ + + /**#@+ + * Sets the padding size + * + * @link http://www.w3.org/TR/CSS21/box.html#padding-properties + * @param $val + */ + function set_padding_top($val) { + $this->_set_style_side_width_important('padding','top',$val); + } + + function set_padding_right($val) { + $this->_set_style_side_width_important('padding','right',$val); + } + + function set_padding_bottom($val) { + $this->_set_style_side_width_important('padding','bottom',$val); + } + + function set_padding_left($val) { + $this->_set_style_side_width_important('padding','left',$val); + } + + function set_padding($val) { + $val = str_replace("none", "0px", $val); + $this->_set_style_type_important('padding','',$val); + } + /**#@-*/ + + /** + * Sets a single border + * + * @param string $side + * @param string $border_spec ([width] [style] [color]) + */ + protected function _set_border($side, $border_spec, $important) { + $border_spec = preg_replace("/\s*\,\s*/", ",", $border_spec); + //$border_spec = str_replace(",", " ", $border_spec); // Why did we have this ?? rbg(10, 102, 10) > rgb(10 102 10) + $arr = explode(" ", $border_spec); + + // FIXME: handle partial values + + //For consistency of individal and combined properties, and with ie8 and firefox3 + //reset all attributes, even if only partially given + $this->_set_style_side_type('border',$side,'_style',self::$_defaults['border_'.$side.'_style'],$important); + $this->_set_style_side_type('border',$side,'_width',self::$_defaults['border_'.$side.'_width'],$important); + $this->_set_style_side_type('border',$side,'_color',self::$_defaults['border_'.$side.'_color'],$important); + + foreach ($arr as $value) { + $value = trim($value); + if ( in_array($value, self::$BORDER_STYLES) ) { + $this->_set_style_side_type('border',$side,'_style',$value,$important); + + } else if ( preg_match("/[.0-9]+(?:px|pt|pc|em|ex|%|in|mm|cm)|(?:thin|medium|thick)/", $value ) ) { + $this->_set_style_side_type('border',$side,'_width',$value,$important); + + } else { + // must be colour + $this->_set_style_side_type('border',$side,'_color',$value,$important); + } + } + + //see __set and __get, on all assignments clear cache! + $this->_prop_cache['border_'.$side] = null; + $this->_props['border_'.$side] = $border_spec; + } + + /**#@+ + * Sets the border styles + * + * @link http://www.w3.org/TR/CSS21/box.html#border-properties + * @param string $val + */ + function set_border_top($val) { $this->_set_border("top", $val, isset($this->_important_props['border_top'])); } + function set_border_right($val) { $this->_set_border("right", $val, isset($this->_important_props['border_right'])); } + function set_border_bottom($val) { $this->_set_border("bottom", $val, isset($this->_important_props['border_bottom'])); } + function set_border_left($val) { $this->_set_border("left", $val, isset($this->_important_props['border_left'])); } + + function set_border($val) { + $important = isset($this->_important_props["border"]); + $this->_set_border("top", $val, $important); + $this->_set_border("right", $val, $important); + $this->_set_border("bottom", $val, $important); + $this->_set_border("left", $val, $important); + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["border"] = null; + $this->_props["border"] = $val; + } + + function set_border_width($val) { + $this->_set_style_type_important('border','_width',$val); + } + + function set_border_color($val) { + $this->_set_style_type_important('border','_color',$val); + } + + function set_border_style($val) { + $this->_set_style_type_important('border','_style',$val); + } + + /**#@+ + * Sets the outline styles + * + * @link http://www.w3.org/TR/CSS21/ui.html#dynamic-outlines + * @param string $val + */ + function set_outline($val) { + $important = isset($this->_important_props["outline"]); + + $props = array( + "outline_style", + "outline_width", + "outline_color", + ); + + foreach($props as $prop) { + $_val = self::$_defaults[$prop]; + + if ( !isset($this->_important_props[$prop]) || $important) { + //see __set and __get, on all assignments clear cache! + $this->_prop_cache[$prop] = null; + if ($important) { + $this->_important_props[$prop] = true; + } + $this->_props[$prop] = $_val; + } + } + + $val = preg_replace("/\s*\,\s*/", ",", $val); // when rgb() has spaces + $arr = explode(" ", $val); + foreach ($arr as $value) { + $value = trim($value); + if ( in_array($value, self::$BORDER_STYLES) ) { + $this->set_outline_style($value); + } else if ( preg_match("/[.0-9]+(?:px|pt|pc|em|ex|%|in|mm|cm)|(?:thin|medium|thick)/", $value ) ) { + $this->set_outline_width($value); + } else { + // must be colour + $this->set_outline_color($value); + } + } + + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["outline"] = null; + $this->_props["outline"] = $val; + } + + function set_outline_width($val) { + $this->_set_style_type_important('outline','_width',$val); + } + + function set_outline_color($val) { + $this->_set_style_type_important('outline','_color',$val); + } + + function set_outline_style($val) { + $this->_set_style_type_important('outline','_style',$val); + } + /**#@-*/ + + + /** + * Sets the border spacing + * + * @link http://www.w3.org/TR/CSS21/box.html#border-properties + * @param float $val + */ + function set_border_spacing($val) { + $arr = explode(" ", $val); + + if ( count($arr) == 1 ) + $arr[1] = $arr[0]; + + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["border_spacing"] = null; + $this->_props["border_spacing"] = "$arr[0] $arr[1]"; + } + + /** + * Sets the list style image + * + * @link http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-image + * @param $val + */ + function set_list_style_image($val) { + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["list_style_image"] = null; + $this->_props["list_style_image"] = $this->_image($val); + } + + /** + * Sets the list style + * + * @link http://www.w3.org/TR/CSS21/generate.html#propdef-list-style + * @param $val + */ + 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) { + /* http://www.w3.org/TR/CSS21/generate.html#list-style + * A value of 'none' for the 'list-style' property sets both 'list-style-type' and 'list-style-image' to 'none' + */ + if ($value === "none") { + $this->_set_style("list_style_type", $value, $important); + $this->_set_style("list_style_image", $value, $important); + continue; + } + + //On setting or merging or inheriting list_style_image as well as list_style_type, + //and url exists, then url has precedence, otherwise fall back to list_style_type + //Firefox is wrong here (list_style_image gets overwritten on explicite list_style_type) + //Internet Explorer 7/8 and dompdf is right. + + if (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); + } + } + + //see __set and __get, on all assignments clear cache, not needed on direct set through __set + $this->_prop_cache["list_style"] = null; + $this->_props["list_style"] = $val; + } + + function set_size($val) { + $length_re = "/(\d+\s*(?:pt|px|pc|em|ex|in|cm|mm|%))/"; + + $val = mb_strtolower($val); + + if ( $val === "auto" ) { + return; + } + + $parts = preg_split("/\s+/", $val); + + $computed = array(); + if ( preg_match($length_re, $parts[0]) ) { + $computed[] = $this->length_in_pt($parts[0]); + + if ( isset($parts[1]) && preg_match($length_re, $parts[1]) ) { + $computed[] = $this->length_in_pt($parts[1]); + } + else { + $computed[] = $computed[0]; + } + } + elseif ( isset(CPDF_Adapter::$PAPER_SIZES[$parts[0]]) ) { + $computed = array_slice(CPDF_Adapter::$PAPER_SIZES[$parts[0]], 2, 2); + + if ( isset($parts[1]) && $parts[1] === "landscape" ) { + $computed = array_reverse($computed); + } + } + else { + return; + } + + $this->_props["size"] = $computed; + } + + /** + * Sets the CSS3 transform property + * + * @link http://www.w3.org/TR/css3-2d-transforms/#transform-property + * @param string $val + */ + function set_transform($val) { + $number = "\s*([^,\s]+)\s*"; + $tr_value = "\s*([^,\s]+)\s*"; + $angle = "\s*([^,\s]+(?:deg|rad)?)\s*"; + + if( !preg_match_all("/[a-z]+\([^\)]+\)/i", $val, $parts, PREG_SET_ORDER) ) { + return; + } + + $functions = array( + //"matrix" => "\($number,$number,$number,$number,$number,$number\)", + + "translate" => "\($tr_value(?:,$tr_value)?\)", + "translateX" => "\($tr_value\)", + "translateY" => "\($tr_value\)", + + "scale" => "\($number(?:,$number)?\)", + "scaleX" => "\($number\)", + "scaleY" => "\($number\)", + + "rotate" => "\($angle\)", + + "skew" => "\($angle(?:,$angle)?\)", + "skewX" => "\($angle\)", + "skewY" => "\($angle\)", + ); + + $transforms = array(); + + foreach($parts as $part) { + $t = $part[0]; + + foreach($functions as $name => $pattern) { + if (preg_match("/$name\s*$pattern/i", $t, $matches)) { + $values = array_slice($matches, 1); + + switch($name) { + //
\n";
+ /*DEBUGCSS*/ printf("_specificity(): 0x%08x \"%s\"\n", ($a << 24) | ($b << 16) | ($c << 8) | ($d), $selector);
+ /*DEBUGCSS*/ print "";
+ }
+
+ return ($a << 24) | ($b << 16) | ($c << 8) | ($d);
+ }
+
+ /**
+ * converts a CSS selector to an XPath query.
+ *
+ * @param string $selector
+ * @return string
+ */
+ private function _css_selector_to_xpath($selector, $first_pass = false) {
+
+ // Collapse white space and strip whitespace around delimiters
+// $search = array("/\\s+/", "/\\s+([.>#+:])\\s+/");
+// $replace = array(" ", "\\1");
+// $selector = preg_replace($search, $replace, trim($selector));
+
+ // Initial query (non-absolute)
+ $query = "//";
+
+ // Will contain :before and :after if they must be created
+ $pseudo_elements = array();
+
+ // Parse the selector
+ //$s = preg_split("/([ :>.#+])/", $selector, -1, PREG_SPLIT_DELIM_CAPTURE);
+
+ $delimiters = array(" ", ">", ".", "#", "+", ":", "[");
+
+ // Add an implicit * at the beginning of the selector
+ // if it begins with an attribute selector
+ if ( $selector[0] === "[" )
+ $selector = "*$selector";
+
+ // Add an implicit space at the beginning of the selector if there is no
+ // delimiter there already.
+ if ( !in_array($selector[0], $delimiters) )
+ $selector = " $selector";
+
+ $tok = "";
+ $len = mb_strlen($selector);
+ $i = 0;
+
+ while ( $i < $len ) {
+
+ $s = $selector[$i];
+ $i++;
+
+ // Eat characters up to the next delimiter
+ $tok = "";
+ $in_attr = false;
+
+ while ($i < $len) {
+ $c = $selector[$i];
+ $c_prev = $selector[$i-1];
+
+ if ( !$in_attr && in_array($c, $delimiters) )
+ break;
+
+ if ( $c_prev === "[" ) {
+ $in_attr = true;
+ }
+
+ $tok .= $selector[$i++];
+ }
+
+ switch ($s) {
+
+ case " ":
+ case ">":
+ // All elements matching the next token that are direct children of
+ // the current token
+ $expr = $s === " " ? "descendant" : "child";
+
+ if ( mb_substr($query, -1, 1) !== "/" )
+ $query .= "/";
+
+ if ( !$tok )
+ $tok = "*";
+
+ $query .= "$expr::$tok";
+ $tok = "";
+ break;
+
+ case ".":
+ case "#":
+ // All elements matching the current token with a class/id equal to
+ // the _next_ token.
+
+ $attr = $s === "." ? "class" : "id";
+
+ // empty class/id == *
+ if ( mb_substr($query, -1, 1) === "/" )
+ $query .= "*";
+
+ // Match multiple classes: $tok contains the current selected
+ // class. Search for class attributes with class="$tok",
+ // class=".* $tok .*" and class=".* $tok"
+
+ // This doesn't work because libxml only supports XPath 1.0...
+ //$query .= "[matches(@$attr,\"^${tok}\$|^${tok}[ ]+|[ ]+${tok}\$|[ ]+${tok}[ ]+\")]";
+
+ // Query improvement by Michael Sheakoski \n[$debug_nodename\n";
+ foreach ($applied_styles as $spec => $arr) {
+ printf("specificity: 0x%08x\n",$spec);
+ foreach ($arr as $s) {
+ print "[\n";
+ $s->debug_print();
+ print "]\n";
+ }
+ }
+ }
+
+ // Merge the new styles with the inherited styles
+ foreach ($applied_styles as $arr) {
+ foreach ($arr as $s)
+ $style->merge($s);
+ }
+ }
+
+ // Inherit parent's styles if required
+ if ( $p ) {
+
+ if (DEBUGCSS) {
+ print "inherit:\n";
+ print "[\n";
+ $p->get_style()->debug_print();
+ print "]\n";
+ }
+
+ $style->inherit( $p->get_style() );
+ }
+
+ if (DEBUGCSS) {
+ print "DomElementStyle:\n";
+ print "[\n";
+ $style->debug_print();
+ print "]\n";
+ print "/$debug_nodename]\n";
+ }
+
+ /*DEBUGCSS print: see below different print debugging method
+ pre_r($frame->get_node()->nodeName . ":");
+ echo ""; + echo $style; + echo "";*/ + $frame->set_style($style); + + } + + // We're done! Clean out the registry of all styles since we + // won't be needing this later. + foreach ( array_keys($this->_styles) as $key ) { + $this->_styles[$key] = null; + unset($this->_styles[$key]); + } + + } + + + /** + * parse a CSS string using a regex parser + * + * Called by {@link Stylesheet::parse_css()} + * + * @param string $str + */ + private function _parse_css($str) { + + $str = trim($str); + + // Destroy comments and remove HTML comments + $css = preg_replace(array( + "'/\*.*?\*/'si", + "/^$/" + ), "", $str); + + // FIXME: handle '{' within strings, e.g. [attr="string {}"] + + // Something more legible: + $re = + "/\s* # Skip leading whitespace \n". + "( @([^\s]+)\s+([^{;]*) (?:;|({)) )? # Match @rules followed by ';' or '{' \n". + "(?(1) # Only parse sub-sections if we're in an @rule... \n". + " (?(4) # ...and if there was a leading '{' \n". + " \s*( (?:(?>[^{}]+) ({)? # Parse rulesets and individual @page rules \n". + " (?(6) (?>[^}]*) }) \s*)+? \n". + " ) \n". + " }) # Balancing '}' \n". + "| # Branch to match regular rules (not preceeded by '@')\n". + "([^{]*{[^}]*})) # Parse normal rulesets\n". + "/xs"; + + if ( preg_match_all($re, $css, $matches, PREG_SET_ORDER) === false ) + // An error occured + throw new DOMPDF_Exception("Error parsing css file: preg_match_all() failed."); + + // After matching, the array indicies are set as follows: + // + // [0] => complete text of match + // [1] => contains '@import ...;' or '@media {' if applicable + // [2] => text following @ for cases where [1] is set + // [3] => media types or full text following '@import ...;' + // [4] => '{', if present + // [5] => rulesets within media rules + // [6] => '{', within media rules + // [7] => individual rules, outside of media rules + // + //pre_r($matches); + foreach ( $matches as $match ) { + $match[2] = trim($match[2]); + + if ( $match[2] !== "" ) { + // Handle @rules + switch ($match[2]) { + + case "import": + $this->_parse_import($match[3]); + break; + + case "media": + $acceptedmedia = self::$ACCEPTED_GENERIC_MEDIA_TYPES; + if ( defined("DOMPDF_DEFAULT_MEDIA_TYPE") ) { + $acceptedmedia[] = DOMPDF_DEFAULT_MEDIA_TYPE; + } else { + $acceptedmedia[] = self::$ACCEPTED_DEFAULT_MEDIA_TYPE; + } + if ( in_array(mb_strtolower(trim($match[3])), $acceptedmedia ) ) { + $this->_parse_sections($match[5]); + } + break; + + case "page": + //This handles @page to be applied to page oriented media + //Note: This has a reduced syntax: + //@page { margin:1cm; color:blue; } + //Not a sequence of styles like a full.css, but only the properties + //of a single style, which is applied to the very first "root" frame before + //processing other styles of the frame. + //Working properties: + // margin (for margin around edge of paper) + // font-family (default font of pages) + // color (default text color of pages) + //Non working properties: + // border + // padding + // background-color + //Todo:Reason is unknown + //Other properties (like further font or border attributes) not tested. + //If a border or background color around each paper sheet is desired, + //assign it to the tag, possibly only for the css of the correct media type. + + // If the page has a name, skip the style. + if ($match[3] !== "") + return; + + // Store the style for later... + if ( is_null($this->_page_style) ) + $this->_page_style = $this->_parse_properties($match[5]); + else + $this->_page_style->merge($this->_parse_properties($match[5])); + break; + + case "font-face": + $this->_parse_font_face($match[5]); + break; + + default: + // ignore everything else + break; + } + + continue; + } + + if ( $match[7] !== "" ) + $this->_parse_sections($match[7]); + + } + } + + /* See also style.cls Style::_image(), refactoring?, works also for imported css files */ + protected function _image($val) { + $DEBUGCSS=DEBUGCSS; + + 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 = explode_url($val); + if ( $parsed_url["protocol"] == "" && $this->get_protocol() == "" ) { + if ($parsed_url["path"][0] === '/' || $parsed_url["path"][0] === '\\' ) { + $path = $_SERVER["DOCUMENT_ROOT"].'/'; + } else { + $path = $this->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 + // FIXME: Is this causing problems for imported CSS files? There are some './none' references when running the test cases. + if (!$path) { $path = 'none'; } + } else { + $path = build_url($this->get_protocol(), + $this->get_host(), + $this->get_base_path(), + $val); + } + } + if ($DEBUGCSS) { + print "
[_image\n"; + print_r($parsed_url); + print $this->get_protocol()."\n".$this->get_base_path()."\n".$path."\n"; + print "_image]";; + } + return $path; + } + + /** + * parse @import{} sections + * + * @param string $url the url of the imported CSS file + */ + private function _parse_import($url) { + $arr = preg_split("/[\s\n,]/", $url,-1, PREG_SPLIT_NO_EMPTY); + $url = array_shift($arr); + $accept = false; + + if ( count($arr) > 0 ) { + + $acceptedmedia = self::$ACCEPTED_GENERIC_MEDIA_TYPES; + if ( defined("DOMPDF_DEFAULT_MEDIA_TYPE") ) { + $acceptedmedia[] = DOMPDF_DEFAULT_MEDIA_TYPE; + } else { + $acceptedmedia[] = self::$ACCEPTED_DEFAULT_MEDIA_TYPE; + } + + // @import url media_type [media_type...] + foreach ( $arr as $type ) { + if ( in_array(mb_strtolower(trim($type)), $acceptedmedia) ) { + $accept = true; + break; + } + } + + } else { + // unconditional import + $accept = true; + } + + if ( $accept ) { + // Store our current base url properties in case the new url is elsewhere + $protocol = $this->_protocol; + $host = $this->_base_host; + $path = $this->_base_path; + + // $url = str_replace(array('"',"url", "(", ")"), "", $url); + // If the protocol is php, assume that we will import using file:// + // $url = build_url($protocol == "php://" ? "file://" : $protocol, $host, $path, $url); + // Above does not work for subfolders and absolute urls. + // Todo: As above, do we need to replace php or file to an empty protocol for local files? + + $url = $this->_image($url); + + $this->load_css_file($url); + + // Restore the current base url + $this->_protocol = $protocol; + $this->_base_host = $host; + $this->_base_path = $path; + } + + } + + /** + * 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(); + foreach($src[0] as $i => $value) { + $sources[] = array( + "local" => strtolower($src[1][$i]) === "local", + "uri" => $src[2][$i], + "format" => $src[4][$i], + ); + } + + //@todo download font file, ttf2afm, etc + } + + /** + * parse regular CSS blocks + * + * _parse_properties() creates a new Style object based on the provided + * CSS rules. + * + * @param string $str CSS rules + * @return Style + */ + private function _parse_properties($str) { + $properties = preg_split("/;(?=(?:[^\(]*\([^\)]*\))*(?![^\)]*\)))/", $str); + + if (DEBUGCSS) print '[_parse_properties'; + + // Create the style + $style = new Style($this); + foreach ($properties as $prop) { + // If the $prop contains an url, the regex may be wrong + // @todo: fix the regex so that it works everytime + /*if (strpos($prop, "url(") === false) { + if (preg_match("/([a-z-]+)\s*:\s*[^:]+$/i", $prop, $m)) + $prop = $m[0]; + }*/ + //A css property can have " ! important" appended (whitespace optional) + //strip this off to decode core of the property correctly. + //Pass on in the style to allow proper handling: + //!important properties can only be overridden by other !important ones. + //$style->$prop_name = is a shortcut of $style->__set($prop_name,$value);. + //If no specific set function available, set _props["prop_name"] + //style is always copied completely, or $_props handled separately + //Therefore set a _important_props["prop_name"]=true to indicate the modifier + + /* Instead of short code, prefer the typical case with fast code + $important = preg_match("/(.*?)!\s*important/",$prop,$match); + if ( $important ) { + $prop = $match[1]; + } + $prop = trim($prop); + */ + if (DEBUGCSS) print '('; + $important = false; + $prop = trim($prop); + if (substr($prop,-9) === 'important') { + $prop_tmp = rtrim(substr($prop,0,-9)); + if (substr($prop_tmp,-1) === '!') { + $prop = rtrim(substr($prop_tmp,0,-1)); + $important = true; + } + } + + if ($prop == "") { + if (DEBUGCSS) print 'empty)'; + continue; + } + + $i = mb_strpos($prop, ":"); + if ( $i === false ) { + if (DEBUGCSS) print 'novalue'.$prop.')'; + continue; + } + + $prop_name = rtrim(mb_strtolower(mb_substr($prop, 0, $i))); + $value = ltrim(mb_substr($prop, $i+1)); + if (DEBUGCSS) print $prop_name.':='.$value.($important?'!IMPORTANT':'').')'; + //New style, anyway empty + //if ($important || !$style->important_get($prop_name) ) { + //$style->$prop_name = array($value,$important); + //assignment might be replaced by overloading through __set, + //and overloaded functions might check _important_props, + //therefore set _important_props first. + if ($important) { + $style->important_set($prop_name); + } + //For easier debugging, don't use overloading of assignments with __set + $style->$prop_name = $value; + //$style->props_set($prop_name, $value); + } + if (DEBUGCSS) print '_parse_properties]'; + + return $style; + } + + /** + * parse selector + rulesets + * + * @param string $str CSS selectors and rulesets + */ + private function _parse_sections($str) { + // Pre-process: collapse all whitespace and strip whitespace around '>', + // '.', ':', '+', '#' + + $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(",", mb_substr($sect, 0, $i)); + if (DEBUGCSS) print '[section'; + $style = $this->_parse_properties(trim(mb_substr($sect, $i+1))); + + // Assign it to the selected elements + foreach ($selectors as $selector) { + $selector = trim($selector); + + if ($selector == "") { + if (DEBUGCSS) print '#empty#'; + continue; + } + if (DEBUGCSS) print '#'.$selector.'#'; + //if (DEBUGCSS) { if (strpos($selector,'p') !== false) print '!!!p!!!#'; } + + $this->add_style($selector, $style); + } + if (DEBUGCSS) print 'section]'; + } + if (DEBUGCSS) print '_parse_sections]'; + } + + /** + * dumps the entire stylesheet as a string + * + * Generates a string of each selector and associated style in the + * Stylesheet. Useful for debugging. + * + * @return string + */ + function __toString() { + $str = ""; + foreach ($this->_styles as $selector => $style) + $str .= "$selector => " . $style->__toString() . "\n"; + + return $str; + } +} diff --git a/application/third_party/dompdf/include/table_cell_frame_decorator.cls.php b/application/third_party/dompdf/include/table_cell_frame_decorator.cls.php new file mode 100644 index 00000000..d23eaa44 --- /dev/null +++ b/application/third_party/dompdf/include/table_cell_frame_decorator.cls.php @@ -0,0 +1,135 @@ + + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library in the file LICENSE.LGPL; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + * + * Alternatively, you may distribute this software under the terms of the + * PHP License, version 3.0 or later. A copy of this license should have + * been distributed with this file in the file LICENSE.PHP . If this is not + * the case, you can obtain a copy at http://www.php.net/license/3_0.txt. + * + * The latest version of DOMPDF might be available at: + * http://www.dompdf.com/ + * + * @link http://www.dompdf.com/ + * @copyright 2004 Benj Carson + * @author Benj Carson
+ * array(0 => x1,
+ * 1 => y1,
+ * 2 => x2,
+ * 3 => y2,
+ * ...
+ * );
+ *
+ *
+ * See {@link Style::munge_colour()} for the format of the colour array.
+ * See {@link Cpdf::setLineStyle()} for a description of the $style
+ * parameter (aka dash)
+ *
+ * @param array $points
+ * @param array $color
+ * @param float $width
+ * @param array $style
+ * @param bool $fill Fills the polygon if true
+ */
+ function polygon($points, $color, $width = null, $style = null, $fill = false) {
+ // FIXME
+ }
+
+ /**
+ * Draws a circle at $x,$y with radius $r
+ *
+ * See {@link Style::munge_colour()} for the format of the colour array.
+ * See {@link Cpdf::setLineStyle()} for a description of the $style
+ * parameter (aka dash)
+ *
+ * @param float $x
+ * @param float $y
+ * @param float $r
+ * @param array $color
+ * @param float $width
+ * @param array $style
+ * @param bool $fill Fills the circle if true
+ */
+ function circle($x, $y, $r, $color, $width = null, $style = null, $fill = false) {
+ // FIXME
+ }
+
+ /**
+ * Add an image to the pdf.
+ *
+ * The image is placed at the specified x and y coordinates with the
+ * given width and height.
+ *
+ * @param string $img_url the path to the image
+ * @param string $img_type the type (e.g. extension) of the image
+ * @param float $x x position
+ * @param float $y y position
+ * @param int $w width (in pixels)
+ * @param int $h height (in pixels)
+ */
+ function image($img_url, $img_type, $x, $y, $w, $h) {
+ // FIXME
+ }
+
+ /**
+ * Writes text at the specified x and y coordinates
+ *
+ * See {@link Style::munge_colour()} for the format of the colour array.
+ *
+ * @param float $x
+ * @param float $y
+ * @param string $text the text to write
+ * @param string $font the font file to use
+ * @param float $size the font size, in points
+ * @param array $color
+ * @param float $adjust word spacing adjustment
+ */
+ function text($x, $y, $text, $font, $size, $color = array(0,0,0), $adjust = 0) {
+ // FIXME
+ }
+
+ function javascript($code) {
+ // FIXME
+ }
+
+ /**
+ * Add a named destination (similar to ... in html)
+ *
+ * @param string $anchorname The name of the named destination
+ */
+ function add_named_dest($anchorname) {
+ // FIXME
+ }
+
+ /**
+ * 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) {
+ // FIXME
+ }
+
+ /**
+ * Add meta information to the PDF
+ *
+ * @param string $label label of the value (Creator, Producer, etc.)
+ * @param string $value the text to set
+ */
+ function add_info($label, $value) {
+ $method = "Set$label";
+ if ( in_array("Title", "Author", "Keywords", "Subject") && method_exists($this->_pdf, $method) ) {
+ $this->_pdf->$method($value);
+ }
+ }
+
+ /**
+ * Calculates text size, in points
+ *
+ * @param string $text the text to be sized
+ * @param string $font the desired font
+ * @param float $size the desired font size
+ * @param float $spacing word spacing, if any
+ * @return float
+ */
+ function get_text_width($text, $font, $size, $spacing = 0) {
+ // FIXME
+ }
+
+ /**
+ * Calculates font height, in points
+ *
+ * @param string $font
+ * @param float $size
+ * @return float
+ */
+ function get_font_height($font, $size) {
+ // FIXME
+ }
+
+
+ /**
+ * Starts a new page
+ *
+ * Subsequent drawing operations will appear on the new page.
+ */
+ function new_page() {
+ // FIXME
+ }
+
+ /**
+ * Streams the PDF directly to the browser
+ *
+ * @param string $filename the name of the PDF file
+ * @param array $options associative array, 'Attachment' => 0 or 1, 'compress' => 1 or 0
+ */
+ function stream($filename, $options = null) {
+ // FIXME
+ }
+
+ /**
+ * Returns the PDF as a string
+ *
+ * @param array $options associative array: 'compress' => 1 or 0
+ * @return string
+ */
+ function output($options = null) {
+ // FIXME
+ }
+
+}
+
+// Workaround for idiotic limitation on statics...
+PDFLib_Adapter::$PAPER_SIZES = CPDF_Adapter::$PAPER_SIZES;
diff --git a/application/third_party/dompdf/include/text_frame_decorator.cls.php b/application/third_party/dompdf/include/text_frame_decorator.cls.php
new file mode 100644
index 00000000..0bcb77f2
--- /dev/null
+++ b/application/third_party/dompdf/include/text_frame_decorator.cls.php
@@ -0,0 +1,204 @@
+
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library in the file LICENSE.LGPL; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * Alternatively, you may distribute this software under the terms of the
+ * PHP License, version 3.0 or later. A copy of this license should have
+ * been distributed with this file in the file LICENSE.PHP . If this is not
+ * the case, you can obtain a copy at http://www.php.net/license/3_0.txt.
+ *
+ * The latest version of DOMPDF might be available at:
+ * http://www.dompdf.com/
+ *
+ * @link http://www.dompdf.com/
+ * @copyright 2004 Benj Carson
+ * @author Benj Carson Text_Renderer cpdf:'.$base.' '.$descent.' '.$size.''; + } 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 '
Text_Renderer other than cpdf:'.$base.' '.$descent.' '.$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 ( count($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)); + } + } +} diff --git a/application/third_party/dompdf/include/ttf_info.cls.php b/application/third_party/dompdf/include/ttf_info.cls.php new file mode 100644 index 00000000..8fdeb3bc --- /dev/null +++ b/application/third_party/dompdf/include/ttf_info.cls.php @@ -0,0 +1,306 @@ +_dirRestriction && preg_match('[\.\/|\.\.\/]', $data)) + { + $this->exitClass('Error: Directory restriction is enforced!'); + } + + $this->filename = $data; + return $this; + } // public function setFontFile + + /** + * function setFontsDir() + * set the Font Directory + * @public + * @param string $data the new value + * @return object referrence to this + */ + public function setFontsDir($data) + { + if ($this->_dirRestriction && preg_match('[\.\/|\.\.\/]', $data)) + { + $this->exitClass('Error: Directory restriction is enforced!'); + } + + $this->fontsdir = $data; + return $this; + } // public function setFontsDir + + /** + * function readFontsDir() + * @public + * @return information contained in the TTF 'name' table of all fonts in a directory. + */ + public function readFontsDir() + { + if (empty($this->fontsdir)) { $this->exitClass('Error: Fonts Directory has not been set with setFontsDir().'); } + if (empty($this->backupDir)){ $this->backupDir = $this->fontsdir; } + + //$this->array = array(); + $d = dir($this->fontsdir); + + while (false !== ($e = $d->read())) + { + if($e != '.' && $e != '..') + { + $e = $this->fontsdir . $e; + if($this->_recursive && is_dir($e)) + { + $this->setFontsDir($e); + $this->readFontsDir(); + } + else if ($this->is_ttf($e) === true) + { + $this->setFontFile($e); + $this->array[] = $this->getFontInfo(); + } + } + } + + if (!empty($this->backupDir)){ $this->fontsdir = $this->backupDir; } + + $d->close(); + return $this; + } // public function readFontsDir + + /** + * function setProtectedVar() + * @public + * @param string $var the new variable + * @param string $data the new value + * @return object reference to this + + * DISABLED, NO REAL USE YET + + public function setProtectedVar($var, $data) + { + if ($var == 'filename') + { + $this->setFontFile($data); + } else { + //if (isset($var) && !empty($data)) + $this->$var = $data; + } + return $this; + } + */ + /** + * function getFontInfo() + * @public + * @return information contained in the TTF 'name' table. + */ + public function getFontInfo() + { + $fd = fopen ($this->filename, "r"); + $this->text = fread ($fd, filesize($this->filename)); + fclose ($fd); + + $number_of_tables = hexdec($this->dec2ord($this->text[4]).$this->dec2ord($this->text[5])); + + for ($i=0;$i<$number_of_tables;$i++) + { + $tag = $this->text[12+$i*16].$this->text[12+$i*16+1].$this->text[12+$i*16+2].$this->text[12+$i*16+3]; + + if ($tag == 'name') + { + $this->ntOffset = hexdec( + $this->dec2ord($this->text[12+$i*16+8]).$this->dec2ord($this->text[12+$i*16+8+1]). + $this->dec2ord($this->text[12+$i*16+8+2]).$this->dec2ord($this->text[12+$i*16+8+3])); + + $offset_storage_dec = hexdec($this->dec2ord($this->text[$this->ntOffset+4]).$this->dec2ord($this->text[$this->ntOffset+5])); + $number_name_records_dec = hexdec($this->dec2ord($this->text[$this->ntOffset+2]).$this->dec2ord($this->text[$this->ntOffset+3])); + } + } + + $storage_dec = $offset_storage_dec + $this->ntOffset; + $storage_hex = strtoupper(dechex($storage_dec)); + + for ($j=0;$j<$number_name_records_dec;$j++) + { + $platform_id_dec = hexdec($this->dec2ord($this->text[$this->ntOffset+6+$j*12+0]).$this->dec2ord($this->text[$this->ntOffset+6+$j*12+1])); + $name_id_dec = hexdec($this->dec2ord($this->text[$this->ntOffset+6+$j*12+6]).$this->dec2ord($this->text[$this->ntOffset+6+$j*12+7])); + $string_length_dec = hexdec($this->dec2ord($this->text[$this->ntOffset+6+$j*12+8]).$this->dec2ord($this->text[$this->ntOffset+6+$j*12+9])); + $string_offset_dec = hexdec($this->dec2ord($this->text[$this->ntOffset+6+$j*12+10]).$this->dec2ord($this->text[$this->ntOffset+6+$j*12+11])); + + if (!empty($name_id_dec) and empty($font_tags[$name_id_dec])) + { + for($l=0;$l<$string_length_dec;$l++) + { + if (ord($this->text[$storage_dec+$string_offset_dec+$l]) == '0') { continue; } + else { $font_tags[$name_id_dec] .= ($this->text[$storage_dec+$string_offset_dec+$l]); } + } + } + } + return $font_tags; + } // public function getFontInfo + + /** + * function getCopyright() + * @public + * @return 'Copyright notice' contained in the TTF 'name' table at index 0 + */ + public function getCopyright() + { + $this->info = $this->getFontInfo(); + return $this->info[0]; + } // public function getCopyright + + /** + * function getFontFamily() + * @public + * @return 'Font Family name' contained in the TTF 'name' table at index 1 + */ + public function getFontFamily() + { + $this->info = $this->getFontInfo(); + return $this->info[1]; + } // public function getFontFamily + + /** + * function getFontSubFamily() + * @public + * @return 'Font Subfamily name' contained in the TTF 'name' table at index 2 + */ + public function getFontSubFamily() + { + $this->info = $this->getFontInfo(); + return $this->info[2]; + } // public function getFontSubFamily + + /** + * function getFontId() + * @public + * @return 'Unique font identifier' contained in the TTF 'name' table at index 3 + */ + public function getFontId() + { + $this->info = $this->getFontInfo(); + return $this->info[3]; + } // public function getFontId + + /** + * function getFullFontName() + * @public + * @return 'Full font name' contained in the TTF 'name' table at index 4 + */ + public function getFullFontName() + { + $this->info = $this->getFontInfo(); + return $this->info[4]; + } // public function getFullFontName + + /** + * function dec2ord() + * Used to lessen redundant calls to multiple functions. + * @protected + * @return object + */ + protected function dec2ord($dec) + { + return $this->dec2hex(ord($dec)); + } // protected function dec2ord + + /** + * function dec2hex() + * private function to perform Hexadecimal to decimal with proper padding. + * @protected + * @return object + */ + protected function dec2hex($dec) + { + return str_repeat('0', 2-strlen(($hex=strtoupper(dechex($dec))))) . $hex; + } // protected function dec2hex + + /** + * function dec2hex() + * private function to perform Hexadecimal to decimal with proper padding. + * @protected + * @return object + */ + protected function exitClass($message) + { + echo $message; + exit; + } // protected function dec2hex + + /** + * function dec2hex() + * private helper function to test in the file in question is a ttf. + * @protected + * @return object + */ + protected function is_ttf($file) + { + $ext = explode('.', $file); + $ext = $ext[count($ext)-1]; + return preg_match("/ttf$/i",$ext) ? true : false; + } // protected function is_ttf +} // class ttfInfo + +function getFontInfo($resource) +{ + $ttfInfo = new TTF_Info; + $ttfInfo->setFontFile($resource); + return $ttfInfo->getFontInfo(); +} +?> \ No newline at end of file diff --git a/application/third_party/dompdf/index.php b/application/third_party/dompdf/index.php new file mode 100644 index 00000000..7ed173a8 --- /dev/null +++ b/application/third_party/dompdf/index.php @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/application/third_party/dompdf/lib/class.pdf.php b/application/third_party/dompdf/lib/class.pdf.php new file mode 100644 index 00000000..d8a0ba58 --- /dev/null +++ b/application/third_party/dompdf/lib/class.pdf.php @@ -0,0 +1,4617 @@ + + * @author Orion Richardson
| + | This file and the 14 PostScript(R) AFM files it accompanies may be used, copied, and distributed for any purpose and without charge, with or without modification, provided that all copyright notices are retained; that the AFM files are not distributed without this file; that all modifications to this file or any of the AFM files are prominently noted in the modified file(s); and that this paragraph is not modified. Adobe Systems has no responsibility or obligation to support the use of the AFM files. Col | +
Source http://www.adobe.com/devnet/font/#pcfi
+ + \ No newline at end of file diff --git a/application/third_party/dompdf/lib/html5lib/Data.php b/application/third_party/dompdf/lib/html5lib/Data.php new file mode 100644 index 00000000..497345f4 --- /dev/null +++ b/application/third_party/dompdf/lib/html5lib/Data.php @@ -0,0 +1,114 @@ + 0xFFFD, // REPLACEMENT CHARACTER + 0x0D => 0x000A, // LINE FEED (LF) + 0x80 => 0x20AC, // EURO SIGN ('€') + 0x81 => 0x0081, // */
+ $this->ignore_lf_token = 2;
+
+ $this->original_mode = $this->mode;
+ $this->flag_frameset_ok = false;
+ $this->mode = self::IN_CDATA_RCDATA;
+
+ /* Switch the tokeniser's content model flag to the
+ RCDATA state. */
+ $this->content_model = HTML5_Tokenizer::RCDATA;
+ break;
+
+ /* A start tag token whose tag name is "xmp" */
+ case 'xmp':
+ /* If the stack of open elements has a p element in
+ scope, then act as if an end tag with the tag name
+ "p" has been seen. */
+ if ($this->elementInScope('p')) {
+ $this->emitToken(array(
+ 'name' => 'p',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+ }
+
+ /* Reconstruct the active formatting elements, if any. */
+ $this->reconstructActiveFormattingElements();
+
+ $this->flag_frameset_ok = false;
+
+ $this->insertCDATAElement($token);
+ break;
+
+ case 'iframe':
+ $this->flag_frameset_ok = false;
+ $this->insertCDATAElement($token);
+ break;
+
+ case 'noembed': case 'noscript':
+ // XSCRIPT: should check scripting flag
+ $this->insertCDATAElement($token);
+ break;
+
+ /* A start tag whose tag name is "select" */
+ case 'select':
+ /* Reconstruct the active formatting elements, if any. */
+ $this->reconstructActiveFormattingElements();
+
+ /* Insert an HTML element for the token. */
+ $this->insertElement($token);
+
+ $this->flag_frameset_ok = false;
+
+ /* If the insertion mode is one of in table", "in caption",
+ * "in column group", "in table body", "in row", or "in
+ * cell", then switch the insertion mode to "in select in
+ * table". Otherwise, switch the insertion mode to "in
+ * select". */
+ if (
+ $this->mode === self::IN_TABLE || $this->mode === self::IN_CAPTION ||
+ $this->mode === self::IN_COLUMN_GROUP || $this->mode ==+self::IN_TABLE_BODY ||
+ $this->mode === self::IN_ROW || $this->mode === self::IN_CELL
+ ) {
+ $this->mode = self::IN_SELECT_IN_TABLE;
+ } else {
+ $this->mode = self::IN_SELECT;
+ }
+ break;
+
+ case 'option': case 'optgroup':
+ if ($this->elementInScope('option')) {
+ $this->emitToken(array(
+ 'name' => 'option',
+ 'type' => HTML5_Tokenizer::ENDTAG,
+ ));
+ }
+ $this->reconstructActiveFormattingElements();
+ $this->insertElement($token);
+ break;
+
+ case 'rp': case 'rt':
+ /* If the stack of open elements has a ruby element in scope, then generate
+ * implied end tags. If the current node is not then a ruby element, this is
+ * a parse error; pop all the nodes from the current node up to the node
+ * immediately before the bottommost ruby element on the stack of open elements.
+ */
+ if ($this->elementInScope('ruby')) {
+ $this->generateImpliedEndTags();
+ }
+ $peek = false;
+ do {
+ if ($peek) {
+ // parse error
+ }
+ $peek = array_pop($this->stack);
+ } while ($peek->tagName !== 'ruby');
+ $this->stack[] = $peek; // we popped one too many
+ $this->insertElement($token);
+ break;
+
+ // spec diversion
+
+ case 'math':
+ $this->reconstructActiveFormattingElements();
+ $token = $this->adjustMathMLAttributes($token);
+ $token = $this->adjustForeignAttributes($token);
+ $this->insertForeignElement($token, self::NS_MATHML);
+ if (isset($token['self-closing'])) {
+ // XERROR: acknowledge the token's self-closing flag
+ array_pop($this->stack);
+ }
+ if ($this->mode !== self::IN_FOREIGN_CONTENT) {
+ $this->secondary_mode = $this->mode;
+ $this->mode = self::IN_FOREIGN_CONTENT;
+ }
+ break;
+
+ case 'svg':
+ $this->reconstructActiveFormattingElements();
+ $token = $this->adjustSVGAttributes($token);
+ $token = $this->adjustForeignAttributes($token);
+ $this->insertForeignElement($token, self::NS_SVG);
+ if (isset($token['self-closing'])) {
+ // XERROR: acknowledge the token's self-closing flag
+ array_pop($this->stack);
+ }
+ if ($this->mode !== self::IN_FOREIGN_CONTENT) {
+ $this->secondary_mode = $this->mode;
+ $this->mode = self::IN_FOREIGN_CONTENT;
+ }
+ break;
+
+ case 'caption': case 'col': case 'colgroup': case 'frame': case 'head':
+ case 'tbody': case 'td': case 'tfoot': case 'th': case 'thead': case 'tr':
+ // parse error
+ break;
+
+ /* A start tag token not covered by the previous entries */
+ default:
+ /* Reconstruct the active formatting elements, if any. */
+ $this->reconstructActiveFormattingElements();
+
+ $this->insertElement($token);
+ /* This element will be a phrasing element. */
+ break;
+ }
+ break;
+
+ case HTML5_Tokenizer::ENDTAG:
+ switch($token['name']) {
+ /* An end tag with the tag name "body" */
+ case 'body':
+ /* If the stack of open elements does not have a body
+ * element in scope, this is a parse error; ignore the
+ * token. */
+ if(!$this->elementInScope('body')) {
+ $this->ignored = true;
+
+ /* Otherwise, if there is a node in the stack of open
+ * elements that is not either a dc element, a dd element,
+ * a ds element, a dt element, an li element, an optgroup
+ * element, an option element, a p element, an rp element,
+ * an rt element, a tbody element, a td element, a tfoot
+ * element, a th element, a thead element, a tr element,
+ * the body element, or the html element, then this is a
+ * parse error.
+ */
+ } else {
+ // XERROR: implement this check for parse error
+ }
+
+ /* Change the insertion mode to "after body". */
+ $this->mode = self::AFTER_BODY;
+ break;
+
+ /* An end tag with the tag name "html" */
+ case 'html':
+ /* Act as if an end tag with tag name "body" had been seen,
+ then, if that token wasn't ignored, reprocess the current
+ token. */
+ $this->emitToken(array(
+ 'name' => 'body',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+
+ if (!$this->ignored) $this->emitToken($token);
+ break;
+
+ case 'address': case 'article': case 'aside': case 'blockquote':
+ case 'center': case 'datagrid': case 'details': case 'dir':
+ case 'div': case 'dl': case 'fieldset': case 'footer':
+ case 'header': case 'hgroup': case 'listing': case 'menu':
+ case 'nav': case 'ol': case 'pre': case 'section': case 'ul':
+ /* If the stack of open elements has an element in scope
+ with the same tag name as that of the token, then generate
+ implied end tags. */
+ if($this->elementInScope($token['name'])) {
+ $this->generateImpliedEndTags();
+
+ /* Now, if the current node is not an element with
+ the same tag name as that of the token, then this
+ is a parse error. */
+ // XERROR: implement parse error logic
+
+ /* If the stack of open elements has an element in
+ scope with the same tag name as that of the token,
+ then pop elements from this stack until an element
+ with that tag name has been popped from the stack. */
+ do {
+ $node = array_pop($this->stack);
+ } while ($node->tagName !== $token['name']);
+ } else {
+ // parse error
+ }
+ break;
+
+ /* An end tag whose tag name is "form" */
+ case 'form':
+ /* Let node be the element that the form element pointer is set to. */
+ $node = $this->form_pointer;
+ /* Set the form element pointer to null. */
+ $this->form_pointer = null;
+ /* If node is null or the stack of open elements does not
+ * have node in scope, then this is a parse error; ignore the token. */
+ if ($node === null || !in_array($node, $this->stack)) {
+ // parse error
+ $this->ignored = true;
+ } else {
+ /* 1. Generate implied end tags. */
+ $this->generateImpliedEndTags();
+ /* 2. If the current node is not node, then this is a parse error. */
+ if (end($this->stack) !== $node) {
+ // parse error
+ }
+ /* 3. Remove node from the stack of open elements. */
+ array_splice($this->stack, array_search($node, $this->stack, true), 1);
+ }
+
+ break;
+
+ /* An end tag whose tag name is "p" */
+ case 'p':
+ /* If the stack of open elements has a p element in scope,
+ then generate implied end tags, except for p elements. */
+ if($this->elementInScope('p')) {
+ /* Generate implied end tags, except for elements with
+ * the same tag name as the token. */
+ $this->generateImpliedEndTags(array('p'));
+
+ /* If the current node is not a p element, then this is
+ a parse error. */
+ // XERROR: implement
+
+ /* Pop elements from the stack of open elements until
+ * an element with the same tag name as the token has
+ * been popped from the stack. */
+ do {
+ $node = array_pop($this->stack);
+ } while ($node->tagName !== 'p');
+
+ } else {
+ // parse error
+ $this->emitToken(array(
+ 'name' => 'p',
+ 'type' => HTML5_Tokenizer::STARTTAG,
+ ));
+ $this->emitToken($token);
+ }
+ break;
+
+ /* An end tag whose tag name is "li" */
+ case 'li':
+ /* If the stack of open elements does not have an element
+ * in list item scope with the same tag name as that of the
+ * token, then this is a parse error; ignore the token. */
+ if ($this->elementInScope($token['name'], self::SCOPE_LISTITEM)) {
+ /* Generate implied end tags, except for elements with the
+ * same tag name as the token. */
+ $this->generateImpliedEndTags(array($token['name']));
+ /* If the current node is not an element with the same tag
+ * name as that of the token, then this is a parse error. */
+ // XERROR: parse error
+ /* Pop elements from the stack of open elements until an
+ * element with the same tag name as the token has been
+ * popped from the stack. */
+ do {
+ $node = array_pop($this->stack);
+ } while ($node->tagName !== $token['name']);
+ } else {
+ // XERROR: parse error
+ }
+ break;
+
+ /* An end tag whose tag name is "dc", "dd", "ds", "dt" */
+ case 'dc': case 'dd': case 'ds': case 'dt':
+ if($this->elementInScope($token['name'])) {
+ $this->generateImpliedEndTags(array($token['name']));
+
+ /* If the current node is not an element with the same
+ tag name as the token, then this is a parse error. */
+ // XERROR: implement parse error
+
+ /* Pop elements from the stack of open elements until
+ * an element with the same tag name as the token has
+ * been popped from the stack. */
+ do {
+ $node = array_pop($this->stack);
+ } while ($node->tagName !== $token['name']);
+
+ } else {
+ // XERROR: parse error
+ }
+ break;
+
+ /* An end tag whose tag name is one of: "h1", "h2", "h3", "h4",
+ "h5", "h6" */
+ case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6':
+ $elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6');
+
+ /* If the stack of open elements has in scope an element whose
+ tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then
+ generate implied end tags. */
+ if($this->elementInScope($elements)) {
+ $this->generateImpliedEndTags();
+
+ /* Now, if the current node is not an element with the same
+ tag name as that of the token, then this is a parse error. */
+ // XERROR: implement parse error
+
+ /* If the stack of open elements has in scope an element
+ whose tag name is one of "h1", "h2", "h3", "h4", "h5", or
+ "h6", then pop elements from the stack until an element
+ with one of those tag names has been popped from the stack. */
+ do {
+ $node = array_pop($this->stack);
+ } while (!in_array($node->tagName, $elements));
+ } else {
+ // parse error
+ }
+ break;
+
+ /* An end tag whose tag name is one of: "a", "b", "big", "em",
+ "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u" */
+ case 'a': case 'b': case 'big': case 'code': case 'em': case 'font':
+ case 'i': case 'nobr': case 's': case 'small': case 'strike':
+ case 'strong': case 'tt': case 'u':
+ // XERROR: generally speaking this needs parse error logic
+ /* 1. Let the formatting element be the last element in
+ the list of active formatting elements that:
+ * is between the end of the list and the last scope
+ marker in the list, if any, or the start of the list
+ otherwise, and
+ * has the same tag name as the token.
+ */
+ while(true) {
+ for($a = count($this->a_formatting) - 1; $a >= 0; $a--) {
+ if($this->a_formatting[$a] === self::MARKER) {
+ break;
+
+ } elseif($this->a_formatting[$a]->tagName === $token['name']) {
+ $formatting_element = $this->a_formatting[$a];
+ $in_stack = in_array($formatting_element, $this->stack, true);
+ $fe_af_pos = $a;
+ break;
+ }
+ }
+
+ /* If there is no such node, or, if that node is
+ also in the stack of open elements but the element
+ is not in scope, then this is a parse error. Abort
+ these steps. The token is ignored. */
+ if(!isset($formatting_element) || ($in_stack &&
+ !$this->elementInScope($token['name']))) {
+ $this->ignored = true;
+ break;
+
+ /* Otherwise, if there is such a node, but that node
+ is not in the stack of open elements, then this is a
+ parse error; remove the element from the list, and
+ abort these steps. */
+ } elseif(isset($formatting_element) && !$in_stack) {
+ unset($this->a_formatting[$fe_af_pos]);
+ $this->a_formatting = array_merge($this->a_formatting);
+ break;
+ }
+
+ /* Otherwise, there is a formatting element and that
+ * element is in the stack and is in scope. If the
+ * element is not the current node, this is a parse
+ * error. In any case, proceed with the algorithm as
+ * written in the following steps. */
+ // XERROR: implement me
+
+ /* 2. Let the furthest block be the topmost node in the
+ stack of open elements that is lower in the stack
+ than the formatting element, and is not an element in
+ the phrasing or formatting categories. There might
+ not be one. */
+ $fe_s_pos = array_search($formatting_element, $this->stack, true);
+ $length = count($this->stack);
+
+ for($s = $fe_s_pos + 1; $s < $length; $s++) {
+ $category = $this->getElementCategory($this->stack[$s]);
+
+ if($category !== self::PHRASING && $category !== self::FORMATTING) {
+ $furthest_block = $this->stack[$s];
+ break;
+ }
+ }
+
+ /* 3. If there is no furthest block, then the UA must
+ skip the subsequent steps and instead just pop all
+ the nodes from the bottom of the stack of open
+ elements, from the current node up to the formatting
+ element, and remove the formatting element from the
+ list of active formatting elements. */
+ if(!isset($furthest_block)) {
+ for($n = $length - 1; $n >= $fe_s_pos; $n--) {
+ array_pop($this->stack);
+ }
+
+ unset($this->a_formatting[$fe_af_pos]);
+ $this->a_formatting = array_merge($this->a_formatting);
+ break;
+ }
+
+ /* 4. Let the common ancestor be the element
+ immediately above the formatting element in the stack
+ of open elements. */
+ $common_ancestor = $this->stack[$fe_s_pos - 1];
+
+ /* 5. Let a bookmark note the position of the
+ formatting element in the list of active formatting
+ elements relative to the elements on either side
+ of it in the list. */
+ $bookmark = $fe_af_pos;
+
+ /* 6. Let node and last node be the furthest block.
+ Follow these steps: */
+ $node = $furthest_block;
+ $last_node = $furthest_block;
+
+ while(true) {
+ for($n = array_search($node, $this->stack, true) - 1; $n >= 0; $n--) {
+ /* 6.1 Let node be the element immediately
+ prior to node in the stack of open elements. */
+ $node = $this->stack[$n];
+
+ /* 6.2 If node is not in the list of active
+ formatting elements, then remove node from
+ the stack of open elements and then go back
+ to step 1. */
+ if(!in_array($node, $this->a_formatting, true)) {
+ array_splice($this->stack, $n, 1);
+
+ } else {
+ break;
+ }
+ }
+
+ /* 6.3 Otherwise, if node is the formatting
+ element, then go to the next step in the overall
+ algorithm. */
+ if($node === $formatting_element) {
+ break;
+
+ /* 6.4 Otherwise, if last node is the furthest
+ block, then move the aforementioned bookmark to
+ be immediately after the node in the list of
+ active formatting elements. */
+ } elseif($last_node === $furthest_block) {
+ $bookmark = array_search($node, $this->a_formatting, true) + 1;
+ }
+
+ /* 6.5 Create an element for the token for which
+ * the element node was created, replace the entry
+ * for node in the list of active formatting
+ * elements with an entry for the new element,
+ * replace the entry for node in the stack of open
+ * elements with an entry for the new element, and
+ * let node be the new element. */
+ // we don't know what the token is anymore
+ // XDOM
+ $clone = $node->cloneNode();
+ $a_pos = array_search($node, $this->a_formatting, true);
+ $s_pos = array_search($node, $this->stack, true);
+ $this->a_formatting[$a_pos] = $clone;
+ $this->stack[$s_pos] = $clone;
+ $node = $clone;
+
+ /* 6.6 Insert last node into node, first removing
+ it from its previous parent node if any. */
+ // XDOM
+ if($last_node->parentNode !== null) {
+ $last_node->parentNode->removeChild($last_node);
+ }
+
+ // XDOM
+ $node->appendChild($last_node);
+
+ /* 6.7 Let last node be node. */
+ $last_node = $node;
+
+ /* 6.8 Return to step 1 of this inner set of steps. */
+ }
+
+ /* 7. If the common ancestor node is a table, tbody,
+ * tfoot, thead, or tr element, then, foster parent
+ * whatever last node ended up being in the previous
+ * step, first removing it from its previous parent
+ * node if any. */
+ // XDOM
+ if ($last_node->parentNode) { // common step
+ $last_node->parentNode->removeChild($last_node);
+ }
+ if (in_array($common_ancestor->tagName, array('table', 'tbody', 'tfoot', 'thead', 'tr'))) {
+ $this->fosterParent($last_node);
+ /* Otherwise, append whatever last node ended up being
+ * in the previous step to the common ancestor node,
+ * first removing it from its previous parent node if
+ * any. */
+ } else {
+ // XDOM
+ $common_ancestor->appendChild($last_node);
+ }
+
+ /* 8. Create an element for the token for which the
+ * formatting element was created. */
+ // XDOM
+ $clone = $formatting_element->cloneNode();
+
+ /* 9. Take all of the child nodes of the furthest
+ block and append them to the element created in the
+ last step. */
+ // XDOM
+ while($furthest_block->hasChildNodes()) {
+ $child = $furthest_block->firstChild;
+ $furthest_block->removeChild($child);
+ $clone->appendChild($child);
+ }
+
+ /* 10. Append that clone to the furthest block. */
+ // XDOM
+ $furthest_block->appendChild($clone);
+
+ /* 11. Remove the formatting element from the list
+ of active formatting elements, and insert the new element
+ into the list of active formatting elements at the
+ position of the aforementioned bookmark. */
+ $fe_af_pos = array_search($formatting_element, $this->a_formatting, true);
+ array_splice($this->a_formatting, $fe_af_pos, 1);
+
+ $af_part1 = array_slice($this->a_formatting, 0, $bookmark - 1);
+ $af_part2 = array_slice($this->a_formatting, $bookmark);
+ $this->a_formatting = array_merge($af_part1, array($clone), $af_part2);
+
+ /* 12. Remove the formatting element from the stack
+ of open elements, and insert the new element into the stack
+ of open elements immediately below the position of the
+ furthest block in that stack. */
+ $fe_s_pos = array_search($formatting_element, $this->stack, true);
+ array_splice($this->stack, $fe_s_pos, 1);
+
+ $fb_s_pos = array_search($furthest_block, $this->stack, true);
+ $s_part1 = array_slice($this->stack, 0, $fb_s_pos + 1);
+ $s_part2 = array_slice($this->stack, $fb_s_pos + 1);
+ $this->stack = array_merge($s_part1, array($clone), $s_part2);
+
+ /* 13. Jump back to step 1 in this series of steps. */
+ unset($formatting_element, $fe_af_pos, $fe_s_pos, $furthest_block);
+ }
+ break;
+
+ case 'applet': case 'button': case 'marquee': case 'object':
+ /* If the stack of open elements has an element in scope whose
+ tag name matches the tag name of the token, then generate implied
+ tags. */
+ if($this->elementInScope($token['name'])) {
+ $this->generateImpliedEndTags();
+
+ /* Now, if the current node is not an element with the same
+ tag name as the token, then this is a parse error. */
+ // XERROR: implement logic
+
+ /* Pop elements from the stack of open elements until
+ * an element with the same tag name as the token has
+ * been popped from the stack. */
+ do {
+ $node = array_pop($this->stack);
+ } while ($node->tagName !== $token['name']);
+
+ /* Clear the list of active formatting elements up to the
+ * last marker. */
+ $keys = array_keys($this->a_formatting, self::MARKER, true);
+ $marker = end($keys);
+
+ for($n = count($this->a_formatting) - 1; $n > $marker; $n--) {
+ array_pop($this->a_formatting);
+ }
+ } else {
+ // parse error
+ }
+ break;
+
+ case 'br':
+ // Parse error
+ $this->emitToken(array(
+ 'name' => 'br',
+ 'type' => HTML5_Tokenizer::STARTTAG,
+ ));
+ break;
+
+ /* An end tag token not covered by the previous entries */
+ default:
+ for($n = count($this->stack) - 1; $n >= 0; $n--) {
+ /* Initialise node to be the current node (the bottommost
+ node of the stack). */
+ $node = $this->stack[$n];
+
+ /* If node has the same tag name as the end tag token,
+ then: */
+ if($token['name'] === $node->tagName) {
+ /* Generate implied end tags. */
+ $this->generateImpliedEndTags();
+
+ /* If the tag name of the end tag token does not
+ match the tag name of the current node, this is a
+ parse error. */
+ // XERROR: implement this
+
+ /* Pop all the nodes from the current node up to
+ node, including node, then stop these steps. */
+ // XSKETCHY
+ do {
+ $pop = array_pop($this->stack);
+ } while ($pop !== $node);
+ break;
+
+ } else {
+ $category = $this->getElementCategory($node);
+
+ if($category !== self::FORMATTING && $category !== self::PHRASING) {
+ /* Otherwise, if node is in neither the formatting
+ category nor the phrasing category, then this is a
+ parse error. Stop this algorithm. The end tag token
+ is ignored. */
+ $this->ignored = true;
+ break;
+ // parse error
+ }
+ }
+ /* Set node to the previous entry in the stack of open elements. Loop. */
+ }
+ break;
+ }
+ break;
+ }
+ break;
+
+ case self::IN_CDATA_RCDATA:
+ if (
+ $token['type'] === HTML5_Tokenizer::CHARACTER ||
+ $token['type'] === HTML5_Tokenizer::SPACECHARACTER
+ ) {
+ $this->insertText($token['data']);
+ } elseif ($token['type'] === HTML5_Tokenizer::EOF) {
+ // parse error
+ /* If the current node is a script element, mark the script
+ * element as "already executed". */
+ // probably not necessary
+ array_pop($this->stack);
+ $this->mode = $this->original_mode;
+ $this->emitToken($token);
+ } elseif ($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'script') {
+ array_pop($this->stack);
+ $this->mode = $this->original_mode;
+ // we're ignoring all of the execution stuff
+ } elseif ($token['type'] === HTML5_Tokenizer::ENDTAG) {
+ array_pop($this->stack);
+ $this->mode = $this->original_mode;
+ }
+ break;
+
+ case self::IN_TABLE:
+ $clear = array('html', 'table');
+
+ /* A character token */
+ if ($token['type'] === HTML5_Tokenizer::CHARACTER ||
+ $token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
+ /* Let the pending table character tokens
+ * be an empty list of tokens. */
+ $this->pendingTableCharacters = "";
+ $this->pendingTableCharactersDirty = false;
+ /* Let the original insertion mode be the current
+ * insertion mode. */
+ $this->original_mode = $this->mode;
+ /* Switch the insertion mode to
+ * "in table text" and
+ * reprocess the token. */
+ $this->mode = self::IN_TABLE_TEXT;
+ $this->emitToken($token);
+
+ /* A comment token */
+ } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
+ /* Append a Comment node to the current node with the data
+ attribute set to the data given in the comment token. */
+ $this->insertComment($token['data']);
+
+ } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
+ // parse error
+
+ /* A start tag whose tag name is "caption" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ $token['name'] === 'caption') {
+ /* Clear the stack back to a table context. */
+ $this->clearStackToTableContext($clear);
+
+ /* Insert a marker at the end of the list of active
+ formatting elements. */
+ $this->a_formatting[] = self::MARKER;
+
+ /* Insert an HTML element for the token, then switch the
+ insertion mode to "in caption". */
+ $this->insertElement($token);
+ $this->mode = self::IN_CAPTION;
+
+ /* A start tag whose tag name is "colgroup" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ $token['name'] === 'colgroup') {
+ /* Clear the stack back to a table context. */
+ $this->clearStackToTableContext($clear);
+
+ /* Insert an HTML element for the token, then switch the
+ insertion mode to "in column group". */
+ $this->insertElement($token);
+ $this->mode = self::IN_COLUMN_GROUP;
+
+ /* A start tag whose tag name is "col" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ $token['name'] === 'col') {
+ $this->emitToken(array(
+ 'name' => 'colgroup',
+ 'type' => HTML5_Tokenizer::STARTTAG,
+ 'attr' => array()
+ ));
+
+ $this->emitToken($token);
+
+ /* A start tag whose tag name is one of: "tbody", "tfoot", "thead" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],
+ array('tbody', 'tfoot', 'thead'))) {
+ /* Clear the stack back to a table context. */
+ $this->clearStackToTableContext($clear);
+
+ /* Insert an HTML element for the token, then switch the insertion
+ mode to "in table body". */
+ $this->insertElement($token);
+ $this->mode = self::IN_TABLE_BODY;
+
+ /* A start tag whose tag name is one of: "td", "th", "tr" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ in_array($token['name'], array('td', 'th', 'tr'))) {
+ /* Act as if a start tag token with the tag name "tbody" had been
+ seen, then reprocess the current token. */
+ $this->emitToken(array(
+ 'name' => 'tbody',
+ 'type' => HTML5_Tokenizer::STARTTAG,
+ 'attr' => array()
+ ));
+
+ $this->emitToken($token);
+
+ /* A start tag whose tag name is "table" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ $token['name'] === 'table') {
+ /* Parse error. Act as if an end tag token with the tag name "table"
+ had been seen, then, if that token wasn't ignored, reprocess the
+ current token. */
+ $this->emitToken(array(
+ 'name' => 'table',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+
+ if (!$this->ignored) $this->emitToken($token);
+
+ /* An end tag whose tag name is "table" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
+ $token['name'] === 'table') {
+ /* If the stack of open elements does not have an element in table
+ scope with the same tag name as the token, this is a parse error.
+ Ignore the token. (fragment case) */
+ if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
+ $this->ignored = true;
+
+ /* Otherwise: */
+ } else {
+ do {
+ $node = array_pop($this->stack);
+ } while ($node->tagName !== 'table');
+
+ /* Reset the insertion mode appropriately. */
+ $this->resetInsertionMode();
+ }
+
+ /* An end tag whose tag name is one of: "body", "caption", "col",
+ "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],
+ array('body', 'caption', 'col', 'colgroup', 'html', 'tbody', 'td',
+ 'tfoot', 'th', 'thead', 'tr'))) {
+ // Parse error. Ignore the token.
+
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ ($token['name'] === 'style' || $token['name'] === 'script')) {
+ $this->processWithRulesFor($token, self::IN_HEAD);
+
+ } elseif ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'input' &&
+ // assignment is intentional
+ /* If the token does not have an attribute with the name "type", or
+ * if it does, but that attribute's value is not an ASCII
+ * case-insensitive match for the string "hidden", then: act as
+ * described in the "anything else" entry below. */
+ ($type = $this->getAttr($token, 'type')) && strtolower($type) === 'hidden') {
+ // I.e., if its an input with the type attribute == 'hidden'
+ /* Otherwise */
+ // parse error
+ $this->insertElement($token);
+ array_pop($this->stack);
+ } elseif ($token['type'] === HTML5_Tokenizer::EOF) {
+ /* If the current node is not the root html element, then this is a parse error. */
+ if (end($this->stack)->tagName !== 'html') {
+ // Note: It can only be the current node in the fragment case.
+ // parse error
+ }
+ /* Stop parsing. */
+ /* Anything else */
+ } else {
+ /* Parse error. Process the token as if the insertion mode was "in
+ body", with the following exception: */
+
+ $old = $this->foster_parent;
+ $this->foster_parent = true;
+ $this->processWithRulesFor($token, self::IN_BODY);
+ $this->foster_parent = $old;
+ }
+ break;
+
+ case self::IN_TABLE_TEXT:
+ /* A character token */
+ if($token['type'] === HTML5_Tokenizer::CHARACTER) {
+ /* Append the character token to the pending table
+ * character tokens list. */
+ $this->pendingTableCharacters .= $token['data'];
+ $this->pendingTableCharactersDirty = true;
+ } elseif ($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
+ $this->pendingTableCharacters .= $token['data'];
+ /* Anything else */
+ } else {
+ if ($this->pendingTableCharacters !== '' && is_string($this->pendingTableCharacters)) {
+ /* If any of the tokens in the pending table character tokens list
+ * are character tokens that are not one of U+0009 CHARACTER
+ * TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or
+ * U+0020 SPACE, then reprocess those character tokens using the
+ * rules given in the "anything else" entry in the in table"
+ * insertion mode.*/
+ if ($this->pendingTableCharactersDirty) {
+ /* Parse error. Process the token using the rules for the
+ * "in body" insertion mode, except that if the current
+ * node is a table, tbody, tfoot, thead, or tr element,
+ * then, whenever a node would be inserted into the current
+ * node, it must instead be foster parented. */
+ // XERROR
+ $old = $this->foster_parent;
+ $this->foster_parent = true;
+ $text_token = array(
+ 'type' => HTML5_Tokenizer::CHARACTER,
+ 'data' => $this->pendingTableCharacters,
+ );
+ $this->processWithRulesFor($text_token, self::IN_BODY);
+ $this->foster_parent = $old;
+
+ /* Otherwise, insert the characters given by the pending table
+ * character tokens list into the current node. */
+ } else {
+ $this->insertText($this->pendingTableCharacters);
+ }
+ $this->pendingTableCharacters = null;
+ $this->pendingTableCharactersNull = null;
+ }
+
+ /* Switch the insertion mode to the original insertion mode and
+ * reprocess the token.
+ */
+ $this->mode = $this->original_mode;
+ $this->emitToken($token);
+ }
+ break;
+
+ case self::IN_CAPTION:
+ /* An end tag whose tag name is "caption" */
+ if($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'caption') {
+ /* If the stack of open elements does not have an element in table
+ scope with the same tag name as the token, this is a parse error.
+ Ignore the token. (fragment case) */
+ if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
+ $this->ignored = true;
+ // Ignore
+
+ /* Otherwise: */
+ } else {
+ /* Generate implied end tags. */
+ $this->generateImpliedEndTags();
+
+ /* Now, if the current node is not a caption element, then this
+ is a parse error. */
+ // XERROR: implement
+
+ /* Pop elements from this stack until a caption element has
+ been popped from the stack. */
+ do {
+ $node = array_pop($this->stack);
+ } while ($node->tagName !== 'caption');
+
+ /* Clear the list of active formatting elements up to the last
+ marker. */
+ $this->clearTheActiveFormattingElementsUpToTheLastMarker();
+
+ /* Switch the insertion mode to "in table". */
+ $this->mode = self::IN_TABLE;
+ }
+
+ /* A start tag whose tag name is one of: "caption", "col", "colgroup",
+ "tbody", "td", "tfoot", "th", "thead", "tr", or an end tag whose tag
+ name is "table" */
+ } elseif(($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],
+ array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th',
+ 'thead', 'tr'))) || ($token['type'] === HTML5_Tokenizer::ENDTAG &&
+ $token['name'] === 'table')) {
+ /* Parse error. Act as if an end tag with the tag name "caption"
+ had been seen, then, if that token wasn't ignored, reprocess the
+ current token. */
+ $this->emitToken(array(
+ 'name' => 'caption',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+
+ if (!$this->ignored) $this->emitToken($token);
+
+ /* An end tag whose tag name is one of: "body", "col", "colgroup",
+ "html", "tbody", "td", "tfoot", "th", "thead", "tr" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],
+ array('body', 'col', 'colgroup', 'html', 'tbody', 'tfoot', 'th',
+ 'thead', 'tr'))) {
+ // Parse error. Ignore the token.
+ $this->ignored = true;
+
+ /* Anything else */
+ } else {
+ /* Process the token as if the insertion mode was "in body". */
+ $this->processWithRulesFor($token, self::IN_BODY);
+ }
+ break;
+
+ case self::IN_COLUMN_GROUP:
+ /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+ U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+ or U+0020 SPACE */
+ if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
+ /* Append the character to the current node. */
+ $this->insertText($token['data']);
+
+ /* A comment token */
+ } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
+ /* Append a Comment node to the current node with the data
+ attribute set to the data given in the comment token. */
+ $this->insertToken($token['data']);
+
+ } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
+ // parse error
+
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {
+ $this->processWithRulesFor($token, self::IN_BODY);
+
+ /* A start tag whose tag name is "col" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'col') {
+ /* Insert a col element for the token. Immediately pop the current
+ node off the stack of open elements. */
+ $this->insertElement($token);
+ array_pop($this->stack);
+ // XERROR: Acknowledge the token's self-closing flag, if it is set.
+
+ /* An end tag whose tag name is "colgroup" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
+ $token['name'] === 'colgroup') {
+ /* If the current node is the root html element, then this is a
+ parse error, ignore the token. (fragment case) */
+ if(end($this->stack)->tagName === 'html') {
+ $this->ignored = true;
+
+ /* Otherwise, pop the current node (which will be a colgroup
+ element) from the stack of open elements. Switch the insertion
+ mode to "in table". */
+ } else {
+ array_pop($this->stack);
+ $this->mode = self::IN_TABLE;
+ }
+
+ /* An end tag whose tag name is "col" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'col') {
+ /* Parse error. Ignore the token. */
+ $this->ignored = true;
+
+ /* An end-of-file token */
+ /* If the current node is the root html element */
+ } elseif($token['type'] === HTML5_Tokenizer::EOF && end($this->stack)->tagName === 'html') {
+ /* Stop parsing */
+
+ /* Anything else */
+ } else {
+ /* Act as if an end tag with the tag name "colgroup" had been seen,
+ and then, if that token wasn't ignored, reprocess the current token. */
+ $this->emitToken(array(
+ 'name' => 'colgroup',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+
+ if (!$this->ignored) $this->emitToken($token);
+ }
+ break;
+
+ case self::IN_TABLE_BODY:
+ $clear = array('tbody', 'tfoot', 'thead', 'html');
+
+ /* A start tag whose tag name is "tr" */
+ if($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'tr') {
+ /* Clear the stack back to a table body context. */
+ $this->clearStackToTableContext($clear);
+
+ /* Insert a tr element for the token, then switch the insertion
+ mode to "in row". */
+ $this->insertElement($token);
+ $this->mode = self::IN_ROW;
+
+ /* A start tag whose tag name is one of: "th", "td" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ ($token['name'] === 'th' || $token['name'] === 'td')) {
+ /* Parse error. Act as if a start tag with the tag name "tr" had
+ been seen, then reprocess the current token. */
+ $this->emitToken(array(
+ 'name' => 'tr',
+ 'type' => HTML5_Tokenizer::STARTTAG,
+ 'attr' => array()
+ ));
+
+ $this->emitToken($token);
+
+ /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
+ in_array($token['name'], array('tbody', 'tfoot', 'thead'))) {
+ /* If the stack of open elements does not have an element in table
+ scope with the same tag name as the token, this is a parse error.
+ Ignore the token. */
+ if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
+ // Parse error
+ $this->ignored = true;
+
+ /* Otherwise: */
+ } else {
+ /* Clear the stack back to a table body context. */
+ $this->clearStackToTableContext($clear);
+
+ /* Pop the current node from the stack of open elements. Switch
+ the insertion mode to "in table". */
+ array_pop($this->stack);
+ $this->mode = self::IN_TABLE;
+ }
+
+ /* A start tag whose tag name is one of: "caption", "col", "colgroup",
+ "tbody", "tfoot", "thead", or an end tag whose tag name is "table" */
+ } elseif(($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],
+ array('caption', 'col', 'colgroup', 'tbody', 'tfoot', 'thead'))) ||
+ ($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'table')) {
+ /* If the stack of open elements does not have a tbody, thead, or
+ tfoot element in table scope, this is a parse error. Ignore the
+ token. (fragment case) */
+ if(!$this->elementInScope(array('tbody', 'thead', 'tfoot'), self::SCOPE_TABLE)) {
+ // parse error
+ $this->ignored = true;
+
+ /* Otherwise: */
+ } else {
+ /* Clear the stack back to a table body context. */
+ $this->clearStackToTableContext($clear);
+
+ /* Act as if an end tag with the same tag name as the current
+ node ("tbody", "tfoot", or "thead") had been seen, then
+ reprocess the current token. */
+ $this->emitToken(array(
+ 'name' => end($this->stack)->tagName,
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+
+ $this->emitToken($token);
+ }
+
+ /* An end tag whose tag name is one of: "body", "caption", "col",
+ "colgroup", "html", "td", "th", "tr" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],
+ array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th', 'tr'))) {
+ /* Parse error. Ignore the token. */
+ $this->ignored = true;
+
+ /* Anything else */
+ } else {
+ /* Process the token as if the insertion mode was "in table". */
+ $this->processWithRulesFor($token, self::IN_TABLE);
+ }
+ break;
+
+ case self::IN_ROW:
+ $clear = array('tr', 'html');
+
+ /* A start tag whose tag name is one of: "th", "td" */
+ if($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ ($token['name'] === 'th' || $token['name'] === 'td')) {
+ /* Clear the stack back to a table row context. */
+ $this->clearStackToTableContext($clear);
+
+ /* Insert an HTML element for the token, then switch the insertion
+ mode to "in cell". */
+ $this->insertElement($token);
+ $this->mode = self::IN_CELL;
+
+ /* Insert a marker at the end of the list of active formatting
+ elements. */
+ $this->a_formatting[] = self::MARKER;
+
+ /* An end tag whose tag name is "tr" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'tr') {
+ /* If the stack of open elements does not have an element in table
+ scope with the same tag name as the token, this is a parse error.
+ Ignore the token. (fragment case) */
+ if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
+ // Ignore.
+ $this->ignored = true;
+
+ /* Otherwise: */
+ } else {
+ /* Clear the stack back to a table row context. */
+ $this->clearStackToTableContext($clear);
+
+ /* Pop the current node (which will be a tr element) from the
+ stack of open elements. Switch the insertion mode to "in table
+ body". */
+ array_pop($this->stack);
+ $this->mode = self::IN_TABLE_BODY;
+ }
+
+ /* A start tag whose tag name is one of: "caption", "col", "colgroup",
+ "tbody", "tfoot", "thead", "tr" or an end tag whose tag name is "table" */
+ } elseif(($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],
+ array('caption', 'col', 'colgroup', 'tbody', 'tfoot', 'thead', 'tr'))) ||
+ ($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'table')) {
+ /* Act as if an end tag with the tag name "tr" had been seen, then,
+ if that token wasn't ignored, reprocess the current token. */
+ $this->emitToken(array(
+ 'name' => 'tr',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+ if (!$this->ignored) $this->emitToken($token);
+
+ /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
+ in_array($token['name'], array('tbody', 'tfoot', 'thead'))) {
+ /* If the stack of open elements does not have an element in table
+ scope with the same tag name as the token, this is a parse error.
+ Ignore the token. */
+ if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
+ $this->ignored = true;
+
+ /* Otherwise: */
+ } else {
+ /* Otherwise, act as if an end tag with the tag name "tr" had
+ been seen, then reprocess the current token. */
+ $this->emitToken(array(
+ 'name' => 'tr',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+
+ $this->emitToken($token);
+ }
+
+ /* An end tag whose tag name is one of: "body", "caption", "col",
+ "colgroup", "html", "td", "th" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],
+ array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th'))) {
+ /* Parse error. Ignore the token. */
+ $this->ignored = true;
+
+ /* Anything else */
+ } else {
+ /* Process the token as if the insertion mode was "in table". */
+ $this->processWithRulesFor($token, self::IN_TABLE);
+ }
+ break;
+
+ case self::IN_CELL:
+ /* An end tag whose tag name is one of: "td", "th" */
+ if($token['type'] === HTML5_Tokenizer::ENDTAG &&
+ ($token['name'] === 'td' || $token['name'] === 'th')) {
+ /* If the stack of open elements does not have an element in table
+ scope with the same tag name as that of the token, then this is a
+ parse error and the token must be ignored. */
+ if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
+ $this->ignored = true;
+
+ /* Otherwise: */
+ } else {
+ /* Generate implied end tags, except for elements with the same
+ tag name as the token. */
+ $this->generateImpliedEndTags(array($token['name']));
+
+ /* Now, if the current node is not an element with the same tag
+ name as the token, then this is a parse error. */
+ // XERROR: Implement parse error code
+
+ /* Pop elements from this stack until an element with the same
+ tag name as the token has been popped from the stack. */
+ do {
+ $node = array_pop($this->stack);
+ } while ($node->tagName !== $token['name']);
+
+ /* Clear the list of active formatting elements up to the last
+ marker. */
+ $this->clearTheActiveFormattingElementsUpToTheLastMarker();
+
+ /* Switch the insertion mode to "in row". (The current node
+ will be a tr element at this point.) */
+ $this->mode = self::IN_ROW;
+ }
+
+ /* A start tag whose tag name is one of: "caption", "col", "colgroup",
+ "tbody", "td", "tfoot", "th", "thead", "tr" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],
+ array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th',
+ 'thead', 'tr'))) {
+ /* If the stack of open elements does not have a td or th element
+ in table scope, then this is a parse error; ignore the token.
+ (fragment case) */
+ if(!$this->elementInScope(array('td', 'th'), self::SCOPE_TABLE)) {
+ // parse error
+ $this->ignored = true;
+
+ /* Otherwise, close the cell (see below) and reprocess the current
+ token. */
+ } else {
+ $this->closeCell();
+ $this->emitToken($token);
+ }
+
+ /* An end tag whose tag name is one of: "body", "caption", "col",
+ "colgroup", "html" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],
+ array('body', 'caption', 'col', 'colgroup', 'html'))) {
+ /* Parse error. Ignore the token. */
+ $this->ignored = true;
+
+ /* An end tag whose tag name is one of: "table", "tbody", "tfoot",
+ "thead", "tr" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],
+ array('table', 'tbody', 'tfoot', 'thead', 'tr'))) {
+ /* If the stack of open elements does not have a td or th element
+ in table scope, then this is a parse error; ignore the token.
+ (innerHTML case) */
+ if(!$this->elementInScope(array('td', 'th'), self::SCOPE_TABLE)) {
+ // Parse error
+ $this->ignored = true;
+
+ /* Otherwise, close the cell (see below) and reprocess the current
+ token. */
+ } else {
+ $this->closeCell();
+ $this->emitToken($token);
+ }
+
+ /* Anything else */
+ } else {
+ /* Process the token as if the insertion mode was "in body". */
+ $this->processWithRulesFor($token, self::IN_BODY);
+ }
+ break;
+
+ case self::IN_SELECT:
+ /* Handle the token as follows: */
+
+ /* A character token */
+ if(
+ $token['type'] === HTML5_Tokenizer::CHARACTER ||
+ $token['type'] === HTML5_Tokenizer::SPACECHARACTER
+ ) {
+ /* Append the token's character to the current node. */
+ $this->insertText($token['data']);
+
+ /* A comment token */
+ } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
+ /* Append a Comment node to the current node with the data
+ attribute set to the data given in the comment token. */
+ $this->insertComment($token['data']);
+
+ } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
+ // parse error
+
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {
+ $this->processWithRulesFor($token, self::IN_BODY);
+
+ /* A start tag token whose tag name is "option" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ $token['name'] === 'option') {
+ /* If the current node is an option element, act as if an end tag
+ with the tag name "option" had been seen. */
+ if(end($this->stack)->tagName === 'option') {
+ $this->emitToken(array(
+ 'name' => 'option',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+ }
+
+ /* Insert an HTML element for the token. */
+ $this->insertElement($token);
+
+ /* A start tag token whose tag name is "optgroup" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ $token['name'] === 'optgroup') {
+ /* If the current node is an option element, act as if an end tag
+ with the tag name "option" had been seen. */
+ if(end($this->stack)->tagName === 'option') {
+ $this->emitToken(array(
+ 'name' => 'option',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+ }
+
+ /* If the current node is an optgroup element, act as if an end tag
+ with the tag name "optgroup" had been seen. */
+ if(end($this->stack)->tagName === 'optgroup') {
+ $this->emitToken(array(
+ 'name' => 'optgroup',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+ }
+
+ /* Insert an HTML element for the token. */
+ $this->insertElement($token);
+
+ /* An end tag token whose tag name is "optgroup" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
+ $token['name'] === 'optgroup') {
+ /* First, if the current node is an option element, and the node
+ immediately before it in the stack of open elements is an optgroup
+ element, then act as if an end tag with the tag name "option" had
+ been seen. */
+ $elements_in_stack = count($this->stack);
+
+ if($this->stack[$elements_in_stack - 1]->tagName === 'option' &&
+ $this->stack[$elements_in_stack - 2]->tagName === 'optgroup') {
+ $this->emitToken(array(
+ 'name' => 'option',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+ }
+
+ /* If the current node is an optgroup element, then pop that node
+ from the stack of open elements. Otherwise, this is a parse error,
+ ignore the token. */
+ if(end($this->stack)->tagName === 'optgroup') {
+ array_pop($this->stack);
+ } else {
+ // parse error
+ $this->ignored = true;
+ }
+
+ /* An end tag token whose tag name is "option" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
+ $token['name'] === 'option') {
+ /* If the current node is an option element, then pop that node
+ from the stack of open elements. Otherwise, this is a parse error,
+ ignore the token. */
+ if(end($this->stack)->tagName === 'option') {
+ array_pop($this->stack);
+ } else {
+ // parse error
+ $this->ignored = true;
+ }
+
+ /* An end tag whose tag name is "select" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
+ $token['name'] === 'select') {
+ /* If the stack of open elements does not have an element in table
+ scope with the same tag name as the token, this is a parse error.
+ Ignore the token. (fragment case) */
+ if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
+ $this->ignored = true;
+ // parse error
+
+ /* Otherwise: */
+ } else {
+ /* Pop elements from the stack of open elements until a select
+ element has been popped from the stack. */
+ do {
+ $node = array_pop($this->stack);
+ } while ($node->tagName !== 'select');
+
+ /* Reset the insertion mode appropriately. */
+ $this->resetInsertionMode();
+ }
+
+ /* A start tag whose tag name is "select" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'select') {
+ /* Parse error. Act as if the token had been an end tag with the
+ tag name "select" instead. */
+ $this->emitToken(array(
+ 'name' => 'select',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ ($token['name'] === 'input' || $token['name'] === 'keygen' || $token['name'] === 'textarea')) {
+ // parse error
+ $this->emitToken(array(
+ 'name' => 'select',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+ $this->emitToken($token);
+
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'script') {
+ $this->processWithRulesFor($token, self::IN_HEAD);
+
+ } elseif($token['type'] === HTML5_Tokenizer::EOF) {
+ // XERROR: If the current node is not the root html element, then this is a parse error.
+ /* Stop parsing */
+
+ /* Anything else */
+ } else {
+ /* Parse error. Ignore the token. */
+ $this->ignored = true;
+ }
+ break;
+
+ case self::IN_SELECT_IN_TABLE:
+
+ if($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ in_array($token['name'], array('caption', 'table', 'tbody',
+ 'tfoot', 'thead', 'tr', 'td', 'th'))) {
+ // parse error
+ $this->emitToken(array(
+ 'name' => 'select',
+ 'type' => HTML5_Tokenizer::ENDTAG,
+ ));
+ $this->emitToken($token);
+
+ /* An end tag whose tag name is one of: "caption", "table", "tbody",
+ "tfoot", "thead", "tr", "td", "th" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
+ in_array($token['name'], array('caption', 'table', 'tbody', 'tfoot', 'thead', 'tr', 'td', 'th'))) {
+ /* Parse error. */
+ // parse error
+
+ /* If the stack of open elements has an element in table scope with
+ the same tag name as that of the token, then act as if an end tag
+ with the tag name "select" had been seen, and reprocess the token.
+ Otherwise, ignore the token. */
+ if($this->elementInScope($token['name'], self::SCOPE_TABLE)) {
+ $this->emitToken(array(
+ 'name' => 'select',
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+
+ $this->emitToken($token);
+ } else {
+ $this->ignored = true;
+ }
+ } else {
+ $this->processWithRulesFor($token, self::IN_SELECT);
+ }
+ break;
+
+ case self::IN_FOREIGN_CONTENT:
+ if ($token['type'] === HTML5_Tokenizer::CHARACTER ||
+ $token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
+ $this->insertText($token['data']);
+ } elseif ($token['type'] === HTML5_Tokenizer::COMMENT) {
+ $this->insertComment($token['data']);
+ } elseif ($token['type'] === HTML5_Tokenizer::DOCTYPE) {
+ // XERROR: parse error
+ } elseif ($token['type'] === HTML5_Tokenizer::ENDTAG &&
+ $token['name'] === 'script' && end($this->stack)->tagName === 'script' &&
+ // XDOM
+ end($this->stack)->namespaceURI === self::NS_SVG) {
+ array_pop($this->stack);
+ // a bunch of script running mumbo jumbo
+ } elseif (
+ ($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ ((
+ $token['name'] !== 'mglyph' &&
+ $token['name'] !== 'malignmark' &&
+ // XDOM
+ end($this->stack)->namespaceURI === self::NS_MATHML &&
+ in_array(end($this->stack)->tagName, array('mi', 'mo', 'mn', 'ms', 'mtext'))
+ ) ||
+ (
+ $token['name'] === 'svg' &&
+ // XDOM
+ end($this->stack)->namespaceURI === self::NS_MATHML &&
+ end($this->stack)->tagName === 'annotation-xml'
+ ) ||
+ (
+ // XDOM
+ end($this->stack)->namespaceURI === self::NS_SVG &&
+ in_array(end($this->stack)->tagName, array('foreignObject', 'desc', 'title'))
+ ) ||
+ (
+ // XSKETCHY && XDOM
+ end($this->stack)->namespaceURI === self::NS_HTML
+ ))
+ ) || $token['type'] === HTML5_Tokenizer::ENDTAG
+ ) {
+ $this->processWithRulesFor($token, $this->secondary_mode);
+ /* If, after doing so, the insertion mode is still "in foreign
+ * content", but there is no element in scope that has a namespace
+ * other than the HTML namespace, switch the insertion mode to the
+ * secondary insertion mode. */
+ if ($this->mode === self::IN_FOREIGN_CONTENT) {
+ $found = false;
+ // this basically duplicates elementInScope()
+ for ($i = count($this->stack) - 1; $i >= 0; $i--) {
+ // XDOM
+ $node = $this->stack[$i];
+ if ($node->namespaceURI !== self::NS_HTML) {
+ $found = true;
+ break;
+ } elseif (in_array($node->tagName, array('table', 'html',
+ 'applet', 'caption', 'td', 'th', 'button', 'marquee',
+ 'object')) || ($node->tagName === 'foreignObject' &&
+ $node->namespaceURI === self::NS_SVG)) {
+ break;
+ }
+ }
+ if (!$found) {
+ $this->mode = $this->secondary_mode;
+ }
+ }
+ } elseif ($token['type'] === HTML5_Tokenizer::EOF || (
+ $token['type'] === HTML5_Tokenizer::STARTTAG &&
+ (in_array($token['name'], array('b', "big", "blockquote", "body", "br",
+ "center", "code", "dc", "dd", "div", "dl", "ds", "dt", "em", "embed", "h1", "h2",
+ "h3", "h4", "h5", "h6", "head", "hr", "i", "img", "li", "listing",
+ "menu", "meta", "nobr", "ol", "p", "pre", "ruby", "s", "small",
+ "span", "strong", "strike", "sub", "sup", "table", "tt", "u", "ul",
+ "var")) || ($token['name'] === 'font' && ($this->getAttr($token, 'color') ||
+ $this->getAttr($token, 'face') || $this->getAttr($token, 'size')))))) {
+ // XERROR: parse error
+ do {
+ $node = array_pop($this->stack);
+ // XDOM
+ } while ($node->namespaceURI !== self::NS_HTML);
+ $this->stack[] = $node;
+ $this->mode = $this->secondary_mode;
+ $this->emitToken($token);
+ } elseif ($token['type'] === HTML5_Tokenizer::STARTTAG) {
+ static $svg_lookup = array(
+ 'altglyph' => 'altGlyph',
+ 'altglyphdef' => 'altGlyphDef',
+ 'altglyphitem' => 'altGlyphItem',
+ 'animatecolor' => 'animateColor',
+ 'animatemotion' => 'animateMotion',
+ 'animatetransform' => 'animateTransform',
+ 'clippath' => 'clipPath',
+ 'feblend' => 'feBlend',
+ 'fecolormatrix' => 'feColorMatrix',
+ 'fecomponenttransfer' => 'feComponentTransfer',
+ 'fecomposite' => 'feComposite',
+ 'feconvolvematrix' => 'feConvolveMatrix',
+ 'fediffuselighting' => 'feDiffuseLighting',
+ 'fedisplacementmap' => 'feDisplacementMap',
+ 'fedistantlight' => 'feDistantLight',
+ 'feflood' => 'feFlood',
+ 'fefunca' => 'feFuncA',
+ 'fefuncb' => 'feFuncB',
+ 'fefuncg' => 'feFuncG',
+ 'fefuncr' => 'feFuncR',
+ 'fegaussianblur' => 'feGaussianBlur',
+ 'feimage' => 'feImage',
+ 'femerge' => 'feMerge',
+ 'femergenode' => 'feMergeNode',
+ 'femorphology' => 'feMorphology',
+ 'feoffset' => 'feOffset',
+ 'fepointlight' => 'fePointLight',
+ 'fespecularlighting' => 'feSpecularLighting',
+ 'fespotlight' => 'feSpotLight',
+ 'fetile' => 'feTile',
+ 'feturbulence' => 'feTurbulence',
+ 'foreignobject' => 'foreignObject',
+ 'glyphref' => 'glyphRef',
+ 'lineargradient' => 'linearGradient',
+ 'radialgradient' => 'radialGradient',
+ 'textpath' => 'textPath',
+ );
+ // XDOM
+ $current = end($this->stack);
+ if ($current->namespaceURI === self::NS_MATHML) {
+ $token = $this->adjustMathMLAttributes($token);
+ }
+ if ($current->namespaceURI === self::NS_SVG &&
+ isset($svg_lookup[$token['name']])) {
+ $token['name'] = $svg_lookup[$token['name']];
+ }
+ if ($current->namespaceURI === self::NS_SVG) {
+ $token = $this->adjustSVGAttributes($token);
+ }
+ $token = $this->adjustForeignAttributes($token);
+ $this->insertForeignElement($token, $current->namespaceURI);
+ if (isset($token['self-closing'])) {
+ array_pop($this->stack);
+ // XERROR: acknowledge self-closing flag
+ }
+ }
+ break;
+
+ case self::AFTER_BODY:
+ /* Handle the token as follows: */
+
+ /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+ U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+ or U+0020 SPACE */
+ if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
+ /* Process the token as it would be processed if the insertion mode
+ was "in body". */
+ $this->processWithRulesFor($token, self::IN_BODY);
+
+ /* A comment token */
+ } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
+ /* Append a Comment node to the first element in the stack of open
+ elements (the html element), with the data attribute set to the
+ data given in the comment token. */
+ // XDOM
+ $comment = $this->dom->createComment($token['data']);
+ $this->stack[0]->appendChild($comment);
+
+ } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
+ // parse error
+
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {
+ $this->processWithRulesFor($token, self::IN_BODY);
+
+ /* An end tag with the tag name "html" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'html') {
+ /* If the parser was originally created as part of the HTML
+ * fragment parsing algorithm, this is a parse error; ignore
+ * the token. (fragment case) */
+ $this->ignored = true;
+ // XERROR: implement this
+
+ $this->mode = self::AFTER_AFTER_BODY;
+
+ } elseif($token['type'] === HTML5_Tokenizer::EOF) {
+ /* Stop parsing */
+
+ /* Anything else */
+ } else {
+ /* Parse error. Set the insertion mode to "in body" and reprocess
+ the token. */
+ $this->mode = self::IN_BODY;
+ $this->emitToken($token);
+ }
+ break;
+
+ case self::IN_FRAMESET:
+ /* Handle the token as follows: */
+
+ /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+ U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+ U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */
+ if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
+ /* Append the character to the current node. */
+ $this->insertText($token['data']);
+
+ /* A comment token */
+ } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
+ /* Append a Comment node to the current node with the data
+ attribute set to the data given in the comment token. */
+ $this->insertComment($token['data']);
+
+ } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
+ // parse error
+
+ /* A start tag with the tag name "frameset" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ $token['name'] === 'frameset') {
+ $this->insertElement($token);
+
+ /* An end tag with the tag name "frameset" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
+ $token['name'] === 'frameset') {
+ /* If the current node is the root html element, then this is a
+ parse error; ignore the token. (fragment case) */
+ if(end($this->stack)->tagName === 'html') {
+ $this->ignored = true;
+ // Parse error
+
+ } else {
+ /* Otherwise, pop the current node from the stack of open
+ elements. */
+ array_pop($this->stack);
+
+ /* If the parser was not originally created as part of the HTML
+ * fragment parsing algorithm (fragment case), and the current
+ * node is no longer a frameset element, then switch the
+ * insertion mode to "after frameset". */
+ $this->mode = self::AFTER_FRAMESET;
+ }
+
+ /* A start tag with the tag name "frame" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ $token['name'] === 'frame') {
+ /* Insert an HTML element for the token. */
+ $this->insertElement($token);
+
+ /* Immediately pop the current node off the stack of open elements. */
+ array_pop($this->stack);
+
+ // XERROR: Acknowledge the token's self-closing flag, if it is set.
+
+ /* A start tag with the tag name "noframes" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ $token['name'] === 'noframes') {
+ /* Process the token using the rules for the "in head" insertion mode. */
+ $this->processwithRulesFor($token, self::IN_HEAD);
+
+ } elseif($token['type'] === HTML5_Tokenizer::EOF) {
+ // XERROR: If the current node is not the root html element, then this is a parse error.
+ /* Stop parsing */
+ /* Anything else */
+ } else {
+ /* Parse error. Ignore the token. */
+ $this->ignored = true;
+ }
+ break;
+
+ case self::AFTER_FRAMESET:
+ /* Handle the token as follows: */
+
+ /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+ U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+ U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */
+ if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
+ /* Append the character to the current node. */
+ $this->insertText($token['data']);
+
+ /* A comment token */
+ } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
+ /* Append a Comment node to the current node with the data
+ attribute set to the data given in the comment token. */
+ $this->insertComment($token['data']);
+
+ } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
+ // parse error
+
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {
+ $this->processWithRulesFor($token, self::IN_BODY);
+
+ /* An end tag with the tag name "html" */
+ } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
+ $token['name'] === 'html') {
+ $this->mode = self::AFTER_AFTER_FRAMESET;
+
+ /* A start tag with the tag name "noframes" */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
+ $token['name'] === 'noframes') {
+ $this->processWithRulesFor($token, self::IN_HEAD);
+
+ } elseif($token['type'] === HTML5_Tokenizer::EOF) {
+ /* Stop parsing */
+
+ /* Anything else */
+ } else {
+ /* Parse error. Ignore the token. */
+ $this->ignored = true;
+ }
+ break;
+
+ case self::AFTER_AFTER_BODY:
+ /* A comment token */
+ if($token['type'] === HTML5_Tokenizer::COMMENT) {
+ /* Append a Comment node to the Document object with the data
+ attribute set to the data given in the comment token. */
+ // XDOM
+ $comment = $this->dom->createComment($token['data']);
+ $this->dom->appendChild($comment);
+
+ } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE ||
+ $token['type'] === HTML5_Tokenizer::SPACECHARACTER ||
+ ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html')) {
+ $this->processWithRulesFor($token, self::IN_BODY);
+
+ /* An end-of-file token */
+ } elseif($token['type'] === HTML5_Tokenizer::EOF) {
+ /* OMG DONE!! */
+ } else {
+ // parse error
+ $this->mode = self::IN_BODY;
+ $this->emitToken($token);
+ }
+ break;
+
+ case self::AFTER_AFTER_FRAMESET:
+ /* A comment token */
+ if($token['type'] === HTML5_Tokenizer::COMMENT) {
+ /* Append a Comment node to the Document object with the data
+ attribute set to the data given in the comment token. */
+ // XDOM
+ $comment = $this->dom->createComment($token['data']);
+ $this->dom->appendChild($comment);
+
+ } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE ||
+ $token['type'] === HTML5_Tokenizer::SPACECHARACTER ||
+ ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html')) {
+ $this->processWithRulesFor($token, self::IN_BODY);
+
+ /* An end-of-file token */
+ } elseif($token['type'] === HTML5_Tokenizer::EOF) {
+ /* OMG DONE!! */
+ } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'nofrmaes') {
+ $this->processWithRulesFor($token, self::IN_HEAD);
+ } else {
+ // parse error
+ }
+ break;
+ }
+ // end funky indenting
+ }
+
+ private function insertElement($token, $append = true) {
+ $el = $this->dom->createElementNS(self::NS_HTML, $token['name']);
+
+ if (!empty($token['attr'])) {
+ foreach($token['attr'] as $attr) {
+ if(!$el->hasAttribute($attr['name']) && preg_match("/^[a-zA-Z_:]/", $attr['name'])) {
+ $el->setAttribute($attr['name'], $attr['value']);
+ }
+ }
+ }
+ if ($append) {
+ $this->appendToRealParent($el);
+ $this->stack[] = $el;
+ }
+
+ return $el;
+ }
+
+ private function insertText($data) {
+ if ($data === '') return;
+ if ($this->ignore_lf_token) {
+ if ($data[0] === "\n") {
+ $data = substr($data, 1);
+ if ($data === false) return;
+ }
+ }
+ $text = $this->dom->createTextNode($data);
+ $this->appendToRealParent($text);
+ }
+
+ private function insertComment($data) {
+ $comment = $this->dom->createComment($data);
+ $this->appendToRealParent($comment);
+ }
+
+ private function appendToRealParent($node) {
+ // this is only for the foster_parent case
+ /* If the current node is a table, tbody, tfoot, thead, or tr
+ element, then, whenever a node would be inserted into the current
+ node, it must instead be inserted into the foster parent element. */
+ if(!$this->foster_parent || !in_array(end($this->stack)->tagName,
+ array('table', 'tbody', 'tfoot', 'thead', 'tr'))) {
+ end($this->stack)->appendChild($node);
+ } else {
+ $this->fosterParent($node);
+ }
+ }
+
+ private function elementInScope($el, $scope = self::SCOPE) {
+ if(is_array($el)) {
+ foreach($el as $element) {
+ if($this->elementInScope($element, $scope)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ $leng = count($this->stack);
+
+ for($n = 0; $n < $leng; $n++) {
+ /* 1. Initialise node to be the current node (the bottommost node of
+ the stack). */
+ $node = $this->stack[$leng - 1 - $n];
+
+ if($node->tagName === $el) {
+ /* 2. If node is the target node, terminate in a match state. */
+ return true;
+
+ // We've expanded the logic for these states a little differently;
+ // Hixie's refactoring into "specific scope" is more general, but
+ // this "gets the job done"
+
+ // these are the common states for all scopes
+ } elseif($node->tagName === 'table' || $node->tagName === 'html') {
+ return false;
+
+ // these are valid for "in scope" and "in list item scope"
+ } elseif($scope !== self::SCOPE_TABLE &&
+ (in_array($node->tagName, array('applet', 'caption', 'td',
+ 'th', 'button', 'marquee', 'object')) ||
+ $node->tagName === 'foreignObject' && $node->namespaceURI === self::NS_SVG)) {
+ return false;
+
+
+ // these are valid for "in list item scope"
+ } elseif($scope === self::SCOPE_LISTITEM && in_array($node->tagName, array('ol', 'ul'))) {
+ return false;
+ }
+
+ /* Otherwise, set node to the previous entry in the stack of open
+ elements and return to step 2. (This will never fail, since the loop
+ will always terminate in the previous step if the top of the stack
+ is reached.) */
+ }
+ }
+
+ private function reconstructActiveFormattingElements() {
+ /* 1. If there are no entries in the list of active formatting elements,
+ then there is nothing to reconstruct; stop this algorithm. */
+ $formatting_elements = count($this->a_formatting);
+
+ if($formatting_elements === 0) {
+ return false;
+ }
+
+ /* 3. Let entry be the last (most recently added) element in the list
+ of active formatting elements. */
+ $entry = end($this->a_formatting);
+
+ /* 2. If the last (most recently added) entry in the list of active
+ formatting elements is a marker, or if it is an element that is in the
+ stack of open elements, then there is nothing to reconstruct; stop this
+ algorithm. */
+ if($entry === self::MARKER || in_array($entry, $this->stack, true)) {
+ return false;
+ }
+
+ for($a = $formatting_elements - 1; $a >= 0; true) {
+ /* 4. If there are no entries before entry in the list of active
+ formatting elements, then jump to step 8. */
+ if($a === 0) {
+ $step_seven = false;
+ break;
+ }
+
+ /* 5. Let entry be the entry one earlier than entry in the list of
+ active formatting elements. */
+ $a--;
+ $entry = $this->a_formatting[$a];
+
+ /* 6. If entry is neither a marker nor an element that is also in
+ thetack of open elements, go to step 4. */
+ if($entry === self::MARKER || in_array($entry, $this->stack, true)) {
+ break;
+ }
+ }
+
+ while(true) {
+ /* 7. Let entry be the element one later than entry in the list of
+ active formatting elements. */
+ if(isset($step_seven) && $step_seven === true) {
+ $a++;
+ $entry = $this->a_formatting[$a];
+ }
+
+ /* 8. Perform a shallow clone of the element entry to obtain clone. */
+ $clone = $entry->cloneNode();
+
+ /* 9. Append clone to the current node and push it onto the stack
+ of open elements so that it is the new current node. */
+ $this->appendToRealParent($clone);
+ $this->stack[] = $clone;
+
+ /* 10. Replace the entry for entry in the list with an entry for
+ clone. */
+ $this->a_formatting[$a] = $clone;
+
+ /* 11. If the entry for clone in the list of active formatting
+ elements is not the last entry in the list, return to step 7. */
+ if(end($this->a_formatting) !== $clone) {
+ $step_seven = true;
+ } else {
+ break;
+ }
+ }
+ }
+
+ private function clearTheActiveFormattingElementsUpToTheLastMarker() {
+ /* When the steps below require the UA to clear the list of active
+ formatting elements up to the last marker, the UA must perform the
+ following steps: */
+
+ while(true) {
+ /* 1. Let entry be the last (most recently added) entry in the list
+ of active formatting elements. */
+ $entry = end($this->a_formatting);
+
+ /* 2. Remove entry from the list of active formatting elements. */
+ array_pop($this->a_formatting);
+
+ /* 3. If entry was a marker, then stop the algorithm at this point.
+ The list has been cleared up to the last marker. */
+ if($entry === self::MARKER) {
+ break;
+ }
+ }
+ }
+
+ private function generateImpliedEndTags($exclude = array()) {
+ /* When the steps below require the UA to generate implied end tags,
+ * then, while the current node is a dc element, a dd element, a ds
+ * element, a dt element, an li element, an option element, an optgroup
+ * element, a p element, an rp element, or an rt element, the UA must
+ * pop the current node off the stack of open elements. */
+ $node = end($this->stack);
+ $elements = array_diff(array('dc', 'dd', 'ds', 'dt', 'li', 'p', 'td', 'th', 'tr'), $exclude);
+
+ while(in_array(end($this->stack)->tagName, $elements)) {
+ array_pop($this->stack);
+ }
+ }
+
+ private function getElementCategory($node) {
+ if (!is_object($node)) debug_print_backtrace();
+ $name = $node->tagName;
+ if(in_array($name, $this->special))
+ return self::SPECIAL;
+
+ elseif(in_array($name, $this->scoping))
+ return self::SCOPING;
+
+ elseif(in_array($name, $this->formatting))
+ return self::FORMATTING;
+
+ else
+ return self::PHRASING;
+ }
+
+ private function clearStackToTableContext($elements) {
+ /* When the steps above require the UA to clear the stack back to a
+ table context, it means that the UA must, while the current node is not
+ a table element or an html element, pop elements from the stack of open
+ elements. */
+ while(true) {
+ $name = end($this->stack)->tagName;
+
+ if(in_array($name, $elements)) {
+ break;
+ } else {
+ array_pop($this->stack);
+ }
+ }
+ }
+
+ private function resetInsertionMode($context = null) {
+ /* 1. Let last be false. */
+ $last = false;
+ $leng = count($this->stack);
+
+ for($n = $leng - 1; $n >= 0; $n--) {
+ /* 2. Let node be the last node in the stack of open elements. */
+ $node = $this->stack[$n];
+
+ /* 3. If node is the first node in the stack of open elements, then
+ * set last to true and set node to the context element. (fragment
+ * case) */
+ if($this->stack[0]->isSameNode($node)) {
+ $last = true;
+ $node = $context;
+ }
+
+ /* 4. If node is a select element, then switch the insertion mode to
+ "in select" and abort these steps. (fragment case) */
+ if($node->tagName === 'select') {
+ $this->mode = self::IN_SELECT;
+ break;
+
+ /* 5. If node is a td or th element, then switch the insertion mode
+ to "in cell" and abort these steps. */
+ } elseif($node->tagName === 'td' || $node->nodeName === 'th') {
+ $this->mode = self::IN_CELL;
+ break;
+
+ /* 6. If node is a tr element, then switch the insertion mode to
+ "in row" and abort these steps. */
+ } elseif($node->tagName === 'tr') {
+ $this->mode = self::IN_ROW;
+ break;
+
+ /* 7. If node is a tbody, thead, or tfoot element, then switch the
+ insertion mode to "in table body" and abort these steps. */
+ } elseif(in_array($node->tagName, array('tbody', 'thead', 'tfoot'))) {
+ $this->mode = self::IN_TABLE_BODY;
+ break;
+
+ /* 8. If node is a caption element, then switch the insertion mode
+ to "in caption" and abort these steps. */
+ } elseif($node->tagName === 'caption') {
+ $this->mode = self::IN_CAPTION;
+ break;
+
+ /* 9. If node is a colgroup element, then switch the insertion mode
+ to "in column group" and abort these steps. (innerHTML case) */
+ } elseif($node->tagName === 'colgroup') {
+ $this->mode = self::IN_COLUMN_GROUP;
+ break;
+
+ /* 10. If node is a table element, then switch the insertion mode
+ to "in table" and abort these steps. */
+ } elseif($node->tagName === 'table') {
+ $this->mode = self::IN_TABLE;
+ break;
+
+ /* 11. If node is an element from the MathML namespace or the SVG
+ * namespace, then switch the insertion mode to "in foreign
+ * content", let the secondary insertion mode be "in body", and
+ * abort these steps. */
+ } elseif($node->namespaceURI === self::NS_SVG ||
+ $node->namespaceURI === self::NS_MATHML) {
+ $this->mode = self::IN_FOREIGN_CONTENT;
+ $this->secondary_mode = self::IN_BODY;
+ break;
+
+ /* 12. If node is a head element, then switch the insertion mode
+ to "in body" ("in body"! not "in head"!) and abort these steps.
+ (fragment case) */
+ } elseif($node->tagName === 'head') {
+ $this->mode = self::IN_BODY;
+ break;
+
+ /* 13. If node is a body element, then switch the insertion mode to
+ "in body" and abort these steps. */
+ } elseif($node->tagName === 'body') {
+ $this->mode = self::IN_BODY;
+ break;
+
+ /* 14. If node is a frameset element, then switch the insertion
+ mode to "in frameset" and abort these steps. (fragment case) */
+ } elseif($node->tagName === 'frameset') {
+ $this->mode = self::IN_FRAMESET;
+ break;
+
+ /* 15. If node is an html element, then: if the head element
+ pointer is null, switch the insertion mode to "before head",
+ otherwise, switch the insertion mode to "after head". In either
+ case, abort these steps. (fragment case) */
+ } elseif($node->tagName === 'html') {
+ $this->mode = ($this->head_pointer === null)
+ ? self::BEFORE_HEAD
+ : self::AFTER_HEAD;
+
+ break;
+
+ /* 16. If last is true, then set the insertion mode to "in body"
+ and abort these steps. (fragment case) */
+ } elseif($last) {
+ $this->mode = self::IN_BODY;
+ break;
+ }
+ }
+ }
+
+ private function closeCell() {
+ /* If the stack of open elements has a td or th element in table scope,
+ then act as if an end tag token with that tag name had been seen. */
+ foreach(array('td', 'th') as $cell) {
+ if($this->elementInScope($cell, self::SCOPE_TABLE)) {
+ $this->emitToken(array(
+ 'name' => $cell,
+ 'type' => HTML5_Tokenizer::ENDTAG
+ ));
+
+ break;
+ }
+ }
+ }
+
+ private function processWithRulesFor($token, $mode) {
+ /* "using the rules for the m insertion mode", where m is one of these
+ * modes, the user agent must use the rules described under the m
+ * insertion mode's section, but must leave the insertion mode
+ * unchanged unless the rules in m themselves switch the insertion mode
+ * to a new value. */
+ return $this->emitToken($token, $mode);
+ }
+
+ private function insertCDATAElement($token) {
+ $this->insertElement($token);
+ $this->original_mode = $this->mode;
+ $this->mode = self::IN_CDATA_RCDATA;
+ $this->content_model = HTML5_Tokenizer::CDATA;
+ }
+
+ private function insertRCDATAElement($token) {
+ $this->insertElement($token);
+ $this->original_mode = $this->mode;
+ $this->mode = self::IN_CDATA_RCDATA;
+ $this->content_model = HTML5_Tokenizer::RCDATA;
+ }
+
+ private function getAttr($token, $key) {
+ if (!isset($token['attr'])) return false;
+ $ret = false;
+ foreach ($token['attr'] as $keypair) {
+ if ($keypair['name'] === $key) $ret = $keypair['value'];
+ }
+ return $ret;
+ }
+
+ private function getCurrentTable() {
+ /* The current table is the last table element in the stack of open
+ * elements, if there is one. If there is no table element in the stack
+ * of open elements (fragment case), then the current table is the
+ * first element in the stack of open elements (the html element). */
+ for ($i = count($this->stack) - 1; $i >= 0; $i--) {
+ if ($this->stack[$i]->tagName === 'table') {
+ return $this->stack[$i];
+ }
+ }
+ return $this->stack[0];
+ }
+
+ private function getFosterParent() {
+ /* The foster parent element is the parent element of the last
+ table element in the stack of open elements, if there is a
+ table element and it has such a parent element. If there is no
+ table element in the stack of open elements (innerHTML case),
+ then the foster parent element is the first element in the
+ stack of open elements (the html element). Otherwise, if there
+ is a table element in the stack of open elements, but the last
+ table element in the stack of open elements has no parent, or
+ its parent node is not an element, then the foster parent
+ element is the element before the last table element in the
+ stack of open elements. */
+ for($n = count($this->stack) - 1; $n >= 0; $n--) {
+ if($this->stack[$n]->tagName === 'table') {
+ $table = $this->stack[$n];
+ break;
+ }
+ }
+
+ if(isset($table) && $table->parentNode !== null) {
+ return $table->parentNode;
+
+ } elseif(!isset($table)) {
+ return $this->stack[0];
+
+ } elseif(isset($table) && ($table->parentNode === null ||
+ $table->parentNode->nodeType !== XML_ELEMENT_NODE)) {
+ return $this->stack[$n - 1];
+ }
+ }
+
+ public function fosterParent($node) {
+ $foster_parent = $this->getFosterParent();
+ $table = $this->getCurrentTable(); // almost equivalent to last table element, except it can be html
+ /* When a node node is to be foster parented, the node node must be
+ * be inserted into the foster parent element. */
+ /* If the foster parent element is the parent element of the last table
+ * element in the stack of open elements, then node must be inserted
+ * immediately before the last table element in the stack of open
+ * elements in the foster parent element; otherwise, node must be
+ * appended to the foster parent element. */
+ if ($table->tagName === 'table' && $table->parentNode->isSameNode($foster_parent)) {
+ $foster_parent->insertBefore($node, $table);
+ } else {
+ $foster_parent->appendChild($node);
+ }
+ }
+
+ /**
+ * For debugging, prints the stack
+ */
+ private function printStack() {
+ $names = array();
+ foreach ($this->stack as $i => $element) {
+ $names[] = $element->tagName;
+ }
+ echo " -> stack [" . implode(', ', $names) . "]\n";
+ }
+
+ /**
+ * For debugging, prints active formatting elements
+ */
+ private function printActiveFormattingElements() {
+ if (!$this->a_formatting) return;
+ $names = array();
+ foreach ($this->a_formatting as $node) {
+ if ($node === self::MARKER) $names[] = 'MARKER';
+ else $names[] = $node->tagName;
+ }
+ echo " -> active formatting [" . implode(', ', $names) . "]\n";
+ }
+
+ public function currentTableIsTainted() {
+ return !empty($this->getCurrentTable()->tainted);
+ }
+
+ /**
+ * Sets up the tree constructor for building a fragment.
+ */
+ public function setupContext($context = null) {
+ $this->fragment = true;
+ if ($context) {
+ $context = $this->dom->createElementNS(self::NS_HTML, $context);
+ /* 4.1. Set the HTML parser's tokenization stage's content model
+ * flag according to the context element, as follows: */
+ switch ($context->tagName) {
+ case 'title': case 'textarea':
+ $this->content_model = HTML5_Tokenizer::RCDATA;
+ break;
+ case 'style': case 'script': case 'xmp': case 'iframe':
+ case 'noembed': case 'noframes':
+ $this->content_model = HTML5_Tokenizer::CDATA;
+ break;
+ case 'noscript':
+ // XSCRIPT: assuming scripting is enabled
+ $this->content_model = HTML5_Tokenizer::CDATA;
+ break;
+ case 'plaintext':
+ $this->content_model = HTML5_Tokenizer::PLAINTEXT;
+ break;
+ }
+ /* 4.2. Let root be a new html element with no attributes. */
+ $root = $this->dom->createElementNS(self::NS_HTML, 'html');
+ $this->root = $root;
+ /* 4.3 Append the element root to the Document node created above. */
+ $this->dom->appendChild($root);
+ /* 4.4 Set up the parser's stack of open elements so that it
+ * contains just the single element root. */
+ $this->stack = array($root);
+ /* 4.5 Reset the parser's insertion mode appropriately. */
+ $this->resetInsertionMode($context);
+ /* 4.6 Set the parser's form element pointer to the nearest node
+ * to the context element that is a form element (going straight up
+ * the ancestor chain, and including the element itself, if it is a
+ * form element), or, if there is no such form element, to null. */
+ $node = $context;
+ do {
+ if ($node->tagName === 'form') {
+ $this->form_pointer = $node;
+ break;
+ }
+ } while ($node = $node->parentNode);
+ }
+ }
+
+ public function adjustMathMLAttributes($token) {
+ foreach ($token['attr'] as &$kp) {
+ if ($kp['name'] === 'definitionurl') {
+ $kp['name'] = 'definitionURL';
+ }
+ }
+ return $token;
+ }
+
+ public function adjustSVGAttributes($token) {
+ static $lookup = array(
+ 'attributename' => 'attributeName',
+ 'attributetype' => 'attributeType',
+ 'basefrequency' => 'baseFrequency',
+ 'baseprofile' => 'baseProfile',
+ 'calcmode' => 'calcMode',
+ 'clippathunits' => 'clipPathUnits',
+ 'contentscripttype' => 'contentScriptType',
+ 'contentstyletype' => 'contentStyleType',
+ 'diffuseconstant' => 'diffuseConstant',
+ 'edgemode' => 'edgeMode',
+ 'externalresourcesrequired' => 'externalResourcesRequired',
+ 'filterres' => 'filterRes',
+ 'filterunits' => 'filterUnits',
+ 'glyphref' => 'glyphRef',
+ 'gradienttransform' => 'gradientTransform',
+ 'gradientunits' => 'gradientUnits',
+ 'kernelmatrix' => 'kernelMatrix',
+ 'kernelunitlength' => 'kernelUnitLength',
+ 'keypoints' => 'keyPoints',
+ 'keysplines' => 'keySplines',
+ 'keytimes' => 'keyTimes',
+ 'lengthadjust' => 'lengthAdjust',
+ 'limitingconeangle' => 'limitingConeAngle',
+ 'markerheight' => 'markerHeight',
+ 'markerunits' => 'markerUnits',
+ 'markerwidth' => 'markerWidth',
+ 'maskcontentunits' => 'maskContentUnits',
+ 'maskunits' => 'maskUnits',
+ 'numoctaves' => 'numOctaves',
+ 'pathlength' => 'pathLength',
+ 'patterncontentunits' => 'patternContentUnits',
+ 'patterntransform' => 'patternTransform',
+ 'patternunits' => 'patternUnits',
+ 'pointsatx' => 'pointsAtX',
+ 'pointsaty' => 'pointsAtY',
+ 'pointsatz' => 'pointsAtZ',
+ 'preservealpha' => 'preserveAlpha',
+ 'preserveaspectratio' => 'preserveAspectRatio',
+ 'primitiveunits' => 'primitiveUnits',
+ 'refx' => 'refX',
+ 'refy' => 'refY',
+ 'repeatcount' => 'repeatCount',
+ 'repeatdur' => 'repeatDur',
+ 'requiredextensions' => 'requiredExtensions',
+ 'requiredfeatures' => 'requiredFeatures',
+ 'specularconstant' => 'specularConstant',
+ 'specularexponent' => 'specularExponent',
+ 'spreadmethod' => 'spreadMethod',
+ 'startoffset' => 'startOffset',
+ 'stddeviation' => 'stdDeviation',
+ 'stitchtiles' => 'stitchTiles',
+ 'surfacescale' => 'surfaceScale',
+ 'systemlanguage' => 'systemLanguage',
+ 'tablevalues' => 'tableValues',
+ 'targetx' => 'targetX',
+ 'targety' => 'targetY',
+ 'textlength' => 'textLength',
+ 'viewbox' => 'viewBox',
+ 'viewtarget' => 'viewTarget',
+ 'xchannelselector' => 'xChannelSelector',
+ 'ychannelselector' => 'yChannelSelector',
+ 'zoomandpan' => 'zoomAndPan',
+ );
+ foreach ($token['attr'] as &$kp) {
+ if (isset($lookup[$kp['name']])) {
+ $kp['name'] = $lookup[$kp['name']];
+ }
+ }
+ return $token;
+ }
+
+ public function adjustForeignAttributes($token) {
+ static $lookup = array(
+ 'xlink:actuate' => array('xlink', 'actuate', self::NS_XLINK),
+ 'xlink:arcrole' => array('xlink', 'arcrole', self::NS_XLINK),
+ 'xlink:href' => array('xlink', 'href', self::NS_XLINK),
+ 'xlink:role' => array('xlink', 'role', self::NS_XLINK),
+ 'xlink:show' => array('xlink', 'show', self::NS_XLINK),
+ 'xlink:title' => array('xlink', 'title', self::NS_XLINK),
+ 'xlink:type' => array('xlink', 'type', self::NS_XLINK),
+ 'xml:base' => array('xml', 'base', self::NS_XML),
+ 'xml:lang' => array('xml', 'lang', self::NS_XML),
+ 'xml:space' => array('xml', 'space', self::NS_XML),
+ 'xmlns' => array(null, 'xmlns', self::NS_XMLNS),
+ 'xmlns:xlink' => array('xmlns', 'xlink', self::NS_XMLNS),
+ );
+ foreach ($token['attr'] as &$kp) {
+ if (isset($lookup[$kp['name']])) {
+ $kp['name'] = $lookup[$kp['name']];
+ }
+ }
+ return $token;
+ }
+
+ public function insertForeignElement($token, $namespaceURI) {
+ $el = $this->dom->createElementNS($namespaceURI, $token['name']);
+ if (!empty($token['attr'])) {
+ foreach ($token['attr'] as $kp) {
+ $attr = $kp['name'];
+ if (is_array($attr)) {
+ $ns = $attr[2];
+ $attr = $attr[1];
+ } else {
+ $ns = self::NS_HTML;
+ }
+ if (!$el->hasAttributeNS($ns, $attr)) {
+ // XSKETCHY: work around godawful libxml bug
+ if ($ns === self::NS_XLINK) {
+ $el->setAttribute('xlink:'.$attr, $kp['value']);
+ } elseif ($ns === self::NS_HTML) {
+ // Another godawful libxml bug
+ $el->setAttribute($attr, $kp['value']);
+ } else {
+ $el->setAttributeNS($ns, $attr, $kp['value']);
+ }
+ }
+ }
+ }
+ $this->appendToRealParent($el);
+ $this->stack[] = $el;
+ // XERROR: see below
+ /* If the newly created element has an xmlns attribute in the XMLNS
+ * namespace whose value is not exactly the same as the element's
+ * namespace, that is a parse error. Similarly, if the newly created
+ * element has an xmlns:xlink attribute in the XMLNS namespace whose
+ * value is not the XLink Namespace, that is a parse error. */
+ }
+
+ public function save() {
+ $this->dom->normalize();
+ if (!$this->fragment) {
+ return $this->dom;
+ } else {
+ if ($this->root) {
+ return $this->root->childNodes;
+ } else {
+ return $this->dom->childNodes;
+ }
+ }
+ }
+}
+
diff --git a/application/third_party/dompdf/lib/html5lib/named-character-references.ser b/application/third_party/dompdf/lib/html5lib/named-character-references.ser
new file mode 100644
index 00000000..e3ae0502
--- /dev/null
+++ b/application/third_party/dompdf/lib/html5lib/named-character-references.ser
@@ -0,0 +1 @@
+a:52:{s:1:"A";a:16:{s:1:"E";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:198;}s:9:"codepoint";i:198;}}}}s:1:"M";a:1:{s:1:"P";a:2:{s:1:";";a:1:{s:9:"codepoint";i:38;}s:9:"codepoint";i:38;}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:193;}s:9:"codepoint";i:193;}}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:258;}}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:194;}s:9:"codepoint";i:194;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1040;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120068;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:192;}s:9:"codepoint";i:192;}}}}}s:1:"l";a:1:{s:1:"p";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:913;}}}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:256;}}}}}s:1:"n";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10835;}}}s:1:"o";a:2:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:260;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120120;}}}}s:1:"p";a:1:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"y";a:1:{s:1:"F";a:1:{s:1:"u";a:1:{s:1:"n";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8289;}}}}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:197;}s:9:"codepoint";i:197;}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119964;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8788;}}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:195;}s:9:"codepoint";i:195;}}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:196;}s:9:"codepoint";i:196;}}}}s:1:"B";a:8:{s:1:"a";a:2:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"s";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8726;}}}}}}}}s:1:"r";a:2:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10983;}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8966;}}}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1041;}}}s:1:"e";a:3:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8757;}}}}}}s:1:"r";a:1:{s:1:"n";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8492;}}}}}}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:914;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120069;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120121;}}}}s:1:"r";a:1:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:728;}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8492;}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"p";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8782;}}}}}}}s:1:"C";a:14:{s:1:"H";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1063;}}}}s:1:"O";a:1:{s:1:"P";a:1:{s:1:"Y";a:2:{s:1:";";a:1:{s:9:"codepoint";i:169;}s:9:"codepoint";i:169;}}}s:1:"a";a:3:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:262;}}}}}s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8914;}s:1:"i";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"D";a:1:{s:1:"i";a:1:{s:1:"f";a:1:{s:1:"f";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"D";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8517;}}}}}}}}}}}}}}}}}}}s:1:"y";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"y";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8493;}}}}}}}s:1:"c";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:268;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:199;}s:9:"codepoint";i:199;}}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:264;}}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8752;}}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:266;}}}}s:1:"e";a:2:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:184;}}}}}}s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:183;}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8493;}}}s:1:"h";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:935;}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:"l";a:1:{s:1:"e";a:4:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8857;}}}}s:1:"M";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8854;}}}}}}s:1:"P";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8853;}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8855;}}}}}}}}}}}s:1:"l";a:1:{s:1:"o";a:2:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"w";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"C";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"I";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8754;}}}}}}}}}}}}}}}}}}}}}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"C";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"l";a:1:{s:1:"y";a:2:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"Q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8221;}}}}}}}}}}}}s:1:"Q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8217;}}}}}}}}}}}}}}}s:1:"o";a:4:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8759;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10868;}}}}}s:1:"n";a:3:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8801;}}}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8751;}}}}s:1:"t";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"I";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8750;}}}}}}}}}}}}}}s:1:"p";a:2:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8450;}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"d";a:1:{s:1:"u";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8720;}}}}}}}}s:1:"u";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"C";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"w";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"C";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"I";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8755;}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10799;}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119966;}}}}s:1:"u";a:1:{s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8915;}s:1:"C";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8781;}}}}}}}s:1:"D";a:11:{s:1:"D";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8517;}s:1:"o";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"h";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10513;}}}}}}}}s:1:"J";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1026;}}}}s:1:"S";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1029;}}}}s:1:"Z";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1039;}}}}s:1:"a";a:3:{s:1:"g";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8225;}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8609;}}}s:1:"s";a:1:{s:1:"h";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10980;}}}}}s:1:"c";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:270;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1044;}}}s:1:"e";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8711;}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:916;}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120071;}}}s:1:"i";a:2:{s:1:"a";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:4:{s:1:"A";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:180;}}}}}}s:1:"D";a:1:{s:1:"o";a:2:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:729;}}s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"A";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:733;}}}}}}}}}}}}s:1:"G";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:96;}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:732;}}}}}}}}}}}}}}s:1:"m";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8900;}}}}}}s:1:"f";a:1:{s:1:"f";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"D";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8518;}}}}}}}}}}}}}s:1:"o";a:4:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120123;}}}s:1:"t";a:3:{s:1:";";a:1:{s:9:"codepoint";i:168;}s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8412;}}}}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8784;}}}}}}}s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:6:{s:1:"C";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"I";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8751;}}}}}}}}}}}}}}}}s:1:"D";a:1:{s:1:"o";a:2:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:168;}}s:1:"w";a:1:{s:1:"n";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8659;}}}}}}}}}}s:1:"L";a:2:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:3:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8656;}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8660;}}}}}}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10980;}}}}}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"g";a:2:{s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10232;}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10234;}}}}}}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10233;}}}}}}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8658;}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8872;}}}}}}}}}s:1:"U";a:1:{s:1:"p";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8657;}}}}}}s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8661;}}}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8741;}}}}}}}}}}}}}}}}s:1:"w";a:1:{s:1:"n";a:6:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8595;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10515;}}}}s:1:"U";a:1:{s:1:"p";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8693;}}}}}}}}}}}}}s:1:"B";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:785;}}}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:3:{s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10576;}}}}}}}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10590;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8637;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10582;}}}}}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:2:{s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10591;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8641;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10583;}}}}}}}}}}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8868;}s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8615;}}}}}}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8659;}}}}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119967;}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:272;}}}}}}}s:1:"E";a:16:{s:1:"N";a:1:{s:1:"G";a:1:{s:1:";";a:1:{s:9:"codepoint";i:330;}}}s:1:"T";a:1:{s:1:"H";a:2:{s:1:";";a:1:{s:9:"codepoint";i:208;}s:9:"codepoint";i:208;}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:201;}s:9:"codepoint";i:201;}}}}}s:1:"c";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:282;}}}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:202;}s:9:"codepoint";i:202;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1069;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:278;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120072;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:200;}s:9:"codepoint";i:200;}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8712;}}}}}}}s:1:"m";a:2:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:274;}}}}s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:2:{s:1:"S";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"S";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9723;}}}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"y";a:1:{s:1:"S";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"S";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9643;}}}}}}}}}}}}}}}}}}}}s:1:"o";a:2:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:280;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120124;}}}}s:1:"p";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:917;}}}}}}}s:1:"q";a:1:{s:1:"u";a:2:{s:1:"a";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10869;}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8770;}}}}}}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"b";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8652;}}}}}}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8496;}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10867;}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:919;}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:203;}s:9:"codepoint";i:203;}}}s:1:"x";a:2:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8707;}}}}}s:1:"p";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8519;}}}}}}}}}}}}}s:1:"F";a:5:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1060;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120073;}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"d";a:2:{s:1:"S";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"S";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9724;}}}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"y";a:1:{s:1:"S";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"S";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9642;}}}}}}}}}}}}}}}}}}}}}s:1:"o";a:3:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120125;}}}s:1:"r";a:1:{s:1:"A";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8704;}}}}}s:1:"u";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8497;}}}}}}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8497;}}}}}s:1:"G";a:12:{s:1:"J";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1027;}}}}s:1:"T";a:2:{s:1:";";a:1:{s:9:"codepoint";i:62;}s:9:"codepoint";i:62;}s:1:"a";a:1:{s:1:"m";a:1:{s:1:"m";a:1:{s:1:"a";a:2:{s:1:";";a:1:{s:9:"codepoint";i:915;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:988;}}}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:286;}}}}}}s:1:"c";a:3:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:290;}}}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:284;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1043;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:288;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120074;}}}s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8921;}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120126;}}}}s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:6:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8805;}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8923;}}}}}}}}}}s:1:"F";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8807;}}}}}}}}}}s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10914;}}}}}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8823;}}}}}s:1:"S";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10878;}}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8819;}}}}}}}}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119970;}}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8811;}}}s:1:"H";a:8:{s:1:"A";a:1:{s:1:"R";a:1:{s:1:"D";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1066;}}}}}}s:1:"a";a:2:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:711;}}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:94;}}}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:292;}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8460;}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"b";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8459;}}}}}}}}}}}}s:1:"o";a:2:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8461;}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"z";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"L";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9472;}}}}}}}}}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8459;}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:294;}}}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"p";a:2:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"H";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8782;}}}}}}}}}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8783;}}}}}}}}}}s:1:"I";a:14:{s:1:"E";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1045;}}}}s:1:"J";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:306;}}}}}s:1:"O";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1025;}}}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:205;}s:9:"codepoint";i:205;}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:206;}s:9:"codepoint";i:206;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1048;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:304;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8465;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:204;}s:9:"codepoint";i:204;}}}}}s:1:"m";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8465;}s:1:"a";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:298;}}}s:1:"g";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"y";a:1:{s:1:"I";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8520;}}}}}}}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8658;}}}}}}}s:1:"n";a:2:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8748;}s:1:"e";a:2:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8747;}}}}}s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8898;}}}}}}}}}}}s:1:"v";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:2:{s:1:"C";a:1:{s:1:"o";a:1:{s:1:"m";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8291;}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8290;}}}}}}}}}}}}}}s:1:"o";a:3:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:302;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120128;}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:921;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8464;}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:296;}}}}}}s:1:"u";a:2:{s:1:"k";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1030;}}}}s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:207;}s:9:"codepoint";i:207;}}}}s:1:"J";a:5:{s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:308;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1049;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120077;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120129;}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119973;}}}s:1:"e";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1032;}}}}}}s:1:"u";a:1:{s:1:"k";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1028;}}}}}}s:1:"K";a:7:{s:1:"H";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1061;}}}}s:1:"J";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1036;}}}}s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:922;}}}}}s:1:"c";a:2:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:310;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1050;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120078;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120130;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119974;}}}}}s:1:"L";a:11:{s:1:"J";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1033;}}}}s:1:"T";a:2:{s:1:";";a:1:{s:9:"codepoint";i:60;}s:9:"codepoint";i:60;}s:1:"a";a:5:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:313;}}}}}s:1:"m";a:1:{s:1:"b";a:1:{s:1:"d";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:923;}}}}}s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10218;}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8466;}}}}}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8606;}}}}s:1:"c";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:317;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:315;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1051;}}}s:1:"e";a:2:{s:1:"f";a:1:{s:1:"t";a:10:{s:1:"A";a:2:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"B";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10216;}}}}}}}}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8592;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8676;}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8646;}}}}}}}}}}}}}}}}s:1:"C";a:1:{s:1:"e";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8968;}}}}}}}}s:1:"D";a:1:{s:1:"o";a:2:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"B";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10214;}}}}}}}}}}}}s:1:"w";a:1:{s:1:"n";a:2:{s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10593;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8643;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10585;}}}}}}}}}}}}}}s:1:"F";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8970;}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8596;}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10574;}}}}}}}}}}}}s:1:"T";a:2:{s:1:"e";a:1:{s:1:"e";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8867;}s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8612;}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10586;}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8882;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10703;}}}}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8884;}}}}}}}}}}}}}}s:1:"U";a:1:{s:1:"p";a:3:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10577;}}}}}}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10592;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8639;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10584;}}}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8636;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10578;}}}}}}}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8656;}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8660;}}}}}}}}}}}}}s:1:"s";a:1:{s:1:"s";a:6:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8922;}}}}}}}}}}}}}s:1:"F";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8806;}}}}}}}}}}s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8822;}}}}}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10913;}}}}}s:1:"S";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10877;}}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8818;}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120079;}}}s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8920;}s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8666;}}}}}}}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:319;}}}}}}s:1:"o";a:3:{s:1:"n";a:1:{s:1:"g";a:4:{s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10229;}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10231;}}}}}}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10230;}}}}}}}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10232;}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10234;}}}}}}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10233;}}}}}}}}}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120131;}}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"r";a:2:{s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8601;}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8600;}}}}}}}}}}}}}}}s:1:"s";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8466;}}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8624;}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:321;}}}}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8810;}}}s:1:"M";a:8:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10501;}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1052;}}}s:1:"e";a:2:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8287;}}}}}}}}}}s:1:"l";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8499;}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120080;}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:"P";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8723;}}}}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120132;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8499;}}}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:924;}}}s:1:"N";a:9:{s:1:"J";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1034;}}}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:323;}}}}}}s:1:"c";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:327;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:325;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1053;}}}s:1:"e";a:3:{s:1:"g";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"v";a:1:{s:1:"e";a:3:{s:1:"M";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8203;}}}}}}}}}}}}s:1:"T";a:1:{s:1:"h";a:1:{s:1:"i";a:2:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8203;}}}}}}}}s:1:"n";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8203;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"y";a:1:{s:1:"T";a:1:{s:1:"h";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8203;}}}}}}}}}}}}}}}}}}}}s:1:"s";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"d";a:2:{s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8811;}}}}}}}}}}}}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:"L";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8810;}}}}}}}}}}}}}s:1:"w";a:1:{s:1:"L";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10;}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120081;}}}s:1:"o";a:4:{s:1:"B";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8288;}}}}}}s:1:"n";a:1:{s:1:"B";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"k";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:160;}}}}}}}}}}}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8469;}}}s:1:"t";a:11:{s:1:";";a:1:{s:9:"codepoint";i:10988;}s:1:"C";a:2:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8802;}}}}}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:"C";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8813;}}}}}}}s:1:"D";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8742;}}}}}}}}}}}}}}}}}}s:1:"E";a:3:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8713;}}}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8800;}}}}}s:1:"x";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8708;}}}}}}}s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8815;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8817;}}}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8825;}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8821;}}}}}}}}}}}}}s:1:"L";a:1:{s:1:"e";a:2:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"T";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8938;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8940;}}}}}}}}}}}}}}}}s:1:"s";a:1:{s:1:"s";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8814;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8816;}}}}}}s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8824;}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8820;}}}}}}}}}}s:1:"P";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8832;}s:1:"S";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8928;}}}}}}}}}}}}}}}}}}}s:1:"R";a:2:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"E";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8716;}}}}}}}}}}}}}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"T";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8939;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8941;}}}}}}}}}}}}}}}}}}}s:1:"S";a:2:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"S";a:1:{s:1:"u";a:2:{s:1:"b";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8930;}}}}}}}}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8931;}}}}}}}}}}}}}}}}}}}s:1:"u";a:3:{s:1:"b";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8840;}}}}}}}}}}s:1:"c";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8833;}s:1:"S";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8929;}}}}}}}}}}}}}}}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8841;}}}}}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8769;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8772;}}}}}}s:1:"F";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8775;}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8777;}}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8740;}}}}}}}}}}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119977;}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:209;}s:9:"codepoint";i:209;}}}}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:925;}}}s:1:"O";a:14:{s:1:"E";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:338;}}}}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:211;}s:9:"codepoint";i:211;}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:212;}s:9:"codepoint";i:212;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1054;}}}s:1:"d";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:336;}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120082;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:210;}s:9:"codepoint";i:210;}}}}}s:1:"m";a:3:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:332;}}}}s:1:"e";a:1:{s:1:"g";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:937;}}}}s:1:"i";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:927;}}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120134;}}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"C";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"l";a:1:{s:1:"y";a:2:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"Q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8220;}}}}}}}}}}}}s:1:"Q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8216;}}}}}}}}}}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10836;}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119978;}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:2:{s:1:";";a:1:{s:9:"codepoint";i:216;}s:9:"codepoint";i:216;}}}}}s:1:"t";a:1:{s:1:"i";a:2:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:213;}s:9:"codepoint";i:213;}}}s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10807;}}}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:214;}s:9:"codepoint";i:214;}}}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"r";a:2:{s:1:"B";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:175;}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"c";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9182;}}s:1:"k";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9140;}}}}}}}}s:1:"P";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9180;}}}}}}}}}}}}}}}}s:1:"P";a:9:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"D";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8706;}}}}}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1055;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120083;}}}s:1:"h";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:934;}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:928;}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:"M";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:177;}}}}}}}}}s:1:"o";a:2:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8460;}}}}}}}}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8473;}}}}s:1:"r";a:4:{s:1:";";a:1:{s:9:"codepoint";i:10939;}s:1:"e";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:"s";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8826;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10927;}}}}}}s:1:"S";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8828;}}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8830;}}}}}}}}}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8243;}}}}s:1:"o";a:2:{s:1:"d";a:1:{s:1:"u";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8719;}}}}}s:1:"p";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8759;}s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8733;}}}}}}}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119979;}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:936;}}}}s:1:"Q";a:4:{s:1:"U";a:1:{s:1:"O";a:1:{s:1:"T";a:2:{s:1:";";a:1:{s:9:"codepoint";i:34;}s:9:"codepoint";i:34;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120084;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8474;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119980;}}}}}s:1:"R";a:12:{s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10512;}}}}}s:1:"E";a:1:{s:1:"G";a:2:{s:1:";";a:1:{s:9:"codepoint";i:174;}s:9:"codepoint";i:174;}}s:1:"a";a:3:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:340;}}}}}s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10219;}}}s:1:"r";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8608;}s:1:"t";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10518;}}}}}}s:1:"c";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:344;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:342;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1056;}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8476;}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:2:{s:1:"E";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8715;}}}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"b";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8651;}}}}}}}}}}}}s:1:"U";a:1:{s:1:"p";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"b";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10607;}}}}}}}}}}}}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8476;}}}s:1:"h";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:929;}}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:8:{s:1:"A";a:2:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"B";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10217;}}}}}}}}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8594;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8677;}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8644;}}}}}}}}}}}}}}}s:1:"C";a:1:{s:1:"e";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8969;}}}}}}}}s:1:"D";a:1:{s:1:"o";a:2:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"B";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10215;}}}}}}}}}}}}s:1:"w";a:1:{s:1:"n";a:2:{s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10589;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8642;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10581;}}}}}}}}}}}}}}s:1:"F";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8971;}}}}}}s:1:"T";a:2:{s:1:"e";a:1:{s:1:"e";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8866;}s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8614;}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10587;}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8883;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10704;}}}}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8885;}}}}}}}}}}}}}}s:1:"U";a:1:{s:1:"p";a:3:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10575;}}}}}}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10588;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8638;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10580;}}}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8640;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10579;}}}}}}}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8658;}}}}}}}}}}s:1:"o";a:2:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8477;}}}s:1:"u";a:1:{s:1:"n";a:1:{s:1:"d";a:1:{s:1:"I";a:1:{s:1:"m";a:1:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10608;}}}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8667;}}}}}}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8475;}}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8625;}}}s:1:"u";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"D";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"y";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10740;}}}}}}}}}}}}s:1:"S";a:13:{s:1:"H";a:2:{s:1:"C";a:1:{s:1:"H";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1065;}}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1064;}}}}s:1:"O";a:1:{s:1:"F";a:1:{s:1:"T";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1068;}}}}}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:346;}}}}}}s:1:"c";a:5:{s:1:";";a:1:{s:9:"codepoint";i:10940;}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:352;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:350;}}}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:348;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1057;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120086;}}}s:1:"h";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"t";a:4:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8595;}}}}}}}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8592;}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8594;}}}}}}}}}}}s:1:"U";a:1:{s:1:"p";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8593;}}}}}}}}}}}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:931;}}}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"C";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8728;}}}}}}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120138;}}}}s:1:"q";a:2:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8730;}}}s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:4:{s:1:";";a:1:{s:9:"codepoint";i:9633;}s:1:"I";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8851;}}}}}}}}}}}}}s:1:"S";a:1:{s:1:"u";a:2:{s:1:"b";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8847;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8849;}}}}}}}}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8848;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8850;}}}}}}}}}}}}}}s:1:"U";a:1:{s:1:"n";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8852;}}}}}}}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119982;}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8902;}}}}s:1:"u";a:4:{s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8912;}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8912;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8838;}}}}}}}}}}s:1:"c";a:2:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"s";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8827;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10928;}}}}}}s:1:"S";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8829;}}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8831;}}}}}}}}}}}s:1:"h";a:1:{s:1:"T";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8715;}}}}}}}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8721;}}s:1:"p";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8913;}s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8835;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8839;}}}}}}}}}}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8913;}}}}}}}s:1:"T";a:11:{s:1:"H";a:1:{s:1:"O";a:1:{s:1:"R";a:1:{s:1:"N";a:2:{s:1:";";a:1:{s:9:"codepoint";i:222;}s:9:"codepoint";i:222;}}}}s:1:"R";a:1:{s:1:"A";a:1:{s:1:"D";a:1:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8482;}}}}}s:1:"S";a:2:{s:1:"H";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1035;}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1062;}}}}s:1:"a";a:2:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9;}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:932;}}}s:1:"c";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:356;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:354;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1058;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120087;}}}s:1:"h";a:2:{s:1:"e";a:2:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8756;}}}}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:920;}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8201;}}}}}}}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8764;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8771;}}}}}}s:1:"F";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8773;}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8776;}}}}}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120139;}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8411;}}}}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119983;}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:358;}}}}}}}s:1:"U";a:14:{s:1:"a";a:2:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:218;}s:9:"codepoint";i:218;}}}}s:1:"r";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8607;}s:1:"o";a:1:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10569;}}}}}}}}s:1:"b";a:1:{s:1:"r";a:2:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1038;}}}s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:364;}}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:219;}s:9:"codepoint";i:219;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1059;}}}s:1:"d";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:368;}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120088;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:217;}s:9:"codepoint";i:217;}}}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:362;}}}}}s:1:"n";a:2:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:"r";a:2:{s:1:"B";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:818;}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"c";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9183;}}s:1:"k";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9141;}}}}}}}}s:1:"P";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9181;}}}}}}}}}}}}}}}s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8899;}s:1:"P";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8846;}}}}}}}}}s:1:"o";a:2:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:370;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120140;}}}}s:1:"p";a:8:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8593;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10514;}}}}s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8645;}}}}}}}}}}}}}}}s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8597;}}}}}}}}}}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"b";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10606;}}}}}}}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8869;}s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8613;}}}}}}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8657;}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8661;}}}}}}}}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"r";a:2:{s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8598;}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8599;}}}}}}}}}}}}}}s:1:"s";a:1:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:978;}s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:933;}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:366;}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119984;}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:360;}}}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:220;}s:9:"codepoint";i:220;}}}}s:1:"V";a:9:{s:1:"D";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8875;}}}}}s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10987;}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1042;}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8873;}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10982;}}}}}}s:1:"e";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8897;}}s:1:"r";a:3:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8214;}}}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8214;}s:1:"i";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:4:{s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8739;}}}}s:1:"L";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:124;}}}}}s:1:"S";a:1:{s:1:"e";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10072;}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8768;}}}}}}}}}}}s:1:"y";a:1:{s:1:"T";a:1:{s:1:"h";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8202;}}}}}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120089;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120141;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119985;}}}}s:1:"v";a:1:{s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8874;}}}}}}}s:1:"W";a:5:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:372;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8896;}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120090;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120142;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119986;}}}}}s:1:"X";a:4:{s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120091;}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:926;}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120143;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119987;}}}}}s:1:"Y";a:9:{s:1:"A";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1071;}}}}s:1:"I";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1031;}}}}s:1:"U";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1070;}}}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:221;}s:9:"codepoint";i:221;}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:374;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1067;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120092;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120144;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119988;}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:376;}}}}}s:1:"Z";a:8:{s:1:"H";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1046;}}}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:377;}}}}}}s:1:"c";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:381;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1047;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:379;}}}}s:1:"e";a:2:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"W";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8203;}}}}}}}}}}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:918;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8488;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8484;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119989;}}}}}s:1:"a";a:16:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:225;}s:9:"codepoint";i:225;}}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:259;}}}}}}s:1:"c";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8766;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8767;}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:226;}s:9:"codepoint";i:226;}}}s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:180;}s:9:"codepoint";i:180;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1072;}}}s:1:"e";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:230;}s:9:"codepoint";i:230;}}}}s:1:"f";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8289;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120094;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:224;}s:9:"codepoint";i:224;}}}}}s:1:"l";a:2:{s:1:"e";a:2:{s:1:"f";a:1:{s:1:"s";a:1:{s:1:"y";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8501;}}}}}s:1:"p";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8501;}}}}s:1:"p";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:945;}}}}}s:1:"m";a:2:{s:1:"a";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:257;}}}s:1:"l";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10815;}}}}s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:38;}s:9:"codepoint";i:38;}}s:1:"n";a:2:{s:1:"d";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8743;}s:1:"a";a:1:{s:1:"n";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10837;}}}}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10844;}}s:1:"s";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10840;}}}}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10842;}}}s:1:"g";a:7:{s:1:";";a:1:{s:9:"codepoint";i:8736;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10660;}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8736;}}}s:1:"m";a:1:{s:1:"s";a:1:{s:1:"d";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8737;}s:1:"a";a:8:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10664;}}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10665;}}s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10666;}}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10667;}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10668;}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10669;}}s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10670;}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10671;}}}}}}s:1:"r";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8735;}s:1:"v";a:1:{s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8894;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10653;}}}}}}s:1:"s";a:2:{s:1:"p";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8738;}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8491;}}}s:1:"z";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9084;}}}}}}}s:1:"o";a:2:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:261;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120146;}}}}s:1:"p";a:7:{s:1:";";a:1:{s:9:"codepoint";i:8776;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10864;}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10863;}}}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8778;}}s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8779;}}}s:1:"o";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:39;}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8776;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8778;}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:229;}s:9:"codepoint";i:229;}}}}s:1:"s";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119990;}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:42;}}s:1:"y";a:1:{s:1:"m";a:1:{s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8776;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8781;}}}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:227;}s:9:"codepoint";i:227;}}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:228;}s:9:"codepoint";i:228;}}}s:1:"w";a:2:{s:1:"c";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8755;}}}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10769;}}}}}}s:1:"b";a:16:{s:1:"N";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10989;}}}}s:1:"a";a:2:{s:1:"c";a:1:{s:1:"k";a:4:{s:1:"c";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8780;}}}}}s:1:"e";a:1:{s:1:"p";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1014;}}}}}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8245;}}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8765;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8909;}}}}}}}}s:1:"r";a:2:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8893;}}}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8965;}s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8965;}}}}}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9141;}s:1:"t";a:1:{s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9142;}}}}}}}}s:1:"c";a:2:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8780;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1073;}}}s:1:"d";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8222;}}}}}s:1:"e";a:5:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"u";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8757;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8757;}}}}}}s:1:"m";a:1:{s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10672;}}}}}}s:1:"p";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1014;}}}}s:1:"r";a:1:{s:1:"n";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8492;}}}}}s:1:"t";a:3:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:946;}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8502;}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8812;}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120095;}}}s:1:"i";a:1:{s:1:"g";a:7:{s:1:"c";a:3:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8898;}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9711;}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8899;}}}}s:1:"o";a:3:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10752;}}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10753;}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10754;}}}}}}}s:1:"s";a:2:{s:1:"q";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10758;}}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9733;}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:2:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9661;}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9651;}}}}}}}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10756;}}}}}}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8897;}}}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8896;}}}}}}}}s:1:"k";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10509;}}}}}}s:1:"l";a:3:{s:1:"a";a:2:{s:1:"c";a:1:{s:1:"k";a:3:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"z";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10731;}}}}}}}}s:1:"s";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9642;}}}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:4:{s:1:";";a:1:{s:9:"codepoint";i:9652;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9662;}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9666;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9656;}}}}}}}}}}}}}}}}s:1:"n";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9251;}}}}s:1:"k";a:2:{i:1;a:2:{i:2;a:1:{s:1:";";a:1:{s:9:"codepoint";i:9618;}}i:4;a:1:{s:1:";";a:1:{s:9:"codepoint";i:9617;}}}i:3;a:1:{i:4;a:1:{s:1:";";a:1:{s:9:"codepoint";i:9619;}}}}s:1:"o";a:1:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9608;}}}}}s:1:"n";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8976;}}}}s:1:"o";a:4:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120147;}}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8869;}s:1:"t";a:1:{s:1:"o";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8869;}}}}}s:1:"w";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8904;}}}}}s:1:"x";a:12:{s:1:"D";a:4:{s:1:"L";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9559;}}s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9556;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9558;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9555;}}}s:1:"H";a:5:{s:1:";";a:1:{s:9:"codepoint";i:9552;}s:1:"D";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9574;}}s:1:"U";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9577;}}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9572;}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9575;}}}s:1:"U";a:4:{s:1:"L";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9565;}}s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9562;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9564;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9561;}}}s:1:"V";a:7:{s:1:";";a:1:{s:9:"codepoint";i:9553;}s:1:"H";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9580;}}s:1:"L";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9571;}}s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9568;}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9579;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9570;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9567;}}}s:1:"b";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10697;}}}}s:1:"d";a:4:{s:1:"L";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9557;}}s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9554;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9488;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9484;}}}s:1:"h";a:5:{s:1:";";a:1:{s:9:"codepoint";i:9472;}s:1:"D";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9573;}}s:1:"U";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9576;}}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9516;}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9524;}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8863;}}}}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8862;}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8864;}}}}}}s:1:"u";a:4:{s:1:"L";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9563;}}s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9560;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9496;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9492;}}}s:1:"v";a:7:{s:1:";";a:1:{s:9:"codepoint";i:9474;}s:1:"H";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9578;}}s:1:"L";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9569;}}s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9566;}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9532;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9508;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9500;}}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8245;}}}}}}s:1:"r";a:2:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:728;}}}}s:1:"v";a:1:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:166;}s:9:"codepoint";i:166;}}}}}s:1:"s";a:4:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119991;}}}s:1:"e";a:1:{s:1:"m";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8271;}}}}s:1:"i";a:1:{s:1:"m";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8765;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8909;}}}}s:1:"o";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:92;}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10693;}}}}}s:1:"u";a:2:{s:1:"l";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8226;}s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8226;}}}}}s:1:"m";a:1:{s:1:"p";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8782;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10926;}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8783;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8783;}}}}}}}s:1:"c";a:15:{s:1:"a";a:3:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:263;}}}}}s:1:"p";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8745;}s:1:"a";a:1:{s:1:"n";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10820;}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10825;}}}}}}s:1:"c";a:2:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10827;}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10823;}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10816;}}}}}s:1:"r";a:2:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8257;}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:711;}}}}}s:1:"c";a:4:{s:1:"a";a:2:{s:1:"p";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10829;}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:269;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:231;}s:9:"codepoint";i:231;}}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:265;}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10828;}s:1:"s";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10832;}}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:267;}}}}s:1:"e";a:3:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:184;}s:9:"codepoint";i:184;}}}s:1:"m";a:1:{s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10674;}}}}}}s:1:"n";a:1:{s:1:"t";a:3:{s:1:";";a:1:{s:9:"codepoint";i:162;}s:9:"codepoint";i:162;s:1:"e";a:1:{s:1:"r";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:183;}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120096;}}}s:1:"h";a:3:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1095;}}}s:1:"e";a:1:{s:1:"c";a:1:{s:1:"k";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10003;}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10003;}}}}}}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:967;}}}s:1:"i";a:1:{s:1:"r";a:7:{s:1:";";a:1:{s:9:"codepoint";i:9675;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10691;}}s:1:"c";a:3:{s:1:";";a:1:{s:9:"codepoint";i:710;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8791;}}}s:1:"l";a:1:{s:1:"e";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8634;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8635;}}}}}}}}}}}s:1:"d";a:5:{s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:174;}}s:1:"S";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9416;}}s:1:"a";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8859;}}}}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8858;}}}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8861;}}}}}}}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8791;}}s:1:"f";a:1:{s:1:"n";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10768;}}}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10991;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10690;}}}}}}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9827;}s:1:"u";a:1:{s:1:"i";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9827;}}}}}}}}s:1:"o";a:4:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:58;}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8788;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8788;}}}}}}s:1:"m";a:2:{s:1:"m";a:1:{s:1:"a";a:2:{s:1:";";a:1:{s:9:"codepoint";i:44;}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:64;}}}}s:1:"p";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8705;}s:1:"f";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8728;}}}s:1:"l";a:1:{s:1:"e";a:2:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8705;}}}}}s:1:"x";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8450;}}}}}}}}s:1:"n";a:2:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8773;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10861;}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8750;}}}}}s:1:"p";a:3:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120148;}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8720;}}}}s:1:"y";a:3:{s:1:";";a:1:{s:9:"codepoint";i:169;}s:9:"codepoint";i:169;s:1:"s";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8471;}}}}}}s:1:"r";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8629;}}}}s:1:"o";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10007;}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119992;}}}s:1:"u";a:2:{s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10959;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10961;}}}s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10960;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10962;}}}}}s:1:"t";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8943;}}}}}s:1:"u";a:7:{s:1:"d";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:2:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10552;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10549;}}}}}}s:1:"e";a:2:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8926;}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8927;}}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8630;}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10557;}}}}}}s:1:"p";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8746;}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10824;}}}}}}s:1:"c";a:2:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10822;}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10826;}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8845;}}}}s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10821;}}}}s:1:"r";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8631;}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10556;}}}}}s:1:"l";a:1:{s:1:"y";a:3:{s:1:"e";a:1:{s:1:"q";a:2:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8926;}}}}}s:1:"s";a:1:{s:1:"u";a:1:{s:1:"c";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8927;}}}}}}}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8910;}}}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8911;}}}}}}}}s:1:"r";a:1:{s:1:"e";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:164;}s:9:"codepoint";i:164;}}}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8630;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8631;}}}}}}}}}}}}}}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8910;}}}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8911;}}}}}s:1:"w";a:2:{s:1:"c";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8754;}}}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8753;}}}}}s:1:"y";a:1:{s:1:"l";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9005;}}}}}}}s:1:"d";a:19:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8659;}}}}s:1:"H";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10597;}}}}s:1:"a";a:4:{s:1:"g";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8224;}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8504;}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8595;}}}s:1:"s";a:1:{s:1:"h";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8208;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8867;}}}}}s:1:"b";a:2:{s:1:"k";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10511;}}}}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:733;}}}}}s:1:"c";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:271;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1076;}}}s:1:"d";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8518;}s:1:"a";a:2:{s:1:"g";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8225;}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8650;}}}}s:1:"o";a:1:{s:1:"t";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10871;}}}}}}}s:1:"e";a:3:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:176;}s:9:"codepoint";i:176;}s:1:"l";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:948;}}}}s:1:"m";a:1:{s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10673;}}}}}}}s:1:"f";a:2:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10623;}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120097;}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8643;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8642;}}}}}s:1:"i";a:5:{s:1:"a";a:1:{s:1:"m";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8900;}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"d";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8900;}s:1:"s";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9830;}}}}}}}}s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9830;}}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:168;}}s:1:"g";a:1:{s:1:"a";a:1:{s:1:"m";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:989;}}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8946;}}}}s:1:"v";a:3:{s:1:";";a:1:{s:9:"codepoint";i:247;}s:1:"i";a:1:{s:1:"d";a:1:{s:1:"e";a:3:{s:1:";";a:1:{s:9:"codepoint";i:247;}s:9:"codepoint";i:247;s:1:"o";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8903;}}}}}}}}}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8903;}}}}}}s:1:"j";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1106;}}}}s:1:"l";a:1:{s:1:"c";a:2:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8990;}}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8973;}}}}}}s:1:"o";a:5:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:36;}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120149;}}}s:1:"t";a:5:{s:1:";";a:1:{s:9:"codepoint";i:729;}s:1:"e";a:1:{s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8784;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8785;}}}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8760;}}}}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8724;}}}}}s:1:"s";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8865;}}}}}}}}s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8966;}}}}}}}}}}}}}s:1:"w";a:1:{s:1:"n";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8595;}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8650;}}}}}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8643;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8642;}}}}}}}}}}}}}}}}s:1:"r";a:2:{s:1:"b";a:1:{s:1:"k";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10512;}}}}}}}s:1:"c";a:2:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8991;}}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8972;}}}}}}s:1:"s";a:3:{s:1:"c";a:2:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119993;}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1109;}}}s:1:"o";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10742;}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:273;}}}}}}s:1:"t";a:2:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8945;}}}}s:1:"r";a:1:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9663;}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9662;}}}}}s:1:"u";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8693;}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10607;}}}}}s:1:"w";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10662;}}}}}}}s:1:"z";a:2:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1119;}}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10239;}}}}}}}}}s:1:"e";a:18:{s:1:"D";a:2:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10871;}}}}s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8785;}}}}s:1:"a";a:2:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:233;}s:9:"codepoint";i:233;}}}}s:1:"s";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10862;}}}}}}s:1:"c";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:283;}}}}}s:1:"i";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8790;}s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:234;}s:9:"codepoint";i:234;}}}s:1:"o";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8789;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1101;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:279;}}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8519;}}s:1:"f";a:2:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8786;}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120098;}}}s:1:"g";a:3:{s:1:";";a:1:{s:9:"codepoint";i:10906;}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:232;}s:9:"codepoint";i:232;}}}}s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10902;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10904;}}}}}}s:1:"l";a:4:{s:1:";";a:1:{s:9:"codepoint";i:10905;}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9191;}}}}}}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8467;}}s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10901;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10903;}}}}}}s:1:"m";a:3:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:275;}}}}s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8709;}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8709;}}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8709;}}}}}s:1:"s";a:1:{s:1:"p";a:2:{i:1;a:2:{i:3;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8196;}}i:4;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8197;}}}s:1:";";a:1:{s:9:"codepoint";i:8195;}}}}s:1:"n";a:2:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:331;}}s:1:"s";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8194;}}}}s:1:"o";a:2:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:281;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120150;}}}}s:1:"p";a:3:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8917;}s:1:"s";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10723;}}}}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10865;}}}}s:1:"s";a:1:{s:1:"i";a:3:{s:1:";";a:1:{s:9:"codepoint";i:1013;}s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:949;}}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:949;}}}}}s:1:"q";a:4:{s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8790;}}}}s:1:"o";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8789;}}}}}}s:1:"s";a:2:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8770;}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:2:{s:1:"g";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10902;}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10901;}}}}}}}}}}s:1:"u";a:3:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:61;}}}}s:1:"e";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8799;}}}}s:1:"i";a:1:{s:1:"v";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8801;}s:1:"D";a:1:{s:1:"D";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10872;}}}}}}s:1:"v";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10725;}}}}}}}}s:1:"r";a:2:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8787;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10609;}}}}}s:1:"s";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8495;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8784;}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8770;}}}}s:1:"t";a:2:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:951;}}s:1:"h";a:2:{s:1:";";a:1:{s:9:"codepoint";i:240;}s:9:"codepoint";i:240;}}s:1:"u";a:2:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:235;}s:9:"codepoint";i:235;}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8364;}}}}s:1:"x";a:3:{s:1:"c";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:33;}}}s:1:"i";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8707;}}}}s:1:"p";a:2:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8496;}}}}}}}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8519;}}}}}}}}}}}}}s:1:"f";a:11:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8786;}}}}}}}}}}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1092;}}}s:1:"e";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9792;}}}}}}s:1:"f";a:3:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:64259;}}}}}s:1:"l";a:2:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:64256;}}}s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:64260;}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120099;}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:64257;}}}}}s:1:"l";a:3:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9837;}}}s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:64258;}}}}s:1:"t";a:1:{s:1:"n";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9649;}}}}}s:1:"n";a:1:{s:1:"o";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:402;}}}}s:1:"o";a:2:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120151;}}}s:1:"r";a:2:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8704;}}}}s:1:"k";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8916;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10969;}}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10765;}}}}}}}}s:1:"r";a:2:{s:1:"a";a:2:{s:1:"c";a:6:{i:1;a:6:{i:2;a:2:{s:1:";";a:1:{s:9:"codepoint";i:189;}s:9:"codepoint";i:189;}i:3;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8531;}}i:4;a:2:{s:1:";";a:1:{s:9:"codepoint";i:188;}s:9:"codepoint";i:188;}i:5;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8533;}}i:6;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8537;}}i:8;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8539;}}}i:2;a:2:{i:3;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8532;}}i:5;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8534;}}}i:3;a:3:{i:4;a:2:{s:1:";";a:1:{s:9:"codepoint";i:190;}s:9:"codepoint";i:190;}i:5;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8535;}}i:8;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8540;}}}i:4;a:1:{i:5;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8536;}}}i:5;a:2:{i:6;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8538;}}i:8;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8541;}}}i:7;a:1:{i:8;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8542;}}}}s:1:"s";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8260;}}}}s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8994;}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119995;}}}}}s:1:"g";a:16:{s:1:"E";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8807;}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10892;}}}s:1:"a";a:3:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:501;}}}}}s:1:"m";a:1:{s:1:"m";a:1:{s:1:"a";a:2:{s:1:";";a:1:{s:9:"codepoint";i:947;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:989;}}}}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10886;}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:287;}}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:285;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1075;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:289;}}}}s:1:"e";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8805;}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8923;}}s:1:"q";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8805;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8807;}}s:1:"s";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10878;}}}}}}}s:1:"s";a:4:{s:1:";";a:1:{s:9:"codepoint";i:10878;}s:1:"c";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10921;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10880;}s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10882;}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10884;}}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10900;}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120100;}}}s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8811;}s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8921;}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8503;}}}}}s:1:"j";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1107;}}}}s:1:"l";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8823;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10898;}}s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10917;}}s:1:"j";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10916;}}}s:1:"n";a:4:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8809;}}s:1:"a";a:1:{s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10890;}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10890;}}}}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10888;}s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10888;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8809;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8935;}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120152;}}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:96;}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8458;}}}s:1:"i";a:1:{s:1:"m";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8819;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10894;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10896;}}}}}s:1:"t";a:7:{s:1:";";a:1:{s:9:"codepoint";i:62;}s:9:"codepoint";i:62;s:1:"c";a:2:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10919;}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10874;}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8919;}}}}s:1:"l";a:1:{s:1:"P";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10645;}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10876;}}}}}}s:1:"r";a:5:{s:1:"a";a:2:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10886;}}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10616;}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8919;}}}}s:1:"e";a:1:{s:1:"q";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8923;}}}}}s:1:"q";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10892;}}}}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8823;}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8819;}}}}}}}s:1:"h";a:10:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8660;}}}}s:1:"a";a:4:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8202;}}}}}s:1:"l";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:189;}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8459;}}}}}s:1:"r";a:2:{s:1:"d";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1098;}}}}s:1:"r";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8596;}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10568;}}}}s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8621;}}}}}s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8463;}}}}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:293;}}}}}s:1:"e";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9829;}s:1:"u";a:1:{s:1:"i";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9829;}}}}}}}}s:1:"l";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8230;}}}}}s:1:"r";a:1:{s:1:"c";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8889;}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120101;}}}s:1:"k";a:1:{s:1:"s";a:2:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10533;}}}}}}s:1:"w";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10534;}}}}}}}}s:1:"o";a:5:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8703;}}}}s:1:"m";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8763;}}}}}s:1:"o";a:1:{s:1:"k";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8617;}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8618;}}}}}}}}}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120153;}}}s:1:"r";a:1:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8213;}}}}}}s:1:"s";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119997;}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8463;}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:295;}}}}}}s:1:"y";a:2:{s:1:"b";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8259;}}}}}s:1:"p";a:1:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8208;}}}}}}}s:1:"i";a:15:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:237;}s:9:"codepoint";i:237;}}}}}s:1:"c";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8291;}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:238;}s:9:"codepoint";i:238;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1080;}}}s:1:"e";a:2:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1077;}}}s:1:"x";a:1:{s:1:"c";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:161;}s:9:"codepoint";i:161;}}}}s:1:"f";a:2:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8660;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120102;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:236;}s:9:"codepoint";i:236;}}}}}s:1:"i";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8520;}s:1:"i";a:2:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10764;}}}}s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8749;}}}}s:1:"n";a:1:{s:1:"f";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10716;}}}}}s:1:"o";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8489;}}}}}s:1:"j";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:307;}}}}}s:1:"m";a:3:{s:1:"a";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:299;}}}s:1:"g";a:3:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8465;}}s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8464;}}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8465;}}}}}}s:1:"t";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:305;}}}}s:1:"o";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8887;}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:437;}}}}}s:1:"n";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8712;}s:1:"c";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8453;}}}}}s:1:"f";a:1:{s:1:"i";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8734;}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10717;}}}}}}}s:1:"o";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:305;}}}}}s:1:"t";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8747;}s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8890;}}}}s:1:"e";a:2:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8484;}}}}}s:1:"r";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8890;}}}}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10775;}}}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10812;}}}}}}}s:1:"o";a:4:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1105;}}}s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:303;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120154;}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:953;}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10812;}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:191;}s:9:"codepoint";i:191;}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119998;}}}s:1:"i";a:1:{s:1:"n";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8712;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8953;}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8949;}}}}s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8948;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8947;}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8712;}}}}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8290;}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:297;}}}}}}s:1:"u";a:2:{s:1:"k";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1110;}}}}s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:239;}s:9:"codepoint";i:239;}}}}s:1:"j";a:6:{s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:309;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1081;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120103;}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:567;}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120155;}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119999;}}}s:1:"e";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1112;}}}}}}s:1:"u";a:1:{s:1:"k";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1108;}}}}}}s:1:"k";a:8:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"a";a:2:{s:1:";";a:1:{s:9:"codepoint";i:954;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1008;}}}}}}s:1:"c";a:2:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:311;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1082;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120104;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:312;}}}}}}s:1:"h";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1093;}}}}s:1:"j";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1116;}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120156;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120000;}}}}}s:1:"l";a:22:{s:1:"A";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8666;}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8656;}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10523;}}}}}}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10510;}}}}}s:1:"E";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8806;}s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10891;}}}s:1:"H";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10594;}}}}s:1:"a";a:9:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:314;}}}}}s:1:"e";a:1:{s:1:"m";a:1:{s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10676;}}}}}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8466;}}}}}s:1:"m";a:1:{s:1:"b";a:1:{s:1:"d";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:955;}}}}}s:1:"n";a:1:{s:1:"g";a:3:{s:1:";";a:1:{s:9:"codepoint";i:10216;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10641;}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10216;}}}}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10885;}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:171;}s:9:"codepoint";i:171;}}}s:1:"r";a:1:{s:1:"r";a:8:{s:1:";";a:1:{s:9:"codepoint";i:8592;}s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8676;}s:1:"f";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10527;}}}}s:1:"f";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10525;}}}s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8617;}}}s:1:"l";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8619;}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10553;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10611;}}}}s:1:"t";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8610;}}}}}s:1:"t";a:3:{s:1:";";a:1:{s:9:"codepoint";i:10923;}s:1:"a";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10521;}}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10925;}}}}s:1:"b";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10508;}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10098;}}}}s:1:"r";a:2:{s:1:"a";a:1:{s:1:"c";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:123;}}s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:91;}}}}s:1:"k";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10635;}}s:1:"s";a:1:{s:1:"l";a:2:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10639;}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10637;}}}}}}}s:1:"c";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:318;}}}}}s:1:"e";a:2:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:316;}}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8968;}}}}s:1:"u";a:1:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:123;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1083;}}}s:1:"d";a:4:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10550;}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8220;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8222;}}}}}s:1:"r";a:2:{s:1:"d";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10599;}}}}}s:1:"u";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10571;}}}}}}}s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8626;}}}}s:1:"e";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8804;}s:1:"f";a:1:{s:1:"t";a:5:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8592;}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8610;}}}}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8637;}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8636;}}}}}}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8647;}}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8596;}s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8646;}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8651;}}}}}}}}}s:1:"s";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8621;}}}}}}}}}}}}}}}}s:1:"t";a:1:{s:1:"h";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8907;}}}}}}}}}}}}}s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8922;}}s:1:"q";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8804;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8806;}}s:1:"s";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10877;}}}}}}}s:1:"s";a:5:{s:1:";";a:1:{s:9:"codepoint";i:10877;}s:1:"c";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10920;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10879;}s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10881;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10883;}}}}}}s:1:"g";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10899;}}}}s:1:"s";a:5:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10885;}}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8918;}}}}s:1:"e";a:1:{s:1:"q";a:2:{s:1:"g";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8922;}}}}s:1:"q";a:1:{s:1:"g";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10891;}}}}}}}s:1:"g";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8822;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8818;}}}}}}}s:1:"f";a:3:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10620;}}}}}s:1:"l";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8970;}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120105;}}}s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8822;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10897;}}}s:1:"h";a:2:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8637;}}s:1:"u";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8636;}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10602;}}}}}s:1:"b";a:1:{s:1:"l";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9604;}}}}}s:1:"j";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1113;}}}}s:1:"l";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8810;}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8647;}}}}s:1:"c";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8990;}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10603;}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9722;}}}}}s:1:"m";a:2:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:320;}}}}}s:1:"o";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9136;}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9136;}}}}}}}}}}s:1:"n";a:4:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8808;}}s:1:"a";a:1:{s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10889;}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10889;}}}}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10887;}s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10887;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8808;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8934;}}}}}s:1:"o";a:8:{s:1:"a";a:2:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10220;}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8701;}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10214;}}}}s:1:"n";a:1:{s:1:"g";a:3:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10229;}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10231;}}}}}}}}}}}}}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10236;}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10230;}}}}}}}}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8619;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8620;}}}}}}}}}}}}}s:1:"p";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10629;}}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120157;}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10797;}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10804;}}}}}}s:1:"w";a:2:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8727;}}}}s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:95;}}}}}s:1:"z";a:3:{s:1:";";a:1:{s:9:"codepoint";i:9674;}s:1:"e";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9674;}}}}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10731;}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:40;}s:1:"l";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10643;}}}}}}s:1:"r";a:5:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8646;}}}}s:1:"c";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8991;}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8651;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10605;}}}}}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8206;}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8895;}}}}}s:1:"s";a:6:{s:1:"a";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8249;}}}}}s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120001;}}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8624;}}s:1:"i";a:1:{s:1:"m";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8818;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10893;}}s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10895;}}}}s:1:"q";a:2:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:91;}}s:1:"u";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8216;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8218;}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:322;}}}}}}s:1:"t";a:9:{s:1:";";a:1:{s:9:"codepoint";i:60;}s:9:"codepoint";i:60;s:1:"c";a:2:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10918;}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10873;}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8918;}}}}s:1:"h";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8907;}}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8905;}}}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10614;}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10875;}}}}}}s:1:"r";a:2:{s:1:"P";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10646;}}}}s:1:"i";a:3:{s:1:";";a:1:{s:9:"codepoint";i:9667;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8884;}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9666;}}}}}s:1:"u";a:1:{s:1:"r";a:2:{s:1:"d";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10570;}}}}}}s:1:"u";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10598;}}}}}}}}s:1:"m";a:14:{s:1:"D";a:1:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8762;}}}}}s:1:"a";a:4:{s:1:"c";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:175;}s:9:"codepoint";i:175;}}s:1:"l";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9794;}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10016;}s:1:"e";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10016;}}}}}}s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8614;}s:1:"s";a:1:{s:1:"t";a:1:{s:1:"o";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8614;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8615;}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8612;}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8613;}}}}}}}s:1:"r";a:1:{s:1:"k";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9646;}}}}}}s:1:"c";a:2:{s:1:"o";a:1:{s:1:"m";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10793;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1084;}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8212;}}}}}s:1:"e";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8737;}}}}}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120106;}}}s:1:"h";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8487;}}}s:1:"i";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:181;}s:9:"codepoint";i:181;}}}s:1:"d";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8739;}s:1:"a";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:42;}}}}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10992;}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:183;}s:9:"codepoint";i:183;}}}}s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8722;}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8863;}}s:1:"d";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8760;}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10794;}}}}}}}s:1:"l";a:2:{s:1:"c";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10971;}}}s:1:"d";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8230;}}}}s:1:"n";a:1:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8723;}}}}}}s:1:"o";a:2:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8871;}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120158;}}}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8723;}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120002;}}}s:1:"t";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8766;}}}}}}s:1:"u";a:3:{s:1:";";a:1:{s:9:"codepoint";i:956;}s:1:"l";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8888;}}}}}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8888;}}}}}}s:1:"n";a:23:{s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8653;}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8654;}}}}}}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8655;}}}}}}}}}}}s:1:"V";a:2:{s:1:"D";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8879;}}}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8878;}}}}}}s:1:"a";a:4:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8711;}}}}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:324;}}}}}s:1:"p";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8777;}s:1:"o";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:329;}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8777;}}}}}}s:1:"t";a:1:{s:1:"u";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9838;}s:1:"a";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9838;}s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8469;}}}}}}}}s:1:"b";a:1:{s:1:"s";a:1:{s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:160;}s:9:"codepoint";i:160;}}}s:1:"c";a:5:{s:1:"a";a:2:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10819;}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:328;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:326;}}}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8775;}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10818;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1085;}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8211;}}}}}s:1:"e";a:6:{s:1:";";a:1:{s:9:"codepoint";i:8800;}s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8663;}}}}s:1:"a";a:1:{s:1:"r";a:2:{s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10532;}}}s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8599;}s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8599;}}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8802;}}}}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10536;}}}}}s:1:"x";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8708;}s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8708;}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120107;}}}s:1:"g";a:3:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8817;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8817;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8821;}}}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8815;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8815;}}}}s:1:"h";a:3:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8654;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8622;}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10994;}}}}}s:1:"i";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8715;}s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8956;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8954;}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8715;}}}s:1:"j";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1114;}}}}s:1:"l";a:6:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8653;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8602;}}}}s:1:"d";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8229;}}}s:1:"e";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8816;}s:1:"f";a:1:{s:1:"t";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8602;}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8622;}}}}}}}}}}}}}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8816;}}s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8814;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8820;}}}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8814;}s:1:"r";a:1:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8938;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8940;}}}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8740;}}}}s:1:"o";a:2:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120159;}}}s:1:"t";a:4:{s:1:";";a:1:{s:9:"codepoint";i:172;}s:9:"codepoint";i:172;s:1:"i";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8713;}s:1:"v";a:3:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8713;}}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8951;}}s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8950;}}}}}s:1:"n";a:1:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8716;}s:1:"v";a:3:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8716;}}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8958;}}s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8957;}}}}}}}s:1:"p";a:3:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8742;}s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8742;}}}}}}}}s:1:"o";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10772;}}}}}}s:1:"r";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8832;}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8928;}}}}s:1:"e";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8832;}}}}}s:1:"r";a:4:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8655;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8603;}}}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8603;}}}}}}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8939;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8941;}}}}}}s:1:"s";a:7:{s:1:"c";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8833;}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8929;}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120003;}}}s:1:"h";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"t";a:2:{s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8740;}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8742;}}}}}}}}}}}}}s:1:"i";a:1:{s:1:"m";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8769;}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8772;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8772;}}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8740;}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8742;}}}}s:1:"q";a:1:{s:1:"s";a:1:{s:1:"u";a:2:{s:1:"b";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8930;}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8931;}}}}}}s:1:"u";a:3:{s:1:"b";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8836;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8840;}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8840;}}}}}}}s:1:"c";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8833;}}}s:1:"p";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8837;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8841;}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8841;}}}}}}}}}s:1:"t";a:4:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8825;}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:241;}s:9:"codepoint";i:241;}}}}s:1:"l";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8824;}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8938;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8940;}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8939;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8941;}}}}}}}}}}}}}}}}s:1:"u";a:2:{s:1:";";a:1:{s:9:"codepoint";i:957;}s:1:"m";a:3:{s:1:";";a:1:{s:9:"codepoint";i:35;}s:1:"e";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8470;}}}}s:1:"s";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8199;}}}}}s:1:"v";a:6:{s:1:"D";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8877;}}}}}s:1:"H";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10500;}}}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8876;}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"f";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10718;}}}}}}s:1:"l";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10498;}}}}}s:1:"r";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10499;}}}}}}s:1:"w";a:3:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8662;}}}}s:1:"a";a:1:{s:1:"r";a:2:{s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10531;}}}s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8598;}s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8598;}}}}}}s:1:"n";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10535;}}}}}}}s:1:"o";a:18:{s:1:"S";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9416;}}s:1:"a";a:2:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:243;}s:9:"codepoint";i:243;}}}}s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8859;}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8858;}s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:244;}s:9:"codepoint";i:244;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1086;}}}s:1:"d";a:5:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8861;}}}}s:1:"b";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:337;}}}}}s:1:"i";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10808;}}}s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8857;}}}s:1:"s";a:1:{s:1:"o";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10684;}}}}}}s:1:"e";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:339;}}}}}s:1:"f";a:2:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10687;}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120108;}}}s:1:"g";a:3:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:731;}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:242;}s:9:"codepoint";i:242;}}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10689;}}}s:1:"h";a:2:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10677;}}}}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8486;}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8750;}}}}s:1:"l";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8634;}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10686;}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10683;}}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8254;}}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10688;}}}s:1:"m";a:3:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:333;}}}}s:1:"e";a:1:{s:1:"g";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:969;}}}}s:1:"i";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:959;}}}}}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10678;}}s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8854;}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120160;}}}}s:1:"p";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10679;}}}s:1:"e";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10681;}}}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8853;}}}}}s:1:"r";a:7:{s:1:";";a:1:{s:9:"codepoint";i:8744;}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8635;}}}}s:1:"d";a:4:{s:1:";";a:1:{s:9:"codepoint";i:10845;}s:1:"e";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8500;}s:1:"o";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8500;}}}}}s:1:"f";a:2:{s:1:";";a:1:{s:9:"codepoint";i:170;}s:9:"codepoint";i:170;}s:1:"m";a:2:{s:1:";";a:1:{s:9:"codepoint";i:186;}s:9:"codepoint";i:186;}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8886;}}}}}s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10838;}}}s:1:"s";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10839;}}}}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10843;}}}s:1:"s";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8500;}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:2:{s:1:";";a:1:{s:9:"codepoint";i:248;}s:9:"codepoint";i:248;}}}}s:1:"o";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8856;}}}}s:1:"t";a:1:{s:1:"i";a:2:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:245;}s:9:"codepoint";i:245;}}}s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8855;}s:1:"a";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10806;}}}}}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:246;}s:9:"codepoint";i:246;}}}s:1:"v";a:1:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9021;}}}}}}s:1:"p";a:12:{s:1:"a";a:1:{s:1:"r";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8741;}s:1:"a";a:3:{s:1:";";a:1:{s:9:"codepoint";i:182;}s:9:"codepoint";i:182;s:1:"l";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8741;}}}}}}s:1:"s";a:2:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10995;}}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:11005;}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8706;}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1087;}}}s:1:"e";a:1:{s:1:"r";a:5:{s:1:"c";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:37;}}}}s:1:"i";a:1:{s:1:"o";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:46;}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8240;}}}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8869;}}s:1:"t";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8241;}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120109;}}}s:1:"h";a:3:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:966;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:966;}}}s:1:"m";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8499;}}}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9742;}}}}}s:1:"i";a:3:{s:1:";";a:1:{s:9:"codepoint";i:960;}s:1:"t";a:1:{s:1:"c";a:1:{s:1:"h";a:1:{s:1:"f";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8916;}}}}}}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:982;}}}s:1:"l";a:2:{s:1:"a";a:1:{s:1:"n";a:2:{s:1:"c";a:1:{s:1:"k";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8463;}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8462;}}}}s:1:"k";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8463;}}}}}s:1:"u";a:1:{s:1:"s";a:9:{s:1:";";a:1:{s:9:"codepoint";i:43;}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10787;}}}}}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8862;}}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10786;}}}}s:1:"d";a:2:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8724;}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10789;}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10866;}}s:1:"m";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:177;}s:9:"codepoint";i:177;}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10790;}}}}s:1:"t";a:1:{s:1:"w";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10791;}}}}}}}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:177;}}s:1:"o";a:3:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10773;}}}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120161;}}}s:1:"u";a:1:{s:1:"n";a:1:{s:1:"d";a:2:{s:1:";";a:1:{s:9:"codepoint";i:163;}s:9:"codepoint";i:163;}}}}s:1:"r";a:10:{s:1:";";a:1:{s:9:"codepoint";i:8826;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10931;}}s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10935;}}}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8828;}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10927;}s:1:"c";a:6:{s:1:";";a:1:{s:9:"codepoint";i:8826;}s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10935;}}}}}}}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"l";a:1:{s:1:"y";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8828;}}}}}}}}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10927;}}}s:1:"n";a:3:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10937;}}}}}}}s:1:"e";a:1:{s:1:"q";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10933;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8936;}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8830;}}}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8242;}s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8473;}}}}}s:1:"n";a:3:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10933;}}s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10937;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8936;}}}}}s:1:"o";a:3:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8719;}}s:1:"f";a:3:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9006;}}}}}s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8978;}}}}}s:1:"s";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8979;}}}}}}s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8733;}s:1:"t";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8733;}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8830;}}}}s:1:"u";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8880;}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120005;}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:968;}}}s:1:"u";a:1:{s:1:"n";a:1:{s:1:"c";a:1:{s:1:"s";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8200;}}}}}}}s:1:"q";a:6:{s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120110;}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10764;}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120162;}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8279;}}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120006;}}}}s:1:"u";a:3:{s:1:"a";a:1:{s:1:"t";a:2:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"n";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8461;}}}}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10774;}}}}}}s:1:"e";a:1:{s:1:"s";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:63;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8799;}}}}}}s:1:"o";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:34;}s:9:"codepoint";i:34;}}}}s:1:"r";a:21:{s:1:"A";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8667;}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8658;}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10524;}}}}}}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10511;}}}}}s:1:"H";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10596;}}}}s:1:"a";a:7:{s:1:"c";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10714;}}s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:341;}}}}}s:1:"d";a:1:{s:1:"i";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8730;}}}}s:1:"e";a:1:{s:1:"m";a:1:{s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10675;}}}}}}}s:1:"n";a:1:{s:1:"g";a:4:{s:1:";";a:1:{s:9:"codepoint";i:10217;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10642;}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10661;}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10217;}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:187;}s:9:"codepoint";i:187;}}}s:1:"r";a:1:{s:1:"r";a:11:{s:1:";";a:1:{s:9:"codepoint";i:8594;}s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10613;}}}s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8677;}s:1:"f";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10528;}}}}s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10547;}}s:1:"f";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10526;}}}s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8618;}}}s:1:"l";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8620;}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10565;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10612;}}}}s:1:"t";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8611;}}}s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8605;}}}}s:1:"t";a:2:{s:1:"a";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10522;}}}}s:1:"i";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8758;}s:1:"n";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8474;}}}}}}}}}s:1:"b";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10509;}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10099;}}}}s:1:"r";a:2:{s:1:"a";a:1:{s:1:"c";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:125;}}s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:93;}}}}s:1:"k";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10636;}}s:1:"s";a:1:{s:1:"l";a:2:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10638;}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10640;}}}}}}}s:1:"c";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:345;}}}}}s:1:"e";a:2:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:343;}}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8969;}}}}s:1:"u";a:1:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:125;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1088;}}}s:1:"d";a:4:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10551;}}}s:1:"l";a:1:{s:1:"d";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10601;}}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8221;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8221;}}}}}s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8627;}}}}s:1:"e";a:3:{s:1:"a";a:1:{s:1:"l";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8476;}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8475;}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8476;}}}}}s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8477;}}}}s:1:"c";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9645;}}}s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:174;}s:9:"codepoint";i:174;}}s:1:"f";a:3:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10621;}}}}}s:1:"l";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8971;}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120111;}}}s:1:"h";a:2:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8641;}}s:1:"u";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8640;}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10604;}}}}}s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:961;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1009;}}}}s:1:"i";a:3:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:6:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8594;}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8611;}}}}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8641;}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8640;}}}}}}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8644;}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8652;}}}}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8649;}}}}}}}}}}}}s:1:"s";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8605;}}}}}}}}}}}s:1:"t";a:1:{s:1:"h";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8908;}}}}}}}}}}}}}}s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:730;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8787;}}}}}}}}}}}}s:1:"l";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8644;}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8652;}}}}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8207;}}}s:1:"m";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9137;}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9137;}}}}}}}}}}s:1:"n";a:1:{s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10990;}}}}}s:1:"o";a:4:{s:1:"a";a:2:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10221;}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8702;}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10215;}}}}s:1:"p";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10630;}}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120163;}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10798;}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10805;}}}}}}}s:1:"p";a:2:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:41;}s:1:"g";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10644;}}}}}s:1:"p";a:1:{s:1:"o";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10770;}}}}}}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8649;}}}}}s:1:"s";a:4:{s:1:"a";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8250;}}}}}s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120007;}}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8625;}}s:1:"q";a:2:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:93;}}s:1:"u";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8217;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8217;}}}}}}s:1:"t";a:3:{s:1:"h";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8908;}}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8906;}}}}}s:1:"r";a:1:{s:1:"i";a:4:{s:1:";";a:1:{s:9:"codepoint";i:9657;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8885;}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9656;}}s:1:"l";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10702;}}}}}}}}s:1:"u";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10600;}}}}}}}s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8478;}}}s:1:"s";a:19:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:347;}}}}}}s:1:"b";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8218;}}}}}s:1:"c";a:10:{s:1:";";a:1:{s:9:"codepoint";i:8827;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10932;}}s:1:"a";a:2:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10936;}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:353;}}}}}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8829;}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10928;}s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:351;}}}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:349;}}}}s:1:"n";a:3:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10934;}}s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10938;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8937;}}}}}s:1:"p";a:1:{s:1:"o";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10771;}}}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8831;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1089;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8901;}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8865;}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10854;}}}}}s:1:"e";a:7:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8664;}}}}s:1:"a";a:1:{s:1:"r";a:2:{s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10533;}}}s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8600;}s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8600;}}}}}}s:1:"c";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:167;}s:9:"codepoint";i:167;}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:59;}}}s:1:"s";a:1:{s:1:"w";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10537;}}}}}s:1:"t";a:1:{s:1:"m";a:2:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8726;}}}}}s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8726;}}}}s:1:"x";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10038;}}}}s:1:"f";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:120112;}s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8994;}}}}}}s:1:"h";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9839;}}}}s:1:"c";a:2:{s:1:"h";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1097;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1096;}}}s:1:"o";a:1:{s:1:"r";a:1:{s:1:"t";a:2:{s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8739;}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8741;}}}}}}}}}}}}s:1:"y";a:2:{s:1:";";a:1:{s:9:"codepoint";i:173;}s:9:"codepoint";i:173;}}s:1:"i";a:2:{s:1:"g";a:1:{s:1:"m";a:1:{s:1:"a";a:3:{s:1:";";a:1:{s:9:"codepoint";i:963;}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:962;}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:962;}}}}}s:1:"m";a:8:{s:1:";";a:1:{s:9:"codepoint";i:8764;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10858;}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8771;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8771;}}}s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10910;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10912;}}}s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10909;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10911;}}}s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8774;}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10788;}}}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10610;}}}}}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8592;}}}}}s:1:"m";a:4:{s:1:"a";a:2:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"m";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8726;}}}}}}}}}}}s:1:"s";a:1:{s:1:"h";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10803;}}}}}s:1:"e";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10724;}}}}}}}s:1:"i";a:2:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8739;}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8995;}}}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10922;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10924;}}}}s:1:"o";a:3:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1100;}}}}}s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:47;}s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10692;}s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9023;}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120164;}}}}s:1:"p";a:1:{s:1:"a";a:2:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9824;}s:1:"u";a:1:{s:1:"i";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9824;}}}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8741;}}}}s:1:"q";a:3:{s:1:"c";a:2:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8851;}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8852;}}}}s:1:"s";a:1:{s:1:"u";a:2:{s:1:"b";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8847;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8849;}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8847;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8849;}}}}}}}s:1:"p";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8848;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8850;}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8848;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8850;}}}}}}}}}s:1:"u";a:3:{s:1:";";a:1:{s:9:"codepoint";i:9633;}s:1:"a";a:1:{s:1:"r";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9633;}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9642;}}}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9642;}}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8594;}}}}}s:1:"s";a:4:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120008;}}}s:1:"e";a:1:{s:1:"t";a:1:{s:1:"m";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8726;}}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8995;}}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8902;}}}}}}s:1:"t";a:2:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9734;}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9733;}}}}s:1:"r";a:2:{s:1:"a";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:2:{s:1:"e";a:1:{s:1:"p";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1013;}}}}}}}}s:1:"p";a:1:{s:1:"h";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:981;}}}}}}}}}s:1:"n";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:175;}}}}}s:1:"u";a:5:{s:1:"b";a:9:{s:1:";";a:1:{s:9:"codepoint";i:8834;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10949;}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10941;}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8838;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10947;}}}}}s:1:"m";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10945;}}}}}s:1:"n";a:2:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10955;}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8842;}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10943;}}}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10617;}}}}}s:1:"s";a:3:{s:1:"e";a:1:{s:1:"t";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8834;}s:1:"e";a:1:{s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8838;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10949;}}}}s:1:"n";a:1:{s:1:"e";a:1:{s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8842;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10955;}}}}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10951;}}}s:1:"u";a:2:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10965;}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10963;}}}}}s:1:"c";a:1:{s:1:"c";a:6:{s:1:";";a:1:{s:9:"codepoint";i:8827;}s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10936;}}}}}}}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"l";a:1:{s:1:"y";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8829;}}}}}}}}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10928;}}}s:1:"n";a:3:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10938;}}}}}}}s:1:"e";a:1:{s:1:"q";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10934;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8937;}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8831;}}}}}}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8721;}}s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9834;}}}s:1:"p";a:13:{i:1;a:2:{s:1:";";a:1:{s:9:"codepoint";i:185;}s:9:"codepoint";i:185;}i:2;a:2:{s:1:";";a:1:{s:9:"codepoint";i:178;}s:9:"codepoint";i:178;}i:3;a:2:{s:1:";";a:1:{s:9:"codepoint";i:179;}s:9:"codepoint";i:179;}s:1:";";a:1:{s:9:"codepoint";i:8835;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10950;}}s:1:"d";a:2:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10942;}}}s:1:"s";a:1:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10968;}}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8839;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10948;}}}}}s:1:"h";a:1:{s:1:"s";a:1:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10967;}}}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10619;}}}}}s:1:"m";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10946;}}}}}s:1:"n";a:2:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10956;}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8843;}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10944;}}}}}s:1:"s";a:3:{s:1:"e";a:1:{s:1:"t";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8835;}s:1:"e";a:1:{s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8839;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10950;}}}}s:1:"n";a:1:{s:1:"e";a:1:{s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8843;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10956;}}}}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10952;}}}s:1:"u";a:2:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10964;}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10966;}}}}}}s:1:"w";a:3:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8665;}}}}s:1:"a";a:1:{s:1:"r";a:2:{s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10534;}}}s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8601;}s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8601;}}}}}}s:1:"n";a:1:{s:1:"w";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10538;}}}}}}s:1:"z";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:223;}s:9:"codepoint";i:223;}}}}}s:1:"t";a:13:{s:1:"a";a:2:{s:1:"r";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8982;}}}}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:964;}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9140;}}}}s:1:"c";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:357;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:355;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1090;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8411;}}}}s:1:"e";a:1:{s:1:"l";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8981;}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120113;}}}s:1:"h";a:4:{s:1:"e";a:2:{s:1:"r";a:1:{s:1:"e";a:2:{i:4;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8756;}}s:1:"f";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8756;}}}}}}}s:1:"t";a:1:{s:1:"a";a:3:{s:1:";";a:1:{s:9:"codepoint";i:952;}s:1:"s";a:1:{s:1:"y";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:977;}}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:977;}}}}}s:1:"i";a:2:{s:1:"c";a:1:{s:1:"k";a:2:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8776;}}}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8764;}}}}}}s:1:"n";a:1:{s:1:"s";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8201;}}}}}s:1:"k";a:2:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8776;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8764;}}}}}s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:254;}s:9:"codepoint";i:254;}}}}s:1:"i";a:3:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:732;}}}}s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:4:{s:1:";";a:1:{s:9:"codepoint";i:215;}s:9:"codepoint";i:215;s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8864;}s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10801;}}}}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10800;}}}}}s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8749;}}}}s:1:"o";a:3:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10536;}}}s:1:"p";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8868;}s:1:"b";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9014;}}}}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10993;}}}}s:1:"f";a:2:{s:1:";";a:1:{s:9:"codepoint";i:120165;}s:1:"o";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10970;}}}}}}s:1:"s";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10537;}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8244;}}}}}}s:1:"r";a:3:{s:1:"a";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8482;}}}}s:1:"i";a:7:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:5:{s:1:";";a:1:{s:9:"codepoint";i:9653;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9663;}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9667;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8884;}}}}}}}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8796;}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9657;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8885;}}}}}}}}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9708;}}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8796;}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10810;}}}}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10809;}}}}}s:1:"s";a:1:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10701;}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10811;}}}}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"z";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9186;}}}}}}}}s:1:"s";a:3:{s:1:"c";a:2:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120009;}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1094;}}}s:1:"h";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1115;}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:359;}}}}}}s:1:"w";a:2:{s:1:"i";a:1:{s:1:"x";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8812;}}}}s:1:"o";a:1:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"d";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8606;}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8608;}}}}}}}}}}}}}}}}}}s:1:"u";a:18:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8657;}}}}s:1:"H";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10595;}}}}s:1:"a";a:2:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:250;}s:9:"codepoint";i:250;}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8593;}}}}s:1:"b";a:1:{s:1:"r";a:2:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1118;}}}s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:365;}}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:251;}s:9:"codepoint";i:251;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1091;}}}s:1:"d";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8645;}}}}s:1:"b";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:369;}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10606;}}}}}s:1:"f";a:2:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10622;}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120114;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:249;}s:9:"codepoint";i:249;}}}}}s:1:"h";a:2:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8639;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8638;}}}}s:1:"b";a:1:{s:1:"l";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9600;}}}}}s:1:"l";a:2:{s:1:"c";a:2:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8988;}s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8988;}}}}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8975;}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9720;}}}}}s:1:"m";a:2:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:363;}}}}s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:168;}s:9:"codepoint";i:168;}}s:1:"o";a:2:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:371;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120166;}}}}s:1:"p";a:6:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8593;}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8597;}}}}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8639;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8638;}}}}}}}}}}}}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8846;}}}}s:1:"s";a:1:{s:1:"i";a:3:{s:1:";";a:1:{s:9:"codepoint";i:965;}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:978;}}s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:965;}}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8648;}}}}}}}}}}s:1:"r";a:3:{s:1:"c";a:2:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8989;}s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8989;}}}}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8974;}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:367;}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9721;}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120010;}}}}s:1:"t";a:3:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8944;}}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:361;}}}}}s:1:"r";a:1:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9653;}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9652;}}}}}s:1:"u";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8648;}}}}s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:252;}s:9:"codepoint";i:252;}}}s:1:"w";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10663;}}}}}}}}s:1:"v";a:14:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8661;}}}}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10984;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10985;}}}}}s:1:"D";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8872;}}}}}s:1:"a";a:2:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10652;}}}}}s:1:"r";a:7:{s:1:"e";a:1:{s:1:"p";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:949;}}}}}}}}s:1:"k";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1008;}}}}}}s:1:"n";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8709;}}}}}}}}s:1:"p";a:3:{s:1:"h";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:966;}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:982;}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8733;}}}}}}}s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8597;}s:1:"h";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1009;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:962;}}}}}}s:1:"t";a:2:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:977;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8882;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8883;}}}}}}}}}}}}}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1074;}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8866;}}}}}s:1:"e";a:3:{s:1:"e";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8744;}s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8891;}}}}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8794;}}}}s:1:"l";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8942;}}}}}s:1:"r";a:2:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:124;}}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:124;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120115;}}}s:1:"l";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8882;}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120167;}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8733;}}}}}s:1:"r";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8883;}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120011;}}}}s:1:"z";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"z";a:1:{s:1:"a";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10650;}}}}}}}}s:1:"w";a:7:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:373;}}}}}s:1:"e";a:2:{s:1:"d";a:2:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10847;}}}}s:1:"g";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8743;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8793;}}}}}s:1:"i";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8472;}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120116;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120168;}}}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8472;}}s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8768;}s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8768;}}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120012;}}}}}s:1:"x";a:14:{s:1:"c";a:3:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8898;}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9711;}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8899;}}}}s:1:"d";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9661;}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120117;}}}s:1:"h";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10234;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10231;}}}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:958;}}s:1:"l";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10232;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10229;}}}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10236;}}}}s:1:"n";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8955;}}}}s:1:"o";a:3:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10752;}}}}s:1:"p";a:2:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120169;}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10753;}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10754;}}}}}}s:1:"r";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10233;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10230;}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120013;}}}s:1:"q";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10758;}}}}}}s:1:"u";a:2:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10756;}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9651;}}}}}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8897;}}}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8896;}}}}}}}s:1:"y";a:8:{s:1:"a";a:1:{s:1:"c";a:2:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:253;}s:9:"codepoint";i:253;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1103;}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:375;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1099;}}}s:1:"e";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:165;}s:9:"codepoint";i:165;}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120118;}}}s:1:"i";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1111;}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120170;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120014;}}}}s:1:"u";a:2:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1102;}}}s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:255;}s:9:"codepoint";i:255;}}}}s:1:"z";a:10:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:378;}}}}}}s:1:"c";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:382;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1079;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:380;}}}}s:1:"e";a:2:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8488;}}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:950;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120119;}}}s:1:"h";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1078;}}}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8669;}}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120171;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120015;}}}}s:1:"w";a:2:{s:1:"j";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8205;}}s:1:"n";a:1:{s:1:"j";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8204;}}}}}}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/AdobeFontMetrics.php b/application/third_party/dompdf/lib/php-font-lib/classes/AdobeFontMetrics.php
new file mode 100644
index 00000000..a62daaa9
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/AdobeFontMetrics.php
@@ -0,0 +1,217 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib;
+
+use FontLib\Table\Type\name;
+use FontLib\TrueType\File;
+
+/**
+ * Adobe Font Metrics file creation utility class.
+ *
+ * @package php-font-lib
+ */
+class AdobeFontMetrics {
+ private $f;
+
+ /**
+ * @var File
+ */
+ private $font;
+
+ function __construct(File $font) {
+ $this->font = $font;
+ }
+
+ function write($file, $encoding = null) {
+ $map_data = array();
+
+ if ($encoding) {
+ $encoding = preg_replace("/[^a-z0-9-_]/", "", $encoding);
+ $map_file = dirname(__FILE__) . "/../maps/$encoding.map";
+ if (!file_exists($map_file)) {
+ throw new \Exception("Unkown encoding ($encoding)");
+ }
+
+ $map = new EncodingMap($map_file);
+ $map_data = $map->parse();
+ }
+
+ $this->f = fopen($file, "w+");
+
+ $font = $this->font;
+
+ $this->startSection("FontMetrics", 4.1);
+ $this->addPair("Notice", "Converted by PHP-font-lib");
+ $this->addPair("Comment", "https://github.com/PhenX/php-font-lib");
+
+ $encoding_scheme = ($encoding ? $encoding : "FontSpecific");
+ $this->addPair("EncodingScheme", $encoding_scheme);
+
+ $records = $font->getData("name", "records");
+ foreach ($records as $id => $record) {
+ if (!isset(name::$nameIdCodes[$id]) || preg_match("/[\r\n]/", $record->string)) {
+ continue;
+ }
+
+ $this->addPair(name::$nameIdCodes[$id], $record->string);
+ }
+
+ $os2 = $font->getData("OS/2");
+ $this->addPair("Weight", ($os2["usWeightClass"] > 400 ? "Bold" : "Medium"));
+
+ $post = $font->getData("post");
+ $this->addPair("ItalicAngle", $post["italicAngle"]);
+ $this->addPair("IsFixedPitch", ($post["isFixedPitch"] ? "true" : "false"));
+ $this->addPair("UnderlineThickness", $font->normalizeFUnit($post["underlineThickness"]));
+ $this->addPair("UnderlinePosition", $font->normalizeFUnit($post["underlinePosition"]));
+
+ $hhea = $font->getData("hhea");
+
+ if (isset($hhea["ascent"])) {
+ $this->addPair("FontHeightOffset", $font->normalizeFUnit($hhea["lineGap"]));
+ $this->addPair("Ascender", $font->normalizeFUnit($hhea["ascent"]));
+ $this->addPair("Descender", $font->normalizeFUnit($hhea["descent"]));
+ }
+ else {
+ $this->addPair("FontHeightOffset", $font->normalizeFUnit($os2["typoLineGap"]));
+ $this->addPair("Ascender", $font->normalizeFUnit($os2["typoAscender"]));
+ $this->addPair("Descender", -abs($font->normalizeFUnit($os2["typoDescender"])));
+ }
+
+ $head = $font->getData("head");
+ $this->addArray("FontBBox", array(
+ $font->normalizeFUnit($head["xMin"]),
+ $font->normalizeFUnit($head["yMin"]),
+ $font->normalizeFUnit($head["xMax"]),
+ $font->normalizeFUnit($head["yMax"]),
+ ));
+
+ $glyphIndexArray = $font->getUnicodeCharMap();
+
+ if ($glyphIndexArray) {
+ $hmtx = $font->getData("hmtx");
+ $names = $font->getData("post", "names");
+
+ $this->startSection("CharMetrics", count($hmtx));
+
+ if ($encoding) {
+ foreach ($map_data as $code => $value) {
+ list($c, $name) = $value;
+
+ if (!isset($glyphIndexArray[$c])) {
+ continue;
+ }
+
+ $g = $glyphIndexArray[$c];
+
+ if (!isset($hmtx[$g])) {
+ $hmtx[$g] = $hmtx[0];
+ }
+
+ $this->addMetric(array(
+ "C" => ($code > 255 ? -1 : $code),
+ "WX" => $font->normalizeFUnit($hmtx[$g][0]),
+ "N" => $name,
+ ));
+ }
+ }
+ else {
+ foreach ($glyphIndexArray as $c => $g) {
+ if (!isset($hmtx[$g])) {
+ $hmtx[$g] = $hmtx[0];
+ }
+
+ $this->addMetric(array(
+ "U" => $c,
+ "WX" => $font->normalizeFUnit($hmtx[$g][0]),
+ "N" => (isset($names[$g]) ? $names[$g] : sprintf("uni%04x", $c)),
+ "G" => $g,
+ ));
+ }
+ }
+
+ $this->endSection("CharMetrics");
+
+ $kern = $font->getData("kern", "subtable");
+ $tree = $kern["tree"];
+
+ if (!$encoding && is_array($tree)) {
+ $this->startSection("KernData");
+ $this->startSection("KernPairs", count($tree, COUNT_RECURSIVE) - count($tree));
+
+ foreach ($tree as $left => $values) {
+ if (!is_array($values)) {
+ continue;
+ }
+ if (!isset($glyphIndexArray[$left])) {
+ continue;
+ }
+
+ $left_gid = $glyphIndexArray[$left];
+
+ if (!isset($names[$left_gid])) {
+ continue;
+ }
+
+ $left_name = $names[$left_gid];
+
+ $this->addLine("");
+
+ foreach ($values as $right => $value) {
+ if (!isset($glyphIndexArray[$right])) {
+ continue;
+ }
+
+ $right_gid = $glyphIndexArray[$right];
+
+ if (!isset($names[$right_gid])) {
+ continue;
+ }
+
+ $right_name = $names[$right_gid];
+ $this->addPair("KPX", "$left_name $right_name $value");
+ }
+ }
+
+ $this->endSection("KernPairs");
+ $this->endSection("KernData");
+ }
+ }
+
+ $this->endSection("FontMetrics");
+ }
+
+ function addLine($line) {
+ fwrite($this->f, "$line\n");
+ }
+
+ function addPair($key, $value) {
+ $this->addLine("$key $value");
+ }
+
+ function addArray($key, $array) {
+ $this->addLine("$key " . implode(" ", $array));
+ }
+
+ function addMetric($data) {
+ $array = array();
+ foreach ($data as $key => $value) {
+ $array[] = "$key $value";
+ }
+ $this->addLine(implode(" ; ", $array));
+ }
+
+ function startSection($name, $value = "") {
+ $this->addLine("Start$name $value");
+ }
+
+ function endSection($name) {
+ $this->addLine("End$name");
+ }
+}
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Autoloader.php b/application/third_party/dompdf/lib/php-font-lib/classes/Autoloader.php
new file mode 100644
index 00000000..cd305453
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Autoloader.php
@@ -0,0 +1,43 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib;
+
+/**
+ * Autoloads FontLib classes
+ *
+ * @package php-font-lib
+ */
+class Autoloader {
+ const PREFIX = 'FontLib';
+
+ /**
+ * Register the autoloader
+ */
+ public static function register() {
+ spl_autoload_register(array(new self, 'autoload'));
+ }
+
+ /**
+ * Autoloader
+ *
+ * @param string
+ */
+ public static function autoload($class) {
+ $prefixLength = strlen(self::PREFIX);
+ if (0 === strncmp(self::PREFIX, $class, $prefixLength)) {
+ $file = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, $prefixLength));
+ $file = realpath(__DIR__ . (empty($file) ? '' : DIRECTORY_SEPARATOR) . $file . '.php');
+ if (file_exists($file)) {
+ require_once $file;
+ }
+ }
+ }
+}
+
+Autoloader::register();
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/BinaryStream.php b/application/third_party/dompdf/lib/php-font-lib/classes/BinaryStream.php
new file mode 100644
index 00000000..ab104544
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/BinaryStream.php
@@ -0,0 +1,444 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib;
+
+/**
+ * Generic font file binary stream.
+ *
+ * @package php-font-lib
+ */
+class BinaryStream {
+ /**
+ * @var resource The file pointer
+ */
+ protected $f;
+
+ const uint8 = 1;
+ const int8 = 2;
+ const uint16 = 3;
+ const int16 = 4;
+ const uint32 = 5;
+ const int32 = 6;
+ const shortFrac = 7;
+ const Fixed = 8;
+ const FWord = 9;
+ const uFWord = 10;
+ const F2Dot14 = 11;
+ const longDateTime = 12;
+ const char = 13;
+
+ const modeRead = "rb";
+ const modeWrite = "wb";
+ const modeReadWrite = "rb+";
+
+ static function backtrace() {
+ var_dump(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));
+ }
+
+ /**
+ * Open a font file in read mode
+ *
+ * @param string $filename The file name of the font to open
+ *
+ * @return bool
+ */
+ public function load($filename) {
+ return $this->open($filename, self::modeRead);
+ }
+
+ /**
+ * Open a font file in a chosen mode
+ *
+ * @param string $filename The file name of the font to open
+ * @param string $mode The opening mode
+ *
+ * @throws \Exception
+ * @return bool
+ */
+ public function open($filename, $mode = self::modeRead) {
+ if (!in_array($mode, array(self::modeRead, self::modeWrite, self::modeReadWrite))) {
+ throw new \Exception("Unkown file open mode");
+ }
+
+ $this->f = fopen($filename, $mode);
+
+ return $this->f != false;
+ }
+
+ /**
+ * Close the internal file pointer
+ */
+ public function close() {
+ return fclose($this->f) != false;
+ }
+
+ /**
+ * Change the internal file pointer
+ *
+ * @param resource $fp
+ *
+ * @throws \Exception
+ */
+ public function setFile($fp) {
+ if (!is_resource($fp)) {
+ throw new \Exception('$fp is not a valid resource');
+ }
+
+ $this->f = $fp;
+ }
+
+ /**
+ * Create a temporary file in write mode
+ *
+ * @param bool $allow_memory Allow in-memory files
+ *
+ * @return resource the temporary file pointer resource
+ */
+ public static function getTempFile($allow_memory = true) {
+ $f = null;
+
+ if ($allow_memory) {
+ $f = fopen("php://temp", "rb+");
+ }
+ else {
+ $f = fopen(tempnam(sys_get_temp_dir(), "fnt"), "rb+");
+ }
+
+ return $f;
+ }
+
+ /**
+ * Move the internal file pinter to $offset bytes
+ *
+ * @param int $offset
+ *
+ * @return bool True if the $offset position exists in the file
+ */
+ public function seek($offset) {
+ return fseek($this->f, $offset, SEEK_SET) == 0;
+ }
+
+ /**
+ * Gives the current position in the file
+ *
+ * @return int The current position
+ */
+ public function pos() {
+ return ftell($this->f);
+ }
+
+ public function skip($n) {
+ fseek($this->f, $n, SEEK_CUR);
+ }
+
+ public function read($n) {
+ if ($n < 1) {
+ return "";
+ }
+
+ return fread($this->f, $n);
+ }
+
+ public function write($data, $length = null) {
+ if ($data === null || $data === "" || $data === false) {
+ return 0;
+ }
+
+ return fwrite($this->f, $data, $length);
+ }
+
+ public function readUInt8() {
+ return ord($this->read(1));
+ }
+
+ public function readUInt8Many($count) {
+ return array_values(unpack("C*", $this->read($count)));
+ }
+
+ public function writeUInt8($data) {
+ return $this->write(chr($data), 1);
+ }
+
+ public function readInt8() {
+ $v = $this->readUInt8();
+
+ if ($v >= 0x80) {
+ $v -= 0x100;
+ }
+
+ return $v;
+ }
+
+ public function readInt8Many($count) {
+ return array_values(unpack("c*", $this->read($count)));
+ }
+
+ public function writeInt8($data) {
+ if ($data < 0) {
+ $data += 0x100;
+ }
+
+ return $this->writeUInt8($data);
+ }
+
+ public function readUInt16() {
+ $a = unpack("nn", $this->read(2));
+
+ return $a["n"];
+ }
+
+ public function readUInt16Many($count) {
+ return array_values(unpack("n*", $this->read($count * 2)));
+ }
+
+ public function readUFWord() {
+ return $this->readUInt16();
+ }
+
+ public function writeUInt16($data) {
+ return $this->write(pack("n", $data), 2);
+ }
+
+ public function writeUFWord($data) {
+ return $this->writeUInt16($data);
+ }
+
+ public function readInt16() {
+ $a = unpack("nn", $this->read(2));
+ $v = $a["n"];
+
+ if ($v >= 0x8000) {
+ $v -= 0x10000;
+ }
+
+ return $v;
+ }
+
+ public function readInt16Many($count) {
+ $vals = array_values(unpack("n*", $this->read($count * 2)));
+ foreach ($vals as &$v) {
+ if ($v >= 0x8000) {
+ $v -= 0x10000;
+ }
+ }
+
+ return $vals;
+ }
+
+ public function readFWord() {
+ return $this->readInt16();
+ }
+
+ public function writeInt16($data) {
+ if ($data < 0) {
+ $data += 0x10000;
+ }
+
+ return $this->writeUInt16($data);
+ }
+
+ public function writeFWord($data) {
+ return $this->writeInt16($data);
+ }
+
+ public function readUInt32() {
+ $a = unpack("NN", $this->read(4));
+
+ return $a["N"];
+ }
+
+ public function writeUInt32($data) {
+ return $this->write(pack("N", $data), 4);
+ }
+
+ public function readFixed() {
+ $d = $this->readInt16();
+ $d2 = $this->readUInt16();
+
+ return round($d + $d2 / 0x10000, 4);
+ }
+
+ public function writeFixed($data) {
+ $left = floor($data);
+ $right = ($data - $left) * 0x10000;
+
+ return $this->writeInt16($left) + $this->writeUInt16($right);
+ }
+
+ public function readLongDateTime() {
+ $this->readUInt32(); // ignored
+ $date = $this->readUInt32() - 2082844800;
+
+ # PHP_INT_MIN isn't defined in PHP < 7.0
+ $php_int_min = defined("PHP_INT_MIN") ? PHP_INT_MIN : ~PHP_INT_MAX;
+
+ if (is_string($date) || $date > PHP_INT_MAX || $date < $php_int_min) {
+ $date = 0;
+ }
+
+ return strftime("%Y-%m-%d %H:%M:%S", $date);
+ }
+
+ public function writeLongDateTime($data) {
+ $date = strtotime($data);
+ $date += 2082844800;
+
+ return $this->writeUInt32(0) + $this->writeUInt32($date);
+ }
+
+ public function unpack($def) {
+ $d = array();
+ foreach ($def as $name => $type) {
+ $d[$name] = $this->r($type);
+ }
+
+ return $d;
+ }
+
+ public function pack($def, $data) {
+ $bytes = 0;
+ foreach ($def as $name => $type) {
+ $bytes += $this->w($type, $data[$name]);
+ }
+
+ return $bytes;
+ }
+
+ /**
+ * Read a data of type $type in the file from the current position
+ *
+ * @param mixed $type The data type to read
+ *
+ * @return mixed The data that was read
+ */
+ public function r($type) {
+ switch ($type) {
+ case self::uint8:
+ return $this->readUInt8();
+ case self::int8:
+ return $this->readInt8();
+ case self::uint16:
+ return $this->readUInt16();
+ case self::int16:
+ return $this->readInt16();
+ case self::uint32:
+ return $this->readUInt32();
+ case self::int32:
+ return $this->readUInt32();
+ case self::shortFrac:
+ return $this->readFixed();
+ case self::Fixed:
+ return $this->readFixed();
+ case self::FWord:
+ return $this->readInt16();
+ case self::uFWord:
+ return $this->readUInt16();
+ case self::F2Dot14:
+ return $this->readInt16();
+ case self::longDateTime:
+ return $this->readLongDateTime();
+ case self::char:
+ return $this->read(1);
+ default:
+ if (is_array($type)) {
+ if ($type[0] == self::char) {
+ return $this->read($type[1]);
+ }
+ if ($type[0] == self::uint16) {
+ return $this->readUInt16Many($type[1]);
+ }
+ if ($type[0] == self::int16) {
+ return $this->readInt16Many($type[1]);
+ }
+ if ($type[0] == self::uint8) {
+ return $this->readUInt8Many($type[1]);
+ }
+ if ($type[0] == self::int8) {
+ return $this->readInt8Many($type[1]);
+ }
+
+ $ret = array();
+ for ($i = 0; $i < $type[1]; $i++) {
+ $ret[] = $this->r($type[0]);
+ }
+
+ return $ret;
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Write $data of type $type in the file from the current position
+ *
+ * @param mixed $type The data type to write
+ * @param mixed $data The data to write
+ *
+ * @return int The number of bytes read
+ */
+ public function w($type, $data) {
+ switch ($type) {
+ case self::uint8:
+ return $this->writeUInt8($data);
+ case self::int8:
+ return $this->writeInt8($data);
+ case self::uint16:
+ return $this->writeUInt16($data);
+ case self::int16:
+ return $this->writeInt16($data);
+ case self::uint32:
+ return $this->writeUInt32($data);
+ case self::int32:
+ return $this->writeUInt32($data);
+ case self::shortFrac:
+ return $this->writeFixed($data);
+ case self::Fixed:
+ return $this->writeFixed($data);
+ case self::FWord:
+ return $this->writeInt16($data);
+ case self::uFWord:
+ return $this->writeUInt16($data);
+ case self::F2Dot14:
+ return $this->writeInt16($data);
+ case self::longDateTime:
+ return $this->writeLongDateTime($data);
+ case self::char:
+ return $this->write($data, 1);
+ default:
+ if (is_array($type)) {
+ if ($type[0] == self::char) {
+ return $this->write($data, $type[1]);
+ }
+
+ $ret = 0;
+ for ($i = 0; $i < $type[1]; $i++) {
+ if (isset($data[$i])) {
+ $ret += $this->w($type[0], $data[$i]);
+ }
+ }
+
+ return $ret;
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Converts a Uint32 value to string
+ *
+ * @param int $uint32
+ *
+ * @return string The string
+ */
+ public function convertUInt32ToStr($uint32) {
+ return chr(($uint32 >> 24) & 0xFF) . chr(($uint32 >> 16) & 0xFF) . chr(($uint32 >> 8) & 0xFF) . chr($uint32 & 0xFF);
+ }
+}
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/EOT/File.php b/application/third_party/dompdf/lib/php-font-lib/classes/EOT/File.php
new file mode 100644
index 00000000..13d59257
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/EOT/File.php
@@ -0,0 +1,160 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\EOT;
+
+/**
+ * EOT font file.
+ *
+ * @package php-font-lib
+ */
+class File extends \FontLib\TrueType\File {
+ const TTEMBED_SUBSET = 0x00000001;
+ const TTEMBED_TTCOMPRESSED = 0x00000004;
+ const TTEMBED_FAILIFVARIATIONSIMULATED = 0x00000010;
+ const TTMBED_EMBEDEUDC = 0x00000020;
+ const TTEMBED_VALIDATIONTESTS = 0x00000040; // Deprecated
+ const TTEMBED_WEBOBJECT = 0x00000080;
+ const TTEMBED_XORENCRYPTDATA = 0x10000000;
+
+ /**
+ * @var Header
+ */
+ public $header;
+
+ function parseHeader() {
+ if (!empty($this->header)) {
+ return;
+ }
+
+ $this->header = new Header($this);
+ $this->header->parse();
+ }
+
+ function parse() {
+ $this->parseHeader();
+
+ $flags = $this->header->data["Flags"];
+
+ if ($flags & self::TTEMBED_TTCOMPRESSED) {
+ $mtx_version = $this->readUInt8();
+ $mtx_copy_limit = $this->readUInt8() << 16 | $this->readUInt8() << 8 | $this->readUInt8();
+ $mtx_offset_1 = $this->readUInt8() << 16 | $this->readUInt8() << 8 | $this->readUInt8();
+ $mtx_offset_2 = $this->readUInt8() << 16 | $this->readUInt8() << 8 | $this->readUInt8();
+ /*
+ var_dump("$mtx_version $mtx_copy_limit $mtx_offset_1 $mtx_offset_2");
+
+ $pos = $this->pos();
+ $size = $mtx_offset_1 - $pos;
+ var_dump("pos: $pos");
+ var_dump("size: $size");*/
+ }
+
+ if ($flags & self::TTEMBED_XORENCRYPTDATA) {
+ // Process XOR
+ }
+ // TODO Read font data ...
+ }
+
+ /**
+ * Little endian version of the read method
+ *
+ * @param int $n The number of bytes to read
+ *
+ * @return string
+ */
+ public function read($n) {
+ if ($n < 1) {
+ return "";
+ }
+
+ $string = fread($this->f, $n);
+ $chunks = str_split($string, 2);
+ $chunks = array_map("strrev", $chunks);
+
+ return implode("", $chunks);
+ }
+
+ public function readUInt32() {
+ $uint32 = parent::readUInt32();
+
+ return $uint32 >> 16 & 0x0000FFFF | $uint32 << 16 & 0xFFFF0000;
+ }
+
+ /**
+ * Get font copyright
+ *
+ * @return string|null
+ */
+ function getFontCopyright() {
+ return null;
+ }
+
+ /**
+ * Get font name
+ *
+ * @return string|null
+ */
+ function getFontName() {
+ return $this->header->data["FamilyName"];
+ }
+
+ /**
+ * Get font subfamily
+ *
+ * @return string|null
+ */
+ function getFontSubfamily() {
+ return $this->header->data["StyleName"];
+ }
+
+ /**
+ * Get font subfamily ID
+ *
+ * @return string|null
+ */
+ function getFontSubfamilyID() {
+ return $this->header->data["StyleName"];
+ }
+
+ /**
+ * Get font full name
+ *
+ * @return string|null
+ */
+ function getFontFullName() {
+ return $this->header->data["FullName"];
+ }
+
+ /**
+ * Get font version
+ *
+ * @return string|null
+ */
+ function getFontVersion() {
+ return $this->header->data["VersionName"];
+ }
+
+ /**
+ * Get font weight
+ *
+ * @return string|null
+ */
+ function getFontWeight() {
+ return $this->header->data["Weight"];
+ }
+
+ /**
+ * Get font Postscript name
+ *
+ * @return string|null
+ */
+ function getFontPostscriptName() {
+ return null;
+ }
+}
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/EOT/Header.php b/application/third_party/dompdf/lib/php-font-lib/classes/EOT/Header.php
new file mode 100644
index 00000000..960e36ad
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/EOT/Header.php
@@ -0,0 +1,113 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\EOT;
+
+use Exception;
+use FontLib\Font;
+
+/**
+ * TrueType font file header.
+ *
+ * @package php-font-lib
+ *
+ * @property File $font
+ */
+class Header extends \FontLib\Header {
+ protected $def = array(
+ "format" => self::uint32,
+ "numTables" => self::uint16,
+ "searchRange" => self::uint16,
+ "entrySelector" => self::uint16,
+ "rangeShift" => self::uint16,
+ );
+
+ public function parse() {
+ $font = $this->font;
+
+ $this->data = $font->unpack(array(
+ "EOTSize" => self::uint32,
+ "FontDataSize" => self::uint32,
+ "Version" => self::uint32,
+ "Flags" => self::uint32,
+ "FontPANOSE" => array(self::uint8, 10),
+ "Charset" => self::uint8,
+ "Italic" => self::uint8,
+ "Weight" => self::uint32,
+ "fsType" => self::uint16,
+ "MagicNumber" => self::uint16,
+ "UnicodeRange1" => self::uint32,
+ "UnicodeRange2" => self::uint32,
+ "UnicodeRange3" => self::uint32,
+ "UnicodeRange4" => self::uint32,
+ "CodePageRange1" => self::uint32,
+ "CodePageRange2" => self::uint32,
+ "CheckSumAdjustment" => self::uint32,
+ "Reserved1" => self::uint32,
+ "Reserved2" => self::uint32,
+ "Reserved3" => self::uint32,
+ "Reserved4" => self::uint32,
+ ));
+
+ $this->data["Padding1"] = $font->readUInt16();
+ $this->readString("FamilyName");
+
+ $this->data["Padding2"] = $font->readUInt16();
+ $this->readString("StyleName");
+
+ $this->data["Padding3"] = $font->readUInt16();
+ $this->readString("VersionName");
+
+ $this->data["Padding4"] = $font->readUInt16();
+ $this->readString("FullName");
+
+ switch ($this->data["Version"]) {
+ default:
+ throw new Exception("Unknown EOT version " . $this->data["Version"]);
+
+ case 0x00010000:
+ // Nothing to do more
+ break;
+
+ case 0x00020001:
+ $this->data["Padding5"] = $font->readUInt16();
+ $this->readString("RootString");
+ break;
+
+ case 0x00020002:
+ $this->data["Padding5"] = $font->readUInt16();
+ $this->readString("RootString");
+
+ $this->data["RootStringCheckSum"] = $font->readUInt32();
+ $this->data["EUDCCodePage"] = $font->readUInt32();
+
+ $this->data["Padding6"] = $font->readUInt16();
+ $this->readString("Signature");
+
+ $this->data["EUDCFlags"] = $font->readUInt32();
+ $this->data["EUDCFontSize"] = $font->readUInt32();
+ break;
+ }
+
+ if (!empty($this->data["RootString"])) {
+ $this->data["RootString"] = explode("\0", $this->data["RootString"]);
+ }
+ }
+
+ private function readString($name) {
+ $font = $this->font;
+ $size = $font->readUInt16();
+
+ $this->data["{$name}Size"] = $size;
+ $this->data[$name] = Font::UTF16ToUTF8($font->read($size));
+ }
+
+ public function encode() {
+ //return $this->font->pack($this->def, $this->data);
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/EncodingMap.php b/application/third_party/dompdf/lib/php-font-lib/classes/EncodingMap.php
new file mode 100644
index 00000000..2acdebc5
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/EncodingMap.php
@@ -0,0 +1,37 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib;
+
+/**
+ * Encoding map used to map a code point to a Unicode char.
+ *
+ * @package php-font-lib
+ */
+class EncodingMap {
+ private $f;
+
+ function __construct($file) {
+ $this->f = fopen($file, "r");
+ }
+
+ function parse() {
+ $map = array();
+
+ while ($line = fgets($this->f)) {
+ if (preg_match('/^[\!\=]([0-9A-F]{2,})\s+U\+([0-9A-F]{2})([0-9A-F]{2})\s+([^\s]+)/', $line, $matches)) {
+ $unicode = (hexdec($matches[2]) << 8) + hexdec($matches[3]);
+ $map[hexdec($matches[1])] = array($unicode, $matches[4]);
+ }
+ }
+
+ ksort($map);
+
+ return $map;
+ }
+}
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Exception/FontNotFoundException.php b/application/third_party/dompdf/lib/php-font-lib/classes/Exception/FontNotFoundException.php
new file mode 100644
index 00000000..d97f2523
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Exception/FontNotFoundException.php
@@ -0,0 +1,11 @@
+message = 'Font not found in: ' . $fontPath;
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Font.php b/application/third_party/dompdf/lib/php-font-lib/classes/Font.php
new file mode 100644
index 00000000..ecc216e8
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Font.php
@@ -0,0 +1,89 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib;
+
+use FontLib\Exception\FontNotFoundException;
+
+/**
+ * Generic font file.
+ *
+ * @package php-font-lib
+ */
+class Font {
+ static $debug = false;
+
+ /**
+ * @param string $file The font file
+ *
+ * @return TrueType\File|null $file
+ */
+ public static function load($file) {
+ if(!file_exists($file)){
+ throw new FontNotFoundException($file);
+ }
+
+ $header = file_get_contents($file, false, null, null, 4);
+ $class = null;
+
+ switch ($header) {
+ case "\x00\x01\x00\x00":
+ case "true":
+ case "typ1":
+ $class = "TrueType\\File";
+ break;
+
+ case "OTTO":
+ $class = "OpenType\\File";
+ break;
+
+ case "wOFF":
+ $class = "WOFF\\File";
+ break;
+
+ case "ttcf":
+ $class = "TrueType\\Collection";
+ break;
+
+ // Unknown type or EOT
+ default:
+ $magicNumber = file_get_contents($file, false, null, 34, 2);
+
+ if ($magicNumber === "LP") {
+ $class = "EOT\\File";
+ }
+ }
+
+ if ($class) {
+ $class = "FontLib\\$class";
+
+ /** @var TrueType\File $obj */
+ $obj = new $class;
+ $obj->load($file);
+
+ return $obj;
+ }
+
+ return null;
+ }
+
+ static function d($str) {
+ if (!self::$debug) {
+ return;
+ }
+ echo "$str\n";
+ }
+
+ static function UTF16ToUTF8($str) {
+ return mb_convert_encoding($str, "utf-8", "utf-16");
+ }
+
+ static function UTF8ToUTF16($str) {
+ return mb_convert_encoding($str, "utf-16", "utf-8");
+ }
+}
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Glyph/Outline.php b/application/third_party/dompdf/lib/php-font-lib/classes/Glyph/Outline.php
new file mode 100644
index 00000000..330db091
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Glyph/Outline.php
@@ -0,0 +1,110 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ * @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
+ */
+namespace FontLib\Glyph;
+
+use FontLib\Table\Type\glyf;
+use FontLib\TrueType\File;
+use FontLib\BinaryStream;
+
+/**
+ * `glyf` font table.
+ *
+ * @package php-font-lib
+ */
+class Outline extends BinaryStream {
+ /**
+ * @var \FontLib\Table\Type\glyf
+ */
+ protected $table;
+
+ protected $offset;
+ protected $size;
+
+ // Data
+ public $numberOfContours;
+ public $xMin;
+ public $yMin;
+ public $xMax;
+ public $yMax;
+
+ public $raw;
+
+ /**
+ * @param glyf $table
+ * @param $offset
+ * @param $size
+ *
+ * @return Outline
+ */
+ static function init(glyf $table, $offset, $size, BinaryStream $font) {
+ $font->seek($offset);
+
+ if ($font->readInt16() > -1) {
+ /** @var OutlineSimple $glyph */
+ $glyph = new OutlineSimple($table, $offset, $size);
+ }
+ else {
+ /** @var OutlineComposite $glyph */
+ $glyph = new OutlineComposite($table, $offset, $size);
+ }
+
+ $glyph->parse($font);
+
+ return $glyph;
+ }
+
+ /**
+ * @return File
+ */
+ function getFont() {
+ return $this->table->getFont();
+ }
+
+ function __construct(glyf $table, $offset = null, $size = null) {
+ $this->table = $table;
+ $this->offset = $offset;
+ $this->size = $size;
+ }
+
+ function parse(BinaryStream $font) {
+ $font->seek($this->offset);
+
+ if (!$this->size) {
+ return;
+ }
+
+ $this->raw = $font->read($this->size);
+ }
+
+ function parseData() {
+ $font = $this->getFont();
+ $font->seek($this->offset);
+
+ $this->numberOfContours = $font->readInt16();
+ $this->xMin = $font->readFWord();
+ $this->yMin = $font->readFWord();
+ $this->xMax = $font->readFWord();
+ $this->yMax = $font->readFWord();
+ }
+
+ function encode() {
+ $font = $this->getFont();
+
+ return $font->write($this->raw, strlen($this->raw));
+ }
+
+ function getSVGContours() {
+ // Inherit
+ }
+
+ function getGlyphIDs() {
+ return array();
+ }
+}
+
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Glyph/OutlineComponent.php b/application/third_party/dompdf/lib/php-font-lib/classes/Glyph/OutlineComponent.php
new file mode 100644
index 00000000..9cafaf4d
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Glyph/OutlineComponent.php
@@ -0,0 +1,31 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ * @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
+ */
+
+namespace FontLib\Glyph;
+/**
+ * Glyph outline component
+ *
+ * @package php-font-lib
+ */
+class OutlineComponent {
+ public $flags;
+ public $glyphIndex;
+ public $a, $b, $c, $d, $e, $f;
+ public $point_compound;
+ public $point_component;
+ public $instructions;
+
+ function getMatrix() {
+ return array(
+ $this->a, $this->b,
+ $this->c, $this->d,
+ $this->e, $this->f,
+ );
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Glyph/OutlineComposite.php b/application/third_party/dompdf/lib/php-font-lib/classes/Glyph/OutlineComposite.php
new file mode 100644
index 00000000..8ab0d2c6
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Glyph/OutlineComposite.php
@@ -0,0 +1,242 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ * @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
+ */
+
+namespace FontLib\Glyph;
+
+/**
+ * Composite glyph outline
+ *
+ * @package php-font-lib
+ */
+class OutlineComposite extends Outline {
+ const ARG_1_AND_2_ARE_WORDS = 0x0001;
+ const ARGS_ARE_XY_VALUES = 0x0002;
+ const ROUND_XY_TO_GRID = 0x0004;
+ const WE_HAVE_A_SCALE = 0x0008;
+ const MORE_COMPONENTS = 0x0020;
+ const WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
+ const WE_HAVE_A_TWO_BY_TWO = 0x0080;
+ const WE_HAVE_INSTRUCTIONS = 0x0100;
+ const USE_MY_METRICS = 0x0200;
+ const OVERLAP_COMPOUND = 0x0400;
+
+ /**
+ * @var OutlineComponent[]
+ */
+ public $components = array();
+
+ function getGlyphIDs() {
+ if (empty($this->components)) {
+ $this->parseData();
+ }
+
+ $glyphIDs = array();
+ foreach ($this->components as $_component) {
+ $glyphIDs[] = $_component->glyphIndex;
+
+ $_glyph = $this->table->data[$_component->glyphIndex];
+
+ if ($_glyph !== $this) {
+ $glyphIDs = array_merge($glyphIDs, $_glyph->getGlyphIDs());
+ }
+ }
+
+ return $glyphIDs;
+ }
+
+ /*function parse() {
+ //$this->parseData();
+ }*/
+
+ function parseData() {
+ parent::parseData();
+
+ $font = $this->getFont();
+
+ do {
+ $flags = $font->readUInt16();
+ $glyphIndex = $font->readUInt16();
+
+ $a = 1.0;
+ $b = 0.0;
+ $c = 0.0;
+ $d = 1.0;
+ $e = 0.0;
+ $f = 0.0;
+
+ $point_compound = null;
+ $point_component = null;
+
+ $instructions = null;
+
+ if ($flags & self::ARG_1_AND_2_ARE_WORDS) {
+ if ($flags & self::ARGS_ARE_XY_VALUES) {
+ $e = $font->readInt16();
+ $f = $font->readInt16();
+ }
+ else {
+ $point_compound = $font->readUInt16();
+ $point_component = $font->readUInt16();
+ }
+ }
+ else {
+ if ($flags & self::ARGS_ARE_XY_VALUES) {
+ $e = $font->readInt8();
+ $f = $font->readInt8();
+ }
+ else {
+ $point_compound = $font->readUInt8();
+ $point_component = $font->readUInt8();
+ }
+ }
+
+ if ($flags & self::WE_HAVE_A_SCALE) {
+ $a = $d = $font->readInt16();
+ }
+ elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) {
+ $a = $font->readInt16();
+ $d = $font->readInt16();
+ }
+ elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) {
+ $a = $font->readInt16();
+ $b = $font->readInt16();
+ $c = $font->readInt16();
+ $d = $font->readInt16();
+ }
+
+ //if ($flags & self::WE_HAVE_INSTRUCTIONS) {
+ //
+ //}
+
+ $component = new OutlineComponent();
+ $component->flags = $flags;
+ $component->glyphIndex = $glyphIndex;
+ $component->a = $a;
+ $component->b = $b;
+ $component->c = $c;
+ $component->d = $d;
+ $component->e = $e;
+ $component->f = $f;
+ $component->point_compound = $point_compound;
+ $component->point_component = $point_component;
+ $component->instructions = $instructions;
+
+ $this->components[] = $component;
+ } while ($flags & self::MORE_COMPONENTS);
+ }
+
+ function encode() {
+ $font = $this->getFont();
+
+ $gids = $font->getSubset();
+
+ $size = $font->writeInt16(-1);
+ $size += $font->writeFWord($this->xMin);
+ $size += $font->writeFWord($this->yMin);
+ $size += $font->writeFWord($this->xMax);
+ $size += $font->writeFWord($this->yMax);
+
+ foreach ($this->components as $_i => $_component) {
+ $flags = 0;
+ if ($_component->point_component === null && $_component->point_compound === null) {
+ $flags |= self::ARGS_ARE_XY_VALUES;
+
+ if (abs($_component->e) > 0x7F || abs($_component->f) > 0x7F) {
+ $flags |= self::ARG_1_AND_2_ARE_WORDS;
+ }
+ }
+ elseif ($_component->point_component > 0xFF || $_component->point_compound > 0xFF) {
+ $flags |= self::ARG_1_AND_2_ARE_WORDS;
+ }
+
+ if ($_component->b == 0 && $_component->c == 0) {
+ if ($_component->a == $_component->d) {
+ if ($_component->a != 1.0) {
+ $flags |= self::WE_HAVE_A_SCALE;
+ }
+ }
+ else {
+ $flags |= self::WE_HAVE_AN_X_AND_Y_SCALE;
+ }
+ }
+ else {
+ $flags |= self::WE_HAVE_A_TWO_BY_TWO;
+ }
+
+ if ($_i < count($this->components) - 1) {
+ $flags |= self::MORE_COMPONENTS;
+ }
+
+ $size += $font->writeUInt16($flags);
+
+ $new_gid = array_search($_component->glyphIndex, $gids);
+ $size += $font->writeUInt16($new_gid);
+
+ if ($flags & self::ARG_1_AND_2_ARE_WORDS) {
+ if ($flags & self::ARGS_ARE_XY_VALUES) {
+ $size += $font->writeInt16($_component->e);
+ $size += $font->writeInt16($_component->f);
+ }
+ else {
+ $size += $font->writeUInt16($_component->point_compound);
+ $size += $font->writeUInt16($_component->point_component);
+ }
+ }
+ else {
+ if ($flags & self::ARGS_ARE_XY_VALUES) {
+ $size += $font->writeInt8($_component->e);
+ $size += $font->writeInt8($_component->f);
+ }
+ else {
+ $size += $font->writeUInt8($_component->point_compound);
+ $size += $font->writeUInt8($_component->point_component);
+ }
+ }
+
+ if ($flags & self::WE_HAVE_A_SCALE) {
+ $size += $font->writeInt16($_component->a);
+ }
+ elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) {
+ $size += $font->writeInt16($_component->a);
+ $size += $font->writeInt16($_component->d);
+ }
+ elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) {
+ $size += $font->writeInt16($_component->a);
+ $size += $font->writeInt16($_component->b);
+ $size += $font->writeInt16($_component->c);
+ $size += $font->writeInt16($_component->d);
+ }
+ }
+
+ return $size;
+ }
+
+ public function getSVGContours() {
+ $contours = array();
+
+ /** @var \FontLib\Table\Type\glyf $glyph_data */
+ $glyph_data = $this->getFont()->getTableObject("glyf");
+
+ /** @var Outline[] $glyphs */
+ $glyphs = $glyph_data->data;
+
+ foreach ($this->components as $component) {
+ $_glyph = $glyphs[$component->glyphIndex];
+
+ if ($_glyph !== $this) {
+ $contours[] = array(
+ "contours" => $_glyph->getSVGContours(),
+ "transform" => $component->getMatrix(),
+ );
+ }
+ }
+
+ return $contours;
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Glyph/OutlineSimple.php b/application/third_party/dompdf/lib/php-font-lib/classes/Glyph/OutlineSimple.php
new file mode 100644
index 00000000..3c023de9
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Glyph/OutlineSimple.php
@@ -0,0 +1,335 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ * @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
+ */
+
+namespace FontLib\Glyph;
+
+/**
+ * `glyf` font table.
+ *
+ * @package php-font-lib
+ */
+class OutlineSimple extends Outline {
+ const ON_CURVE = 0x01;
+ const X_SHORT_VECTOR = 0x02;
+ const Y_SHORT_VECTOR = 0x04;
+ const REPEAT = 0x08;
+ const THIS_X_IS_SAME = 0x10;
+ const THIS_Y_IS_SAME = 0x20;
+
+ public $instructions;
+ public $points;
+
+ function parseData() {
+ parent::parseData();
+
+ if (!$this->size) {
+ return;
+ }
+
+ $font = $this->getFont();
+
+ $noc = $this->numberOfContours;
+
+ if ($noc == 0) {
+ return;
+ }
+
+ $endPtsOfContours = $font->r(array(self::uint16, $noc));
+
+ $instructionLength = $font->readUInt16();
+ $this->instructions = $font->r(array(self::uint8, $instructionLength));
+
+ $count = $endPtsOfContours[$noc - 1] + 1;
+
+ // Flags
+ $flags = array();
+ for ($index = 0; $index < $count; $index++) {
+ $flags[$index] = $font->readUInt8();
+
+ if ($flags[$index] & self::REPEAT) {
+ $repeats = $font->readUInt8();
+
+ for ($i = 1; $i <= $repeats; $i++) {
+ $flags[$index + $i] = $flags[$index];
+ }
+
+ $index += $repeats;
+ }
+ }
+
+ $points = array();
+ foreach ($flags as $i => $flag) {
+ $points[$i]["onCurve"] = $flag & self::ON_CURVE;
+ $points[$i]["endOfContour"] = in_array($i, $endPtsOfContours);
+ }
+
+ // X Coords
+ $x = 0;
+ for ($i = 0; $i < $count; $i++) {
+ $flag = $flags[$i];
+
+ if ($flag & self::THIS_X_IS_SAME) {
+ if ($flag & self::X_SHORT_VECTOR) {
+ $x += $font->readUInt8();
+ }
+ }
+ else {
+ if ($flag & self::X_SHORT_VECTOR) {
+ $x -= $font->readUInt8();
+ }
+ else {
+ $x += $font->readInt16();
+ }
+ }
+
+ $points[$i]["x"] = $x;
+ }
+
+ // Y Coords
+ $y = 0;
+ for ($i = 0; $i < $count; $i++) {
+ $flag = $flags[$i];
+
+ if ($flag & self::THIS_Y_IS_SAME) {
+ if ($flag & self::Y_SHORT_VECTOR) {
+ $y += $font->readUInt8();
+ }
+ }
+ else {
+ if ($flag & self::Y_SHORT_VECTOR) {
+ $y -= $font->readUInt8();
+ }
+ else {
+ $y += $font->readInt16();
+ }
+ }
+
+ $points[$i]["y"] = $y;
+ }
+
+ $this->points = $points;
+ }
+
+ public function splitSVGPath($path) {
+ preg_match_all('/([a-z])|(-?\d+(?:\.\d+)?)/i', $path, $matches, PREG_PATTERN_ORDER);
+
+ return $matches[0];
+ }
+
+ public function makePoints($path) {
+ $path = $this->splitSVGPath($path);
+ $l = count($path);
+ $i = 0;
+
+ $points = array();
+
+ while ($i < $l) {
+ switch ($path[$i]) {
+ // moveTo
+ case "M":
+ $points[] = array(
+ "onCurve" => true,
+ "x" => $path[++$i],
+ "y" => $path[++$i],
+ "endOfContour" => false,
+ );
+ break;
+
+ // lineTo
+ case "L":
+ $points[] = array(
+ "onCurve" => true,
+ "x" => $path[++$i],
+ "y" => $path[++$i],
+ "endOfContour" => false,
+ );
+ break;
+
+ // quadraticCurveTo
+ case "Q":
+ $points[] = array(
+ "onCurve" => false,
+ "x" => $path[++$i],
+ "y" => $path[++$i],
+ "endOfContour" => false,
+ );
+ $points[] = array(
+ "onCurve" => true,
+ "x" => $path[++$i],
+ "y" => $path[++$i],
+ "endOfContour" => false,
+ );
+ break;
+
+ // closePath
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case "z":
+ $points[count($points) - 1]["endOfContour"] = true;
+
+ default:
+ $i++;
+ break;
+ }
+ }
+
+ return $points;
+ }
+
+ function encode() {
+ if (empty($this->points)) {
+ return parent::encode();
+ }
+
+ return $this->size = $this->encodePoints($this->points);
+ }
+
+ public function encodePoints($points) {
+ $endPtsOfContours = array();
+ $flags = array();
+ $coords_x = array();
+ $coords_y = array();
+
+ $last_x = 0;
+ $last_y = 0;
+ $xMin = $yMin = 0xFFFF;
+ $xMax = $yMax = -0xFFFF;
+ foreach ($points as $i => $point) {
+ $flag = 0;
+ if ($point["onCurve"]) {
+ $flag |= self::ON_CURVE;
+ }
+
+ if ($point["endOfContour"]) {
+ $endPtsOfContours[] = $i;
+ }
+
+ // Simplified, we could do some optimizations
+ if ($point["x"] == $last_x) {
+ $flag |= self::THIS_X_IS_SAME;
+ }
+ else {
+ $x = intval($point["x"]);
+ $xMin = min($x, $xMin);
+ $xMax = max($x, $xMax);
+ $coords_x[] = $x - $last_x; // int16
+ }
+
+ // Simplified, we could do some optimizations
+ if ($point["y"] == $last_y) {
+ $flag |= self::THIS_Y_IS_SAME;
+ }
+ else {
+ $y = intval($point["y"]);
+ $yMin = min($y, $yMin);
+ $yMax = max($y, $yMax);
+ $coords_y[] = $y - $last_y; // int16
+ }
+
+ $flags[] = $flag;
+ $last_x = $point["x"];
+ $last_y = $point["y"];
+ }
+
+ $font = $this->getFont();
+
+ $l = 0;
+ $l += $font->writeInt16(count($endPtsOfContours)); // endPtsOfContours
+ $l += $font->writeFWord(isset($this->xMin) ? $this->xMin : $xMin); // xMin
+ $l += $font->writeFWord(isset($this->yMin) ? $this->yMin : $yMin); // yMin
+ $l += $font->writeFWord(isset($this->xMax) ? $this->xMax : $xMax); // xMax
+ $l += $font->writeFWord(isset($this->yMax) ? $this->yMax : $yMax); // yMax
+
+ // Simple glyf
+ $l += $font->w(array(self::uint16, count($endPtsOfContours)), $endPtsOfContours); // endPtsOfContours
+ $l += $font->writeUInt16(0); // instructionLength
+ $l += $font->w(array(self::uint8, count($flags)), $flags); // flags
+ $l += $font->w(array(self::int16, count($coords_x)), $coords_x); // xCoordinates
+ $l += $font->w(array(self::int16, count($coords_y)), $coords_y); // yCoordinates
+ return $l;
+ }
+
+ public function getSVGContours($points = null) {
+ $path = "";
+
+ if (!$points) {
+ if (empty($this->points)) {
+ $this->parseData();
+ }
+
+ $points = $this->points;
+ }
+
+ $length = count($points);
+ $firstIndex = 0;
+ $count = 0;
+
+ for ($i = 0; $i < $length; $i++) {
+ $count++;
+
+ if ($points[$i]["endOfContour"]) {
+ $path .= $this->getSVGPath($points, $firstIndex, $count);
+ $firstIndex = $i + 1;
+ $count = 0;
+ }
+ }
+
+ return $path;
+ }
+
+ protected function getSVGPath($points, $startIndex, $count) {
+ $offset = 0;
+ $path = "";
+
+ while ($offset < $count) {
+ $point = $points[$startIndex + $offset % $count];
+ $point_p1 = $points[$startIndex + ($offset + 1) % $count];
+
+ if ($offset == 0) {
+ $path .= "M{$point['x']},{$point['y']} ";
+ }
+
+ if ($point["onCurve"]) {
+ if ($point_p1["onCurve"]) {
+ $path .= "L{$point_p1['x']},{$point_p1['y']} ";
+ $offset++;
+ }
+ else {
+ $point_p2 = $points[$startIndex + ($offset + 2) % $count];
+
+ if ($point_p2["onCurve"]) {
+ $path .= "Q{$point_p1['x']},{$point_p1['y']},{$point_p2['x']},{$point_p2['y']} ";
+ }
+ else {
+ $path .= "Q{$point_p1['x']},{$point_p1['y']}," . $this->midValue($point_p1['x'], $point_p2['x']) . "," . $this->midValue($point_p1['y'], $point_p2['y']) . " ";
+ }
+
+ $offset += 2;
+ }
+ }
+ else {
+ if ($point_p1["onCurve"]) {
+ $path .= "Q{$point['x']},{$point['y']},{$point_p1['x']},{$point_p1['y']} ";
+ }
+ else {
+ $path .= "Q{$point['x']},{$point['y']}," . $this->midValue($point['x'], $point_p1['x']) . "," . $this->midValue($point['y'], $point_p1['y']) . " ";
+ }
+
+ $offset++;
+ }
+ }
+
+ $path .= "z ";
+
+ return $path;
+ }
+
+ function midValue($a, $b) {
+ return $a + ($b - $a) / 2;
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Header.php b/application/third_party/dompdf/lib/php-font-lib/classes/Header.php
new file mode 100644
index 00000000..cbf137ed
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Header.php
@@ -0,0 +1,37 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace FontLib;
+
+use FontLib\TrueType\File;
+
+/**
+ * Font header container.
+ *
+ * @package php-font-lib
+ */
+abstract class Header extends BinaryStream {
+ /**
+ * @var File
+ */
+ protected $font;
+ protected $def = array();
+
+ public $data;
+
+ public function __construct(File $font) {
+ $this->font = $font;
+ }
+
+ public function encode() {
+ return $this->font->pack($this->def, $this->data);
+ }
+
+ public function parse() {
+ $this->data = $this->font->unpack($this->def);
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/OpenType/File.php b/application/third_party/dompdf/lib/php-font-lib/classes/OpenType/File.php
new file mode 100644
index 00000000..9c6df96f
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/OpenType/File.php
@@ -0,0 +1,18 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\OpenType;
+
+/**
+ * Open Type font, the same as a TrueType one.
+ *
+ * @package php-font-lib
+ */
+class File extends \FontLib\TrueType\File {
+ //
+}
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/OpenType/TableDirectoryEntry.php b/application/third_party/dompdf/lib/php-font-lib/classes/OpenType/TableDirectoryEntry.php
new file mode 100644
index 00000000..dd75a3e1
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/OpenType/TableDirectoryEntry.php
@@ -0,0 +1,18 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\OpenType;
+
+/**
+ * Open Type Table directory entry, the same as a TrueType one.
+ *
+ * @package php-font-lib
+ */
+class TableDirectoryEntry extends \FontLib\TrueType\TableDirectoryEntry {
+
+}
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/DirectoryEntry.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/DirectoryEntry.php
new file mode 100644
index 00000000..2b5846d3
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/DirectoryEntry.php
@@ -0,0 +1,129 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace FontLib\Table;
+
+use FontLib\TrueType\File;
+use FontLib\Font;
+use FontLib\BinaryStream;
+
+/**
+ * Generic Font table directory entry.
+ *
+ * @package php-font-lib
+ */
+class DirectoryEntry extends BinaryStream {
+ /**
+ * @var File
+ */
+ protected $font;
+
+ /**
+ * @var Table
+ */
+ protected $font_table;
+
+ public $entryLength = 4;
+
+ public $tag;
+ public $checksum;
+ public $offset;
+ public $length;
+
+ protected $origF;
+
+ static function computeChecksum($data) {
+ $len = strlen($data);
+ $mod = $len % 4;
+
+ if ($mod) {
+ $data = str_pad($data, $len + (4 - $mod), "\0");
+ }
+
+ $len = strlen($data);
+
+ $hi = 0x0000;
+ $lo = 0x0000;
+
+ for ($i = 0; $i < $len; $i += 4) {
+ $hi += (ord($data[$i]) << 8) + ord($data[$i + 1]);
+ $lo += (ord($data[$i + 2]) << 8) + ord($data[$i + 3]);
+ $hi += $lo >> 16;
+ $lo = $lo & 0xFFFF;
+ $hi = $hi & 0xFFFF;
+ }
+
+ return ($hi << 8) + $lo;
+ }
+
+ function __construct(File $font) {
+ $this->font = $font;
+ $this->f = $font->f;
+ }
+
+ function parse() {
+ $this->tag = $this->font->read(4);
+ }
+
+ function open($filename, $mode = self::modeRead) {
+ // void
+ }
+
+ function setTable(Table $font_table) {
+ $this->font_table = $font_table;
+ }
+
+ function encode($entry_offset) {
+ Font::d("\n==== $this->tag ====");
+ //Font::d("Entry offset = $entry_offset");
+
+ $data = $this->font_table;
+ $font = $this->font;
+
+ $table_offset = $font->pos();
+ $this->offset = $table_offset;
+ $table_length = $data->encode();
+
+ $font->seek($table_offset);
+ $table_data = $font->read($table_length);
+
+ $font->seek($entry_offset);
+
+ $font->write($this->tag, 4);
+ $font->writeUInt32(self::computeChecksum($table_data));
+ $font->writeUInt32($table_offset);
+ $font->writeUInt32($table_length);
+
+ Font::d("Bytes written = $table_length");
+
+ $font->seek($table_offset + $table_length);
+ }
+
+ /**
+ * @return File
+ */
+ function getFont() {
+ return $this->font;
+ }
+
+ function startRead() {
+ $this->font->seek($this->offset);
+ }
+
+ function endRead() {
+ //
+ }
+
+ function startWrite() {
+ $this->font->seek($this->offset);
+ }
+
+ function endWrite() {
+ //
+ }
+}
+
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/Table.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Table.php
new file mode 100644
index 00000000..b1271123
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Table.php
@@ -0,0 +1,93 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace FontLib\Table;
+
+use FontLib\TrueType\File;
+use FontLib\Font;
+use FontLib\BinaryStream;
+
+/**
+ * Generic font table.
+ *
+ * @package php-font-lib
+ */
+class Table extends BinaryStream {
+ /**
+ * @var DirectoryEntry
+ */
+ protected $entry;
+ protected $def = array();
+
+ public $data;
+
+ final public function __construct(DirectoryEntry $entry) {
+ $this->entry = $entry;
+ $entry->setTable($this);
+ }
+
+ /**
+ * @return File
+ */
+ public function getFont() {
+ return $this->entry->getFont();
+ }
+
+ protected function _encode() {
+ if (empty($this->data)) {
+ Font::d(" >> Table is empty");
+
+ return 0;
+ }
+
+ return $this->getFont()->pack($this->def, $this->data);
+ }
+
+ protected function _parse() {
+ $this->data = $this->getFont()->unpack($this->def);
+ }
+
+ protected function _parseRaw() {
+ $this->data = $this->getFont()->read($this->entry->length);
+ }
+
+ protected function _encodeRaw() {
+ return $this->getFont()->write($this->data, $this->entry->length);
+ }
+
+ public function toHTML() {
+ return "" . var_export($this->data, true) . "
";
+ }
+
+ final public function encode() {
+ $this->entry->startWrite();
+
+ if (false && empty($this->def)) {
+ $length = $this->_encodeRaw();
+ }
+ else {
+ $length = $this->_encode();
+ }
+
+ $this->entry->endWrite();
+
+ return $length;
+ }
+
+ final public function parse() {
+ $this->entry->startRead();
+
+ if (false && empty($this->def)) {
+ $this->_parseRaw();
+ }
+ else {
+ $this->_parse();
+ }
+
+ $this->entry->endRead();
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/cmap.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/cmap.php
new file mode 100644
index 00000000..7db77e1a
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/cmap.php
@@ -0,0 +1,298 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\Table\Type;
+use FontLib\Table\Table;
+
+/**
+ * `cmap` font table.
+ *
+ * @package php-font-lib
+ */
+class cmap extends Table {
+ private static $header_format = array(
+ "version" => self::uint16,
+ "numberSubtables" => self::uint16,
+ );
+
+ private static $subtable_header_format = array(
+ "platformID" => self::uint16,
+ "platformSpecificID" => self::uint16,
+ "offset" => self::uint32,
+ );
+
+ private static $subtable_v4_format = array(
+ "length" => self::uint16,
+ "language" => self::uint16,
+ "segCountX2" => self::uint16,
+ "searchRange" => self::uint16,
+ "entrySelector" => self::uint16,
+ "rangeShift" => self::uint16,
+ );
+
+ private static $subtable_v12_format = array(
+ "length" => self::uint32,
+ "language" => self::uint32,
+ "ngroups" => self::uint32
+ );
+
+ protected function _parse() {
+ $font = $this->getFont();
+
+ $cmap_offset = $font->pos();
+
+ $data = $font->unpack(self::$header_format);
+
+ $subtables = array();
+ for ($i = 0; $i < $data["numberSubtables"]; $i++) {
+ $subtables[] = $font->unpack(self::$subtable_header_format);
+ }
+
+ $data["subtables"] = $subtables;
+
+ foreach ($data["subtables"] as $i => &$subtable) {
+ $font->seek($cmap_offset + $subtable["offset"]);
+
+ $subtable["format"] = $font->readUInt16();
+
+ // @todo Only CMAP version 4 and 12
+ if (($subtable["format"] != 4) && ($subtable["format"] != 12)) {
+ unset($data["subtables"][$i]);
+ $data["numberSubtables"]--;
+ continue;
+ }
+
+ if ($subtable["format"] == 12) {
+
+ $font->readUInt16();
+
+ $subtable += $font->unpack(self::$subtable_v12_format);
+
+ $glyphIndexArray = array();
+ $endCodes = array();
+ $startCodes = array();
+
+ for ($p = 0; $p < $subtable['ngroups']; $p++) {
+
+ $startCode = $startCodes[] = $font->readUInt32();
+ $endCode = $endCodes[] = $font->readUInt32();
+ $startGlyphCode = $font->readUInt32();
+
+ for ($c = $startCode; $c <= $endCode; $c++) {
+ $glyphIndexArray[$c] = $startGlyphCode;
+ $startGlyphCode++;
+ }
+ }
+
+ $subtable += array(
+ "startCode" => $startCodes,
+ "endCode" => $endCodes,
+ "glyphIndexArray" => $glyphIndexArray,
+ );
+
+ }
+ else if ($subtable["format"] == 4) {
+
+ $subtable += $font->unpack(self::$subtable_v4_format);
+
+ $segCount = $subtable["segCountX2"] / 2;
+ $subtable["segCount"] = $segCount;
+
+ $endCode = $font->readUInt16Many($segCount);
+
+ $font->readUInt16(); // reservedPad
+
+ $startCode = $font->readUInt16Many($segCount);
+ $idDelta = $font->readInt16Many($segCount);
+
+ $ro_start = $font->pos();
+ $idRangeOffset = $font->readUInt16Many($segCount);
+
+ $glyphIndexArray = array();
+ for ($i = 0; $i < $segCount; $i++) {
+ $c1 = $startCode[$i];
+ $c2 = $endCode[$i];
+ $d = $idDelta[$i];
+ $ro = $idRangeOffset[$i];
+
+ if ($ro > 0) {
+ $font->seek($subtable["offset"] + 2 * $i + $ro);
+ }
+
+ for ($c = $c1; $c <= $c2; $c++) {
+ if ($ro == 0) {
+ $gid = ($c + $d) & 0xFFFF;
+ }
+ else {
+ $offset = ($c - $c1) * 2 + $ro;
+ $offset = $ro_start + 2 * $i + $offset;
+
+ $font->seek($offset);
+ $gid = $font->readUInt16();
+
+ if ($gid != 0) {
+ $gid = ($gid + $d) & 0xFFFF;
+ }
+ }
+
+ if ($gid > 0) {
+ $glyphIndexArray[$c] = $gid;
+ }
+ }
+ }
+
+ $subtable += array(
+ "endCode" => $endCode,
+ "startCode" => $startCode,
+ "idDelta" => $idDelta,
+ "idRangeOffset" => $idRangeOffset,
+ "glyphIndexArray" => $glyphIndexArray,
+ );
+ }
+ }
+
+ $this->data = $data;
+ }
+
+ function _encode() {
+ $font = $this->getFont();
+
+ $subset = $font->getSubset();
+ $glyphIndexArray = $font->getUnicodeCharMap();
+
+ $newGlyphIndexArray = array();
+ foreach ($glyphIndexArray as $code => $gid) {
+ $new_gid = array_search($gid, $subset);
+ if ($new_gid !== false) {
+ $newGlyphIndexArray[$code] = $new_gid;
+ }
+ }
+
+ ksort($newGlyphIndexArray); // Sort by char code
+
+ $segments = array();
+
+ $i = -1;
+ $prevCode = 0xFFFF;
+ $prevGid = 0xFFFF;
+
+ foreach ($newGlyphIndexArray as $code => $gid) {
+ if (
+ $prevCode + 1 != $code ||
+ $prevGid + 1 != $gid
+ ) {
+ $i++;
+ $segments[$i] = array();
+ }
+
+ $segments[$i][] = array($code, $gid);
+
+ $prevCode = $code;
+ $prevGid = $gid;
+ }
+
+ $segments[][] = array(0xFFFF, 0xFFFF);
+
+ $startCode = array();
+ $endCode = array();
+ $idDelta = array();
+
+ foreach ($segments as $codes) {
+ $start = reset($codes);
+ $end = end($codes);
+
+ $startCode[] = $start[0];
+ $endCode[] = $end[0];
+ $idDelta[] = $start[1] - $start[0];
+ }
+
+ $segCount = count($startCode);
+ $idRangeOffset = array_fill(0, $segCount, 0);
+
+ $searchRange = 1;
+ $entrySelector = 0;
+ while ($searchRange * 2 <= $segCount) {
+ $searchRange *= 2;
+ $entrySelector++;
+ }
+ $searchRange *= 2;
+ $rangeShift = $segCount * 2 - $searchRange;
+
+ $subtables = array(
+ array(
+ // header
+ "platformID" => 3, // Unicode
+ "platformSpecificID" => 1,
+ "offset" => null,
+
+ // subtable
+ "format" => 4,
+ "length" => null,
+ "language" => 0,
+ "segCount" => $segCount,
+ "segCountX2" => $segCount * 2,
+ "searchRange" => $searchRange,
+ "entrySelector" => $entrySelector,
+ "rangeShift" => $rangeShift,
+ "startCode" => $startCode,
+ "endCode" => $endCode,
+ "idDelta" => $idDelta,
+ "idRangeOffset" => $idRangeOffset,
+ "glyphIndexArray" => $newGlyphIndexArray,
+ )
+ );
+
+ $data = array(
+ "version" => 0,
+ "numberSubtables" => count($subtables),
+ "subtables" => $subtables,
+ );
+
+ $length = $font->pack(self::$header_format, $data);
+
+ $subtable_headers_size = $data["numberSubtables"] * 8; // size of self::$subtable_header_format
+ $subtable_headers_offset = $font->pos();
+
+ $length += $font->write(str_repeat("\0", $subtable_headers_size), $subtable_headers_size);
+
+ // write subtables data
+ foreach ($data["subtables"] as $i => $subtable) {
+ $length_before = $length;
+ $data["subtables"][$i]["offset"] = $length;
+
+ $length += $font->writeUInt16($subtable["format"]);
+
+ $before_subheader = $font->pos();
+ $length += $font->pack(self::$subtable_v4_format, $subtable);
+
+ $segCount = $subtable["segCount"];
+ $length += $font->w(array(self::uint16, $segCount), $subtable["endCode"]);
+ $length += $font->writeUInt16(0); // reservedPad
+ $length += $font->w(array(self::uint16, $segCount), $subtable["startCode"]);
+ $length += $font->w(array(self::int16, $segCount), $subtable["idDelta"]);
+ $length += $font->w(array(self::uint16, $segCount), $subtable["idRangeOffset"]);
+ $length += $font->w(array(self::uint16, $segCount), array_values($subtable["glyphIndexArray"]));
+
+ $after_subtable = $font->pos();
+
+ $subtable["length"] = $length - $length_before;
+ $font->seek($before_subheader);
+ $length += $font->pack(self::$subtable_v4_format, $subtable);
+
+ $font->seek($after_subtable);
+ }
+
+ // write subtables headers
+ $font->seek($subtable_headers_offset);
+ foreach ($data["subtables"] as $subtable) {
+ $font->pack(self::$subtable_header_format, $subtable);
+ }
+
+ return $length;
+ }
+}
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/glyf.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/glyf.php
new file mode 100644
index 00000000..1fbec3fd
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/glyf.php
@@ -0,0 +1,154 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\Table\Type;
+
+use FontLib\Table\Table;
+use FontLib\Glyph\Outline;
+use FontLib\Glyph\OutlineSimple;
+
+/**
+ * `glyf` font table.
+ *
+ * @package php-font-lib
+ * @property Outline[] $data
+ */
+class glyf extends Table {
+ protected function _parse() {
+ $font = $this->getFont();
+ $offset = $font->pos();
+
+ $loca = $font->getData("loca");
+ $real_loca = array_slice($loca, 0, -1); // Not the last dummy loca entry
+
+ $data = array();
+
+ foreach ($real_loca as $gid => $location) {
+ $_offset = $offset + $loca[$gid];
+ $_size = $loca[$gid + 1] - $loca[$gid];
+ $data[$gid] = Outline::init($this, $_offset, $_size, $font);
+ }
+
+ $this->data = $data;
+ }
+
+ public function getGlyphIDs($gids = array()) {
+ $glyphIDs = array();
+
+ foreach ($gids as $_gid) {
+ $_glyph = $this->data[$_gid];
+ $glyphIDs = array_merge($glyphIDs, $_glyph->getGlyphIDs());
+ }
+
+ return array_unique(array_merge($gids, $glyphIDs));
+ }
+
+ public function toHTML() {
+ $max = 160;
+ $font = $this->getFont();
+
+ $head = $font->getData("head");
+ $head_json = json_encode($head);
+
+ $os2 = $font->getData("OS/2");
+ $os2_json = json_encode($os2);
+
+ $hmtx = $font->getData("hmtx");
+ $hmtx_json = json_encode($hmtx);
+
+ $names = $font->getData("post", "names");
+ $glyphIndexArray = array_flip($font->getUnicodeCharMap());
+
+ $width = (abs($head["xMin"]) + $head["xMax"]);
+ $height = (abs($head["yMin"]) + $head["yMax"]);
+
+ $ratio = 1;
+ if ($width > $max || $height > $max) {
+ $ratio = max($width, $height) / $max;
+ $width = round($width / $ratio);
+ $height = round($height / $ratio);
+ }
+
+ $n = 500;
+
+ $s = "" . "Only the first $n simple glyphs are shown (" . count($this->data) . " total)
+ Simple glyph
+ Composite glyph
+ Zoom:
+
+ ";
+
+ foreach ($this->data as $g => $glyph) {
+ if ($n-- <= 0) {
+ break;
+ }
+
+ $glyph->parseData();
+
+ $shape = array(
+ "SVGContours" => $glyph->getSVGContours(),
+ "xMin" => $glyph->xMin,
+ "yMin" => $glyph->yMin,
+ "xMax" => $glyph->xMax,
+ "yMax" => $glyph->yMax,
+ );
+ $shape_json = json_encode($shape);
+
+ $type = ($glyph instanceof OutlineSimple ? "simple" : "composite");
+ $char = isset($glyphIndexArray[$g]) ? $glyphIndexArray[$g] : 0;
+ $name = isset($names[$g]) ? $names[$g] : sprintf("uni%04x", $char);
+ $char = $char ? "{$glyphIndexArray[$g]};" : "";
+
+ $s .= "
+ $g
+ $char
+ $name
+ ";
+
+ if ($type == "composite") {
+ foreach ($glyph->getGlyphIDs() as $_id) {
+ $s .= "$_id ";
+ }
+ }
+
+ $s .= "
+
+
+ ";
+ }
+
+ return $s;
+ }
+
+
+ protected function _encode() {
+ $font = $this->getFont();
+ $subset = $font->getSubset();
+ $data = $this->data;
+
+ $loca = array();
+
+ $length = 0;
+ foreach ($subset as $gid) {
+ $loca[] = $length;
+ $length += $data[$gid]->encode();
+ }
+
+ $loca[] = $length; // dummy loca
+ $font->getTableObject("loca")->data = $loca;
+
+ return $length;
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/head.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/head.php
new file mode 100644
index 00000000..6349f145
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/head.php
@@ -0,0 +1,46 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\Table\Type;
+use FontLib\Table\Table;
+use Exception;
+
+/**
+ * `head` font table.
+ *
+ * @package php-font-lib
+ */
+class head extends Table {
+ protected $def = array(
+ "tableVersion" => self::Fixed,
+ "fontRevision" => self::Fixed,
+ "checkSumAdjustment" => self::uint32,
+ "magicNumber" => self::uint32,
+ "flags" => self::uint16,
+ "unitsPerEm" => self::uint16,
+ "created" => self::longDateTime,
+ "modified" => self::longDateTime,
+ "xMin" => self::FWord,
+ "yMin" => self::FWord,
+ "xMax" => self::FWord,
+ "yMax" => self::FWord,
+ "macStyle" => self::uint16,
+ "lowestRecPPEM" => self::uint16,
+ "fontDirectionHint" => self::int16,
+ "indexToLocFormat" => self::int16,
+ "glyphDataFormat" => self::int16,
+ );
+
+ protected function _parse() {
+ parent::_parse();
+
+ if ($this->data["magicNumber"] != 0x5F0F3CF5) {
+ throw new Exception("Incorrect magic number (" . dechex($this->data["magicNumber"]) . ")");
+ }
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/hhea.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/hhea.php
new file mode 100644
index 00000000..dc60a14b
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/hhea.php
@@ -0,0 +1,44 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\Table\Type;
+use FontLib\Table\Table;
+
+/**
+ * `hhea` font table.
+ *
+ * @package php-font-lib
+ */
+class hhea extends Table {
+ protected $def = array(
+ "version" => self::Fixed,
+ "ascent" => self::FWord,
+ "descent" => self::FWord,
+ "lineGap" => self::FWord,
+ "advanceWidthMax" => self::uFWord,
+ "minLeftSideBearing" => self::FWord,
+ "minRightSideBearing" => self::FWord,
+ "xMaxExtent" => self::FWord,
+ "caretSlopeRise" => self::int16,
+ "caretSlopeRun" => self::int16,
+ "caretOffset" => self::FWord,
+ self::int16,
+ self::int16,
+ self::int16,
+ self::int16,
+ "metricDataFormat" => self::int16,
+ "numOfLongHorMetrics" => self::uint16,
+ );
+
+ function _encode() {
+ $font = $this->getFont();
+ $this->data["numOfLongHorMetrics"] = count($font->getSubset());
+
+ return parent::_encode();
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/hmtx.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/hmtx.php
new file mode 100644
index 00000000..76e3307e
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/hmtx.php
@@ -0,0 +1,59 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\Table\Type;
+use FontLib\Table\Table;
+
+/**
+ * `hmtx` font table.
+ *
+ * @package php-font-lib
+ */
+class hmtx extends Table {
+ protected function _parse() {
+ $font = $this->getFont();
+ $offset = $font->pos();
+
+ $numOfLongHorMetrics = $font->getData("hhea", "numOfLongHorMetrics");
+ $numGlyphs = $font->getData("maxp", "numGlyphs");
+
+ $font->seek($offset);
+
+ $data = array();
+ $metrics = $font->readUInt16Many($numOfLongHorMetrics * 2);
+ for ($gid = 0, $mid = 0; $gid < $numOfLongHorMetrics; $gid++) {
+ $advanceWidth = isset($metrics[$mid]) ? $metrics[$mid] : 0;
+ $mid += 1;
+ $leftSideBearing = isset($metrics[$mid]) ? $metrics[$mid] : 0;
+ $mid += 1;
+ $data[$gid] = array($advanceWidth, $leftSideBearing);
+ }
+
+ if ($numOfLongHorMetrics < $numGlyphs) {
+ $lastWidth = end($data);
+ $data = array_pad($data, $numGlyphs, $lastWidth);
+ }
+
+ $this->data = $data;
+ }
+
+ protected function _encode() {
+ $font = $this->getFont();
+ $subset = $font->getSubset();
+ $data = $this->data;
+
+ $length = 0;
+
+ foreach ($subset as $gid) {
+ $length += $font->writeUInt16($data[$gid][0]);
+ $length += $font->writeUInt16($data[$gid][1]);
+ }
+
+ return $length;
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/kern.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/kern.php
new file mode 100644
index 00000000..98759464
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/kern.php
@@ -0,0 +1,80 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\Table\Type;
+use FontLib\Table\Table;
+
+/**
+ * `kern` font table.
+ *
+ * @package php-font-lib
+ */
+class kern extends Table {
+ protected function _parse() {
+ $font = $this->getFont();
+
+ $data = $font->unpack(array(
+ "version" => self::uint16,
+ "nTables" => self::uint16,
+
+ // only the first subtable will be parsed
+ "subtableVersion" => self::uint16,
+ "length" => self::uint16,
+ "coverage" => self::uint16,
+ ));
+
+ $data["format"] = ($data["coverage"] >> 8);
+
+ $subtable = array();
+
+ switch ($data["format"]) {
+ case 0:
+ $subtable = $font->unpack(array(
+ "nPairs" => self::uint16,
+ "searchRange" => self::uint16,
+ "entrySelector" => self::uint16,
+ "rangeShift" => self::uint16,
+ ));
+
+ $pairs = array();
+ $tree = array();
+
+ $values = $font->readUInt16Many($subtable["nPairs"] * 3);
+ for ($i = 0, $idx = 0; $i < $subtable["nPairs"]; $i++) {
+ $left = $values[$idx++];
+ $right = $values[$idx++];
+ $value = $values[$idx++];
+
+ if ($value >= 0x8000) {
+ $value -= 0x10000;
+ }
+
+ $pairs[] = array(
+ "left" => $left,
+ "right" => $right,
+ "value" => $value,
+ );
+
+ $tree[$left][$right] = $value;
+ }
+
+ //$subtable["pairs"] = $pairs;
+ $subtable["tree"] = $tree;
+ break;
+
+ case 1:
+ case 2:
+ case 3:
+ break;
+ }
+
+ $data["subtable"] = $subtable;
+
+ $this->data = $data;
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/loca.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/loca.php
new file mode 100644
index 00000000..cbc2a200
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/loca.php
@@ -0,0 +1,80 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\Table\Type;
+use FontLib\Table\Table;
+
+/**
+ * `loca` font table.
+ *
+ * @package php-font-lib
+ */
+class loca extends Table {
+ protected function _parse() {
+ $font = $this->getFont();
+ $offset = $font->pos();
+
+ $indexToLocFormat = $font->getData("head", "indexToLocFormat");
+ $numGlyphs = $font->getData("maxp", "numGlyphs");
+
+ $font->seek($offset);
+
+ $data = array();
+
+ // 2 bytes
+ if ($indexToLocFormat == 0) {
+ $d = $font->read(($numGlyphs + 1) * 2);
+ $loc = unpack("n*", $d);
+
+ for ($i = 0; $i <= $numGlyphs; $i++) {
+ $data[] = isset($loc[$i + 1]) ? $loc[$i + 1] * 2 : 0;
+ }
+ }
+
+ // 4 bytes
+ else {
+ if ($indexToLocFormat == 1) {
+ $d = $font->read(($numGlyphs + 1) * 4);
+ $loc = unpack("N*", $d);
+
+ for ($i = 0; $i <= $numGlyphs; $i++) {
+ $data[] = isset($loc[$i + 1]) ? $loc[$i + 1] : 0;
+ }
+ }
+ }
+
+ $this->data = $data;
+ }
+
+ function _encode() {
+ $font = $this->getFont();
+ $data = $this->data;
+
+ $indexToLocFormat = $font->getData("head", "indexToLocFormat");
+ $numGlyphs = $font->getData("maxp", "numGlyphs");
+ $length = 0;
+
+ // 2 bytes
+ if ($indexToLocFormat == 0) {
+ for ($i = 0; $i <= $numGlyphs; $i++) {
+ $length += $font->writeUInt16($data[$i] / 2);
+ }
+ }
+
+ // 4 bytes
+ else {
+ if ($indexToLocFormat == 1) {
+ for ($i = 0; $i <= $numGlyphs; $i++) {
+ $length += $font->writeUInt32($data[$i]);
+ }
+ }
+ }
+
+ return $length;
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/maxp.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/maxp.php
new file mode 100644
index 00000000..b4ebae03
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/maxp.php
@@ -0,0 +1,42 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\Table\Type;
+use FontLib\Table\Table;
+
+/**
+ * `maxp` font table.
+ *
+ * @package php-font-lib
+ */
+class maxp extends Table {
+ protected $def = array(
+ "version" => self::Fixed,
+ "numGlyphs" => self::uint16,
+ "maxPoints" => self::uint16,
+ "maxContours" => self::uint16,
+ "maxComponentPoints" => self::uint16,
+ "maxComponentContours" => self::uint16,
+ "maxZones" => self::uint16,
+ "maxTwilightPoints" => self::uint16,
+ "maxStorage" => self::uint16,
+ "maxFunctionDefs" => self::uint16,
+ "maxInstructionDefs" => self::uint16,
+ "maxStackElements" => self::uint16,
+ "maxSizeOfInstructions" => self::uint16,
+ "maxComponentElements" => self::uint16,
+ "maxComponentDepth" => self::uint16,
+ );
+
+ function _encode() {
+ $font = $this->getFont();
+ $this->data["numGlyphs"] = count($font->getSubset());
+
+ return parent::_encode();
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/name.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/name.php
new file mode 100644
index 00000000..794824d3
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/name.php
@@ -0,0 +1,193 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\Table\Type;
+
+use FontLib\Table\Table;
+use FontLib\Font;
+
+/**
+ * `name` font table.
+ *
+ * @package php-font-lib
+ */
+class name extends Table {
+ private static $header_format = array(
+ "format" => self::uint16,
+ "count" => self::uint16,
+ "stringOffset" => self::uint16,
+ );
+
+ const NAME_COPYRIGHT = 0;
+ const NAME_NAME = 1;
+ const NAME_SUBFAMILY = 2;
+ const NAME_SUBFAMILY_ID = 3;
+ const NAME_FULL_NAME = 4;
+ const NAME_VERSION = 5;
+ const NAME_POSTSCRIPT_NAME = 6;
+ const NAME_TRADEMARK = 7;
+ const NAME_MANUFACTURER = 8;
+ const NAME_DESIGNER = 9;
+ const NAME_DESCRIPTION = 10;
+ const NAME_VENDOR_URL = 11;
+ const NAME_DESIGNER_URL = 12;
+ const NAME_LICENSE = 13;
+ const NAME_LICENSE_URL = 14;
+ const NAME_PREFERRE_FAMILY = 16;
+ const NAME_PREFERRE_SUBFAMILY = 17;
+ const NAME_COMPAT_FULL_NAME = 18;
+ const NAME_SAMPLE_TEXT = 19;
+
+ static $nameIdCodes = array(
+ 0 => "Copyright",
+ 1 => "FontName",
+ 2 => "FontSubfamily",
+ 3 => "UniqueID",
+ 4 => "FullName",
+ 5 => "Version",
+ 6 => "PostScriptName",
+ 7 => "Trademark",
+ 8 => "Manufacturer",
+ 9 => "Designer",
+ 10 => "Description",
+ 11 => "FontVendorURL",
+ 12 => "FontDesignerURL",
+ 13 => "LicenseDescription",
+ 14 => "LicenseURL",
+ // 15
+ 16 => "PreferredFamily",
+ 17 => "PreferredSubfamily",
+ 18 => "CompatibleFullName",
+ 19 => "SampleText",
+ );
+
+ static $platforms = array(
+ 0 => "Unicode",
+ 1 => "Macintosh",
+ // 2 => Reserved
+ 3 => "Microsoft",
+ );
+
+ static $platformSpecific = array(
+ // Unicode
+ 0 => array(
+ 0 => "Default semantics",
+ 1 => "Version 1.1 semantics",
+ 2 => "ISO 10646 1993 semantics (deprecated)",
+ 3 => "Unicode 2.0 or later semantics",
+ ),
+
+ // Macintosh
+ 1 => array(
+ 0 => "Roman",
+ 1 => "Japanese",
+ 2 => "Traditional Chinese",
+ 3 => "Korean",
+ 4 => "Arabic",
+ 5 => "Hebrew",
+ 6 => "Greek",
+ 7 => "Russian",
+ 8 => "RSymbol",
+ 9 => "Devanagari",
+ 10 => "Gurmukhi",
+ 11 => "Gujarati",
+ 12 => "Oriya",
+ 13 => "Bengali",
+ 14 => "Tamil",
+ 15 => "Telugu",
+ 16 => "Kannada",
+ 17 => "Malayalam",
+ 18 => "Sinhalese",
+ 19 => "Burmese",
+ 20 => "Khmer",
+ 21 => "Thai",
+ 22 => "Laotian",
+ 23 => "Georgian",
+ 24 => "Armenian",
+ 25 => "Simplified Chinese",
+ 26 => "Tibetan",
+ 27 => "Mongolian",
+ 28 => "Geez",
+ 29 => "Slavic",
+ 30 => "Vietnamese",
+ 31 => "Sindhi",
+ ),
+
+ // Microsoft
+ 3 => array(
+ 0 => "Symbol",
+ 1 => "Unicode BMP (UCS-2)",
+ 2 => "ShiftJIS",
+ 3 => "PRC",
+ 4 => "Big5",
+ 5 => "Wansung",
+ 6 => "Johab",
+ // 7 => Reserved
+ // 8 => Reserved
+ // 9 => Reserved
+ 10 => "Unicode UCS-4",
+ ),
+ );
+
+ protected function _parse() {
+ $font = $this->getFont();
+
+ $tableOffset = $font->pos();
+
+ $data = $font->unpack(self::$header_format);
+
+ $records = array();
+ for ($i = 0; $i < $data["count"]; $i++) {
+ $record = new nameRecord();
+ $record_data = $font->unpack(nameRecord::$format);
+ $record->map($record_data);
+
+ $records[] = $record;
+ }
+
+ $names = array();
+ foreach ($records as $record) {
+ $font->seek($tableOffset + $data["stringOffset"] + $record->offset);
+ $s = $font->read($record->length);
+ $record->string = Font::UTF16ToUTF8($s);
+ $names[$record->nameID] = $record;
+ }
+
+ $data["records"] = $names;
+
+ $this->data = $data;
+ }
+
+ protected function _encode() {
+ $font = $this->getFont();
+
+ /** @var nameRecord[] $records */
+ $records = $this->data["records"];
+ $count_records = count($records);
+
+ $this->data["count"] = $count_records;
+ $this->data["stringOffset"] = 6 + $count_records * 12; // 6 => uint16 * 3, 12 => sizeof self::$record_format
+
+ $length = $font->pack(self::$header_format, $this->data);
+
+ $offset = 0;
+ foreach ($records as $record) {
+ $record->length = mb_strlen($record->getUTF16(), "8bit");
+ $record->offset = $offset;
+ $offset += $record->length;
+ $length += $font->pack(nameRecord::$format, (array)$record);
+ }
+
+ foreach ($records as $record) {
+ $str = $record->getUTF16();
+ $length += $font->write($str, mb_strlen($str, "8bit"));
+ }
+
+ return $length;
+ }
+}
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/nameRecord.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/nameRecord.php
new file mode 100644
index 00000000..2073c20d
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/nameRecord.php
@@ -0,0 +1,53 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace FontLib\Table\Type;
+
+use FontLib\Font;
+use FontLib\BinaryStream;
+
+/**
+ * Font table name record.
+ *
+ * @package php-font-lib
+ */
+class nameRecord extends BinaryStream {
+ public $platformID;
+ public $platformSpecificID;
+ public $languageID;
+ public $nameID;
+ public $length;
+ public $offset;
+ public $string;
+
+ public static $format = array(
+ "platformID" => self::uint16,
+ "platformSpecificID" => self::uint16,
+ "languageID" => self::uint16,
+ "nameID" => self::uint16,
+ "length" => self::uint16,
+ "offset" => self::uint16,
+ );
+
+ public function map($data) {
+ foreach ($data as $key => $value) {
+ $this->$key = $value;
+ }
+ }
+
+ public function getUTF8() {
+ return $this->string;
+ }
+
+ public function getUTF16() {
+ return Font::UTF8ToUTF16($this->string);
+ }
+
+ function __toString() {
+ return $this->string;
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/os2.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/os2.php
new file mode 100644
index 00000000..19a3e21f
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/os2.php
@@ -0,0 +1,47 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\Table\Type;
+use FontLib\Table\Table;
+
+/**
+ * `OS/2` font table.
+ *
+ * @package php-font-lib
+ */
+class os2 extends Table {
+ protected $def = array(
+ "version" => self::uint16,
+ "xAvgCharWidth" => self::int16,
+ "usWeightClass" => self::uint16,
+ "usWidthClass" => self::uint16,
+ "fsType" => self::int16,
+ "ySubscriptXSize" => self::int16,
+ "ySubscriptYSize" => self::int16,
+ "ySubscriptXOffset" => self::int16,
+ "ySubscriptYOffset" => self::int16,
+ "ySuperscriptXSize" => self::int16,
+ "ySuperscriptYSize" => self::int16,
+ "ySuperscriptXOffset" => self::int16,
+ "ySuperscriptYOffset" => self::int16,
+ "yStrikeoutSize" => self::int16,
+ "yStrikeoutPosition" => self::int16,
+ "sFamilyClass" => self::int16,
+ "panose" => array(self::uint8, 10),
+ "ulCharRange" => array(self::uint32, 4),
+ "achVendID" => array(self::char, 4),
+ "fsSelection" => self::uint16,
+ "fsFirstCharIndex" => self::uint16,
+ "fsLastCharIndex" => self::uint16,
+ "typoAscender" => self::int16,
+ "typoDescender" => self::int16,
+ "typoLineGap" => self::int16,
+ "winAscent" => self::int16,
+ "winDescent" => self::int16,
+ );
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/post.php b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/post.php
new file mode 100644
index 00000000..ec5806b7
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/Table/Type/post.php
@@ -0,0 +1,141 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\Table\Type;
+use FontLib\Table\Table;
+use FontLib\TrueType\File;
+
+/**
+ * `post` font table.
+ *
+ * @package php-font-lib
+ */
+class post extends Table {
+ protected $def = array(
+ "format" => self::Fixed,
+ "italicAngle" => self::Fixed,
+ "underlinePosition" => self::FWord,
+ "underlineThickness" => self::FWord,
+ "isFixedPitch" => self::uint32,
+ "minMemType42" => self::uint32,
+ "maxMemType42" => self::uint32,
+ "minMemType1" => self::uint32,
+ "maxMemType1" => self::uint32,
+ );
+
+ protected function _parse() {
+ $font = $this->getFont();
+ $data = $font->unpack($this->def);
+
+ $names = array();
+
+ switch ($data["format"]) {
+ case 1:
+ $names = File::$macCharNames;
+ break;
+
+ case 2:
+ $data["numberOfGlyphs"] = $font->readUInt16();
+
+ $glyphNameIndex = $font->readUInt16Many($data["numberOfGlyphs"]);
+
+ $data["glyphNameIndex"] = $glyphNameIndex;
+
+ $namesPascal = array();
+ for ($i = 0; $i < $data["numberOfGlyphs"]; $i++) {
+ $len = $font->readUInt8();
+ $namesPascal[] = $font->read($len);
+ }
+
+ foreach ($glyphNameIndex as $g => $index) {
+ if ($index < 258) {
+ $names[$g] = File::$macCharNames[$index];
+ }
+ else {
+ $names[$g] = $namesPascal[$index - 258];
+ }
+ }
+
+ break;
+
+ case 2.5:
+ // TODO
+ break;
+
+ case 3:
+ // nothing
+ break;
+
+ case 4:
+ // TODO
+ break;
+ }
+
+ $data["names"] = $names;
+
+ $this->data = $data;
+ }
+
+ function _encode() {
+ $font = $this->getFont();
+ $data = $this->data;
+ $data["format"] = 3;
+
+ $length = $font->pack($this->def, $data);
+
+ return $length;
+ /*
+ $subset = $font->getSubset();
+
+ switch($data["format"]) {
+ case 1:
+ // nothing to do
+ break;
+
+ case 2:
+ $old_names = $data["names"];
+
+ $glyphNameIndex = range(0, count($subset));
+
+ $names = array();
+ foreach($subset as $gid) {
+ $names[] = $data["names"][$data["glyphNameIndex"][$gid]];
+ }
+
+ $numberOfGlyphs = count($names);
+ $length += $font->writeUInt16($numberOfGlyphs);
+
+ foreach($glyphNameIndex as $gni) {
+ $length += $font->writeUInt16($gni);
+ }
+
+ //$names = array_slice($names, 257);
+ foreach($names as $name) {
+ $len = strlen($name);
+ $length += $font->writeUInt8($len);
+ $length += $font->write($name, $len);
+ }
+
+ break;
+
+ case 2.5:
+ // TODO
+ break;
+
+ case 3:
+ // nothing
+ break;
+
+ case 4:
+ // TODO
+ break;
+ }
+
+ return $length;*/
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/TrueType/Collection.php b/application/third_party/dompdf/lib/php-font-lib/classes/TrueType/Collection.php
new file mode 100644
index 00000000..460ef4da
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/TrueType/Collection.php
@@ -0,0 +1,100 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\TrueType;
+
+use Countable;
+use FontLib\BinaryStream;
+use Iterator;
+use OutOfBoundsException;
+
+/**
+ * TrueType collection font file.
+ *
+ * @package php-font-lib
+ */
+class Collection extends BinaryStream implements Iterator, Countable {
+ /**
+ * Current iterator position.
+ *
+ * @var integer
+ */
+ private $position = 0;
+
+ protected $collectionOffsets = array();
+ protected $collection = array();
+ protected $version;
+ protected $numFonts;
+
+ function parse() {
+ if (isset($this->numFonts)) {
+ return;
+ }
+
+ $this->read(4); // tag name
+
+ $this->version = $this->readFixed();
+ $this->numFonts = $this->readUInt32();
+
+ for ($i = 0; $i < $this->numFonts; $i++) {
+ $this->collectionOffsets[] = $this->readUInt32();
+ }
+ }
+
+ /**
+ * @param int $fontId
+ *
+ * @throws OutOfBoundsException
+ * @return File
+ */
+ function getFont($fontId) {
+ $this->parse();
+
+ if (!isset($this->collectionOffsets[$fontId])) {
+ throw new OutOfBoundsException();
+ }
+
+ if (isset($this->collection[$fontId])) {
+ return $this->collection[$fontId];
+ }
+
+ $font = new File();
+ $font->f = $this->f;
+ $font->setTableOffset($this->collectionOffsets[$fontId]);
+
+ return $this->collection[$fontId] = $font;
+ }
+
+ function current() {
+ return $this->getFont($this->position);
+ }
+
+ function key() {
+ return $this->position;
+ }
+
+ function next() {
+ return ++$this->position;
+ }
+
+ function rewind() {
+ $this->position = 0;
+ }
+
+ function valid() {
+ $this->parse();
+
+ return isset($this->collectionOffsets[$this->position]);
+ }
+
+ function count() {
+ $this->parse();
+
+ return $this->numFonts;
+ }
+}
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/TrueType/File.php b/application/third_party/dompdf/lib/php-font-lib/classes/TrueType/File.php
new file mode 100644
index 00000000..b61da0f2
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/TrueType/File.php
@@ -0,0 +1,471 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\TrueType;
+
+use FontLib\AdobeFontMetrics;
+use FontLib\Font;
+use FontLib\BinaryStream;
+use FontLib\Table\Table;
+use FontLib\Table\DirectoryEntry;
+use FontLib\Table\Type\glyf;
+use FontLib\Table\Type\name;
+use FontLib\Table\Type\nameRecord;
+
+/**
+ * TrueType font file.
+ *
+ * @package php-font-lib
+ */
+class File extends BinaryStream {
+ /**
+ * @var Header
+ */
+ public $header = array();
+
+ private $tableOffset = 0; // Used for TTC
+
+ private static $raw = false;
+
+ protected $directory = array();
+ protected $data = array();
+
+ protected $glyph_subset = array();
+
+ public $glyph_all = array();
+
+ static $macCharNames = array(
+ ".notdef", ".null", "CR",
+ "space", "exclam", "quotedbl", "numbersign",
+ "dollar", "percent", "ampersand", "quotesingle",
+ "parenleft", "parenright", "asterisk", "plus",
+ "comma", "hyphen", "period", "slash",
+ "zero", "one", "two", "three",
+ "four", "five", "six", "seven",
+ "eight", "nine", "colon", "semicolon",
+ "less", "equal", "greater", "question",
+ "at", "A", "B", "C", "D", "E", "F", "G",
+ "H", "I", "J", "K", "L", "M", "N", "O",
+ "P", "Q", "R", "S", "T", "U", "V", "W",
+ "X", "Y", "Z", "bracketleft",
+ "backslash", "bracketright", "asciicircum", "underscore",
+ "grave", "a", "b", "c", "d", "e", "f", "g",
+ "h", "i", "j", "k", "l", "m", "n", "o",
+ "p", "q", "r", "s", "t", "u", "v", "w",
+ "x", "y", "z", "braceleft",
+ "bar", "braceright", "asciitilde", "Adieresis",
+ "Aring", "Ccedilla", "Eacute", "Ntilde",
+ "Odieresis", "Udieresis", "aacute", "agrave",
+ "acircumflex", "adieresis", "atilde", "aring",
+ "ccedilla", "eacute", "egrave", "ecircumflex",
+ "edieresis", "iacute", "igrave", "icircumflex",
+ "idieresis", "ntilde", "oacute", "ograve",
+ "ocircumflex", "odieresis", "otilde", "uacute",
+ "ugrave", "ucircumflex", "udieresis", "dagger",
+ "degree", "cent", "sterling", "section",
+ "bullet", "paragraph", "germandbls", "registered",
+ "copyright", "trademark", "acute", "dieresis",
+ "notequal", "AE", "Oslash", "infinity",
+ "plusminus", "lessequal", "greaterequal", "yen",
+ "mu", "partialdiff", "summation", "product",
+ "pi", "integral", "ordfeminine", "ordmasculine",
+ "Omega", "ae", "oslash", "questiondown",
+ "exclamdown", "logicalnot", "radical", "florin",
+ "approxequal", "increment", "guillemotleft", "guillemotright",
+ "ellipsis", "nbspace", "Agrave", "Atilde",
+ "Otilde", "OE", "oe", "endash",
+ "emdash", "quotedblleft", "quotedblright", "quoteleft",
+ "quoteright", "divide", "lozenge", "ydieresis",
+ "Ydieresis", "fraction", "currency", "guilsinglleft",
+ "guilsinglright", "fi", "fl", "daggerdbl",
+ "periodcentered", "quotesinglbase", "quotedblbase", "perthousand",
+ "Acircumflex", "Ecircumflex", "Aacute", "Edieresis",
+ "Egrave", "Iacute", "Icircumflex", "Idieresis",
+ "Igrave", "Oacute", "Ocircumflex", "applelogo",
+ "Ograve", "Uacute", "Ucircumflex", "Ugrave",
+ "dotlessi", "circumflex", "tilde", "macron",
+ "breve", "dotaccent", "ring", "cedilla",
+ "hungarumlaut", "ogonek", "caron", "Lslash",
+ "lslash", "Scaron", "scaron", "Zcaron",
+ "zcaron", "brokenbar", "Eth", "eth",
+ "Yacute", "yacute", "Thorn", "thorn",
+ "minus", "multiply", "onesuperior", "twosuperior",
+ "threesuperior", "onehalf", "onequarter", "threequarters",
+ "franc", "Gbreve", "gbreve", "Idot",
+ "Scedilla", "scedilla", "Cacute", "cacute",
+ "Ccaron", "ccaron", "dmacron"
+ );
+
+ function getTable() {
+ $this->parseTableEntries();
+
+ return $this->directory;
+ }
+
+ function setTableOffset($offset) {
+ $this->tableOffset = $offset;
+ }
+
+ function parse() {
+ $this->parseTableEntries();
+
+ $this->data = array();
+
+ foreach ($this->directory as $tag => $table) {
+ if (empty($this->data[$tag])) {
+ $this->readTable($tag);
+ }
+ }
+ }
+
+ function utf8toUnicode($str) {
+ $len = strlen($str);
+ $out = array();
+
+ for ($i = 0; $i < $len; $i++) {
+ $uni = -1;
+ $h = ord($str[$i]);
+
+ if ($h <= 0x7F) {
+ $uni = $h;
+ }
+ elseif ($h >= 0xC2) {
+ if (($h <= 0xDF) && ($i < $len - 1)) {
+ $uni = ($h & 0x1F) << 6 | (ord($str[++$i]) & 0x3F);
+ }
+ elseif (($h <= 0xEF) && ($i < $len - 2)) {
+ $uni = ($h & 0x0F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
+ }
+ elseif (($h <= 0xF4) && ($i < $len - 3)) {
+ $uni = ($h & 0x0F) << 18 | (ord($str[++$i]) & 0x3F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
+ }
+ }
+
+ if ($uni >= 0) {
+ $out[] = $uni;
+ }
+ }
+
+ return $out;
+ }
+
+ function getUnicodeCharMap() {
+ $subtable = null;
+ foreach ($this->getData("cmap", "subtables") as $_subtable) {
+ if ($_subtable["platformID"] == 0 || $_subtable["platformID"] == 3 && $_subtable["platformSpecificID"] == 1) {
+ $subtable = $_subtable;
+ break;
+ }
+ }
+
+ if ($subtable) {
+ return $subtable["glyphIndexArray"];
+ }
+
+ return null;
+ }
+
+ function setSubset($subset) {
+ if (!is_array($subset)) {
+ $subset = $this->utf8toUnicode($subset);
+ }
+
+ $subset = array_unique($subset);
+
+ $glyphIndexArray = $this->getUnicodeCharMap();
+
+ if (!$glyphIndexArray) {
+ return;
+ }
+
+ $gids = array(
+ 0, // .notdef
+ 1, // .null
+ );
+
+ foreach ($subset as $code) {
+ if (!isset($glyphIndexArray[$code])) {
+ continue;
+ }
+
+ $gid = $glyphIndexArray[$code];
+ $gids[$gid] = $gid;
+ }
+
+ /** @var glyf $glyf */
+ $glyf = $this->getTableObject("glyf");
+ $gids = $glyf->getGlyphIDs($gids);
+
+ sort($gids);
+
+ $this->glyph_subset = $gids;
+ $this->glyph_all = array_values($glyphIndexArray); // FIXME
+ }
+
+ function getSubset() {
+ if (empty($this->glyph_subset)) {
+ return $this->glyph_all;
+ }
+
+ return $this->glyph_subset;
+ }
+
+ function encode($tags = array()) {
+ if (!self::$raw) {
+ $tags = array_merge(array("head", "hhea", "cmap", "hmtx", "maxp", "glyf", "loca", "name", "post"), $tags);
+ }
+ else {
+ $tags = array_keys($this->directory);
+ }
+
+ $num_tables = count($tags);
+ $n = 16; // @todo
+
+ Font::d("Tables : " . implode(", ", $tags));
+
+ /** @var DirectoryEntry[] $entries */
+ $entries = array();
+ foreach ($tags as $tag) {
+ if (!isset($this->directory[$tag])) {
+ Font::d(" >> '$tag' table doesn't exist");
+ continue;
+ }
+
+ $entries[$tag] = $this->directory[$tag];
+ }
+
+ $this->header->data["numTables"] = $num_tables;
+ $this->header->encode();
+
+ $directory_offset = $this->pos();
+ $offset = $directory_offset + $num_tables * $n;
+ $this->seek($offset);
+
+ $i = 0;
+ foreach ($entries as $entry) {
+ $entry->encode($directory_offset + $i * $n);
+ $i++;
+ }
+ }
+
+ function parseHeader() {
+ if (!empty($this->header)) {
+ return;
+ }
+
+ $this->seek($this->tableOffset);
+
+ $this->header = new Header($this);
+ $this->header->parse();
+ }
+
+ function getFontType(){
+ $class_parts = explode("\\", get_class($this));
+ return $class_parts[1];
+ }
+
+ function parseTableEntries() {
+ $this->parseHeader();
+
+ if (!empty($this->directory)) {
+ return;
+ }
+
+ if (empty($this->header->data["numTables"])) {
+ return;
+ }
+
+
+ $type = $this->getFontType();
+ $class = "FontLib\\$type\\TableDirectoryEntry";
+
+ for ($i = 0; $i < $this->header->data["numTables"]; $i++) {
+ /** @var TableDirectoryEntry $entry */
+ $entry = new $class($this);
+ $entry->parse();
+
+ $this->directory[$entry->tag] = $entry;
+ }
+ }
+
+ function normalizeFUnit($value, $base = 1000) {
+ return round($value * ($base / $this->getData("head", "unitsPerEm")));
+ }
+
+ protected function readTable($tag) {
+ $this->parseTableEntries();
+
+ if (!self::$raw) {
+ $name_canon = preg_replace("/[^a-z0-9]/", "", strtolower($tag));
+
+ $class = "FontLib\\Table\\Type\\$name_canon";
+
+ if (!isset($this->directory[$tag]) || !@class_exists($class)) {
+ return;
+ }
+ }
+ else {
+ $class = "FontLib\\Table\\Table";
+ }
+
+ /** @var Table $table */
+ $table = new $class($this->directory[$tag]);
+ $table->parse();
+
+ $this->data[$tag] = $table;
+ }
+
+ /**
+ * @param $name
+ *
+ * @return Table
+ */
+ public function getTableObject($name) {
+ return $this->data[$name];
+ }
+
+ public function setTableObject($name, Table $data) {
+ $this->data[$name] = $data;
+ }
+
+ public function getData($name, $key = null) {
+ $this->parseTableEntries();
+
+ if (empty($this->data[$name])) {
+ $this->readTable($name);
+ }
+
+ if (!isset($this->data[$name])) {
+ return null;
+ }
+
+ if (!$key) {
+ return $this->data[$name]->data;
+ }
+ else {
+ return $this->data[$name]->data[$key];
+ }
+ }
+
+ function addDirectoryEntry(DirectoryEntry $entry) {
+ $this->directory[$entry->tag] = $entry;
+ }
+
+ function saveAdobeFontMetrics($file, $encoding = null) {
+ $afm = new AdobeFontMetrics($this);
+ $afm->write($file, $encoding);
+ }
+
+ /**
+ * Get a specific name table string value from its ID
+ *
+ * @param int $nameID The name ID
+ *
+ * @return string|null
+ */
+ function getNameTableString($nameID) {
+ /** @var nameRecord[] $records */
+ $records = $this->getData("name", "records");
+
+ if (!isset($records[$nameID])) {
+ return null;
+ }
+
+ return $records[$nameID]->string;
+ }
+
+ /**
+ * Get font copyright
+ *
+ * @return string|null
+ */
+ function getFontCopyright() {
+ return $this->getNameTableString(name::NAME_COPYRIGHT);
+ }
+
+ /**
+ * Get font name
+ *
+ * @return string|null
+ */
+ function getFontName() {
+ return $this->getNameTableString(name::NAME_NAME);
+ }
+
+ /**
+ * Get font subfamily
+ *
+ * @return string|null
+ */
+ function getFontSubfamily() {
+ return $this->getNameTableString(name::NAME_SUBFAMILY);
+ }
+
+ /**
+ * Get font subfamily ID
+ *
+ * @return string|null
+ */
+ function getFontSubfamilyID() {
+ return $this->getNameTableString(name::NAME_SUBFAMILY_ID);
+ }
+
+ /**
+ * Get font full name
+ *
+ * @return string|null
+ */
+ function getFontFullName() {
+ return $this->getNameTableString(name::NAME_FULL_NAME);
+ }
+
+ /**
+ * Get font version
+ *
+ * @return string|null
+ */
+ function getFontVersion() {
+ return $this->getNameTableString(name::NAME_VERSION);
+ }
+
+ /**
+ * Get font weight
+ *
+ * @return string|null
+ */
+ function getFontWeight() {
+ return $this->getTableObject("OS/2")->data["usWeightClass"];
+ }
+
+ /**
+ * Get font Postscript name
+ *
+ * @return string|null
+ */
+ function getFontPostscriptName() {
+ return $this->getNameTableString(name::NAME_POSTSCRIPT_NAME);
+ }
+
+ function reduce() {
+ $names_to_keep = array(
+ name::NAME_COPYRIGHT,
+ name::NAME_NAME,
+ name::NAME_SUBFAMILY,
+ name::NAME_SUBFAMILY_ID,
+ name::NAME_FULL_NAME,
+ name::NAME_VERSION,
+ name::NAME_POSTSCRIPT_NAME,
+ );
+
+ foreach ($this->data["name"]->data["records"] as $id => $rec) {
+ if (!in_array($id, $names_to_keep)) {
+ unset($this->data["name"]->data["records"][$id]);
+ }
+ }
+ }
+}
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/TrueType/Header.php b/application/third_party/dompdf/lib/php-font-lib/classes/TrueType/Header.php
new file mode 100644
index 00000000..7ff79cce
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/TrueType/Header.php
@@ -0,0 +1,31 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\TrueType;
+
+/**
+ * TrueType font file header.
+ *
+ * @package php-font-lib
+ */
+class Header extends \FontLib\Header {
+ protected $def = array(
+ "format" => self::uint32,
+ "numTables" => self::uint16,
+ "searchRange" => self::uint16,
+ "entrySelector" => self::uint16,
+ "rangeShift" => self::uint16,
+ );
+
+ public function parse() {
+ parent::parse();
+
+ $format = $this->data["format"];
+ $this->data["formatText"] = $this->convertUInt32ToStr($format);
+ }
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/TrueType/TableDirectoryEntry.php b/application/third_party/dompdf/lib/php-font-lib/classes/TrueType/TableDirectoryEntry.php
new file mode 100644
index 00000000..fc4fe555
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/TrueType/TableDirectoryEntry.php
@@ -0,0 +1,33 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\TrueType;
+
+use FontLib\Table\DirectoryEntry;
+
+/**
+ * TrueType table directory entry.
+ *
+ * @package php-font-lib
+ */
+class TableDirectoryEntry extends DirectoryEntry {
+ function __construct(File $font) {
+ parent::__construct($font);
+ }
+
+ function parse() {
+ parent::parse();
+
+ $font = $this->font;
+ $this->checksum = $font->readUInt32();
+ $this->offset = $font->readUInt32();
+ $this->length = $font->readUInt32();
+ $this->entryLength += 12;
+ }
+}
+
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/WOFF/File.php b/application/third_party/dompdf/lib/php-font-lib/classes/WOFF/File.php
new file mode 100644
index 00000000..9e54b3fb
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/WOFF/File.php
@@ -0,0 +1,81 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\WOFF;
+
+use FontLib\Table\DirectoryEntry;
+
+/**
+ * WOFF font file.
+ *
+ * @package php-font-lib
+ *
+ * @property TableDirectoryEntry[] $directory
+ */
+class File extends \FontLib\TrueType\File {
+ function parseHeader() {
+ if (!empty($this->header)) {
+ return;
+ }
+
+ $this->header = new Header($this);
+ $this->header->parse();
+ }
+
+ public function load($file) {
+ parent::load($file);
+
+ $this->parseTableEntries();
+ $dataOffset = $this->pos() + count($this->directory) * 20;
+
+ $fw = $this->getTempFile(false);
+ $fr = $this->f;
+
+ $this->f = $fw;
+ $offset = $this->header->encode();
+
+ foreach ($this->directory as $entry) {
+ // Read ...
+ $this->f = $fr;
+ $this->seek($entry->offset);
+ $data = $this->read($entry->length);
+
+ if ($entry->length < $entry->origLength) {
+ $data = gzuncompress($data);
+ }
+
+ // Prepare data ...
+ $length = strlen($data);
+ $entry->length = $entry->origLength = $length;
+ $entry->offset = $dataOffset;
+
+ // Write ...
+ $this->f = $fw;
+
+ // Woff Entry
+ $this->seek($offset);
+ $offset += $this->write($entry->tag, 4); // tag
+ $offset += $this->writeUInt32($dataOffset); // offset
+ $offset += $this->writeUInt32($length); // length
+ $offset += $this->writeUInt32($length); // origLength
+ $offset += $this->writeUInt32(DirectoryEntry::computeChecksum($data)); // checksum
+
+ // Data
+ $this->seek($dataOffset);
+ $dataOffset += $this->write($data, $length);
+ }
+
+ $this->f = $fw;
+ $this->seek(0);
+
+ // Need to re-parse this, don't know why
+ $this->header = null;
+ $this->directory = array();
+ $this->parseTableEntries();
+ }
+}
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/WOFF/Header.php b/application/third_party/dompdf/lib/php-font-lib/classes/WOFF/Header.php
new file mode 100644
index 00000000..65a6f147
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/WOFF/Header.php
@@ -0,0 +1,32 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\WOFF;
+
+/**
+ * WOFF font file header.
+ *
+ * @package php-font-lib
+ */
+class Header extends \FontLib\TrueType\Header {
+ protected $def = array(
+ "format" => self::uint32,
+ "flavor" => self::uint32,
+ "length" => self::uint32,
+ "numTables" => self::uint16,
+ self::uint16,
+ "totalSfntSize" => self::uint32,
+ "majorVersion" => self::uint16,
+ "minorVersion" => self::uint16,
+ "metaOffset" => self::uint32,
+ "metaLength" => self::uint32,
+ "metaOrigLength" => self::uint32,
+ "privOffset" => self::uint32,
+ "privLength" => self::uint32,
+ );
+}
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/php-font-lib/classes/WOFF/TableDirectoryEntry.php b/application/third_party/dompdf/lib/php-font-lib/classes/WOFF/TableDirectoryEntry.php
new file mode 100644
index 00000000..eb67c9c4
--- /dev/null
+++ b/application/third_party/dompdf/lib/php-font-lib/classes/WOFF/TableDirectoryEntry.php
@@ -0,0 +1,34 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace FontLib\WOFF;
+
+use FontLib\Table\DirectoryEntry;
+
+/**
+ * WOFF font file table directory entry.
+ *
+ * @package php-font-lib
+ */
+class TableDirectoryEntry extends DirectoryEntry {
+ public $origLength;
+
+ function __construct(File $font) {
+ parent::__construct($font);
+ }
+
+ function parse() {
+ parent::parse();
+
+ $font = $this->font;
+ $this->offset = $font->readUInt32();
+ $this->length = $font->readUInt32();
+ $this->origLength = $font->readUInt32();
+ $this->checksum = $font->readUInt32();
+ }
+}
diff --git a/application/third_party/dompdf/lib/res/broken_image.png b/application/third_party/dompdf/lib/res/broken_image.png
new file mode 100644
index 00000000..771a1a37
Binary files /dev/null and b/application/third_party/dompdf/lib/res/broken_image.png differ
diff --git a/application/third_party/dompdf/lib/res/html.css b/application/third_party/dompdf/lib/res/html.css
new file mode 100644
index 00000000..2105f865
--- /dev/null
+++ b/application/third_party/dompdf/lib/res/html.css
@@ -0,0 +1,508 @@
+/**
+ * dompdf default stylesheet.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998 the Initial Developer.
+ * All Rights Reserved.
+ *
+ * @package dompdf
+ * @link http://dompdf.github.com/
+ * @author Benj Carson
+ * @author Blake Ross
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ * @version $Id$
+ */
+
+@page {
+ margin: 1.2cm;
+}
+
+html {
+ display: -dompdf-page;
+ counter-reset: page;
+}
+
+/* blocks */
+
+div, map, dt, isindex {
+ display: block;
+}
+
+body {
+ page-break-before: avoid;
+ display: block;
+ counter-increment: page;
+}
+
+p, dl, multicol {
+ display: block;
+ margin: 1em 0;
+}
+
+dd {
+ display: block;
+ margin-left: 40px;
+}
+
+blockquote {
+ display: block;
+ margin: 1em 40px;
+}
+
+address {
+ display: block;
+ font-style: italic;
+}
+
+center {
+ display: block;
+ text-align: center;
+}
+
+blockquote[type=cite] {
+ display: block;
+ margin: 1em 0px;
+ padding-left: 1em;
+ border-left: solid;
+ border-color: blue;
+ border-width: thin;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ display: block;
+ font-weight: bold;
+}
+
+h1 {
+ font-size: 2em;
+ margin: .67em 0;
+}
+
+h2 {
+ font-size: 1.5em;
+ margin: .83em 0;
+}
+
+h3 {
+ font-size: 1.17em;
+ margin: 1em 0;
+}
+
+h4 {
+ margin: 1.33em 0;
+}
+
+h5 {
+ font-size: 0.83em;
+ margin: 1.67em 0;
+}
+
+h6 {
+ font-size: 0.67em;
+ margin: 2.33em 0;
+}
+
+listing {
+ display: block;
+ font-family: fixed;
+ font-size: medium;
+ white-space: pre;
+ margin: 1em 0;
+}
+
+plaintext, xmp, pre {
+ display: block;
+ font-family: fixed;
+ white-space: pre;
+ margin: 1em 0;
+}
+
+article, aside, details,
+figcaption, figure,
+footer, header, hgroup,
+nav, section {
+ display: block;
+}
+
+/* tables */
+
+table {
+ display: table;
+ border-spacing: 2px;
+ border-collapse: separate;
+ margin-top: 0;
+ margin-bottom: 0;
+ text-indent: 0;
+ text-align: left; /* quirk */
+}
+
+table[border] {
+ border-style: outset;
+ border-color: gray;
+}
+
+/* This won't work (???) */
+/*
+table[border] td,
+table[border] th {
+ border: 1pt solid grey;
+}*/
+
+/* make sure backgrounds are inherited in tables -- see bug 4510 */
+td, th, tr {
+ background: inherit;
+}
+
+/* caption inherits from table not table-outer */
+caption {
+ display: block;
+ text-align: center;
+}
+
+tr {
+ display: table-row;
+ vertical-align: inherit;
+}
+
+col {
+ display: table-column;
+}
+
+colgroup {
+ display: table-column-group;
+}
+
+tbody {
+ display: table-row-group;
+ vertical-align: middle;
+}
+
+thead {
+ display: table-header-group;
+ vertical-align: middle;
+}
+
+tfoot {
+ display: table-footer-group;
+ vertical-align: middle;
+}
+
+/* To simulate tbody auto-insertion */
+table > tr {
+ vertical-align: middle;
+}
+
+td {
+ display: table-cell;
+ vertical-align: inherit;
+ text-align: inherit;
+ padding: 1px;
+}
+
+th {
+ display: table-cell;
+ vertical-align: inherit;
+ font-weight: bold;
+ padding: 1px;
+ text-align: center;
+}
+
+/* inlines */
+q {
+ quotes: '"' '"' "'" "'"; /* FIXME only the first level is used */
+}
+
+q:before {
+ content: open-quote;
+}
+
+q:after {
+ content: close-quote;
+}
+
+:link {
+ color: #00c;
+ text-decoration: underline;
+}
+
+b, strong {
+ font-weight: bolder;
+}
+
+i, cite, em, var, dfn {
+ font-style: italic;
+}
+
+tt, code, kbd, samp {
+ font-family: fixed;
+}
+
+u, ins {
+ text-decoration: underline;
+}
+
+s, strike, del {
+ text-decoration: line-through;
+}
+
+blink {
+ text-decoration: blink;
+}
+
+big {
+ font-size: larger;
+}
+
+small {
+ font-size: smaller;
+}
+
+sub {
+ vertical-align: sub;
+ font-size: smaller;
+ line-height: normal;
+}
+
+sup {
+ vertical-align: super;
+ font-size: smaller;
+ line-height: normal;
+}
+
+nobr {
+ white-space: nowrap;
+}
+
+/* lists */
+
+ul, menu, dir {
+ display: block;
+ list-style-type: disc;
+ margin: 1em 0;
+ padding-left: 40px;
+}
+
+ol {
+ display: block;
+ list-style-type: decimal;
+ margin: 1em 0;
+ padding-left: 40px;
+}
+
+li {
+ display: list-item;
+}
+
+/*li:before {
+ display: -dompdf-list-bullet !important;
+ content: counter(-dompdf-default-counter) ". ";
+ padding-right: 0.5em;
+}*/
+
+/* nested lists have no top/bottom margins */
+ul ul, ul ol, ul dir, ul menu, ul dl,
+ol ul, ol ol, ol dir, ol menu, ol dl,
+dir ul, dir ol, dir dir, dir menu, dir dl,
+menu ul, menu ol, menu dir, menu menu, menu dl,
+dl ul, dl ol, dl dir, dl menu, dl dl {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+/* 2 deep unordered lists use a circle */
+ol ul, ul ul, menu ul, dir ul,
+ol menu, ul menu, menu menu, dir menu,
+ol dir, ul dir, menu dir, dir dir {
+ list-style-type: circle;
+}
+
+/* 3 deep (or more) unordered lists use a square */
+ol ol ul, ol ul ul, ol menu ul, ol dir ul,
+ol ol menu, ol ul menu, ol menu menu, ol dir menu,
+ol ol dir, ol ul dir, ol menu dir, ol dir dir,
+ul ol ul, ul ul ul, ul menu ul, ul dir ul,
+ul ol menu, ul ul menu, ul menu menu, ul dir menu,
+ul ol dir, ul ul dir, ul menu dir, ul dir dir,
+menu ol ul, menu ul ul, menu menu ul, menu dir ul,
+menu ol menu, menu ul menu, menu menu menu, menu dir menu,
+menu ol dir, menu ul dir, menu menu dir, menu dir dir,
+dir ol ul, dir ul ul, dir menu ul, dir dir ul,
+dir ol menu, dir ul menu, dir menu menu, dir dir menu,
+dir ol dir, dir ul dir, dir menu dir, dir dir dir {
+ list-style-type: square;
+}
+
+/* forms */
+/* From http://dev.w3.org/csswg/css3-ui/#appearance */
+form {
+ display: block;
+}
+
+input, button, select {
+ display: inline-block;
+ font-family: sans-serif;
+}
+
+input[type=text],
+input[type=password],
+select {
+ width: 12em;
+}
+
+input[type=text],
+input[type=password],
+input[type=button],
+input[type=submit],
+input[type=reset],
+input[type=file],
+button,
+textarea,
+select {
+ background: #FFF;
+ border: 1px solid #999;
+ padding: 2px;
+ margin: 2px;
+}
+
+input[type=button],
+input[type=submit],
+input[type=reset],
+input[type=file],
+button {
+ background: #CCC;
+ width: 8em;
+ text-align: center;
+}
+
+input[type=text]:before,
+input[type=button]:before,
+input[type=submit]:before,
+input[type=reset]:before {
+ content: attr(value);
+}
+
+input[type=file]:before {
+ content: "Chose a file";
+}
+
+input[type=password][value]:before {
+ font-family: "DejaVu Sans";
+ content: "\2022\2022\2022\2022\2022\2022\2022\2022";
+ line-height: 1em;
+}
+
+input[type=checkbox],
+input[type=radio],
+select:after {
+ font-family: "DejaVu Sans";
+ font-size: 18px;
+ line-height: 1;
+}
+
+input[type=checkbox]:before {
+ content: "\2610";
+}
+
+input[type=checkbox][checked]:before {
+ content: "\2611";
+}
+
+input[type=radio]:before {
+ content: "\25CB";
+}
+
+input[type=radio][checked]:before {
+ content: "\25C9";
+}
+
+textarea {
+ display: block;
+ height: 3em;
+ overflow: hidden;
+ font-family: monospace;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+}
+
+select {
+ position: relative!important;
+ overflow: hidden!important;
+}
+
+select:after {
+ position: absolute;
+ right: 0;
+ top: 0;
+ height: 5em;
+ width: 1.4em;
+ text-align: center;
+ background: #CCC;
+ content: "\25BE";
+}
+
+select option {
+ display: none;
+}
+
+select option[selected] {
+ display: inline;
+}
+
+fieldset {
+ display: block;
+ margin: 0.6em 2px 2px;
+ padding: 0.75em;
+ border: 1pt groove #666;
+ position: relative;
+}
+
+fieldset > legend {
+ position: absolute;
+ top: -0.6em;
+ left: 0.75em;
+ padding: 0 0.3em;
+ background: white;
+}
+
+legend {
+ display: inline-block;
+}
+
+/* leafs */
+
+hr {
+ display: block;
+ height: 0;
+ border: 1px inset;
+ margin: 0.5em auto 0.5em auto;
+}
+
+iframe {
+ border: 2px inset;
+}
+
+noframes {
+ display: none;
+}
+
+br {
+ display: -dompdf-br;
+}
+
+img, img_generated {
+ display: -dompdf-image;
+}
+
+dompdf_generated {
+ display: inline;
+}
+
+/* hidden elements */
+area, base, basefont, head, meta, script, style, title,
+noembed, noscript, param {
+ display: none;
+ -dompdf-keep: yes;
+}
diff --git a/application/third_party/dompdf/lib/ttf2ufm/README.TXT b/application/third_party/dompdf/lib/ttf2ufm/README.TXT
new file mode 100644
index 00000000..be9839b6
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/README.TXT
@@ -0,0 +1,24 @@
+To embed TrueType fonts (.TTF) files, you need to extract the font metrics and
+build the required tables using the provided utility (/fonts/ttf2ufm).
+
+TTF2UFM is a modified version of Mark Heath's TTF 2 PT1 converter
+(http://ttf2pt1.sourceforge.net/) by Steven Wittens
+(http://www.acko.net/blog/ufpdf). ttf2ufm, is included in /ttf2ufm-src.
+The /fonts/ttf2ufm folder contains a compiled Windows binary.
+TTF 2 UFM is identical to TTF 2 PT1 except that it also generates a .ufm file
+for usage with makefontuni.php.
+
+
+Setting up a Truetype font for usage with TCPDF:
+ 1) Generate the font's .ufm metrics file by processing it with the provided
+ ttf2ufm program (modified ttf2pt1). For example:
+ $ ttf2ufm -a -F myfont.ttf
+ 2) Run makefontuni.php with the .ttf and .ufm filenames as argument:
+ $ php -q makefontuni.php myfont.ttf myfont.ufm
+ 3) Copy the resulting .php, .z and .ctg.z file to the TCPDF font directory.
+ 4) Rename php font files variations for bold and italic using the following schema:
+ [basic-font-name]b.php for bold variation
+ [basic-font-name]i.php for oblique variation
+ [basic-font-name]bi.php for bold oblique variation
+ 5) Convert all fonts filenames to lowercase.
+
\ No newline at end of file
diff --git a/application/third_party/dompdf/lib/ttf2ufm/bin/ttf2ufm.exe b/application/third_party/dompdf/lib/ttf2ufm/bin/ttf2ufm.exe
new file mode 100644
index 00000000..ad623592
Binary files /dev/null and b/application/third_party/dompdf/lib/ttf2ufm/bin/ttf2ufm.exe differ
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/CHANGES b/application/third_party/dompdf/lib/ttf2ufm/src/CHANGES
new file mode 100644
index 00000000..e69de29b
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/CHANGES.html b/application/third_party/dompdf/lib/ttf2ufm/src/CHANGES.html
new file mode 100644
index 00000000..c638b6d4
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/CHANGES.html
@@ -0,0 +1,815 @@
+
+
+
+TTF2PT1 - CHANGES history
+
+
+
+
+TTF2PT1 - CHANGES history
+
+
+
+
+
+3.4.4 -- December 31, 2003
+
+
+
+New features:
+
+- Improved the auto-vectoring (-OV) alrogithm.
+
- Allow use of any encoding table of format 4 in the ttf parser.
+
- Take the first available format 4 encoding table if no known
+ table is found in the ttf parser.
+
- The ttf parser lists the available encodings if no supported
+ encoding table is found. This can be used to list the encodings in
+ any font by specifying a bogus explicit PID/EID, such as
+ with option -l plane+pid=50,eid=50.
+
+
+Bug fixes:
+
+- Fix to build all the features on Windows MS C++, by Tomoo Amano.
+
- Fix for a null pointer in the encodings, bad inner loop variable.
+
- Unified the parsing of font name strings and improved the checks
+ against invalid characters.
+
+
+
+3.4.3 -- December 2, 2002
+
+
+
+New features:
+
+- scripts/forceiso got an optional argument to select the
+ format of the names for glyphs without standard Latin-1 names.
+
+
+Bug fixes:
+
+- Changed the glyph names in scripts/forceiso to match those in ttf2pt1.
+
- Included the missing directory app/TeX.
+
+
+
+3.4.2 -- August 30, 2002
+
+
+
+New features:
+
+- New map for T2A_compat encoding (for Cyrillic LaTeX) by Mikhail
+ Umorin.
+
- Scripts supporting font conversion for CJK-LaTeX, by Mike Fabian
+ from SuSE.
+
+
+Bug fixes:
+
+- Explicit owner/group/permissions are used to install directories.
+
- In scripts/convert fixed the addition of encoding name to the font
+ name for the external encoding maps, was missing "/" at the start.
+
- Fixed the divergence between two copies of UniqueID.
+
- Fixed the recovery after defective empty contours.
+
+
+
+3.4.1 -- June 13, 2002
+
+
+
+New features:
+
+- Added Autotrace support for the bitmap fonts (-OZ). It's horrible.
+
- Added vectorization of bitmap fonts (-OV) - functionally the same thing as
+ autotrace but home-grown. Works mostly decently but still with large
+ space for impprovement.
+
- Relaxed the conditions for warnings about long glyphs.
+
+
+Bug fixes:
+
+- Fix by Rob Kolstad for a crash in the new outline smoothing
+ code (on small thin contours) and diagnostic for another crash.
+
- Fix by Holger Huesing for a crash on degenerate contours.
+
- Fix for bitmaps of zero dimensions.
+
- The BDF reader does not fail on redefintion of the properties.
+
- Fix for reading of BDF glyphs with 0 size.
+
- Fix for a hang when guessing the boldness of some fonts.
+
- Fix by Adriano Konzen for scaling coefficients in composite glyphs.
+
+
+
+3.4.0 -- November 24, 2001
+
+
+
+New features:
+
+- Parser for the BDF bitmap fonts.
+
- Vastly improved the smoothing of the outlines.
+
- The options are saved as a comment in the output file.
+
- New script other/showdf for visual comparison of the fonts.
+
- New option -G to select the file types to generate.
+
- Creation of the dvips encoding files (by Rigel).
+
- More glyphs in the Chinese maps (by Rigel).
+
- Made the assignment of ISO8859/1 glyph names to the glyphs in the
+ fonts without PostScript names in them dependent on the original
+ encoding: no change for the 8-bit encodings, for the Unicode encoding
+ the names are assigned to the glyph with the codes 0-255 in Unicode,
+ and for the other 16-bit encodings the 8859/1 names are not assigned
+ at all.
+
+
+Bug fixes:
+
+- Added a check for spaces in the PostScript font name in the FreeType
+ parser.
+
- Made "-" a valid character in the glyph names.
+
- Fixed handling of the Unicode names returned by FreeType, though
+ not perfectly.
+
- Changed the build for FreeType-2.0.4.
+
- Fixed the handling and printing of bad glyph names.
+
- Fixed the bug with duplicated glyph names when more than 256 glyphs are
+ extracted from a font that has no PostScript glyph names defined.
+
- Added ability to map a glyph to more than one code when unisng the
+ native parser (-pttf).
+
+
+
+3.3.5 -- September 12, 2001
+
+
+
+Packaged by Sergey Babkin.
+
+
+Bug fixes:
+
+- Fixed the scaling of Ascender and Descender in the AFM file.
+
- Fixed the brekage of "-l adobestd".
+
+
+
+3.3.4 -- June 4, 2001
+
+
+
+Packaged by Sergey Babkin.
+
+
+New features:
+
+- Cyrillic (full set of glyphs) language tables (by Zvezdan Petkovic).
+ Now the languages "russian" and "bulgarian" are provided for compatibility
+ only, use the common language "cyrillic" instead.
+
- More information in FONTS on using Cyrillic fonts with
+ Netscape (by Zvezdan Petkovic)
+
- In the Netscape print filter added removal of the clipping path command:
+ otherwise Netscape tends to cut off a large piece of the rightmost column
+ of the tables.
+
- One more script for printing from Netscape (by Zvezdan Petkovic).
+
- Added selection of the base TTF encoding by pid/eid in the external maps.
+
- Improved the recognition of substituted stems for intersecting contours.
+
- Improved the substituted hints to make the horizontal positioning of
+ the points at the same height more uniform at small pixel sizes.
+
- Made the algorithm for calculation of standard stem widths more
+ selective.
+
- Added link to the GnuWin32 project.
+
+
+Bug fixes:
+
+- TH: Print out metrics of un-encoded glyphs even without "-a" option.
+
- Added missing "/" in Fontmap generation in convert (by Zvezdan Petkovic).
+
- Removed unneccessary "\n" in messages in x2gs.
+
- Removed the broken overoptimisation of "0 0 rmoveto".
+
- Removed the useless warnings about multiple codes for a glyph.
+
- Changed the FreeType2 include directory in the Makefile to match the
+ FreeType's default.
+
+
+
+3.3.3 -- March 4, 2001
+
+
+
+Packaged by Sergey Babkin.
+
+
+New features:
+
+- TH: Added printing of front-end parser in the header of the font file.
+
- Tested build with FreeType 2.0 Release.
+
+
+Bug fixes:
+
+- Changed the installation script which on some versions of bash
+ copied all files into the share directory.
+
- Fixed the close sequences of html2man comments in the HTML files,
+ now they should display correctly with lynx.
+
- Restored the ability to include un-encoded characters into the
+ customised maps (those with codes over 255).
+
- Fixed the Unicode mapping of the Cyrillic letters "YO" and "yo"
+ (by Yuri Shemanin).
+
- Fixed the spurious aborts when the conversion-by-plane function
+ gets called for auto-guessing of encoding.
+
+
+
+3.3.2 -- November 20, 2000
+
+
+
+Packaged by Sergey Babkin.
+
+
+New features:
+
+- Added generation of man pages.
+
- Added "make install" and "make uninstall".
+
- Added language option "-l plane".
+
- In other/showg added better support of comparison files:
+
+ - printing of the comparison file legend;
+
- guessing of missing glyph names in a comparison file by code;
+
- bounding boxes of all comparison files are used for page layout.
+
+ - Added ability to use external t1asm instead of compiling it in.
+
- Renamed the fonts installation guide from INSTALL*html to FONTS*html
+ to avoid confusion with installation of ttf2pt1 itself.
+
+
+Bug fixes:
+
+- Removed erroneous extra fclose(pfa_file).
+
- Fixed random memory corruption that manifested with crash on Linux
+ when converting fonts not containing glyph names.
+
- Removed from the output file the comments that confused dvips. Changed
+ other/showg to work without them.
+
- In other/showg added better checks for missing glyphs, now it
+ gives warnings about them and the output file does not crash PostScript.
+
+
+Other:
+
+- ttf2pfa is no longer included, people interested in history
+ should look for it in the older versions.
+
+
+
+3.3.1 -- October 22, 2000
+
+
+
+Packaged by Sergey Babkin.
+
+
+New features:
+
+- Added front-end parser based on the FreeType-2 library. See Makefile
+for build instructions.
+
- Changed the handling of encodings to accomodate the FreeType model.
+
- Further cleaned up the front-end parser interface.
+
+
+Bug fixes:
+
+- Fixed a bug that caused core dump on Alpha machines.
+
- Fixed a bug in the outline smoothing that occasionally caused core dump.
+
- Cleaned up warnings from picky compilers
+
- Fixed more bugs in the Windows port (by Stefan Bauer).
+
- Fixed the RPM spec file (suggested by Brian Armstrong).
+
+
+
+
+3.3.0 -- September 22, 2000
+
+
+
+Packaged by Sergey Babkin.
+
+
+New features:
+
+- Converted most of the outlines' processing to floating point
+arithmetic.
+
- Added splitting of curves crossing the quadrant boundaries (no gross
+damage is done any more to the Marvosym font and others like it).
+
- Added modular interface for front-end font parsers and option to control
+their selection at run time.
+
- Grouped the outline processing control options into one to reduce the
+options namespace pollution.
+
- Thomas moved the Chinese maps into a separate module, chinese-maps.
+
- Thomas added option -V to print version number. In addition, the version
+number is put in the header of the font file.
+
- Added long option names (suggested by Thomas).
+
- Added support for multi-level composite glyphs.
+
- TH: Made <fontname> command-line argument optional; default to <ttf-file>
+with suffix replaced.
+
- In other/showg added more ways to specify glyphs and the comparison option.
+
+
+Bug fixes:
+
+- Fixed the VC++ batch file, added batch file for Cygnus GCC on Windows.
+
- Removed parentheses from the Version string in AFM files because it does
+not help StarOffice anyway. StarOffice 5.2 has been reported to have this
+bug fixed. Added paragraph on StarOffice in FONTS.html.
+
- Made messages on the '?' option parameter more meaningful (by Johan Vromans).
+
- Changed the latin1 encoding table to include the Euro sign, Z and z with
+caron (by Thomas Henlich).
+
- Improved the smoothing code which occasionally had problems with
+joining curves. Also fixed a few minor bugs in it.
+
+
+
+3.22 -- May 23, 2000
+
+
+
+Packaged by Sergey Babkin.
+
+
+New features:
+
+- Included windows support by Frank Siegert (somewhat amended)
+
- Added control over verbosity of warnings.
+
- Added arguments and initialization functions to the language
+translation routines.
+
- Added support of planes determined by arguments to the external
+maps.
+
- Added compact external maps format (primarily for Eastern fonts).
+
- Added external maps for Chinese GBK and Big5 encodings (converted
+from ttf2pfb) as well as maps for other Chinese encodings by Wang Lei.
+
- Added the idea of buckets to speed up the search in external maps.
+
- Changed the grouping algorithm for substituted hints: now it creates
+a bit bigger files but requires smaller hint stack when being rendered.
+
- Added maximal limit of hint stack depth, glyphs requiring bigger
+stack get generation of substituted hints disabled. This makes substituted
+hints safe to use, no more lost glyphs due to hint stack overflow.
+
- Added the font dump program other/dumpf.
+
- Changed the testing HTML generator other/lst.pl to use tables.
+
- Added debugging script other/cntstems.pl to count required hint
+stack depth for the glyphs.
+
+
+Bug fixes:
+
+- Fixed printing of UID in script/trans. Changed the auto-generated UID to
+be in range 4000000-4999999 which is reserved by Adobe for private use.
+
- Fixed handling of "cleartomark" in built-in t1asm.
+
- Added handling of "can't happen" case in straighten() routine
+which actually happened on strange fonts and caused failure on assertion.
+
- Made it always include the glyph .notdef in the resulting font.
+
- Placed the version string in AFM file in parentheses, hopefully
+that would fix the problem with StarOffice.
+
- Improved the smoothing code which occasionally had problems with
+joining curves.
+
+
+
+3.21 -- March 1, 2000
+
+
+
+Sergey Babkin: committed the changes by Petr Titera and
+my bugfixes.
+
+
+New features:
+
+- New Unicode map format with glyph names, by Petr Titera.
+
- Option to force the Unicode encoding by Petr Titera
+ (I changed it to work on any MS encoding, not only Symbol).
+
- Slightly tweaked the calculation of hints, should be better now.
+
+
+Bug fixes:
+
+- The unicode-sample.map with description of the map formats
+ was lost in the release process, restored and enhanced.
+
- Renamed the table ISOLatin1Encoding to Fmt3Encoding to reflect
+ the way it is used. Saved the original one for reference
+ purposes. In the new table renamed "quoteright" to "quotesingle"
+ as Thomas Henlich suggested (and he were right).
+
- In the ISOLatinEncoding table renamed the glyph "grave"
+ at octal 0140 to "quoteleft", "quotesingle" at octal 047 to
+ "quoteright" to conform to the standard as suggested by
+ Martin Trautner).
+
- Fixed bug in scripts/trans that corrupted the UniqueID record
+ in the translated fonts.
+
- Fixed bug in interaction of substituted hints with BlueZones.
+ Now the fonts with hint substitution seem to be always at least
+ not worse than without it (well, when they fit in the X11
+ file size limit).
+
+
+
+
+3.2 -- January 15, 2000
+
+
+
+Sergey Babkin: combined my changes with the changes by
+Thomas Henlich. The result deserves a not-so-minor version
+increase.
+
+
+New features:
+
+- Support of the external Unicode re-encoding maps
+ (by Thomas).
+
- Support for inclusion of all the glyphs from the
+ source file into the resulting file (inspired by
+ Thomas but I re-implemented it to remove the limitation
+ of his implementation: not more than 1024 glyphs).
+
- The hints substitution. It's an experimental feature
+ yet and needs further work.
+
- Support for UniqueID and its auto-generation.
+
- Support for the name-based conversions from Unicode
+ in general and the adobestd "language" in particular.
+
- Started the split of the source code into multiple
+ files. This needs more work to do it in a cleaner
+ way.
+
- Better framework for the debugging printout
+ in the converter.
+
- Utilities to install the fonts in Netscape
+ Navigator/Communicator 4.x.
+
- Patches for bigger font files in the X11 rasterizer.
+
- Linux RPM spec-file (by Johan Vromans).
+
- Added the COPYRIGHT file (BSD-style, as we discussed
+ on the mailing list earlier) and the CHANGES file.
+
- Creation of the .pfb files from the convert
+ script.
+
- Changed the .notdef-s in the built-in
+ ISOLatin1Encoding table to some valid names (by Thomas).
+ Thomas also suggested replacing `quoteright' by
+ `quotesingle' but this seems to be against the
+ Adobe ISOLatin1 table.
+
- New aliases windows-1251 and cp-866 for
+ the Russian encodings: those are expected by Netscape
+ navigator.
+
- The font comparison program other/cmpf.
+
- The "magnifying glass" program for glyph outlines:
+ other/showg.
+
- Other updates of the tools in the `other' subdirectory.
+
- Added a link to T1LIB in README.
+
- A few new options in convert.cfg.
+
+
+Bux fixes:
+
+- A bug in the outline smoothing code that corrupted some
+ of the fonts (for example, Microsoft Verdana).
+
- Added explicit `cleartomark' to the end of file,
+ this seems to be compatible with both old and new version
+ of t1asm (suggested by Thomas).
+
- Added the FontEncoding statement to the AFM files
+ (techincally this was not a bug because this statement
+ is optional but some programs want it).
+
- A coredump when the converter tried to print a warning
+ (rather ironically) about a weird glyph width.
+
- Changed the underscores in the font names to dashes (this
+ has been proposed long time ago by Johan Vromans).
+
- No more glyph names of font names staring with a digit.
+
- The names of the fonts in font and AFM files are now the
+ same as in the generated Ghostscript Fontmap file.
+ Warning: the names in Fontmap have been
+ changed.
+ - The forceiso script does not corrupt the character
+ and kerning pairs counts any more, and is optional at all.
+
- Fix for a loop going to 254 instead of 255 (by Thomas).
+
- Added ':' in the font header (by Thomas).
+
- A coredump when wrong language name is given (this was
+ also fixed by Thomas but I noticed it too late, after
+ I already fixed it by myself).
+
- Fixed the links to the Adobe documents in README.
+
+
+
+
+3.13 -- October 18, 1999
+
+
+
+Packaged by Sergey Babkin.
+
+
+New features:
+
+- New option -v for automatic re-scaling based on the vertical size of the font
+
- Changed the code to use getopt() instead of a home-made version of it.
+
- Latin2 language support by Szalay Tamas.
+
+
+Bux fixes:
+
+- Fix for the bug that made possible calls of malloc(0).
+
- Refinement of the option -w to prevent extra wide spacing
+
+
+
+3.12 -- October 2, 1999
+
+
+
+Packaged by Sergey Babkin.
+
+
+New features:
+
+- Added support for the Bulgarian language (actually, for now just an alias
+of Russian).
+
- Added option -w that tries to make sure that the character widths are not
+too narrow.
+
- Added the concept of aliased encodings.
+
- Now the conversion scripts create and install the .afm files too.
+
- The conversion script removes the intermediate files after installation.
+
- Added tunables to the conversion script.
+
- Installation of the Ghostscript fonts can now be done automatically
+together with the X11 fonts.
+
+
+Bux fixes:
+
+- (FINALLY!!!) A correct fix for the infamous Red Hat 6.0 stdio "feature".
+
- A number of little bugs discovered by a picky SGI compiler (well, maybe
+some day I'll try to run it through the UnixWare lint and see what happens).
+
- A diagnostic message about the empty encodings in the convert script was
+made less cryptic and a bug in the awk sub-script was fixed.
+
- The .afm creation code now considers the option -t.
+
+
+
+3.11 -- May 24, 1999
+
+
+
+Packaged by Sergey Babkin.
+
+
+New features:
+
+- It includes the Turkish (Latin5, ISO8859/9)
+language support by Turgut Uyar and Baltic (ISO8859/4) languages support by
+Rihardas Hepas.
+
- Also the installation script got updated: the configuration parameters
+are moved to a separate file and the generated fonts.dir files should now be
+compatible with Xfsft.
+
+
+
+3.1 -- March 28, 1999
+
+
+
+Packaged by Sergey Babkin.
+
+
+New features:
+
+- Improved the interaction of the character-level hints and font-level hints
+
+
+
+
+3.0 -- March 6, 1999
+
+
+
+Packaged by Sergey Babkin.
+
+
+New features:
+
+- Added HTML documents.
+
+
+
+3.0beta2 -- February 14, 1999
+
+
+
+Packaged by Sergey Babkin.
+
+
+New features:
+
+- Added ability to print the .afm file instead of the font to STDOUT.
+
- Added the guessing of the /ForceBold parameter that proved to be useful.
+
+
+Bux fixes:
+
+- Removed the force-fixed option that proved to be troublesome.
+
+
+
+3.0beta1 -- December 11, 1998
+
+
+
+By Andrew Weeks.
+
+
+New features:
+
+- Added option (passed to t1asm) to create a compressed binary
+version of the font (A PFB file).
+
+
+Bux fixes:
+
+- Versions of handle_post and handle_cmap that deal with some
+problems with buggy fonts.
+
- Minor Bug Fixes.
+
+
+
+3.0beta-afm -- December 5, 1998
+
+
+
+By Thomas Henlich.
+
+
+New features:
+
+- Integration of AFM file creation.
+
+
+
+3.0beta -- November 15, 1998
+
+
+
+By Sergey Babkin.
+
+
+New features:
+
+- Added the auto-calculation of the italic angle.
+
+
+Bux fixes:
+
+- Fixed a couple of bugs.
+
+
+
+3.0alpha -- October 19, 1998
+
+
+
+By Sergey Babkin.
+
+
+New features:
+
+- Improved (although still not perfect) handling of
+scaling in composite glyphs
+
- Automatic correction of outlines to make them more
+smooth (to correct both rounding errors introduced
+during conversion and present in the original font)
+
- Automatic generation of hints (still has lots of
+space for improvement)
+
- Automatic generation of BlueValues etc.
+
+
+Bux fixes:
+
+- Scaling of fonts to 1000x1000 M-square required by
+Type1 standard
+
- Printing out the contours in reverse direction, because
+TTF directions are different from Type1 ones (that was
+the major reason why the fonts generated by
+version 2.2 were rendered so badly in small sizes)
+
+
+
+June 22, 1998 (AKA 2.2)
+
+
+
+By Thomas Henlich.
+
+
+Bux fixes:
+
+- "width" should be "short int" because otherwise:
+characters with negative widths (e.g. -4) become *very* wide (65532)
+
- The number of /CharStrings is numglyphs and not numglyphs+1
+
+
+
+February 13, 1998
+
+
+
+By Mark Heath.
+
+
+Bux fixes:
+
+- An original Bug Reported by Frank, which was just incorrect syntax in the
+Type 1 header, managed to creep back into the Feb 04 Version. This has been
+Fixed in the Feb 13 Version.
+
+
+
+February 4, 1998
+
+
+
+By Mark Heath.
+
+
+Bux fixes:
+
+- A workaround was implemented in ttf2pfa by altering the matrix. I suspect
+I will have to calculate the correct values, as matrix ops are probably not
+allowed in Type 1 format.
+
+
+
+
+The older history seems to be lost.
+
+
+
+(S.B.: The story how we got the version numbers is rather funny. Initially
+there were no version umbers, the releases were marked by dates. The version
+from June 22 1998 untarred itself into a directory "ttf2pt1-22". When I
+made my changes to it I assumed that this was the version number meaning
+version 2.2. Since Mark asked me to send him a complete archive I supposed
+that I have to bump the version number. And I bumped it to 3.0 because the
+changes were rather extensive. Mark silently agreed and released the new
+version as 3.0. And that's the end of the story about how we got this
+Microsoft-like high version number.)
+
+
+
+
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/COPYRIGHT b/application/third_party/dompdf/lib/ttf2ufm/src/COPYRIGHT
new file mode 100644
index 00000000..75e8f38e
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/COPYRIGHT
@@ -0,0 +1,87 @@
+The following copyright notice applies to all the files provided
+in this distribution unless explicitly noted otherwise
+(the most notable exception being t1asm.c).
+
+ Copyright (c) 1997-2003 by the AUTHORS:
+ Andrew Weeks
+ Frank M. Siegert
+ Mark Heath
+ Thomas Henlich
+ Sergey Babkin ,
+ Turgut Uyar
+ Rihardas Hepas
+ Szalay Tamas
+ Johan Vromans
+ Petr Titera
+ Lei Wang
+ Chen Xiangyang
+ Zvezdan Petkovic
+ Rigel
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+ This product includes software developed by the TTF2PT1 Project
+ and its contributors.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+For the approximate list of the AUTHORS' responsibilities see the
+project history.
+
+Other contributions to the project are:
+
+Turgut Uyar
+ The Unicode translation table for the Turkish language.
+
+Rihardas Hepas
+ The Unicode translation table for the Baltic languages.
+
+Szalay Tamas
+ The Unicode translation table for the Central European languages.
+
+Johan Vromans
+ The RPM file.
+
+Petr Titera
+ The Unicode map format with names, the forced Unicode option.
+
+Frank M. Siegert
+ Port to Windows
+
+Lei Wang
+Chen Xiangyang
+ Translation maps for Chinese fonts.
+
+Zvezdan Petkovic
+ The Unicode translation tables for the Cyrillic alphabet.
+
+Rigel
+ Generation of the dvips encoding files, modification to the Chinese maps.
+
+I. Lee Hetherington
+ The Type1 assembler (from the package 't1utils'), its full copyright
+ notice:
+ Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.
+ Permission is hereby granted to use, modify, and distribute this program
+ for any purpose provided this copyright notice and the one below remain
+ intact.
+
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/FONTS b/application/third_party/dompdf/lib/ttf2ufm/src/FONTS
new file mode 100644
index 00000000..dc28cc0d
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/FONTS
@@ -0,0 +1,462 @@
+Sergey A. Babkin
+ or
+(Do not edit this file, it is generated from FONTS.html!!!)
+
+THE FONT INSTALLATION GUIDE
+for the TTF to Type1 converter and fonts generated by it
+========================================================
+
+There is historically a number of problems with the support of the 8-bit
+character encodings. This installation guide pays a lot of attention
+to the 8-bit issues, because these issues are responsible for the
+most of troubles during the installation of fonts. But they are
+not the only things covered in this guide, so it's worth reading
+even if all you need is plain ASCII. For convenience of reading
+I have marked the paragraphs dealing solely with 8-bit problems
+with characters *8*.
+
+To simplify this installation the distribution package of the
+converter contains a number of scripts written in shell and
+Perl. So, to run them you will need a shell interpreter (Bourne-shell,
+POSIX-shell, Korn-shell are OK, ba-shell is probably also OK but not
+tested yet). The Perl scripts were tested with Perl5 but probably
+should work with Perl4 too. All the scripts are located in the
+`scripts' subdirectory.
+
+This guide considers the following issues of installation of the
+fonts:
+
+- X11
+- Ghostscript
+- MS Windows
+- Netscape Navigator/Communicator
+- Linux RPM package
+- FrameMaker
+- StarOffice
+
+X11
+===
+
+To simplify the conversion a set of scripts is provided with ttf2pt1.
+They are collected in the `scripts' subdirectory.
+
+`Convert' is the master conversion script provided with ttf2pt1.
+When installed into a public directory it's named `ttf2pt1_convert'
+to avoid name collisions with the other programs.
+
+It's called as:
+
+ convert [config-file]
+
+If the configuration file is not specified as an argument then the file
+`convert.cfg' in the current directory is used. This file contains
+a set of configuration variables. The distribution contains a sample file
+file `convert.cfg.sample'. Please copy it to `convert.cfg',
+look inside it and change the configuration variables. The more stable
+configuration variables, such as the path names of the scripts and
+encoding files are located in `convert' itself, they are
+automatically updated when installing ttf2pt1.
+
+Put all the TTF fonts you want to convert into some directory (this
+may be just the directory that already contains all the Windows
+fonts on a mounted FAT filesystem). If you have fonts in different
+source encoding then put the fonts in each of the encodings
+into a separate directory. Up to 10 source directories are
+supported. If you (in a rather unlikely case) have more source
+directories then you can make two separate runs of the converter,
+converting up to 10 directories at a time.
+
+The variables in the configuration file are:
+
+SRCDIRS - the list of directories (with absolute paths) with
+ TTF fonts. Each line contains at least 3 fields: the name of the directory,
+ the language of the fonts in it (if you have fonts for different
+ languages you have to put them into the separate directories) and the
+ encoding of the fonts. Again, if you have some of the TTF typefaces in
+ one encoding, and some in another (say, CP-1251 and KOI-8), you have
+ to put them into the separate source directories. Some lines may contain
+ 4 fields. Then the fourth field is the name of the external map to
+ convert the Unicode fonts into the desirable encoding. This map is
+ used instead of the built-in map for the specified language.
+
+*8*
+An interesting thing is that some languages have more than one
+widely used character encodings. For example, the widely used
+encodings for Russian are IBM CP-866 (MS-DOS and Unix), KOI-8
+(Unix and VAX, also the standard Internet encoding), IBM CP-1251 (MS Windows).
+That's why I have provided the means to generate the converted fonts
+in more than one encoding. See the file encodings/README for
+details about the encoding tables. Actually, if you plan to use
+these fonts with Netscape Navigator better use the aliases
+cp-866 instead of ibm-866 and windows-1251 instead of ibm-1251
+because that's what Netscape wants.
+
+DSTDIR - directory for the resulting Type1 fonts. Be careful!
+ This directory gets completely wiped out before conversion,
+ so don't use any already existing directory for this purpose.
+
+DSTENC{language} - the list of encodings in which the destination
+ fonts will be generated for each language. Each font of that
+ language will be generated in each of the specified
+ encodings. If you don't want any translation, just specify both
+ SRCENC and DSTENC as iso8859-1 (or if you want any other encoding
+ specified in the fonts.dir, copy the description of 8859-1 with
+ new name and use this new name for SRCENC and DSTENC).
+
+FOUNDRY - the foundry name to be used in the fonts.dir file. I have
+ set it to `fromttf' to avoid name conflicts with any existing font for
+ sure. But this foundry name is not registered in X11 standards and
+ if you want to get the full standard compliance or have a font server
+ that enforces such a compliance, use `misc'.
+
+The next few parameters control the general behavior of the converter.
+They default values are set to something reasonable.
+
+CORRECTWIDTH - if the value is set to YES then use the
+ converter option -w, otherwise don't use it. See the description of
+ this option in the README file.
+
+REMOVET1A - if the value is set to YES then after
+ conversion remove the un-encoded .t1a font files and the
+ intermediate .xpfa font metric files.
+
+INSTALLFONTMAP - a Ghostscript parameter, if the value is set to
+ YES then install the entries for the new fonts
+ right into the main Fontmap file. Otherwise just leave
+ the file Fontmap.ttf in the Ghostscript configuration
+ directory.
+
+HINTSUBST - if the value is set to YES use the option
+ -H, otherwise don't use it. This option enables the
+ hint substitution technique. If you have not installed the X11 patch
+ described above, use this option with great caution. See further
+ description of this option in the README file.
+
+ENFORCEISO - if the value is set to YES then
+ disguise the resulting fonts as the fonts in ISOLatin1 encoding. Historically
+ this was neccessary due to the way the installer scripts created the
+ X11 font configuration files. It is not neccessary any more for this
+ purpose. But if you plan to use these fonts with some other application
+ that expects ISOLatin1 encoding then better enable this option.
+
+ALLGLYPHS - if the value is set to YES then
+ include all the glyphs from the source fonts into the resulting fonts, even
+ if these glyphs are inaccessible. If it's set to NO then
+ include only the glyphs which have codes assigned to them. The glyphs
+ without codes can not be used directly. But some clever programs,
+ such as the Type 1 library from XFree86 3.9 and higher can change
+ the encoding on the fly and use another set of glyphs. If you have not
+ installed the X11 patch described above, use this option with great
+ caution. See further description of the option option -a in the
+ README file.
+
+GENUID - if the value is set to YES then use
+ the option -uA of the converter to generate UniqueIDs for
+ the converted fonts. The standard X11 Type 1 library does not use
+ this ID, so it may only be neccessary for the other applications.
+ The script is clever enough to generate different UniqueID for the
+ same font converted to multiple encodings. Also after conversion it
+ checks all the fonts generacted during the session for duplicated
+ UniqueID and shows those. Still, this does not quarantee that these
+ UniqueIDs won't overlap with some other fonts. The UniqueIDs are
+ generated as hash values from the font names, so it's guaranteed
+ that if the `convert' script runs multiple times it will
+ generate the same UniqueIDs during each run. See further description
+ of this option in the README file.
+
+GENUID - if the value is set to YES then create
+ the .pfb files, otherwise the .pfa files. The .pfb
+ files are more compact but contain binary data, so you may experience some
+ troubles when transferring them through the network.
+
+The following parameters are used to locate the other scripts and
+configuration files. By default the scripts do a bit of guessing for them:
+they search in the ttf2pt1 installation directory if ttf2pt1
+was installed or otherwise suppose that you are running `convert' with
+`scripts' subdirectory being the current directory.
+
+ENCDIR - directory containing the descriptions of encodings
+MAPDIR - directory containing the external map files
+
+Besides that a few parameters are built into the `convert' script itself.
+You probably won't need to change them:
+
+T1ASM, TTF2PT1, TRANS, T1FDIR, FORCEISO - paths to the other script
+
+Also there are a few parameters controlling the installation of
+fonts for Ghostscript. Please look at their description in the
+Ghostscript section of documentation or in the ttf2pt1_x2gs(1)
+manual page before running `convert'. If these parameters are
+set, `convert' will call the `x2gs' script automatically
+to install the newly converted fonts in Ghostscript.
+
+After creating the configuration file run the `convert' script. Look at
+the result and the log file in DSTDIR.
+
+Add the directory with newly converted fonts to the configuration
+of X server or font server. For most of the systems this step is
+very straightforward. For HP-UX it's rather tricky and poorly
+documented, so the file FONTS.hpux gives a short description.
+
+If you don't have the privileges of the root user, you still can
+configure your private font server. Just use some non-standard
+port number (see FONTS.hpux for an example, exept that you won't
+need all the HP-related stuff on any other system).
+
+Known Problems
+--------------
+
+- One catch is that the X11 Type 1 font library has a rather low limit
+ on the font size. Because of this the fonts with more complicated
+ outlines and the enabled hint substitution may not fit into
+ this limit. The same applies to the fonts with very complicated
+ outlines or with very many glyphs (especially the fonts with
+ over 256 glyphs). So you will need to excercise caution with
+ these options if you plan using these fonts with X11. Some vendors
+ such as HP provide the Type 1 implementation licensed from Adobe
+ which should have no such problem.
+
+ But there is a solution even for the generic X11. A patch located
+ in the subdirectory `app/X11' fixes this problem as well
+ as some other minor problems. Its description is provided in
+ app/X11/README.
+
+ To fix the X11 font library, you have to get the X11 sources. I
+ can recommend the ftp sites of the XFree86 project ftp://ftp.xfree86.org
+ or of the Open Group ftp://ftp.x.org. This patch was made on the sources
+ of XFree86 so you may have better success with applying it to the
+ XFree86 distribution. After you have got the sources, make sure
+ that you can compile them. Then apply the patch as described.
+ Make sure that it was applied properly. Compile the sources again
+ (actually, you need only the fonts library, the fonts server, and
+ possibly the X server). It would be prudent now to save your old
+ font library, font server and, possibly, X server. Then install
+ the new recently compiled versions of these files. Of course,
+ if you know someone who already has compiled these files for the
+ same OS as yours, you can just copy the binary fles from him.
+
+ Alas, building the X11 system from the source code is not the
+ easiest thing in the world and if you have no experience it
+ can be quite difficult. In this case just avoid the aforementioned
+ features or check each converted font to make sure that it
+ works properly.
+
+- The Type1 font library from the standard X11 distribution
+ does not work on HP-UX (at least, up to 10.01). The font server
+ supplied with HP-UX up to 10.01 is also broken. Starting from
+ HP-UX 10.20 (I don't know about 10.10) they supply a proprietary font
+ library and the converted fonts work fine with it, provided that
+ they are configured properly (see the file FONTS.hpux).
+
+- The fonts.scale files created by the older versions of the
+ ttf2pt1 installation program (up to release 3.1) have conflicted
+ with the language definitions of the Xfsft font server and
+ parts of it included into XFree86. To overcome this incompatibility
+ the never versions creats the fonts.scale file describing all the
+ fonts as belonging to the adobe-fontspecific encoding and
+ the fonts.alias file with the proper names. The drawback of
+ this solution is that xlsfonts gives the list of twice more
+ fonts. But as a side effect the option ENFORCEISO in
+ `convert.cfg' is not required for X11 any more.
+
+- The conversion script has no support for Eastern multi-plane fonts.
+ Contribution of such a support would be welcome.
+
+Ghostscript
+===========
+
+The fonts generated with ttf2pt1 work fine with Ghostscript by
+themselves. The script `x2gs' (or `ttf2pt1_x2gs' when installed
+into a public directory, to avoid name conflicts with other
+programs) links the font files from the X11 direcotry into the Ghostscript
+directory and automatically creates the description file (Fontmap)
+in Ghostscript format.
+
+It's called as:
+
+ x2gs [config-file]
+
+If the configuration file is not specified as an argument then the file
+`convert.cfg' in the current directory is used, just like the
+`convert' script does. Indeed, this configuration file is used for
+both scripts.
+
+The Ghostscript-related parameters in the configuration file are:
+
+DSTDIR - the X11 font directory used by `x2gs' as the
+ source of the fonts. This parameter is common with the X11
+ configuration.
+
+GSDIR - the base directory of Ghostsript. If this
+ parameter is set to an empty string then `convert' won't
+ call `x2gs'. So if you want to get only the X11 fonts
+ installed then set this parameter to an empty string. This
+ directory may vary on various system, so please check your
+ system and set this value accordingly before running the script.
+
+GSFONTDIR - the font directory of Ghostscript. In the standard
+ Ghostscript installation it's a subdirectory of GSDIR
+ but some systems may use completely different directories.
+
+GSCONFDIR - the configuration subdirectory of Ghostscript
+ that contains the Fontmap file.
+
+INSTALLFONTMAP - if the value is set to YES then
+ install the entries for the new fonts right into the main
+ Fontmap file. Otherwise just leave the file Fontmap.ttf
+ in the Ghostscript configuration directory.
+
+
+After preparing the configuration file run the script. It symbolicaly links
+all the font files and creates the description file Fontmap.ttf in
+GSCONDFIR. After that there are two choices.
+
+If the option INSTALLFONTMAP was set to YES then
+the font descriptions are also automatically installed into the
+master Fontmap file. The script is clever enough to
+detect if it was run multiple times with the same directories
+and if so it replaces the old Fontmap entries with
+the new ones instead of just accumulating all of them. You
+may also run it multiple times for multiple X11 directories
+and all the results will be properly collected in the Fontmap.
+But it's your responsibility to watch that the names of the
+font files don't overlap. If the X11 font directory gets
+renamed then you have to remove its font entries from the
+Fontmap and only after that re-run `x2gs'
+for the new directory.
+
+On the other hand if the option INSTALLFONTMAP was set to
+NO then go to the GSCONFDIR directory and insert the
+contents of Fontmap.ttf into the Fontmap file
+manually. This step may be left manual to make the installation
+a little bit more safe.
+
+After that you may also want to redefine some of the aliases in
+Fontmap to refer to the newly installed fonts.
+But the redefinition of the aliases may be dangerous if the width of
+characters in the new font will be different from the old font.
+Alas, there is no visible solution of this problem yet.
+
+MS Windows
+===========
+
+Ttf2pt1 can be built on Windows either with native compiler or in
+POSIX emulation mode.
+
+Native MS Windows compilers require a different way to build the converter
+instead of the Makefile (their make programs commonly are quite weird
+and limited in capabilities). An example of batch file winbuild.bat
+is provided for MS Visual C/C++. Probably it can be easily adapted for other
+32-bit Windows and DOS compilers. The important part is to define the
+preprocessor symbol WINDOWS during compilation.
+
+Cygnus make almost supports full Makefiles but not quite. Seems
+like its POSIX support is also of the same quality "almost but not quite".
+So another command file cygbuild.sh is provided for Cygnus GNU C, also
+with the preprocessor symbol WINDOWS defined. It is intended to be run from
+the Cygnus BASH shell. To run the programs produced by the Cygnus compiler
+the Cygnus library file CYGWIN1.DLL should be copied first into
+C:\WINDOWS.
+
+To run the accompanying scripts Perl for Windows will be required as well as
+other tools from the Cygnus set.
+
+The Windows support was not particularly tested, so in case of problems with
+building or running the converter please let us know.
+
+The pre-built code (possibly of an older version) of ttf2pt1 for MS Windows is
+available from the GnuWin32 project from
+
+http://gnuwin32.sourceforge.net/packages/ttf2pt1.htm
+
+Netscape Navigator/Communicator
+===============================
+
+Basically, the biggest problem with Netscape Navigator is that
+it has built-in fixed PostScript font names and built-in fixed
+glyph tables for them. Oh, no, that's two! Let's start over:
+basically the two biggest problems of Netscape Navigator are
+that (one)it has built-in fixed PostScript font names and (two)
+built-in fixed glyph tables for them and (three) it always
+assumes that the fonts have ISOLatin1 encoding. OK, let's
+start over again: basically the three biggest problems of Netscape
+Navigator are that (one) it has built-in fixed PostScript font names,
+(two) built-in fixed glyph tables for them and (three) it always
+assumes that the fonts have ISOLatin1 encoding and (four) it
+does not remember the scaled font size between the sessions.
+You did not expect such a Spanish Inquisition, did you ? (*)
+
+Luckily, we have solutions for all of these problems. They are
+located in the subdirectory `app/netscape' and described
+in app/netscape/README.
+
+ -------
+ *) See Monty Python's Flying Circus, episode 15
+
+*8*
+Netscape and cyrillic fonts
+---------------------------
+(courtesy of Zvezdan Petkovic)
+
+If you use TrueType fonts in your X, as I do, and you always get
+KOI8-R encoded pages, then your Netscape does not recognise windows-1251
+encoding. Microsoft TrueType fonts simply declare all encodings they
+can support including KOI8-R. For some reason, KOI8-R always wins over
+ISO-8859-5 in Netscape under X. If you are reading other cyrillic
+languages besides Russian, you might want to either erase KOI8-R entries
+from the fonts.dir and fonts.scale files, or alternatively fix Netscape.
+I put this line in my .Xdefaults.
+
+ Netscape*documentFonts.charset*koi8-r: iso-8859-5
+
+Notice that you can still read Russian sites without trouble because
+Netscape translates KOI8-R to ISO-8859-5 on the fly. I read both Russian
+and Serbian sites with no trouble.
+
+Note: If anybody knows the way to tell Netscape under Unix how to
+recognise {windows,ibm,cp}-1251 encoded fonts, I'd like to hear about that.
+
+Linux RPM package
+=================
+
+The spec file for the creation of a Linux RPM package is located in
+app/RPM. It has been contributed by Johan Vromans. When
+make all is ran in the main directory it among the other
+things creates the version of itself adapted to Linux in app/RPM,
+you may want to copy that version back to the main directory.
+
+Warning: Please note that the install section is incomplete, and
+the installed scripts won't work until the paths inside them
+are corrected.
+
+FrameMaker
+==========
+
+The fonts and AFM files generated by the version 3.2 and higher
+should work with Framemaker without problems. The AFM files
+generated by the previous versions of the converter require a
+line added to them:
+
+ EncodingScheme FontSpecific
+
+And the underscores in the font names of the font and AFM files
+generated by the older versions may need to be changed to dashes.
+
+NOTE by Jason Baietto: Ignore the directions in the Frame on-line docs
+that say to put a "serverdict begin 0 exitserver" line in the pfa files.
+Doing this caused both my printer and ghostscript to choke on the resulting
+output from FrameMaker, so I would not advise doing this (though your
+mileage may vary).
+
+StarOffice
+==========
+
+StarOffice 5.1x has been reported to crash if the .afm file contains
+spaces in the values of such statements as Version, Weight etc.
+These spaces are permitted by the Adobe spec, so this is a problem of
+StarOffice. The easiest way to fix these .afm files for StarOffice
+is to remove spaces in these strings or remove these strings (in case if
+they are optional) at all. This can be done automatically with a sed
+script. It seems that StarOffice 5.2 has this problem fixed, so we decided to
+spend no efforts on providing workarounds for 5.1 with ttf2pt1.
+
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/FONTS.hpux b/application/third_party/dompdf/lib/ttf2ufm/src/FONTS.hpux
new file mode 100644
index 00000000..b9eb4b41
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/FONTS.hpux
@@ -0,0 +1,107 @@
+Sergey A. Babkin
+ or
+(Do not edit this file, it is generated from FONTS.hpux.html!!!)
+
+How to install new Type1 fonts on an HP-UX 10.20 machine
+--------------------------------------------------------
+
+1. Add the font files to /usr/lib/X11/fonts/type1.st/typefaces.
+
+2. Add the font descriptions to
+/usr/lib/X11/fonts/type1.st/typefaces/fonts.scale. Run `mkfontdir'
+in /usr/lib/X11/fonts/type1.st/typefaces. In the descriptions
+you have to specify the font manufacturer as `misc', like:
+
+ -misc-courier-...
+
+3. Copy /usr/lib/X11/fonts/type1.st/typefaces/fonts.dir to
+/usr/lib/X11/fonts/type1.st/licenses/STSYSTEM/DISPLAYS/fonts.dir.
+Better yet, create a symbolic link.
+
+4. For each font encoding you are going to use create a description
+file in /usr/lib/X11/fonts/stadmin/type1/charsets. Of course, if you
+are going to use the same fonts in several encodings, the best way
+would be to create fair descriptions of charsets and really store
+only one encoding in typefaces, all the others will be produced
+automatically. That's not difficult at all.
+But the simplest way is to just copy the file cp.iso8859-1
+to cp., like cp.koi8-r.
+
+5. Restart you X server and/or font server.
+
+What if you don't have the `root' privileges ?
+----------------------------------------------
+
+You still can run the font server and configure your X server
+to get the fonts from it.
+
+Further let's suppose that the name on which you are going
+to run the font server is named `somehost'. Login to it
+and configure the font server.
+
+First, choose some unused port. Numbers around 9000 are a good
+choice. Verify that this port is not used by somebody else
+by entering
+
+ netstat -naf inet |grep 9000
+
+and look what happens. If you get nothing, that's good, this
+port is unused. If you get some lines of data, try abother port.
+
+Go to you home directory $HOME and create some directory for
+your font server, say, $HOME/fs. Copy the directory structure
+of /usr/lib/X11/fonts/type1.st into $HOME/fs, so that in result
+you get $HOME/fs/type1.st/. Copy the directory
+structure of /usr/lib/X11/fonts/stadmin/type1/charsets into $HOME/fs,
+so that in result you get $HOME/fs/charsets/.
+Install the new fonts in these directorues as described above.
+
+Then create the fontserver configuration file, say, $HOME/fs/xfs.cfg.
+The sample contents (supposing that my $HOME is equal to /home/babkin)
+is:
+
+--------------8<----------- cut here -----------------------------
+# font server configuration file
+# $XConsortium: config.cpp,v 1.7 91/08/22 11:39:59 rws Exp $
+
+rasterizers = /usr/lib/X11/fs/ufstrast.sl,/usr/lib/X11/fs/iforast.sl
+
+clone-self = off
+use-syslog = off
+catalogue = /home/babkin/fs/type1.st
+# in decipoints
+default-point-size = 120
+default-resolutions = 100,100,75,75
+port=9000
+error-file=/home/babkin/fs/fs.err
+--------------8<----------- cut here -----------------------------
+
+Then create the script to start your font server, say, $HOME/fs/runme:
+
+--------------8<----------- cut here -----------------------------
+TYPE1_CODEPAGE_DIR=$HOME/fs/charsets
+export TYPE1_CODEPAGE_DIR
+kill `ps -ef | grep $HOME/\[f\]s/xfs.cfg | awk '{print $2}'`;
+nohup xfs -config $HOME/fs/xfs.cfg &
+--------------8<----------- cut here -----------------------------
+
+Don't forget to make $HOME/fs/runme executable. Then you can
+execute it manually or from you .profile.
+
+After you get your font server running, just execute the following
+command (with proper host name and port number) in your X session
+
+ xset fp+ tcp/somehost:9000
+
+to get the access to your private font server. You can add this
+information to the configuration data of your X server or just
+put it also into your .profile. In the latter case the best way
+to do that would be like:
+
+--------------8<----------- cut here -----------------------------
+...
+$HOME/fs/runme
+sleep 2 # give it some time to start
+xset fp+ tcp/somehost:9000
+...
+--------------8<----------- cut here -----------------------------
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/FONTS.hpux.html b/application/third_party/dompdf/lib/ttf2ufm/src/FONTS.hpux.html
new file mode 100644
index 00000000..80889cae
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/FONTS.hpux.html
@@ -0,0 +1,197 @@
+
+
+
+How to install new Type1 fonts on an HP-UX 10.20 machine
+
+
+
+Sergey A. Babkin
+
+
+<babkin@bellatlantic.net> or <sab123@hotmail.com>
+
+
+
+
+How to install new Type1 fonts on an HP-UX 10.20 machine
+
+
+
+1. Add the font files to /usr/lib/X11/fonts/type1.st/typefaces.
+
+
+2. Add the font descriptions to
+/usr/lib/X11/fonts/type1.st/typefaces/fonts.scale. Run `mkfontdir'
+in /usr/lib/X11/fonts/type1.st/typefaces. In the descriptions
+you have to specify the font manufacturer as `misc', like:
+
+
+
+ -misc-courier-...
+
+
+
+3. Copy /usr/lib/X11/fonts/type1.st/typefaces/fonts.dir to
+/usr/lib/X11/fonts/type1.st/licenses/STSYSTEM/DISPLAYS/fonts.dir.
+Better yet, create a symbolic link.
+
+
+4. For each font encoding you are going to use create a description
+file in /usr/lib/X11/fonts/stadmin/type1/charsets. Of course, if you
+are going to use the same fonts in several encodings, the best way
+would be to create fair descriptions of charsets and really store
+only one encoding in typefaces, all the others will be produced
+automatically. That's not difficult at all.
+But the simplest way is to just copy the file cp.iso8859-1
+to cp.<your-encoding-name>, like cp.koi8-r.
+
+
+5. Restart you X server and/or font server.
+
+
+
+What if you don't have the `root' privileges ?
+
+
+
+You still can run the font server and configure your X server
+to get the fonts from it.
+
+
+Further let's suppose that the name on which you are going
+to run the font server is named `somehost'. Login to it
+and configure the font server.
+
+
+First, choose some unused port. Numbers around 9000 are a good
+choice. Verify that this port is not used by somebody else
+by entering
+
+
+
+ netstat -naf inet |grep 9000
+
+
+and look what happens. If you get nothing, that's good, this
+port is unused. If you get some lines of data, try abother port.
+
+
+Go to you home directory $HOME and create some directory for
+your font server, say, $HOME/fs. Copy the directory structure
+of /usr/lib/X11/fonts/type1.st into $HOME/fs, so that in result
+you get $HOME/fs/type1.st/<whatever was there>. Copy the directory
+structure of /usr/lib/X11/fonts/stadmin/type1/charsets into $HOME/fs,
+so that in result you get $HOME/fs/charsets/<whatever was there>.
+Install the new fonts in these directorues as described above.
+
+
+Then create the fontserver configuration file, say, $HOME/fs/xfs.cfg.
+The sample contents (supposing that my $HOME is equal to /home/babkin)
+is:
+
+
+
+
+
+# font server configuration file
+
+# $XConsortium: config.cpp,v 1.7 91/08/22 11:39:59 rws Exp $
+
+
+
+rasterizers = /usr/lib/X11/fs/ufstrast.sl,/usr/lib/X11/fs/iforast.sl
+
+
+
+clone-self = off
+
+use-syslog = off
+
+catalogue = /home/babkin/fs/type1.st
+
+# in decipoints
+
+default-point-size = 120
+
+default-resolutions = 100,100,75,75
+
+port=9000
+
+error-file=/home/babkin/fs/fs.err
+
+
+
+
+
+Then create the script to start your font server, say, $HOME/fs/runme:
+
+
+
+
+
+TYPE1_CODEPAGE_DIR=$HOME/fs/charsets
+
+export TYPE1_CODEPAGE_DIR
+
+kill `ps -ef | grep $HOME/\[f\]s/xfs.cfg | awk '{print $2}'`;
+
+nohup xfs -config $HOME/fs/xfs.cfg &
+
+
+
+
+
+Don't forget to make $HOME/fs/runme executable. Then you can
+execute it manually or from you .profile.
+
+
+After you get your font server running, just execute the following
+command (with proper host name and port number) in your X session
+
+
+
+ xset fp+ tcp/somehost:9000
+
+
+to get the access to your private font server. You can add this
+information to the configuration data of your X server or just
+put it also into your .profile. In the latter case the best way
+to do that would be like:
+
+
+
+
+
+...
+
+$HOME/fs/runme
+
+sleep 2 # give it some time to start
+
+xset fp+ tcp/somehost:9000
+
+...
+
+
+
+
+
+
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/FONTS.html b/application/third_party/dompdf/lib/ttf2ufm/src/FONTS.html
new file mode 100644
index 00000000..352bd069
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/FONTS.html
@@ -0,0 +1,708 @@
+
+
+
+The ttf2pt1 font installation guide
+
+
+
+Sergey A. Babkin
+
+
+<babkin@bellatlantic.net> or <sab123@hotmail.com>
+
+
+
+
+
+
+THE FONT INSTALLATION GUIDE
+
+for the TTF to Type1 converter and fonts generated by it
+
+
+
+There is historically a number of problems with the support of the 8-bit
+character encodings. This installation guide pays a lot of attention
+to the 8-bit issues, because these issues are responsible for the
+most of troubles during the installation of fonts. But they are
+not the only things covered in this guide, so it's worth reading
+even if all you need is plain ASCII. For convenience of reading
+I have marked the paragraphs dealing solely with 8-bit problems
+with characters *8*.
+
+
+To simplify this installation the distribution package of the
+converter contains a number of scripts written in shell and
+Perl. So, to run them you will need a shell interpreter (Bourne-shell,
+POSIX-shell, Korn-shell are OK, ba-shell is probably also OK but not
+tested yet). The Perl scripts were tested with Perl5 but probably
+should work with Perl4 too. All the scripts are located in the
+`scripts' subdirectory.
+
+
+This guide considers the following issues of installation of the
+fonts:
+
+
+
+
+
+X11
+
+
+
+
+
+
+To simplify the conversion a set of scripts is provided with ttf2pt1.
+They are collected in the `scripts' subdirectory.
+
+
+
+`Convert' is the master conversion script provided with ttf2pt1.
+When installed into a public directory it's named `ttf2pt1_convert'
+to avoid name collisions with the other programs.
+
+
+
+It's called as:
+
+
+
+
+
+
+ convert [config-file]
+
+
+
+If the configuration file is not specified as an argument then the file
+`convert.cfg' in the current directory is used. This file contains
+a set of configuration variables. The distribution contains a sample file
+file `convert.cfg.sample'. Please copy it to `convert.cfg',
+look inside it and change the configuration variables. The more stable
+configuration variables, such as the path names of the scripts and
+encoding files are located in `convert' itself, they are
+automatically updated when installing ttf2pt1.
+
+
+Put all the TTF fonts you want to convert into some directory (this
+may be just the directory that already contains all the Windows
+fonts on a mounted FAT filesystem). If you have fonts in different
+source encoding then put the fonts in each of the encodings
+into a separate directory. Up to 10 source directories are
+supported. If you (in a rather unlikely case) have more source
+directories then you can make two separate runs of the converter,
+converting up to 10 directories at a time.
+
+
+The variables in the configuration file are:
+
+
+
+
+SRCDIRS - the list of directories (with absolute paths) with
+ TTF fonts. Each line contains at least 3 fields: the name of the directory,
+ the language of the fonts in it (if you have fonts for different
+ languages you have to put them into the separate directories) and the
+ encoding of the fonts. Again, if you have some of the TTF typefaces in
+ one encoding, and some in another (say, CP-1251 and KOI-8), you have
+ to put them into the separate source directories. Some lines may contain
+ 4 fields. Then the fourth field is the name of the external map to
+ convert the Unicode fonts into the desirable encoding. This map is
+ used instead of the built-in map for the specified language.
+
+
+*8*
+An interesting thing is that some languages have more than one
+widely used character encodings. For example, the widely used
+encodings for Russian are IBM CP-866 (MS-DOS and Unix), KOI-8
+(Unix and VAX, also the standard Internet encoding), IBM CP-1251 (MS Windows).
+That's why I have provided the means to generate the converted fonts
+in more than one encoding. See the file encodings/README for
+details about the encoding tables. Actually, if you plan to use
+these fonts with Netscape Navigator better use the aliases
+cp-866 instead of ibm-866 and windows-1251 instead of ibm-1251
+because that's what Netscape wants.
+
+
+
+DSTDIR - directory for the resulting Type1 fonts. Be careful!
+ This directory gets completely wiped out before conversion,
+ so don't use any already existing directory for this purpose.
+
+
+
+DSTENC{language} - the list of encodings in which the destination
+ fonts will be generated for each language. Each font of that
+ language will be generated in each of the specified
+ encodings. If you don't want any translation, just specify both
+ SRCENC and DSTENC as iso8859-1 (or if you want any other encoding
+ specified in the fonts.dir, copy the description of 8859-1 with
+ new name and use this new name for SRCENC and DSTENC).
+
+
+
+FOUNDRY - the foundry name to be used in the fonts.dir file. I have
+ set it to `fromttf' to avoid name conflicts with any existing font for
+ sure. But this foundry name is not registered in X11 standards and
+ if you want to get the full standard compliance or have a font server
+ that enforces such a compliance, use `misc'.
+
+
+
+The next few parameters control the general behavior of the converter.
+They default values are set to something reasonable.
+
+
+
+
+CORRECTWIDTH - if the value is set to YES then use the
+ converter option -w, otherwise don't use it. See the description of
+ this option in the README file.
+
+
+
+REMOVET1A - if the value is set to YES then after
+ conversion remove the un-encoded .t1a font files and the
+ intermediate .xpfa font metric files.
+
+
+
+INSTALLFONTMAP - a Ghostscript parameter, if the value is set to
+ YES then install the entries for the new fonts
+ right into the main Fontmap file. Otherwise just leave
+ the file Fontmap.ttf in the Ghostscript configuration
+ directory.
+
+
+
+HINTSUBST - if the value is set to YES use the option
+ -H, otherwise don't use it. This option enables the
+ hint substitution technique. If you have not installed the X11 patch
+ described above, use this option with great caution. See further
+ description of this option in the README file.
+
+
+
+ENFORCEISO - if the value is set to YES then
+ disguise the resulting fonts as the fonts in ISOLatin1 encoding. Historically
+ this was neccessary due to the way the installer scripts created the
+ X11 font configuration files. It is not neccessary any more for this
+ purpose. But if you plan to use these fonts with some other application
+ that expects ISOLatin1 encoding then better enable this option.
+
+
+
+ALLGLYPHS - if the value is set to YES then
+ include all the glyphs from the source fonts into the resulting fonts, even
+ if these glyphs are inaccessible. If it's set to NO then
+ include only the glyphs which have codes assigned to them. The glyphs
+ without codes can not be used directly. But some clever programs,
+ such as the Type 1 library from XFree86 3.9 and higher can change
+ the encoding on the fly and use another set of glyphs. If you have not
+ installed the X11 patch described above, use this option with great
+ caution. See further description of the option option -a in the
+ README file.
+
+
+
+GENUID - if the value is set to YES then use
+ the option -uA of the converter to generate UniqueIDs for
+ the converted fonts. The standard X11 Type 1 library does not use
+ this ID, so it may only be neccessary for the other applications.
+ The script is clever enough to generate different UniqueID for the
+ same font converted to multiple encodings. Also after conversion it
+ checks all the fonts generacted during the session for duplicated
+ UniqueID and shows those. Still, this does not quarantee that these
+ UniqueIDs won't overlap with some other fonts. The UniqueIDs are
+ generated as hash values from the font names, so it's guaranteed
+ that if the `convert' script runs multiple times it will
+ generate the same UniqueIDs during each run. See further description
+ of this option in the README file.
+
+
+
+GENUID - if the value is set to YES then create
+ the .pfb files, otherwise the .pfa files. The .pfb
+ files are more compact but contain binary data, so you may experience some
+ troubles when transferring them through the network.
+
+
+
+The following parameters are used to locate the other scripts and
+configuration files. By default the scripts do a bit of guessing for them:
+they search in the ttf2pt1 installation directory if ttf2pt1
+was installed or otherwise suppose that you are running `convert' with
+`scripts' subdirectory being the current directory.
+
+
+
+
+ENCDIR - directory containing the descriptions of encodings
+
+
+MAPDIR - directory containing the external map files
+
+
+
+Besides that a few parameters are built into the `convert' script itself.
+You probably won't need to change them:
+
+
+
+
+T1ASM, TTF2PT1, TRANS, T1FDIR, FORCEISO - paths to the other script
+
+
+
+Also there are a few parameters controlling the installation of
+fonts for Ghostscript. Please look at their description in the
+Ghostscript section of documentation or in the ttf2pt1_x2gs(1)
+manual page before running `convert'. If these parameters are
+set, `convert' will call the `x2gs' script automatically
+to install the newly converted fonts in Ghostscript.
+
+
+After creating the configuration file run the `convert' script. Look at
+the result and the log file in DSTDIR.
+
+
+Add the directory with newly converted fonts to the configuration
+of X server or font server. For most of the systems this step is
+very straightforward. For HP-UX it's rather tricky and poorly
+documented, so the file FONTS.hpux gives a short description.
+
+
+If you don't have the privileges of the root user, you still can
+configure your private font server. Just use some non-standard
+port number (see FONTS.hpux for an example, exept that you won't
+need all the HP-related stuff on any other system).
+
+
+
+
+Known Problems
+
+
+
+
+
+
+- One catch is that the X11 Type 1 font library has a rather low limit
+ on the font size. Because of this the fonts with more complicated
+ outlines and the enabled hint substitution may not fit into
+ this limit. The same applies to the fonts with very complicated
+ outlines or with very many glyphs (especially the fonts with
+ over 256 glyphs). So you will need to excercise caution with
+ these options if you plan using these fonts with X11. Some vendors
+ such as HP provide the Type 1 implementation licensed from Adobe
+ which should have no such problem.
+
+
+ But there is a solution even for the generic X11. A patch located
+ in the subdirectory `app/X11' fixes this problem as well
+ as some other minor problems. Its description is provided in
+ app/X11/README.
+
+
+ To fix the X11 font library, you have to get the X11 sources. I
+ can recommend the ftp sites of the XFree86 project ftp://ftp.xfree86.org
+ or of the Open Group ftp://ftp.x.org. This patch was made on the sources
+ of XFree86 so you may have better success with applying it to the
+ XFree86 distribution. After you have got the sources, make sure
+ that you can compile them. Then apply the patch as described.
+ Make sure that it was applied properly. Compile the sources again
+ (actually, you need only the fonts library, the fonts server, and
+ possibly the X server). It would be prudent now to save your old
+ font library, font server and, possibly, X server. Then install
+ the new recently compiled versions of these files. Of course,
+ if you know someone who already has compiled these files for the
+ same OS as yours, you can just copy the binary fles from him.
+
+
+ Alas, building the X11 system from the source code is not the
+ easiest thing in the world and if you have no experience it
+ can be quite difficult. In this case just avoid the aforementioned
+ features or check each converted font to make sure that it
+ works properly.
+
+
+
- The Type1 font library from the standard X11 distribution
+ does not work on HP-UX (at least, up to 10.01). The font server
+ supplied with HP-UX up to 10.01 is also broken. Starting from
+ HP-UX 10.20 (I don't know about 10.10) they supply a proprietary font
+ library and the converted fonts work fine with it, provided that
+ they are configured properly (see the file FONTS.hpux).
+
+
+
- The fonts.scale files created by the older versions of the
+ ttf2pt1 installation program (up to release 3.1) have conflicted
+ with the language definitions of the Xfsft font server and
+ parts of it included into XFree86. To overcome this incompatibility
+ the never versions creats the fonts.scale file describing all the
+ fonts as belonging to the adobe-fontspecific encoding and
+ the fonts.alias file with the proper names. The drawback of
+ this solution is that xlsfonts gives the list of twice more
+ fonts. But as a side effect the option ENFORCEISO in
+ `convert.cfg' is not required for X11 any more.
+
+
+
- The conversion script has no support for Eastern multi-plane fonts.
+ Contribution of such a support would be welcome.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ghostscript
+
+
+
+
+
+
+
+The fonts generated with ttf2pt1 work fine with Ghostscript by
+themselves. The script `x2gs' (or `ttf2pt1_x2gs' when installed
+into a public directory, to avoid name conflicts with other
+programs) links the font files from the X11 direcotry into the Ghostscript
+directory and automatically creates the description file (Fontmap)
+in Ghostscript format.
+
+
+It's called as:
+
+
+
+
+
+
+ x2gs [config-file]
+
+
+
+If the configuration file is not specified as an argument then the file
+`convert.cfg' in the current directory is used, just like the
+`convert' script does. Indeed, this configuration file is used for
+both scripts.
+
+
+The Ghostscript-related parameters in the configuration file are:
+
+
+DSTDIR - the X11 font directory used by `x2gs' as the
+ source of the fonts. This parameter is common with the X11
+ configuration.
+
+
+GSDIR - the base directory of Ghostsript. If this
+ parameter is set to an empty string then `convert' won't
+ call `x2gs'. So if you want to get only the X11 fonts
+ installed then set this parameter to an empty string. This
+ directory may vary on various system, so please check your
+ system and set this value accordingly before running the script.
+
+
+GSFONTDIR - the font directory of Ghostscript. In the standard
+ Ghostscript installation it's a subdirectory of GSDIR
+ but some systems may use completely different directories.
+
+
+GSCONFDIR - the configuration subdirectory of Ghostscript
+ that contains the Fontmap file.
+
+
+INSTALLFONTMAP - if the value is set to YES then
+ install the entries for the new fonts right into the main
+ Fontmap file. Otherwise just leave the file Fontmap.ttf
+ in the Ghostscript configuration directory.
+
+
+
+After preparing the configuration file run the script. It symbolicaly links
+all the font files and creates the description file Fontmap.ttf in
+GSCONDFIR. After that there are two choices.
+
+
+If the option INSTALLFONTMAP was set to YES then
+the font descriptions are also automatically installed into the
+master Fontmap file. The script is clever enough to
+detect if it was run multiple times with the same directories
+and if so it replaces the old Fontmap entries with
+the new ones instead of just accumulating all of them. You
+may also run it multiple times for multiple X11 directories
+and all the results will be properly collected in the Fontmap.
+But it's your responsibility to watch that the names of the
+font files don't overlap. If the X11 font directory gets
+renamed then you have to remove its font entries from the
+Fontmap and only after that re-run `x2gs'
+for the new directory.
+
+
+On the other hand if the option INSTALLFONTMAP was set to
+NO then go to the GSCONFDIR directory and insert the
+contents of Fontmap.ttf into the Fontmap file
+manually. This step may be left manual to make the installation
+a little bit more safe.
+
+
+After that you may also want to redefine some of the aliases in
+Fontmap to refer to the newly installed fonts.
+But the redefinition of the aliases may be dangerous if the width of
+characters in the new font will be different from the old font.
+Alas, there is no visible solution of this problem yet.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+MS Windows
+
+
+
+Ttf2pt1 can be built on Windows either with native compiler or in
+POSIX emulation mode.
+
+
+Native MS Windows compilers require a different way to build the converter
+instead of the Makefile (their make programs commonly are quite weird
+and limited in capabilities). An example of batch file winbuild.bat
+is provided for MS Visual C/C++. Probably it can be easily adapted for other
+32-bit Windows and DOS compilers. The important part is to define the
+preprocessor symbol WINDOWS during compilation.
+
+
+Cygnus make almost supports full Makefiles but not quite. Seems
+like its POSIX support is also of the same quality "almost but not quite".
+So another command file cygbuild.sh is provided for Cygnus GNU C, also
+with the preprocessor symbol WINDOWS defined. It is intended to be run from
+the Cygnus BASH shell. To run the programs produced by the Cygnus compiler
+the Cygnus library file CYGWIN1.DLL should be copied first into
+C:\WINDOWS.
+
+
+To run the accompanying scripts Perl for Windows will be required as well as
+other tools from the Cygnus set.
+
+
+The Windows support was not particularly tested, so in case of problems with
+building or running the converter please let us know.
+
+
+The pre-built code (possibly of an older version) of ttf2pt1 for MS Windows is
+available from the GnuWin32 project from
+
+http://gnuwin32.sourceforge.net/packages/ttf2pt1.htm
+
+Netscape Navigator/Communicator
+
+
+
+Basically, the biggest problem with Netscape Navigator is that
+it has built-in fixed PostScript font names and built-in fixed
+glyph tables for them. Oh, no, that's two! Let's start over:
+basically the two biggest problems of Netscape Navigator are
+that (one)it has built-in fixed PostScript font names and (two)
+built-in fixed glyph tables for them and (three) it always
+assumes that the fonts have ISOLatin1 encoding. OK, let's
+start over again: basically the three biggest problems of Netscape
+Navigator are that (one) it has built-in fixed PostScript font names,
+(two) built-in fixed glyph tables for them and (three) it always
+assumes that the fonts have ISOLatin1 encoding and (four) it
+does not remember the scaled font size between the sessions.
+You did not expect such a Spanish Inquisition, did you ? (*)
+
+
+Luckily, we have solutions for all of these problems. They are
+located in the subdirectory `app/netscape' and described
+in app/netscape/README.
+
+
+
+ -------
+ *) See Monty Python's Flying Circus, episode 15
+ +*8* +
+ +
+ Netscape*documentFonts.charset*koi8-r: iso-8859-5 ++
+ +Notice that you can still read Russian sites without trouble because +Netscape translates KOI8-R to ISO-8859-5 on the fly. I read both Russian +and Serbian sites with no trouble. +
+ +Note: If anybody knows the way to tell Netscape under Unix how to +recognise {windows,ibm,cp}-1251 encoded fonts, I'd like to hear about that. +
+ +Warning: Please note that the install section is incomplete, and +the installed scripts won't work until the paths inside them +are corrected. +
+ + EncodingScheme FontSpecific +
+ +And the underscores in the font names of the font and AFM files +generated by the older versions may need to be changed to dashes. +
+ +NOTE by Jason Baietto: Ignore the directions in the Frame on-line docs +that say to put a "serverdict begin 0 exitserver" line in the pfa files. +Doing this caused both my printer and ghostscript to choke on the resulting +output from FrameMaker, so I would not advise doing this (though your +mileage may vary). +
+
+
+
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/Makefile b/application/third_party/dompdf/lib/ttf2ufm/src/Makefile
new file mode 100644
index 00000000..3a81cdc8
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/Makefile
@@ -0,0 +1,279 @@
+
+# This file should be configured before running `make'.
+# Uncomment or change the values that are relevant for your OS.
+
+# The preferred C compiler (by default use the OS-specific default value).
+# For BSD/OS, FreeBSD, Linux (all flavors), NetBSD, OpenBSD the default
+# compiler is GNU C.
+# (Note please the politically correct ordering by alphabet ! :-)
+#
+# Use GNU C even if it's not the default compiler
+#
+#CC=gcc
+#
+# Use the standard ANSI C compiler on HP-UX even if it's not default
+#
+#CC=c89
+
+#
+# The system-dependent flags for the C compiler
+#
+# Default
+
+CFLAGS_SYS= -g
+
+# For GNU C
+#
+#CFLAGS_SYS= -O2
+#
+# For GNU C with long options support library (Linux etc.)
+#
+#CFLAGS_SYS= -O2 -D_GNU_SOURCE
+#
+# For GNU C on HP-UX/PA-RISC 1.1
+#
+#CFLAGS_SYS= -O2 -Wa,-w
+#
+# For the standard ANSI C on HP-UX
+#
+#CFLAGS_SYS= +O2 -D_HPUX_SOURCE
+
+#
+# The system-dependent libraries
+#
+# Defalut (for the BSD-style OSes)
+
+LIBS_SYS= -lm
+
+# For SystemV (such as SCO, UnixWare, Solaris, but _NOT_ Linux or HP-UX)
+#
+#LIBS_SYS= -lm -lsocket
+
+#
+# The flags for C compiler for the FreeType-2 library (disabled by default).
+# This WON'T BUILD with FT2-beta8, use the FreeType release 2.0.4
+# http://download.sourceforge.net/freetype/freetype-2.0.4.tar.gz
+
+#CFLAGS_FT=
+
+# To enable use of the FreeType-2 library
+# (if the include and lib directory do not match your installation,
+# modify them), also uncomment LIBS_FT
+#
+CFLAGS_FT = -DUSE_FREETYPE -I/usr/include/freetype2 -I/usr/include
+
+#
+# The FreeType-2 library flags (disabled by default)
+
+#LIBS_FT=
+
+# To enable use of the FreeType-2 library
+# (if the include and lib directory do not match your installation,
+# modify them), also uncomment CFLAGS_FT
+#
+LIBS_FT= -L/usr/lib -lfreetype
+
+#
+# The flags for C compiler for the Autotrace library (disabled by default).
+# USE OF THIS FEATURE IS STRONGLY DISCOURAGED, THE BUILT-IN TRACING
+# (AKA VECTORIZATION) PROVIDES MUCH BETTER RESULTS.
+# The tested version is 0.29a (and the fonts produced with it are
+# absolutely not usable).
+# http://download.sourceforge.net/autotrace/autotrace-0.29.tar.gz
+
+CFLAGS_AT=
+
+# To enable use of the Autotrace library
+# (if the include and lib directory do not match your installation,
+# modify them), also uncomment LIBS_AT
+#
+#CFLAGS_AT = -DUSE_AUTOTRACE -I/usr/local/include
+
+#
+# The Autotrace library flags (disabled by default)
+
+LIBS_AT=
+
+# To enable use of the Autotrace library
+# (if the include and lib directory do not match your installation,
+# modify them), also uncomment CFLAGS_AT
+#
+#LIBS_AT= -L/usr/local/lib -lautotrace
+
+#
+# Preference of front-ends if multiple parsers match a file
+# (by default the build-in front-end takes preference over FreeType)
+
+CFLAGS_PREF=
+
+# To prefer FreeType (if enabled):
+#
+#CFLAGS_PREF= -DPREFER_FREETYPE
+
+# Uncomment the second line to not compile t1asm into ttf2pt1
+CFLAGS_EXTT1ASM=
+#CFLAGS_EXTT1ASM= -DEXTERNAL_T1ASM
+
+CFLAGS= $(CFLAGS_SYS) $(CFLAGS_FT) $(CFLAGS_AT) $(CFLAGS_PREF)
+LIBS= $(LIBS_SYS) $(LIBS_FT) $(LIBS_AT)
+
+# Installation-related stuff
+#
+# The base dir for installation and subdirs in it
+INSTDIR = /usr/local
+# for binaries
+BINDIR = $(INSTDIR)/bin
+# for binaries of little general interest
+LIBXDIR = $(INSTDIR)/libexec/ttf2pt1
+# for scripts, maps/encodings etc.
+SHAREDIR = $(INSTDIR)/share/ttf2pt1
+MANDIR = $(INSTDIR)/man
+
+# owner and group of installed files
+OWNER = root
+GROUP = bin
+
+# After you have configured the Makefile, comment out the following
+# definition:
+warning: docs
+ @echo >&2
+ @echo " You have to configure the Makefile before running make!" >&2
+ @echo "(or if you are lazy and hope that it will work as is run \`make all')">&2
+ @echo >&2
+
+DOCS=CHANGES README FONTS FONTS.hpux encodings/README other/README \
+ app/X11/README app/netscape/README app/TeX/README
+
+SUBDIRS = app encodings maps scripts other
+TXTFILES = README* FONTS* CHANGES* COPYRIGHT
+
+MANS1=ttf2pt1.1 ttf2pt1_convert.1 ttf2pt1_x2gs.1
+MANS=$(MANS1) $(MANS5)
+
+all: t1asm ttf2pt1 docs mans rpm
+
+docs: $(DOCS)
+
+mans: $(MANS)
+
+clean:
+ rm -f t1asm ttf2pt1 *.o app/RPM/Makefile app/RPM/*.spec *.core core.* core
+ ( cd other && make clean; )
+ ( cd app/netscape && make clean; )
+
+veryclean: clean
+ rm -f $(DOCS) $(MANS)
+
+rpm: app/RPM/Makefile app/RPM/ttf2pt1.spec
+
+ttf2pt1.1: README.html
+ scripts/html2man . .
+
+Ever wanted to install a particular font on your XServer but only could find
+the font you are after in True Type Format?
+
+
+Ever asked comp.fonts for a True Type to Type 1 converter and got a List
+of Commercial software that doesn't run on your Operating System?
+
+
+Well, this program should be the answer. This program is written in C (so it
+should be portable) and therefore should run on any OS. The only limitation
+is that the program requires some method of converting Big endian integers into
+local host integers so the network functions ntohs and ntohl are used. These
+can be replaced by macros if your platform doesn't have them.
+Of course the target platform requires a C compiler and command line ability.
+
+
+
+Ttf2pt1 is a font converter from the True Type format (and some other formats
+supported by the FreeType library as well) to the Adobe Type1 format.
+
+
+The versions 3.0 and later got rather extensive post-processing algorithm that
+brings the converted fonts to the requirements of the Type1 standard, tries to
+correct the rounding errors introduced during conversions and some simple
+kinds of bugs that are typical for the public domain TTF fonts. It
+also generates the hints that enable much better rendering of fonts in
+small sizes that are typical for the computer displays. But everything
+has its price, and some of the optimizations may not work well for certain
+fonts. That's why the options were added to the converter, to control
+the performed optimizations.
+
+
+
+The converter is simple to run, just:
+
+
+
+
+
+
+The first variant creates the file Fontname.pfa (or Fontname.pfb if the
+option '-b' was used) with the converted font and Fontname.afm with the
+font metrics, the second one prints the font or another file (if the option
+'-G' was used) on the standard output from where it can be immediately
+piped through some filter. If no Fontname is specified for the first
+variant, the name is generated from ttffont by replacing the .ttf
+filename suffix.
+
+
+Most of the time no options are neccessary (with a possible exception
+of '-e'). But if there are some troubles with the resulting font, they
+may be used to control the conversion.
+The options are:
+
+
+
+
+-a - Include all the glyphs from the source file into the converted
+ file. If this option is not specified then only the glyphs that have
+ been assigned some encoding are included, because the rest of glyphs
+ would be inaccessible anyway and would only consume the disk space.
+ But some applications are clever enough to change the encoding on
+ the fly and thus use the other glyphs, in this case they could
+ benefit from using this option. But there is a catch: the X11 library
+ has rather low limit for the font size. Including more glyphs increases
+ the file size and thus increases the chance of hitting this limit.
+ See app/X11/README for the description of a
+ patch to X11 which fixes this problem.
+
+
+
+-b - Encode the resulting font to produce a ready .pfb file.
+
+
+
+-d suboptions - Debugging options. The suboptions are:
+
+
+
+
+ r - Do not reverse the direction of outlines. The TTF fonts have
+ the standard direction of outlines opposite to the Type1 fonts. So
+ they should be reversed during proper conversion. This option
+ may be used for debugging or to handle a TTF font with wrong
+ direction of outlines (possibly, converted in a broken way from
+ a Type1 font). The first signs of the wrong direction are the
+ letters like "P" or "B" without the unpainted "holes" inside.
+
+
+
+
+-F - Force the Unicode encoding: any type of MS encoding specified
+ in the font is ignored and the font is treated like it has Unicode
+ encoding. WARNING: this option is intended for buggy fonts
+ which actually are in Unicode but are marked as something else. The
+ effect on the other fonts is unpredictable.
+
+
+
+-G suboptions - File generation options. The suboptions may be lowercase
+ or uppercase, the lowercase ones disable the generation of particular
+ files, the corresponding uppercase suboptions enable the generation of the
+ same kind of files. If the result of ttf2pt1 is requested to be printed on
+ the standard output, the last enabling suboption of -G determines
+ which file will be written to the standard output and the rest of files
+ will be discarded. For example, -G A will request the AFM file.
+ The suboptions to disable/enable the generation of the files are:
+
+
+
+
+ a/A - The Adobe font metrics file (.afm).
+ Default: enabled
+
+
+ e/E - The dvips encoding file (.enc).
+ Default: disabled
+
+
+
+
+ After the plus sign an optional argument for the language extractor
+ may be specified. The format of the argument is absolutely up to
+ the particular language converter. The primary purpose of the
+ argument is to support selection of planes for the multi-plane
+ Eastern encodings but it can also be used in any other way. The
+ language extractor may decide to add the plane name in some form
+ to the name of the resulting font. None of the currently supported
+ languages make any use of the argument yet.
+
+
+ As of now the following languages are supported:
+
+
+ The argument of the "plane" language may be in one of three forms:
+
+ plane+pid=<pid>,eid=<eid>
+
+
+ Pid (TTF platform id) and eid (TTF encoding id) select a particular
+ TTF encoding table in the original font. They are specified as decimal
+ numbers. If this particular encoding table is not present in the font
+ file then the conversion fails. The native ("ttf") front-end parser supports
+ only pid=3 (Windows platform), the FreeType-based ("ft") front-end supports
+ any platform. If pid/eid is not specified then the TTF encoding table is
+ determined as usual: Unicode encoding if it's first or an 8-bit encoding
+ if not (and for an 8-bit encoding the plane number is silently ignored).
+ To prevent the converter from falling back to an 8-bit encoding, specify
+ the Unicode pid/eid value explicitly.
+
+
+ Plane_number is a hexadecimal (if starts with "0x") or decimal number.
+ It gives the values of upper bytes for which 256 characters will be
+ selected. If not specified, defaults to 0. It is also used as a font
+ name suffix (the leading "0x" is not included into the suffix).
+
+
+
+ NOTE:
+
+ It seems that many Eastern fonts use features of the TTF format that are
+ not supported by the ttf2pt1's built-in front-end parser. Because of
+ this for now we recommend using the FreeType-based parser (option
+ '-p ft') with the "plane" language.
+
+
+
+
+
+ NOTE:
+ You may notice that the language names are not uniform: some are the
+ names of particular languages and some are names of encodings. This
+ is because of the different approaches. The original idea was to
+ implement a conversion from Unicode to the appropriate Windows
+ encoding for a given language. And then use the translation tables
+ to generate the fonts in whatever final encodings are needed. This
+ would allow to pile together the Unicode fonts and the non-Unicode
+ Windows fonts for that language and let the program to sort them out
+ automatically. And then generate fonts in all the possible encodings
+ for that language. An example of this approach is the Russian language
+ support. But if there is no multiplicity of encodings used for some
+ languages and if the non-Unicode fonts are not considered important
+ by the users, another way would be simpler to implement: just provide
+ only one table for extraction of the target encoding from Unicode
+ and don't bother with the translation tables. The latin* "languages"
+ are examples of this approach. If somebody feels that he needs the
+ Type1 fonts both in Latin-* and Windows encodings he or she is absolutely
+ welcome to submit the code to implement it.
+
+
+ WARNING:
+ Some of the glyphs included into the AdobeStandard encoding are not
+ included into the Unicode standard. The most typical examples of such
+ glyphs are ligatures like 'fi', 'fl' etc. Because of this the font
+ designers may place them at various places. The converter tries to
+ do its best, if the glyphs have honest Adobe names and/or are
+ placed at the same codes as in the Microsoft fonts they will be
+ picked up. Otherwise a possible solution is to use the option '-L'
+ with an external map.
+
+
+
+-L file[+[pid=<pid>,eid=<eid>,][plane]] - Extract the fonts for the specified
+ language from a multi-language font using the map from this file. This is
+ rather like the option '-l' but the encoding map is not
+ compiled into the program, it's taken from that file, so it's
+ easy to edit. Examples of such files are provided in
+ maps/adobe-standard-encoding.map, CP1250.map. (NOTE:
+ the 'standard encoding' map does not include all the glyphs of the
+ AdobeStandard encoding, it's provided only as an example.) The
+ description of the supported map formats is in the file
+ maps/unicode-sample.map.
+
+
+ Likewise to '-l', an argument may be specified after the map file
+ name. But in this case the argument has fixed meaning: it selects the
+ original TTF encoding table (the syntax is the same as in '-l plane')
+ and/or a plane of the map file. The plane name also gets added after dash
+ to the font name. The plane is a concept used in the Eastern fonts with big
+ number of glyphs: one TTF font gets divided into multiple Type1 fonts,
+ each containing one plane of up to 256 glyphs. But with a little
+ creativity this concept may be used for other purposes of combining
+ multiple translation maps into one file. To extract multiple planes
+ from a TTF font ttf2pt1 must be run multiple times, each time with
+ a different plane name specified.
+
+
+ The default original TTF encoding table used for the option '-L' is
+ Unicode. The map files may include directives to specify different original
+ TTF encodings. However if the pid/eid pair is specified with
+ it overrides any original encoding specified in the map file.
+
+
+
+-m type=value - Set maximal or minimal limits of resources.
+ These limits control the the font generation by limiting the resources
+ that the font is permitted to require from the PostScript interpreter.
+ The currently supported types of limits are:
+
+
+
+
+
+
+
+ h/H - Autogeneration of hints. The really complex outlines
+ may confuse the algorithm, so theoretically it may be useful
+ sometimes to disable them. Although up to now it seems that
+ even bad hints are better than no hints at all.
+ Default: enabled
+
+
+ u/U - Hint substitution. Hint substitution is a technique
+ permitting generation of more detailed hints for the rasterizer. It allows
+ to use different sets of hints for different parts of a glyph and change
+ these sets as neccessary during rasterization (that's why "substituted").
+ So it should improve the quality of the fonts rendered at small sizes.
+ But there are two catches: First, the X11 library has rather low limit for
+ the font size. More detailed hints increase the file size and thus increase
+ the chance of hitting this limit (that does not mean that you shall hit it
+ but you may if your fonts are particularly big). This is especially
+ probable for Unicode fonts converted with option '-a', so you may want to
+ use '-a' together with '-Ou'. See app/X11/README for the description of
+ a patch to X11 which fixes this problem. Second, some rasterizers (again,
+ X11 is the typical example) have a limitation for total number of hints
+ used when drawing a glyph (also known as the hint stack depth). If that
+ stack overflows the glyph is ignored. Starting from version 3.22 ttf2pt1
+ uses algorithms to minimizing this depth, with the trade-off of slightly
+ bigger font files. The glyphs which still exceed the limit set by option
+ '-mh' have all the substituted hints removed and only base hints left.
+ The algorithms seem to have been refined far enough to make the fonts with
+ substituted hints look better than the fonts without them or at least the
+ same. Still if the original fonts are not well-designed the detailed
+ hinting may emphasize the defects of the design, such as non-even thickness
+ of lines. So provided that you are not afraid of the X11 bug the best idea
+ would be to generate a font with this feature and without it, then compare
+ the results using the program other/cmpf (see the description
+ in other/README) and decide which one looks better.
+ Default: enabled
+
+
+ o/O - Space optimization of the outlines' code. This kind of optimization
+ never hurts, and the only reason to disable this feature is for comparison
+ of the generated fonts with the fonts generated by the previous versions of
+ converter. Well, it _almost_ never hurts. As it turned out there exist
+ some brain-damaged printers which don't understand it. Actually this
+ feature does not change the outlines at all. The Type 1 font manual
+ provides a set of redundant operators that make font description shorter,
+ such as '10 hlineto' instead of '0 10 rlineto' to describe a horizontal
+ line. This feature enables use of these operators.
+ Default: enabled
+
+
+ s/S - Smoothing of outlines. If the font is broken in some
+ way (even the ones that are not easily noticeable), such smoothing
+ may break it further. So disabling this feature is the first thing to be
+ tried if some font looks odd. But with smoothing off the hint generation
+ algorithms may not work properly too.
+ Default: enabled
+
+
+ t/T - Auto-scaling to the 1000x1000 Type1 standard matrix. The
+ TTF fonts are described in terms of an arbitrary matrix up to
+ 4000x4000. The converted fonts must be scaled to conform to
+ the Type1 standard. But the scaling introduces additional rounding
+ errors, so it may be curious sometimes to look at the font in its
+ original scale.
+ Default: enabled
+
+
+ v/V - Do vectorization on the bitmap fonts. Functionally
+ "vectorization" is the same thing as "autotracing", a different word is
+ used purely to differentiate it from the Autotrace library. It tries to
+ produce nice smooth outlines from bitmaps. This feature is still a work
+ in progress though the results are already mostly decent.
+ Default: disabled
+
+
+ w/W - Glyphs' width corection. This option is designed to be
+ used on broken fonts which specify too narrow widths for the
+ letters. You can tell that a font can benefit from this option
+ if you see that the characters are smashed together without
+ any whitespace between them. This option causes the converter
+ to set the character widths to the actual width of this character
+ plus the width of a typical vertical stem. But on the other hand
+ the well-designed fonts may have characters that look better if
+ their widths are set slightly narrower. Such well-designed fonts
+ will benefit from disabling this feature. You may want to convert
+ a font with and without this feature, compare the results and
+ select the better one. This feature may be used only on proportional
+ fonts, it has no effect on the fixed-width fonts.
+ Default: disabled
+
+
+ z/Z - Use the Autotrace library on the bitmap fonts. The results
+ are horrible and the use of this option is not recommended. This option is
+ present for experimental purposes. It may change or be removed in the
+ future. The working tracing can be achieved with option -OV.
+ Default: disabled
+
+
+
+ ttf - built-in parser for the ttf files (suffix .ttf)
+
+
+ The parser ft is NOT linked in by default. See Makefile
+ for instructions how to enable it. We do no support this parser on
+ Windows: probably it will work but nobody tried and nobody knows how
+ to build it.
+
+
+ The conversion of the bitmap fonts (such as BDF) is simplistic yet,
+ producing jagged outlines. When converting such fonts, it might be
+ a good idea to turn off the hint substitution (using option -Ou)
+ because the hints produced will be huge but not adding much to the
+ quality of the fonts.
+
+
+
+-u number - Mark the font with this value as its
+ UniqueID. The UniqueID is used by the printers with the hard disks
+ to cache the rasterized characters and thus significantly
+ speed-up the printing. Some of those printers just can't
+ store the fonts without UniqueID on their disk.The problem
+ is that the ID is supposed to be unique, as it name says. And
+ there is no easy way to create a guaranteed unique ID. Adobe specifies
+ the range 4000000-4999999 for private IDs but still it's difficult
+ to guarantee the uniqueness within it. So if you don't really need the
+ UniqueID don't use it, it's optional. Luckily there are a few millions of
+ possible IDs, so the chances of collision are rather low.
+ If instead of the number a special value 'A' is given
+ then the converter generates the value of UniqueID automatically,
+ as a hash of the font name. (NOTE: in the version 3.22 the
+ algorithm for autogeneration of UniqueID was changed to fit the values
+ into the Adobe-spacified range. This means that if UniqueIDs were used
+ then the printer's cache may need to be flushed before replacing the
+ fonts converted by an old version with fonts converted by a newer version).
+ A simple way to find if any of the fonts in a given directory have
+ duplicated UniqueIDs is to use the command:
+
+
+ cat *.pf[ab] | grep UniqueID | sort | uniq -c | grep -v ' 1 '
+
+
+ Or if you use scripts/convert it will do that for you automatically
+ plus it will also give the exact list of files with duplicate UIDs.
+
+
+
+-v size - Re-scale the font to get the size of a typical uppercase
+ letter somewhere around the specified size. Actually, it re-scales
+ the whole font to get the size of one language-dependent letter to be
+ at least of the specified size. Now this letter is "A" in all the
+ supported languages. The size is specified in the points of the
+ Type 1 coordinate grids, the maximal value is 1000. This is an
+ experimental option and should be used with caution. It tries to
+ increase the visible font size for a given point size and thus make
+ the font more readable. But if overused it may cause the fonts to
+ look out of scale. As of now the interesting values of size for
+ this option seem to be located mostly between 600 and 850. This
+ re-scaling may be quite useful but needs more experience to
+ understand the balance of its effects.
+
+
+
+-W level - Select the verbosity level of the warnings.
+ Currently the levels from 0 to 4 are supported. Level 0 means no warnings
+ at all, level 4 means all the possible warnings. The default level is 3.
+ Other levels may be added in the future, so using the level number 99 is
+ recommended to get all the possible warnings. Going below level 2 is
+ not generally recommended because you may miss valuable information about
+ the problems with the fonts being converted.
+
+
+
+Obsolete option:
+-A - Print the font metrics (.afm file) instead of the font on STDOUT.
+ Use -GA instead.
+
+
+
+Very obsolete option:
+
+
+
+The .pfa font format supposes that the description of the characters
+is binary encoded and encrypted. This converter does not encode or
+encrypt the data by default, you have to specify the option '-e'
+or use the t1asm program to assemble (that means, encode and
+encrypt) the font program. The t1asm program that is included with
+the converter is actually a part of the t1utils package, rather old
+version of which may be obtained from
+
+
+
+
+Note that t1asm from the old version of that package won't work properly
+with the files generated by ttf2pt1 version 3.20 and later. Please use
+t1asm packaged with ttf2pt1 or from the new version t1utils
+instead. For a newer version of t1utils please look at
+
+
+
+
+
+
+So, the following command lines:
+
+
+
+
+represent two ways to get a working font. The benefit of the second form
+is that other filters may be applied to the font between the converter
+and assembler.
+
+
+
+
+
+
+
+
+
+ ttf2pt1-chinese - contains the Chinese conversion maps
+
+
+The general versioning policy for the optional packages is the following:
+These packages may have no direct dependency on the ttf2pt1 version.
+But they may be updated in future, as well as some versions of optional
+packages may have dependencies on certain versions of ttf2pt1.
+To avoid unneccessary extra releases on one hand and keep the updates in
+sync with the ttf2pt1 itself on the other hand, a new version of an optional
+package will be released only if there are any changes to it and it will be
+given the same version number as ttf2pt1 released at the same time. So not
+every release of ttf2pt1 would have a corresponding release of all optional
+packages. For example, to get the correct version of optional packages for an
+imaginary release 8.3.4 of ttf2pt1 you would need to look for optional
+packages of the highest version not higher than (but possibly equal to) 8.3.4.
+
+
+
+
+Send the bug reports to the ttf2pt1 development mailing list at
+ttf2pt1-devel@lists.sourceforge.net.
+
+
+Try to collect more information about the problem and include it into
+the bug report. (Of course, even better if you would provide a ready
+fix, but just a detailed bug report is also good). Provide detailed
+information about your problem, this will speed up the response greatly.
+Don't just write "this font looks strange after conversion" but describe
+what's exactly wrong with it: for example, what characters look wrong
+and what exactly is wrong about their look. Providing a link to the
+original font file would be also a good idea. Try to do a little
+troublehooting and report its result. This not only would help with
+the fix but may also give you a temporary work-around for the bug.
+
+
+First, enable full warnings with option '-W99', save them to
+a file and read carefully. Sometimes the prolem is with a not implemented
+feature which is reported in the warnings. Still, reporting about such
+problems may be a good idea: some features were missed to cut corners,
+in hope that no real font is using them. So a report about a font using
+such a feature may motivate someone to implement it. Of course, you
+may be the most motivated person: after all, you are the one wishing
+to convert that font. ;-) Seriously, the philosophy "scrath your own itch"
+seems to be the strongest moving force behind the Open Source software.
+
+
+The next step is playing with the options. This serves a dual purpose:
+on one hand, it helps to localize the bug, on the other hand you may be
+able to get a working version of the font for the meantime while the
+bug is being fixed. The typical options to try out are: first '-Ou', if
+it does not help then '-Os', then '-Oh', then '-Oo'.
+They are described in a bit more detail above. Try them one by one
+and in combinations. See if with them the resulting fonts look better.
+
+
+On some fonts ttf2pt1 just crashes. Commonly that happens because the
+font being converted is highly defective (although sometimes the bug
+is in ttf2pt1 itself). In any case it should not crash, so the reports
+about such cases will help to handle these defects properly in future.
+
+
+We try to respond to the bug reports in a timely fashion but alas, this
+may not always be possible, especially if the problem is complex.
+This is a volunteer project and its resources are limited. Because
+of this we would appreciate bug reports as detailed as possible,
+and we would appreciate the ready fixes and contributions even more.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ttf2pt1-devel@lists.sourceforge.net
+
+
+
+
+mheath@netspace.net.au
+
+
+
+A.Weeks@mcc.ac.uk
+
+
+
+babkin@users.sourceforge.net (preferred)
+
+
+
+
+http://www.netspace.net.au/~mheath/ttf2pt1/
+
+
+
+
+
+http://sourceforge.net/projects/gnuwin32
+
+
+
+http://www.lcdf.org/~eddietwo/type/
+
+
+
+http://www.rightbrain.com/pages/books.html
+
+
+
+http://fonts.apple.com/TTRefMan/index.html
+
+
+
+http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf
+
+
+
+http://partners.adobe.com/asn/developer/PDFS/TN/T1_SPEC.PDF
+
+
+
+http://partners.adobe.com/asn/developer/PDFS/TN/5015.Type1_Supp.pdf
+
+
+
+http://partners.adobe.com/asn/developer/PDFS/TN/5004.AFM_Spec.pdf
+
+
+
+http://www.cs.wpi.edu/~matt/courses/cs563/talks/surface/bez_surf.html
+
+
+
+http://www.neuroinformatik.ruhr-uni-bochum.de/ini/PEOPLE/rmz/t1lib/t1lib.html
+
+
+
+http://www.freetype.org
+
+
+
+http://heliotrope.homestead.com/files/printsoft.html
+
+
+
+http://linuxartist.org/fonts/
+
+
+
+
+Please note also that ttf2pfa has not been maintained for a long time.
+All of its functionality has been integrated into ttf2pt1 and all the
+development moved to ttf2pt1, including Andrew Weeks, the author of
+ttf2pfa. Ttf2pfa is provided for historical reasons only. Please use
+ttf2pt1 instead.
+
+
+
+Run it like this:
+
+
+
+
+The first parameter is the truetype filename, the second is a stem for
+the output file names. The program will create a fontname.pfa containing
+the Postscript font and a fontname.afm containing the metrics.
+
+
+The motivation behind this is that in Linux if you do not have a
+Postscript printer, but only some other printer, you can only print
+Postscript by using Ghostscript. But the fonts that come with
+Ghostscript are very poor (they are converted from bitmaps and look
+rather lumpy). This is rather frustrating as the PC running Linux
+probably has MS-Windows as well and will therefore have truetype fonts,
+but which are quite useless with Linux, X or Ghostscript.
+
+
+The program has been tested on over a hundred different TrueType fonts
+from various sources, and seems to work fairly well. The converted
+characters look OK, and the program doesn't seem to crash any more. I'm
+not sure about the AFM files though, as I have no means to test them.
+
+
+The fonts generated will not work with X, as the font rasterizer that
+comes with X only copes with Type 1 fonts. If I have the time I may
+modify ttf2pfa to generate Type 1s.
+
+
+
+
+Copyright on fonts, however, is a difficult legal question. Any
+copyright statements found in a font will be preserved in the output.
+Whether you are entitled to translate them at all I don't know.
+
+
+If you have a license to run a software package, like say MS-Windows, on
+your PC, then you probably have a right to use any part of it, including
+fonts, on that PC, even if not using that package for its intended
+purpose.
+
+
+I am not a lawyer, however, so this is not a legal opinion, and may be
+garbage.
+
+
+There shouldn't be a any problem with public domain fonts.
+
+
+
+
+The TrueType format was originally developed by Apple for the MAC, which
+has opposite endianness to the PC, so to ensure compatibility 16 and 32
+bit fields are the wrong way round from the PC's point of view. This is
+the reason for all the 'ntohs' and 'ntohl' calls. Doing it this way
+means the program will also work on big-endian machines like Suns.
+
+
+I doubt whether it will work on a DOS-based PC though.
+
+
+The program produces what technically are Type 3 rather than Type 1
+fonts. They are not compressed or encrypted and are plain text. This is
+so I (and you) can see what's going on, and (if you're a Postscript guru
+and really want to) can alter the outlines.
+
+
+I only translate the outlines, not the 'instructions' that come with
+them. This latter task is probably virtually impossible anyway. TrueType
+outlines are B-splines rather than the Bezier curves that Postscript
+uses. I believe that my conversion algorithm is reasonably correct, if
+nothing else because the characters look right.
+
+
+
+
+Then there are buggy fonts (yes, a font can have bugs). I try to deal
+with these in as sane a manner as possible, but it's not always
+possible.
+
+
+
+
+TrueType fonts are organised differently. As well as the glyph
+descriptions there are a number of tables. One of these is a mapping
+from a character set into the glyph array, and another is a mapping from
+the glyph array into a set of Postscript character names. The problems
+are:
+
+ 1) Microsoft uses Unicode, a 16-bit system, to encode the font.
+
+
+I deal with (1) by assuming a Latin1 encoding. The MS-Windows and
+Unicode character sets are both supersets of ISO-8859-1. This usually
+means that most characters will be properly encoded, but you should be
+warned that some software may assume that fonts have an Adobe encoding.
+Symbol, or Dingbat, fonts are in fact less of a problem, as they have
+private encodings starting at 0xF000. It is easy to just lose the top
+byte.
+
+
+Postscript fonts can be re-encoded, either manually, or by software.
+Groff, for example, generates postscript that re-encodes fonts with the
+Adobe encoding. The problem here is that not all characters in the Adobe
+set are in the MS-Windows set. In particular there are no fi and fl
+ligatures. This means that conversions of the versions of
+Times-New-Roman and Arial that come with MS-Windows cannot be used
+blindly as replacements for Adobe Times-Roman and Helvetica. You can get
+expanded versions of MS fonts from Microsoft's web site which do contain
+these ligatures (and a lot else besides).
+
+
+I deal with (2) by creating new character names. This can be error-prone
+because I do not know which of them is the correct glyph to give the
+name to. Some (buggy) fonts have large numbers of blank glyphs, all with
+the same name.
+
+
+(almost every TrueType font has three glyphs called .notdef, one of them
+is usually an empty square shape, one has no outline and has zero width,
+and one has no outline and a positive width. This example is not really
+a problem with well formed fonts since the .notdef characters are only
+used for unprintable characters, which shouldn't occur in your documents
+anyway).
+
+
+
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/app/RPM/Makefile b/application/third_party/dompdf/lib/ttf2ufm/src/app/RPM/Makefile
new file mode 100644
index 00000000..02a33b4d
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/app/RPM/Makefile
@@ -0,0 +1,279 @@
+
+# This file should be configured before running `make'.
+# Uncomment or change the values that are relevant for your OS.
+
+# The preferred C compiler (by default use the OS-specific default value).
+# For BSD/OS, FreeBSD, Linux (all flavors), NetBSD, OpenBSD the default
+# compiler is GNU C.
+# (Note please the politically correct ordering by alphabet ! :-)
+#
+# Use GNU C even if it's not the default compiler
+#
+CC=gcc
+#
+# Use the standard ANSI C compiler on HP-UX even if it's not default
+#
+#CC=c89
+
+#
+# The system-dependent flags for the C compiler
+#
+# Default
+
+CFLAGS_SYS= -O2 -D_GNU_SOURCE
+
+# For GNU C
+#
+CFLAGS_SYS= -O2 -D_GNU_SOURCE
+#
+# For GNU C with long options support library (Linux etc.)
+#
+CFLAGS_SYS= -O2 -D_GNU_SOURCE
+#
+# For GNU C on HP-UX/PA-RISC 1.1
+#
+#CFLAGS_SYS= -O2 -Wa,-w
+#
+# For the standard ANSI C on HP-UX
+#
+#CFLAGS_SYS= +O2 -D_HPUX_SOURCE
+
+#
+# The system-dependent libraries
+#
+# Defalut (for the BSD-style OSes)
+
+LIBS_SYS= -lm
+
+# For SystemV (such as SCO, UnixWare, Solaris, but _NOT_ Linux or HP-UX)
+#
+#LIBS_SYS= -lm -lsocket
+
+#
+# The flags for C compiler for the FreeType-2 library (disabled by default).
+# This WON'T BUILD with FT2-beta8, use the FreeType release 2.0.4
+# http://download.sourceforge.net/freetype/freetype-2.0.4.tar.gz
+
+CFLAGS_FT=
+
+# To enable use of the FreeType-2 library
+# (if the include and lib directory do not match your installation,
+# modify them), also uncomment LIBS_FT
+#
+#CFLAGS_FT = -DUSE_FREETYPE -I/usr/include/freetype2 -I/usr/include
+
+#
+# The FreeType-2 library flags (disabled by default)
+
+LIBS_FT=
+
+# To enable use of the FreeType-2 library
+# (if the include and lib directory do not match your installation,
+# modify them), also uncomment CFLAGS_FT
+#
+#LIBS_FT= -L/usr/lib -lfreetype
+
+#
+# The flags for C compiler for the Autotrace library (disabled by default).
+# USE OF THIS FEATURE IS STRONGLY DISCOURAGED, THE BUILT-IN TRACING
+# (AKA VECTORIZATION) PROVIDES MUCH BETTER RESULTS.
+# The tested version is 0.29a (and the fonts produced with it are
+# absolutely not usable).
+# http://download.sourceforge.net/autotrace/autotrace-0.29.tar.gz
+
+CFLAGS_AT=
+
+# To enable use of the Autotrace library
+# (if the include and lib directory do not match your installation,
+# modify them), also uncomment LIBS_AT
+#
+#CFLAGS_AT = -DUSE_AUTOTRACE -I/usr/local/include
+
+#
+# The Autotrace library flags (disabled by default)
+
+LIBS_AT=
+
+# To enable use of the Autotrace library
+# (if the include and lib directory do not match your installation,
+# modify them), also uncomment CFLAGS_AT
+#
+#LIBS_AT= -L/usr/local/lib -lautotrace
+
+#
+# Preference of front-ends if multiple parsers match a file
+# (by default the build-in front-end takes preference over FreeType)
+
+CFLAGS_PREF=
+
+# To prefer FreeType (if enabled):
+#
+#CFLAGS_PREF= -DPREFER_FREETYPE
+
+# Uncomment the second line to not compile t1asm into ttf2pt1
+CFLAGS_EXTT1ASM=
+#CFLAGS_EXTT1ASM= -DEXTERNAL_T1ASM
+
+CFLAGS= $(CFLAGS_SYS) $(CFLAGS_FT) $(CFLAGS_AT) $(CFLAGS_PREF)
+LIBS= $(LIBS_SYS) $(LIBS_FT) $(LIBS_AT)
+
+# Installation-related stuff
+#
+# The base dir for installation and subdirs in it
+INSTDIR = /home/eclecticgeek/apps
+# for binaries
+BINDIR = $(INSTDIR)/bin
+# for binaries of little general interest
+LIBXDIR = $(INSTDIR)/libexec/ttf2pt1
+# for scripts, maps/encodings etc.
+SHAREDIR = $(INSTDIR)/share/ttf2pt1
+MANDIR = $(INSTDIR)/man
+
+# owner and group of installed files
+OWNER = eclecticgeek
+GROUP = pg1755828
+
+# After you have configured the Makefile, comment out the following
+# definition:
+##warning: docs
+## @echo >&2
+## @echo " You have to configure the Makefile before running make!" >&2
+## @echo "(or if you are lazy and hope that it will work as is run \`make all')">&2
+## @echo >&2
+#
+DOCS=CHANGES README FONTS FONTS.hpux encodings/README other/README \
+ app/X11/README app/netscape/README app/TeX/README
+
+SUBDIRS = app encodings maps scripts other
+TXTFILES = README* FONTS* CHANGES* COPYRIGHT
+
+MANS1=ttf2pt1.1 ttf2pt1_convert.1 ttf2pt1_x2gs.1
+MANS=$(MANS1) $(MANS5)
+
+all: t1asm ttf2pt1 docs mans rpm
+
+docs: $(DOCS)
+
+mans: $(MANS)
+
+clean:
+ rm -f t1asm ttf2pt1 *.o app/RPM/Makefile app/RPM/*.spec *.core core.* core
+ ( cd other && make clean; )
+ ( cd app/netscape && make clean; )
+
+veryclean: clean
+ rm -f $(DOCS) $(MANS)
+
+rpm: app/RPM/Makefile app/RPM/ttf2pt1.spec
+
+ttf2pt1.1: README.html
+ scripts/html2man . .
+
+The tiny Perl-script 'sfd2map' converts .sfd files (as used by
+CJK-LaTeX) to .map files (as used by ttf2pt1).
+
+
+Actually I currently don't use that script stand-alone for performance
+reasons.
+
+
+Currently I use such a conversion in another small script 'cjk-latex-config'
+(attached as well) which creates .tfm files usable with CJK-LaTeX
+from TrueType fonts as listed in /etc/ttf2pk/ttfonts.map. When called like
+
+
+The .sfd files cannot be directly used as input to ttf2pt1 because the
+format of the .map files which ttf2pt1 expects is slightly different,
+therefore I made the 'sfd2map' converter script.
+
+
+But then I noticed that I would have to parse the generated map file
+*again* to get a list of the plane numbers to use. That seemed to be a
+bit wastful because I had just parsed the .sfd file to convert it to
+.map, therefore I included sfd2map as a function in 'cjk-latex-config'
+as well and collected the plane numbers during the conversion.
+
+
+But 'cjk-latex-config' is maybe a little bit SuSE specific, therefore
+I kept 'sfd2map' also as a standalong script. Use it if you like.
+
+
+'cjk-latex-config' calls another small script 'cjk-latex-t1mapgen'
+to generate a cjk-latex.map file containing something like
+
+
+Maybe this is also SuSE specific, I'm not sure about in what
+directories the relevant files are stored on other Linux-like systems.
+
+
+I'm not yet sure whether they work on other systems beside SuSE Linux.
+They have hard coded path names where to find the TrueType fonts,
+ttfonts.map, the TeX fonts etc and cjk-latex-config checks
+whether freetype-tools.rpm is installed. freetype-tools.rpm might
+have another name for other distributions and for distributions
+which don't use rpm this check can't work anyway.
+
+
+These are small details and it should not be difficult to adapt the
+scripts for other Linux-like systems though.
+
+
+
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/app/TeX/cjk-latex-config b/application/third_party/dompdf/lib/ttf2ufm/src/app/TeX/cjk-latex-config
new file mode 100644
index 00000000..4ee30e28
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/app/TeX/cjk-latex-config
@@ -0,0 +1,352 @@
+#!/usr/bin/perl -w
+#
+# Copyright (c) 2002 SuSE Linux AG, Nuernberg, Germany. All rights reserved.
+#
+# Author: Mike Fabian
+
+These are patches for XFree86 versions 3.3.4 and 3.9
+to fix a few known problems with big Type1 fonts and
+with strange handling of the standard stem width table.
+The patch for XFree86 3.3.4 probably may be easily
+installed on any other distribution of X11.
+They are supposed to be installed in the subdirectory
+
+
+Sorry that the description has so little details but if
+you know how to build X11 then this is enough, otherwise
+any more details won't help much.
+
+
+The patches have been submitted to the XFree86 project,
+hope they will be included in some next release of XFree86
+and X11.
+
+
+
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/app/X11/t1-xf86.334.patch b/application/third_party/dompdf/lib/ttf2ufm/src/app/X11/t1-xf86.334.patch
new file mode 100644
index 00000000..31e98e2d
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/app/X11/t1-xf86.334.patch
@@ -0,0 +1,199 @@
+*** fontfcn.c 2000/01/02 18:55:56 1.1
+--- fontfcn.c 2000/01/02 19:00:17
+***************
+*** 33,38 ****
+--- 33,39 ----
+ #include
+
+This is a collection of supplements to Netscape 4.x on
+Unix. Probably they will also work with Netscape 3.x,
+possilby with minor modifications.
+
+
+
+
+This is a program that allows to substitute the font metrics
+of any PostScript font in Netscape.
+
+
+When Netscape prints the files to PostScript format it uses a
+built-in table of character widths. It prints all the fixed-width
+characters in the typeface "Courier" and all the variable-width
+characters in the typeface "Times". And if the PostScript printer
+has these fonts by Adobe then everything goes fine because
+the tables inside Netscape are generated from the Adobe fonts.
+But if the fonts are different (say, those supplied with Ghostscripts
+or the fonts with non-latin characters) then the result is quite
+ugly. This program allows to replace the width tables inside
+the Netscape executable with the tables for any given font.
+The only problem is that Netscape can hold only one set of tables
+at once. So if you want to print with different fonts (say,
+for different languages or encodings) you will have to make
+multiple copies of the executable, tune each of them for its
+font and then run them separately.
+
+
+I tried to make the program as machine-independent as possible.
+But because it patches the binary files it still has the dependencies
+on hardware. The default version as supplied was designed for
+Intel x86 machines but it should work OK on any machine
+with 32-bit CPU and 4Kbyte (or less) page size. If it can't
+find the tables matching the font names on some other architecture
+the first thing to try would be reduce the `PAGEBITS' definition
+in the source code. On the machines with non-page-aligned structure
+of executables it won't work at all. I don't know whether would
+it work on the 64-bit machines. This may depend on whether the
+Netscape executable was compiled in 32-bit or 64-bit mode. For
+the 64-bit executables it may be neccessary to change the definition
+of the type `tptr' to an 8-byte integer type (probably `long'
+or `long long'). Also must be re-compiled for patching of the
+Netscape binary for each particular machine architecture because
+it assumes the byte order of the current machine.
+
+
+It might be possible to create a program that would patch
+a running Netscape binary on the fly, that would allow
+changing the printing fonts as neccessary when Netscape is
+running. But this would be even more platform-dependent,
+so I don't feel any enthusiasm about doing that.
+
+
+I have tested the program on the Intel machines, Netscape
+4.08 and 4.7, OS FreeBSD (both a.out and ELF formats of the
+Netscape binary) and UnixWare.
+
+
+After all these scary issues are resolved the compiling
+is easy: just run `make'.
+
+
+To command to patch the Netscape is:
+
+
+ ./nsfix <netscape-binary> <config-file>
+
+
+
+Please make a copy of the original Netscape binary before
+patching in case anything goes wrong. Patch the copy, test
+that it works OK and only then install it. The configuration
+file describes the fonts that are to be used. An example
+is provided in the file psfonts.cf.
+
+
+Each line in the configuration file consists of 4
+columns:
+
+
+
+<PS_font_name> <font_base_file> <suffix_afm> <suffix_font>
+
+
+
+For example, the following line from my configuration file:
+
+
+
+Courier /usr/lib/X11/fonts/ttf/cokoi8n.koi8-r .afm .pfa
+
+
+
+says that the font `Courier' will be replaced with the
+font taken from the file `/usr/lib/X11/fonts/ttf/cokoi8n.koi8-r.pfa'
+and the metrics for that font will be taken from the file
+`/usr/lib/X11/fonts/ttf/cokoi8n.koi8-r.afm' .
+
+
+One more caveat: the new font must have a proper encoding
+table. Some fonts contain characters for multiple encodings
+hoping that the program wil re-encode them as neccessary.
+This won't work in this case, only the primary encoding table
+of the font will be used.
+
+
+
+
+These are the filters for printing from Netscape.
+
+
+Changing the metrics is not the end of the story. This will
+provide proper placement of the characters but not the
+characters themselves. There are a few ways to provide
+the characters:
+
+
+First, if you use GhostScript you may configure proper
+aliases in the GhostScript configuration file. We will
+consider this variant trivial and won't discuss it furter
+except for one caveat: Netscape tries to re-encode the
+fonts per the ISO Latin-1 encoding. If the primary encoding
+of the font is different this cause unexpected effects.
+So you still may consider using the filters (at least in a
+simplified form) to solve this problem.
+
+
+Second, load the fonts right into your printer. This is
+very much like configuring GhostScript.
+
+
+Third, use the provided filters. The script `nsfilter'
+reads the output of Netscape on its standard input and
+puts the result to its standard output. It uses the same
+configuration file `psfonts.cf' as `nsfix'. First it
+looks for the configuration file in the user's home
+directory ($HOME/.netscape/psfonts.cf) and if the
+file it not there then the second guess is the system-wide
+configuration file /usr/local/etc/psfonts.cf. The
+script inserts the fonts into the output and also
+removes the Netscape's experiments with the encodings.
+
+
+`nsfilter' is generally intended to be ran by user, not by the
+printing subsystem. The reason is that the user may have
+changed fonts in his Netscape and the printing subsystem
+would have no way to access user's configuration file.
+But if all the users are using the same fonts then it
+may be incorporated into the printing subsystem and use
+the system-wide configuration file.
+
+
+The script `nsprint' is purely for convenience, to type it
+as a printing command in the Netscape printing window.
+It just pipelines the data through `nsfilter' to the
+printing program which also gets all the arguments. Please
+note that the SystemV-style and BSD-style systems use different
+printing programs (although they commonly provide compatibility
+with the other style too). The script tries to guess the
+type of system and use its native print program, `lp' or
+`lpr'. But in case it guesses wrong you may want
+to change this in the script. Also if the printer does not support
+PostScript directly this script may be a good place to
+insert a call to GhostScript.
+
+
+
+
+Netscape on Unix has a very annoying "feature", it does
+not remember the desired base size of the scalable screen
+fonts and always resets it to 12.0 points. Even if the size
+is changed manually in its preferences file, Netscape
+forgets it after it exits.
+
+
+So my solution was to write a program which would change
+the size to my favorite one every time right before
+starting Netscape. `notscape' is exactly such a program,
+it sets the font sizes an then transparently executes
+netscape. It takes the font sizes from the file
+`$HOME/.netscape/fontsz.cf' . An example of such file
+is provided. The format of the file is quite self-explanatory,
+for example the lines
+
+
+
+fixed-koi8-r 140
+
+mean "set the size of the fixed-width screen font in the
+encoding koi8-r to 14.0 points; set the size of the proportional
+(variable-width) font in the encoding koi8-r to 15.0 points".
+
+
+
+
+
+To print from Netscape, I usually print to the Postscript file first.
+Then I use this small script to change the names of Times and Courier fonts
+in the file and remove `/Encoding' lines. After that the file can be
+sent to printer.
+
+
+
+
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/app/netscape/fontsz.cf b/application/third_party/dompdf/lib/ttf2ufm/src/app/netscape/fontsz.cf
new file mode 100644
index 00000000..90935eda
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/app/netscape/fontsz.cf
@@ -0,0 +1,8 @@
+fixed-koi8-r 150
+prop-koi8-r 150
+fixed-iso-8859-5 150
+prop-iso-8859-5 150
+fixed-iso-8859-1 150
+prop-iso-8859-1 150
+fixed-x-user-defined 150
+prop-x-user-defined 150
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/app/netscape/notscape b/application/third_party/dompdf/lib/ttf2ufm/src/app/netscape/notscape
new file mode 100644
index 00000000..67d87bcb
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/app/netscape/notscape
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+NDIR=$HOME/.netscape
+PFILE=$NDIR/preferences.js
+CFFILE=$NDIR/fontsz.cf
+TMPFILE=$NDIR/fontsz.sed
+
+die() {
+ echo "notscape: can't $*" >&2
+ exit 1
+}
+
+[ -r $CFFILE ] && {
+awk '{ printf("/intl.font_spec_list/s/-[^-]*-\\([^-]*\\)-%s,/-%s-\\1-%s,/\n", \
+ $1, $2, $1); }' <$CFFILE >$TMPFILE
+
+cp $PFILE $PFILE.old || die "save old pref file"
+sed -f $TMPFILE <$PFILE.old >$PFILE.new || die "create new pref file"
+[ -s $PFILE.new ] || die "create new pref file"
+
+mv $PFILE.new $PFILE || die "install new pref file"
+
+}
+
+exec netscape -no-about-splash "$@"
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/app/netscape/nsfilter b/application/third_party/dompdf/lib/ttf2ufm/src/app/netscape/nsfilter
new file mode 100644
index 00000000..77b5b64b
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/app/netscape/nsfilter
@@ -0,0 +1,24 @@
+#!/bin/sh
+CONFLOCAL=$HOME/.netscape/psfonts.cf
+CONFGLOBAL=/usr/local/etc/nspsfonts.cf
+
+if [ -r "$CONFLOCAL" ]
+then
+ CONF="$CONFLOCAL"
+else
+ CONF="$CONFGLOBAL"
+fi
+
+grep -v "^#" <$CONF | grep -v "^$" | while :
+do {
+ read nsname base afm pfa x
+ [ -z "$nsname" ] && break;
+
+ fname=`awk '/^FontName/ {print $2;}' <$base$afm`
+
+ cat $base$pfa
+ echo "/$nsname /$fname findfont definefont"
+
+} done
+
+grep -v "^ /Encoding isolatin1encoding def$" | egrep -v '^newpath .* closepath clip newpath$'
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/app/netscape/nsfix.c b/application/third_party/dompdf/lib/ttf2ufm/src/app/netscape/nsfix.c
new file mode 100644
index 00000000..6aa47c91
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/app/netscape/nsfix.c
@@ -0,0 +1,469 @@
+/*
+ * Fix the Netscape executable for specified font widths
+ *
+ * (c) 1999 Copyright by Sergey Babkin
+ * see COPYRIGHT
+ */
+
+#include
+
+
+
+
+The file names are supposed to have the suffix .tbl. Each file
+describes one encoding, and all the tables for a given language
+are stored in the same directory.
+
+
+The file format is quite simple: just a sequence of rows in
+format
+
+
+
+<name> <decimal code>
+
+
+
+The names do not have to conform to any standard, just the same
+glyph must have the same name in all the files for a given language.
+
+
+Not all the codes need to be described in the tables, the codes that
+are not mentioned in the tables are left untranslated. So a file
+of zero length may be used in case when no translation is neccessary.
+
+
+The translation changes only the encoding table of the font and does not
+rename the glyphs in the font file.
+
+
+
+
+The file for ISO-8859/1 is just a copy of file for KOI-8. It is neccessary
+because Netscape has rather weird ideas about the documents in
+KOI-8 encoding. The common way to fool Netscape is to set the KOI-8
+fonts for the ISO-8859/1 encoding and set the default encoding
+in Netscape to 8859/1.
+
+
+The directory `latin1' contains an empty table for ISO-8859/1
+because it does not need any translation.
+
+
+
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/adobestd/adobe-std.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/adobestd/adobe-std.tbl
new file mode 100644
index 00000000..e69de29b
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/README b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/README
new file mode 100644
index 00000000..08f8ce36
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/README
@@ -0,0 +1,3 @@
+These files are copies of thos provided for the language "cyrillic"
+and are provided for compatibility purposes only, please
+use the language "cyrillic" instead.
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/encodings.alias b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/encodings.alias
new file mode 100644
index 00000000..f8ef5c17
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/encodings.alias
@@ -0,0 +1,4 @@
+# alias real-name
+iso8859-1 koi8-r
+windows-1251 ibm-1251
+cp-866 ibm-866
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/ibm-1251.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/ibm-1251.tbl
new file mode 100644
index 00000000..02e57978
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/ibm-1251.tbl
@@ -0,0 +1,127 @@
+cyr_DJE 128
+cyr_GJE 129
+quotesinglbase 130
+cyr_gje 131
+quotedblbase 132
+ellipsis 133
+dagger 134
+daggerdbl 135
+Euro 136
+perthousand 137
+cyr_LJE 138
+guilsinglleft 139
+cyr_NJE 140
+cyr_KJE 141
+cyr_TSHE 142
+cyr_DZHE 143
+cyr_dje 144
+quotesinglleft 145
+quotesinglright 146
+quotedblleft 147
+quotedblright 148
+bullet 149
+endash 150
+emdash 151
+trademark 153
+cyr_lje 154
+guilsinglright 155
+cyr_nje 156
+cyr_kje 157
+cyr_tshe 158
+cyr_dzhe 159
+nbspace 160
+cyr_SHORT_U 161
+cyr_short_u 162
+cyr_JE 163
+currency 164
+cyr_GHE_UPTURN 165
+brokenbar 166
+section 167
+cyr_IO 168
+copyright 169
+cyr_UKRAINIAN_IE 170
+guillemotleft 171
+notsign 172
+hyphen 173
+registered 174
+cyr_YI 175
+degree 176
+plusminus 177
+cyr_BYELORUSSIAN_UKRAINIAN_I 178
+cyr_byelorussian_ukrainian_i 179
+cyr_ghe_upturn 180
+mu 181
+paragraph 182
+periodcentered 183
+cyr_io 184
+numero 185
+cyr_ukrainian_ie 186
+guillemotright 187
+cyr_je 188
+cyr_DZE 189
+cyr_dze 190
+cyr_yi 191
+cyr_A 192
+cyr_BE 193
+cyr_VE 194
+cyr_GHE 195
+cyr_DE 196
+cyr_IE 197
+cyr_ZHE 198
+cyr_ZE 199
+cyr_I 200
+cyr_SHORT_I 201
+cyr_KA 202
+cyr_EL 203
+cyr_EM 204
+cyr_EN 205
+cyr_O 206
+cyr_PE 207
+cyr_ER 208
+cyr_ES 209
+cyr_TE 210
+cyr_U 211
+cyr_EF 212
+cyr_HA 213
+cyr_TSE 214
+cyr_CHE 215
+cyr_SHA 216
+cyr_SHCHA 217
+cyr_HARD_SIGN 218
+cyr_YERU 219
+cyr_SOFT_SIGN 220
+cyr_E 221
+cyr_YU 222
+cyr_YA 223
+cyr_a 224
+cyr_be 225
+cyr_ve 226
+cyr_ghe 227
+cyr_de 228
+cyr_ie 229
+cyr_zhe 230
+cyr_ze 231
+cyr_i 232
+cyr_short_i 233
+cyr_ka 234
+cyr_el 235
+cyr_em 236
+cyr_en 237
+cyr_o 238
+cyr_pe 239
+cyr_er 240
+cyr_es 241
+cyr_te 242
+cyr_u 243
+cyr_ef 244
+cyr_ha 245
+cyr_tse 246
+cyr_che 247
+cyr_sha 248
+cyr_shcha 249
+cyr_hard_sign 250
+cyr_yeru 251
+cyr_soft_sign 252
+cyr_e 253
+cyr_yu 254
+cyr_ya 255
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/ibm-866.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/ibm-866.tbl
new file mode 100644
index 00000000..ea95dcf9
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/ibm-866.tbl
@@ -0,0 +1,128 @@
+cyr_A 128
+cyr_BE 129
+cyr_CHE 151
+cyr_DE 132
+cyr_E 157
+cyr_EF 148
+cyr_EL 139
+cyr_EM 140
+cyr_EN 141
+cyr_ER 144
+cyr_ES 145
+cyr_GHE 131
+cyr_HA 149
+cyr_HARD_SIGN 154
+cyr_I 136
+cyr_IE 133
+cyr_KA 138
+cyr_O 142
+cyr_PE 143
+cyr_SHA 152
+cyr_SHCHA 153
+cyr_SHORT_I 137
+cyr_SOFT_SIGN 156
+cyr_TE 146
+cyr_TSE 150
+cyr_U 147
+cyr_VE 130
+cyr_YA 159
+cyr_YERU 155
+cyr_IO 240
+cyr_YU 158
+cyr_ZE 135
+cyr_ZHE 134
+cyr_a 160
+cyr_be 161
+cyr_che 231
+cyr_de 164
+cyr_e 237
+cyr_ef 228
+cyr_el 171
+cyr_em 172
+cyr_en 173
+cyr_er 224
+cyr_es 225
+graphic_100pc 219
+graphic_25pc 178
+graphic_50pc 177
+graphic_75pc 176
+graphic_LD 187
+graphic_LR 205
+graphic_LRD 203
+graphic_LRT 202
+graphic_LRTD 206
+graphic_LRd 209
+graphic_LRt 207
+graphic_LRtd 216
+graphic_LT 188
+graphic_LTD 185
+graphic_Ld 184
+graphic_Lt 190
+graphic_Ltd 181
+graphic_RD 201
+graphic_RT 200
+graphic_RTD 204
+graphic_Rd 213
+graphic_Rt 212
+graphic_Rtd 198
+graphic_TD 186
+copyright 252
+degree 248
+graphic_dintegral 245
+graphic_divide 246
+graphic_equal 247
+graphic_fatdot 249
+graphic_ge 242
+graphic_lD 183
+graphic_lT 189
+graphic_lTD 182
+graphic_ld 191
+graphic_le 243
+graphic_leandot 250
+graphic_lefthalf 221
+graphic_lowerhalf 220
+graphic_lr 196
+graphic_lrD 210
+graphic_lrT 208
+graphic_lrTD 215
+graphic_lrd 194
+graphic_lrt 193
+graphic_lrtd 197
+graphic_lt 217
+graphic_ltd 180
+graphic_power2 253
+graphic_rD 214
+graphic_rT 211
+graphic_rTD 199
+graphic_rd 218
+graphic_righthalf 222
+graphic_root 251
+graphic_rt 192
+graphic_rtd 195
+nbspace 255
+graphic_square 254
+graphic_td 179
+graphic_tintegral 244
+graphic_upperhalf 223
+cyr_ghe 163
+cyr_ha 229
+cyr_hard_sign 234
+cyr_i 168
+cyr_ie 165
+cyr_ka 170
+cyr_o 174
+cyr_pe 175
+cyr_sha 232
+cyr_shcha 233
+cyr_short_i 169
+cyr_soft_sign 236
+cyr_te 226
+cyr_tse 230
+cyr_u 227
+cyr_ve 162
+cyr_ya 239
+cyr_yeru 235
+cyr_io 241
+cyr_yu 238
+cyr_ze 167
+cyr_zhe 166
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/iso8859-5.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/iso8859-5.tbl
new file mode 100644
index 00000000..6bf76afc
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/iso8859-5.tbl
@@ -0,0 +1,127 @@
+cyr_GHE_UPTURN 128
+cyr_ghe_upturn 129
+quotesinglbase 130
+currency 131
+quotedblbase 132
+ellipsis 133
+dagger 134
+daggerdbl 135
+Euro 136
+perthousand 137
+brokenbar 138
+guilsinglleft 139
+copyright 140
+guillemotleft 141
+notsign 142
+registered 143
+degree 144
+quotesinglleft 145
+quotesinglright 146
+quotedblleft 147
+quotedblright 148
+bullet 149
+endash 150
+emdash 151
+trademark 153
+plusminus 154
+guilsinglright 155
+mu 156
+paragraph 157
+periodcentered 158
+guillemotright 159
+nbspace 160
+cyr_IO 161
+cyr_DJE 162
+cyr_GJE 163
+cyr_UKRAINIAN_IE 164
+cyr_DZE 165
+cyr_BYELORUSSIAN_UKRAINIAN_I 166
+cyr_YI 167
+cyr_JE 168
+cyr_LJE 169
+cyr_NJE 170
+cyr_TSHE 171
+cyr_KJE 172
+hyphen 173
+cyr_SHORT_U 174
+cyr_DZHE 175
+cyr_A 176
+cyr_BE 177
+cyr_VE 178
+cyr_GHE 179
+cyr_DE 180
+cyr_IE 181
+cyr_ZHE 182
+cyr_ZE 183
+cyr_I 184
+cyr_SHORT_I 185
+cyr_KA 186
+cyr_EL 187
+cyr_EM 188
+cyr_EN 189
+cyr_O 190
+cyr_PE 191
+cyr_ER 192
+cyr_ES 193
+cyr_TE 194
+cyr_U 195
+cyr_EF 196
+cyr_HA 197
+cyr_TSE 198
+cyr_CHE 199
+cyr_SHA 200
+cyr_SHCHA 201
+cyr_HARD_SIGN 202
+cyr_YERU 203
+cyr_SOFT_SIGN 204
+cyr_E 205
+cyr_YU 206
+cyr_YA 207
+cyr_a 208
+cyr_be 209
+cyr_ve 210
+cyr_ghe 211
+cyr_de 212
+cyr_ie 213
+cyr_zhe 214
+cyr_ze 215
+cyr_i 216
+cyr_short_i 217
+cyr_ka 218
+cyr_el 219
+cyr_em 220
+cyr_en 221
+cyr_o 222
+cyr_pe 223
+cyr_er 224
+cyr_es 225
+cyr_te 226
+cyr_u 227
+cyr_ef 228
+cyr_ha 229
+cyr_tse 230
+cyr_che 231
+cyr_sha 232
+cyr_shcha 233
+cyr_hard_sign 234
+cyr_yeru 235
+cyr_soft_sign 236
+cyr_e 237
+cyr_yu 238
+cyr_ya 239
+numero 240
+cyr_io 241
+cyr_dje 242
+cyr_gje 243
+cyr_ukrainian_ie 244
+cyr_dze 245
+cyr_byelorussian_ukrainian_i 246
+cyr_yi 247
+cyr_je 248
+cyr_lje 249
+cyr_nje 250
+cyr_tshe 251
+cyr_kje 252
+section 253
+cyr_short_u 254
+cyr_dzhe 255
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/koi8-r.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/koi8-r.tbl
new file mode 100644
index 00000000..eb0c3073
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/bulgarian/koi8-r.tbl
@@ -0,0 +1,128 @@
+cyr_A 225
+cyr_BE 226
+cyr_CHE 254
+cyr_DE 228
+cyr_E 252
+cyr_EF 230
+cyr_EL 236
+cyr_EM 237
+cyr_EN 238
+cyr_ER 242
+cyr_ES 243
+cyr_GHE 231
+cyr_HA 232
+cyr_HARD_SIGN 255
+cyr_I 233
+cyr_IE 229
+cyr_KA 235
+cyr_O 239
+cyr_PE 240
+cyr_SHA 251
+cyr_SHCHA 253
+cyr_SHORT_I 234
+cyr_SOFT_SIGN 248
+cyr_TE 244
+cyr_TSE 227
+cyr_U 245
+cyr_VE 247
+cyr_YA 241
+cyr_YERU 249
+cyr_IO 179
+cyr_YU 224
+cyr_ZE 250
+cyr_ZHE 246
+cyr_a 193
+cyr_be 194
+cyr_che 222
+cyr_de 196
+cyr_e 220
+cyr_ef 198
+cyr_el 204
+cyr_em 205
+cyr_en 206
+cyr_er 210
+cyr_es 211
+graphic_100pc 141
+graphic_25pc 144
+graphic_50pc 145
+graphic_75pc 146
+graphic_LD 168
+graphic_LR 160
+graphic_LRD 184
+graphic_LRT 187
+graphic_LRTD 190
+graphic_LRd 182
+graphic_LRt 185
+graphic_LRtd 188
+graphic_LT 174
+graphic_LTD 181
+graphic_Ld 166
+graphic_Lt 172
+graphic_Ltd 178
+graphic_RD 165
+graphic_RT 171
+graphic_RTD 177
+graphic_Rd 162
+graphic_Rt 170
+graphic_Rtd 175
+graphic_TD 161
+copyright 191
+degree 156
+graphic_dintegral 155
+graphic_divide 159
+graphic_equal 151
+graphic_fatdot 149
+graphic_ge 153
+graphic_lD 167
+graphic_lT 173
+graphic_lTD 180
+graphic_ld 131
+graphic_le 152
+graphic_leandot 158
+graphic_lefthalf 142
+graphic_lowerhalf 140
+graphic_lr 128
+graphic_lrD 183
+graphic_lrT 186
+graphic_lrTD 189
+graphic_lrd 136
+graphic_lrt 137
+graphic_lrtd 138
+graphic_lt 133
+graphic_ltd 135
+graphic_power2 157
+graphic_rD 164
+graphic_rT 169
+graphic_rTD 176
+graphic_rd 130
+graphic_righthalf 143
+graphic_root 150
+graphic_rt 132
+graphic_rtd 134
+nbspace 154
+graphic_square 148
+graphic_td 129
+graphic_tintegral 147
+graphic_upperhalf 139
+cyr_ghe 199
+cyr_ha 200
+cyr_hard_sign 223
+cyr_i 201
+cyr_ie 197
+cyr_ka 203
+cyr_o 207
+cyr_pe 208
+cyr_sha 219
+cyr_shcha 221
+cyr_short_i 202
+cyr_soft_sign 216
+cyr_te 212
+cyr_tse 195
+cyr_u 213
+cyr_ve 215
+cyr_ya 209
+cyr_yeru 217
+cyr_io 163
+cyr_yu 192
+cyr_ze 218
+cyr_zhe 214
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/encodings.alias b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/encodings.alias
new file mode 100644
index 00000000..f8ef5c17
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/encodings.alias
@@ -0,0 +1,4 @@
+# alias real-name
+iso8859-1 koi8-r
+windows-1251 ibm-1251
+cp-866 ibm-866
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/ibm-1251.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/ibm-1251.tbl
new file mode 100644
index 00000000..02e57978
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/ibm-1251.tbl
@@ -0,0 +1,127 @@
+cyr_DJE 128
+cyr_GJE 129
+quotesinglbase 130
+cyr_gje 131
+quotedblbase 132
+ellipsis 133
+dagger 134
+daggerdbl 135
+Euro 136
+perthousand 137
+cyr_LJE 138
+guilsinglleft 139
+cyr_NJE 140
+cyr_KJE 141
+cyr_TSHE 142
+cyr_DZHE 143
+cyr_dje 144
+quotesinglleft 145
+quotesinglright 146
+quotedblleft 147
+quotedblright 148
+bullet 149
+endash 150
+emdash 151
+trademark 153
+cyr_lje 154
+guilsinglright 155
+cyr_nje 156
+cyr_kje 157
+cyr_tshe 158
+cyr_dzhe 159
+nbspace 160
+cyr_SHORT_U 161
+cyr_short_u 162
+cyr_JE 163
+currency 164
+cyr_GHE_UPTURN 165
+brokenbar 166
+section 167
+cyr_IO 168
+copyright 169
+cyr_UKRAINIAN_IE 170
+guillemotleft 171
+notsign 172
+hyphen 173
+registered 174
+cyr_YI 175
+degree 176
+plusminus 177
+cyr_BYELORUSSIAN_UKRAINIAN_I 178
+cyr_byelorussian_ukrainian_i 179
+cyr_ghe_upturn 180
+mu 181
+paragraph 182
+periodcentered 183
+cyr_io 184
+numero 185
+cyr_ukrainian_ie 186
+guillemotright 187
+cyr_je 188
+cyr_DZE 189
+cyr_dze 190
+cyr_yi 191
+cyr_A 192
+cyr_BE 193
+cyr_VE 194
+cyr_GHE 195
+cyr_DE 196
+cyr_IE 197
+cyr_ZHE 198
+cyr_ZE 199
+cyr_I 200
+cyr_SHORT_I 201
+cyr_KA 202
+cyr_EL 203
+cyr_EM 204
+cyr_EN 205
+cyr_O 206
+cyr_PE 207
+cyr_ER 208
+cyr_ES 209
+cyr_TE 210
+cyr_U 211
+cyr_EF 212
+cyr_HA 213
+cyr_TSE 214
+cyr_CHE 215
+cyr_SHA 216
+cyr_SHCHA 217
+cyr_HARD_SIGN 218
+cyr_YERU 219
+cyr_SOFT_SIGN 220
+cyr_E 221
+cyr_YU 222
+cyr_YA 223
+cyr_a 224
+cyr_be 225
+cyr_ve 226
+cyr_ghe 227
+cyr_de 228
+cyr_ie 229
+cyr_zhe 230
+cyr_ze 231
+cyr_i 232
+cyr_short_i 233
+cyr_ka 234
+cyr_el 235
+cyr_em 236
+cyr_en 237
+cyr_o 238
+cyr_pe 239
+cyr_er 240
+cyr_es 241
+cyr_te 242
+cyr_u 243
+cyr_ef 244
+cyr_ha 245
+cyr_tse 246
+cyr_che 247
+cyr_sha 248
+cyr_shcha 249
+cyr_hard_sign 250
+cyr_yeru 251
+cyr_soft_sign 252
+cyr_e 253
+cyr_yu 254
+cyr_ya 255
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/ibm-866.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/ibm-866.tbl
new file mode 100644
index 00000000..ea95dcf9
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/ibm-866.tbl
@@ -0,0 +1,128 @@
+cyr_A 128
+cyr_BE 129
+cyr_CHE 151
+cyr_DE 132
+cyr_E 157
+cyr_EF 148
+cyr_EL 139
+cyr_EM 140
+cyr_EN 141
+cyr_ER 144
+cyr_ES 145
+cyr_GHE 131
+cyr_HA 149
+cyr_HARD_SIGN 154
+cyr_I 136
+cyr_IE 133
+cyr_KA 138
+cyr_O 142
+cyr_PE 143
+cyr_SHA 152
+cyr_SHCHA 153
+cyr_SHORT_I 137
+cyr_SOFT_SIGN 156
+cyr_TE 146
+cyr_TSE 150
+cyr_U 147
+cyr_VE 130
+cyr_YA 159
+cyr_YERU 155
+cyr_IO 240
+cyr_YU 158
+cyr_ZE 135
+cyr_ZHE 134
+cyr_a 160
+cyr_be 161
+cyr_che 231
+cyr_de 164
+cyr_e 237
+cyr_ef 228
+cyr_el 171
+cyr_em 172
+cyr_en 173
+cyr_er 224
+cyr_es 225
+graphic_100pc 219
+graphic_25pc 178
+graphic_50pc 177
+graphic_75pc 176
+graphic_LD 187
+graphic_LR 205
+graphic_LRD 203
+graphic_LRT 202
+graphic_LRTD 206
+graphic_LRd 209
+graphic_LRt 207
+graphic_LRtd 216
+graphic_LT 188
+graphic_LTD 185
+graphic_Ld 184
+graphic_Lt 190
+graphic_Ltd 181
+graphic_RD 201
+graphic_RT 200
+graphic_RTD 204
+graphic_Rd 213
+graphic_Rt 212
+graphic_Rtd 198
+graphic_TD 186
+copyright 252
+degree 248
+graphic_dintegral 245
+graphic_divide 246
+graphic_equal 247
+graphic_fatdot 249
+graphic_ge 242
+graphic_lD 183
+graphic_lT 189
+graphic_lTD 182
+graphic_ld 191
+graphic_le 243
+graphic_leandot 250
+graphic_lefthalf 221
+graphic_lowerhalf 220
+graphic_lr 196
+graphic_lrD 210
+graphic_lrT 208
+graphic_lrTD 215
+graphic_lrd 194
+graphic_lrt 193
+graphic_lrtd 197
+graphic_lt 217
+graphic_ltd 180
+graphic_power2 253
+graphic_rD 214
+graphic_rT 211
+graphic_rTD 199
+graphic_rd 218
+graphic_righthalf 222
+graphic_root 251
+graphic_rt 192
+graphic_rtd 195
+nbspace 255
+graphic_square 254
+graphic_td 179
+graphic_tintegral 244
+graphic_upperhalf 223
+cyr_ghe 163
+cyr_ha 229
+cyr_hard_sign 234
+cyr_i 168
+cyr_ie 165
+cyr_ka 170
+cyr_o 174
+cyr_pe 175
+cyr_sha 232
+cyr_shcha 233
+cyr_short_i 169
+cyr_soft_sign 236
+cyr_te 226
+cyr_tse 230
+cyr_u 227
+cyr_ve 162
+cyr_ya 239
+cyr_yeru 235
+cyr_io 241
+cyr_yu 238
+cyr_ze 167
+cyr_zhe 166
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/iso8859-5.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/iso8859-5.tbl
new file mode 100644
index 00000000..6bf76afc
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/iso8859-5.tbl
@@ -0,0 +1,127 @@
+cyr_GHE_UPTURN 128
+cyr_ghe_upturn 129
+quotesinglbase 130
+currency 131
+quotedblbase 132
+ellipsis 133
+dagger 134
+daggerdbl 135
+Euro 136
+perthousand 137
+brokenbar 138
+guilsinglleft 139
+copyright 140
+guillemotleft 141
+notsign 142
+registered 143
+degree 144
+quotesinglleft 145
+quotesinglright 146
+quotedblleft 147
+quotedblright 148
+bullet 149
+endash 150
+emdash 151
+trademark 153
+plusminus 154
+guilsinglright 155
+mu 156
+paragraph 157
+periodcentered 158
+guillemotright 159
+nbspace 160
+cyr_IO 161
+cyr_DJE 162
+cyr_GJE 163
+cyr_UKRAINIAN_IE 164
+cyr_DZE 165
+cyr_BYELORUSSIAN_UKRAINIAN_I 166
+cyr_YI 167
+cyr_JE 168
+cyr_LJE 169
+cyr_NJE 170
+cyr_TSHE 171
+cyr_KJE 172
+hyphen 173
+cyr_SHORT_U 174
+cyr_DZHE 175
+cyr_A 176
+cyr_BE 177
+cyr_VE 178
+cyr_GHE 179
+cyr_DE 180
+cyr_IE 181
+cyr_ZHE 182
+cyr_ZE 183
+cyr_I 184
+cyr_SHORT_I 185
+cyr_KA 186
+cyr_EL 187
+cyr_EM 188
+cyr_EN 189
+cyr_O 190
+cyr_PE 191
+cyr_ER 192
+cyr_ES 193
+cyr_TE 194
+cyr_U 195
+cyr_EF 196
+cyr_HA 197
+cyr_TSE 198
+cyr_CHE 199
+cyr_SHA 200
+cyr_SHCHA 201
+cyr_HARD_SIGN 202
+cyr_YERU 203
+cyr_SOFT_SIGN 204
+cyr_E 205
+cyr_YU 206
+cyr_YA 207
+cyr_a 208
+cyr_be 209
+cyr_ve 210
+cyr_ghe 211
+cyr_de 212
+cyr_ie 213
+cyr_zhe 214
+cyr_ze 215
+cyr_i 216
+cyr_short_i 217
+cyr_ka 218
+cyr_el 219
+cyr_em 220
+cyr_en 221
+cyr_o 222
+cyr_pe 223
+cyr_er 224
+cyr_es 225
+cyr_te 226
+cyr_u 227
+cyr_ef 228
+cyr_ha 229
+cyr_tse 230
+cyr_che 231
+cyr_sha 232
+cyr_shcha 233
+cyr_hard_sign 234
+cyr_yeru 235
+cyr_soft_sign 236
+cyr_e 237
+cyr_yu 238
+cyr_ya 239
+numero 240
+cyr_io 241
+cyr_dje 242
+cyr_gje 243
+cyr_ukrainian_ie 244
+cyr_dze 245
+cyr_byelorussian_ukrainian_i 246
+cyr_yi 247
+cyr_je 248
+cyr_lje 249
+cyr_nje 250
+cyr_tshe 251
+cyr_kje 252
+section 253
+cyr_short_u 254
+cyr_dzhe 255
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/koi8-r.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/koi8-r.tbl
new file mode 100644
index 00000000..eb0c3073
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/cyrillic/koi8-r.tbl
@@ -0,0 +1,128 @@
+cyr_A 225
+cyr_BE 226
+cyr_CHE 254
+cyr_DE 228
+cyr_E 252
+cyr_EF 230
+cyr_EL 236
+cyr_EM 237
+cyr_EN 238
+cyr_ER 242
+cyr_ES 243
+cyr_GHE 231
+cyr_HA 232
+cyr_HARD_SIGN 255
+cyr_I 233
+cyr_IE 229
+cyr_KA 235
+cyr_O 239
+cyr_PE 240
+cyr_SHA 251
+cyr_SHCHA 253
+cyr_SHORT_I 234
+cyr_SOFT_SIGN 248
+cyr_TE 244
+cyr_TSE 227
+cyr_U 245
+cyr_VE 247
+cyr_YA 241
+cyr_YERU 249
+cyr_IO 179
+cyr_YU 224
+cyr_ZE 250
+cyr_ZHE 246
+cyr_a 193
+cyr_be 194
+cyr_che 222
+cyr_de 196
+cyr_e 220
+cyr_ef 198
+cyr_el 204
+cyr_em 205
+cyr_en 206
+cyr_er 210
+cyr_es 211
+graphic_100pc 141
+graphic_25pc 144
+graphic_50pc 145
+graphic_75pc 146
+graphic_LD 168
+graphic_LR 160
+graphic_LRD 184
+graphic_LRT 187
+graphic_LRTD 190
+graphic_LRd 182
+graphic_LRt 185
+graphic_LRtd 188
+graphic_LT 174
+graphic_LTD 181
+graphic_Ld 166
+graphic_Lt 172
+graphic_Ltd 178
+graphic_RD 165
+graphic_RT 171
+graphic_RTD 177
+graphic_Rd 162
+graphic_Rt 170
+graphic_Rtd 175
+graphic_TD 161
+copyright 191
+degree 156
+graphic_dintegral 155
+graphic_divide 159
+graphic_equal 151
+graphic_fatdot 149
+graphic_ge 153
+graphic_lD 167
+graphic_lT 173
+graphic_lTD 180
+graphic_ld 131
+graphic_le 152
+graphic_leandot 158
+graphic_lefthalf 142
+graphic_lowerhalf 140
+graphic_lr 128
+graphic_lrD 183
+graphic_lrT 186
+graphic_lrTD 189
+graphic_lrd 136
+graphic_lrt 137
+graphic_lrtd 138
+graphic_lt 133
+graphic_ltd 135
+graphic_power2 157
+graphic_rD 164
+graphic_rT 169
+graphic_rTD 176
+graphic_rd 130
+graphic_righthalf 143
+graphic_root 150
+graphic_rt 132
+graphic_rtd 134
+nbspace 154
+graphic_square 148
+graphic_td 129
+graphic_tintegral 147
+graphic_upperhalf 139
+cyr_ghe 199
+cyr_ha 200
+cyr_hard_sign 223
+cyr_i 201
+cyr_ie 197
+cyr_ka 203
+cyr_o 207
+cyr_pe 208
+cyr_sha 219
+cyr_shcha 221
+cyr_short_i 202
+cyr_soft_sign 216
+cyr_te 212
+cyr_tse 195
+cyr_u 213
+cyr_ve 215
+cyr_ya 209
+cyr_yeru 217
+cyr_io 163
+cyr_yu 192
+cyr_ze 218
+cyr_zhe 214
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/latin1/iso8859-1.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/latin1/iso8859-1.tbl
new file mode 100644
index 00000000..e69de29b
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/latin2/iso8859-2.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/latin2/iso8859-2.tbl
new file mode 100644
index 00000000..e69de29b
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/latin4/iso8859-4 b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/latin4/iso8859-4
new file mode 100644
index 00000000..e69de29b
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/latin4/iso8859-4.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/latin4/iso8859-4.tbl
new file mode 100644
index 00000000..e69de29b
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/latin5/iso8859-9 b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/latin5/iso8859-9
new file mode 100644
index 00000000..e69de29b
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/README b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/README
new file mode 100644
index 00000000..08f8ce36
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/README
@@ -0,0 +1,3 @@
+These files are copies of thos provided for the language "cyrillic"
+and are provided for compatibility purposes only, please
+use the language "cyrillic" instead.
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/encodings.alias b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/encodings.alias
new file mode 100644
index 00000000..f8ef5c17
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/encodings.alias
@@ -0,0 +1,4 @@
+# alias real-name
+iso8859-1 koi8-r
+windows-1251 ibm-1251
+cp-866 ibm-866
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/ibm-1251.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/ibm-1251.tbl
new file mode 100644
index 00000000..02e57978
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/ibm-1251.tbl
@@ -0,0 +1,127 @@
+cyr_DJE 128
+cyr_GJE 129
+quotesinglbase 130
+cyr_gje 131
+quotedblbase 132
+ellipsis 133
+dagger 134
+daggerdbl 135
+Euro 136
+perthousand 137
+cyr_LJE 138
+guilsinglleft 139
+cyr_NJE 140
+cyr_KJE 141
+cyr_TSHE 142
+cyr_DZHE 143
+cyr_dje 144
+quotesinglleft 145
+quotesinglright 146
+quotedblleft 147
+quotedblright 148
+bullet 149
+endash 150
+emdash 151
+trademark 153
+cyr_lje 154
+guilsinglright 155
+cyr_nje 156
+cyr_kje 157
+cyr_tshe 158
+cyr_dzhe 159
+nbspace 160
+cyr_SHORT_U 161
+cyr_short_u 162
+cyr_JE 163
+currency 164
+cyr_GHE_UPTURN 165
+brokenbar 166
+section 167
+cyr_IO 168
+copyright 169
+cyr_UKRAINIAN_IE 170
+guillemotleft 171
+notsign 172
+hyphen 173
+registered 174
+cyr_YI 175
+degree 176
+plusminus 177
+cyr_BYELORUSSIAN_UKRAINIAN_I 178
+cyr_byelorussian_ukrainian_i 179
+cyr_ghe_upturn 180
+mu 181
+paragraph 182
+periodcentered 183
+cyr_io 184
+numero 185
+cyr_ukrainian_ie 186
+guillemotright 187
+cyr_je 188
+cyr_DZE 189
+cyr_dze 190
+cyr_yi 191
+cyr_A 192
+cyr_BE 193
+cyr_VE 194
+cyr_GHE 195
+cyr_DE 196
+cyr_IE 197
+cyr_ZHE 198
+cyr_ZE 199
+cyr_I 200
+cyr_SHORT_I 201
+cyr_KA 202
+cyr_EL 203
+cyr_EM 204
+cyr_EN 205
+cyr_O 206
+cyr_PE 207
+cyr_ER 208
+cyr_ES 209
+cyr_TE 210
+cyr_U 211
+cyr_EF 212
+cyr_HA 213
+cyr_TSE 214
+cyr_CHE 215
+cyr_SHA 216
+cyr_SHCHA 217
+cyr_HARD_SIGN 218
+cyr_YERU 219
+cyr_SOFT_SIGN 220
+cyr_E 221
+cyr_YU 222
+cyr_YA 223
+cyr_a 224
+cyr_be 225
+cyr_ve 226
+cyr_ghe 227
+cyr_de 228
+cyr_ie 229
+cyr_zhe 230
+cyr_ze 231
+cyr_i 232
+cyr_short_i 233
+cyr_ka 234
+cyr_el 235
+cyr_em 236
+cyr_en 237
+cyr_o 238
+cyr_pe 239
+cyr_er 240
+cyr_es 241
+cyr_te 242
+cyr_u 243
+cyr_ef 244
+cyr_ha 245
+cyr_tse 246
+cyr_che 247
+cyr_sha 248
+cyr_shcha 249
+cyr_hard_sign 250
+cyr_yeru 251
+cyr_soft_sign 252
+cyr_e 253
+cyr_yu 254
+cyr_ya 255
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/ibm-866.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/ibm-866.tbl
new file mode 100644
index 00000000..ea95dcf9
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/ibm-866.tbl
@@ -0,0 +1,128 @@
+cyr_A 128
+cyr_BE 129
+cyr_CHE 151
+cyr_DE 132
+cyr_E 157
+cyr_EF 148
+cyr_EL 139
+cyr_EM 140
+cyr_EN 141
+cyr_ER 144
+cyr_ES 145
+cyr_GHE 131
+cyr_HA 149
+cyr_HARD_SIGN 154
+cyr_I 136
+cyr_IE 133
+cyr_KA 138
+cyr_O 142
+cyr_PE 143
+cyr_SHA 152
+cyr_SHCHA 153
+cyr_SHORT_I 137
+cyr_SOFT_SIGN 156
+cyr_TE 146
+cyr_TSE 150
+cyr_U 147
+cyr_VE 130
+cyr_YA 159
+cyr_YERU 155
+cyr_IO 240
+cyr_YU 158
+cyr_ZE 135
+cyr_ZHE 134
+cyr_a 160
+cyr_be 161
+cyr_che 231
+cyr_de 164
+cyr_e 237
+cyr_ef 228
+cyr_el 171
+cyr_em 172
+cyr_en 173
+cyr_er 224
+cyr_es 225
+graphic_100pc 219
+graphic_25pc 178
+graphic_50pc 177
+graphic_75pc 176
+graphic_LD 187
+graphic_LR 205
+graphic_LRD 203
+graphic_LRT 202
+graphic_LRTD 206
+graphic_LRd 209
+graphic_LRt 207
+graphic_LRtd 216
+graphic_LT 188
+graphic_LTD 185
+graphic_Ld 184
+graphic_Lt 190
+graphic_Ltd 181
+graphic_RD 201
+graphic_RT 200
+graphic_RTD 204
+graphic_Rd 213
+graphic_Rt 212
+graphic_Rtd 198
+graphic_TD 186
+copyright 252
+degree 248
+graphic_dintegral 245
+graphic_divide 246
+graphic_equal 247
+graphic_fatdot 249
+graphic_ge 242
+graphic_lD 183
+graphic_lT 189
+graphic_lTD 182
+graphic_ld 191
+graphic_le 243
+graphic_leandot 250
+graphic_lefthalf 221
+graphic_lowerhalf 220
+graphic_lr 196
+graphic_lrD 210
+graphic_lrT 208
+graphic_lrTD 215
+graphic_lrd 194
+graphic_lrt 193
+graphic_lrtd 197
+graphic_lt 217
+graphic_ltd 180
+graphic_power2 253
+graphic_rD 214
+graphic_rT 211
+graphic_rTD 199
+graphic_rd 218
+graphic_righthalf 222
+graphic_root 251
+graphic_rt 192
+graphic_rtd 195
+nbspace 255
+graphic_square 254
+graphic_td 179
+graphic_tintegral 244
+graphic_upperhalf 223
+cyr_ghe 163
+cyr_ha 229
+cyr_hard_sign 234
+cyr_i 168
+cyr_ie 165
+cyr_ka 170
+cyr_o 174
+cyr_pe 175
+cyr_sha 232
+cyr_shcha 233
+cyr_short_i 169
+cyr_soft_sign 236
+cyr_te 226
+cyr_tse 230
+cyr_u 227
+cyr_ve 162
+cyr_ya 239
+cyr_yeru 235
+cyr_io 241
+cyr_yu 238
+cyr_ze 167
+cyr_zhe 166
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/iso8859-5.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/iso8859-5.tbl
new file mode 100644
index 00000000..6bf76afc
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/iso8859-5.tbl
@@ -0,0 +1,127 @@
+cyr_GHE_UPTURN 128
+cyr_ghe_upturn 129
+quotesinglbase 130
+currency 131
+quotedblbase 132
+ellipsis 133
+dagger 134
+daggerdbl 135
+Euro 136
+perthousand 137
+brokenbar 138
+guilsinglleft 139
+copyright 140
+guillemotleft 141
+notsign 142
+registered 143
+degree 144
+quotesinglleft 145
+quotesinglright 146
+quotedblleft 147
+quotedblright 148
+bullet 149
+endash 150
+emdash 151
+trademark 153
+plusminus 154
+guilsinglright 155
+mu 156
+paragraph 157
+periodcentered 158
+guillemotright 159
+nbspace 160
+cyr_IO 161
+cyr_DJE 162
+cyr_GJE 163
+cyr_UKRAINIAN_IE 164
+cyr_DZE 165
+cyr_BYELORUSSIAN_UKRAINIAN_I 166
+cyr_YI 167
+cyr_JE 168
+cyr_LJE 169
+cyr_NJE 170
+cyr_TSHE 171
+cyr_KJE 172
+hyphen 173
+cyr_SHORT_U 174
+cyr_DZHE 175
+cyr_A 176
+cyr_BE 177
+cyr_VE 178
+cyr_GHE 179
+cyr_DE 180
+cyr_IE 181
+cyr_ZHE 182
+cyr_ZE 183
+cyr_I 184
+cyr_SHORT_I 185
+cyr_KA 186
+cyr_EL 187
+cyr_EM 188
+cyr_EN 189
+cyr_O 190
+cyr_PE 191
+cyr_ER 192
+cyr_ES 193
+cyr_TE 194
+cyr_U 195
+cyr_EF 196
+cyr_HA 197
+cyr_TSE 198
+cyr_CHE 199
+cyr_SHA 200
+cyr_SHCHA 201
+cyr_HARD_SIGN 202
+cyr_YERU 203
+cyr_SOFT_SIGN 204
+cyr_E 205
+cyr_YU 206
+cyr_YA 207
+cyr_a 208
+cyr_be 209
+cyr_ve 210
+cyr_ghe 211
+cyr_de 212
+cyr_ie 213
+cyr_zhe 214
+cyr_ze 215
+cyr_i 216
+cyr_short_i 217
+cyr_ka 218
+cyr_el 219
+cyr_em 220
+cyr_en 221
+cyr_o 222
+cyr_pe 223
+cyr_er 224
+cyr_es 225
+cyr_te 226
+cyr_u 227
+cyr_ef 228
+cyr_ha 229
+cyr_tse 230
+cyr_che 231
+cyr_sha 232
+cyr_shcha 233
+cyr_hard_sign 234
+cyr_yeru 235
+cyr_soft_sign 236
+cyr_e 237
+cyr_yu 238
+cyr_ya 239
+numero 240
+cyr_io 241
+cyr_dje 242
+cyr_gje 243
+cyr_ukrainian_ie 244
+cyr_dze 245
+cyr_byelorussian_ukrainian_i 246
+cyr_yi 247
+cyr_je 248
+cyr_lje 249
+cyr_nje 250
+cyr_tshe 251
+cyr_kje 252
+section 253
+cyr_short_u 254
+cyr_dzhe 255
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/koi8-r.tbl b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/koi8-r.tbl
new file mode 100644
index 00000000..eb0c3073
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/encodings/russian/koi8-r.tbl
@@ -0,0 +1,128 @@
+cyr_A 225
+cyr_BE 226
+cyr_CHE 254
+cyr_DE 228
+cyr_E 252
+cyr_EF 230
+cyr_EL 236
+cyr_EM 237
+cyr_EN 238
+cyr_ER 242
+cyr_ES 243
+cyr_GHE 231
+cyr_HA 232
+cyr_HARD_SIGN 255
+cyr_I 233
+cyr_IE 229
+cyr_KA 235
+cyr_O 239
+cyr_PE 240
+cyr_SHA 251
+cyr_SHCHA 253
+cyr_SHORT_I 234
+cyr_SOFT_SIGN 248
+cyr_TE 244
+cyr_TSE 227
+cyr_U 245
+cyr_VE 247
+cyr_YA 241
+cyr_YERU 249
+cyr_IO 179
+cyr_YU 224
+cyr_ZE 250
+cyr_ZHE 246
+cyr_a 193
+cyr_be 194
+cyr_che 222
+cyr_de 196
+cyr_e 220
+cyr_ef 198
+cyr_el 204
+cyr_em 205
+cyr_en 206
+cyr_er 210
+cyr_es 211
+graphic_100pc 141
+graphic_25pc 144
+graphic_50pc 145
+graphic_75pc 146
+graphic_LD 168
+graphic_LR 160
+graphic_LRD 184
+graphic_LRT 187
+graphic_LRTD 190
+graphic_LRd 182
+graphic_LRt 185
+graphic_LRtd 188
+graphic_LT 174
+graphic_LTD 181
+graphic_Ld 166
+graphic_Lt 172
+graphic_Ltd 178
+graphic_RD 165
+graphic_RT 171
+graphic_RTD 177
+graphic_Rd 162
+graphic_Rt 170
+graphic_Rtd 175
+graphic_TD 161
+copyright 191
+degree 156
+graphic_dintegral 155
+graphic_divide 159
+graphic_equal 151
+graphic_fatdot 149
+graphic_ge 153
+graphic_lD 167
+graphic_lT 173
+graphic_lTD 180
+graphic_ld 131
+graphic_le 152
+graphic_leandot 158
+graphic_lefthalf 142
+graphic_lowerhalf 140
+graphic_lr 128
+graphic_lrD 183
+graphic_lrT 186
+graphic_lrTD 189
+graphic_lrd 136
+graphic_lrt 137
+graphic_lrtd 138
+graphic_lt 133
+graphic_ltd 135
+graphic_power2 157
+graphic_rD 164
+graphic_rT 169
+graphic_rTD 176
+graphic_rd 130
+graphic_righthalf 143
+graphic_root 150
+graphic_rt 132
+graphic_rtd 134
+nbspace 154
+graphic_square 148
+graphic_td 129
+graphic_tintegral 147
+graphic_upperhalf 139
+cyr_ghe 199
+cyr_ha 200
+cyr_hard_sign 223
+cyr_i 201
+cyr_ie 197
+cyr_ka 203
+cyr_o 207
+cyr_pe 208
+cyr_sha 219
+cyr_shcha 221
+cyr_short_i 202
+cyr_soft_sign 216
+cyr_te 212
+cyr_tse 195
+cyr_u 213
+cyr_ve 215
+cyr_ya 209
+cyr_yeru 217
+cyr_io 163
+cyr_yu 192
+cyr_ze 218
+cyr_zhe 214
diff --git a/application/third_party/dompdf/lib/ttf2ufm/src/ft.c b/application/third_party/dompdf/lib/ttf2ufm/src/ft.c
new file mode 100644
index 00000000..3bbcb896
--- /dev/null
+++ b/application/third_party/dompdf/lib/ttf2ufm/src/ft.c
@@ -0,0 +1,649 @@
+/*
+ * The font parser using the FreeType library version 2.
+ *
+ * see COPYRIGHT
+ *
+ */
+
+#ifdef USE_FREETYPE
+
+#include
+
+TTF2PT1 - A True Type to PostScript Type 1 Font Converter
+
+
+
+
+
+[
+
+
+ Based on ttf2pfa by Andrew Weeks, and help from Frank Siegert.
+
+]
+
+
+ Modification by Mark Heath.
+
+ Further modification by Sergey Babkin.
+
+ The Type1 assembler by I. Lee Hetherington with modifications by
+ Kai-Uwe Herbing.
+
+
+ ttf2pt1 [-options] ttffont.ttf [Fontname]
+
+or
+
+ ttf2pt1 [-options] ttffont.ttf -
+
+
+
+ a - Print out the absolute coordinates of dots in outlines. Such
+ a font can not be used by any program (that's why this option is
+ incompatible with '-e') but it has proven to be a valuable debuging
+ information.
+
+
+
+-e - Assemble the resulting font to produce a ready .pfa file.
+
+ [ S.B.: Personally I don't think that this option is particularly useful.
+ The same result may be achieved by piping the unassembled data
+ through t1asm, the Type 1 assembler. And, anyways, it's good to
+ have the t1utils package handy. But Mark and many users think that
+ this functionality is good and it took not much time to add this option. ]
+
+
+ f/F - The font file. Depending on the other options this file
+ will have one of the suffixes .t1a, .pfa or .pfb. If the conversion result
+ is requested on the standard output ('-' is used as the output file name)
+ then the font file will also be written there by default, if not overwritten
+ by another suboption of -G.
+ Default: enabled
+
+
+
+-l language[+argument] - Extract the fonts for the specified language from a
+ multi-language Unicode font. If this option is not used the converter
+ tries to guess the language by the values of the shell variable LANG.
+ If it is not able to guess the language by LANG it tries all the
+ languages in the order they are listed.
+
+ latin1 - for all the languages using the Latin-1 encoding
+
+ latin2 - for the Central European languages
+
+ latin4 - for the Baltic languages
+
+ latin5 - for the Turkish language
+
+ cyrillic - for the languages with Cyrillic alphabet
+
+ russian - historic synonym for cyrillic
+
+ bulgarian - historic synonym for cyrillic
+
+ adobestd - for the AdobeStandard encoding used by TeX
+
+ plane+argument - to select one plane from a multi-byte encoding
+
+ plane+pid=<pid>,eid=<eid>,<plane_number>
+
+ plane+<plane_number>
+
+ h - the maximal hint stack depth for the substituted hints.
+ The default value is 128, according to the limitation in X11. This seems to
+ be the lowest (and thus the safest) widespread value. To display the
+ hint stack depth required by each glyph in a .t1a file use the script
+ scripts/cntstems.pl.
+
+
+
+-O suboptions - Outline processing options. The suboptions
+ may be lowercase or uppercase, the lowercase ones disable the features,
+ the corresponding uppercase suboptions enable the same features.
+ The suboptions to disable/enable features are:
+
+ b/B - Guessing of the ForceBold parameter. This parameter helps
+ the Type1 engine to rasterize the bold fonts properly at small sizes.
+ But the algorithm used to guess the proper value of this flag makes
+ that guess based solely on the font name. In rare cases that may cause
+ errors, in these cases you may want to disable this guessing.
+ Default: enabled
+
+
+
+-p parser_name - Use the specified front-end parser to read the font file.
+ If this option is not used, ttf2pt1 selects the parser automatically based
+ on the suffix of the font file name, it uses the first parser in its
+ list that supports this font type. Now two parsers are supported:
+
+ bdf - built-in parser for the BDF files (suffix .bdf)
+
+ ft - parser based on the FreeType-2 library (suffixes .ttf,
+ .otf, .pfa, .pfb)
+
+ The algorithm that implemented the forced fixed width had major
+ flaws, so it was disabled. The code is still in the program and
+ some day it will be refined and returned back. Meanwhile the
+ option name '-f' was reused for another option. The old version was:
+
+-f - Don't try to force the fixed width of font. Normally the converter
+ considers the fonts in which the glyph width deviates by not more
+ than 5% as buggy fixed width fonts and forces them to have really
+ fixed width. If this is undesirable, it can be disabled by this option.
+
+
+ http://ttf2pt1.sourceforge.net/t1utils.tar.gz
+
+
+
+
+ http://www.lcdf.org/~eddietwo/type/
+
+
+
+ ttf2pt1 -e ttffont.ttf t1font
+
+
+ ttf2pt1 ttffont.ttf - | t1asm >t1font.pfa
+
+Installation and deinstallation of the converter
+
+
+
+The converter may be easily installed systemwide with
+
+
+ make install
+
+
+and uninstalled with
+
+
+ make uninstall
+
+
+By default the Makefile is configured to install in the hierarchy
+of directory /usr/local. This destination directory as well as
+the structure of the hierarchy may be changed by editing the Makefile.
+
+
+Installation of the fonts
+
+
+
+Running the converter manually becomes somewhat boring if it has to
+be applied to a few hundreds of fonts and then you have to generate the
+fonts.scale and/or Fontmap files. The FONTS file describes how to use
+the supplied scripts to handle such cases easily. It also discusses
+the installation of the fonts for a few widespread programs.
+
+Other utilities
+
+
+
+A few other small interesting programs that allow a cloase look at
+the fonts are located in the subdirectory 'other'. They
+are described shortly in others/README.
+
+Optional packages
+
+
+
+Some auxiliary files are not needed by everyone and are big enough that
+moving them to a separate package speeds up the downloads of the main
+package significantly. As of now we have one such optional package:
+
+TO DO:
+
+
+
+
+
+
+
+TROUBLESHOOTING AND BUG REPORTS
+
+
+
+
+
+Have problems with conversion of some font ? The converter dumps core ? Or your
+printer refuses to understand the converted fonts ? Or some characters are
+missing ? Or some characters look strange ?
+
+CONTACTS
+
+
+
+
+
+
+
+
+
+
+
+
+
+ttf2pt1-announce@lists.sourceforge.net
+
+ The mailing list with announcements about ttf2pt1. It is a moderated mailing
+ with extremely low traffic. Everyone is encouraged to subscribe to keep in
+ touch with the current status of project. To subscribe use the Web interface
+ at http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-announce.
+ If you have only e-mail access to the Net then send a subscribe request to
+ the development mailing list ttf2pt1-devel@lists.sourceforge.net and somebody
+ will help you with subscription.
+
+
+ttf2pt1-users@lists.sourceforge.net
+
+ The ttf2pt1 mailing lists for development and users issues. They have not
+ that much traffic either. To subscribe use the Web interface at
+ http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-devel
+ and http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-users.
+ If you have only e-mail access to the Net then send a subscribe request to
+ the development mailing list ttf2pt1-devel@lists.sourceforge.net and somebody
+ will help you with subscription.
+
+ Mark Heath
+
+ Andrew Weeks
+
+
+sab123@hotmail.com
+
+
+http://members.bellatlantic.net/~babkin
+
+ Sergey Babkin
+
+SEE ALSO
+
+
+
+
+
+
+http://ttf2pt1.sourceforge.net
+
+ The main page of the project.
+
+ The old main page of the project.
+
+ Precompiled binaries for Windows.
+
+ The home page of the Type 1 utilities package.
+
+ The first book about PostScript on the Web, "Thinking in PostScript".
+
+ The True Type reference manual.
+
+ Adobe PostScript reference manual.
+
+ Specification of the Type 1 font format.
+
+ The Type 1 font format supplement.
+
+ Specification of the Adobe font metrics file format.
+
+
+http://www.cs.wpi.edu/~matt/courses/cs563/talks/curves.html
+
+ Information about the Bezier curves.
+
+ A stand-alone library supporting the Type1 fonts. Is neccessary
+ to compile the programs other/cmpf and other/dmpf.
+
+ A library supporting the TTF fonts. Also many useful TTF programs
+ are included with it.
+
+ Moses Gold's collection of links to printing software.
+
+ Collection of font-related links.
+
+
+
+
+Following is the Readme of ttf2pfa (true type to type 3 font converter) It
+covers other issues regarding the use of this software. Please note that
+although ttf2pfa is a public domain software, ttf2pt1
+is instead covered by an Open Source license. See the COPYRIGHT
+file for details.
+
+
+
+
+True Type to Postscript Font converter
+
+
+
+My mind is still reeling from the discovery that I was able to write
+this program. What it does is it reads a Microsoft TrueType font and
+creates a Postscript font. '_A_ postscript font', that is, not necessarily
+the same font, you understand, but a fair imitation.
+
+ ttf2pfa fontfile.ttf fontname
+
+
+Copyright issues
+
+
+
+I am putting this program into the public domain, so don't bother
+sending me any money, I'd only have to declare it for income tax.
+
+About the Program
+
+
+
+It was written in C on a IBM PC running Linux.
+
+Problems that may occur
+
+
+
+Most seriously, very complex characters (with lots of outline segments)
+can make Ghostscript releases 2.x.x fail with a 'limitcheck' error. It
+is possible that this may happen with some older Postscript printers as
+well. Such characters will be flagged by the program and there are
+basically two things you can do. First is to edit the .pfa file to
+simplify or remove the offending character. This is not really
+recommended. The second is to use Ghostscript release 3, if you can get
+it. This has much larger limits and does not seem to have any problems
+with complex characters.
+
+Encodings
+
+
+
+A postscript font must have a 256 element array, called an encoding,
+each element of which is a name, which is also the name of a procedure
+contained within the font. The 'BuildChar' command takes a byte and uses
+it to index the encoding array to find a character name, and then looks
+that up in the font's procedure table find the commands to draw the
+glyph. However, not all characters need be in the encoding array. Those
+that are not cannot be drawn (at least not using 'show'), however it is
+possible to 're-encode' the font to enable these characters. There are
+several standard encodings: Adobe's original, ISO-Latin1 and Symbol
+being the most commonly encountered.
+
+ 2) that more than one glyph is given the same Postscript name.
+
+Scripts to support CJK-LaTeX
+
+
+by Mike Fabian
+<mfabian@suse.de>
+
+ cjk-latex-config --type1
+
+this script will use ttf2pt1 to generate .pfb files as well from these TrueType
+fonts to be used with CJK-LaTeX.
+
+ cyberb00 BitstreamCyberbit-Roman-00 <cyberb00.pfb
+
+ cyberb01 BitstreamCyberbit-Roman-01 <cyberb01.pfb
+
+ cyberb02 BitstreamCyberbit-Roman-02 <cyberb02.pfb
+
+ [...]
+
+after all .pfb files have been generated.
+
+Recommended patches for the X11 font library
+
+
+by Sergey Babkin
+<babkin@bellatlantic.net>, <sab123@hotmail.com>
+
+
+ xc/lib/font/Type1
+
+
+of the X11 source tree and after that the font library,
+font server and X server should be rebuilt.
+
+Installing the fonts in Netscape Navigator
+
+
+
+by Sergey Babkin
+<babkin@bellatlantic.net>, <sab123@hotmail.com>
+
+
+ Makefile
+
+ nsfix.c
+ psfonts.cf
+
+ nsfilter
+
+ nsprint
+ psfonts.cf
+
+ notscape
+
+ fontsz.cf
+
+prop-koi8-r 150
+
+
+ nspr
+
+
+by Zvezdan Petkovic
+
+<babkin@bellatlantic.net> or <sab123@hotmail.com>
+
+The Translation Tables
+
+
+
+These translation tables are used to translate the Type 1 fonts between
+different encodings of the same language.
+
+Examples
+
+
+
+The directory `russian' contains the tables for some encodings of the
+Russian language: KOI-8, IBM CP-866, IBM CP-1251 and just for fun
+ISO-8859/5 (nobody uses it anyways). The tables describe both russian
+letters and table graphics characters (except for CP-1251 for which
+the table graphics is not defined, so the table graphics portion for
+it is just copied from KOI-8).
+