|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace NFePHP\DA\Legacy\FPDF; |
|
4
|
|
|
|
|
5
|
|
|
/** |
|
6
|
|
|
* Classe origial adaptada para PHP 7.2 |
|
7
|
|
|
* @author Americo Belmiro de Souza Neto |
|
8
|
|
|
* @email [email protected] |
|
9
|
|
|
*/ |
|
10
|
|
|
|
|
11
|
|
|
class Fpdf1 |
|
12
|
|
|
{ |
|
13
|
|
|
const FPDF_VERSION = '1.6'; |
|
14
|
|
|
|
|
15
|
|
|
public $page; //current page number |
|
16
|
|
|
public $n; //current object number |
|
17
|
|
|
public $offsets; //array of object offsets |
|
18
|
|
|
public $buffer; //buffer holding in-memory PDF |
|
19
|
|
|
public $pages; //array containing pages |
|
20
|
|
|
public $state; //current document state |
|
21
|
|
|
public $compress; //compression flag |
|
22
|
|
|
public $k; //scale factor (number of points in user unit) |
|
23
|
|
|
public $defOrientation; //default orientation |
|
24
|
|
|
public $curOrientation; //current orientation |
|
25
|
|
|
public $pageFormats; //available page formats |
|
26
|
|
|
public $defPageFormat; //default page format |
|
27
|
|
|
public $curPageFormat; //current page format |
|
28
|
|
|
public $pageSizes; //array storing non-default page sizes |
|
29
|
|
|
public $wPt; |
|
30
|
|
|
public $hPt; //dimensions of current page in points |
|
31
|
|
|
public $w; |
|
32
|
|
|
public $h; //dimensions of current page in user unit |
|
33
|
|
|
public $lMargin; //left margin |
|
34
|
|
|
public $tMargin; //top margin |
|
35
|
|
|
public $rMargin; //right margin |
|
36
|
|
|
public $bMargin; //page break margin |
|
37
|
|
|
public $cMargin; //cell margin |
|
38
|
|
|
public $x; |
|
39
|
|
|
public $y; //current position in user unit |
|
40
|
|
|
public $lasth; //height of last printed cell |
|
41
|
|
|
public $lineWidth; //line width in user unit |
|
42
|
|
|
public $coreFonts; //array of standard font names |
|
43
|
|
|
public $fonts; //array of used fonts |
|
44
|
|
|
public $fontFiles; //array of font files |
|
45
|
|
|
public $diffs; //array of encoding differences |
|
46
|
|
|
public $fontFamily; //current font family |
|
47
|
|
|
public $fontStyle; //current font style |
|
48
|
|
|
public $underline; //underlining flag |
|
49
|
|
|
public $currentFont; //current font info |
|
50
|
|
|
public $fontSizePt; //current font size in points |
|
51
|
|
|
public $fontSize; //current font size in user unit |
|
52
|
|
|
public $drawColor; //commands for drawing color |
|
53
|
|
|
public $fillColor; //commands for filling color |
|
54
|
|
|
public $textColor; //commands for text color |
|
55
|
|
|
public $colorFlag; //indicates whether fill and text colors are different |
|
56
|
|
|
public $ws; //word spacing |
|
57
|
|
|
public $images; //array of used images |
|
58
|
|
|
public $PageLinks; //array of links in pages |
|
59
|
|
|
public $links; //array of internal links |
|
60
|
|
|
public $autoPageBreak; //automatic page breaking |
|
61
|
|
|
public $pageBreakTrigger; //threshold used to trigger page breaks |
|
62
|
|
|
public $inHeader; //flag set when processing header |
|
63
|
|
|
public $inFooter; //flag set when processing footer |
|
64
|
|
|
public $zoomMode; //zoom display mode |
|
65
|
|
|
public $layoutMode; //layout display mode |
|
66
|
|
|
public $title; //title |
|
67
|
|
|
public $subject; //subject |
|
68
|
|
|
public $author; //author |
|
69
|
|
|
public $keywords; //keywords |
|
70
|
|
|
public $creator; //creator |
|
71
|
|
|
public $aliasNbPages; //alias for total number of pages |
|
72
|
|
|
public $pdfVersion; //PDF version number |
|
73
|
|
|
|
|
74
|
|
|
public function __construct($orientation = 'P', $unit = 'mm', $format = 'A4') |
|
75
|
|
|
{ |
|
76
|
|
|
//Some checks |
|
77
|
|
|
$this->dochecks(); |
|
78
|
|
|
//Initialization of properties |
|
79
|
|
|
$this->page = 0; |
|
80
|
|
|
$this->n = 2; |
|
81
|
|
|
$this->buffer = ''; |
|
82
|
|
|
$this->pages = array(); |
|
83
|
|
|
$this->pageSizes = array(); |
|
84
|
|
|
$this->state = 0; |
|
85
|
|
|
$this->fonts = array(); |
|
86
|
|
|
$this->fontFiles = array(); |
|
87
|
|
|
$this->diffs = array(); |
|
88
|
|
|
$this->images = array(); |
|
89
|
|
|
$this->links = array(); |
|
90
|
|
|
$this->inHeader = false; |
|
91
|
|
|
$this->inFooter = false; |
|
92
|
|
|
$this->lasth = 0; |
|
93
|
|
|
$this->fontFamily = ''; |
|
94
|
|
|
$this->fontStyle = ''; |
|
95
|
|
|
$this->fontSizePt = 12; |
|
96
|
|
|
$this->underline = false; |
|
97
|
|
|
$this->drawColor = '0 G'; |
|
98
|
|
|
$this->fillColor = '0 g'; |
|
99
|
|
|
$this->textColor = '0 g'; |
|
100
|
|
|
$this->colorFlag = false; |
|
101
|
|
|
$this->ws = 0; |
|
102
|
|
|
//Standard fonts |
|
103
|
|
|
$this->coreFonts = [ |
|
104
|
|
|
'courier'=>'Courier', |
|
105
|
|
|
'courierB'=>'Courier-Bold', |
|
106
|
|
|
'courierI'=>'Courier-Oblique', |
|
107
|
|
|
'courierBI'=>'Courier-BoldOblique', |
|
108
|
|
|
'helvetica'=>'Helvetica', |
|
109
|
|
|
'helveticaB'=>'Helvetica-Bold', |
|
110
|
|
|
'helveticaI'=>'Helvetica-Oblique', |
|
111
|
|
|
'helveticaBI'=>'Helvetica-BoldOblique', |
|
112
|
|
|
'times'=>'Times-Roman', |
|
113
|
|
|
'timesB'=>'Times-Bold', |
|
114
|
|
|
'timesI'=>'Times-Italic', |
|
115
|
|
|
'timesBI'=>'Times-BoldItalic', |
|
116
|
|
|
'symbol'=>'Symbol', |
|
117
|
|
|
'zapfdingbats'=>'ZapfDingbats' |
|
118
|
|
|
]; |
|
119
|
|
|
//Scale factor |
|
120
|
|
|
if ($unit == 'pt') { |
|
121
|
|
|
$this->k = 1; |
|
122
|
|
|
} elseif ($unit == 'mm') { |
|
123
|
|
|
$this->k = 72/25.4; |
|
124
|
|
|
} elseif ($unit == 'cm') { |
|
125
|
|
|
$this->k = 72/2.54; |
|
126
|
|
|
} elseif ($unit == 'in') { |
|
127
|
|
|
$this->k = 72; |
|
128
|
|
|
} else { |
|
129
|
|
|
$this->error('Incorrect unit: '.$unit); |
|
130
|
|
|
} |
|
131
|
|
|
//Page format |
|
132
|
|
|
$this->pageFormats = array( |
|
133
|
|
|
'a3' => array(841.89,1190.55), |
|
134
|
|
|
'a4' => array(595.28,841.89), |
|
135
|
|
|
'a5' => array(420.94,595.28), |
|
136
|
|
|
'letter' => array(612,792), |
|
137
|
|
|
'legal' => array(612,1008) |
|
138
|
|
|
); |
|
139
|
|
|
if (is_string($format)) { |
|
140
|
|
|
$format = $this->getpageformat($format); |
|
141
|
|
|
} |
|
142
|
|
|
$this->defPageFormat = $format; |
|
143
|
|
|
$this->curPageFormat = $format; |
|
144
|
|
|
//Page orientation |
|
145
|
|
|
$orientation = strtolower($orientation); |
|
146
|
|
|
if ($orientation == 'p' || $orientation == 'portrait') { |
|
147
|
|
|
$this->defOrientation='P'; |
|
148
|
|
|
$this->w = $this->defPageFormat[0]; |
|
149
|
|
|
$this->h = $this->defPageFormat[1]; |
|
150
|
|
|
} elseif ($orientation == 'l' || $orientation == 'landscape') { |
|
151
|
|
|
$this->defOrientation = 'L'; |
|
152
|
|
|
$this->w = $this->defPageFormat[1]; |
|
153
|
|
|
$this->h = $this->defPageFormat[0]; |
|
154
|
|
|
} else { |
|
155
|
|
|
$this->error('Incorrect orientation: '.$orientation); |
|
156
|
|
|
} |
|
157
|
|
|
$this->curOrientation = $this->defOrientation; |
|
158
|
|
|
$this->wPt = $this->w*$this->k; |
|
159
|
|
|
$this->hPt = $this->h*$this->k; |
|
160
|
|
|
//Page margins (1 cm) |
|
161
|
|
|
$margin = 28.35/$this->k; |
|
162
|
|
|
$this->setMargins($margin, $margin); |
|
163
|
|
|
//Interior cell margin (1 mm) |
|
164
|
|
|
$this->cMargin = $margin/10; |
|
165
|
|
|
//Line width (0.2 mm) |
|
166
|
|
|
$this->lineWidth = .567/$this->k; |
|
167
|
|
|
//Automatic page break |
|
168
|
|
|
$this->setAutoPageBreak(true, 2*$margin); |
|
169
|
|
|
//Full width display mode |
|
170
|
|
|
$this->setDisplayMode('fullwidth'); |
|
171
|
|
|
//Enable compression |
|
172
|
|
|
$this->setCompression(true); |
|
173
|
|
|
//Set default PDF version number |
|
174
|
|
|
$this->pdfVersion='1.3'; |
|
175
|
|
|
} |
|
176
|
|
|
|
|
177
|
|
|
public function setMargins($left, $top, $right = null) |
|
178
|
|
|
{ |
|
179
|
|
|
//Set left, top and right margins |
|
180
|
|
|
$this->lMargin = $left; |
|
181
|
|
|
$this->tMargin = $top; |
|
182
|
|
|
if ($right === null) { |
|
183
|
|
|
$right = $left; |
|
184
|
|
|
} |
|
185
|
|
|
$this->rMargin=$right; |
|
186
|
|
|
} |
|
187
|
|
|
|
|
188
|
|
|
public function setLeftMargin($margin) |
|
189
|
|
|
{ |
|
190
|
|
|
//Set left margin |
|
191
|
|
|
$this->lMargin = $margin; |
|
192
|
|
|
if ($this->page>0 && $this->x<$margin) { |
|
193
|
|
|
$this->x = $margin; |
|
194
|
|
|
} |
|
195
|
|
|
} |
|
196
|
|
|
|
|
197
|
|
|
public function setTopMargin($margin) |
|
198
|
|
|
{ |
|
199
|
|
|
//Set top margin |
|
200
|
|
|
$this->tMargin = $margin; |
|
201
|
|
|
} |
|
202
|
|
|
|
|
203
|
|
|
public function setRightMargin($margin) |
|
204
|
|
|
{ |
|
205
|
|
|
//Set right margin |
|
206
|
|
|
$this->rMargin = $margin; |
|
207
|
|
|
} |
|
208
|
|
|
|
|
209
|
|
|
public function setAutoPageBreak($auto, $margin = 0) |
|
210
|
|
|
{ |
|
211
|
|
|
//Set auto page break mode and triggering margin |
|
212
|
|
|
$this->autoPageBreak = $auto; |
|
213
|
|
|
$this->bMargin = $margin; |
|
214
|
|
|
$this->pageBreakTrigger = $this->h-$margin; |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
public function setDisplayMode($zoom, $layout = 'continuous') |
|
218
|
|
|
{ |
|
219
|
|
|
//Set display mode in viewer |
|
220
|
|
|
if ($zoom=='fullpage' || $zoom=='fullwidth' || $zoom=='real' || $zoom=='default' || !is_string($zoom)) { |
|
221
|
|
|
$this->zoomMode = $zoom; |
|
222
|
|
|
} else { |
|
223
|
|
|
$this->error('Incorrect zoom display mode: '.$zoom); |
|
224
|
|
|
} |
|
225
|
|
|
if ($layout=='single' || $layout=='continuous' || $layout=='two' || $layout=='default') { |
|
226
|
|
|
$this->layoutMode = $layout; |
|
227
|
|
|
} else { |
|
228
|
|
|
$this->error('Incorrect layout display mode: '.$layout); |
|
229
|
|
|
} |
|
230
|
|
|
} |
|
231
|
|
|
|
|
232
|
|
|
public function setCompression($compress) |
|
233
|
|
|
{ |
|
234
|
|
|
//Set page compression |
|
235
|
|
|
if (function_exists('gzcompress')) { |
|
236
|
|
|
$this->compress = $compress; |
|
237
|
|
|
} else { |
|
238
|
|
|
$this->compress = false; |
|
239
|
|
|
} |
|
240
|
|
|
} |
|
241
|
|
|
|
|
242
|
|
|
public function setTitle($title, $isUTF8 = false) |
|
243
|
|
|
{ |
|
244
|
|
|
//Title of document |
|
245
|
|
|
if ($isUTF8) { |
|
246
|
|
|
$title = $this->utf8Toutf16($title); |
|
247
|
|
|
} |
|
248
|
|
|
$this->title = $title; |
|
249
|
|
|
} |
|
250
|
|
|
|
|
251
|
|
|
public function setSubject($subject, $isUTF8 = false) |
|
252
|
|
|
{ |
|
253
|
|
|
//Subject of document |
|
254
|
|
|
if ($isUTF8) { |
|
255
|
|
|
$subject = $this->utf8Toutf16($subject); |
|
256
|
|
|
} |
|
257
|
|
|
$this->subject = $subject; |
|
258
|
|
|
} |
|
259
|
|
|
|
|
260
|
|
|
public function setAuthor($author, $isUTF8 = false) |
|
261
|
|
|
{ |
|
262
|
|
|
//Author of document |
|
263
|
|
|
if ($isUTF8) { |
|
264
|
|
|
$author = $this->utf8Toutf16($author); |
|
265
|
|
|
} |
|
266
|
|
|
$this->author=$author; |
|
267
|
|
|
} |
|
268
|
|
|
|
|
269
|
|
|
public function setKeywords($keywords, $isUTF8 = false) |
|
270
|
|
|
{ |
|
271
|
|
|
//Keywords of document |
|
272
|
|
|
if ($isUTF8) { |
|
273
|
|
|
$keywords = $this->utf8Toutf16($keywords); |
|
274
|
|
|
} |
|
275
|
|
|
$this->keywords = $keywords; |
|
276
|
|
|
} |
|
277
|
|
|
|
|
278
|
|
|
public function setCreator($creator, $isUTF8 = false) |
|
279
|
|
|
{ |
|
280
|
|
|
//Creator of document |
|
281
|
|
|
if ($isUTF8) { |
|
282
|
|
|
$creator = $this->utf8Toutf16($creator); |
|
283
|
|
|
} |
|
284
|
|
|
$this->creator = $creator; |
|
285
|
|
|
} |
|
286
|
|
|
|
|
287
|
|
|
public function aliasNbPages($alias = '{nb}') |
|
288
|
|
|
{ |
|
289
|
|
|
//Define an alias for total number of pages |
|
290
|
|
|
$this->aliasNbPages=$alias; |
|
291
|
|
|
} |
|
292
|
|
|
|
|
293
|
|
|
public function error($msg) |
|
294
|
|
|
{ |
|
295
|
|
|
throw new \Exception($msg); |
|
296
|
|
|
} |
|
297
|
|
|
|
|
298
|
|
|
public function open() |
|
299
|
|
|
{ |
|
300
|
|
|
//Begin document |
|
301
|
|
|
$this->state = 1; |
|
302
|
|
|
} |
|
303
|
|
|
|
|
304
|
|
|
public function close() |
|
305
|
|
|
{ |
|
306
|
|
|
//Terminate document |
|
307
|
|
|
if ($this->state == 3) { |
|
308
|
|
|
return; |
|
309
|
|
|
} |
|
310
|
|
|
if ($this->page == 0) { |
|
311
|
|
|
$this->addPage(); |
|
312
|
|
|
} |
|
313
|
|
|
//Page footer |
|
314
|
|
|
$this->inFooter = true; |
|
315
|
|
|
$this->footer(); |
|
316
|
|
|
$this->inFooter = false; |
|
317
|
|
|
//Close page |
|
318
|
|
|
$this->endPage(); |
|
319
|
|
|
//Close document |
|
320
|
|
|
$this->endDoc(); |
|
321
|
|
|
} |
|
322
|
|
|
|
|
323
|
|
|
public function addPage($orientation = '', $format = '') |
|
324
|
|
|
{ |
|
325
|
|
|
//Start a new page |
|
326
|
|
|
if ($this->state==0) { |
|
327
|
|
|
$this->open(); |
|
328
|
|
|
} |
|
329
|
|
|
$family = $this->fontFamily; |
|
330
|
|
|
$style = $this->fontStyle.($this->underline ? 'U' : ''); |
|
331
|
|
|
$size = $this->fontSizePt; |
|
332
|
|
|
$lw = $this->lineWidth; |
|
333
|
|
|
$dc = $this->drawColor; |
|
334
|
|
|
$fc = $this->fillColor; |
|
335
|
|
|
$tc = $this->textColor; |
|
336
|
|
|
$cf = $this->colorFlag; |
|
337
|
|
|
if ($this->page > 0) { |
|
338
|
|
|
//Page footer |
|
339
|
|
|
$this->inFooter = true; |
|
340
|
|
|
$this->footer(); |
|
341
|
|
|
$this->inFooter = false; |
|
342
|
|
|
//Close page |
|
343
|
|
|
$this->endPage(); |
|
344
|
|
|
} |
|
345
|
|
|
//Start new page |
|
346
|
|
|
$this->beginPage($orientation, $format); |
|
347
|
|
|
//Set line cap style to square |
|
348
|
|
|
$this->out('2 J'); |
|
349
|
|
|
//Set line width |
|
350
|
|
|
$this->lineWidth = $lw; |
|
351
|
|
|
$this->out(sprintf('%.2F w', $lw*$this->k)); |
|
352
|
|
|
//Set font |
|
353
|
|
|
if ($family) { |
|
354
|
|
|
$this->setFont($family, $style, $size); |
|
355
|
|
|
} |
|
356
|
|
|
//Set colors |
|
357
|
|
|
$this->drawColor = $dc; |
|
358
|
|
|
if ($dc!='0 G') { |
|
359
|
|
|
$this->out($dc); |
|
360
|
|
|
} |
|
361
|
|
|
$this->fillColor = $fc; |
|
362
|
|
|
if ($fc != '0 g') { |
|
363
|
|
|
$this->out($fc); |
|
364
|
|
|
} |
|
365
|
|
|
$this->textColor = $tc; |
|
366
|
|
|
$this->colorFlag = $cf; |
|
367
|
|
|
//Page header |
|
368
|
|
|
$this->inHeader = true; |
|
369
|
|
|
$this->Header(); |
|
370
|
|
|
$this->inHeader = false; |
|
371
|
|
|
//Restore line width |
|
372
|
|
|
if ($this->lineWidth != $lw) { |
|
373
|
|
|
$this->lineWidth = $lw; |
|
374
|
|
|
$this->out(sprintf('%.2F w', $lw*$this->k)); |
|
375
|
|
|
} |
|
376
|
|
|
//Restore font |
|
377
|
|
|
if ($family) { |
|
378
|
|
|
$this->setFont($family, $style, $size); |
|
379
|
|
|
} |
|
380
|
|
|
//Restore colors |
|
381
|
|
|
if ($this->drawColor != $dc) { |
|
382
|
|
|
$this->drawColor = $dc; |
|
383
|
|
|
$this->out($dc); |
|
384
|
|
|
} |
|
385
|
|
|
if ($this->fillColor != $fc) { |
|
386
|
|
|
$this->fillColor = $fc; |
|
387
|
|
|
$this->out($fc); |
|
388
|
|
|
} |
|
389
|
|
|
$this->textColor = $tc; |
|
390
|
|
|
$this->colorFlag = $cf; |
|
391
|
|
|
} |
|
392
|
|
|
|
|
393
|
|
|
public function header() |
|
394
|
|
|
{ |
|
395
|
|
|
//To be implemented in your own inherited class |
|
396
|
|
|
} |
|
397
|
|
|
|
|
398
|
|
|
public function footer() |
|
399
|
|
|
{ |
|
400
|
|
|
//To be implemented in your own inherited class |
|
401
|
|
|
} |
|
402
|
|
|
|
|
403
|
|
|
public function pageNo() |
|
404
|
|
|
{ |
|
405
|
|
|
//Get current page number |
|
406
|
|
|
return $this->page; |
|
407
|
|
|
} |
|
408
|
|
|
|
|
409
|
|
|
public function setDrawColor($r, $g = null, $b = null) |
|
410
|
|
|
{ |
|
411
|
|
|
//Set color for all stroking operations |
|
412
|
|
|
if (($r==0 && $g==0 && $b==0) || $g===null) { |
|
413
|
|
|
$this->drawColor = sprintf('%.3F G', $r/255); |
|
414
|
|
|
} else { |
|
415
|
|
|
$this->drawColor = sprintf('%.3F %.3F %.3F RG', $r/255, $g/255, $b/255); |
|
416
|
|
|
} |
|
417
|
|
|
if ($this->page > 0) { |
|
418
|
|
|
$this->out($this->drawColor); |
|
419
|
|
|
} |
|
420
|
|
|
} |
|
421
|
|
|
|
|
422
|
|
|
public function setFillColor($r, $g = null, $b = null) |
|
423
|
|
|
{ |
|
424
|
|
|
//Set color for all filling operations |
|
425
|
|
|
if (($r==0 && $g==0 && $b==0) || $g===null) { |
|
426
|
|
|
$this->fillColor = sprintf('%.3F g', $r/255); |
|
427
|
|
|
} else { |
|
428
|
|
|
$this->fillColor = sprintf('%.3F %.3F %.3F rg', $r/255, $g/255, $b/255); |
|
429
|
|
|
} |
|
430
|
|
|
$this->colorFlag = ($this->fillColor != $this->textColor); |
|
431
|
|
|
if ($this->page > 0) { |
|
432
|
|
|
$this->out($this->fillColor); |
|
433
|
|
|
} |
|
434
|
|
|
} |
|
435
|
|
|
|
|
436
|
|
|
public function settextColor($r, $g = null, $b = null) |
|
437
|
|
|
{ |
|
438
|
|
|
//Set color for text |
|
439
|
|
|
if (($r==0 && $g==0 && $b==0) || $g===null) { |
|
440
|
|
|
$this->textColor = sprintf('%.3F g', $r/255); |
|
441
|
|
|
} else { |
|
442
|
|
|
$this->textColor = sprintf('%.3F %.3F %.3F rg', $r/255, $g/255, $b/255); |
|
443
|
|
|
} |
|
444
|
|
|
$this->colorFlag = ($this->fillColor != $this->textColor); |
|
445
|
|
|
} |
|
446
|
|
|
|
|
447
|
|
|
public function getStringWidth($s) |
|
448
|
|
|
{ |
|
449
|
|
|
//Get width of a string in the current font |
|
450
|
|
|
$s = (string)$s; |
|
451
|
|
|
$cw =& $this->currentFont['cw']; |
|
452
|
|
|
$w = 0; |
|
453
|
|
|
$l = strlen($s); |
|
454
|
|
|
for ($i=0; $i<$l; $i++) { |
|
455
|
|
|
$w += $cw[$s[$i]]; |
|
456
|
|
|
} |
|
457
|
|
|
return $w*$this->fontSize/1000; |
|
458
|
|
|
} |
|
459
|
|
|
|
|
460
|
|
|
public function setLineWidth($width) |
|
461
|
|
|
{ |
|
462
|
|
|
//Set line width |
|
463
|
|
|
$this->lineWidth = $width; |
|
464
|
|
|
if ($this->page > 0) { |
|
465
|
|
|
$this->out(sprintf('%.2F w', $width*$this->k)); |
|
466
|
|
|
} |
|
467
|
|
|
} |
|
468
|
|
|
|
|
469
|
|
|
public function line($x1, $y1, $x2, $y2) |
|
470
|
|
|
{ |
|
471
|
|
|
//Draw a line |
|
472
|
|
|
$this->out( |
|
473
|
|
|
sprintf( |
|
474
|
|
|
'%.2F %.2F m %.2F %.2F l S', |
|
475
|
|
|
$x1*$this->k, |
|
476
|
|
|
($this->h-$y1)*$this->k, |
|
477
|
|
|
$x2*$this->k, |
|
478
|
|
|
($this->h-$y2)*$this->k |
|
479
|
|
|
) |
|
480
|
|
|
); |
|
481
|
|
|
} |
|
482
|
|
|
|
|
483
|
|
|
public function rect($x, $y, $w, $h, $style = '') |
|
484
|
|
|
{ |
|
485
|
|
|
//Draw a rectangle |
|
486
|
|
|
if ($style == 'F') { |
|
487
|
|
|
$op = 'f'; |
|
488
|
|
|
} elseif ($style == 'FD' || $style == 'DF') { |
|
489
|
|
|
$op = 'B'; |
|
490
|
|
|
} else { |
|
491
|
|
|
$op = 'S'; |
|
492
|
|
|
} |
|
493
|
|
|
$this->out( |
|
494
|
|
|
sprintf( |
|
495
|
|
|
'%.2F %.2F %.2F %.2F re %s', |
|
496
|
|
|
$x*$this->k, |
|
497
|
|
|
($this->h-$y)*$this->k, |
|
498
|
|
|
$w*$this->k, |
|
499
|
|
|
-$h*$this->k, |
|
500
|
|
|
$op |
|
501
|
|
|
) |
|
502
|
|
|
); |
|
503
|
|
|
} |
|
504
|
|
|
|
|
505
|
|
|
public function addFont($family, $style = '', $file = '') |
|
506
|
|
|
{ |
|
507
|
|
|
//Add a TrueType or Type1 font |
|
508
|
|
|
$family = strtolower($family); |
|
509
|
|
|
if ($file == '') { |
|
510
|
|
|
$file = str_replace(' ', '', $family).strtolower($style).'.php'; |
|
511
|
|
|
} |
|
512
|
|
|
if ($family=='arial') { |
|
513
|
|
|
$family='helvetica'; |
|
514
|
|
|
} |
|
515
|
|
|
$style = strtoupper($style); |
|
516
|
|
|
if ($style == 'IB') { |
|
517
|
|
|
$style = 'BI'; |
|
518
|
|
|
} |
|
519
|
|
|
$fontkey = $family.$style; |
|
520
|
|
|
if (isset($this->fonts[$fontkey])) { |
|
521
|
|
|
return; |
|
522
|
|
|
} |
|
523
|
|
|
include $this->getFontPath().$file; |
|
524
|
|
|
if (!isset($name)) { |
|
|
|
|
|
|
525
|
|
|
$this->error('Could not include font definition file'); |
|
526
|
|
|
} |
|
527
|
|
|
$i = count($this->fonts)+1; |
|
528
|
|
|
$this->fonts[$fontkey] = [ |
|
529
|
|
|
'i'=>$i, |
|
530
|
|
|
'type'=>$type, |
|
|
|
|
|
|
531
|
|
|
'name'=>$name, |
|
|
|
|
|
|
532
|
|
|
'desc'=>$desc, |
|
|
|
|
|
|
533
|
|
|
'up'=>$up, |
|
|
|
|
|
|
534
|
|
|
'ut'=>$ut, |
|
|
|
|
|
|
535
|
|
|
'cw'=>$cw, |
|
|
|
|
|
|
536
|
|
|
'enc'=>$enc, |
|
|
|
|
|
|
537
|
|
|
'file'=>$file |
|
538
|
|
|
]; |
|
539
|
|
|
if ($diff) { |
|
540
|
|
|
//Search existing encodings |
|
541
|
|
|
$d = 0; |
|
542
|
|
|
$nb = count($this->diffs); |
|
543
|
|
|
for ($i=1; $i<=$nb; $i++) { |
|
544
|
|
|
if ($this->diffs[$i] == $diff) { |
|
|
|
|
|
|
545
|
|
|
$d = $i; |
|
546
|
|
|
break; |
|
547
|
|
|
} |
|
548
|
|
|
} |
|
549
|
|
|
if ($d == 0) { |
|
550
|
|
|
$d = $nb+1; |
|
551
|
|
|
$this->diffs[$d] = $diff; |
|
552
|
|
|
} |
|
553
|
|
|
$this->fonts[$fontkey]['diff'] = $d; |
|
554
|
|
|
} |
|
555
|
|
|
if ($file) { |
|
556
|
|
|
if ($type=='TrueType') { |
|
557
|
|
|
$this->fontFiles[$file] = array('length1'=>$originalsize); |
|
|
|
|
|
|
558
|
|
|
} else { |
|
559
|
|
|
$this->fontFiles[$file] = array('length1'=>$size1, 'length2'=>$size2); |
|
|
|
|
|
|
560
|
|
|
} |
|
561
|
|
|
} |
|
562
|
|
|
} |
|
563
|
|
|
|
|
564
|
|
|
public function setFont($family, $style = '', $size = 0) |
|
565
|
|
|
{ |
|
566
|
|
|
//Select a font; size given in points |
|
567
|
|
|
global $fpdf_charwidths; |
|
|
|
|
|
|
568
|
|
|
$family = strtolower($family); |
|
569
|
|
|
if ($family == '') { |
|
570
|
|
|
$family = $this->fontFamily; |
|
571
|
|
|
} |
|
572
|
|
|
if ($family == 'arial') { |
|
573
|
|
|
$family = 'helvetica'; |
|
574
|
|
|
} elseif ($family == 'symbol' || $family == 'zapfdingbats') { |
|
575
|
|
|
$style = ''; |
|
576
|
|
|
} |
|
577
|
|
|
$style = strtoupper($style); |
|
578
|
|
|
if (strpos($style, 'U') !== false) { |
|
579
|
|
|
$this->underline = true; |
|
580
|
|
|
$style = str_replace('U', '', $style); |
|
581
|
|
|
} else { |
|
582
|
|
|
$this->underline = false; |
|
583
|
|
|
} |
|
584
|
|
|
if ($style == 'IB') { |
|
585
|
|
|
$style = 'BI'; |
|
586
|
|
|
} |
|
587
|
|
|
if ($size == 0) { |
|
588
|
|
|
$size = $this->fontSizePt; |
|
589
|
|
|
} |
|
590
|
|
|
//Test if font is already selected |
|
591
|
|
|
if ($this->fontFamily==$family && $this->fontStyle==$style && $this->fontSizePt==$size) { |
|
592
|
|
|
return; |
|
593
|
|
|
} |
|
594
|
|
|
//Test if used for the first time |
|
595
|
|
|
$fontkey = $family.$style; |
|
596
|
|
|
if (!isset($this->fonts[$fontkey])) { |
|
597
|
|
|
//Check if one of the standard fonts |
|
598
|
|
|
if (isset($this->coreFonts[$fontkey])) { |
|
599
|
|
|
if (!isset($fpdf_charwidths[$fontkey])) { |
|
600
|
|
|
//Load metric file |
|
601
|
|
|
$file=$family; |
|
602
|
|
|
if ($family=='times' || $family=='helvetica') { |
|
603
|
|
|
$file .= strtolower($style); |
|
604
|
|
|
} |
|
605
|
|
|
include $this->getFontPath().$file.'.php'; |
|
606
|
|
|
if (!isset($fpdf_charwidths[$fontkey])) { |
|
607
|
|
|
$this->error('Could not include font metric file'); |
|
608
|
|
|
} |
|
609
|
|
|
} |
|
610
|
|
|
$i = count($this->fonts)+1; |
|
611
|
|
|
$name = $this->coreFonts[$fontkey]; |
|
612
|
|
|
$cw = $fpdf_charwidths[$fontkey]; |
|
613
|
|
|
$this->fonts[$fontkey] = ['i'=>$i, 'type'=>'core', 'name'=>$name, 'up'=>-100, 'ut'=>50, 'cw'=>$cw]; |
|
614
|
|
|
} else { |
|
615
|
|
|
$this->error('Undefined font: '.$family.' '.$style); |
|
616
|
|
|
} |
|
617
|
|
|
} |
|
618
|
|
|
//Select it |
|
619
|
|
|
$this->fontFamily = $family; |
|
620
|
|
|
$this->fontStyle = $style; |
|
621
|
|
|
$this->fontSizePt = $size; |
|
622
|
|
|
$this->fontSize = $size/$this->k; |
|
623
|
|
|
$this->currentFont =& $this->fonts[$fontkey]; |
|
624
|
|
|
if ($this->page > 0) { |
|
625
|
|
|
$this->out(sprintf('BT /F%d %.2F Tf ET', $this->currentFont['i'], $this->fontSizePt)); |
|
626
|
|
|
} |
|
627
|
|
|
} |
|
628
|
|
|
|
|
629
|
|
|
public function setFontSize($size) |
|
630
|
|
|
{ |
|
631
|
|
|
//Set font size in points |
|
632
|
|
|
if ($this->fontSizePt == $size) { |
|
633
|
|
|
return; |
|
634
|
|
|
} |
|
635
|
|
|
$this->fontSizePt = $size; |
|
636
|
|
|
$this->fontSize = $size/$this->k; |
|
637
|
|
|
if ($this->page > 0) { |
|
638
|
|
|
$this->out(sprintf('BT /F%d %.2F Tf ET', $this->currentFont['i'], $this->fontSizePt)); |
|
639
|
|
|
} |
|
640
|
|
|
} |
|
641
|
|
|
|
|
642
|
|
|
public function addlink() |
|
643
|
|
|
{ |
|
644
|
|
|
//Create a new internal link |
|
645
|
|
|
$n = count($this->links)+1; |
|
646
|
|
|
$this->links[$n] = array(0, 0); |
|
647
|
|
|
return $n; |
|
648
|
|
|
} |
|
649
|
|
|
|
|
650
|
|
|
public function setlink($link, $y = 0, $page = -1) |
|
651
|
|
|
{ |
|
652
|
|
|
//Set destination of internal link |
|
653
|
|
|
if ($y == -1) { |
|
654
|
|
|
$y = $this->y; |
|
655
|
|
|
} |
|
656
|
|
|
if ($page == -1) { |
|
657
|
|
|
$page = $this->page; |
|
658
|
|
|
} |
|
659
|
|
|
$this->links[$link] = array($page, $y); |
|
660
|
|
|
} |
|
661
|
|
|
|
|
662
|
|
|
public function link($x, $y, $w, $h, $link) |
|
663
|
|
|
{ |
|
664
|
|
|
//Put a link on the page |
|
665
|
|
|
$this->PageLinks[$this->page][] = [ |
|
666
|
|
|
$x*$this->k, |
|
667
|
|
|
$this->hPt-$y*$this->k, |
|
668
|
|
|
$w*$this->k, |
|
669
|
|
|
$h*$this->k, |
|
670
|
|
|
$link |
|
671
|
|
|
]; |
|
672
|
|
|
} |
|
673
|
|
|
|
|
674
|
|
|
public function text($x, $y, $txt) |
|
675
|
|
|
{ |
|
676
|
|
|
//Output a string |
|
677
|
|
|
$s = sprintf('BT %.2F %.2F Td (%s) Tj ET', $x*$this->k, ($this->h-$y)*$this->k, $this->escape($txt)); |
|
678
|
|
|
if ($this->underline && $txt!='') { |
|
679
|
|
|
$s .= ' '.$this->doUnderLine($x, $y, $txt); |
|
680
|
|
|
} |
|
681
|
|
|
if ($this->colorFlag) { |
|
682
|
|
|
$s = 'q '.$this->textColor.' '.$s.' Q'; |
|
683
|
|
|
} |
|
684
|
|
|
$this->out($s); |
|
685
|
|
|
} |
|
686
|
|
|
|
|
687
|
|
|
public function acceptPageBreak() |
|
688
|
|
|
{ |
|
689
|
|
|
//Accept automatic page break or not |
|
690
|
|
|
return $this->autoPageBreak; |
|
691
|
|
|
} |
|
692
|
|
|
|
|
693
|
|
|
public function cell($w, $h = 0, $txt = '', $border = 0, $ln = 0, $align = '', $fill = false, $link = '') |
|
694
|
|
|
{ |
|
695
|
|
|
//Output a cell |
|
696
|
|
|
$k = $this->k; |
|
697
|
|
|
if ($this->y+$h > $this->PageBreakTrigger |
|
|
|
|
|
|
698
|
|
|
&& !$this->InHeader |
|
|
|
|
|
|
699
|
|
|
&& !$this->InFooter |
|
|
|
|
|
|
700
|
|
|
&& $this->acceptPageBreak() |
|
701
|
|
|
) { |
|
702
|
|
|
//Automatic page break |
|
703
|
|
|
$x = $this->x; |
|
704
|
|
|
$ws = $this->ws; |
|
705
|
|
|
if ($ws > 0) { |
|
706
|
|
|
$this->ws = 0; |
|
707
|
|
|
$this->out('0 Tw'); |
|
708
|
|
|
} |
|
709
|
|
|
$this->addPage($this->curOrientation, $this->curPageFormat); |
|
|
|
|
|
|
710
|
|
|
$this->x = $x; |
|
711
|
|
|
if ($ws > 0) { |
|
712
|
|
|
$this->ws = $ws; |
|
713
|
|
|
$this->out(sprintf('%.3F Tw', $ws*$k)); |
|
714
|
|
|
} |
|
715
|
|
|
} |
|
716
|
|
|
if ($w == 0) { |
|
717
|
|
|
$w = $this->w-$this->rMargin-$this->x; |
|
718
|
|
|
} |
|
719
|
|
|
$s=''; |
|
720
|
|
|
if ($fill || $border==1) { |
|
721
|
|
|
if ($fill) { |
|
722
|
|
|
$op=($border==1) ? 'B' : 'f'; |
|
723
|
|
|
} else { |
|
724
|
|
|
$op='S'; |
|
725
|
|
|
} |
|
726
|
|
|
$s=sprintf('%.2F %.2F %.2F %.2F re %s ', $this->x*$k, ($this->h-$this->y)*$k, $w*$k, -$h*$k, $op); |
|
727
|
|
|
} |
|
728
|
|
|
if (is_string($border)) { |
|
729
|
|
|
$x = $this->x; |
|
730
|
|
|
$y = $this->y; |
|
731
|
|
|
if (strpos($border, 'L') !== false) { |
|
732
|
|
|
$s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $x*$k, ($this->h-$y)*$k, $x*$k, ($this->h-($y+$h))*$k); |
|
733
|
|
|
} |
|
734
|
|
|
if (strpos($border, 'T') !== false) { |
|
735
|
|
|
$s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $x*$k, ($this->h-$y)*$k, ($x+$w)*$k, ($this->h-$y)*$k); |
|
736
|
|
|
} |
|
737
|
|
|
if (strpos($border, 'R') !== false) { |
|
738
|
|
|
$s .= sprintf( |
|
739
|
|
|
'%.2F %.2F m %.2F %.2F l S ', |
|
740
|
|
|
($x+$w)*$k, |
|
741
|
|
|
($this->h-$y)*$k, |
|
742
|
|
|
($x+$w)*$k, |
|
743
|
|
|
($this->h-($y+$h))*$k |
|
744
|
|
|
); |
|
745
|
|
|
} |
|
746
|
|
|
if (strpos($border, 'B') !== false) { |
|
747
|
|
|
$s .= sprintf( |
|
748
|
|
|
'%.2F %.2F m %.2F %.2F l S ', |
|
749
|
|
|
$x*$k, |
|
750
|
|
|
($this->h-($y+$h))*$k, |
|
751
|
|
|
($x+$w)*$k, |
|
752
|
|
|
($this->h-($y+$h))*$k |
|
753
|
|
|
); |
|
754
|
|
|
} |
|
755
|
|
|
} |
|
756
|
|
|
if ($txt !== '') { |
|
757
|
|
|
if ($align == 'R') { |
|
758
|
|
|
$dx = $w-$this->cMargin-$this->getStringWidth($txt); |
|
759
|
|
|
} elseif ($align == 'C') { |
|
760
|
|
|
$dx = ($w-$this->getStringWidth($txt))/2; |
|
761
|
|
|
} else { |
|
762
|
|
|
$dx = $this->cMargin; |
|
763
|
|
|
} |
|
764
|
|
|
if ($this->colorFlag) { |
|
765
|
|
|
$s .= 'q '.$this->textColor.' '; |
|
766
|
|
|
} |
|
767
|
|
|
$txt2 = str_replace(')', '\\)', str_replace('(', '\\(', str_replace('\\', '\\\\', $txt))); |
|
768
|
|
|
$s .= sprintf( |
|
769
|
|
|
'BT %.2F %.2F Td (%s) Tj ET', |
|
770
|
|
|
($this->x+$dx)*$k, |
|
771
|
|
|
($this->h-($this->y+.5*$h+.3*$this->fontSize))*$k, |
|
772
|
|
|
$txt2 |
|
773
|
|
|
); |
|
774
|
|
|
if ($this->underline) { |
|
775
|
|
|
$s .= ' '.$this->doUnderLine($this->x+$dx, $this->y+.5*$h+.3*$this->fontSize, $txt); |
|
776
|
|
|
} |
|
777
|
|
|
if ($this->colorFlag) { |
|
778
|
|
|
$s.=' Q'; |
|
779
|
|
|
} |
|
780
|
|
|
if ($link) { |
|
781
|
|
|
$this->link( |
|
782
|
|
|
$this->x+$dx, |
|
783
|
|
|
$this->y+.5*$h-.5*$this->fontSize, |
|
784
|
|
|
$this->getStringWidth($txt), |
|
785
|
|
|
$this->fontSize, |
|
786
|
|
|
$link |
|
787
|
|
|
); |
|
788
|
|
|
} |
|
789
|
|
|
} |
|
790
|
|
|
if ($s) { |
|
791
|
|
|
$this->out($s); |
|
792
|
|
|
} |
|
793
|
|
|
$this->lasth = $h; |
|
794
|
|
|
if ($ln > 0) { |
|
795
|
|
|
//Go to next line |
|
796
|
|
|
$this->y += $h; |
|
797
|
|
|
if ($ln == 1) { |
|
798
|
|
|
$this->x = $this->lMargin; |
|
799
|
|
|
} |
|
800
|
|
|
} else { |
|
801
|
|
|
$this->x += $w; |
|
802
|
|
|
} |
|
803
|
|
|
} |
|
804
|
|
|
|
|
805
|
|
|
public function multicell($w, $h, $txt, $border = 0, $align = 'J', $fill = false) |
|
806
|
|
|
{ |
|
807
|
|
|
//Output text with automatic or explicit line breaks |
|
808
|
|
|
$cw =& $this->currentFont['cw']; |
|
809
|
|
|
if ($w == 0) { |
|
810
|
|
|
$w = $this->w-$this->rMargin-$this->x; |
|
811
|
|
|
} |
|
812
|
|
|
$wmax = ($w-2*$this->cMargin)*1000/$this->fontSize; |
|
813
|
|
|
$s = str_replace("\r", '', $txt); |
|
814
|
|
|
$nb = strlen($s); |
|
815
|
|
|
if ($nb>0 && $s[$nb-1] == "\n") { |
|
816
|
|
|
$nb--; |
|
817
|
|
|
} |
|
818
|
|
|
$b = 0; |
|
819
|
|
|
if ($border) { |
|
820
|
|
|
if ($border == 1) { |
|
821
|
|
|
$border = 'LTRB'; |
|
822
|
|
|
$b = 'LRT'; |
|
823
|
|
|
$b2 = 'LR'; |
|
824
|
|
|
} else { |
|
825
|
|
|
$b2 = ''; |
|
826
|
|
|
if (strpos($border, 'L') !== false) { |
|
827
|
|
|
$b2 .= 'L'; |
|
828
|
|
|
} |
|
829
|
|
|
if (strpos($border, 'R') !== false) { |
|
830
|
|
|
$b2 .= 'R'; |
|
831
|
|
|
} |
|
832
|
|
|
$b=(strpos($border, 'T') !== false) ? $b2.'T' : $b2; |
|
833
|
|
|
} |
|
834
|
|
|
} |
|
835
|
|
|
$sep = -1; |
|
836
|
|
|
$i = 0; |
|
837
|
|
|
$j = 0; |
|
838
|
|
|
$l = 0; |
|
839
|
|
|
$ns = 0; |
|
840
|
|
|
$nl = 1; |
|
841
|
|
|
while ($i<$nb) { |
|
842
|
|
|
//Get next character |
|
843
|
|
|
$c = $s[$i]; |
|
844
|
|
|
if ($c == "\n") { |
|
845
|
|
|
//Explicit line break |
|
846
|
|
|
if ($this->ws > 0) { |
|
847
|
|
|
$this->ws = 0; |
|
848
|
|
|
$this->out('0 Tw'); |
|
849
|
|
|
} |
|
850
|
|
|
$this->cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill); |
|
851
|
|
|
$i++; |
|
852
|
|
|
$sep = -1; |
|
853
|
|
|
$j = $i; |
|
854
|
|
|
$l = 0; |
|
855
|
|
|
$ns = 0; |
|
856
|
|
|
$nl++; |
|
857
|
|
|
if ($border && $nl == 2) { |
|
858
|
|
|
$b=$b2; |
|
|
|
|
|
|
859
|
|
|
} |
|
860
|
|
|
continue; |
|
861
|
|
|
} |
|
862
|
|
|
if ($c == ' ') { |
|
863
|
|
|
$sep = $i; |
|
864
|
|
|
$ls = $l; |
|
865
|
|
|
$ns++; |
|
866
|
|
|
} |
|
867
|
|
|
$l += $cw[$c]; |
|
868
|
|
|
if ($l > $wmax) { |
|
869
|
|
|
//Automatic line break |
|
870
|
|
|
if ($sep == -1) { |
|
871
|
|
|
if ($i == $j) { |
|
872
|
|
|
$i++; |
|
873
|
|
|
} |
|
874
|
|
|
if ($this->ws > 0) { |
|
875
|
|
|
$this->ws = 0; |
|
876
|
|
|
$this->out('0 Tw'); |
|
877
|
|
|
} |
|
878
|
|
|
$this->cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill); |
|
879
|
|
|
} else { |
|
880
|
|
|
if ($align=='J') { |
|
881
|
|
|
$this->ws = ($ns>1) ? ($wmax-$ls)/1000*$this->fontSize/($ns-1) : 0; |
|
|
|
|
|
|
882
|
|
|
$this->out(sprintf('%.3F Tw', $this->ws*$this->k)); |
|
883
|
|
|
} |
|
884
|
|
|
$this->cell($w, $h, substr($s, $j, $sep-$j), $b, 2, $align, $fill); |
|
885
|
|
|
$i = $sep+1; |
|
886
|
|
|
} |
|
887
|
|
|
$sep = -1; |
|
888
|
|
|
$j = $i; |
|
889
|
|
|
$l = 0; |
|
890
|
|
|
$ns = 0; |
|
891
|
|
|
$nl++; |
|
892
|
|
|
if ($border && $nl == 2) { |
|
893
|
|
|
$b = $b2; |
|
894
|
|
|
} |
|
895
|
|
|
} else { |
|
896
|
|
|
$i++; |
|
897
|
|
|
} |
|
898
|
|
|
} |
|
899
|
|
|
//Last chunk |
|
900
|
|
|
if ($this->ws > 0) { |
|
901
|
|
|
$this->ws = 0; |
|
902
|
|
|
$this->out('0 Tw'); |
|
903
|
|
|
} |
|
904
|
|
|
if ($border && strpos($border, 'B')!==false) { |
|
905
|
|
|
$b .= 'B'; |
|
906
|
|
|
} |
|
907
|
|
|
$this->cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill); |
|
908
|
|
|
$this->x = $this->lMargin; |
|
909
|
|
|
} |
|
910
|
|
|
|
|
911
|
|
|
public function write($h, $txt, $link = '') |
|
912
|
|
|
{ |
|
913
|
|
|
//Output text in flowing mode |
|
914
|
|
|
$cw =& $this->currentFont['cw']; |
|
915
|
|
|
$w = $this->w-$this->rMargin-$this->x; |
|
916
|
|
|
$wmax = ($w-2*$this->cMargin)*1000/$this->fontSize; |
|
917
|
|
|
$s = str_replace("\r", '', $txt); |
|
918
|
|
|
$nb = strlen($s); |
|
919
|
|
|
$sep = -1; |
|
920
|
|
|
$i = 0; |
|
921
|
|
|
$j = 0; |
|
922
|
|
|
$l = 0; |
|
923
|
|
|
$nl = 1; |
|
924
|
|
|
while ($i < $nb) { |
|
925
|
|
|
//Get next character |
|
926
|
|
|
$c=$s[$i]; |
|
927
|
|
|
if ($c=="\n") { |
|
928
|
|
|
//Explicit line break |
|
929
|
|
|
$this->cell($w, $h, substr($s, $j, $i-$j), 0, 2, '', 0, $link); |
|
|
|
|
|
|
930
|
|
|
$i++; |
|
931
|
|
|
$sep = -1; |
|
932
|
|
|
$j = $i; |
|
933
|
|
|
$l = 0; |
|
934
|
|
|
if ($nl == 1) { |
|
935
|
|
|
$this->x = $this->lMargin; |
|
936
|
|
|
$w = $this->w-$this->rMargin-$this->x; |
|
937
|
|
|
$wmax = ($w-2*$this->cMargin)*1000/$this->fontSize; |
|
938
|
|
|
} |
|
939
|
|
|
$nl++; |
|
940
|
|
|
continue; |
|
941
|
|
|
} |
|
942
|
|
|
if ($c == ' ') { |
|
943
|
|
|
$sep = $i; |
|
944
|
|
|
} |
|
945
|
|
|
$l += $cw[$c]; |
|
946
|
|
|
if ($l > $wmax) { |
|
947
|
|
|
//Automatic line break |
|
948
|
|
|
if ($sep == -1) { |
|
949
|
|
|
if ($this->x > $this->lMargin) { |
|
950
|
|
|
//Move to next line |
|
951
|
|
|
$this->x = $this->lMargin; |
|
952
|
|
|
$this->y += $h; |
|
953
|
|
|
$w = $this->w-$this->rMargin-$this->x; |
|
954
|
|
|
$wmax = ($w-2*$this->cMargin)*1000/$this->fontSize; |
|
955
|
|
|
$i++; |
|
956
|
|
|
$nl++; |
|
957
|
|
|
continue; |
|
958
|
|
|
} |
|
959
|
|
|
if ($i == $j) { |
|
960
|
|
|
$i++; |
|
961
|
|
|
} |
|
962
|
|
|
$this->cell($w, $h, substr($s, $j, $i-$j), 0, 2, '', 0, $link); |
|
|
|
|
|
|
963
|
|
|
} else { |
|
964
|
|
|
$this->cell($w, $h, substr($s, $j, $sep-$j), 0, 2, '', 0, $link); |
|
|
|
|
|
|
965
|
|
|
$i = $sep+1; |
|
966
|
|
|
} |
|
967
|
|
|
$sep = -1; |
|
968
|
|
|
$j = $i; |
|
969
|
|
|
$l = 0; |
|
970
|
|
|
if ($nl == 1) { |
|
971
|
|
|
$this->x = $this->lMargin; |
|
972
|
|
|
$w = $this->w-$this->rMargin-$this->x; |
|
973
|
|
|
$wmax = ($w-2*$this->cMargin)*1000/$this->fontSize; |
|
974
|
|
|
} |
|
975
|
|
|
$nl++; |
|
976
|
|
|
} else { |
|
977
|
|
|
$i++; |
|
978
|
|
|
} |
|
979
|
|
|
} |
|
980
|
|
|
//Last chunk |
|
981
|
|
|
if ($i != $j) { |
|
982
|
|
|
$this->cell($l/1000*$this->fontSize, $h, substr($s, $j), 0, 0, '', 0, $link); |
|
|
|
|
|
|
983
|
|
|
} |
|
984
|
|
|
} |
|
985
|
|
|
|
|
986
|
|
|
public function ln($h = null) |
|
987
|
|
|
{ |
|
988
|
|
|
//Line feed; default value is last cell height |
|
989
|
|
|
$this->x = $this->lMargin; |
|
990
|
|
|
if ($h === null) { |
|
991
|
|
|
$this->y += $this->lasth; |
|
992
|
|
|
} else { |
|
993
|
|
|
$this->y += $h; |
|
994
|
|
|
} |
|
995
|
|
|
} |
|
996
|
|
|
|
|
997
|
|
|
public function image($file, $x = null, $y = null, $w = 0, $h = 0, $type = '', $link = '') |
|
998
|
|
|
{ |
|
999
|
|
|
//Put an image on the page |
|
1000
|
|
|
if (!isset($this->images[$file])) { |
|
1001
|
|
|
//First use of this image, get info |
|
1002
|
|
|
if ($type == '') { |
|
1003
|
|
|
$pos = strrpos($file, '.'); |
|
1004
|
|
|
if (!$pos) { |
|
1005
|
|
|
$this->error('Image file has no extension and no type was specified: '.$file); |
|
1006
|
|
|
} |
|
1007
|
|
|
$type = substr($file, $pos+1); |
|
1008
|
|
|
} |
|
1009
|
|
|
$type = strtolower($type); |
|
1010
|
|
|
if ($type == 'jpeg') { |
|
1011
|
|
|
$type = 'jpg'; |
|
1012
|
|
|
} |
|
1013
|
|
|
$mtd = 'parse'.strtoupper($type); |
|
1014
|
|
|
if (!method_exists($this, $mtd)) { |
|
1015
|
|
|
$this->error('Unsupported image type: '.$type); |
|
1016
|
|
|
} |
|
1017
|
|
|
$info = $this->$mtd($file); |
|
1018
|
|
|
$info['i'] = count($this->images)+1; |
|
1019
|
|
|
$this->images[$file] = $info; |
|
1020
|
|
|
} else { |
|
1021
|
|
|
$info = $this->images[$file]; |
|
1022
|
|
|
} |
|
1023
|
|
|
//Automatic width and height calculation if needed |
|
1024
|
|
|
if ($w == 0 && $h == 0) { |
|
1025
|
|
|
//Put image at 72 dpi |
|
1026
|
|
|
$w = $info['w']/$this->k; |
|
1027
|
|
|
$h = $info['h']/$this->k; |
|
1028
|
|
|
} elseif ($w == 0) { |
|
1029
|
|
|
$w = $h*$info['w']/$info['h']; |
|
1030
|
|
|
} elseif ($h == 0) { |
|
1031
|
|
|
$h = $w*$info['h']/$info['w']; |
|
1032
|
|
|
} |
|
1033
|
|
|
//Flowing mode |
|
1034
|
|
|
if ($y === null) { |
|
1035
|
|
|
if ($this->y+$h > $this->pageBreakTrigger |
|
1036
|
|
|
&& !$this->inHeader |
|
1037
|
|
|
&& !$this->inFooter |
|
1038
|
|
|
&& $this->acceptPageBreak() |
|
1039
|
|
|
) { |
|
1040
|
|
|
//Automatic page break |
|
1041
|
|
|
$x2 = $this->x; |
|
1042
|
|
|
$this->addPage($this->curOrientation, $this->curPageFormat); |
|
|
|
|
|
|
1043
|
|
|
$this->x = $x2; |
|
1044
|
|
|
} |
|
1045
|
|
|
$y = $this->y; |
|
1046
|
|
|
$this->y += $h; |
|
1047
|
|
|
} |
|
1048
|
|
|
if ($x === null) { |
|
1049
|
|
|
$x = $this->x; |
|
1050
|
|
|
} |
|
1051
|
|
|
$this->out( |
|
1052
|
|
|
sprintf( |
|
1053
|
|
|
'q %.2F 0 0 %.2F %.2F %.2F cm /I%d Do Q', |
|
1054
|
|
|
$w*$this->k, |
|
1055
|
|
|
$h*$this->k, |
|
1056
|
|
|
$x*$this->k, |
|
1057
|
|
|
($this->h-($y+$h))*$this->k, |
|
1058
|
|
|
$info['i'] |
|
1059
|
|
|
) |
|
1060
|
|
|
); |
|
1061
|
|
|
if ($link) { |
|
1062
|
|
|
$this->link($x, $y, $w, $h, $link); |
|
1063
|
|
|
} |
|
1064
|
|
|
} |
|
1065
|
|
|
|
|
1066
|
|
|
public function getX() |
|
1067
|
|
|
{ |
|
1068
|
|
|
//Get x position |
|
1069
|
|
|
return $this->x; |
|
1070
|
|
|
} |
|
1071
|
|
|
|
|
1072
|
|
|
public function setX($x) |
|
1073
|
|
|
{ |
|
1074
|
|
|
//Set x position |
|
1075
|
|
|
if ($x >= 0) { |
|
1076
|
|
|
$this->x = $x; |
|
1077
|
|
|
} else { |
|
1078
|
|
|
$this->x = $this->w+$x; |
|
1079
|
|
|
} |
|
1080
|
|
|
} |
|
1081
|
|
|
|
|
1082
|
|
|
public function getY() |
|
1083
|
|
|
{ |
|
1084
|
|
|
//Get y position |
|
1085
|
|
|
return $this->y; |
|
1086
|
|
|
} |
|
1087
|
|
|
|
|
1088
|
|
|
public function setY($y) |
|
1089
|
|
|
{ |
|
1090
|
|
|
//Set y position and reset x |
|
1091
|
|
|
$this->x = $this->lMargin; |
|
1092
|
|
|
if ($y >= 0) { |
|
1093
|
|
|
$this->y = $y; |
|
1094
|
|
|
} else { |
|
1095
|
|
|
$this->y = $this->h+$y; |
|
1096
|
|
|
} |
|
1097
|
|
|
} |
|
1098
|
|
|
|
|
1099
|
|
|
public function setXY($x, $y) |
|
1100
|
|
|
{ |
|
1101
|
|
|
//Set x and y positions |
|
1102
|
|
|
$this->setY($y); |
|
1103
|
|
|
$this->setX($x); |
|
1104
|
|
|
} |
|
1105
|
|
|
|
|
1106
|
|
|
public function getPdf() |
|
1107
|
|
|
{ |
|
1108
|
|
|
if ($this->state < 3) { |
|
1109
|
|
|
$this->close(); |
|
1110
|
|
|
} |
|
1111
|
|
|
return $this->buffer; |
|
1112
|
|
|
} |
|
1113
|
|
|
|
|
1114
|
|
|
public function output($name = '', $dest = '') |
|
1115
|
|
|
{ |
|
1116
|
|
|
//Output PDF to some destination |
|
1117
|
|
|
if ($this->state < 3) { |
|
1118
|
|
|
$this->close(); |
|
1119
|
|
|
} |
|
1120
|
|
|
$dest = strtoupper($dest); |
|
1121
|
|
|
if ($dest == '') { |
|
1122
|
|
|
if ($name == '') { |
|
1123
|
|
|
$name = 'doc.pdf'; |
|
1124
|
|
|
$dest = 'I'; |
|
1125
|
|
|
} else { |
|
1126
|
|
|
$dest = 'F'; |
|
1127
|
|
|
} |
|
1128
|
|
|
} |
|
1129
|
|
|
switch ($dest) { |
|
1130
|
|
|
case 'I': |
|
1131
|
|
|
//Send to standard output |
|
1132
|
|
|
if (ob_get_length()) { |
|
1133
|
|
|
$this->error('Some data has already been output, can\'t send PDF file'); |
|
1134
|
|
|
} |
|
1135
|
|
|
if (php_sapi_name() != 'cli') { |
|
1136
|
|
|
//We send to a browser |
|
1137
|
|
|
header('Content-Type: application/pdf'); |
|
1138
|
|
|
if (headers_sent()) { |
|
1139
|
|
|
$this->error('Some data has already been output, can\'t send PDF file'); |
|
1140
|
|
|
} |
|
1141
|
|
|
header('Content-Length: '.strlen($this->buffer)); |
|
1142
|
|
|
header('Content-Disposition: inline; filename="'.$name.'"'); |
|
1143
|
|
|
header('Cache-Control: private, max-age=0, must-revalidate'); |
|
1144
|
|
|
header('Pragma: public'); |
|
1145
|
|
|
ini_set('zlib.output_compression', '0'); |
|
1146
|
|
|
} |
|
1147
|
|
|
echo $this->buffer; |
|
1148
|
|
|
break; |
|
1149
|
|
|
case 'D': |
|
1150
|
|
|
//Download file |
|
1151
|
|
|
if (ob_get_length()) { |
|
1152
|
|
|
$this->error('Some data has already been output, can\'t send PDF file'); |
|
1153
|
|
|
} |
|
1154
|
|
|
header('Content-Type: application/x-download'); |
|
1155
|
|
|
if (headers_sent()) { |
|
1156
|
|
|
$this->error('Some data has already been output, can\'t send PDF file'); |
|
1157
|
|
|
} |
|
1158
|
|
|
header('Content-Length: '.strlen($this->buffer)); |
|
1159
|
|
|
header('Content-Disposition: attachment; filename="'.$name.'"'); |
|
1160
|
|
|
header('Cache-Control: private, max-age=0, must-revalidate'); |
|
1161
|
|
|
header('Pragma: public'); |
|
1162
|
|
|
ini_set('zlib.output_compression', '0'); |
|
1163
|
|
|
echo $this->buffer; |
|
1164
|
|
|
break; |
|
1165
|
|
|
case 'F': |
|
1166
|
|
|
//Save to local file |
|
1167
|
|
|
$f=fopen($name, 'wb'); |
|
1168
|
|
|
if (!$f) { |
|
1169
|
|
|
$this->error('Unable to create output file: '.$name); |
|
1170
|
|
|
} |
|
1171
|
|
|
fwrite($f, $this->buffer, strlen($this->buffer)); |
|
1172
|
|
|
fclose($f); |
|
1173
|
|
|
break; |
|
1174
|
|
|
case 'S': |
|
1175
|
|
|
//Return as a string |
|
1176
|
|
|
return $this->buffer; |
|
1177
|
|
|
default: |
|
1178
|
|
|
$this->error('Incorrect output destination: '.$dest); |
|
1179
|
|
|
} |
|
1180
|
|
|
return ''; |
|
1181
|
|
|
} |
|
1182
|
|
|
|
|
1183
|
|
|
protected function dochecks() |
|
1184
|
|
|
{ |
|
1185
|
|
|
//Check availability of %F |
|
1186
|
|
|
if (sprintf('%.1F', 1.0)!='1.0') { |
|
1187
|
|
|
$this->error('This version of PHP is not supported'); |
|
1188
|
|
|
} |
|
1189
|
|
|
//Check mbstring overloading |
|
1190
|
|
|
if (ini_get('mbstring.func_overload') & 2) { |
|
1191
|
|
|
$this->error('mbstring overloading must be disabled'); |
|
1192
|
|
|
} |
|
1193
|
|
|
} |
|
1194
|
|
|
|
|
1195
|
|
|
protected function getpageformat($format) |
|
1196
|
|
|
{ |
|
1197
|
|
|
$format=strtolower($format); |
|
1198
|
|
|
if (!isset($this->pageFormats[$format])) { |
|
1199
|
|
|
$this->error('Unknown page format: '.$format); |
|
1200
|
|
|
} |
|
1201
|
|
|
$a=$this->pageFormats[$format]; |
|
1202
|
|
|
return array($a[0]/$this->k, $a[1]/$this->k); |
|
1203
|
|
|
} |
|
1204
|
|
|
|
|
1205
|
|
|
protected function getFontPath() |
|
1206
|
|
|
{ |
|
1207
|
|
|
if (!defined('FPDF_FONTPATH') && is_dir(dirname(__FILE__).'/font')) { |
|
1208
|
|
|
define('FPDF_FONTPATH', dirname(__FILE__).'/font/'); |
|
1209
|
|
|
} |
|
1210
|
|
|
return defined('FPDF_FONTPATH') ? FPDF_FONTPATH : ''; |
|
1211
|
|
|
} |
|
1212
|
|
|
|
|
1213
|
|
|
protected function beginPage($orientation, $format) |
|
1214
|
|
|
{ |
|
1215
|
|
|
$this->page++; |
|
1216
|
|
|
$this->pages[$this->page] = ''; |
|
1217
|
|
|
$this->state = 2; |
|
1218
|
|
|
$this->x = $this->lMargin; |
|
1219
|
|
|
$this->y = $this->tMargin; |
|
1220
|
|
|
$this->fontFamily = ''; |
|
1221
|
|
|
//Check page size |
|
1222
|
|
|
if ($orientation == '') { |
|
1223
|
|
|
$orientation = $this->defOrientation; |
|
1224
|
|
|
} else { |
|
1225
|
|
|
$orientation = strtoupper($orientation[0]); |
|
1226
|
|
|
} |
|
1227
|
|
|
if ($format == '') { |
|
1228
|
|
|
$format = $this->defPageFormat; |
|
1229
|
|
|
} else { |
|
1230
|
|
|
if (is_string($format)) { |
|
1231
|
|
|
$format=$this->getpageformat($format); |
|
1232
|
|
|
} |
|
1233
|
|
|
} |
|
1234
|
|
|
if ($orientation != $this->curOrientation |
|
1235
|
|
|
|| $format[0]!=$this->curPageFormat[0] |
|
1236
|
|
|
|| $format[1]!=$this->curPageFormat[1] |
|
1237
|
|
|
) { |
|
1238
|
|
|
//New size |
|
1239
|
|
|
if ($orientation == 'P') { |
|
1240
|
|
|
$this->w = $format[0]; |
|
1241
|
|
|
$this->h = $format[1]; |
|
1242
|
|
|
} else { |
|
1243
|
|
|
$this->w = $format[1]; |
|
1244
|
|
|
$this->h = $format[0]; |
|
1245
|
|
|
} |
|
1246
|
|
|
$this->wPt = $this->w*$this->k; |
|
1247
|
|
|
$this->hPt = $this->h*$this->k; |
|
1248
|
|
|
$this->pageBreakTrigger = $this->h-$this->bMargin; |
|
1249
|
|
|
$this->curOrientation = $orientation; |
|
1250
|
|
|
$this->curPageFormat = $format; |
|
1251
|
|
|
} |
|
1252
|
|
|
if ($orientation != $this->defOrientation |
|
1253
|
|
|
|| $format[0] != $this->defPageFormat[0] |
|
1254
|
|
|
|| $format[1] != $this->defPageFormat[1] |
|
1255
|
|
|
) { |
|
1256
|
|
|
$this->PageSizes[$this->page] = array($this->wPt, $this->hPt); |
|
|
|
|
|
|
1257
|
|
|
} |
|
1258
|
|
|
} |
|
1259
|
|
|
|
|
1260
|
|
|
protected function endPage() |
|
1261
|
|
|
{ |
|
1262
|
|
|
$this->state = 1; |
|
1263
|
|
|
} |
|
1264
|
|
|
|
|
1265
|
|
|
protected function escape($s) |
|
1266
|
|
|
{ |
|
1267
|
|
|
//Escape special characters in strings |
|
1268
|
|
|
$s = str_replace('\\', '\\\\', $s); |
|
1269
|
|
|
$s = str_replace('(', '\\(', $s); |
|
1270
|
|
|
$s = str_replace(')', '\\)', $s); |
|
1271
|
|
|
$s = str_replace("\r", '\\r', $s); |
|
1272
|
|
|
return $s; |
|
1273
|
|
|
} |
|
1274
|
|
|
|
|
1275
|
|
|
protected function textString($s) |
|
1276
|
|
|
{ |
|
1277
|
|
|
//Format a text string |
|
1278
|
|
|
return '('.$this->escape($s).')'; |
|
1279
|
|
|
} |
|
1280
|
|
|
|
|
1281
|
|
|
protected function utf8Toutf16($s) |
|
1282
|
|
|
{ |
|
1283
|
|
|
//Convert UTF-8 to UTF-16BE with BOM |
|
1284
|
|
|
$res = "\xFE\xFF"; |
|
1285
|
|
|
$nb = strlen($s); |
|
1286
|
|
|
$i = 0; |
|
1287
|
|
|
while ($i < $nb) { |
|
1288
|
|
|
$c1 = ord($s[$i++]); |
|
1289
|
|
|
if ($c1 >= 224) { |
|
1290
|
|
|
//3-byte character |
|
1291
|
|
|
$c2 = ord($s[$i++]); |
|
1292
|
|
|
$c3 = ord($s[$i++]); |
|
1293
|
|
|
$res .= chr((($c1 & 0x0F)<<4) + (($c2 & 0x3C)>>2)); |
|
1294
|
|
|
$res .= chr((($c2 & 0x03)<<6) + ($c3 & 0x3F)); |
|
1295
|
|
|
} elseif ($c1 >= 192) { |
|
1296
|
|
|
//2-byte character |
|
1297
|
|
|
$c2 = ord($s[$i++]); |
|
1298
|
|
|
$res .= chr(($c1 & 0x1C)>>2); |
|
1299
|
|
|
$res .= chr((($c1 & 0x03)<<6) + ($c2 & 0x3F)); |
|
1300
|
|
|
} else { |
|
1301
|
|
|
//Single-byte character |
|
1302
|
|
|
$res .= "\0".chr($c1); |
|
1303
|
|
|
} |
|
1304
|
|
|
} |
|
1305
|
|
|
return $res; |
|
1306
|
|
|
} |
|
1307
|
|
|
|
|
1308
|
|
|
protected function doUnderLine($x, $y, $txt) |
|
1309
|
|
|
{ |
|
1310
|
|
|
//Underline text |
|
1311
|
|
|
$up = $this->currentFont['up']; |
|
1312
|
|
|
$ut = $this->currentFont['ut']; |
|
1313
|
|
|
$w = $this->getStringWidth($txt)+$this->ws*substr_count($txt, ' '); |
|
1314
|
|
|
return sprintf( |
|
1315
|
|
|
'%.2F %.2F %.2F %.2F re f', |
|
1316
|
|
|
$x*$this->k, |
|
1317
|
|
|
($this->h-($y-$up/1000*$this->fontSize))*$this->k, |
|
1318
|
|
|
$w*$this->k, |
|
1319
|
|
|
-$ut/1000*$this->fontSizePt |
|
1320
|
|
|
); |
|
1321
|
|
|
} |
|
1322
|
|
|
|
|
1323
|
|
|
protected function parseJPG($file) |
|
1324
|
|
|
{ |
|
1325
|
|
|
//Extract info from a JPEG file |
|
1326
|
|
|
$a = getImageSize($file); |
|
1327
|
|
|
if (!$a) { |
|
|
|
|
|
|
1328
|
|
|
$this->error('Missing or incorrect image file: '.$file); |
|
1329
|
|
|
} |
|
1330
|
|
|
if ($a[2]!=2) { |
|
1331
|
|
|
$this->error('Not a JPEG file: '.$file); |
|
1332
|
|
|
} |
|
1333
|
|
|
if (!isset($a['channels']) || $a['channels'] == 3) { |
|
1334
|
|
|
$colspace = 'DeviceRGB'; |
|
1335
|
|
|
} elseif ($a['channels'] == 4) { |
|
1336
|
|
|
$colspace = 'DeviceCMYK'; |
|
1337
|
|
|
} else { |
|
1338
|
|
|
$colspace='DeviceGray'; |
|
1339
|
|
|
} |
|
1340
|
|
|
$bpc = isset($a['bits']) ? $a['bits'] : 8; |
|
1341
|
|
|
//Read whole file |
|
1342
|
|
|
$f = fopen($file, 'rb'); |
|
1343
|
|
|
$data = ''; |
|
1344
|
|
|
while (!feof($f)) { |
|
1345
|
|
|
$data .= fread($f, 8192); |
|
1346
|
|
|
} |
|
1347
|
|
|
fclose($f); |
|
1348
|
|
|
return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$data); |
|
1349
|
|
|
} |
|
1350
|
|
|
|
|
1351
|
|
|
protected function parsePNG($file) |
|
1352
|
|
|
{ |
|
1353
|
|
|
//Extract info from a PNG file |
|
1354
|
|
|
$f = fopen($file, 'rb'); |
|
1355
|
|
|
if (!$f) { |
|
1356
|
|
|
$this->error('Can\'t open image file: '.$file); |
|
1357
|
|
|
} |
|
1358
|
|
|
//Check signature |
|
1359
|
|
|
if ($this->readstream($f, 8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) { |
|
1360
|
|
|
$this->error('Not a PNG file: '.$file); |
|
1361
|
|
|
} |
|
1362
|
|
|
//Read header chunk |
|
1363
|
|
|
$this->readstream($f, 4); |
|
1364
|
|
|
if ($this->readstream($f, 4)!='IHDR') { |
|
1365
|
|
|
$this->error('Incorrect PNG file: '.$file); |
|
1366
|
|
|
} |
|
1367
|
|
|
$w = $this->readint($f); |
|
1368
|
|
|
$h = $this->readint($f); |
|
1369
|
|
|
$bpc = ord($this->readstream($f, 1)); |
|
1370
|
|
|
if ($bpc>8) { |
|
1371
|
|
|
$this->error('16-bit depth not supported: '.$file); |
|
1372
|
|
|
} |
|
1373
|
|
|
$ct = ord($this->readstream($f, 1)); |
|
1374
|
|
|
if ($ct == 0) { |
|
1375
|
|
|
$colspace = 'DeviceGray'; |
|
1376
|
|
|
} elseif ($ct == 2) { |
|
1377
|
|
|
$colspace = 'DeviceRGB'; |
|
1378
|
|
|
} elseif ($ct == 3) { |
|
1379
|
|
|
$colspace = 'Indexed'; |
|
1380
|
|
|
} else { |
|
1381
|
|
|
$this->error('Alpha channel not supported: '.$file); |
|
1382
|
|
|
} |
|
1383
|
|
|
if (ord($this->readstream($f, 1)) != 0) { |
|
1384
|
|
|
$this->error('Unknown compression method: '.$file); |
|
1385
|
|
|
} |
|
1386
|
|
|
if (ord($this->readstream($f, 1)) != 0) { |
|
1387
|
|
|
$this->error('Unknown filter method: '.$file); |
|
1388
|
|
|
} |
|
1389
|
|
|
if (ord($this->readstream($f, 1)) != 0) { |
|
1390
|
|
|
$this->error('Interlacing not supported: '.$file); |
|
1391
|
|
|
} |
|
1392
|
|
|
$this->readstream($f, 4); |
|
1393
|
|
|
$parms = '/DecodeParms <</Predictor 15 /Colors ' |
|
1394
|
|
|
. ($ct==2 ? 3 : 1) |
|
1395
|
|
|
. ' /BitsPerComponent ' |
|
1396
|
|
|
. $bpc |
|
1397
|
|
|
. ' /Columns ' |
|
1398
|
|
|
. $w |
|
1399
|
|
|
. '>>'; |
|
1400
|
|
|
//Scan chunks looking for palette, transparency and image data |
|
1401
|
|
|
$pal = ''; |
|
1402
|
|
|
$trns = ''; |
|
1403
|
|
|
$data = ''; |
|
1404
|
|
|
do { |
|
1405
|
|
|
$n = $this->readint($f); |
|
1406
|
|
|
$type = $this->readstream($f, 4); |
|
1407
|
|
|
if ($type == 'PLTE') { |
|
1408
|
|
|
//Read palette |
|
1409
|
|
|
$pal = $this->readstream($f, $n); |
|
1410
|
|
|
$this->readstream($f, 4); |
|
1411
|
|
|
} elseif ($type == 'tRNS') { |
|
1412
|
|
|
//Read transparency info |
|
1413
|
|
|
$t = $this->readstream($f, $n); |
|
1414
|
|
|
if ($ct == 0) { |
|
1415
|
|
|
$trns = array(ord(substr($t, 1, 1))); |
|
1416
|
|
|
} elseif ($ct == 2) { |
|
1417
|
|
|
$trns = array(ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1))); |
|
1418
|
|
|
} else { |
|
1419
|
|
|
$pos = strpos($t, chr(0)); |
|
1420
|
|
|
if ($pos !== false) { |
|
1421
|
|
|
$trns = array($pos); |
|
1422
|
|
|
} |
|
1423
|
|
|
} |
|
1424
|
|
|
$this->readstream($f, 4); |
|
1425
|
|
|
} elseif ($type == 'IDAT') { |
|
1426
|
|
|
//Read image data block |
|
1427
|
|
|
$data .= $this->readstream($f, $n); |
|
1428
|
|
|
$this->readstream($f, 4); |
|
1429
|
|
|
} elseif ($type == 'IEND') { |
|
1430
|
|
|
break; |
|
1431
|
|
|
} else { |
|
1432
|
|
|
$this->readstream($f, $n+4); |
|
1433
|
|
|
} |
|
1434
|
|
|
} while ($n); |
|
1435
|
|
|
if ($colspace == 'Indexed' && empty($pal)) { |
|
|
|
|
|
|
1436
|
|
|
$this->error('Missing palette in '.$file); |
|
1437
|
|
|
} |
|
1438
|
|
|
fclose($f); |
|
1439
|
|
|
return [ |
|
1440
|
|
|
'w'=>$w, |
|
1441
|
|
|
'h'=>$h, |
|
1442
|
|
|
'cs'=>$colspace, |
|
1443
|
|
|
'bpc'=>$bpc, |
|
1444
|
|
|
'f'=>'FlateDecode', |
|
1445
|
|
|
'parms'=>$parms, |
|
1446
|
|
|
'pal'=>$pal, |
|
1447
|
|
|
'trns'=>$trns, |
|
1448
|
|
|
'data'=>$data |
|
1449
|
|
|
]; |
|
1450
|
|
|
} |
|
1451
|
|
|
|
|
1452
|
|
|
protected function readstream($f, $n) |
|
1453
|
|
|
{ |
|
1454
|
|
|
//Read n bytes from stream |
|
1455
|
|
|
$res=''; |
|
1456
|
|
|
while ($n > 0 && !feof($f)) { |
|
1457
|
|
|
$s=fread($f, $n); |
|
1458
|
|
|
if ($s === false) { |
|
1459
|
|
|
$this->error('Error while reading stream'); |
|
1460
|
|
|
} |
|
1461
|
|
|
$n -= strlen($s); |
|
1462
|
|
|
$res .= $s; |
|
1463
|
|
|
} |
|
1464
|
|
|
if ($n > 0) { |
|
1465
|
|
|
$this->error('Unexpected end of stream'); |
|
1466
|
|
|
} |
|
1467
|
|
|
return $res; |
|
1468
|
|
|
} |
|
1469
|
|
|
|
|
1470
|
|
|
protected function readint($f) |
|
1471
|
|
|
{ |
|
1472
|
|
|
//Read a 4-byte integer from stream |
|
1473
|
|
|
$a = unpack('Ni', $this->readstream($f, 4)); |
|
1474
|
|
|
return $a['i']; |
|
1475
|
|
|
} |
|
1476
|
|
|
|
|
1477
|
|
|
protected function parseGIF($file) |
|
1478
|
|
|
{ |
|
1479
|
|
|
//Extract info from a GIF file (via PNG conversion) |
|
1480
|
|
|
if (!function_exists('imagepng')) { |
|
1481
|
|
|
$this->error('GD extension is required for GIF support'); |
|
1482
|
|
|
} |
|
1483
|
|
|
if (!function_exists('imagecreatefromgif')) { |
|
1484
|
|
|
$this->error('GD has no GIF read support'); |
|
1485
|
|
|
} |
|
1486
|
|
|
$im = imagecreatefromgif($file); |
|
1487
|
|
|
if (!$im) { |
|
1488
|
|
|
$this->error('Missing or incorrect image file: '.$file); |
|
1489
|
|
|
} |
|
1490
|
|
|
imageinterlace($im, 0); |
|
1491
|
|
|
$tmp = tempnam('.', 'gif'); |
|
1492
|
|
|
if (!$tmp) { |
|
1493
|
|
|
$this->error('Unable to create a temporary file'); |
|
1494
|
|
|
} |
|
1495
|
|
|
if (!imagepng($im, $tmp)) { |
|
1496
|
|
|
$this->error('Error while saving to temporary file'); |
|
1497
|
|
|
} |
|
1498
|
|
|
imagedestroy($im); |
|
1499
|
|
|
$info=$this->parsePNG($tmp); |
|
1500
|
|
|
unlink($tmp); |
|
1501
|
|
|
return $info; |
|
1502
|
|
|
} |
|
1503
|
|
|
|
|
1504
|
|
|
protected function newObj() |
|
1505
|
|
|
{ |
|
1506
|
|
|
//Begin a new object |
|
1507
|
|
|
$this->n++; |
|
1508
|
|
|
$this->offsets[$this->n] = strlen($this->buffer); |
|
1509
|
|
|
$this->out($this->n.' 0 obj'); |
|
1510
|
|
|
} |
|
1511
|
|
|
|
|
1512
|
|
|
protected function putStream($s) |
|
1513
|
|
|
{ |
|
1514
|
|
|
$this->out('stream'); |
|
1515
|
|
|
$this->out($s); |
|
1516
|
|
|
$this->out('endstream'); |
|
1517
|
|
|
} |
|
1518
|
|
|
|
|
1519
|
|
|
protected function out($s) |
|
1520
|
|
|
{ |
|
1521
|
|
|
//Add a line to the document |
|
1522
|
|
|
if ($this->state == 2) { |
|
1523
|
|
|
$this->pages[$this->page].=$s."\n"; |
|
1524
|
|
|
} else { |
|
1525
|
|
|
$this->buffer .= $s."\n"; |
|
1526
|
|
|
} |
|
1527
|
|
|
} |
|
1528
|
|
|
|
|
1529
|
|
|
protected function putPages() |
|
1530
|
|
|
{ |
|
1531
|
|
|
$nb = $this->page; |
|
1532
|
|
|
if (!empty($this->aliasNbPages)) { |
|
1533
|
|
|
//Replace number of pages |
|
1534
|
|
|
for ($n=1; $n<=$nb; $n++) { |
|
1535
|
|
|
$this->pages[$n] = str_replace($this->aliasNbPages, $nb, $this->pages[$n]); |
|
1536
|
|
|
} |
|
1537
|
|
|
} |
|
1538
|
|
|
if ($this->defOrientation == 'P') { |
|
1539
|
|
|
$wPt = $this->defPageFormat[0]*$this->k; |
|
1540
|
|
|
$hPt = $this->defPageFormat[1]*$this->k; |
|
1541
|
|
|
} else { |
|
1542
|
|
|
$wPt = $this->defPageFormat[1]*$this->k; |
|
1543
|
|
|
$hPt = $this->defPageFormat[0]*$this->k; |
|
1544
|
|
|
} |
|
1545
|
|
|
$filter = ($this->compress) ? '/Filter /FlateDecode ' : ''; |
|
1546
|
|
|
for ($n=1; $n<=$nb; $n++) { |
|
1547
|
|
|
//Page |
|
1548
|
|
|
$this->newObj(); |
|
1549
|
|
|
$this->out('<</Type /Page'); |
|
1550
|
|
|
$this->out('/Parent 1 0 R'); |
|
1551
|
|
|
if (isset($this->PageSizes[$n])) { |
|
|
|
|
|
|
1552
|
|
|
$this->out(sprintf('/MediaBox [0 0 %.2F %.2F]', $this->PageSizes[$n][0], $this->PageSizes[$n][1])); |
|
|
|
|
|
|
1553
|
|
|
} |
|
1554
|
|
|
$this->out('/Resources 2 0 R'); |
|
1555
|
|
|
if (isset($this->PageLinks[$n])) { |
|
1556
|
|
|
//Links |
|
1557
|
|
|
$annots = '/Annots ['; |
|
1558
|
|
|
foreach ($this->PageLinks[$n] as $pl) { |
|
1559
|
|
|
$rect = sprintf('%.2F %.2F %.2F %.2F', $pl[0], $pl[1], $pl[0]+$pl[2], $pl[1]-$pl[3]); |
|
1560
|
|
|
$annots .= '<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] '; |
|
1561
|
|
|
if (is_string($pl[4])) { |
|
1562
|
|
|
$annots .= '/A <</S /URI /URI '.$this->textString($pl[4]).'>>>>'; |
|
1563
|
|
|
} else { |
|
1564
|
|
|
$l = $this->links[$pl[4]]; |
|
1565
|
|
|
$h = isset($this->PageSizes[$l[0]]) ? $this->PageSizes[$l[0]][1] : $hPt; |
|
|
|
|
|
|
1566
|
|
|
$annots .= sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>', 1+2*$l[0], $h-$l[1]*$this->k); |
|
1567
|
|
|
} |
|
1568
|
|
|
} |
|
1569
|
|
|
$this->out($annots.']'); |
|
1570
|
|
|
} |
|
1571
|
|
|
$this->out('/Contents '.($this->n+1).' 0 R>>'); |
|
1572
|
|
|
$this->out('endobj'); |
|
1573
|
|
|
//Page content |
|
1574
|
|
|
$p=($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n]; |
|
1575
|
|
|
$this->newObj(); |
|
1576
|
|
|
$this->out('<<'.$filter.'/Length '.strlen($p).'>>'); |
|
1577
|
|
|
$this->putStream($p); |
|
1578
|
|
|
$this->out('endobj'); |
|
1579
|
|
|
} |
|
1580
|
|
|
//Pages root |
|
1581
|
|
|
$this->offsets[1]=strlen($this->buffer); |
|
1582
|
|
|
$this->out('1 0 obj'); |
|
1583
|
|
|
$this->out('<</Type /Pages'); |
|
1584
|
|
|
$kids = '/Kids ['; |
|
1585
|
|
|
for ($i=0; $i<$nb; $i++) { |
|
1586
|
|
|
$kids .= (3+2*$i).' 0 R '; |
|
1587
|
|
|
} |
|
1588
|
|
|
$this->out($kids.']'); |
|
1589
|
|
|
$this->out('/Count '.$nb); |
|
1590
|
|
|
$this->out(sprintf('/MediaBox [0 0 %.2F %.2F]', $wPt, $hPt)); |
|
1591
|
|
|
$this->out('>>'); |
|
1592
|
|
|
$this->out('endobj'); |
|
1593
|
|
|
} |
|
1594
|
|
|
|
|
1595
|
|
|
protected function putFonts() |
|
1596
|
|
|
{ |
|
1597
|
|
|
$nf = $this->n; |
|
1598
|
|
|
foreach ($this->diffs as $diff) { |
|
1599
|
|
|
//Encodings |
|
1600
|
|
|
$this->newObj(); |
|
1601
|
|
|
$this->out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.']>>'); |
|
1602
|
|
|
$this->out('endobj'); |
|
1603
|
|
|
} |
|
1604
|
|
|
foreach ($this->fontFiles as $file => $info) { |
|
1605
|
|
|
//Font file embedding |
|
1606
|
|
|
$this->newObj(); |
|
1607
|
|
|
$this->fontFiles[$file]['n']=$this->n; |
|
1608
|
|
|
$font=''; |
|
1609
|
|
|
$f = fopen($this->getFontPath().$file, 'rb', 1); |
|
1610
|
|
|
if (!$f) { |
|
1611
|
|
|
$this->error('Font file not found'); |
|
1612
|
|
|
} |
|
1613
|
|
|
while (!feof($f)) { |
|
1614
|
|
|
$font.=fread($f, 8192); |
|
1615
|
|
|
} |
|
1616
|
|
|
fclose($f); |
|
1617
|
|
|
$compressed = (substr($file, -2)=='.z'); |
|
1618
|
|
|
if (!$compressed && isset($info['length2'])) { |
|
1619
|
|
|
$header = (ord($font[0])==128); |
|
1620
|
|
|
if ($header) { |
|
1621
|
|
|
//Strip first binary header |
|
1622
|
|
|
$font = substr($font, 6); |
|
1623
|
|
|
} |
|
1624
|
|
|
if ($header && ord($font[$info['length1']]) == 128) { |
|
1625
|
|
|
//Strip second binary header |
|
1626
|
|
|
$font = substr($font, 0, $info['length1']).substr($font, $info['length1']+6); |
|
1627
|
|
|
} |
|
1628
|
|
|
} |
|
1629
|
|
|
$this->out('<</Length '.strlen($font)); |
|
1630
|
|
|
if ($compressed) { |
|
1631
|
|
|
$this->out('/Filter /FlateDecode'); |
|
1632
|
|
|
} |
|
1633
|
|
|
$this->out('/Length1 '.$info['length1']); |
|
1634
|
|
|
if (isset($info['length2'])) { |
|
1635
|
|
|
$this->out('/Length2 '.$info['length2'].' /Length3 0'); |
|
1636
|
|
|
} |
|
1637
|
|
|
$this->out('>>'); |
|
1638
|
|
|
$this->putStream($font); |
|
1639
|
|
|
$this->out('endobj'); |
|
1640
|
|
|
} |
|
1641
|
|
|
foreach ($this->fonts as $k => $font) { |
|
1642
|
|
|
//Font objects |
|
1643
|
|
|
$this->fonts[$k]['n']=$this->n+1; |
|
1644
|
|
|
$type = $font['type']; |
|
1645
|
|
|
$name = $font['name']; |
|
1646
|
|
|
if ($type == 'core') { |
|
1647
|
|
|
//Standard font |
|
1648
|
|
|
$this->newObj(); |
|
1649
|
|
|
$this->out('<</Type /Font'); |
|
1650
|
|
|
$this->out('/BaseFont /'.$name); |
|
1651
|
|
|
$this->out('/Subtype /Type1'); |
|
1652
|
|
|
if ($name != 'Symbol' && $name != 'ZapfDingbats') { |
|
1653
|
|
|
$this->out('/Encoding /WinAnsiEncoding'); |
|
1654
|
|
|
} |
|
1655
|
|
|
$this->out('>>'); |
|
1656
|
|
|
$this->out('endobj'); |
|
1657
|
|
|
} elseif ($type=='Type1' || $type=='TrueType') { |
|
1658
|
|
|
//Additional Type1 or TrueType font |
|
1659
|
|
|
$this->newObj(); |
|
1660
|
|
|
$this->out('<</Type /Font'); |
|
1661
|
|
|
$this->out('/BaseFont /'.$name); |
|
1662
|
|
|
$this->out('/Subtype /'.$type); |
|
1663
|
|
|
$this->out('/FirstChar 32 /LastChar 255'); |
|
1664
|
|
|
$this->out('/Widths '.($this->n+1).' 0 R'); |
|
1665
|
|
|
$this->out('/FontDescriptor '.($this->n+2).' 0 R'); |
|
1666
|
|
|
if ($font['enc']) { |
|
1667
|
|
|
if (isset($font['diff'])) { |
|
1668
|
|
|
$this->out('/Encoding '.($nf+$font['diff']).' 0 R'); |
|
1669
|
|
|
} else { |
|
1670
|
|
|
$this->out('/Encoding /WinAnsiEncoding'); |
|
1671
|
|
|
} |
|
1672
|
|
|
} |
|
1673
|
|
|
$this->out('>>'); |
|
1674
|
|
|
$this->out('endobj'); |
|
1675
|
|
|
//Widths |
|
1676
|
|
|
$this->newObj(); |
|
1677
|
|
|
$cw =& $font['cw']; |
|
1678
|
|
|
$s = '['; |
|
1679
|
|
|
for ($i=32; $i<=255; $i++) { |
|
1680
|
|
|
$s .= $cw[chr($i)].' '; |
|
1681
|
|
|
} |
|
1682
|
|
|
$this->out($s.']'); |
|
1683
|
|
|
$this->out('endobj'); |
|
1684
|
|
|
//Descriptor |
|
1685
|
|
|
$this->newObj(); |
|
1686
|
|
|
$s='<</Type /FontDescriptor /FontName /'.$name; |
|
1687
|
|
|
foreach ($font['desc'] as $k => $v) { |
|
1688
|
|
|
$s .= ' /'.$k.' '.$v; |
|
1689
|
|
|
} |
|
1690
|
|
|
$file=$font['file']; |
|
1691
|
|
|
if ($file) { |
|
1692
|
|
|
$s .= ' /FontFile'.($type=='Type1' ? '' : '2').' '.$this->fontFiles[$file]['n'].' 0 R'; |
|
1693
|
|
|
} |
|
1694
|
|
|
$this->out($s.'>>'); |
|
1695
|
|
|
$this->out('endobj'); |
|
1696
|
|
|
} else { |
|
1697
|
|
|
//Allow for additional types |
|
1698
|
|
|
$mtd='_put'.strtolower($type); |
|
1699
|
|
|
if (!method_exists($this, $mtd)) { |
|
1700
|
|
|
$this->error('Unsupported font type: '.$type); |
|
1701
|
|
|
} |
|
1702
|
|
|
$this->$mtd($font); |
|
1703
|
|
|
} |
|
1704
|
|
|
} |
|
1705
|
|
|
} |
|
1706
|
|
|
|
|
1707
|
|
|
protected function putImages() |
|
1708
|
|
|
{ |
|
1709
|
|
|
foreach (array_keys($this->images) as $file) { |
|
1710
|
|
|
$this->putimage($this->images[$file]); |
|
1711
|
|
|
unset($this->images[$file]['data']); |
|
1712
|
|
|
unset($this->images[$file]['smask']); |
|
1713
|
|
|
} |
|
1714
|
|
|
} |
|
1715
|
|
|
|
|
1716
|
|
|
protected function putimage(&$info) |
|
1717
|
|
|
{ |
|
1718
|
|
|
$this->newobj(); |
|
1719
|
|
|
$info['n'] = $this->n; |
|
1720
|
|
|
$this->out('<</Type /XObject'); |
|
1721
|
|
|
$this->out('/Subtype /Image'); |
|
1722
|
|
|
$this->out('/Width '.$info['w']); |
|
1723
|
|
|
$this->out('/Height '.$info['h']); |
|
1724
|
|
|
if ($info['cs']=='Indexed') { |
|
1725
|
|
|
$this->out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]'); |
|
1726
|
|
|
} else { |
|
1727
|
|
|
$this->out('/ColorSpace /'.$info['cs']); |
|
1728
|
|
|
if ($info['cs']=='DeviceCMYK') { |
|
1729
|
|
|
$this->out('/Decode [1 0 1 0 1 0 1 0]'); |
|
1730
|
|
|
} |
|
1731
|
|
|
} |
|
1732
|
|
|
$this->out('/BitsPerComponent '.$info['bpc']); |
|
1733
|
|
|
if (isset($info['f'])) { |
|
1734
|
|
|
$this->out('/Filter /'.$info['f']); |
|
1735
|
|
|
} |
|
1736
|
|
|
if (isset($info['dp'])) { |
|
1737
|
|
|
$this->out('/DecodeParms <<'.$info['dp'].'>>'); |
|
1738
|
|
|
} |
|
1739
|
|
|
if (isset($info['trns']) && is_array($info['trns'])) { |
|
1740
|
|
|
$trns = ''; |
|
1741
|
|
|
for ($i=0; $i<count($info['trns']); $i++) { |
|
|
|
|
|
|
1742
|
|
|
$trns .= $info['trns'][$i].' '.$info['trns'][$i].' '; |
|
1743
|
|
|
} |
|
1744
|
|
|
$this->out('/Mask ['.$trns.']'); |
|
1745
|
|
|
} |
|
1746
|
|
|
if (isset($info['smask'])) { |
|
1747
|
|
|
$this->out('/SMask '.($this->n+1).' 0 R'); |
|
1748
|
|
|
} |
|
1749
|
|
|
$this->out('/Length '.strlen($info['data']).'>>'); |
|
1750
|
|
|
$this->putstream($info['data']); |
|
1751
|
|
|
$this->out('endobj'); |
|
1752
|
|
|
// Soft mask |
|
1753
|
|
|
if (isset($info['smask'])) { |
|
1754
|
|
|
$dp = '/Predictor 15 /Colors 1 /BitsPerComponent 8 /Columns '.$info['w']; |
|
1755
|
|
|
$smask = [ |
|
1756
|
|
|
'w'=>$info['w'], |
|
1757
|
|
|
'h'=>$info['h'], |
|
1758
|
|
|
'cs'=>'DeviceGray', |
|
1759
|
|
|
'bpc'=>8, |
|
1760
|
|
|
'f'=>$info['f'], |
|
1761
|
|
|
'dp'=>$dp, |
|
1762
|
|
|
'data'=>$info['smask'] |
|
1763
|
|
|
]; |
|
1764
|
|
|
$this->putimage($smask); |
|
1765
|
|
|
} |
|
1766
|
|
|
// Palette |
|
1767
|
|
|
if ($info['cs']=='Indexed') { |
|
1768
|
|
|
$this->putstreamobject($info['pal']); |
|
|
|
|
|
|
1769
|
|
|
} |
|
1770
|
|
|
} |
|
1771
|
|
|
|
|
1772
|
|
|
|
|
1773
|
|
|
/*protected function putImages() |
|
|
|
|
|
|
1774
|
|
|
{ |
|
1775
|
|
|
$filter = ($this->compress) ? '/Filter /FlateDecode ' : ''; |
|
1776
|
|
|
reset($this->images); |
|
1777
|
|
|
foreach (list($file,$info) as each($this->images)) { |
|
1778
|
|
|
$this->newObj(); |
|
1779
|
|
|
$this->images[$file]['n'] = $this->n; |
|
1780
|
|
|
$this->out('<</Type /XObject'); |
|
1781
|
|
|
$this->out('/Subtype /Image'); |
|
1782
|
|
|
$this->out('/Width '.$info['w']); |
|
1783
|
|
|
$this->out('/Height '.$info['h']); |
|
1784
|
|
|
if ($info['cs']=='Indexed') { |
|
1785
|
|
|
$this->out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]'); |
|
1786
|
|
|
} else { |
|
1787
|
|
|
$this->out('/ColorSpace /'.$info['cs']); |
|
1788
|
|
|
if ($info['cs']=='DeviceCMYK') { |
|
1789
|
|
|
$this->out('/Decode [1 0 1 0 1 0 1 0]'); |
|
1790
|
|
|
} |
|
1791
|
|
|
} |
|
1792
|
|
|
$this->out('/BitsPerComponent '.$info['bpc']); |
|
1793
|
|
|
if (isset($info['f'])) { |
|
1794
|
|
|
$this->out('/Filter /'.$info['f']); |
|
1795
|
|
|
} |
|
1796
|
|
|
if (isset($info['parms'])) { |
|
1797
|
|
|
$this->out($info['parms']); |
|
1798
|
|
|
} |
|
1799
|
|
|
if (isset($info['trns']) && is_array($info['trns'])) { |
|
1800
|
|
|
$trns = ''; |
|
1801
|
|
|
for ($i=0; $i<count($info['trns']); $i++) { |
|
1802
|
|
|
$trns.=$info['trns'][$i].' '.$info['trns'][$i].' '; |
|
1803
|
|
|
} |
|
1804
|
|
|
$this->out('/Mask ['.$trns.']'); |
|
1805
|
|
|
} |
|
1806
|
|
|
$this->out('/Length '.strlen($info['data']).'>>'); |
|
1807
|
|
|
$this->putStream($info['data']); |
|
1808
|
|
|
unset($this->images[$file]['data']); |
|
1809
|
|
|
$this->out('endobj'); |
|
1810
|
|
|
//Palette |
|
1811
|
|
|
if ($info['cs'] == 'Indexed') { |
|
1812
|
|
|
$this->newObj(); |
|
1813
|
|
|
$pal=($this->compress) ? gzcompress($info['pal']) : $info['pal']; |
|
1814
|
|
|
$this->out('<<'.$filter.'/Length '.strlen($pal).'>>'); |
|
1815
|
|
|
$this->putStream($pal); |
|
1816
|
|
|
$this->out('endobj'); |
|
1817
|
|
|
} |
|
1818
|
|
|
} |
|
1819
|
|
|
}*/ |
|
1820
|
|
|
|
|
1821
|
|
|
protected function putXobjectDict() |
|
1822
|
|
|
{ |
|
1823
|
|
|
foreach ($this->images as $image) { |
|
1824
|
|
|
$this->out('/I'.$image['i'].' '.$image['n'].' 0 R'); |
|
1825
|
|
|
} |
|
1826
|
|
|
} |
|
1827
|
|
|
|
|
1828
|
|
|
protected function putResourceDict() |
|
1829
|
|
|
{ |
|
1830
|
|
|
$this->out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'); |
|
1831
|
|
|
$this->out('/Font <<'); |
|
1832
|
|
|
foreach ($this->fonts as $font) { |
|
1833
|
|
|
$this->out('/F'.$font['i'].' '.$font['n'].' 0 R'); |
|
1834
|
|
|
} |
|
1835
|
|
|
$this->out('>>'); |
|
1836
|
|
|
$this->out('/XObject <<'); |
|
1837
|
|
|
$this->putXobjectDict(); |
|
1838
|
|
|
$this->out('>>'); |
|
1839
|
|
|
} |
|
1840
|
|
|
|
|
1841
|
|
|
protected function putResources() |
|
1842
|
|
|
{ |
|
1843
|
|
|
$this->putFonts(); |
|
1844
|
|
|
$this->putImages(); |
|
1845
|
|
|
//Resource dictionary |
|
1846
|
|
|
$this->offsets[2] = strlen($this->buffer); |
|
1847
|
|
|
$this->out('2 0 obj'); |
|
1848
|
|
|
$this->out('<<'); |
|
1849
|
|
|
$this->putResourceDict(); |
|
1850
|
|
|
$this->out('>>'); |
|
1851
|
|
|
$this->out('endobj'); |
|
1852
|
|
|
} |
|
1853
|
|
|
|
|
1854
|
|
|
protected function putInfo() |
|
1855
|
|
|
{ |
|
1856
|
|
|
$this->out('/Producer '.$this->textString('FPDF '. self::FPDF_VERSION)); |
|
1857
|
|
|
if (!empty($this->title)) { |
|
1858
|
|
|
$this->out('/Title '.$this->textString($this->title)); |
|
1859
|
|
|
} |
|
1860
|
|
|
if (!empty($this->subject)) { |
|
1861
|
|
|
$this->out('/Subject '.$this->textString($this->subject)); |
|
1862
|
|
|
} |
|
1863
|
|
|
if (!empty($this->author)) { |
|
1864
|
|
|
$this->out('/Author '.$this->textString($this->author)); |
|
1865
|
|
|
} |
|
1866
|
|
|
if (!empty($this->keywords)) { |
|
1867
|
|
|
$this->out('/Keywords '.$this->textString($this->keywords)); |
|
1868
|
|
|
} |
|
1869
|
|
|
if (!empty($this->creator)) { |
|
1870
|
|
|
$this->out('/Creator '.$this->textString($this->creator)); |
|
1871
|
|
|
} |
|
1872
|
|
|
$this->out('/CreationDate '.$this->textString('D:'.@date('YmdHis'))); |
|
1873
|
|
|
} |
|
1874
|
|
|
|
|
1875
|
|
|
protected function putCatalog() |
|
1876
|
|
|
{ |
|
1877
|
|
|
$this->out('/Type /Catalog'); |
|
1878
|
|
|
$this->out('/Pages 1 0 R'); |
|
1879
|
|
|
if ($this->zoomMode=='fullpage') { |
|
1880
|
|
|
$this->out('/OpenAction [3 0 R /Fit]'); |
|
1881
|
|
|
} elseif ($this->zoomMode=='fullwidth') { |
|
1882
|
|
|
$this->out('/OpenAction [3 0 R /FitH null]'); |
|
1883
|
|
|
} elseif ($this->zoomMode=='real') { |
|
1884
|
|
|
$this->out('/OpenAction [3 0 R /XYZ null null 1]'); |
|
1885
|
|
|
} elseif (!is_string($this->zoomMode)) { |
|
1886
|
|
|
$this->out('/OpenAction [3 0 R /XYZ null null '.($this->zoomMode/100).']'); |
|
1887
|
|
|
} |
|
1888
|
|
|
if ($this->layoutMode=='single') { |
|
1889
|
|
|
$this->out('/PageLayout /SinglePage'); |
|
1890
|
|
|
} elseif ($this->layoutMode=='continuous') { |
|
1891
|
|
|
$this->out('/PageLayout /OneColumn'); |
|
1892
|
|
|
} elseif ($this->layoutMode=='two') { |
|
1893
|
|
|
$this->out('/PageLayout /TwoColumnLeft'); |
|
1894
|
|
|
} |
|
1895
|
|
|
} |
|
1896
|
|
|
|
|
1897
|
|
|
protected function putHeader() |
|
1898
|
|
|
{ |
|
1899
|
|
|
$this->out('%PDF-'.$this->pdfVersion); |
|
1900
|
|
|
} |
|
1901
|
|
|
|
|
1902
|
|
|
protected function putTrailer() |
|
1903
|
|
|
{ |
|
1904
|
|
|
$this->out('/Size '.($this->n+1)); |
|
1905
|
|
|
$this->out('/Root '.$this->n.' 0 R'); |
|
1906
|
|
|
$this->out('/Info '.($this->n-1).' 0 R'); |
|
1907
|
|
|
} |
|
1908
|
|
|
|
|
1909
|
|
|
protected function endDoc() |
|
1910
|
|
|
{ |
|
1911
|
|
|
$this->putHeader(); |
|
1912
|
|
|
$this->putPages(); |
|
1913
|
|
|
$this->putResources(); |
|
1914
|
|
|
//Info |
|
1915
|
|
|
$this->newObj(); |
|
1916
|
|
|
$this->out('<<'); |
|
1917
|
|
|
$this->putInfo(); |
|
1918
|
|
|
$this->out('>>'); |
|
1919
|
|
|
$this->out('endobj'); |
|
1920
|
|
|
//Catalog |
|
1921
|
|
|
$this->newObj(); |
|
1922
|
|
|
$this->out('<<'); |
|
1923
|
|
|
$this->putCatalog(); |
|
1924
|
|
|
$this->out('>>'); |
|
1925
|
|
|
$this->out('endobj'); |
|
1926
|
|
|
//Cross-ref |
|
1927
|
|
|
$o=strlen($this->buffer); |
|
1928
|
|
|
$this->out('xref'); |
|
1929
|
|
|
$this->out('0 '.($this->n+1)); |
|
1930
|
|
|
$this->out('0000000000 65535 f '); |
|
1931
|
|
|
for ($i=1; $i<=$this->n; $i++) { |
|
1932
|
|
|
$this->out(sprintf('%010d 00000 n ', $this->offsets[$i])); |
|
1933
|
|
|
} |
|
1934
|
|
|
//Trailer |
|
1935
|
|
|
$this->out('trailer'); |
|
1936
|
|
|
$this->out('<<'); |
|
1937
|
|
|
$this->putTrailer(); |
|
1938
|
|
|
$this->out('>>'); |
|
1939
|
|
|
$this->out('startxref'); |
|
1940
|
|
|
$this->out($o); |
|
1941
|
|
|
$this->out('%%EOF'); |
|
1942
|
|
|
$this->state=3; |
|
1943
|
|
|
} |
|
1944
|
|
|
} |
|
1945
|
|
|
|
This check looks for calls to
isset(...)orempty()on variables that are yet undefined. These calls will always produce the same result and can be removed.This is most likely caused by the renaming of a variable or the removal of a function/method parameter.