1<?php
2/**
3 * Plugin SVG: Converts inline SVG images
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Christopher Smith <chris@jalakai.co.uk>
7 */
8
9if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
10if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
11require_once(DOKU_PLUGIN.'syntax.php');
12
13/**
14 * Include an external file to reduce some clutter and define some
15 * functions.
16 */
17require_once(DOKU_PLUGIN.'svg/header.php');
18
19/**
20 * All DokuWiki plugins to extend the parser/rendering mechanism
21 * need to inherit from this class
22 */
23class syntax_plugin_svg extends DokuWiki_Syntax_Plugin {
24
25 	var $xml_data;
26
27    function getInfo(){
28        return array(
29            'author' => 'Austen Dicken',
30            'email'  => 'admin@cvpcs.org',
31            'date'   => '2007-05-16',
32            'name'   => 'DokuWiki SVG Plugin',
33            'desc'   => 'Supplies a way to render SVG images inline within a document.',
34            'url'    => 'http://www.cvpcs.org/dokuwiki/lib/exe/fetch.php?id=project%3Adokuwiki-svg&cache=cache&media=project:dokuwiki-svg.tar.gz',
35        );
36    }
37
38    function getType(){
39        return 'protected';
40    }
41
42    function getSort(){
43        return 999;
44    }
45
46    function connectTo($mode) {
47        $this->Lexer->addEntryPattern('<svgimage>',$mode,'plugin_svg');
48    }
49
50    function postConnect() {
51        $this->Lexer->addExitPattern('</svgimage>','plugin_svg');
52    }
53
54    function handle($match, $state, $pos, &$handler){
55        switch ($state) {
56          case DOKU_LEXER_ENTER :
57            break;
58          case DOKU_LEXER_MATCHED :
59            break;
60          case DOKU_LEXER_UNMATCHED :
61            break;
62          case DOKU_LEXER_EXIT :
63            break;
64          case DOKU_LEXER_SPECIAL :
65            break;
66        }
67        return array( $state, $match );
68    }
69
70    function render($mode, &$renderer, $data) {
71    	  global $syntax_plugin_svg_pcount;
72        if($mode == 'xhtml'){
73            list( $state, $match ) = $data;
74            switch( $state )
75            {
76            case DOKU_LEXER_ENTER :
77            	$this->xml_data = '';
78            	break;
79            case DOKU_LEXER_EXIT :
80            	if( $syntax_plugin_svg_pcount == 0 )
81            	{
82            		$this->clearImages();
83            	}
84            	$this->save();
85            	$this->renderSVG( $renderer );
86            	$syntax_plugin_svg_pcount++;
87            	break;
88            default:
89            	$this->xml_data .= $match;
90            	break;
91            }
92            return true;
93        }
94        return false;
95    }
96
97    function clearImages()
98    {
99  		foreach( glob(
100  			SYNTAX_PLUGIN_SVG_MEDIADIR .
101  			'media/' .
102  			md5( getID() ) .
103  			'*'
104  			) as $filename )
105  		{
106  			unlink( $filename );
107  		}
108    }
109
110    function save()
111    {
112    	global $syntax_plugin_svg_pcount;
113
114    	$this->xml_data = ltrim( $this->xml_data );
115
116	$filename = md5( getID() ) . $syntax_plugin_svg_pcount . '.svg';
117
118    	switch( $this->getConf( 'output' ) )
119    	{
120    	case 'imagick':
121    		if( extension_loaded( 'imagick' ) )
122    		{
123			$ih = new Imagick();
124			$ih->readImageBlob( $this->xml_data );
125			$ih->setImageFormat( $this->getConf( 'im_format' ) );
126			$ih->writeImage(
127				SYNTAX_PLUGIN_SVG_MEDIADIR .
128					'media/' .
129					substr( $filename, 0, -3 ) .
130					strtolower( $this->getConf( 'im_format' ) )
131				);
132			$ih->destroy();
133    			break;
134    		}
135    	case 'magickwand':
136    		if( extension_loaded( 'magickwand' ) )
137    		{
138	    		$mwh = NewMagickWand();
139	    		MagickReadImageBlob( $mwh, $this->xml_data );
140	    		MagickSetFormat( $mwh, $this->getConf( 'mw_format' ) );
141	    		MagickPaintTransparentImage( $mwh, NewPixelWand( '#FFFFFF' ) );
142	    		MagickWriteImage(
143	    			$mwh,
144	    			SYNTAX_PLUGIN_SVG_MEDIADIR .
145	    				'media/' .
146	    				substr( $filename, 0, -3 ) .
147	    				strtolower( $this->getConf( 'mw_format' ) )
148	    			);
149	    		DestroyMagickWand( $mwh );
150    			break;
151    		}
152    	case 'embed':
153    	case 'object':
154    	case 'iframe':
155    		$fh = fopen( SYNTAX_PLUGIN_SVG_MEDIADIR . 'media/' . $filename, 'w' );
156    		fwrite( $fh, $this->xml_data );
157    		fclose( $fh );
158    		break;
159    	}
160    }
161
162    function renderSVG( &$renderer )
163    {
164    	global $syntax_plugin_svg_pcount;
165
166    	$svgp = new syntax_plugin_svg_parser();
167    	$svgp->parse( $this->xml_data );
168
169    	switch( $this->getConf( 'output' ) )
170    	{
171    	case 'imagick':
172    		if( extension_loaded( 'imagick' ) )
173    		{
174    			$renderer->doc .= '<img src="'
175    								.  getBaseURL( true )
176    								.  'data/svg/media/'
177    								.  md5( getID() ) . $syntax_plugin_svg_pcount
178    								.  '.' . strtolower( $this->getConf( 'im_format' ) )
179    								.  '" width="'
180    								.  $svgp->width . '" height="'
181    								.  $svgp->height . '" alt="SVGImage'
182    								.  $syntax_plugin_svg_pcount . '" />';
183
184    			break;
185    		}
186    	case 'magickwand':
187    		if( extension_loaded( 'magickwand' ) )
188    		{
189    			$renderer->doc .= '<img src="'
190    								.  getBaseURL( true )
191    								.  'data/svg/media/'
192    								.  md5( getID() ) . $syntax_plugin_svg_pcount
193    								.  '.' . strtolower( $this->getConf( 'mw_format' ) )
194    								.  '" width="'
195    								.  $svgp->width . '" height="'
196    								.  $svgp->height . '" alt="SVGImage'
197    								.  $syntax_plugin_svg_pcount . '" />';
198
199    			break;
200    		}
201    	case 'embed':
202    		$renderer->doc .= '<embed src="'
203    							.  getBaseURL( true )
204    							.  'data/svg/media/'
205    							.  md5( getID() ) . $syntax_plugin_svg_pcount . '.svg" width="'
206    							.  $svgp->width . '" height="'
207    							.  $svgp->height . '" '
208    							.  'type="image/svg+xml" '
209    							.  'pluginspage="http://www.adobe.com/svg/viewwer/install/" />';
210    		break;
211    	case 'object':
212    		$renderer->doc .= '<object data="'
213    							.  getBaseURL( true )
214    							.  'data/svg/media/'
215    							.  md5( getID() ) . $syntax_plugin_svg_pcount . '.svg" width="'
216    							.  $svgp->width . '" height="'
217    							.  $svgp->height . '" '
218    							.  'type="image/svg+xml" '
219    							.  'pluginspage="http://www.adobe.com/svg/viewwer/install/" />';
220    	case 'iframe':
221    		$renderer->doc .= '<iframe style="border: none;" src="'
222    							.  getBaseURL( true )
223    							.  'data/svg/media/'
224    							.  md5( getID() ) . $syntax_plugin_svg_pcount . '.svg" width="'
225    							.  $svgp->width . '" height="'
226    							.  $svgp->height . '" '
227    							.  'type="image/svg+xml"></iframe>';
228    		break;
229    	}
230    }
231}
232
233