1<?php
2/**
3 * Annotated Image
4 * based on Fotonotes(tm) see http://www.fotonotes.net/
5 *
6 * Syntax:
7 *  {{aimg>media.png?999x999|Title}}
8 *  @top,left,width,height | note title text
9 *  note text line 1
10 *  ...
11 *  note text line 2
12 *  ~author_name
13 *  @...
14 *  ~
15 *  ...
16 *  {{<aimg}}
17 *
18 * Example:
19 * {{aimg> two.jpg?300x300 |Bla}}
20 * @10,10,100,100|title text
21 * ~zumi
22 * @120, 110, 50, 50|title with a [[link]]
23 * a centered image: \\
24 * {{ two.jpg?100x100 }} \\
25 * and a link((footnote)): \\
26 * [[this is a very interesting link]]
27 * ~
28 * {{<aimg}}
29 *
30 * @license    Released under the Open Source License v2.1 or later (due to Fotonotes)
31 * @author     Itay Donenhirsch (itay@bazoo.org)
32 */
33
34if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
35if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
36require_once(DOKU_PLUGIN.'syntax.php');
37
38class syntax_plugin_aimg extends DokuWiki_Syntax_Plugin {
39
40	function syntax_plugin_aimg() {
41		$this->id_seq_num = 0;
42	}
43
44    function getInfo(){
45        return array(
46            'author' => 'Itay Donenhirsch',
47            'email'  => 'itay@bazoo.org',
48            'date'   => '2009-05-05',
49            'name'   => 'Annotated Image Plugin',
50            'desc'   => 'Use FotoNotes to display annotations on images',
51            'url'    => 'http://itay.bazoo.org/projects/aimg',
52        );
53    }
54
55    function getType(){
56        return 'container';
57    }
58
59    function getAllowedTypes() {
60        return array('formatting','substition','disabled','protected','container','paragraphs');
61    }
62
63	function getPType() {
64		return 'block';
65	}
66
67    function getSort(){
68        return 311;
69    }
70
71    function connectTo($mode) {
72	  $this->Lexer->addEntryPattern('\{\{aimg>[^\}]+\}\}',$mode,'plugin_aimg');
73    }
74
75    function postConnect() {
76	  $this->Lexer->addPattern('^@.*?\n\~.*?\n','plugin_aimg');
77	  $this->Lexer->addExitPattern('\{\{<aimg\}\}','plugin_aimg');
78	}
79
80	function _imgToId($img,$pos) {
81
82		if ($img['title']) {
83			$img_id = str_replace(':','',cleanID($img['title']));
84			$img_id = ltrim($img_id, '0123456789._-');
85		}
86
87		if (empty($img_id)) {
88			if ($img['type'] == 'internalmedia') {
89			  $src = $img['src'];
90			  resolve_mediaid(getNS($ID),$src, $exists);
91			  $nssep = ($conf['useslash']) ? '[:;/]' : '[:;]';
92			  $img_id = preg_replace('!.*'.$nssep.'!','',$src);
93			} else {
94			  $src = parse_url($img['src']);
95			  $img_id = str_replace(':','',cleanID($src['host'].$src['path'].$src['query']));
96			  $img_id = ltrim($img_id, '0123456789._-');
97			}
98			if (empty($img_id)) {
99			  $img_id = 'aimg'.$pos;
100			}
101		}
102
103		return $img_id;
104	}
105
106    function handle($match, $state, $pos, &$handler){
107        switch ($state) {
108		case DOKU_LEXER_ENTER :
109			$img = Doku_Handler_Parse_Media(substr($match, 7, -2));
110			$img_id = $this->_imgToId( $img, $pos );
111		    $img_args = array( $img_id, $img['type'], $img['src'], $img['title'],
112						  $img['align'], $img['width'], $img['height'],
113						  $img['cache']);
114			return array( $state, $img_args );
115
116		case DOKU_LEXER_MATCHED:
117			return array( $state, $match );
118
119		case DOKU_LEXER_EXIT :
120		default:
121			return array( $state );
122        }
123	}
124
125	// adapted from image_map plugin
126	function _render_image( &$renderer, $img_args ) {
127
128		list($img_id, $img_type, $img_src, $img_title,
129			 $img_align, $img_width, $img_height,
130			 $img_cache) = $img_args;
131
132			 if ($img_type == 'internalmedia') {
133			resolve_mediaid(getNS($ID),$img_src, $exists);
134		}
135
136		$img_src = ml($img_src,array('w'=>$img_width,'h'=>$img_height,'cache'=>$img_cache));
137		$renderer->doc .= ' <img src="'.$img_src.'" class="media" ';
138		if (!is_null($img_title)) {
139		  $img_title = $renderer->_xmlEntities($img_title);
140		  $renderer->doc .= ' title="'.$img_title.'"';
141		  $renderer->doc .= ' alt="'.$img_title.'"';
142		} else {
143		  $renderer->doc .= ' alt=""';
144		}
145		if (!is_null($img_width)) {
146		  $renderer->doc .= ' width="'.$renderer->_xmlEntities($img_width).'"';
147		}
148
149		if (!is_null($img_height)) {
150			$renderer->doc .= ' height="'.$renderer->_xmlEntities($img_height).'"';
151		}
152
153		$renderer->doc .= ' />'.DOKU_LF;
154
155		return $img_id;
156	}
157
158    function render($mode, &$renderer, $data) {
159
160        if ( substr($mode,0,5) == 'xhtml' ) {
161			$state = $data[0];
162
163			switch($state) {
164				case DOKU_LEXER_ENTER :
165
166					$arg = $data[1];
167
168					$this->img_id = $arg[0];
169					$this->img_width = $arg[5];
170					$this->img_height = $arg[6];
171					$img_align = $arg[4];
172
173					$align_style = '';
174					switch( $img_align ) {
175					case 'left':
176						$align_style = 'margin-right: auto;';
177						break;
178					case 'right':
179						$align_style = 'margin-left: auto;';
180						break;
181					case 'center':
182					case 'centre':
183						$align_style = 'margin: 0 auto;';
184						break;
185					}
186
187					$style = 'width: '.$this->img_width.'px; height: '.$this->img_height.'px; '.$align_style;
188
189					$renderer->doc .= '<p>'.DOKU_LF;
190
191					$renderer->doc .= '<div id="fn-canvas-id-'.$this->img_id.'" class="fn-canvas fn-container-active" style="'.$style.'" >'.DOKU_LF;
192					$renderer->doc .= ' <div id="'.$this->img_id.'" class="fn-container fn-container-active" >'.DOKU_LF;
193
194					$this->_render_image( $renderer, $arg );
195
196					break;
197
198				case DOKU_LEXER_MATCHED:
199					$this->id_seq_num++;
200					$match = $data[1];
201
202					list($header,$body) = explode( "\n", substr($match, 1, -1), 2 );
203					list($coords,$title) = explode( "|", $header, 2 );
204
205					list($top,$left,$width,$height) = explode( ",", $coords );
206					$style = 'left: '.$left.'px; top: '.$top.'px; width: '.$width.'px; height: '.$height.'px;';
207
208					list($content,$author) = preg_split( "/\n~/", $body, 2 );
209
210					// fix for case with signature right after title
211					if ( $content[0] == '~' ) {
212						$author = substr( $content, 1 );
213						$content = '';
214					}
215
216					$renderer->doc .= '  <div class="fn-area" id="'.$this->img_id.'_'.$this->id_seq_num.'" style="'.$style.'">'.DOKU_LF;
217					$renderer->doc .= '   <div class="fn-note">'.DOKU_LF;
218					$renderer->doc .= '    <span class="fn-note-title">';
219					$renderer->doc .= p_render($mode, p_get_instructions( $title ), $dummy);
220					$renderer->doc .= '</span>'.DOKU_LF;
221					$renderer->doc .= '    <span class="fn-note-content">';
222					$renderer->doc .= p_render($mode, p_get_instructions( $content ), $dummy);
223					$renderer->doc .= '</span>'.DOKU_LF;
224					$renderer->doc .= '    <span class="fn-note-author">';
225					$renderer->doc .= p_render($mode, p_get_instructions( $author ), $dummy);
226					$renderer->doc .= '</span>'.DOKU_LF;
227					$renderer->doc .= '   </div>'.DOKU_LF;
228					$renderer->doc .= '  </div>'.DOKU_LF;
229					break;
230
231				case DOKU_LEXER_EXIT :
232					$renderer->doc .= ' </div>'.DOKU_LF.'</div>'.DOKU_LF;
233					$renderer->doc .= '</p>'.DOKU_LF;
234					break;
235			}
236			return true;
237		} else {
238			return false;
239		}
240    }
241}
242
243//Setup VIM: ex: et ts=4 enc=utf-8 :
244?>