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