commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-old / civicrm / packages / FPDI / fpdf_tpl.php
1 <?php
2 //
3 // FPDI - Version 1.5
4 //
5 // Copyright 2004-2014 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 require_once('fpdi_bridge.php');
21
22 /**
23 * Class FPDF_TPL
24 */
25 class FPDF_TPL extends fpdi_bridge
26 {
27 /**
28 * Array of template data
29 *
30 * @var array
31 */
32 protected $_tpls = array();
33
34 /**
35 * Current Template-Id
36 *
37 * @var int
38 */
39 public $tpl = 0;
40
41 /**
42 * "In Template"-Flag
43 *
44 * @var boolean
45 */
46 protected $_inTpl = false;
47
48 /**
49 * Name prefix of templates used in Resources dictionary
50 *
51 * @var string A String defining the Prefix used as Template-Object-Names. Have to begin with an /
52 */
53 public $tplPrefix = "/TPL";
54
55 /**
56 * Resources used by templates and pages
57 *
58 * @var array
59 */
60 protected $_res = array();
61
62 /**
63 * Last used template data
64 *
65 * @var array
66 */
67 public $lastUsedTemplateData = array();
68
69 /**
70 * Start a template.
71 *
72 * This method starts a template. You can give own coordinates to build an own sized
73 * template. Pay attention, that the margins are adapted to the new template size.
74 * If you want to write outside the template, for example to build a clipped template,
75 * you have to set the margins and "cursor"-position manual after beginTemplate()-call.
76 *
77 * If no parameter is given, the template uses the current page-size.
78 * The method returns an id of the current template. This id is used later for using this template.
79 * Warning: A created template is saved in the resulting PDF at all events. Also if you don't use it after creation!
80 *
81 * @param int $x The x-coordinate given in user-unit
82 * @param int $y The y-coordinate given in user-unit
83 * @param int $w The width given in user-unit
84 * @param int $h The height given in user-unit
85 * @return int The id of new created template
86 * @throws LogicException
87 */
88 public function beginTemplate($x = null, $y = null, $w = null, $h = null)
89 {
90 if (is_subclass_of($this, 'TCPDF')) {
91 throw new LogicException('This method is only usable with FPDF. Use TCPDF methods startTemplate() instead.');
92 }
93
94 if ($this->page <= 0) {
95 throw new LogicException("You have to add at least a page first!");
96 }
97
98 if ($x == null)
99 $x = 0;
100 if ($y == null)
101 $y = 0;
102 if ($w == null)
103 $w = $this->w;
104 if ($h == null)
105 $h = $this->h;
106
107 // Save settings
108 $this->tpl++;
109 $tpl =& $this->_tpls[$this->tpl];
110 $tpl = array(
111 'o_x' => $this->x,
112 'o_y' => $this->y,
113 'o_AutoPageBreak' => $this->AutoPageBreak,
114 'o_bMargin' => $this->bMargin,
115 'o_tMargin' => $this->tMargin,
116 'o_lMargin' => $this->lMargin,
117 'o_rMargin' => $this->rMargin,
118 'o_h' => $this->h,
119 'o_w' => $this->w,
120 'o_FontFamily' => $this->FontFamily,
121 'o_FontStyle' => $this->FontStyle,
122 'o_FontSizePt' => $this->FontSizePt,
123 'o_FontSize' => $this->FontSize,
124 'buffer' => '',
125 'x' => $x,
126 'y' => $y,
127 'w' => $w,
128 'h' => $h
129 );
130
131 $this->SetAutoPageBreak(false);
132
133 // Define own high and width to calculate correct positions
134 $this->h = $h;
135 $this->w = $w;
136
137 $this->_inTpl = true;
138 $this->SetXY($x + $this->lMargin, $y + $this->tMargin);
139 $this->SetRightMargin($this->w - $w + $this->rMargin);
140
141 if ($this->CurrentFont) {
142 $fontKey = $this->FontFamily . $this->FontStyle;
143 if ($fontKey) {
144 $this->_res['tpl'][$this->tpl]['fonts'][$fontKey] =& $this->fonts[$fontKey];
145 $this->_out(sprintf('BT /F%d %.2f Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
146 }
147 }
148
149 return $this->tpl;
150 }
151
152 /**
153 * End template.
154 *
155 * This method ends a template and reset initiated variables collected in {@link beginTemplate()}.
156 *
157 * @return int|boolean If a template is opened, the id is returned. If not a false is returned.
158 */
159 public function endTemplate()
160 {
161 if (is_subclass_of($this, 'TCPDF')) {
162 $args = func_get_args();
163 return call_user_func_array(array($this, 'TCPDF::endTemplate'), $args);
164 }
165
166 if ($this->_inTpl) {
167 $this->_inTpl = false;
168 $tpl = $this->_tpls[$this->tpl];
169 $this->SetXY($tpl['o_x'], $tpl['o_y']);
170 $this->tMargin = $tpl['o_tMargin'];
171 $this->lMargin = $tpl['o_lMargin'];
172 $this->rMargin = $tpl['o_rMargin'];
173 $this->h = $tpl['o_h'];
174 $this->w = $tpl['o_w'];
175 $this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']);
176
177 $this->FontFamily = $tpl['o_FontFamily'];
178 $this->FontStyle = $tpl['o_FontStyle'];
179 $this->FontSizePt = $tpl['o_FontSizePt'];
180 $this->FontSize = $tpl['o_FontSize'];
181
182 $fontKey = $this->FontFamily . $this->FontStyle;
183 if ($fontKey)
184 $this->CurrentFont =& $this->fonts[$fontKey];
185
186 return $this->tpl;
187 } else {
188 return false;
189 }
190 }
191
192 /**
193 * Use a template in current page or other template.
194 *
195 * You can use a template in a page or in another template.
196 * You can give the used template a new size.
197 * All parameters are optional. The width or height is calculated automatically
198 * if one is given. If no parameter is given the origin size as defined in
199 * {@link beginTemplate()} method is used.
200 *
201 * The calculated or used width and height are returned as an array.
202 *
203 * @param int $tplIdx A valid template-id
204 * @param int $x The x-position
205 * @param int $y The y-position
206 * @param int $w The new width of the template
207 * @param int $h The new height of the template
208 * @return array The height and width of the template (array('w' => ..., 'h' => ...))
209 * @throws LogicException|InvalidArgumentException
210 */
211 public function useTemplate($tplIdx, $x = null, $y = null, $w = 0, $h = 0)
212 {
213 if ($this->page <= 0) {
214 throw new LogicException('You have to add at least a page first!');
215 }
216
217 if (!isset($this->_tpls[$tplIdx])) {
218 throw new InvalidArgumentException('Template does not exist!');
219 }
220
221 if ($this->_inTpl) {
222 $this->_res['tpl'][$this->tpl]['tpls'][$tplIdx] =& $this->_tpls[$tplIdx];
223 }
224
225 $tpl = $this->_tpls[$tplIdx];
226 $_w = $tpl['w'];
227 $_h = $tpl['h'];
228
229 if ($x == null) {
230 $x = 0;
231 }
232
233 if ($y == null) {
234 $y = 0;
235 }
236
237 $x += $tpl['x'];
238 $y += $tpl['y'];
239
240 $wh = $this->getTemplateSize($tplIdx, $w, $h);
241 $w = $wh['w'];
242 $h = $wh['h'];
243
244 $tplData = array(
245 'x' => $this->x,
246 'y' => $this->y,
247 'w' => $w,
248 'h' => $h,
249 'scaleX' => ($w / $_w),
250 'scaleY' => ($h / $_h),
251 'tx' => $x,
252 'ty' => ($this->h - $y - $h),
253 'lty' => ($this->h - $y - $h) - ($this->h - $_h) * ($h / $_h)
254 );
255
256 $this->_out(sprintf('q %.4F 0 0 %.4F %.4F %.4F cm',
257 $tplData['scaleX'], $tplData['scaleY'], $tplData['tx'] * $this->k, $tplData['ty'] * $this->k)
258 ); // Translate
259 $this->_out(sprintf('%s%d Do Q', $this->tplPrefix, $tplIdx));
260
261 $this->lastUsedTemplateData = $tplData;
262
263 return array('w' => $w, 'h' => $h);
264 }
265
266 /**
267 * Get the calculated size of a template.
268 *
269 * If one size is given, this method calculates the other one.
270 *
271 * @param int $tplIdx A valid template-id
272 * @param int $w The width of the template
273 * @param int $h The height of the template
274 * @return array The height and width of the template (array('w' => ..., 'h' => ...))
275 */
276 public function getTemplateSize($tplIdx, $w = 0, $h = 0)
277 {
278 if (!isset($this->_tpls[$tplIdx]))
279 return false;
280
281 $tpl = $this->_tpls[$tplIdx];
282 $_w = $tpl['w'];
283 $_h = $tpl['h'];
284
285 if ($w == 0 && $h == 0) {
286 $w = $_w;
287 $h = $_h;
288 }
289
290 if ($w == 0)
291 $w = $h * $_w / $_h;
292 if($h == 0)
293 $h = $w * $_h / $_w;
294
295 return array("w" => $w, "h" => $h);
296 }
297
298 /**
299 * Sets the font used to print character strings.
300 *
301 * See FPDF/TCPDF documentation.
302 *
303 * @see http://fpdf.org/en/doc/setfont.htm
304 * @see http://www.tcpdf.org/doc/code/classTCPDF.html#afd56e360c43553830d543323e81bc045
305 */
306 public function SetFont($family, $style = '', $size = null, $fontfile = '', $subset = 'default', $out = true)
307 {
308 if (is_subclass_of($this, 'TCPDF')) {
309 $args = func_get_args();
310 return call_user_func_array(array($this, 'TCPDF::SetFont'), $args);
311 }
312
313 parent::SetFont($family, $style, $size);
314
315 $fontkey = $this->FontFamily . $this->FontStyle;
316
317 if ($this->_inTpl) {
318 $this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey];
319 } else {
320 $this->_res['page'][$this->page]['fonts'][$fontkey] =& $this->fonts[$fontkey];
321 }
322 }
323
324 /**
325 * Puts an image.
326 *
327 * See FPDF/TCPDF documentation.
328 *
329 * @see http://fpdf.org/en/doc/image.htm
330 * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a714c2bee7d6b39d4d6d304540c761352
331 */
332 public function Image(
333 $file, $x = '', $y = '', $w = 0, $h = 0, $type = '', $link = '', $align = '', $resize = false,
334 $dpi = 300, $palign = '', $ismask = false, $imgmask = false, $border = 0, $fitbox = false,
335 $hidden = false, $fitonpage = false, $alt = false, $altimgs = array()
336 )
337 {
338 if (is_subclass_of($this, 'TCPDF')) {
339 $args = func_get_args();
340 return call_user_func_array(array($this, 'TCPDF::Image'), $args);
341 }
342
343 $ret = parent::Image($file, $x, $y, $w, $h, $type, $link);
344 if ($this->_inTpl) {
345 $this->_res['tpl'][$this->tpl]['images'][$file] =& $this->images[$file];
346 } else {
347 $this->_res['page'][$this->page]['images'][$file] =& $this->images[$file];
348 }
349
350 return $ret;
351 }
352
353 /**
354 * Adds a new page to the document.
355 *
356 * See FPDF/TCPDF documentation.
357 *
358 * This method cannot be used if you'd started a template.
359 *
360 * @see http://fpdf.org/en/doc/addpage.htm
361 * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a5171e20b366b74523709d84c349c1ced
362 */
363 public function AddPage($orientation = '', $format = '', $keepmargins = false, $tocpage = false)
364 {
365 if (is_subclass_of($this, 'TCPDF')) {
366 $args = func_get_args();
367 return call_user_func_array(array($this, 'TCPDF::AddPage'), $args);
368 }
369
370 if ($this->_inTpl) {
371 throw new LogicException('Adding pages in templates is not possible!');
372 }
373
374 parent::AddPage($orientation, $format);
375 }
376
377 /**
378 * Puts a link on a rectangular area of the page.
379 *
380 * Overwritten because adding links in a template will not work.
381 *
382 * @see http://fpdf.org/en/doc/link.htm
383 * @see http://www.tcpdf.org/doc/code/classTCPDF.html#ab87bf1826384fbfe30eb499d42f1d994
384 */
385 public function Link($x, $y, $w, $h, $link, $spaces = 0)
386 {
387 if (is_subclass_of($this, 'TCPDF')) {
388 $args = func_get_args();
389 return call_user_func_array(array($this, 'TCPDF::Link'), $args);
390 }
391
392 if ($this->_inTpl) {
393 throw new LogicException('Using links in templates is not posible!');
394 }
395
396 parent::Link($x, $y, $w, $h, $link);
397 }
398
399 /**
400 * Creates a new internal link and returns its identifier.
401 *
402 * Overwritten because adding links in a template will not work.
403 *
404 * @see http://fpdf.org/en/doc/addlink.htm
405 * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a749522038ed7786c3e1701435dcb891e
406 */
407 public function AddLink()
408 {
409 if (is_subclass_of($this, 'TCPDF')) {
410 $args = func_get_args();
411 return call_user_func_array(array($this, 'TCPDF::AddLink'), $args);
412 }
413
414 if ($this->_inTpl) {
415 throw new LogicException('Adding links in templates is not possible!');
416 }
417
418 return parent::AddLink();
419 }
420
421 /**
422 * Defines the page and position a link points to.
423 *
424 * Overwritten because adding links in a template will not work.
425 *
426 * @see http://fpdf.org/en/doc/setlink.htm
427 * @see http://www.tcpdf.org/doc/code/classTCPDF.html#ace5be60e7857953ea5e2b89cb90df0ae
428 */
429 public function SetLink($link, $y = 0, $page = -1)
430 {
431 if (is_subclass_of($this, 'TCPDF')) {
432 $args = func_get_args();
433 return call_user_func_array(array($this, 'TCPDF::SetLink'), $args);
434 }
435
436 if ($this->_inTpl) {
437 throw new LogicException('Setting links in templates is not possible!');
438 }
439
440 parent::SetLink($link, $y, $page);
441 }
442
443 /**
444 * Writes the form XObjects to the PDF document.
445 */
446 protected function _putformxobjects()
447 {
448 $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
449 reset($this->_tpls);
450
451 foreach($this->_tpls AS $tplIdx => $tpl) {
452 $this->_newobj();
453 $this->_tpls[$tplIdx]['n'] = $this->n;
454 $this->_out('<<'.$filter.'/Type /XObject');
455 $this->_out('/Subtype /Form');
456 $this->_out('/FormType 1');
457 $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',
458 // llx
459 $tpl['x'] * $this->k,
460 // lly
461 -$tpl['y'] * $this->k,
462 // urx
463 ($tpl['w'] + $tpl['x']) * $this->k,
464 // ury
465 ($tpl['h'] - $tpl['y']) * $this->k
466 ));
467
468 if ($tpl['x'] != 0 || $tpl['y'] != 0) {
469 $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]',
470 -$tpl['x'] * $this->k * 2, $tpl['y'] * $this->k * 2
471 ));
472 }
473
474 $this->_out('/Resources ');
475 $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
476
477 if (isset($this->_res['tpl'][$tplIdx])) {
478 $res = $this->_res['tpl'][$tplIdx];
479 if (isset($res['fonts']) && count($res['fonts'])) {
480 $this->_out('/Font <<');
481
482 foreach($res['fonts'] as $font) {
483 $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
484 }
485
486 $this->_out('>>');
487 }
488
489 if(isset($res['images']) || isset($res['tpls'])) {
490 $this->_out('/XObject <<');
491
492 if (isset($res['images'])) {
493 foreach($res['images'] as $image)
494 $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
495 }
496
497 if (isset($res['tpls'])) {
498 foreach($res['tpls'] as $i => $_tpl)
499 $this->_out($this->tplPrefix . $i . ' ' . $_tpl['n'] . ' 0 R');
500 }
501
502 $this->_out('>>');
503 }
504 }
505
506 $this->_out('>>');
507
508 $buffer = ($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
509 $this->_out('/Length ' . strlen($buffer) . ' >>');
510 $this->_putstream($buffer);
511 $this->_out('endobj');
512 }
513 }
514
515 /**
516 * Output images.
517 *
518 * Overwritten to add {@link _putformxobjects()} after _putimages().
519 */
520 public function _putimages()
521 {
522 parent::_putimages();
523 $this->_putformxobjects();
524 }
525
526 /**
527 * Writes the references of XObject resources to the document.
528 *
529 * Overwritten to add the the templates to the XObject resource dictionary.
530 */
531 public function _putxobjectdict()
532 {
533 parent::_putxobjectdict();
534
535 foreach($this->_tpls as $tplIdx => $tpl) {
536 $this->_out(sprintf('%s%d %d 0 R', $this->tplPrefix, $tplIdx, $tpl['n']));
537 }
538 }
539
540 /**
541 * Writes bytes to the resulting document.
542 *
543 * Overwritten to delegate the data to the template buffer.
544 *
545 * @param string $s
546 */
547 public function _out($s)
548 {
549 if ($this->state == 2 && $this->_inTpl) {
550 $this->_tpls[$this->tpl]['buffer'] .= $s . "\n";
551 } else {
552 parent::_out($s);
553 }
554 }
555 }