GetX(); $y_start=$this->GetY(); $fontPT_start=$this->FontSizePt; // //-----------------------------------\ // Parameter validation, defaults // $w if ($this->empty_string($w) || $w <= 0 || !is_numeric($w)) if ($this->rtl) $w = $x_start - $this->lMargin; else $w = $this->w - $this->rMargin - $x_start; // $h if ($h <=0) { $h=99999999; // Trigger for internal calculated of $h $valign = 'T'; // The only sensible value } // Padding $padL = $padLmin = $padR = $padRmin = $this->cMargin; $padT = $padTmin = $padB = $padBmin = $this->cMargin/2; if (isset($pad)) { if (!is_string($pad) && is_numeric($pad)) $padL = $padT = $padR = $padB = $pad; else { $pad_arr=explode(',',$pad); if (isset($pad_arr[0]) && is_numeric($pad_arr[0])) $padL=$pad_arr[0]; if (isset($pad_arr[1]) && is_numeric($pad_arr[1])) $padT=$pad_arr[1]; if (isset($pad_arr[2]) && is_numeric($pad_arr[2])) $padR=$pad_arr[2]; if (isset($pad_arr[3]) && is_numeric($pad_arr[3])) $padB=$pad_arr[3]; } } // if ($pad) // tabsize if (!is_numeric($tab) || $tab < 0 || $tab > $c_tab_max) $tab = $c_tab_dflt; $tab = floor($tab); // $fontmin if (!is_numeric($fontmin) || $fontmin<=0) $fontmin = $c_fontmin_dflt; $fontPT_try=$fontPT_start; $c_font_binaryS_cnt=0; // Set up $fit_arr to represent priority order of attempts to fit text. // The compromises are setup as being cumulative $fit_arr = array(); array_push($fit_arr,array('a',$fontPT_start,$padL,$padT,$padR,$padB)); // first try to fit with start fontsize if (!$fit) $fit=$c_fit_dflt; // default value; if (is_string($fit)) { $fit=strtolower($fit); for ($i=0; $i$padBmin) {$padB=($padB+$padBmin)/2; array_push($fit_arr,array('p',$fontPT_try,$padL,$padT,$padR,$padB)); $padB=$padBmin; array_push($fit_arr,array('p',$fontPT_try,$padL,$padT,$padR,$padB));} if ($padB>0) {$padB=0; array_push($fit_arr,array('p',$fontPT_try,$padL,$padT,$padR,$padB));} if ($padR>$padRmin) {$padR=($padR+$padRmin)/2; array_push($fit_arr,array('p',$fontPT_try,$padL,$padT,$padR,$padB)); $padR=$padRmin; array_push($fit_arr,array('p',$fontPT_try,$padL,$padT,$padR,$padB));} if ($padT>$padTmin) {$padT=($padT+$padTmin)/2; array_push($fit_arr,array('p',$fontPT_try,$padL,$padT,$padR,$padB)); $padT=$padTmin; array_push($fit_arr,array('p',$fontPT_try,$padL,$padT,$padR,$padB));} if ($padT>0) {$padT=0; array_push($fit_arr,array('p',$fontPT_try,$padL,$padT,$padR,$padB));} if ($padL>$padLmin) {$padL=($padL+$padLmin)/2; array_push($fit_arr,array('p',$fontPT_try,$padL,$padT,$padR,$padB)); $padL=$padLmin; array_push($fit_arr,array('p',$fontPT_try,$padL,$padT,$padR,$padB));} } // 'p' if ($fit[$i]=='f' && !array_search('f',$fit_arr)) { // search for best fit fontsize array_push($fit_arr,array('f',$fontPT_try,$padL,$padT,$padR,$padB)); $fontPTbinarySmax=$fontPT_try; $fontPT_try=$fontPTbinarySmin=$fontmin; $c_font_binaryS_cnt=$c_font_binaryS_cnt_max; } // 'f' if ($fit[$i]=='w' && !array_search('w',$fit_arr)) array_push($fit_arr,array('w',$fontPT_try,$padL,$padT,$padR,$padB)); } // loop } // ($fit) //-----------------------------------/ // $txt_try = $this->removeSHY($txt).' '; // Shy depreciated from TCPDF. Added space simplifies word break processing algorithm. $txt_try = $txt_try.' '; $txt_try = str_replace('\n', "\n", $txt_try); // line feed character, not sure of reason why this step is necessary $txt_try = str_replace('\t', "\t", $txt_try); // tab character, not sure of reason why this step is necessary // $solved=false; $safety=25; $last_FontSize_solved = false; $final_font_try = false; $fittype_w_tried = false; // //-----------------------------------\ // Loop through attempts to fit the text in prescribed priority order. No output at this stage while (!$solved && // Continue if not solved count($fit_arr)>0 && // Continue if there are more fit attepts still queued $safety>0) { // stop unintended runaway looping // $safety--; // Iterpret $fit_arr $fit_arr_try = $fit_arr[0]; $fittype_try = $fit_arr_try[0]; $fontPT_try = $fit_arr_try[1]; $padLtry = $fit_arr_try[2]; $padTtry = $fit_arr_try[3]; $padRtry = $fit_arr_try[4]; $padBtry = $fit_arr_try[5]; // // For fit 'f' a binary search is undertaken to find the largest fontsize between the current fontsize and the $fontmin parameter for which all the text fits in the cell. // The algorithm always iterates $c_font_binaryS_cnt_max times. If the last execution of the search was a success then this is used and no further font searching. // If it is not then the most recent successful binary search attempt is recalculated. // If no solution then the $fontmin fontSize is tried since this is not part of the binary search. if ($fittype_try == 'f') { if ($final_font_try) { if ($last_FontSize_solved) $fontPT_try = $last_FontSize_solved; else $fontPT_try = $fontmin; array_shift($fit_arr); // for fit='f' remove entry from fit array only once all necessary fabricated iterations are completed } if ($c_font_binaryS_cnt > 0) { if ($c_font_binaryS_cnt!=$c_font_binaryS_cnt_max && $line_cnt <= $line_cnt_max) $fontPTbinarySmin = $fontPT_try; else $fontPTbinarySmax = $fontPT_try; $fontPT_try = $fit_arr_try[1] = ($fontPTbinarySmax + $fontPTbinarySmin) / 2; $fit_arr[0] = $fit_arr_try; $c_font_binaryS_cnt--; } } else array_shift($fit_arr); // when fit!='f' remove fit_arr entry immediately since no additional iterations are required // $this->SetFontSize($fontPT_try); // Set fontsize for this iteration $line_height = $this->FontSize * $this->cell_height_ratio; // Calculate the line height related to the fontsize $text_block_width = $w - $padLtry - $padRtry; // Calculate the dimension of the text block $text_block_height = $h - $padTtry - $padBtry; $line_cnt_max = floor($text_block_height / $line_height); // calc how many whole lines can fit into the text block // if ($fittype_try == 's') $txt_try = preg_replace('/\s+/', ' ', $txt_try); // remove whitespace which includes tabs and newlines if ($fittype_try == 'w') $fittype_w_tried = true; // ensures that once a word split is attempted it is also applied for lower priority fit attempts // $line_cnt=1; $char=''; $char_w=0; $word=''; $word_w=0; $line_w=0; $line_arr = array(); $line_arr[1]=''; $undisplayed=''; $word_unsolved = false; // //-----------------------------------\\ // Loop through each character within the supplied text for ($i=0; $i<=(strlen($txt_try)-1); $i++) { // $char_prev = $char; $char_w_prev = $char_w; // $char_c = ord($txt_try[$i]); $char = $this->unichr($char_c); $char_w = $this->GetCharWidth($char_c); if ($char == ' ' || $char_c == 9 || $char_c == 10) { // 9 = \t tab, 10 = \n newline if ($word != ' ') { // found a complete word // // If words fits on current line then add it to the current line if (($line_w + $word_w) <= $text_block_width) { $line_arr[$line_cnt] .= $word; $line_w+=$word_w; // // Word does not fit on current line and word can fit on the next line. } else if ($word_w <= $text_block_width) { $line_cnt++; $line_arr[$line_cnt] = $word; $line_w=$word_w; } $word=''; $word_w=0; } // space following a space if ($line_arr[$line_cnt]) { // retain multiple blanks if not at start of line $line_arr[$line_cnt].=$char; $line_w+=$char_w; } } else { // current character is a not a (space, \n, \t) if (($line_w + $word_w + $char_w) > $text_block_width && $fittype_w_tried) { // word extends over max line length and in word break mode if (strlen($word) != 0) { $line_arr[$line_cnt] .= substr($word,0,strlen($word)-1).'-'; // replace the last line letter with a - $word=$char_prev; $word_w=$char_w_prev; // replaced letter goes on next line } $line_cnt++; $line_arr[$line_cnt] = ''; $line_w=0; } else if (($word_w + $char_w) > $text_block_width) $word_unsolved = true; // word cannot be split and is longer than a line. $word.=$char; $word_w+=$char_w; } // nonspace if ($char_c == 9) { // tab - replace special tab character with $tab number of spaces $line_arr[$line_cnt] .= str_repeat(chr(32),$tab); $line_w += $this->GetCharWidth(32) * $tab; } // tab if ($char_c == 10) { // Force a new line when requested $line_cnt++; $line_arr[$line_cnt] = ''; $line_w=0; } // newline if ($line_cnt > $line_cnt_max) { $undisplayed=$line_arr[$line_cnt].$word.substr($txt_try,$i+1); // return text not fitting within cell break; // no point continuing, the text cannot be displayed } } // for //-----------------------------------// if ($fittype_try == 'f') { // font size binary search if ($line_cnt <= $line_cnt_max && !$word_unsolved) $last_FontSize_solved = $fontPT_try; // record the last successful font size. The second last binary search may the the last successful size if ($c_font_binaryS_cnt <= 0) // last binary search attempt where font size was adjusted if ($line_cnt <= $line_cnt_max && !$word_unsolved) $solved=true; // if successful a final font try is not required else $final_font_try = true; // the last binary search was unsuccessful, try either the last successful font fit or if no fit then the minimum font size permitted. } else if ($line_cnt <= $line_cnt_max && !$word_unsolved) $solved=true; // non font fit attempts. Set to solved if all text fitted and no long word issues. } // while // //-----------------------------------/ if ($h==99999999) $h = $padTtry + $line_cnt * $line_height + $padBtry; // $h was not supplied, calculate minimum height required // $this->checkPageBreak($h); // // Border and Fill $style=''; if ($border) $style='D'; if ($fill) $style.='F'; if ($style) $this->Rect($x_start,$y_start,$w,$h,$style); // // Vertical Alignment $text_block_height_spare = $text_block_height - min($line_cnt,$line_cnt_max) * $line_height; $text_block_gap_top = 0; $line_gap = 0; switch ($valign) { case 'T': break; case 'B': $text_block_gap_top = $text_block_height_spare; break; case 'J': $line_gap = $text_block_height_spare / ($line_cnt-1); break; default: $text_block_gap_top = $text_block_height_spare / 2; // 'M' is default } // Position for first line output $write_x = $x_start + $padLtry-$padLmin; $write_y = $y_start + $padTtry + $text_block_gap_top; // //-----------------------------------/ // Output lines for ($line=1; $line<=min($line_cnt,$line_cnt_max); $line++) { $this->x = $write_x; $this->y = $write_y; $this->_out($this->getCellCode(($text_block_width+$padLmin+$padRmin),$line_height, rtrim($line_arr[$line]), 0, 2, $halign, 0, $link, 0, true)); $write_y += $line_height + $line_gap; } // for loop through lines //-----------------------------------/ // // Set new current position $this->x = $x_start; switch ($ln) { case 1: if ($this->rtl) $this->x = $this->w - $this->rMargin; else $this->x = $this->lMargin; case 2: $this->y = $y_start + $h; break; default: if ($this->rtl) $this->x = $x_start - $w; else $this->x = $x_start + $w; $this->y = $y_start; } // $this->SetFontSize($fontPT_start); // reset font size back to the original value at function start if (!$solved) return $undisplayed; // return any undisplayed text. } // class CellFitText } // class ?>