1. public function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false, $ln=1, $x='', $y='', $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0, $valign='T', $fitcell=false) {
  2. $prev_cell_margin = $this->cell_margin;
  3. $prev_cell_padding = $this->cell_padding;
  4. // adjust internal padding
  5. $this->adjustCellPadding($border);
  6. $mc_padding = $this->cell_padding;
  7. $mc_margin = $this->cell_margin;
  8. $this->cell_padding['T'] = 0;
  9. $this->cell_padding['B'] = 0;
  10. $this->setCellMargins(0, 0, 0, 0);
  11. if ($this->empty_string($this->lasth) OR $reseth) {
  12. // reset row height
  13. $this->resetLastH();
  14. }
  15. if (!$this->empty_string($y)) {
  16. $this->SetY($y);
  17. } else {
  18. $y = $this->GetY();
  19. }
  20. $resth = 0;
  21. if ((!$this->InFooter) AND (($y + $h + $mc_margin['T'] + $mc_margin['B']) > $this->PageBreakTrigger)) {
  22. // spit cell in more pages/columns
  23. $newh = $this->PageBreakTrigger - $y;
  24. $resth = $h - $newh; // cell to be printed on the next page/column
  25. $h = $newh;
  26. }
  27. // get current page number
  28. $startpage = $this->page;
  29. // get current column
  30. $startcolumn = $this->current_column;
  31. if (!$this->empty_string($x)) {
  32. $this->SetX($x);
  33. } else {
  34. $x = $this->GetX();
  35. }
  36. // check page for no-write regions and adapt page margins if necessary
  37. $this->checkPageRegions(0, $x, $y);
  38. // apply margins
  39. $oy = $y + $mc_margin['T'];
  40. if ($this->rtl) {
  41. $ox = $this->w - $x - $mc_margin['R'];
  42. } else {
  43. $ox = $x + $mc_margin['L'];
  44. }
  45. $this->x = $ox;
  46. $this->y = $oy;
  47. // set width
  48. if ($this->empty_string($w) OR ($w <= 0)) {
  49. if ($this->rtl) {
  50. $w = $this->x - $this->lMargin - $mc_margin['L'];
  51. } else {
  52. $w = $this->w - $this->x - $this->rMargin - $mc_margin['R'];
  53. }
  54. }
  55. // store original margin values
  56. $lMargin = $this->lMargin;
  57. $rMargin = $this->rMargin;
  58. if ($this->rtl) {
  59. $this->rMargin = $this->w - $this->x;
  60. $this->lMargin = $this->x - $w;
  61. } else {
  62. $this->lMargin = $this->x;
  63. $this->rMargin = $this->w - $this->x - $w;
  64. }
  65. if ($autopadding) {
  66. // add top padding
  67. $this->y += $mc_padding['T'];
  68. }
  69. if ($ishtml) { // ******* Write HTML text
  70. $this->writeHTML($txt, true, 0, $reseth, true, $align);
  71. $nl = 1;
  72. } else { // ******* Write simple text
  73. // vertical alignment
  74. if ($maxh > 0) {
  75. // get text height
  76. $text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border);
  77. if ($fitcell) {
  78. $prev_FontSizePt = $this->FontSizePt;
  79. // try to reduce font size to fit text on cell (use a quick search algorithm)
  80. $fmin = 1;
  81. $fmax = $this->FontSizePt;
  82. $prev_text_height = $text_height;
  83. $maxit = 100; // max number of iterations
  84. while ($maxit > 0) {
  85. $fmid = (($fmax + $fmin) / 2);
  86. $this->SetFontSize($fmid, false);
  87. $this->resetLastH();
  88. $text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border);
  89. if (($text_height == $maxh) OR (($text_height < $maxh) AND ($fmin >= ($fmax - 0.01)))) {
  90. break;
  91. } elseif ($text_height < $maxh) {
  92. $fmin = $fmid;
  93. } else {
  94. $fmax = $fmid;
  95. }
  96. --$maxit;
  97. }
  98. $this->SetFontSize($this->FontSizePt);
  99. }
  100. if ($text_height < $maxh) {
  101. if ($valign == 'M') {
  102. // text vertically centered
  103. $this->y += (($maxh - $text_height) / 2);
  104. } elseif ($valign == 'B') {
  105. // text vertically aligned on bottom
  106. $this->y += ($maxh - $text_height);
  107. }
  108. }
  109. }
  110. $nl = $this->Write($this->lasth, $txt, '', 0, $align, true, $stretch, false, true, $maxh, 0, $mc_margin);
  111. if ($fitcell) {
  112. // restore font size
  113. $this->SetFontSize($prev_FontSizePt);
  114. }
  115. }
  116. if ($autopadding) {
  117. // add bottom padding
  118. $this->y += $mc_padding['B'];
  119. }
  120. // Get end-of-text Y position
  121. $currentY = $this->y;
  122. // get latest page number
  123. $endpage = $this->page;
  124. if ($resth > 0) {
  125. $skip = ($endpage - $startpage);
  126. $tmpresth = $resth;
  127. while ($tmpresth > 0) {
  128. if ($skip <= 0) {
  129. // add a page (or trig AcceptPageBreak() for multicolumn mode)
  130. $this->checkPageBreak($this->PageBreakTrigger + 1);
  131. }
  132. if ($this->num_columns > 1) {
  133. $tmpresth -= ($this->h - $this->y - $this->bMargin);
  134. } else {
  135. $tmpresth -= ($this->h - $this->tMargin - $this->bMargin);
  136. }
  137. --$skip;
  138. }
  139. $currentY = $this->y;
  140. $endpage = $this->page;
  141. }
  142. // get latest column
  143. $endcolumn = $this->current_column;
  144. if ($this->num_columns == 0) {
  145. $this->num_columns = 1;
  146. }
  147. // get border modes
  148. $border_start = $this->getBorderMode($border, $position='start');
  149. $border_end = $this->getBorderMode($border, $position='end');
  150. $border_middle = $this->getBorderMode($border, $position='middle');
  151. // design borders around HTML cells.
  152. for ($page = $startpage; $page <= $endpage; ++$page) { // for each page
  153. $ccode = '';
  154. $this->setPage($page);
  155. if ($this->num_columns < 2) {
  156. // single-column mode
  157. $this->SetX($x);
  158. $this->y = $this->tMargin;
  159. }
  160. // account for margin changes
  161. if ($page > $startpage) {
  162. if (($this->rtl) AND ($this->pagedim[$page]['orm'] != $this->pagedim[$startpage]['orm'])) {
  163. $this->x -= ($this->pagedim[$page]['orm'] - $this->pagedim[$startpage]['orm']);
  164. } elseif ((!$this->rtl) AND ($this->pagedim[$page]['olm'] != $this->pagedim[$startpage]['olm'])) {
  165. $this->x += ($this->pagedim[$page]['olm'] - $this->pagedim[$startpage]['olm']);
  166. }
  167. }
  168. if ($startpage == $endpage) {
  169. // single page
  170. for ($column = $startcolumn; $column <= $endcolumn; ++$column) { // for each column
  171. $this->selectColumn($column);
  172. if ($this->rtl) {
  173. $this->x -= $mc_margin['R'];
  174. } else {
  175. $this->x += $mc_margin['L'];
  176. }
  177. if ($startcolumn == $endcolumn) { // single column
  178. $cborder = $border;
  179. $h = max($h, ($currentY - $oy));
  180. $this->y = $oy;
  181. } elseif ($column == $startcolumn) { // first column
  182. $cborder = $border_start;
  183. $this->y = $oy;
  184. $h = $this->h - $this->y - $this->bMargin;
  185. } elseif ($column == $endcolumn) { // end column
  186. $cborder = $border_end;
  187. $h = $currentY - $this->y;
  188. if ($resth > $h) {
  189. $h = $resth;
  190. }
  191. } else { // middle column
  192. $cborder = $border_middle;
  193. $h = $this->h - $this->y - $this->bMargin;
  194. $resth -= $h;
  195. }
  196. $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
  197. } // end for each column
  198. } elseif ($page == $startpage) { // first page
  199. for ($column = $startcolumn; $column < $this->num_columns; ++$column) { // for each column
  200. $this->selectColumn($column);
  201. if ($this->rtl) {
  202. $this->x -= $mc_margin['R'];
  203. } else {
  204. $this->x += $mc_margin['L'];
  205. }
  206. if ($column == $startcolumn) { // first column
  207. $cborder = $border_start;
  208. $this->y = $oy;
  209. $h = $this->h - $this->y - $this->bMargin;
  210. } else { // middle column
  211. $cborder = $border_middle;
  212. $h = $this->h - $this->y - $this->bMargin;
  213. $resth -= $h;
  214. }
  215. $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
  216. } // end for each column
  217. } elseif ($page == $endpage) { // last page
  218. for ($column = 0; $column <= $endcolumn; ++$column) { // for each column
  219. $this->selectColumn($column);
  220. if ($this->rtl) {
  221. $this->x -= $mc_margin['R'];
  222. } else {
  223. $this->x += $mc_margin['L'];
  224. }
  225. if ($column == $endcolumn) {
  226. // end column
  227. $cborder = $border_end;
  228. $h = $currentY - $this->y;
  229. if ($resth > $h) {
  230. $h = $resth;
  231. }
  232. } else {
  233. // middle column
  234. $cborder = $border_middle;
  235. $h = $this->h - $this->y - $this->bMargin;
  236. $resth -= $h;
  237. }
  238. $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
  239. } // end for each column
  240. } else { // middle page
  241. for ($column = 0; $column < $this->num_columns; ++$column) { // for each column
  242. $this->selectColumn($column);
  243. if ($this->rtl) {
  244. $this->x -= $mc_margin['R'];
  245. } else {
  246. $this->x += $mc_margin['L'];
  247. }
  248. $cborder = $border_middle;
  249. $h = $this->h - $this->y - $this->bMargin;
  250. $resth -= $h;
  251. $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
  252. } // end for each column
  253. }
  254. if ($cborder OR $fill) {
  255. // draw border and fill
  256. if ($this->inxobj) {
  257. // we are inside an XObject template
  258. if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) {
  259. $pagemarkkey = key($this->xobjects[$this->xobjid]['transfmrk']);
  260. $pagemark = &$this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey];
  261. } else {
  262. $pagemark = &$this->xobjects[$this->xobjid]['intmrk'];
  263. }
  264. $pagebuff = $this->xobjects[$this->xobjid]['outdata'];
  265. $pstart = substr($pagebuff, 0, $pagemark);
  266. $pend = substr($pagebuff, $pagemark);
  267. $this->xobjects[$this->xobjid]['outdata'] = $pstart.$ccode.$pend;
  268. $pagemark += strlen($ccode);
  269. } else {
  270. if (end($this->transfmrk[$this->page]) !== false) {
  271. $pagemarkkey = key($this->transfmrk[$this->page]);
  272. $pagemark = &$this->transfmrk[$this->page][$pagemarkkey];
  273. } elseif ($this->InFooter) {
  274. $pagemark = &$this->footerpos[$this->page];
  275. } else {
  276. $pagemark = &$this->intmrk[$this->page];
  277. }
  278. $pagebuff = $this->getPageBuffer($this->page);
  279. $pstart = substr($pagebuff, 0, $pagemark);
  280. $pend = substr($pagebuff, $pagemark);
  281. $this->setPageBuffer($this->page, $pstart.$ccode.$pend);
  282. $pagemark += strlen($ccode);
  283. }
  284. }
  285. } // end for each page
  286. // Get end-of-cell Y position
  287. $currentY = $this->GetY();
  288. // restore original margin values
  289. $this->SetLeftMargin($lMargin);
  290. $this->SetRightMargin($rMargin);
  291. if ($ln > 0) {
  292. //Go to the beginning of the next line
  293. $this->SetY($currentY + $mc_margin['B']);
  294. if ($ln == 2) {
  295. $this->SetX($x + $w + $mc_margin['L'] + $mc_margin['R']);
  296. }
  297. } else {
  298. // go left or right by case
  299. $this->setPage($startpage);
  300. $this->y = $y;
  301. $this->SetX($x + $w + $mc_margin['L'] + $mc_margin['R']);
  302. }
  303. $this->setContentMark();
  304. $this->cell_padding = $prev_cell_padding;
  305. $this->cell_margin = $prev_cell_margin;
  306. return $nl;
  307. }