MDL-40619 mod_quiz: Remove commented non-js behat scenario
[moodle.git] / mod / assign / feedback / editpdf / fpdi / fpdf_tpl.php
1 <?php\r
2 //\r
3 //  FPDF_TPL - Version 1.2.3\r
4 //\r
5 //    Copyright 2004-2013 Setasign - Jan Slabon\r
6 //\r
7 //  Licensed under the Apache License, Version 2.0 (the "License");\r
8 //  you may not use this file except in compliance with the License.\r
9 //  You may obtain a copy of the License at\r
10 //\r
11 //      http://www.apache.org/licenses/LICENSE-2.0\r
12 //\r
13 //  Unless required by applicable law or agreed to in writing, software\r
14 //  distributed under the License is distributed on an "AS IS" BASIS,\r
15 //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16 //  See the License for the specific language governing permissions and\r
17 //  limitations under the License.\r
18 //\r
19 \r
20 class FPDF_TPL extends FPDF {\r
21     /**\r
22      * Array of Tpl-Data\r
23      * @var array\r
24      */\r
25     var $tpls = array();\r
26 \r
27     /**\r
28      * Current Template-ID\r
29      * @var int\r
30      */\r
31     var $tpl = 0;\r
32     \r
33     /**\r
34      * "In Template"-Flag\r
35      * @var boolean\r
36      */\r
37     var $_intpl = false;\r
38     \r
39     /**\r
40      * Nameprefix of Templates used in Resources-Dictonary\r
41      * @var string A String defining the Prefix used as Template-Object-Names. Have to beginn with an /\r
42      */\r
43     var $tplprefix = "/TPL";\r
44 \r
45     /**\r
46      * Resources used By Templates and Pages\r
47      * @var array\r
48      */\r
49     var $_res = array();\r
50     \r
51     /**\r
52      * Last used Template data\r
53      *\r
54      * @var array\r
55      */\r
56     var $lastUsedTemplateData = array();\r
57     \r
58     /**\r
59      * Start a Template\r
60      *\r
61      * This method starts a template. You can give own coordinates to build an own sized\r
62      * Template. Pay attention, that the margins are adapted to the new templatesize.\r
63      * If you want to write outside the template, for example to build a clipped Template,\r
64      * you have to set the Margins and "Cursor"-Position manual after beginTemplate-Call.\r
65      *\r
66      * If no parameter is given, the template uses the current page-size.\r
67      * The Method returns an ID of the current Template. This ID is used later for using this template.\r
68      * Warning: A created Template is used in PDF at all events. Still if you don't use it after creation!\r
69      *\r
70      * @param int $x The x-coordinate given in user-unit\r
71      * @param int $y The y-coordinate given in user-unit\r
72      * @param int $w The width given in user-unit\r
73      * @param int $h The height given in user-unit\r
74      * @return int The ID of new created Template\r
75      */\r
76     function beginTemplate($x = null, $y = null, $w = null, $h = null) {\r
77         if (is_subclass_of($this, 'TCPDF')) {\r
78                 $this->Error('This method is only usable with FPDF. Use TCPDF methods startTemplate() instead.');\r
79                 return;\r
80         }\r
81         \r
82         if ($this->page <= 0)\r
83             $this->error("You have to add a page to fpdf first!");\r
84 \r
85         if ($x == null)\r
86             $x = 0;\r
87         if ($y == null)\r
88             $y = 0;\r
89         if ($w == null)\r
90             $w = $this->w;\r
91         if ($h == null)\r
92             $h = $this->h;\r
93 \r
94         // Save settings\r
95         $this->tpl++;\r
96         $tpl =& $this->tpls[$this->tpl];\r
97         $tpl = array(\r
98             'o_x' => $this->x,\r
99             'o_y' => $this->y,\r
100             'o_AutoPageBreak' => $this->AutoPageBreak,\r
101             'o_bMargin' => $this->bMargin,\r
102             'o_tMargin' => $this->tMargin,\r
103             'o_lMargin' => $this->lMargin,\r
104             'o_rMargin' => $this->rMargin,\r
105             'o_h' => $this->h,\r
106             'o_w' => $this->w,\r
107             'o_FontFamily' => $this->FontFamily,\r
108             'o_FontStyle' => $this->FontStyle,\r
109             'o_FontSizePt' => $this->FontSizePt,\r
110             'o_FontSize' => $this->FontSize,\r
111             'buffer' => '',\r
112             'x' => $x,\r
113             'y' => $y,\r
114             'w' => $w,\r
115             'h' => $h\r
116         );\r
117 \r
118         $this->SetAutoPageBreak(false);\r
119         \r
120         // Define own high and width to calculate possitions correct\r
121         $this->h = $h;\r
122         $this->w = $w;\r
123 \r
124         $this->_intpl = true;\r
125         $this->SetXY($x + $this->lMargin, $y + $this->tMargin);\r
126         $this->SetRightMargin($this->w - $w + $this->rMargin);\r
127 \r
128         if ($this->CurrentFont) {\r
129             $fontkey = $this->FontFamily . $this->FontStyle;\r
130                     $this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey];\r
131             \r
132                 $this->_out(sprintf('BT /F%d %.2f Tf ET', $this->CurrentFont['i'], $this->FontSizePt));\r
133         }\r
134         \r
135         return $this->tpl;\r
136     }\r
137     \r
138     /**\r
139      * End Template\r
140      *\r
141      * This method ends a template and reset initiated variables on beginTemplate.\r
142      *\r
143      * @return mixed If a template is opened, the ID is returned. If not a false is returned.\r
144      */\r
145     function endTemplate() {\r
146         if (is_subclass_of($this, 'TCPDF')) {\r
147                 $args = func_get_args();\r
148                 return call_user_func_array(array($this, 'TCPDF::endTemplate'), $args);\r
149         }\r
150         \r
151         if ($this->_intpl) {\r
152             $this->_intpl = false; \r
153             $tpl =& $this->tpls[$this->tpl];\r
154             $this->SetXY($tpl['o_x'], $tpl['o_y']);\r
155             $this->tMargin = $tpl['o_tMargin'];\r
156             $this->lMargin = $tpl['o_lMargin'];\r
157             $this->rMargin = $tpl['o_rMargin'];\r
158             $this->h = $tpl['o_h'];\r
159             $this->w = $tpl['o_w'];\r
160             $this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']);\r
161             \r
162             $this->FontFamily = $tpl['o_FontFamily'];\r
163                         $this->FontStyle = $tpl['o_FontStyle'];\r
164                         $this->FontSizePt = $tpl['o_FontSizePt'];\r
165                         $this->FontSize = $tpl['o_FontSize'];\r
166                 \r
167                         $fontkey = $this->FontFamily . $this->FontStyle;\r
168                         if ($fontkey)\r
169                 $this->CurrentFont =& $this->fonts[$fontkey];\r
170             \r
171             return $this->tpl;\r
172         } else {\r
173             return false;\r
174         }\r
175     }\r
176     \r
177     /**\r
178      * Use a Template in current Page or other Template\r
179      *\r
180      * You can use a template in a page or in another template.\r
181      * You can give the used template a new size like you use the Image()-method.\r
182      * All parameters are optional. The width or height is calculated automaticaly\r
183      * if one is given. If no parameter is given the origin size as defined in\r
184      * beginTemplate() is used.\r
185      * The calculated or used width and height are returned as an array.\r
186      *\r
187      * @param int $tplidx A valid template-Id\r
188      * @param int $_x The x-position\r
189      * @param int $_y The y-position\r
190      * @param int $_w The new width of the template\r
191      * @param int $_h The new height of the template\r
192      * @retrun array The height and width of the template\r
193      */\r
194     function useTemplate($tplidx, $_x = null, $_y = null, $_w = 0, $_h = 0) {\r
195         if ($this->page <= 0)\r
196                 $this->error('You have to add a page first!');\r
197         \r
198         if (!isset($this->tpls[$tplidx]))\r
199             $this->error('Template does not exist!');\r
200             \r
201         if ($this->_intpl) {\r
202             $this->_res['tpl'][$this->tpl]['tpls'][$tplidx] =& $this->tpls[$tplidx];\r
203         }\r
204         \r
205         $tpl =& $this->tpls[$tplidx];\r
206         $w = $tpl['w'];\r
207         $h = $tpl['h'];\r
208         \r
209         if ($_x == null)\r
210             $_x = 0;\r
211         if ($_y == null)\r
212             $_y = 0;\r
213             \r
214         $_x += $tpl['x'];\r
215         $_y += $tpl['y'];\r
216         \r
217         $wh = $this->getTemplateSize($tplidx, $_w, $_h);\r
218         $_w = $wh['w'];\r
219         $_h = $wh['h'];\r
220     \r
221         $tData = array(\r
222             'x' => $this->x,\r
223             'y' => $this->y,\r
224             'w' => $_w,\r
225             'h' => $_h,\r
226             'scaleX' => ($_w / $w),\r
227             'scaleY' => ($_h / $h),\r
228             'tx' => $_x,\r
229             'ty' =>  ($this->h - $_y - $_h),\r
230             'lty' => ($this->h - $_y - $_h) - ($this->h - $h) * ($_h / $h)\r
231         );\r
232         \r
233         $this->_out(sprintf('q %.4F 0 0 %.4F %.4F %.4F cm', $tData['scaleX'], $tData['scaleY'], $tData['tx'] * $this->k, $tData['ty'] * $this->k)); // Translate \r
234         $this->_out(sprintf('%s%d Do Q', $this->tplprefix, $tplidx));\r
235 \r
236         $this->lastUsedTemplateData = $tData;\r
237         \r
238         return array('w' => $_w, 'h' => $_h);\r
239     }\r
240     \r
241     /**\r
242      * Get The calculated Size of a Template\r
243      *\r
244      * If one size is given, this method calculates the other one.\r
245      *\r
246      * @param int $tplidx A valid template-Id\r
247      * @param int $_w The width of the template\r
248      * @param int $_h The height of the template\r
249      * @return array The height and width of the template\r
250      */\r
251     function getTemplateSize($tplidx, $_w = 0, $_h = 0) {\r
252         if (!isset($this->tpls[$tplidx]))\r
253             return false;\r
254 \r
255         $tpl =& $this->tpls[$tplidx];\r
256         $w = $tpl['w'];\r
257         $h = $tpl['h'];\r
258         \r
259         if ($_w == 0 and $_h == 0) {\r
260             $_w = $w;\r
261             $_h = $h;\r
262         }\r
263 \r
264         if($_w == 0)\r
265                 $_w = $_h * $w / $h;\r
266         if($_h == 0)\r
267                 $_h = $_w * $h / $w;\r
268                 \r
269         return array("w" => $_w, "h" => $_h);\r
270     }\r
271     \r
272     /**\r
273      * See FPDF/TCPDF-Documentation ;-)\r
274      */\r
275     public function SetFont($family, $style='', $size=null, $fontfile='', $subset='default', $out=true) {\r
276         if (is_subclass_of($this, 'TCPDF')) {\r
277                 $args = func_get_args();\r
278                 return call_user_func_array(array($this, 'TCPDF::SetFont'), $args);\r
279         }\r
280         \r
281         parent::SetFont($family, $style, $size);\r
282        \r
283         $fontkey = $this->FontFamily . $this->FontStyle;\r
284         \r
285         if ($this->_intpl) {\r
286             $this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey];\r
287         } else {\r
288             $this->_res['page'][$this->page]['fonts'][$fontkey] =& $this->fonts[$fontkey];\r
289         }\r
290     }\r
291     \r
292     /**\r
293      * See FPDF/TCPDF-Documentation ;-)\r
294      */\r
295     function Image(\r
296                 $file, $x = '', $y = '', $w = 0, $h = 0, $type = '', $link = '', $align = '', $resize = false,\r
297                 $dpi = 300, $palign = '', $ismask = false, $imgmask = false, $border = 0, $fitbox = false,\r
298                 $hidden = false, $fitonpage = false, $alt = false, $altimgs = array()\r
299     ) {\r
300         if (is_subclass_of($this, 'TCPDF')) {\r
301                 $args = func_get_args();\r
302                         return call_user_func_array(array($this, 'TCPDF::Image'), $args);\r
303         }\r
304         \r
305         $ret = parent::Image($file, $x, $y, $w, $h, $type, $link);\r
306         if ($this->_intpl) {\r
307             $this->_res['tpl'][$this->tpl]['images'][$file] =& $this->images[$file];\r
308         } else {\r
309             $this->_res['page'][$this->page]['images'][$file] =& $this->images[$file];\r
310         }\r
311         \r
312         return $ret;\r
313     }\r
314     \r
315     /**\r
316      * See FPDF-Documentation ;-)\r
317      *\r
318      * AddPage is not available when you're "in" a template.\r
319      */\r
320     function AddPage($orientation = '', $format = '', $keepmargins = false, $tocpage = false) {\r
321         if (is_subclass_of($this, 'TCPDF')) {\r
322                 $args = func_get_args();\r
323                 return call_user_func_array(array($this, 'TCPDF::AddPage'), $args);\r
324         }\r
325         \r
326         if ($this->_intpl)\r
327             $this->Error('Adding pages in templates isn\'t possible!');\r
328             \r
329         parent::AddPage($orientation, $format);\r
330     }\r
331 \r
332     /**\r
333      * Preserve adding Links in Templates ...won't work\r
334      */\r
335     function Link($x, $y, $w, $h, $link, $spaces = 0) {\r
336         if (is_subclass_of($this, 'TCPDF')) {\r
337                 $args = func_get_args();\r
338                         return call_user_func_array(array($this, 'TCPDF::Link'), $args);\r
339         }\r
340         \r
341         if ($this->_intpl)\r
342             $this->Error('Using links in templates aren\'t possible!');\r
343             \r
344         parent::Link($x, $y, $w, $h, $link);\r
345     }\r
346     \r
347     function AddLink() {\r
348         if (is_subclass_of($this, 'TCPDF')) {\r
349                 $args = func_get_args();\r
350                         return call_user_func_array(array($this, 'TCPDF::AddLink'), $args);\r
351         }\r
352         \r
353         if ($this->_intpl)\r
354             $this->Error('Adding links in templates aren\'t possible!');\r
355         return parent::AddLink();\r
356     }\r
357     \r
358     function SetLink($link, $y = 0, $page = -1) {\r
359         if (is_subclass_of($this, 'TCPDF')) {\r
360                 $args = func_get_args();\r
361                         return call_user_func_array(array($this, 'TCPDF::SetLink'), $args);\r
362         }\r
363         \r
364         if ($this->_intpl)\r
365             $this->Error('Setting links in templates aren\'t possible!');\r
366         parent::SetLink($link, $y, $page);\r
367     }\r
368     \r
369     /**\r
370      * Private Method that writes the form xobjects\r
371      */\r
372     function _putformxobjects() {\r
373         $filter=($this->compress) ? '/Filter /FlateDecode ' : '';\r
374             reset($this->tpls);\r
375         foreach($this->tpls AS $tplidx => $tpl) {\r
376 \r
377             $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];\r
378                 $this->_newobj();\r
379                 $this->tpls[$tplidx]['n'] = $this->n;\r
380                 $this->_out('<<'.$filter.'/Type /XObject');\r
381             $this->_out('/Subtype /Form');\r
382             $this->_out('/FormType 1');\r
383             $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',\r
384                 // llx\r
385                 $tpl['x'] * $this->k,\r
386                 // lly\r
387                 -$tpl['y'] * $this->k,\r
388                 // urx\r
389                 ($tpl['w'] + $tpl['x']) * $this->k,\r
390                 // ury\r
391                 ($tpl['h'] - $tpl['y']) * $this->k\r
392             ));\r
393             \r
394             if ($tpl['x'] != 0 || $tpl['y'] != 0) {\r
395                 $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]',\r
396                      -$tpl['x'] * $this->k * 2, $tpl['y'] * $this->k * 2\r
397                 ));\r
398             }\r
399             \r
400             $this->_out('/Resources ');\r
401 \r
402             $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');\r
403                 if (isset($this->_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) {\r
404                 $this->_out('/Font <<');\r
405                 foreach($this->_res['tpl'][$tplidx]['fonts'] as $font)\r
406                         $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');\r
407                 $this->_out('>>');\r
408             }\r
409                 if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) || \r
410                    isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls']))\r
411                 {\r
412                 $this->_out('/XObject <<');\r
413                 if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) {\r
414                     foreach($this->_res['tpl'][$tplidx]['images'] as $image)\r
415                                 $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');\r
416                 }\r
417                 if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) {\r
418                     foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl)\r
419                         $this->_out($this->tplprefix . $i . ' ' . $tpl['n'] . ' 0 R');\r
420                 }\r
421                 $this->_out('>>');\r
422                 }\r
423                 $this->_out('>>');\r
424                 \r
425                 $this->_out('/Length ' . strlen($p) . ' >>');\r
426                 $this->_putstream($p);\r
427                 $this->_out('endobj');\r
428         }\r
429     }\r
430     \r
431     /**\r
432      * Overwritten to add _putformxobjects() after _putimages()\r
433      *\r
434      */\r
435     function _putimages() {\r
436         parent::_putimages();\r
437         $this->_putformxobjects();\r
438     }\r
439     \r
440     function _putxobjectdict() {\r
441         parent::_putxobjectdict();\r
442         \r
443         if (count($this->tpls)) {\r
444             foreach($this->tpls as $tplidx => $tpl) {\r
445                 $this->_out(sprintf('%s%d %d 0 R', $this->tplprefix, $tplidx, $tpl['n']));\r
446             }\r
447         }\r
448     }\r
449 \r
450     /**\r
451      * Private Method\r
452      */\r
453     function _out($s) {\r
454         if ($this->state == 2 && $this->_intpl) {\r
455             $this->tpls[$this->tpl]['buffer'] .= $s . "\n";\r
456         } else {\r
457             parent::_out($s);\r
458         }\r
459     }\r
460 }\r