1<?php
2// $Header: /cvsroot/html2ps/output.fpdf.class.php,v 1.27 2007/05/17 13:55:13 Konstantin Exp $
3
4require_once(HTML2PS_DIR.'pdf.fpdf.php');
5require_once(HTML2PS_DIR.'pdf.fpdf.makefont.php');
6// require_once(HTML2PS_DIR.'fpdf/font/makefont/makefont.php');
7
8class OutputDriverFPDF extends OutputDriverGenericPDF {
9  var $pdf;
10  var $locallinks;
11  var $cx;
12  var $cy;
13
14  function OutputDriverFPDF() {
15    $this->OutputDriverGenericPDF();
16  }
17
18  function add_link($x, $y, $w, $h, $target) {
19    $this->_coords2pdf_annotation($x, $y);
20    $this->pdf->add_link_external($x, $y, $w, $h, $target);
21  }
22
23  function add_local_link($left, $top, $width, $height, $anchor) {
24    if (!isset($this->locallinks[$anchor->name])) {
25      $x = 0;
26      $y = $anchor->y;
27      $this->_coords2pdf($x, $y);
28
29      $this->locallinks[$anchor->name] = $this->pdf->AddLink();
30      $this->pdf->SetLink($this->locallinks[$anchor->name],
31                          $y - 20,
32                          $anchor->page);
33    };
34
35    $x = $left;
36    $y = $top - $this->offset;
37    $this->_coords2pdf($x, $y);
38
39    $this->pdf->add_link_internal($x,
40                                  $y,
41                                  $width,
42                                  $height,
43                                  $this->locallinks[$anchor->name]);
44  }
45
46  // UNfortunately, FPDF do not provide any coordinate-space transformation routines
47  // so we need to reverse the Y-axis manually
48  function _coords2pdf(&$x, &$y) {
49    $y = mm2pt($this->media->height()) - $y;
50  }
51
52  // Annotation coordinates are always interpreted in the default (untranslated!)
53  // user space. (See PDF Reference 1.6 Section 8.4 p.575)
54  function _coords2pdf_annotation(&$x, &$y) {
55    $y = $y - $this->offset;
56    $this->_coords2pdf($x, $y);
57  }
58
59  function decoration($underline, $overline, $strikeout) {
60    // underline
61    $this->pdf->SetDecoration($underline, $overline, $strikeout);
62  }
63
64  function circle($x, $y, $r) {
65    $this->pdf->circle($x, $y, $r);
66  }
67
68  function clip() {
69    $this->pdf->Clip();
70  }
71
72  function close() {
73    $this->pdf->Output($this->get_filename());
74  }
75
76  function closepath() {
77    $this->pdf->closepath();
78  }
79
80  function dash($x, $y) {
81    $this->pdf->SetDash(ceil($x), ceil($y));
82  }
83
84  function get_bottom() {
85    return $this->bottom + $this->offset;
86  }
87
88  function field_multiline_text($x, $y, $w, $h, $value, $field_name) {
89    $this->_coords2pdf_annotation($x, $y);
90    $this->pdf->add_field_multiline_text($x, $y, $w, $h, $value, $field_name);
91  }
92
93  function field_text($x, $y, $w, $h, $value, $field_name) {
94    $this->_coords2pdf_annotation($x, $y);
95    $this->pdf->add_field_text($x, $y, $w, $h, $value, $field_name);
96  }
97
98  function field_password($x, $y, $w, $h, $value, $field_name) {
99    $this->_coords2pdf_annotation($x, $y);
100    $this->pdf->add_field_password($x, $y, $w, $h, $value, $field_name);
101  }
102
103  function field_pushbutton($x, $y, $w, $h) {
104    $this->_coords2pdf_annotation($x, $y);
105    $this->pdf->add_field_pushbutton($x, $y, $w, $h);
106  }
107
108  function field_pushbuttonimage($x, $y, $w, $h, $field_name, $value, $actionURL) {
109    $this->_coords2pdf_annotation($x, $y);
110    $this->pdf->add_field_pushbuttonimage($x, $y, $w, $h, $field_name, $value,  $actionURL);
111  }
112
113  function field_pushbuttonreset($x, $y, $w, $h) {
114    $this->_coords2pdf_annotation($x, $y);
115    $this->pdf->add_field_pushbuttonreset($x, $y, $w, $h);
116  }
117
118  function field_pushbuttonsubmit($x, $y, $w, $h, $field_name, $value, $actionURL) {
119    $this->_coords2pdf_annotation($x, $y);
120    $this->pdf->add_field_pushbuttonsubmit($x, $y, $w, $h, $field_name, $value,  $actionURL);
121  }
122
123  function field_checkbox($x, $y, $w, $h, $name, $value, $checked) {
124    $this->_coords2pdf_annotation($x, $y);
125    $this->pdf->add_field_checkbox($x, $y, $w, $h, $name, $value, $checked);
126  }
127
128  function field_radio($x, $y, $w, $h, $groupname, $value, $checked) {
129    static $generated_group_index = 0;
130    if (is_null($groupname)) {
131      $generated_group_index ++;
132      $groupname = "__generated_group_".$generated_group_index;
133    };
134
135    $this->_coords2pdf_annotation($x, $y);
136    $this->pdf->add_field_radio($x, $y, $w, $h, $groupname, $value, $checked);
137  }
138
139  function field_select($x, $y, $w, $h, $name, $value, $options) {
140    $this->_coords2pdf_annotation($x, $y);
141    $this->pdf->add_field_select($x, $y, $w, $h, $name, $value, $options);
142  }
143
144  function fill() {
145    $this->pdf->Fill();
146  }
147
148  function findfont($name, $encoding) {
149    // Todo: encodings handling
150    return $name;
151  }
152
153  function font_ascender($name, $encoding) {
154    return $this->pdf->GetFontAscender($name, $encoding);
155  }
156
157  function font_descender($name, $encoding) {
158    return $this->pdf->GetFontDescender($name, $encoding);
159  }
160
161  function image($image, $x, $y, $scale) {
162    $tmpname = $this->_mktempimage($image);
163
164    $this->_coords2pdf($x, $y);
165    $this->pdf->Image($tmpname,
166                      $x,
167                      $y - $image->sy() * $scale,
168                      $image->sx() * $scale,
169                      $image->sy() * $scale);
170
171    unlink($tmpname);
172  }
173
174  function image_rx($image, $x, $y, $width, $right, $ox, $oy, $scale) {
175    $tmpname = $this->_mktempimage($image);
176
177    // Fill part to the right
178    $cx = $x;
179    while ($cx < $right) {
180      $tx = $cx;
181      $ty = $y + px2pt($image->sy());
182      $this->_coords2pdf($tx, $ty);
183      $this->pdf->Image($tmpname, $tx, $ty, $image->sx() * $scale, $image->sy() * $scale, "png");
184      $cx += $width;
185    };
186
187    // Fill part to the left
188    $cx = $x;
189    while ($cx+$width >= $x - $ox) {
190      $tx = $cx-$width;
191      $ty = $y + px2pt($image->sy());
192      $this->_coords2pdf($tx, $ty);
193      $this->pdf->Image($tmpname, $tx, $ty, $image->sx() * $scale, $image->sy() * $scale, "png");
194      $cx -= $width;
195    };
196
197    unlink($tmpname);
198  }
199
200  function image_rx_ry($image, $x, $y, $width, $height, $right, $bottom, $ox, $oy, $scale) {
201    $tmpname = $this->_mktempimage($image);
202
203    // Fill bottom-right quadrant
204    $cy = $y;
205    while ($cy+$height > $bottom) {
206      $cx = $x;
207      while ($cx < $right) {
208        $tx = $cx;
209        $ty = $cy+$height;
210        $this->_coords2pdf($tx, $ty);
211
212        $this->pdf->Image($tmpname, $tx, $ty, $image->sx() * $scale, $image->sy() * $scale, "png");
213        $cx += $width;
214      };
215      $cy -= $height;
216    }
217
218    // Fill bottom-left quadrant
219    $cy = $y;
220    while ($cy+$height > $bottom) {
221      $cx = $x;
222      while ($cx+$width > $x - $ox) {
223        $tx = $cx;
224        $ty = $cy;
225        $this->_coords2pdf($tx, $ty);
226        $this->pdf->Image($tmpname, $tx, $ty, $image->sx() * $scale, $image->sy() * $scale, "png");
227        $cx -= $width;
228      };
229      $cy -= $height;
230    }
231
232    // Fill top-right quadrant
233    $cy = $y;
234    while ($cy < $y + $oy) {
235      $cx = $x;
236      while ($cx < $right) {
237        $tx = $cx;
238        $ty = $cy;
239        $this->_coords2pdf($tx, $ty);
240        $this->pdf->Image($tmpname, $tx, $ty, $image->sx() * $scale, $image->sy() * $scale, "png");
241        $cx += $width;
242      };
243      $cy += $height;
244    }
245
246    // Fill top-left quadrant
247    $cy = $y;
248    while ($cy < $y + $oy) {
249      $cx = $x;
250      while ($cx+$width > $x - $ox) {
251        $tx = $cx;
252        $ty = $cy;
253        $this->_coords2pdf($tx, $ty);
254        $this->pdf->Image($tmpname, $tx, $ty, $image->sx() * $scale, $image->sy() * $scale, "png");
255        $cx -= $width;
256      };
257      $cy += $height;
258    }
259
260    unlink($tmpname);
261  }
262
263
264  function image_ry($image, $x, $y, $height, $bottom, $ox, $oy, $scale) {
265    $tmpname = $this->_mktempimage($image);
266
267    // Fill part to the bottom
268    $cy = $y;
269    while ($cy+$height > $bottom) {
270      $tx = $x;
271      $ty = $cy + px2pt($image->sy());
272      $this->_coords2pdf($tx, $ty);
273      $this->pdf->Image($tmpname, $tx, $ty, $image->sx() * $scale, $image->sy() * $scale, "png");
274      $cy -= $height;
275    };
276
277    // Fill part to the top
278    $cy = $y;
279    while ($cy-$height < $y + $oy) {
280      $tx = $x;
281      $ty = $cy + px2pt($image->sy());
282      $this->_coords2pdf($tx, $ty);
283      $this->pdf->Image($tmpname, $tx, $ty, $image->sx() * $scale, $image->sy() * $scale, "png");
284      $cy += $height;
285    };
286
287    unlink($tmpname);
288  }
289
290  function image_scaled($image, $x, $y, $scale_x, $scale_y) {
291    $tmpname = $this->_mktempimage($image);
292
293    $this->_coords2pdf($x, $y);
294    $this->pdf->Image($tmpname, $x, $y - $image->sy() * $scale_y, $image->sx() * $scale_x, $image->sy() * $scale_y, "png");
295    unlink($tmpname);
296  }
297
298  function lineto($x, $y) {
299    $this->_coords2pdf($x, $y);
300    $this->pdf->lineto($x, $y);
301  }
302
303  function moveto($x, $y) {
304    $this->_coords2pdf($x, $y);
305    $this->pdf->moveto($x, $y);
306  }
307
308  function new_form($name) {
309    $this->pdf->add_form($name);
310  }
311
312  function next_page($height) {
313    $this->pdf->AddPage(mm2pt($this->media->width()), mm2pt($this->media->height()));
314
315    // Calculate coordinate of the next page bottom edge
316    $this->offset -= $height - $this->offset_delta;
317
318    // Reset the "correction" offset to it normal value
319    // Note: "correction" offset is an offset value required to avoid page breaking
320    // in the middle of text boxes
321    $this->offset_delta = 0;
322
323    $this->pdf->Translate(0, -$this->offset);
324
325    parent::next_page($height);
326  }
327
328  function reset(&$media) {
329    parent::reset($media);
330
331    $this->pdf =& new FPDF('P','pt',array(mm2pt($media->width()), mm2pt($media->height())));
332
333    if (defined('DEBUG_MODE')) {
334      $this->pdf->SetCompression(false);
335    } else {
336      $this->pdf->SetCompression(true);
337    };
338
339    $this->cx = 0;
340    $this->cy = 0;
341
342    $this->locallinks = array();
343  }
344
345  function restore() {
346    $this->pdf->Restore();
347  }
348
349  function save() {
350    $this->pdf->Save();
351  }
352
353  function setfont($name, $encoding, $size) {
354    $this->pdf->SetFont($this->findfont($name, $encoding), $encoding, $size);
355
356    return true;
357  }
358
359  function setlinewidth($x) {
360    $this->pdf->SetLineWidth($x);
361  }
362
363  // PDFLIB wrapper functions
364  function setrgbcolor($r, $g, $b)  {
365    $this->pdf->SetDrawColor($r*255, $g*255, $b*255);
366    $this->pdf->SetFillColor($r*255, $g*255, $b*255);
367    $this->pdf->SetTextColor($r*255, $g*255, $b*255);
368  }
369
370  function show_xy($text, $x, $y) {
371    $this->_coords2pdf($x, $y);
372
373    $this->pdf->Text($x, $y, $text);
374  }
375
376  function stroke() {
377    $this->pdf->stroke();
378  }
379
380  function stringwidth($string, $name, $encoding, $size) {
381    $this->setfont($name, $encoding, $size);
382    $width = $this->pdf->GetStringWidth($string);
383    return $width;
384  }
385
386  function _show_watermark($watermark) {
387    $this->pdf->SetFont("Helvetica", "iso-8859-1", 100);
388
389    $x = $this->left + $this->width / 2;
390    $y = $this->bottom  + $this->height / 2 - $this->offset;
391    $this->_coords2pdf($x, $y);
392
393    $this->pdf->SetTextRendering(1);
394    $this->pdf->SetDecoration(false, false, false);
395    $this->pdf->Translate($x, $y);
396    $this->pdf->Rotate(60);
397
398    $tx = -$this->pdf->GetStringWidth($watermark)/2;
399    $ty = -50;
400    $this->_coords2pdf($tx, $ty);
401
402    // By default, "watermark" is rendered in black color
403    $this->setrgbcolor(0,0,0);
404
405    $this->pdf->Text($tx,
406                     $ty,
407                     $watermark);
408  }
409
410  function _mktempimage($image) {
411    $tempnam = tempnam(WRITER_TEMPDIR, WRITER_FILE_PREFIX);
412
413    switch ($image->get_type()) {
414    case 'image/png':
415      $filename = $tempnam . '.png';
416      imagepng($image->get_handle(), $filename);
417      break;
418
419    case 'image/jpeg':
420    default:
421      $filename = $tempnam . '.jpg';
422      imagejpeg($image->get_handle(), $filename);
423      break;
424    }
425
426    unlink($tempnam);
427    return $filename;
428  }
429}
430?>