11072ee52SAndreas Gohr<?php 21072ee52SAndreas Gohr 31072ee52SAndreas Gohrnamespace dokuwiki\template\sprintdoc; 41072ee52SAndreas Gohr 51072ee52SAndreas Gohrif(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__) . '/../../../'); 61072ee52SAndreas Gohrrequire_once(DOKU_INC . 'inc/init.php'); 71072ee52SAndreas Gohr 81072ee52SAndreas Gohr/** 91072ee52SAndreas Gohr * Custom XML node that allows prepending 101072ee52SAndreas Gohr */ 111072ee52SAndreas Gohrclass SvgNode extends \SimpleXMLElement { 121072ee52SAndreas Gohr /** 131072ee52SAndreas Gohr * @param string $name Name of the new node 141072ee52SAndreas Gohr * @param null|string $value 151072ee52SAndreas Gohr * @return SvgNode 161072ee52SAndreas Gohr */ 171072ee52SAndreas Gohr public function prependChild($name, $value = null) { 181072ee52SAndreas Gohr $dom = dom_import_simplexml($this); 191072ee52SAndreas Gohr 201072ee52SAndreas Gohr $new = $dom->insertBefore( 211072ee52SAndreas Gohr $dom->ownerDocument->createElement($name, $value), 221072ee52SAndreas Gohr $dom->firstChild 231072ee52SAndreas Gohr ); 241072ee52SAndreas Gohr 251072ee52SAndreas Gohr return simplexml_import_dom($new, get_class($this)); 261072ee52SAndreas Gohr } 271072ee52SAndreas Gohr} 281072ee52SAndreas Gohr 291072ee52SAndreas Gohr/** 301072ee52SAndreas Gohr * Manage SVG recoloring 311072ee52SAndreas Gohr */ 321072ee52SAndreas Gohrclass SVG { 331072ee52SAndreas Gohr 341072ee52SAndreas Gohr const IMGDIR = __DIR__ . '/img/'; 351072ee52SAndreas Gohr 361072ee52SAndreas Gohr /** @var SvgNode */ 371072ee52SAndreas Gohr protected $xml; 381072ee52SAndreas Gohr 391072ee52SAndreas Gohr /** 401072ee52SAndreas Gohr * SVG constructor 411072ee52SAndreas Gohr */ 421072ee52SAndreas Gohr public function __construct() { 431072ee52SAndreas Gohr global $INPUT; 441072ee52SAndreas Gohr 451072ee52SAndreas Gohr $svg = cleanID($INPUT->str('svg')); 461072ee52SAndreas Gohr if(blank($svg)) $this->abort(404); 471072ee52SAndreas Gohr 481072ee52SAndreas Gohr // try local file first 491072ee52SAndreas Gohr $file = self::IMGDIR . $svg; 501072ee52SAndreas Gohr if(!file_exists($file)) { 511072ee52SAndreas Gohr // media files are ACL protected 52*3ec07d58SAndreas Gohr if(auth_quickaclcheck($svg) < AUTH_READ) $this->abort(403); 531072ee52SAndreas Gohr $file = mediaFN($svg); 541072ee52SAndreas Gohr } 551072ee52SAndreas Gohr // check if media exists 561072ee52SAndreas Gohr if(!file_exists($file)) $this->abort(404); 571072ee52SAndreas Gohr 581072ee52SAndreas Gohr $this->xml = simplexml_load_file($file, SvgNode::class); 591072ee52SAndreas Gohr } 601072ee52SAndreas Gohr 611072ee52SAndreas Gohr /** 621072ee52SAndreas Gohr * Generate and output 631072ee52SAndreas Gohr */ 641072ee52SAndreas Gohr public function out() { 651072ee52SAndreas Gohr $this->setStyle(); 661072ee52SAndreas Gohr header('image/svg+xml'); 671072ee52SAndreas Gohr echo $this->xml->asXML(); 681072ee52SAndreas Gohr } 691072ee52SAndreas Gohr 701072ee52SAndreas Gohr /** 711072ee52SAndreas Gohr * Generate a style setting from the input variables 721072ee52SAndreas Gohr * 731072ee52SAndreas Gohr * @return string 741072ee52SAndreas Gohr */ 751072ee52SAndreas Gohr protected function makeStyle() { 761072ee52SAndreas Gohr global $INPUT; 771072ee52SAndreas Gohr 781072ee52SAndreas Gohr $element = 'path'; // FIXME configurable? 791072ee52SAndreas Gohr 801072ee52SAndreas Gohr $colors = array( 811072ee52SAndreas Gohr 's' => $this->fixColor($INPUT->str('s')), 821072ee52SAndreas Gohr 'f' => $this->fixColor($INPUT->str('f')), 831072ee52SAndreas Gohr 'sh' => $this->fixColor($INPUT->str('sh')), 841072ee52SAndreas Gohr 'fh' => $this->fixColor($INPUT->str('fh')), 851072ee52SAndreas Gohr ); 861072ee52SAndreas Gohr 871072ee52SAndreas Gohr $style = ''; 881072ee52SAndreas Gohr if($colors['s'] || $colors['f']) { 891072ee52SAndreas Gohr $style .= $element . '{'; 901072ee52SAndreas Gohr if($colors['s']) $style .= 'stroke:' . $colors['s'] . ';'; 911072ee52SAndreas Gohr if($colors['f']) $style .= 'fill:' . $colors['f'] . ';'; 921072ee52SAndreas Gohr $style .= '}'; 931072ee52SAndreas Gohr } 941072ee52SAndreas Gohr 951072ee52SAndreas Gohr if($colors['sh'] || $colors['fh']) { 961072ee52SAndreas Gohr $style .= $element . ':hover{'; 971072ee52SAndreas Gohr if($colors['sh']) $style .= 'stroke:' . $colors['sh'] . ';'; 981072ee52SAndreas Gohr if($colors['fh']) $style .= 'fill:' . $colors['fh'] . ';'; 991072ee52SAndreas Gohr $style .= '}'; 1001072ee52SAndreas Gohr } 1011072ee52SAndreas Gohr 1021072ee52SAndreas Gohr return $style; 1031072ee52SAndreas Gohr } 1041072ee52SAndreas Gohr 1051072ee52SAndreas Gohr /** 1061072ee52SAndreas Gohr * Takes a hexadecimal color string in the following forms: 1071072ee52SAndreas Gohr * 1081072ee52SAndreas Gohr * RGB 1091072ee52SAndreas Gohr * RRGGBB 1101072ee52SAndreas Gohr * RRGGBBAA 1111072ee52SAndreas Gohr * 1121072ee52SAndreas Gohr * Converts it to rgba() form 1131072ee52SAndreas Gohr * 1141072ee52SAndreas Gohr * @param string $color 1151072ee52SAndreas Gohr * @return string 1161072ee52SAndreas Gohr */ 1171072ee52SAndreas Gohr protected function fixColor($color) { 1181072ee52SAndreas Gohr if(preg_match('/^([0-9a-f])([0-9a-f])([0-9a-f])$/i', $color, $m)) { 1191072ee52SAndreas Gohr $r = hexdec($m[1] . $m[1]); 1201072ee52SAndreas Gohr $g = hexdec($m[2] . $m[2]); 1211072ee52SAndreas Gohr $b = hexdec($m[3] . $m[3]); 1221072ee52SAndreas Gohr $a = hexdec('ff'); 1231072ee52SAndreas Gohr } elseif(preg_match('/^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})?$/i', $color, $m)) { 1241072ee52SAndreas Gohr $r = hexdec($m[1]); 1251072ee52SAndreas Gohr $g = hexdec($m[2]); 1261072ee52SAndreas Gohr $b = hexdec($m[3]); 1271072ee52SAndreas Gohr if(isset($m[4])) { 1281072ee52SAndreas Gohr $a = hexdec($m[4]); 1291072ee52SAndreas Gohr } else { 1301072ee52SAndreas Gohr $a = hexdec('ff'); 1311072ee52SAndreas Gohr } 1321072ee52SAndreas Gohr } else { 1331072ee52SAndreas Gohr return ''; 1341072ee52SAndreas Gohr } 1351072ee52SAndreas Gohr 1361072ee52SAndreas Gohr return "rgba($r,$g,$b,$a)"; 1371072ee52SAndreas Gohr } 1381072ee52SAndreas Gohr 1391072ee52SAndreas Gohr /** 1401072ee52SAndreas Gohr * Apply the style to the SVG 1411072ee52SAndreas Gohr */ 1421072ee52SAndreas Gohr protected function setStyle() { 1431072ee52SAndreas Gohr $defs = $this->xml->defs; 1441072ee52SAndreas Gohr if(!$defs) { 1451072ee52SAndreas Gohr $defs = $this->xml->prependChild('defs'); 1461072ee52SAndreas Gohr } 1471072ee52SAndreas Gohr $defs->addChild('style', $this->makeStyle()); 1481072ee52SAndreas Gohr } 1491072ee52SAndreas Gohr 1501072ee52SAndreas Gohr /** 1511072ee52SAndreas Gohr * Abort processing with given status code 1521072ee52SAndreas Gohr * 1531072ee52SAndreas Gohr * @param int $status 1541072ee52SAndreas Gohr */ 1551072ee52SAndreas Gohr protected function abort($status) { 1561072ee52SAndreas Gohr http_status($status); 1571072ee52SAndreas Gohr exit; 1581072ee52SAndreas Gohr } 1591072ee52SAndreas Gohr 1601072ee52SAndreas Gohr} 1611072ee52SAndreas Gohr 1621072ee52SAndreas Gohr// main 1631072ee52SAndreas Gohr$svg = new SVG(); 1641072ee52SAndreas Gohr$svg->out(); 1651072ee52SAndreas Gohr 166