3 // FPDI - Version 1.5.4
5 // Copyright 2004-2015 Setasign - Jan Slabon
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
20 if (!class_exists('fpdi_bridge')) {
21 require_once('fpdi_bridge.php');
27 class FPDF_TPL extends fpdi_bridge
30 * Array of template data
34 protected $_tpls = array();
48 protected $_inTpl = false;
51 * Name prefix of templates used in Resources dictionary
53 * @var string A String defining the Prefix used as Template-Object-Names. Have to begin with an /
55 public $tplPrefix = "/TPL";
58 * Resources used by templates and pages
62 protected $_res = array();
65 * Last used template data
69 public $lastUsedTemplateData = array();
74 * This method starts a template. You can give own coordinates to build an own sized
75 * template. Pay attention, that the margins are adapted to the new template size.
76 * If you want to write outside the template, for example to build a clipped template,
77 * you have to set the margins and "cursor"-position manual after beginTemplate()-call.
79 * If no parameter is given, the template uses the current page-size.
80 * The method returns an id of the current template. This id is used later for using this template.
81 * Warning: A created template is saved in the resulting PDF at all events. Also if you don't use it after creation!
83 * @param int $x The x-coordinate given in user-unit
84 * @param int $y The y-coordinate given in user-unit
85 * @param int $w The width given in user-unit
86 * @param int $h The height given in user-unit
87 * @return int The id of new created template
88 * @throws LogicException
90 public function beginTemplate($x = null, $y = null, $w = null, $h = null)
92 if (is_subclass_of($this, 'TCPDF')) {
93 throw new LogicException('This method is only usable with FPDF. Use TCPDF methods startTemplate() instead.');
96 if ($this->page <= 0) {
97 throw new LogicException("You have to add at least a page first!");
111 $tpl =& $this->_tpls[$this->tpl];
115 'o_AutoPageBreak' => $this->AutoPageBreak,
116 'o_bMargin' => $this->bMargin,
117 'o_tMargin' => $this->tMargin,
118 'o_lMargin' => $this->lMargin,
119 'o_rMargin' => $this->rMargin,
122 'o_FontFamily' => $this->FontFamily,
123 'o_FontStyle' => $this->FontStyle,
124 'o_FontSizePt' => $this->FontSizePt,
125 'o_FontSize' => $this->FontSize,
133 $this->SetAutoPageBreak(false);
135 // Define own high and width to calculate correct positions
139 $this->_inTpl = true;
140 $this->SetXY($x + $this->lMargin, $y + $this->tMargin);
141 $this->SetRightMargin($this->w - $w + $this->rMargin);
143 if ($this->CurrentFont) {
144 $fontKey = $this->FontFamily . $this->FontStyle;
146 $this->_res['tpl'][$this->tpl]['fonts'][$fontKey] =& $this->fonts[$fontKey];
147 $this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
157 * This method ends a template and reset initiated variables collected in {@link beginTemplate()}.
159 * @return int|boolean If a template is opened, the id is returned. If not a false is returned.
161 public function endTemplate()
163 if (is_subclass_of($this, 'TCPDF')) {
164 $args = func_get_args();
165 return call_user_func_array(array($this, 'TCPDF::endTemplate'), $args);
169 $this->_inTpl = false;
170 $tpl = $this->_tpls[$this->tpl];
171 $this->SetXY($tpl['o_x'], $tpl['o_y']);
172 $this->tMargin = $tpl['o_tMargin'];
173 $this->lMargin = $tpl['o_lMargin'];
174 $this->rMargin = $tpl['o_rMargin'];
175 $this->h = $tpl['o_h'];
176 $this->w = $tpl['o_w'];
177 $this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']);
179 $this->FontFamily = $tpl['o_FontFamily'];
180 $this->FontStyle = $tpl['o_FontStyle'];
181 $this->FontSizePt = $tpl['o_FontSizePt'];
182 $this->FontSize = $tpl['o_FontSize'];
184 $fontKey = $this->FontFamily . $this->FontStyle;
186 $this->CurrentFont =& $this->fonts[$fontKey];
195 * Use a template in current page or other template.
197 * You can use a template in a page or in another template.
198 * You can give the used template a new size.
199 * All parameters are optional. The width or height is calculated automatically
200 * if one is given. If no parameter is given the origin size as defined in
201 * {@link beginTemplate()} method is used.
203 * The calculated or used width and height are returned as an array.
205 * @param int $tplIdx A valid template-id
206 * @param int $x The x-position
207 * @param int $y The y-position
208 * @param int $w The new width of the template
209 * @param int $h The new height of the template
210 * @return array The height and width of the template (array('w' => ..., 'h' => ...))
211 * @throws LogicException|InvalidArgumentException
213 public function useTemplate($tplIdx, $x = null, $y = null, $w = 0, $h = 0)
215 if ($this->page <= 0) {
216 throw new LogicException('You have to add at least a page first!');
219 if (!isset($this->_tpls[$tplIdx])) {
220 throw new InvalidArgumentException('Template does not exist!');
224 $this->_res['tpl'][$this->tpl]['tpls'][$tplIdx] =& $this->_tpls[$tplIdx];
227 $tpl = $this->_tpls[$tplIdx];
242 $wh = $this->getTemplateSize($tplIdx, $w, $h);
251 'scaleX' => ($w / $_w),
252 'scaleY' => ($h / $_h),
254 'ty' => ($this->h - $y - $h),
255 'lty' => ($this->h - $y - $h) - ($this->h - $_h) * ($h / $_h)
258 $this->_out(sprintf('q %.4F 0 0 %.4F %.4F %.4F cm',
259 $tplData['scaleX'], $tplData['scaleY'], $tplData['tx'] * $this->k, $tplData['ty'] * $this->k)
261 $this->_out(sprintf('%s%d Do Q', $this->tplPrefix, $tplIdx));
263 $this->lastUsedTemplateData = $tplData;
265 return array('w' => $w, 'h' => $h);
269 * Get the calculated size of a template.
271 * If one size is given, this method calculates the other one.
273 * @param int $tplIdx A valid template-id
274 * @param int $w The width of the template
275 * @param int $h The height of the template
276 * @return array The height and width of the template (array('w' => ..., 'h' => ...))
278 public function getTemplateSize($tplIdx, $w = 0, $h = 0)
280 if (!isset($this->_tpls[$tplIdx]))
283 $tpl = $this->_tpls[$tplIdx];
287 if ($w == 0 && $h == 0) {
297 return array("w" => $w, "h" => $h);
301 * Sets the font used to print character strings.
303 * See FPDF/TCPDF documentation.
305 * @see http://fpdf.org/en/doc/setfont.htm
306 * @see http://www.tcpdf.org/doc/code/classTCPDF.html#afd56e360c43553830d543323e81bc045
308 public function SetFont($family, $style = '', $size = null, $fontfile = '', $subset = 'default', $out = true)
310 if (is_subclass_of($this, 'TCPDF')) {
311 $args = func_get_args();
312 return call_user_func_array(array($this, 'TCPDF::SetFont'), $args);
315 parent::SetFont($family, $style, $size);
317 $fontkey = $this->FontFamily . $this->FontStyle;
320 $this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey];
322 $this->_res['page'][$this->page]['fonts'][$fontkey] =& $this->fonts[$fontkey];
329 * See FPDF/TCPDF documentation.
331 * @see http://fpdf.org/en/doc/image.htm
332 * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a714c2bee7d6b39d4d6d304540c761352
334 public function Image(
335 $file, $x = '', $y = '', $w = 0, $h = 0, $type = '', $link = '', $align = '', $resize = false,
336 $dpi = 300, $palign = '', $ismask = false, $imgmask = false, $border = 0, $fitbox = false,
337 $hidden = false, $fitonpage = false, $alt = false, $altimgs = array()
340 if (is_subclass_of($this, 'TCPDF')) {
341 $args = func_get_args();
342 return call_user_func_array(array($this, 'TCPDF::Image'), $args);
345 $ret = parent::Image($file, $x, $y, $w, $h, $type, $link);
347 $this->_res['tpl'][$this->tpl]['images'][$file] =& $this->images[$file];
349 $this->_res['page'][$this->page]['images'][$file] =& $this->images[$file];
356 * Adds a new page to the document.
358 * See FPDF/TCPDF documentation.
360 * This method cannot be used if you'd started a template.
362 * @see http://fpdf.org/en/doc/addpage.htm
363 * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a5171e20b366b74523709d84c349c1ced
365 public function AddPage($orientation = '', $format = '', $keepmargins = false, $tocpage = false)
367 if (is_subclass_of($this, 'TCPDF')) {
368 $args = func_get_args();
369 return call_user_func_array(array($this, 'TCPDF::AddPage'), $args);
373 throw new LogicException('Adding pages in templates is not possible!');
376 parent::AddPage($orientation, $format);
380 * Puts a link on a rectangular area of the page.
382 * Overwritten because adding links in a template will not work.
384 * @see http://fpdf.org/en/doc/link.htm
385 * @see http://www.tcpdf.org/doc/code/classTCPDF.html#ab87bf1826384fbfe30eb499d42f1d994
387 public function Link($x, $y, $w, $h, $link, $spaces = 0)
389 if (is_subclass_of($this, 'TCPDF')) {
390 $args = func_get_args();
391 return call_user_func_array(array($this, 'TCPDF::Link'), $args);
395 throw new LogicException('Using links in templates is not posible!');
398 parent::Link($x, $y, $w, $h, $link);
402 * Creates a new internal link and returns its identifier.
404 * Overwritten because adding links in a template will not work.
406 * @see http://fpdf.org/en/doc/addlink.htm
407 * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a749522038ed7786c3e1701435dcb891e
409 public function AddLink()
411 if (is_subclass_of($this, 'TCPDF')) {
412 $args = func_get_args();
413 return call_user_func_array(array($this, 'TCPDF::AddLink'), $args);
417 throw new LogicException('Adding links in templates is not possible!');
420 return parent::AddLink();
424 * Defines the page and position a link points to.
426 * Overwritten because adding links in a template will not work.
428 * @see http://fpdf.org/en/doc/setlink.htm
429 * @see http://www.tcpdf.org/doc/code/classTCPDF.html#ace5be60e7857953ea5e2b89cb90df0ae
431 public function SetLink($link, $y = 0, $page = -1)
433 if (is_subclass_of($this, 'TCPDF')) {
434 $args = func_get_args();
435 return call_user_func_array(array($this, 'TCPDF::SetLink'), $args);
439 throw new LogicException('Setting links in templates is not possible!');
442 parent::SetLink($link, $y, $page);
446 * Writes the form XObjects to the PDF document.
448 protected function _putformxobjects()
450 $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
453 foreach($this->_tpls AS $tplIdx => $tpl) {
455 $this->_tpls[$tplIdx]['n'] = $this->n;
456 $this->_out('<<'.$filter.'/Type /XObject');
457 $this->_out('/Subtype /Form');
458 $this->_out('/FormType 1');
459 $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',
461 $tpl['x'] * $this->k,
463 -$tpl['y'] * $this->k,
465 ($tpl['w'] + $tpl['x']) * $this->k,
467 ($tpl['h'] - $tpl['y']) * $this->k
470 if ($tpl['x'] != 0 || $tpl['y'] != 0) {
471 $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]',
472 -$tpl['x'] * $this->k * 2, $tpl['y'] * $this->k * 2
476 $this->_out('/Resources ');
477 $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
479 if (isset($this->_res['tpl'][$tplIdx])) {
480 $res = $this->_res['tpl'][$tplIdx];
481 if (isset($res['fonts']) && count($res['fonts'])) {
482 $this->_out('/Font <<');
484 foreach($res['fonts'] as $font) {
485 $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
491 if(isset($res['images']) || isset($res['tpls'])) {
492 $this->_out('/XObject <<');
494 if (isset($res['images'])) {
495 foreach($res['images'] as $image)
496 $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
499 if (isset($res['tpls'])) {
500 foreach($res['tpls'] as $i => $_tpl)
501 $this->_out($this->tplPrefix . $i . ' ' . $_tpl['n'] . ' 0 R');
510 $buffer = ($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
511 $this->_out('/Length ' . strlen($buffer) . ' >>');
512 $this->_putstream($buffer);
513 $this->_out('endobj');
520 * Overwritten to add {@link _putformxobjects()} after _putimages().
522 public function _putimages()
524 parent::_putimages();
525 $this->_putformxobjects();
529 * Writes the references of XObject resources to the document.
531 * Overwritten to add the the templates to the XObject resource dictionary.
533 public function _putxobjectdict()
535 parent::_putxobjectdict();
537 foreach($this->_tpls as $tplIdx => $tpl) {
538 $this->_out(sprintf('%s%d %d 0 R', $this->tplPrefix, $tplIdx, $tpl['n']));
543 * Writes bytes to the resulting document.
545 * Overwritten to delegate the data to the template buffer.
549 public function _out($s)
551 if ($this->state == 2 && $this->_inTpl) {
552 $this->_tpls[$this->tpl]['buffer'] .= $s . "\n";