blob: d61a24758b5f420174df192fbed864243a2950a3 [file] [log] [blame]
Copybara botbe50d492023-11-30 00:16:42 +01001<?php
2 /*********************************************************************
3 * exFPDF extend FPDF v1.81 *
4 * *
5 * Version: 2.2 *
6 * Date: 12-10-2017 *
7 * Author: Dan Machado *
8 * Require FPDF v1.81, formatedstring v1.0 *
9 **********************************************************************/
10 include 'formatedstring.php';
11 class exFPDF extends FPDF{
12
13 public function PageBreak(){
14 return $this->PageBreakTrigger;
15 }
16
17 public function current_font($c){
18 if($c=='family'){
19 return $this->FontFamily;
20 }
21 elseif($c=='style'){
22 return $this->FontStyle;
23 }
24 elseif($c=='size'){
25 return $this->FontSizePt;
26 }
27 }
28
29 public function get_color($c){
30 if($c=='fill'){
31 return $this->FillColor;
32 }
33 elseif($c=='text'){
34 return $this->TextColor;
35 }
36 }
37
38 public function get_page_width(){
39 return $this->w;
40 }
41
42 public function get_margin($c){
43 if($c=='l'){
44 return $this->lMargin;
45 }
46 elseif($c=='r'){
47 return $this->rMargin;
48 }
49 elseif($c=='t'){
50 return $this->tMargin;
51 }
52 }
53
54 public function get_linewidth(){
55 return $this->LineWidth;
56 }
57
58 public function get_orientation(){
59 return $this->CurOrientation;
60 }
61
62 public function get_page_size()
63 {
64 return $this->CurPageSize;
65 }
66
67 public function get_rotation()
68 {
69 return $this->CurRotation;
70 }
71
72 public function get_scale_factor()
73 {
74 return $this->k;
75 }
76
77 static private $hex=array('0'=>0,'1'=>1,'2'=>2,'3'=>3,'4'=>4,'5'=>5,'6'=>6,'7'=>7,'8'=>8,'9'=>9,
78 'A'=>10,'B'=>11,'C'=>12,'D'=>13,'E'=>14,'F'=>15);
79
80 public function is_rgb($str){
81 $a=true;
82 $tmp=explode(',', trim($str, ','));
83 foreach($tmp as $color){
84 if(!is_numeric($color) || $color<0 || $color>255){
85 $a=false;
86 break;
87 }
88 }
89 return $a;
90 }
91
92 public function is_hex($str){
93 $a=true;
94 $str=strtoupper($str);
95 $n=strlen($str);
96 if(($n==7 || $n==4) && $str[0]=='#'){
97 for($i=1; $i<$n; $i++){
98 if(!isset(self::$hex[$str[$i]])){
99 $a=false;
100 break;
101 }
102 }
103 }
104 else{
105 $a=false;
106 }
107 return $a;
108 }
109
110 public function hextodec($str){
111 $result=array();
112 $str=strtoupper(substr($str,1));
113 $n=strlen($str);
114 for($i=0; $i<3; $i++){
115 if($n==6){
116 $result[$i]=self::$hex[$str[2*$i]]*16+self::$hex[$str[2*$i+1]];
117 }
118 else{
119 $result[$i]=self::$hex[$str[$i]]*16+self::$hex[$str[$i]];
120 }
121 }
122 return $result;
123 }
124 static private $options=array('F'=>'', 'T'=>'', 'D'=>'');
125
126 public function resetColor($str, $p='F'){
127 if(isset(self::$options[$p]) && self::$options[$p]!=$str){
128 self::$options[$p]=$str;
129 $array=array();
130 if($this->is_hex($str)){
131 $array=$this->hextodec($str);
132 }
133 elseif($this->is_rgb($str)){
134 $array=explode(',', trim($str, ','));
135 for($i=0; $i<3; $i++){
136 if(!isset($array[$i])){
137 $array[$i]=0;
138 }
139 }
140 }
141 else{
142 $array=array(null, null, null);
143 $i=0;
144 $tmp=explode(' ', $str);
145 foreach($tmp as $c){
146 if(is_numeric($c)){
147 $array[$i]=$c*256;
148 $i++;
149 }
150 }
151 }
152 if($p=='T'){
153 $this->SetTextColor($array[0],$array[1],$array[2]);
154 }
155 elseif($p=='D'){
156 $this->SetDrawColor($array[0],$array[1], $array[2]);
157 }
158 elseif($p=='F'){
159 $this->SetFillColor($array[0],$array[1],$array[2]);
160 }
161 }
162 }
163 static private $font_def='';
164
165 public function resetFont($font_family, $font_style, $font_size){
166 if(self::$font_def!=$font_family .'-' . $font_style . '-' .$font_size){
167 self::$font_def=$font_family .'-' . $font_style . '-' .$font_size;
168 $this->SetFont($font_family, $font_style, $font_size);
169 }
170 }
171
172 public function resetStaticData(){
173 self::$font_def='';
174 self::$options=array('F'=>'', 'T'=>'', 'D'=>'');
175 }
176
177 /***********************************************************************
178 *
179 * Based on FPDF method SetFont
180 *
181 ************************************************************************/
182
183 private function &FontData($family, $style, $size){
184 if($family=='')
185 $family = $this->FontFamily;
186 else
187 $family = strtolower($family);
188 $style = strtoupper($style);
189 if(strpos($style,'U')!==false){
190 $this->underline = true;
191 $style = str_replace('U','',$style);
192 }
193 if($style=='IB')
194 $style = 'BI';
195 $fontkey = $family.$style;
196 if(!isset($this->fonts[$fontkey])){
197 if($family=='arial')
198 $family = 'helvetica';
199 if(in_array($family,$this->CoreFonts)){
200 if($family=='symbol' || $family=='zapfdingbats')
201 $style = '';
202 $fontkey = $family.$style;
203 if(!isset($this->fonts[$fontkey]))
204 $this->AddFont($family,$style);
205 }
206 else
207 $this->Error('Undefined font: '.$family.' '.$style);
208 }
209 $result['FontSize'] = $size/$this->k;
210 $result['CurrentFont']=&$this->fonts[$fontkey];
211 return $result;
212 }
213
214
215 private function setLines(&$fstring, $p, $q){
216 $parced_str=& $fstring->parced_str;
217 $lines=& $fstring->lines;
218 $linesmap=& $fstring->linesmap;
219 $cfty=$fstring->get_current_style($p);
220 $ffs=$cfty['font-family'] . $cfty['style'];
221 if(!isset($fstring->used_fonts[$ffs])){
222 $fstring->used_fonts[$ffs]=& $this->FontData($cfty['font-family'], $cfty['style'], $cfty['font-size']);
223 }
224 $cw=& $fstring->used_fonts[$ffs]['CurrentFont']['cw'];
225 $wmax = $fstring->width*1000*$this->k;
226 $j=count($lines)-1;
227 $k=strlen($lines[$j]);
228 if(!isset($linesmap[$j][0])) {
229 $linesmap[$j]=array($p,$p, 0);
230 }
231 $sl=$cw[' ']*$cfty['font-size'];
232 $x=$a=$linesmap[$j][2];
233 if($k>0){
234 $x+=$sl;
235 $lines[$j].=' ';
236 $linesmap[$j][2]+=$sl;
237 }
238 $u=$p;
239 $t='';
240 $l=$p+$q;
241 $ftmp='';
242 for($i=$p; $i<$l; $i++){
243 if($ftmp!=$ffs){
244 $cfty=$fstring->get_current_style($i);
245 $ffs=$cfty['font-family'] . $cfty['style'];
246 if(!isset($fstring->used_fonts[$ffs])){
247 $fstring->used_fonts[$ffs]=& $this->FontData($cfty['font-family'], $cfty['style'], $cfty['font-size']);
248 }
249 $cw=& $fstring->used_fonts[$ffs]['CurrentFont']['cw'];
250 $ftmp=$ffs;
251 }
252 $x+=$cw[$parced_str[$i]]*$cfty['font-size'];
253 if($x>$wmax){
254 if($a>0){
255 $t=substr($parced_str,$p, $i-$p);
256 $lines[$j]=substr($lines[$j],0,$k);
257 $linesmap[$j][1]=$p-1;
258 $linesmap[$j][2]=$a;
259 $x-=($a+$sl);
260 $a=0;
261 $u=$p;
262 }
263 else{
264 $x=$cw[$parced_str[$i]]*$cfty['font-size'];
265 $t='';
266 $u=$i;
267 }
268 $j++;
269 $lines[$j]=$t;
270 $linesmap[$j]=array();
271 $linesmap[$j][0]=$u;
272 $linesmap[$j][2]=0;
273 }
274 $lines[$j].=$parced_str[$i];
275 $linesmap[$j][1]=$i;
276 $linesmap[$j][2]=$x;
277 }
278 return;
279 }
280
281 public function &extMultiCell($font_family, $font_style, $font_size, $font_color, $w, $txt){
282 $result=array();
283 if($w==0){
284 return $result;
285 }
286 $current_font=array('font-family'=>$font_family, 'style'=>$font_style, 'font-size'=>$font_size, 'font-color'=>$font_color);
287 $fstring=new formatedString($txt, $w, $current_font);
288 $word='';
289 $p=0;
290 $i=0;
291 $n=strlen($fstring->parced_str);
292 while($i<$n){
293 $word.=$fstring->parced_str[$i];
294 if($fstring->parced_str[$i]=="\n" || $fstring->parced_str[$i]==' ' || $i==$n-1){
295 $word=trim($word);
296 $this->setLines($fstring, $p, strlen($word));
297 $p=$i+1;
298 $word='';
299 if($fstring->parced_str[$i]=="\n" && $i<$n-1){
300 $z=0;
301 $j=count($fstring->lines);
302 $fstring->lines[$j]='';
303 $fstring->linesmap[$j]=array();
304 }
305 }
306 $i++;
307 }
308 if($n==0){
309 return $result;
310 }
311 $n=count($fstring->lines);
312 for($i=0; $i<$n; $i++){
313 $result[$i]=$fstring->break_by_style($i);
314 }
315 return $result;
316 }
317
318 private function GetMixStringWidth($line){
319 $w = 0;
320 foreach($line['chunks'] as $i=>$chunk){
321 $t=0;
322 $cf=& $this->FontData($line['style'][$i]['font-family'], $line['style'][$i]['style'], $line['style'][$i]['font-size']);
323 $cw=& $cf['CurrentFont']['cw'];
324 $s=implode('', explode(' ',$chunk));
325 $l = strlen($s);
326 for($j=0;$j<$l;$j++){
327 $t+=$cw[$s[$j]];
328 }
329 $w+=$t*$line['style'][$i]['font-size'];
330 }
331 return $w;
332 }
333
334 public function CellBlock($w, $lh, &$lines, $align='J'){
335 if($w==0){
336 return;
337 }
338 $ctmp='';
339 $ftmp='';
340 foreach($lines as $i=>$line){
341 $k = $this->k;
342 if($this->y+$lh*$line['height']>$this->PageBreakTrigger){
343 break;
344 }
345 $dx=0;
346 $dw=0;
347 if($line['width']!=0){
348 if($align=='R'){
349 $dx = $w-$line['width']/($this->k*1000);
350 }
351 elseif($align=='C'){
352 $dx = ($w-$line['width']/($this->k*1000))/2;
353 }
354 if($align=='J'){
355 $tmp=explode(' ', implode('',$line['chunks']));
356 $ns=count($tmp);
357 if($ns>1){
358 $sx=implode('',$tmp);
359 $delta=$this->GetMixStringWidth($line)/($this->k*1000);
360 $dw=($w-$delta)*(1/($ns-1));
361 }
362 }
363 }
364 $xx=$this->x+$dx;
365 foreach($line['chunks'] as $tj=>$txt){
366 $this->resetFont($line['style'][$tj]['font-family'], $line['style'][$tj]['style'], $line['style'][$tj]['font-size']);
367 $this->resetColor($line['style'][$tj]['font-color'], 'T');
368 $y=$this->y+0.5*$lh*$line['height'] +0.3*$line['height']/$this->k;
369 if($dw){
370 $tmp=explode(' ', $txt);
371 foreach($tmp as $e=>$tt){
372 if($e>0){
373 $xx+=$dw;
374 if($tt==''){
375 continue;
376 }
377 }
378 $this->Text($xx, $y, $tt);
379 if($line['style'][$tj]['href']){
380 $yr=$this->y+0.5*($lh*$line['height']-$line['height']/$this->k);
381 $this->Link($xx, $yr, $this->GetStringWidth($txt),$line['height']/$this->k, $line['style'][$tj]['href']);
382 }
383 $xx+=$this->GetStringWidth($tt);
384 }
385 }
386 else{
387 $this->Text($xx, $y, $txt);
388 if($line['style'][$tj]['href']){
389 $yr=$this->y+0.5*($lh*$line['height']-$line['height']/$this->k);
390 $this->Link($xx, $yr, $this->GetStringWidth($txt),$line['height']/$this->k, $line['style'][$tj]['href']);
391 }
392 $xx+=$this->GetStringWidth($txt);
393 }
394 }
395 unset($lines[$i]);
396 $this->y += $lh*$line['height'];
397 }
398 }
399
400}
401?>