1<?php
2
3namespace Mpdf\Tag;
4
5use Mpdf\Mpdf;
6use \dokuwiki\plugin\dw2pdf\DokuImageProcessorDecorator as ImageProcessor;
7
8class Img extends Tag
9{
10
11	public function open($attr, &$ahtml, &$ihtml)
12	{
13		$this->mpdf->ignorefollowingspaces = false;
14		$objattr = [];
15		$objattr['margin_top'] = 0;
16		$objattr['margin_bottom'] = 0;
17		$objattr['margin_left'] = 0;
18		$objattr['margin_right'] = 0;
19		$objattr['padding_top'] = 0;
20		$objattr['padding_bottom'] = 0;
21		$objattr['padding_left'] = 0;
22		$objattr['padding_right'] = 0;
23		$objattr['width'] = 0;
24		$objattr['height'] = 0;
25		$objattr['border_top']['w'] = 0;
26		$objattr['border_bottom']['w'] = 0;
27		$objattr['border_left']['w'] = 0;
28		$objattr['border_right']['w'] = 0;
29		if (isset($attr['SRC'])) {
30			$srcpath = $attr['SRC'];
31			$orig_srcpath = (isset($attr['ORIG_SRC']) ? $attr['ORIG_SRC'] : '');
32			$properties = $this->cssManager->MergeCSS('', 'IMG', $attr);
33			if (isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY']) === 'none') {
34				return;
35			}
36			if (isset($properties['Z-INDEX']) && $this->mpdf->current_layer == 0) {
37				$v = (int) $properties['Z-INDEX'];
38				if ($v > 0) {
39					$objattr['z-index'] = $v;
40				}
41			}
42
43			$objattr['visibility'] = 'visible';
44			if (isset($properties['VISIBILITY'])) {
45				$v = strtolower($properties['VISIBILITY']);
46				if (($v === 'hidden' || $v === 'printonly' || $v === 'screenonly') && $this->mpdf->visibility === 'visible') {
47					$objattr['visibility'] = $v;
48				}
49			}
50
51			// VSPACE and HSPACE converted to margins in MergeCSS
52			if (isset($properties['MARGIN-TOP'])) {
53				$objattr['margin_top'] = $this->sizeConverter->convert(
54					$properties['MARGIN-TOP'],
55					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
56					$this->mpdf->FontSize,
57					false
58				);
59			}
60			if (isset($properties['MARGIN-BOTTOM'])) {
61				$objattr['margin_bottom'] = $this->sizeConverter->convert(
62					$properties['MARGIN-BOTTOM'],
63					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
64					$this->mpdf->FontSize,
65					false
66				);
67			}
68			if (isset($properties['MARGIN-LEFT'])) {
69				$objattr['margin_left'] = $this->sizeConverter->convert(
70					$properties['MARGIN-LEFT'],
71					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
72					$this->mpdf->FontSize,
73					false
74				);
75			}
76			if (isset($properties['MARGIN-RIGHT'])) {
77				$objattr['margin_right'] = $this->sizeConverter->convert(
78					$properties['MARGIN-RIGHT'],
79					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
80					$this->mpdf->FontSize,
81					false
82				);
83			}
84
85			if (isset($properties['PADDING-TOP'])) {
86				$objattr['padding_top'] = $this->sizeConverter->convert(
87					$properties['PADDING-TOP'],
88					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
89					$this->mpdf->FontSize,
90					false
91				);
92			}
93			if (isset($properties['PADDING-BOTTOM'])) {
94				$objattr['padding_bottom'] = $this->sizeConverter->convert(
95					$properties['PADDING-BOTTOM'],
96					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
97					$this->mpdf->FontSize,
98					false
99				);
100			}
101			if (isset($properties['PADDING-LEFT'])) {
102				$objattr['padding_left'] = $this->sizeConverter->convert(
103					$properties['PADDING-LEFT'],
104					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
105					$this->mpdf->FontSize,
106					false
107				);
108			}
109			if (isset($properties['PADDING-RIGHT'])) {
110				$objattr['padding_right'] = $this->sizeConverter->convert(
111					$properties['PADDING-RIGHT'],
112					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
113					$this->mpdf->FontSize,
114					false
115				);
116			}
117
118			if (isset($properties['BORDER-TOP'])) {
119				$objattr['border_top'] = $this->mpdf->border_details($properties['BORDER-TOP']);
120			}
121			if (isset($properties['BORDER-BOTTOM'])) {
122				$objattr['border_bottom'] = $this->mpdf->border_details($properties['BORDER-BOTTOM']);
123			}
124			if (isset($properties['BORDER-LEFT'])) {
125				$objattr['border_left'] = $this->mpdf->border_details($properties['BORDER-LEFT']);
126			}
127			if (isset($properties['BORDER-RIGHT'])) {
128				$objattr['border_right'] = $this->mpdf->border_details($properties['BORDER-RIGHT']);
129			}
130
131			if (isset($properties['VERTICAL-ALIGN'])) {
132				$objattr['vertical-align'] = $this->getAlign($properties['VERTICAL-ALIGN']);
133			}
134			$w = 0;
135			$h = 0;
136			if (isset($properties['WIDTH'])) {
137				$w = $this->sizeConverter->convert(
138					$properties['WIDTH'],
139					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
140					$this->mpdf->FontSize,
141					false
142				);
143			} elseif (isset($attr['WIDTH'])) {
144				$w = $this->sizeConverter->convert(
145					$attr['WIDTH'],
146					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
147					$this->mpdf->FontSize,
148					false
149				);
150			}
151			if (isset($properties['HEIGHT'])) {
152				$h = $this->sizeConverter->convert(
153					$properties['HEIGHT'],
154					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
155					$this->mpdf->FontSize,
156					false
157				);
158			} elseif (isset($attr['HEIGHT'])) {
159				$h = $this->sizeConverter->convert(
160					$attr['HEIGHT'],
161					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
162					$this->mpdf->FontSize,
163					false
164				);
165			}
166			$maxw = $maxh = $minw = $minh = false;
167			if (isset($properties['MAX-WIDTH'])) {
168				$maxw = $this->sizeConverter->convert(
169					$properties['MAX-WIDTH'],
170					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
171					$this->mpdf->FontSize,
172					false
173				);
174			} elseif (isset($attr['MAX-WIDTH'])) {
175				$maxw = $this->sizeConverter->convert(
176					$attr['MAX-WIDTH'],
177					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
178					$this->mpdf->FontSize,
179					false
180				);
181			}
182			if (isset($properties['MAX-HEIGHT'])) {
183				$maxh = $this->sizeConverter->convert(
184					$properties['MAX-HEIGHT'],
185					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
186					$this->mpdf->FontSize,
187					false
188				);
189			} elseif (isset($attr['MAX-HEIGHT'])) {
190				$maxh = $this->sizeConverter->convert(
191					$attr['MAX-HEIGHT'],
192					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
193					$this->mpdf->FontSize,
194					false
195				);
196			}
197			if (isset($properties['MIN-WIDTH'])) {
198				$minw = $this->sizeConverter->convert(
199					$properties['MIN-WIDTH'],
200					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
201					$this->mpdf->FontSize,
202					false
203				);
204			} elseif (isset($attr['MIN-WIDTH'])) {
205				$minw = $this->sizeConverter->convert(
206					$attr['MIN-WIDTH'],
207					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
208					$this->mpdf->FontSize,
209					false
210				);
211			}
212			if (isset($properties['MIN-HEIGHT'])) {
213				$minh = $this->sizeConverter->convert(
214					$properties['MIN-HEIGHT'],
215					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
216					$this->mpdf->FontSize,
217					false
218				);
219			} elseif (isset($attr['MIN-HEIGHT'])) {
220				$minh = $this->sizeConverter->convert(
221					$attr['MIN-HEIGHT'],
222					$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
223					$this->mpdf->FontSize,
224					false
225				);
226			}
227
228			if (isset($properties['OPACITY']) && $properties['OPACITY'] > 0 && $properties['OPACITY'] <= 1) {
229				$objattr['opacity'] = $properties['OPACITY'];
230			}
231			if ($this->mpdf->HREF) {
232				if (strpos($this->mpdf->HREF, '.') === false && strpos($this->mpdf->HREF, '@') !== 0) {
233					$href = $this->mpdf->HREF;
234					while (array_key_exists($href, $this->mpdf->internallink)) {
235						$href = '#' . $href;
236					}
237					$this->mpdf->internallink[$href] = $this->mpdf->AddLink();
238					$objattr['link'] = $this->mpdf->internallink[$href];
239				} else {
240					$objattr['link'] = $this->mpdf->HREF;
241				}
242			}
243			$extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top']
244				+ $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
245
246			$extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left']
247				+ $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
248
249			// mPDF 5.7.3 TRANSFORMS
250			if (isset($properties['BACKGROUND-COLOR']) && $properties['BACKGROUND-COLOR'] != '') {
251				$objattr['bgcolor'] = $this->colorConverter->convert($properties['BACKGROUND-COLOR'], $this->mpdf->PDFAXwarnings);
252			}
253
254			/* -- BACKGROUNDS -- */
255			if (isset($properties['GRADIENT-MASK']) && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $properties['GRADIENT-MASK'])) {
256				$objattr['GRADIENT-MASK'] = $properties['GRADIENT-MASK'];
257			}
258			/* -- END BACKGROUNDS -- */
259
260			// mPDF 6
261			$interpolation = false;
262			if (!empty($properties['IMAGE-RENDERING'])) {
263				$interpolation = false;
264				if (strtolower($properties['IMAGE-RENDERING']) === 'crisp-edges') {
265					$interpolation = false;
266				} elseif (strtolower($properties['IMAGE-RENDERING']) === 'optimizequality') {
267					$interpolation = true;
268				} elseif (strtolower($properties['IMAGE-RENDERING']) === 'smooth') {
269					$interpolation = true;
270				} elseif (strtolower($properties['IMAGE-RENDERING']) === 'auto') {
271					$interpolation = $this->mpdf->interpolateImages;
272				}
273				$info['interpolation'] = $interpolation;
274			}
275
276			// Image file
277			$info = $this->imageProcessor->getImage($srcpath, true, true, $orig_srcpath, $interpolation); // mPDF 6
278			if (!$info) {
279				$info = $this->imageProcessor->getImage($this->mpdf->noImageFile);
280				if ($info) {
281					$srcpath = $this->mpdf->noImageFile;
282					$w = ($info['w'] * (25.4 / $this->mpdf->img_dpi));
283					$h = ($info['h'] * (25.4 / $this->mpdf->img_dpi));
284				}
285			}
286			if (!$info) {
287				return;
288			}
289
290			$image_orientation = 0;
291			if (isset($attr['ROTATE'])) {
292				$image_orientation = $attr['ROTATE'];
293			} elseif (isset($properties['IMAGE-ORIENTATION'])) {
294				$image_orientation = $properties['IMAGE-ORIENTATION'];
295			}
296			if ($image_orientation) {
297				if ($image_orientation == 90 || $image_orientation == -90 || $image_orientation == 270) {
298					$tmpw = $info['w'];
299					$info['w'] = $info['h'];
300					$info['h'] = $tmpw;
301				}
302				$objattr['ROTATE'] = $image_orientation;
303			}
304
305			$objattr['file'] = $srcpath;
306			//Default width and height calculation if needed
307			if ($w == 0 && $h == 0) {
308				/* -- IMAGES-WMF -- */
309				if ($info['type'] === 'wmf') {
310					// WMF units are twips (1/20pt)
311					// divide by 20 to get points
312					// divide by k to get user units
313					$w = abs($info['w']) / (20 * Mpdf::SCALE);
314					$h = abs($info['h']) / (20 * Mpdf::SCALE);
315				} else { 							/* -- END IMAGES-WMF -- */
316					if ($info['type'] === 'svg') {
317						// SVG units are pixels
318						$w = abs($info['w']) / Mpdf::SCALE;
319						$h = abs($info['h']) / Mpdf::SCALE;
320					} else {
321						//Put image at default image dpi
322						$w = ($info['w'] / Mpdf::SCALE) * (72 / $this->mpdf->img_dpi);
323						$h = ($info['h'] / Mpdf::SCALE) * (72 / $this->mpdf->img_dpi);
324					}
325				}
326				if (isset($properties['IMAGE-RESOLUTION'])) {
327					if (preg_match('/from-image/i', $properties['IMAGE-RESOLUTION']) && isset($info['set-dpi']) && $info['set-dpi'] > 0) {
328						$w *= $this->mpdf->img_dpi / $info['set-dpi'];
329						$h *= $this->mpdf->img_dpi / $info['set-dpi'];
330					} elseif (preg_match('/(\d+)dpi/i', $properties['IMAGE-RESOLUTION'], $m)) {
331						$dpi = $m[1];
332						if ($dpi > 0) {
333							$w *= $this->mpdf->img_dpi / $dpi;
334							$h *= $this->mpdf->img_dpi / $dpi;
335						}
336					}
337				}
338			}
339			// IF WIDTH OR HEIGHT SPECIFIED
340			if ($w == 0) {
341				$w = $info['h'] ? abs($h * $info['w'] / $info['h']) : INF;
342			}
343
344			if ($h == 0) {
345				$h = $info['w'] ? abs($w * $info['h'] / $info['w']) : INF;
346			}
347
348			if ($minw && $w < $minw) {
349				$w = $minw;
350				$h = $info['w'] ? abs($w * $info['h'] / $info['w']) : INF;
351			}
352			if ($maxw && $w > $maxw) {
353				$w = $maxw;
354				$h = $info['w'] ? abs($w * $info['h'] / $info['w']) : INF;
355			}
356			if ($minh && $h < $minh) {
357				$h = $minh;
358				$w = $info['h'] ? abs($h * $info['w'] / $info['h']) : INF;
359			}
360			if ($maxh && $h > $maxh) {
361				$h = $maxh;
362				$w = $info['h'] ? abs($h * $info['w'] / $info['h']) : INF;
363			}
364
365			// Resize to maximum dimensions of page
366			$maxWidth = $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'];
367			$maxHeight = $this->mpdf->h - ($this->mpdf->tMargin + $this->mpdf->bMargin + 1);
368			if ($this->mpdf->fullImageHeight) {
369				$maxHeight = $this->mpdf->fullImageHeight;
370			}
371			if (($w + $extrawidth) > ($maxWidth + 0.0001)) { // mPDF 5.7.4  0.0001 to allow for rounding errors when w==maxWidth
372				$w = $maxWidth - $extrawidth;
373				$h = abs($w * $info['h'] / $info['w']);
374			}
375
376			if ($h + $extraheight > $maxHeight) {
377				$h = $maxHeight - $extraheight;
378				$w = abs($h * $info['w'] / $info['h']);
379			}
380			$objattr['type'] = 'image';
381			$objattr['itype'] = $info['type'];
382
383			$objattr['orig_h'] = $info['h'];
384			$objattr['orig_w'] = $info['w'];
385			/* -- IMAGES-WMF -- */
386			if ($info['type'] === 'wmf') {
387				$objattr['wmf_x'] = $info['x'];
388				$objattr['wmf_y'] = $info['y'];
389			} else { 						/* -- END IMAGES-WMF -- */
390				if ($info['type'] === 'svg') {
391					$objattr['wmf_x'] = $info['x'];
392					$objattr['wmf_y'] = $info['y'];
393				}
394			}
395			$objattr['height'] = $h + $extraheight;
396			$objattr['width'] = $w + $extrawidth;
397			$objattr['image_height'] = $h;
398			$objattr['image_width'] = $w;
399			/* -- CSS-IMAGE-FLOAT -- */
400			if (!$this->mpdf->ColActive && !$this->mpdf->tableLevel && !$this->mpdf->listlvl && !$this->mpdf->kwt) {
401				if (isset($properties['FLOAT']) && (strtoupper($properties['FLOAT']) === 'RIGHT' || strtoupper($properties['FLOAT']) === 'LEFT')) {
402					$objattr['float'] = strtoupper(substr($properties['FLOAT'], 0, 1));
403				}
404			}
405			/* -- END CSS-IMAGE-FLOAT -- */
406			// mPDF 5.7.3 TRANSFORMS
407			if (isset($properties['TRANSFORM']) && !$this->mpdf->ColActive && !$this->mpdf->kwt) {
408				$objattr['transform'] = $properties['TRANSFORM'];
409			}
410
411			$e = "\xbb\xa4\xactype=image,objattr=" . serialize($objattr) . "\xbb\xa4\xac";
412
413			/* -- TABLES -- */
414			// Output it to buffers
415			if ($this->mpdf->tableLevel) {
416				$this->mpdf->_saveCellTextBuffer($e, $this->mpdf->HREF);
417				$this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] += $objattr['width'];
418			} else {
419				/* -- END TABLES -- */
420				$this->mpdf->_saveTextBuffer($e, $this->mpdf->HREF);
421			} // *TABLES*
422			/* -- ANNOTATIONS -- */
423			if ($this->mpdf->title2annots && isset($attr['TITLE'])) {
424				$objattr = [];
425				$objattr['margin_top'] = 0;
426				$objattr['margin_bottom'] = 0;
427				$objattr['margin_left'] = 0;
428				$objattr['margin_right'] = 0;
429				$objattr['width'] = 0;
430				$objattr['height'] = 0;
431				$objattr['border_top']['w'] = 0;
432				$objattr['border_bottom']['w'] = 0;
433				$objattr['border_left']['w'] = 0;
434				$objattr['border_right']['w'] = 0;
435				$objattr['CONTENT'] = $attr['TITLE'];
436				$objattr['type'] = 'annot';
437				$objattr['POS-X'] = 0;
438				$objattr['POS-Y'] = 0;
439				$objattr['ICON'] = 'Comment';
440				$objattr['AUTHOR'] = '';
441				$objattr['SUBJECT'] = '';
442				$objattr['OPACITY'] = $this->mpdf->annotOpacity;
443				$objattr['COLOR'] = $this->colorConverter->convert('yellow', $this->mpdf->PDFAXwarnings);
444				$e = "\xbb\xa4\xactype=annot,objattr=" . serialize($objattr) . "\xbb\xa4\xac";
445				if ($this->mpdf->tableLevel) { // *TABLES*
446					$this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['textbuffer'][] = [$e]; // *TABLES*
447				} // *TABLES*
448				else { // *TABLES*
449					$this->mpdf->textbuffer[] = [$e];
450				} // *TABLES*
451			}
452			/* -- END ANNOTATIONS -- */
453		}
454	}
455
456	public function close(&$ahtml, &$ihtml)
457	{
458	}
459}
460