fpdf_tpl.php 15 KB

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