From cb012ea47c70197f4fe8f86e633b321eec475b82 Mon Sep 17 00:00:00 2001 From: "Matteo Nastasi (mop)" Date: Thu, 8 Mar 2012 23:17:52 +0100 Subject: [PATCH 1/8] layers management added --- REQUIREMENTS | 1 + get-layerselect-list.gvp | 57 +++++++++++++++++ syntax.php | 128 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 REQUIREMENTS create mode 100644 get-layerselect-list.gvp diff --git a/REQUIREMENTS b/REQUIREMENTS new file mode 100644 index 0000000..188b5b5 --- /dev/null +++ b/REQUIREMENTS @@ -0,0 +1 @@ +graphviz version 2.29.0 (20120228.2305) or greater is required diff --git a/get-layerselect-list.gvp b/get-layerselect-list.gvp new file mode 100644 index 0000000..2cd3095 --- /dev/null +++ b/get-layerselect-list.gvp @@ -0,0 +1,57 @@ +BEG_G { + char* layerlistdelims, layersep, larr[int], outsep="", selisarr[int], selarr[int], selarrtmp[int]; + int i, ct = 0, into; + + if (!isAttr($, "G", "layers")) + return; + + if (isAttr($, "G", "layersep")) + layersep = aget($,layersep); + else + layersep = " :\t"; + + if (isAttr($,"G","layerlistdelims")) + layerlistdelims = aget($,layerlistdelims); + else + layerlistdelims = ","; + + tokens($.layers, larr, layersep); + + if (isAttr($, "G", "layerselect")) { + tokens($.layerselect, selisarr, layerlistdelims); + for (selisarr[i]) { + unset(selarrtmp); + tokens(selisarr[i], selarrtmp, layersep); + if (#selarrtmp == 0) { + continue; + } + else if (#selarrtmp == 1) { + selarr[ct++] = selisarr[i]; + } + else if (#selarrtmp == 2) { + into = 0; + for (larr[i]) { + if (larr[i] == selarrtmp[0]) + into = 1; + if (into == 1) + selarr[ct++] = larr[i]; + if (larr[i] == selarrtmp[1]) { + into = 0; + break; + } + } + } + else { + exit(1); + } + } + for (selarr[i]) { + printf("%s\n", selarr[i]); + } + } + else { + for (larr[i]) { + printf("%s\n", larr[i]); + } + } +} diff --git a/syntax.php b/syntax.php index 518d027..47f4f15 100644 --- a/syntax.php +++ b/syntax.php @@ -74,7 +74,6 @@ function handle($match, $state, $pos, &$handler) { if(preg_match('/\bwidth=([0-9]+)\b/i', $conf,$match)) $return['width'] = $match[1]; if(preg_match('/\bheight=([0-9]+)\b/i', $conf,$match)) $return['height'] = $match[1]; - $input = join("\n",$lines); $return['md5'] = md5($input); // we only pass a hash around @@ -91,14 +90,119 @@ function _cachename($data,$ext){ unset($data['width']); unset($data['height']); unset($data['align']); + unset($data['layer_n']); + unset($data['layer_cur']); + return getcachename(join('x',array_values($data)),'.graphviz.'.$ext); } /** * Create output */ + /* -- code example -- +
+ +
+ + + + +I need: the height and the width of the image to dimension the external div tag + */ + function _render_layered_xhtml($format, &$R, $data, $layers, $in) { + $prefix = basename($in, ".graphviz.txt"); + $gvpath = dirname($this->getConf('path')); + + /* get selected layers */ + unset($out); + exec(sprintf("%s/gvpr -f %s %s", escapeshellarg($gvpath), + escapeshellarg(DOKU_PLUGIN.'graphviz/get-layerselect-list.gvp'), + escapeshellarg($in)), $out, $retval); + $selayers = $out; + + /* FIXME: if dimension is explicitly added use it instead of calculated */ + + /* get image dimensions */ + $cache = $this->_imgfile($data); + unset($out); + exec(sprintf("identify -format '%%Wx%%H' %s", $cache), $out, $retval); + $size = explode("x", $out[0]); + + $width = ($data['width'] > 0 ? $data['width'] : $size[0]); + $height = ($data['height'] > 0 ? $data['height'] : $size[1]); + $R->doc .= sprintf('
+ +
'."\n", + $data['align'], $width, ($data['align'] == '' ? '' : "align: ".$data['align']."; "), + $width, $height); + $img = DOKU_BASE.'lib/plugins/graphviz/img.php?'.buildURLparams($data); + // $in = $this->_cachename($data,'txt'); + /* + $R->doc .= 'doc .= 'doc .= ' width="'.$data['width'].'"'; + if($data['height']) $R->doc .= ' height="'.$data['height'].'"'; + if($data['align'] == 'right') $R->doc .= ' align="right"'; + if($data['align'] == 'left') $R->doc .= ' align="left"'; + $R->doc .= '/>'; + */ + $layers_n = count($layers); + $data['layer_n'] = $layers_n; + for ($i = $layers_n - 1 ; $i >= 0 ; $i--) { + $force_view = ($i == ($layers_n - 1) ? TRUE : FALSE); + $data['layer_cur'] = $i; + $img = DOKU_BASE.'lib/plugins/graphviz/img.php?'.buildURLparams($data); + $R->doc .= sprintf(''."\n", + $prefix, $i, + (array_search($layers[$i], $selayers) === FALSE && !$force_view ? "hidden" : "visible"), $img); + } + $R->doc .= sprintf('
'); + for ($i = 0 ; $i < $layers_n ; $i++) { + if ($i == ($layers_n - 1) && $layers[$i] == '_background_') + continue; + $R->doc .= sprintf('%s %s '."\n", + ($i > 0 ? ": " : ""), (array_search($layers[$i], $selayers) === FALSE ? "" : " checked"), + $prefix, $i, htmlentities($layers[$i])); + } + + $R->doc .= sprintf('
'); + return true; + } + function render($format, &$R, $data) { if($format == 'xhtml'){ + $in = $this->_cachename($data,'txt'); + $gvpath = dirname($this->getConf('path')); + $script = 'BEG_G { char* larr[int]; int i; if (!isAttr($,"G","layers")) return; if (isAttr($,"G","layersep")) tokens($.layers,larr,$.layersep); else tokens($.layers,larr," :\t"); for (larr[i]) { printf("%s\n",larr[i]); } }'; + exec(sprintf("%s/gvpr %s %s", escapeshellarg($gvpath), escapeshellarg($script), escapeshellarg($in)), + $out, $retval); + if ($out[0] != "") { + return $this->_render_layered_xhtml($format, &$R, $data, $out, $in); + } + $cache = $this->_imgfile($data); + $req = sprintf("identify -format '%%Wx%%H' %s", $cache); + exec($req, $out, $retval); + + $size = explode("x", $out[0]); + $img = DOKU_BASE.'lib/plugins/graphviz/img.php?'.buildURLparams($data); $R->doc .= 'doc .= ' width="'.$data['width'].'"'; @@ -119,11 +223,21 @@ function render($format, &$R, $data) { * Return path to the rendered image on our local system */ function _imgfile($data){ - $cache = $this->_cachename($data,'png'); + $txt_data = $data; + unset($txt_data['layer_n']); + unset($txt_data['layer_cur']); + + if (isset($data['layer_n']) && isset($data['layer_cur']) && + $data['layer_cur'] >= 0 && $data['layer_cur'] < $data['layer_n']) { + $cache = $this->_cachename($data,sprintf("%d.png", $data['layer_cur'])); + } + else { + $cache = $this->_cachename($data,'png'); + } // create the file if needed if(!file_exists($cache)){ - $in = $this->_cachename($data,'txt'); + $in = $this->_cachename($txt_data,'txt'); if($this->getConf('path')){ $ok = $this->_run($data,$in,$cache); }else{ @@ -182,6 +296,14 @@ function _run($data,$in,$out) { } $cmd = $this->getConf('path'); + if (isset($data['layer_n']) && isset($data['layer_cur'])) { + $gvpath = dirname($this->getConf('path')); + $script = 'BEG_G { char* larr[int]; int i; if (!isAttr($,"G","layers")) return; if (isAttr($,"G","layersep")) tokens($.layers,larr,$.layersep); else tokens($.layers,larr," :\t"); for (larr[i]) { printf("%s\n",larr[i]); } }'; + exec(sprintf("%s/gvpr %s %s", escapeshellarg($gvpath), escapeshellarg($script), escapeshellarg($in)), + $exout, $retval); + $cmd .= sprintf(" '-Glayerselect=%s'%s", $exout[$data['layer_cur']], ((int)$data['layer_cur'] < (int)$data['layer_n'] - 1 ? ' -Gbgcolor=#00000000' : '')); + } + $cmd .= ' -Tpng'; $cmd .= ' -K'.$data['layout']; $cmd .= ' -o'.escapeshellarg($out); //output From 5f411003d58b8c3674a1f8cfafe0372fd22a642f Mon Sep 17 00:00:00 2001 From: "Matteo Nastasi (mop)" Date: Thu, 8 Mar 2012 23:18:57 +0100 Subject: [PATCH 2/8] dpi attribute management added --- syntax.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/syntax.php b/syntax.php index 47f4f15..d0e4a7f 100644 --- a/syntax.php +++ b/syntax.php @@ -50,6 +50,7 @@ function handle($match, $state, $pos, &$handler) { // prepare default data $return = array( + 'dpi' => 0, 'width' => 0, 'height' => 0, 'layout' => 'dot', @@ -74,6 +75,8 @@ function handle($match, $state, $pos, &$handler) { if(preg_match('/\bwidth=([0-9]+)\b/i', $conf,$match)) $return['width'] = $match[1]; if(preg_match('/\bheight=([0-9]+)\b/i', $conf,$match)) $return['height'] = $match[1]; + if(preg_match('/\bdpi=([0-9]+)\b/i', $conf,$match)) $return['dpi'] = $match[1]; + $input = join("\n",$lines); $return['md5'] = md5($input); // we only pass a hash around @@ -308,6 +311,10 @@ function _run($data,$in,$out) { $cmd .= ' -K'.$data['layout']; $cmd .= ' -o'.escapeshellarg($out); //output $cmd .= ' '.escapeshellarg($in); //input + if (isset($data['dpi']) && $data['dpi'] > 0) { + $cmd .= sprintf(" -Gdpi=%d", $data['dpi']); + } + exec($cmd, $output, $error); From 65f5a43f9f127c4a400f5ed90747a5f3d7e1bd7c Mon Sep 17 00:00:00 2001 From: "Matteo Nastasi (mop)" Date: Sat, 10 Mar 2012 16:28:48 +0100 Subject: [PATCH 3/8] dpi array element moved at the bottom of assigments --- syntax.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syntax.php b/syntax.php index d0e4a7f..e02c82b 100644 --- a/syntax.php +++ b/syntax.php @@ -50,11 +50,11 @@ function handle($match, $state, $pos, &$handler) { // prepare default data $return = array( - 'dpi' => 0, 'width' => 0, 'height' => 0, 'layout' => 'dot', 'align' => '', + 'dpi' => 0, 'version' => $info['date'], //force rebuild of images on update ); From 4b75756e2c12887d7a945d005317012639f4c9c2 Mon Sep 17 00:00:00 2001 From: "Matteo Nastasi (mop)" Date: Sun, 11 Mar 2012 10:36:35 +0100 Subject: [PATCH 4/8] use php function getimagesize instead of identify program call --- syntax.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/syntax.php b/syntax.php index e02c82b..f9ad3e2 100644 --- a/syntax.php +++ b/syntax.php @@ -136,9 +136,7 @@ function _render_layered_xhtml($format, &$R, $data, $layers, $in) { /* get image dimensions */ $cache = $this->_imgfile($data); - unset($out); - exec(sprintf("identify -format '%%Wx%%H' %s", $cache), $out, $retval); - $size = explode("x", $out[0]); + $size = getimagesize($cache); $width = ($data['width'] > 0 ? $data['width'] : $size[0]); $height = ($data['height'] > 0 ? $data['height'] : $size[1]); @@ -201,10 +199,7 @@ function render($format, &$R, $data) { return $this->_render_layered_xhtml($format, &$R, $data, $out, $in); } $cache = $this->_imgfile($data); - $req = sprintf("identify -format '%%Wx%%H' %s", $cache); - exec($req, $out, $retval); - - $size = explode("x", $out[0]); + $size = getimagesize($cache); $img = DOKU_BASE.'lib/plugins/graphviz/img.php?'.buildURLparams($data); $R->doc .= ' Date: Sun, 11 Mar 2012 10:37:33 +0100 Subject: [PATCH 5/8] add author reference --- syntax.php | 1 + 1 file changed, 1 insertion(+) diff --git a/syntax.php b/syntax.php index f9ad3e2..b8840a1 100644 --- a/syntax.php +++ b/syntax.php @@ -3,6 +3,7 @@ * graphviz-Plugin: Parses graphviz-blocks * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Matteo Nastasi * @author Carl-Christian Salvesen * @author Andreas Gohr */ From 605a61da0d4459af3d66a5756367f4d679a04a6f Mon Sep 17 00:00:00 2001 From: "Matteo Nastasi (mop)" Date: Sun, 11 Mar 2012 11:04:55 +0100 Subject: [PATCH 6/8] splicespace mode added to show layers as a stack --- syntax.php | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/syntax.php b/syntax.php index b8840a1..2132a4e 100644 --- a/syntax.php +++ b/syntax.php @@ -56,6 +56,7 @@ function handle($match, $state, $pos, &$handler) { 'layout' => 'dot', 'align' => '', 'dpi' => 0, + 'slicespace'=> 0, 'version' => $info['date'], //force rebuild of images on update ); @@ -77,6 +78,8 @@ function handle($match, $state, $pos, &$handler) { if(preg_match('/\bheight=([0-9]+)\b/i', $conf,$match)) $return['height'] = $match[1]; if(preg_match('/\bdpi=([0-9]+)\b/i', $conf,$match)) $return['dpi'] = $match[1]; + if(in_array ('imagick', get_loaded_extensions()) && + preg_match('/\bslicespace=([0-9]+)\b/i', $conf,$match)) $return['slicespace'] = $match[1]; $input = join("\n",$lines); $return['md5'] = md5($input); // we only pass a hash around @@ -126,6 +129,9 @@ function _render_layered_xhtml($format, &$R, $data, $layers, $in) { $prefix = basename($in, ".graphviz.txt"); $gvpath = dirname($this->getConf('path')); + $layers_n = count($layers); + $data['layer_n'] = $layers_n; + /* get selected layers */ unset($out); exec(sprintf("%s/gvpr -f %s %s", escapeshellarg($gvpath), @@ -141,7 +147,7 @@ function _render_layered_xhtml($format, &$R, $data, $layers, $in) { $width = ($data['width'] > 0 ? $data['width'] : $size[0]); $height = ($data['height'] > 0 ? $data['height'] : $size[1]); - $R->doc .= sprintf('
+ $R->doc .= sprintf('
'."\n", $data['align'], $width, ($data['align'] == '' ? '' : "align: ".$data['align']."; "), - $width, $height); + $width, $height + (isset($data['slicespace']) && $data['slicespace'] > 0 ? $data['slicespace'] * ($layers_n - 1) : 0)); $img = DOKU_BASE.'lib/plugins/graphviz/img.php?'.buildURLparams($data); // $in = $this->_cachename($data,'txt'); /* @@ -166,15 +172,15 @@ function showhide(obj) if($data['align'] == 'left') $R->doc .= ' align="left"'; $R->doc .= '/>'; */ - $layers_n = count($layers); - $data['layer_n'] = $layers_n; for ($i = $layers_n - 1 ; $i >= 0 ; $i--) { $force_view = ($i == ($layers_n - 1) ? TRUE : FALSE); $data['layer_cur'] = $i; $img = DOKU_BASE.'lib/plugins/graphviz/img.php?'.buildURLparams($data); - $R->doc .= sprintf(''."\n", + $R->doc .= sprintf(''."\n", $prefix, $i, - (array_search($layers[$i], $selayers) === FALSE && !$force_view ? "hidden" : "visible"), $img); + (array_search($layers[$i], $selayers) === FALSE && !$force_view ? "hidden" : "visible"), + (isset($data['slicespace']) && $data['slicespace'] > 0 ? $data['slicespace'] * $i : 0), + $img); } $R->doc .= sprintf('
'); for ($i = 0 ; $i < $layers_n ; $i++) { @@ -311,9 +317,28 @@ function _run($data,$in,$out) { $cmd .= sprintf(" -Gdpi=%d", $data['dpi']); } - exec($cmd, $output, $error); + if (isset($data['slicespace']) && $data['slicespace'] > 0) { + $image = new Imagick($out); + $trans = new ImagickPixel('transparent'); + $imageprops = $image->getImageGeometry(); + $w = $imageprops['width']; + $h = $imageprops['height']; + + $draw = new ImagickDraw(); + $draw->setFillColor($trans); // Set up some colors to use for fill and outline + $draw->setStrokeColor( new ImagickPixel( 'rgb(40,40,40)' ) ); + $draw->rectangle( 0, 0, $w-1, $h-1 ); // Draw the rectangle + $image->drawImage( $draw ); + $image->resizeImage( $w*2, $h, imagick::FILTER_LANCZOS, 1.0); + $image->shearImage($trans, 45 , 0); + $imageprops = $image->getImageGeometry(); + $w = $imageprops['width']; + $image->resizeImage( $w/2, $h/2, imagick::FILTER_LANCZOS, 1.0); + $image->writeImage($out); + } + if ($error != 0){ if($conf['debug']){ dbglog(join("\n",$output),'graphviz command failed: '.$cmd); From 0eefe214dd009f1e4390b86465f998aa6747134f Mon Sep 17 00:00:00 2001 From: Matteo Nastasi Date: Sun, 8 Apr 2012 12:56:17 +0200 Subject: [PATCH 7/8] revert order of layers --- syntax.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/syntax.php b/syntax.php index 2132a4e..a4f2e87 100644 --- a/syntax.php +++ b/syntax.php @@ -172,23 +172,25 @@ function showhide(obj) if($data['align'] == 'left') $R->doc .= ' align="left"'; $R->doc .= '/>'; */ - for ($i = $layers_n - 1 ; $i >= 0 ; $i--) { - $force_view = ($i == ($layers_n - 1) ? TRUE : FALSE); + for ($i = 0 ; $i < $layers_n ; $i++) { + $force_view = ($i == 0 ? TRUE : FALSE); $data['layer_cur'] = $i; $img = DOKU_BASE.'lib/plugins/graphviz/img.php?'.buildURLparams($data); $R->doc .= sprintf(''."\n", $prefix, $i, (array_search($layers[$i], $selayers) === FALSE && !$force_view ? "hidden" : "visible"), - (isset($data['slicespace']) && $data['slicespace'] > 0 ? $data['slicespace'] * $i : 0), + (isset($data['slicespace']) && $data['slicespace'] > 0 ? $data['slicespace'] * ($layers_n - $i -1) : 0), $img); } $R->doc .= sprintf('
'); - for ($i = 0 ; $i < $layers_n ; $i++) { - if ($i == ($layers_n - 1) && $layers[$i] == '_background_') + for ($first = true, $i = $layers_n - 1 ; $i >= 0 ; $i--) { + // for ($i = 0, $first = true ; $i < $layers_n ; $i++) { + if ($i == 0 && $layers[$i] == '_background_') continue; $R->doc .= sprintf('%s %s '."\n", - ($i > 0 ? ": " : ""), (array_search($layers[$i], $selayers) === FALSE ? "" : " checked"), + ($first != true ? ": " : ""), (array_search($layers[$i], $selayers) === FALSE ? "" : " checked"), $prefix, $i, htmlentities($layers[$i])); + $first = false; } $R->doc .= sprintf('
'); @@ -306,7 +308,7 @@ function _run($data,$in,$out) { $script = 'BEG_G { char* larr[int]; int i; if (!isAttr($,"G","layers")) return; if (isAttr($,"G","layersep")) tokens($.layers,larr,$.layersep); else tokens($.layers,larr," :\t"); for (larr[i]) { printf("%s\n",larr[i]); } }'; exec(sprintf("%s/gvpr %s %s", escapeshellarg($gvpath), escapeshellarg($script), escapeshellarg($in)), $exout, $retval); - $cmd .= sprintf(" '-Glayerselect=%s'%s", $exout[$data['layer_cur']], ((int)$data['layer_cur'] < (int)$data['layer_n'] - 1 ? ' -Gbgcolor=#00000000' : '')); + $cmd .= sprintf(" '-Glayerselect=%s'%s", $exout[$data['layer_cur']], ((int)$data['layer_cur'] > 0 ? ' -Gbgcolor=#00000000' : '')); } $cmd .= ' -Tpng'; From ec7bdf301608c77f4d8569e5bec7e4adebe75ad8 Mon Sep 17 00:00:00 2001 From: Matteo Nastasi Date: Sun, 8 Apr 2012 13:14:22 +0200 Subject: [PATCH 8/8] standard error redirect to dev/null to prevent annoing log on apache --- syntax.php | 1 + 1 file changed, 1 insertion(+) diff --git a/syntax.php b/syntax.php index a4f2e87..7398a9b 100644 --- a/syntax.php +++ b/syntax.php @@ -318,6 +318,7 @@ function _run($data,$in,$out) { if (isset($data['dpi']) && $data['dpi'] > 0) { $cmd .= sprintf(" -Gdpi=%d", $data['dpi']); } + $cmd .= ' 2>/dev/null'; exec($cmd, $output, $error);