1<?php 2/** 3 * Plugin svgpureInsert: Inserts a non png or other modified svg file, just its pure version 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Andreas Gohr <gohr@cosmocode.de> 7 */ 8 9if(!defined('DOKU_INC')) exit; 10if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/'); 11 12class helper_plugin_svgpureinsert extends DokuWiki_Plugin { 13 14 /** 15 * Gets a local scalable copy of the SVG with its dimensions 16 * 17 * @param $id 18 * @param int $cachetime 19 * @return bool|array either array($file, $width, $height) or false if no cache available 20 */ 21 public function getAdjustedSVG($id, $cachetime = -1) { 22 $info = $this->getInfo(); 23 $cachefile = getCacheName($id . $info['date'], '.svg'); 24 $cachedate = @filemtime($cachefile); 25 if($cachedate && $cachetime < (time() - $cachedate)) { 26 list($width, $height) = $this->readSVGsize($cachefile); 27 return array($cachefile, $width, $height); 28 } 29 30 // still here, create a new cache file 31 if(preg_match('/^https?:\/\//i', $id)) { 32 io_download($id, $cachefile); #FIXME make max size configurable 33 } else { 34 @copy(mediaFN($id), $cachefile); 35 } 36 clearstatcache(false, $cachefile); 37 38 // adjust the size in the cache file 39 if(file_exists($cachefile)){ 40 list($width, $height) = $this->readSVGsize($cachefile, true); 41 return array($cachefile, $width, $height); 42 } 43 44 return false; 45 } 46 47 48 /** 49 * Parse te given XML attributes into an array 50 * 51 * @author troelskn 52 * @link http://stackoverflow.com/a/1083821/172068 53 * @param $input 54 * @return array 55 */ 56 public function parseAttributes($input) { 57 $dom = new DomDocument(); 58 $dom->loadHtml("<html $input />"); 59 $attributes = array(); 60 foreach($dom->documentElement->attributes as $name => $attr) { 61 $attributes[$name] = $attr->value; 62 } 63 return $attributes; 64 } 65 66 /** 67 * Calculates pixel size for any given SVG size 68 * 69 * @param $value 70 * @return int 71 */ 72 public function convertToPixel($value) { 73 if(!preg_match('/^(\d+?(\.\d*)?)(in|em|ex|px|pt|pc|cm|mm)?$/', $value, $m)) return 0; 74 75 $digit = (double) $m[1]; 76 $unit = (string) $m[3]; 77 78 $dpi = 72; 79 $conversions = array( 80 'in' => $dpi, 81 'em' => 16, 82 'ex' => 12, 83 'px' => 1, 84 'pt' => $dpi / 72, # 1/27 of an inch 85 'pc' => $dpi / 6, # 1/6 of an inch 86 'cm' => $dpi / 2.54, # inch to cm 87 'mm' => $dpi / (2.54 * 10), # inch to cm, 88 ); 89 90 if(isset($conversions[$unit])) { 91 $digit = $digit * (float) $conversions[$unit]; 92 } 93 94 return ceil($digit); 95 } 96 97 /** 98 * Read the Size of an SVG from its contents 99 * 100 * @param string $file local SVG file (or part of it) 101 * @param bool $fix should the file's size attributes be fixed as well? 102 * @return array 103 */ 104 public function readSVGsize($file, $fix = false) { 105 $default = array(100, 100); 106 107 $data = io_readFile($file, false); 108 if(!$data) return $default; 109 if(!preg_match('/<svg([^>]*)>/s', $data, $m)) return $default; 110 $attributes = $this->parseAttributes($m[1]); 111 112 $width = $attributes['width']; 113 $height = $attributes['height']; 114 115 if(substr($width, -1, 1) == '%' || substr($height, -1, 1) == '%') { 116 // dimensions are in percent, try viewBox instead 117 list(, , $width, $height) = explode(' ', $attributes['viewbox']); 118 } 119 120 // fix units 121 $width = $this->convertToPixel($width); 122 $height = $this->convertToPixel($height); 123 124 // if calculation failed use default 125 if(!$width) $width = $default[0]; 126 if(!$height) $height = $default[0]; 127 128 // fix the SVG to be autoscaling 129 if($fix) { 130 if(isset($attributes['viewbox'])) unset($attributes['viewbox']); 131 if(isset($attributes['preserveaspectratio'])) unset($attributes['preserveaspectratio']); 132 133 $attributes['width'] = '100%'; 134 $attributes['height'] = '100%'; 135 $attributes['viewBox'] = "0 0 $width $height"; 136 $attributes['preserveAspectRatio'] = 'xMidYMid slice'; 137 138 $svg = '<svg ' . buildAttributes($attributes) . '>'; 139 $data = preg_replace('/<svg([^>]*)>/s', $svg, $data, 1); 140 io_saveFile($file, $data); 141 } 142 143 return array( 144 $width, 145 $height 146 ); 147 } 148 149}