/lib/plugins/rfpdf/lib/rfpdf/fpdf.rb
Ruby | 1632 lines | 1317 code | 145 blank | 170 comment | 163 complexity | 7544c2319f2234d41bfd3a3c5890a365 MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- # Ruby FPDF 1.53d
- # FPDF 1.53 by Olivier Plathey ported to Ruby by Brian Ollenberger
- # Copyright 2005 Brian Ollenberger
- # Please retain this entire copyright notice. If you distribute any
- # modifications, place an additional comment here that clearly indicates
- # that it was modified. You may (but are not send any useful modifications that you make
- # back to me at http://zeropluszero.com/software/fpdf/
- # Bug fixes, examples, external fonts, JPEG support, and upgrade to version
- # 1.53 contributed by Kim Shrier.
- #
- # Bookmark support contributed by Sylvain Lafleur.
- #
- # EPS support contributed by Thiago Jackiw, ported from the PHP version by Valentin Schmidt.
- #
- # Bookmarks contributed by Sylvain Lafleur.
- #
- # 1.53 contributed by Ed Moss
- # Make sure all \n references are inside double quotes - Fix some multicell bugs
- # Handle "\n" at the beginning of a string
- # Bookmarks contributed by Sylvain Lafleur.
- require 'date'
- require 'zlib'
- class FPDF
- include RFPDF
-
- attr_accessor :default_font
-
- FPDF_VERSION = '1.53d'
- Charwidths = {
- 'courier'=>[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600],
-
- 'courierB'=>[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600],
-
- 'courierI'=>[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600],
-
- 'courierBI'=>[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600],
-
- 'helvetica'=>[278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 350, 556, 350, 222, 556, 333, 1000, 556, 556, 333, 1000, 667, 333, 1000, 350, 611, 350, 350, 222, 222, 333, 333, 350, 556, 1000, 333, 1000, 500, 333, 944, 350, 500, 667, 278, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 333, 737, 333, 400, 584, 333, 333, 333, 556, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 584, 611, 556, 556, 556, 556, 500, 556, 500],
-
- 'helveticaB'=>[278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 350, 556, 350, 278, 556, 500, 1000, 556, 556, 333, 1000, 667, 333, 1000, 350, 611, 350, 350, 278, 278, 500, 500, 350, 556, 1000, 333, 1000, 556, 333, 944, 350, 500, 667, 278, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 333, 737, 333, 400, 584, 333, 333, 333, 611, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 584, 611, 611, 611, 611, 611, 556, 611, 556],
-
- 'helveticaI'=>[278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 350, 556, 350, 222, 556, 333, 1000, 556, 556, 333, 1000, 667, 333, 1000, 350, 611, 350, 350, 222, 222, 333, 333, 350, 556, 1000, 333, 1000, 500, 333, 944, 350, 500, 667, 278, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 333, 737, 333, 400, 584, 333, 333, 333, 556, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 584, 611, 556, 556, 556, 556, 500, 556, 500],
-
- 'helveticaBI'=>[278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 350, 556, 350, 278, 556, 500, 1000, 556, 556, 333, 1000, 667, 333, 1000, 350, 611, 350, 350, 278, 278, 500, 500, 350, 556, 1000, 333, 1000, 556, 333, 944, 350, 500, 667, 278, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 333, 737, 333, 400, 584, 333, 333, 333, 611, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 584, 611, 611, 611, 611, 611, 556, 611, 556],
-
- 'times'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 333, 408, 500, 500, 833, 778, 180, 333, 333, 500, 564, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 564, 564, 564, 444, 921, 722, 667, 667, 722, 611, 556, 722, 722, 333, 389, 722, 611, 889, 722, 722, 556, 722, 667, 556, 611, 722, 722, 944, 722, 722, 611, 333, 278, 333, 469, 500, 333, 444, 500, 444, 500, 444, 333, 500, 500, 278, 278, 500, 278, 778, 500, 500, 500, 500, 333, 389, 278, 500, 500, 722, 500, 500, 444, 480, 200, 480, 541, 350, 500, 350, 333, 500, 444, 1000, 500, 500, 333, 1000, 556, 333, 889, 350, 611, 350, 350, 333, 333, 444, 444, 350, 500, 1000, 333, 980, 389, 333, 722, 350, 444, 722, 250, 333, 500, 500, 500, 500, 200, 500, 333, 760, 276, 500, 564, 333, 760, 333, 400, 564, 300, 300, 333, 500, 453, 250, 333, 300, 310, 500, 750, 750, 750, 444, 722, 722, 722, 722, 722, 722, 889, 667, 611, 611, 611, 611, 333, 333, 333, 333, 722, 722, 722, 722, 722, 722, 722, 564, 722, 722, 722, 722, 722, 722, 556, 500, 444, 444, 444, 444, 444, 444, 667, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 500, 500, 500, 500, 500, 500, 564, 500, 500, 500, 500, 500, 500, 500, 500],
-
- 'timesB'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 333, 555, 500, 500, 1000, 833, 278, 333, 333, 500, 570, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, 930, 722, 667, 722, 722, 667, 611, 778, 778, 389, 500, 778, 667, 944, 722, 778, 611, 778, 722, 556, 667, 722, 722, 1000, 722, 722, 667, 333, 278, 333, 581, 500, 333, 500, 556, 444, 556, 444, 333, 500, 556, 278, 333, 556, 278, 833, 556, 500, 556, 556, 444, 389, 333, 556, 500, 722, 500, 500, 444, 394, 220, 394, 520, 350, 500, 350, 333, 500, 500, 1000, 500, 500, 333, 1000, 556, 333, 1000, 350, 667, 350, 350, 333, 333, 500, 500, 350, 500, 1000, 333, 1000, 389, 333, 722, 350, 444, 722, 250, 333, 500, 500, 500, 500, 220, 500, 333, 747, 300, 500, 570, 333, 747, 333, 400, 570, 300, 300, 333, 556, 540, 250, 333, 300, 330, 500, 750, 750, 750, 500, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 389, 389, 389, 389, 722, 722, 778, 778, 778, 778, 778, 570, 778, 722, 722, 722, 722, 722, 611, 556, 500, 500, 500, 500, 500, 500, 722, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 556, 500, 500, 500, 500, 500, 570, 500, 556, 556, 556, 556, 500, 556, 500],
-
- 'timesI'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 333, 420, 500, 500, 833, 778, 214, 333, 333, 500, 675, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 675, 675, 675, 500, 920, 611, 611, 667, 722, 611, 611, 722, 722, 333, 444, 667, 556, 833, 667, 722, 611, 722, 611, 500, 556, 722, 611, 833, 611, 556, 556, 389, 278, 389, 422, 500, 333, 500, 500, 444, 500, 444, 278, 500, 500, 278, 278, 444, 278, 722, 500, 500, 500, 500, 389, 389, 278, 500, 444, 667, 444, 444, 389, 400, 275, 400, 541, 350, 500, 350, 333, 500, 556, 889, 500, 500, 333, 1000, 500, 333, 944, 350, 556, 350, 350, 333, 333, 556, 556, 350, 500, 889, 333, 980, 389, 333, 667, 350, 389, 556, 250, 389, 500, 500, 500, 500, 275, 500, 333, 760, 276, 500, 675, 333, 760, 333, 400, 675, 300, 300, 333, 500, 523, 250, 333, 300, 310, 500, 750, 750, 750, 500, 611, 611, 611, 611, 611, 611, 889, 667, 611, 611, 611, 611, 333, 333, 333, 333, 722, 667, 722, 722, 722, 722, 722, 675, 722, 722, 722, 722, 722, 556, 611, 500, 500, 500, 500, 500, 500, 500, 667, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 500, 500, 500, 500, 500, 500, 675, 500, 500, 500, 500, 500, 444, 500, 444],
-
- 'timesBI'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 389, 555, 500, 500, 833, 778, 278, 333, 333, 500, 570, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, 832, 667, 667, 667, 722, 667, 667, 722, 778, 389, 500, 667, 611, 889, 722, 722, 611, 722, 667, 556, 611, 722, 667, 889, 667, 611, 611, 333, 278, 333, 570, 500, 333, 500, 500, 444, 500, 444, 333, 500, 556, 278, 278, 500, 278, 778, 556, 500, 500, 500, 389, 389, 278, 556, 444, 667, 500, 444, 389, 348, 220, 348, 570, 350, 500, 350, 333, 500, 500, 1000, 500, 500, 333, 1000, 556, 333, 944, 350, 611, 350, 350, 333, 333, 500, 500, 350, 500, 1000, 333, 1000, 389, 333, 722, 350, 389, 611, 250, 389, 500, 500, 500, 500, 220, 500, 333, 747, 266, 500, 606, 333, 747, 333, 400, 570, 300, 300, 333, 576, 500, 250, 333, 300, 300, 500, 750, 750, 750, 500, 667, 667, 667, 667, 667, 667, 944, 667, 667, 667, 667, 667, 389, 389, 389, 389, 722, 722, 722, 722, 722, 722, 722, 570, 722, 722, 722, 722, 722, 611, 611, 500, 500, 500, 500, 500, 500, 500, 722, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 556, 500, 500, 500, 500, 500, 570, 500, 556, 556, 556, 556, 444, 500, 444],
-
- 'symbol'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 333, 713, 500, 549, 833, 778, 439, 333, 333, 500, 549, 250, 549, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 549, 549, 549, 444, 549, 722, 667, 722, 612, 611, 763, 603, 722, 333, 631, 722, 686, 889, 722, 722, 768, 741, 556, 592, 611, 690, 439, 768, 645, 795, 611, 333, 863, 333, 658, 500, 500, 631, 549, 549, 494, 439, 521, 411, 603, 329, 603, 549, 549, 576, 521, 549, 549, 521, 549, 603, 439, 576, 713, 686, 493, 686, 494, 480, 200, 480, 549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 750, 620, 247, 549, 167, 713, 500, 753, 753, 753, 753, 1042, 987, 603, 987, 603, 400, 549, 411, 549, 549, 713, 494, 460, 549, 549, 549, 549, 1000, 603, 1000, 658, 823, 686, 795, 987, 768, 768, 823, 768, 768, 713, 713, 713, 713, 713, 713, 713, 768, 713, 790, 790, 890, 823, 549, 250, 713, 603, 603, 1042, 987, 603, 987, 603, 494, 329, 790, 790, 786, 713, 384, 384, 384, 384, 384, 384, 494, 494, 494, 494, 0, 329, 274, 686, 686, 686, 384, 384, 384, 384, 384, 384, 494, 494, 494, 0],
-
- 'zapfdingbats'=>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, 974, 961, 974, 980, 719, 789, 790, 791, 690, 960, 939, 549, 855, 911, 933, 911, 945, 974, 755, 846, 762, 761, 571, 677, 763, 760, 759, 754, 494, 552, 537, 577, 692, 786, 788, 788, 790, 793, 794, 816, 823, 789, 841, 823, 833, 816, 831, 923, 744, 723, 749, 790, 792, 695, 776, 768, 792, 759, 707, 708, 682, 701, 826, 815, 789, 789, 707, 687, 696, 689, 786, 787, 713, 791, 785, 791, 873, 761, 762, 762, 759, 759, 892, 892, 788, 784, 438, 138, 277, 415, 392, 392, 668, 668, 0, 390, 390, 317, 317, 276, 276, 509, 509, 410, 410, 234, 234, 334, 334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 732, 544, 544, 910, 667, 760, 760, 776, 595, 694, 626, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 894, 838, 1016, 458, 748, 924, 748, 918, 927, 928, 928, 834, 873, 828, 924, 924, 917, 930, 931, 463, 883, 836, 836, 867, 867, 696, 696, 874, 0, 874, 760, 946, 771, 865, 771, 888, 967, 888, 831, 873, 927, 970, 918, 0]
- }
- def initialize(orientation='P', unit='mm', format='A4')
- # Initialization of properties
- @page=0
- @n=2
- @buffer=''
- @pages=[]
- @OrientationChanges=[]
- @state=0
- @default_font = "arial"
- @fonts={}
- @FontFiles={}
- @diffs=[]
- @images={}
- @links=[]
- @PageLinks={}
- @InFooter=false
- @FontFamily=''
- @FontStyle=''
- @FontSizePt=12
- @underline= false
- @DrawColor='0 G'
- @FillColor='0 g'
- @TextColor='0 g'
- @ColorFlag=false
- @ws=0
- @offsets=[]
- # Standard fonts
- @CoreFonts={}
- @CoreFonts['courier']='Courier'
- @CoreFonts['courierB']='Courier-Bold'
- @CoreFonts['courierI']='Courier-Oblique'
- @CoreFonts['courierBI']='Courier-BoldOblique'
- @CoreFonts['helvetica']='Helvetica'
- @CoreFonts['helveticaB']='Helvetica-Bold'
- @CoreFonts['helveticaI']='Helvetica-Oblique'
- @CoreFonts['helveticaBI']='Helvetica-BoldOblique'
- @CoreFonts['times']='Times-Roman'
- @CoreFonts['timesB']='Times-Bold'
- @CoreFonts['timesI']='Times-Italic'
- @CoreFonts['timesBI']='Times-BoldItalic'
- @CoreFonts['symbol']='Symbol'
- @CoreFonts['zapfdingbats']='ZapfDingbats'
- # Scale factor
- if unit=='pt'
- @k=1
- elsif unit=='mm'
- @k=72/25.4
- elsif unit=='cm'
- @k=72/2.54;
- elsif unit=='in'
- @k=72
- else
- raise 'Incorrect unit: '+unit
- end
- # Page format
- if format.is_a? String
- format.downcase!
- if format=='a3'
- format=[841.89,1190.55]
- elsif format=='a4'
- format=[595.28,841.89]
- elsif format=='a5'
- format=[420.94,595.28]
- elsif format=='letter'
- format=[612,792]
- elsif format=='legal'
- format=[612,1008]
- else
- raise 'Unknown page format: '+format
- end
- @fwPt,@fhPt=format
- else
- @fwPt=format[0]*@k
- @fhPt=format[1]*@k
- end
- @fw=@fwPt/@k;
- @fh=@fhPt/@k;
- # Page orientation
- orientation.downcase!
- if orientation=='p' or orientation=='portrait'
- @DefOrientation='P'
- @wPt=@fwPt
- @hPt=@fhPt
- elsif orientation=='l' or orientation=='landscape'
- @DefOrientation='L'
- @wPt=@fhPt
- @hPt=@fwPt
- else
- raise 'Incorrect orientation: '+orientation
- end
- @CurOrientation=@DefOrientation
- @w=@wPt/@k
- @h=@hPt/@k
- # Page margins (1 cm)
- margin=28.35/@k
- SetMargins(margin,margin)
- # Interior cell margin (1 mm)
- @cMargin=margin/10
- # Line width (0.2 mm)
- @LineWidth=0.567/@k
- # Automatic page break
- SetAutoPageBreak(true,2*margin)
- # Full width display mode
- SetDisplayMode('fullwidth')
- # Enable compression
- SetCompression(true)
- # Set default PDF version number
- @PDFVersion='1.3'
- end
- def GetMargins()
- return @lMargin, @tMargin, @rMargin
- end
- def SetMargins(left, top, right=-1)
- # Set left, top and right margins
- @lMargin=left
- @tMargin=top
- right=left if right==-1
- @rMargin=right
- end
- def SetLeftMargin(margin)
- # Set left margin
- @lMargin=margin
- @x=margin if @page>0 and @x<margin
- end
- def SetTopMargin(margin)
- # Set top margin
- @tMargin=margin
- end
- def SetRightMargin(margin)
- #Set right margin
- @rMargin=margin
- end
- def SetAutoPageBreak(auto, margin=0)
- # Set auto page break mode and triggering margin
- @AutoPageBreak=auto
- @bMargin=margin
- @PageBreakTrigger=@h-margin
- end
- def SetDisplayMode(zoom, layout='continuous')
- # Set display mode in viewer
- if zoom=='fullpage' or zoom=='fullwidth' or zoom=='real' or
- zoom=='default' or not zoom.kind_of? String
- @ZoomMode=zoom;
- elsif zoom=='zoom'
- @ZoomMode=layout
- else
- raise 'Incorrect zoom display mode: '+zoom
- end
- if layout=='single' or layout=='continuous' or layout=='two' or
- layout=='default'
- @LayoutMode=layout
- elsif zoom!='zoom'
- raise 'Incorrect layout display mode: '+layout
- end
- end
- def SetCompression(compress)
- # Set page compression
- @compress = compress
- end
- def SetTitle(title)
- # Title of document
- @title=title
- end
- def SetSubject(subject)
- # Subject of document
- @subject=subject
- end
- def SetAuthor(author)
- # Author of document
- @author=author
- end
- def SetKeywords(keywords)
- # Keywords of document
- @keywords=keywords
- end
- def SetCreator(creator)
- # Creator of document
- @creator=creator
- end
- def AliasNbPages(aliasnb='{nb}')
- # Define an alias for total number of pages
- @AliasNbPages=aliasnb
- end
-
- def Error(msg)
- raise 'FPDF error: '+msg
- end
- def Open
- # Begin document
- @state=1
- end
- def Close
- # Terminate document
- return if @state==3
- self.AddPage if @page==0
- # Page footer
- @InFooter=true
- self.Footer
- @InFooter=false
- # Close page
- endpage
- # Close document
- enddoc
- end
- def AddPage(orientation='')
- # Start a new page
- self.Open if @state==0
- family=@FontFamily
- style=@FontStyle+(@underline ? 'U' : '')
- size=@FontSizePt
- lw=@LineWidth
- dc=@DrawColor
- fc=@FillColor
- tc=@TextColor
- cf=@ColorFlag
- if @page>0
- # Page footer
- @InFooter=true
- self.Footer
- @InFooter=false
- # Close page
- endpage
- end
- # Start new page
- beginpage(orientation)
- # Set line cap style to square
- out('2 J')
- # Set line width
- @LineWidth=lw
- out(sprintf('%.2f w',lw*@k))
- # Set font
- SetFont(family,style,size) if family
- # Set colors
- @DrawColor=dc
- out(dc) if dc!='0 G'
- @FillColor=fc
- out(fc) if fc!='0 g'
- @TextColor=tc
- @ColorFlag=cf
- # Page header
- self.Header
- # Restore line width
- if @LineWidth!=lw
- @LineWidth=lw
- out(sprintf('%.2f w',lw*@k))
- end
- # Restore font
- self.SetFont(family,style,size) if family
- # Restore colors
- if @DrawColor!=dc
- @DrawColor=dc
- out(dc)
- end
- if @FillColor!=fc
- @FillColor=fc
- out(fc)
- end
- @TextColor=tc
- @ColorFlag=cf
- end
- alias_method :add_page, :AddPage
- def Header
- # To be implemented in your inherited class
- end
- def Footer
- # To be implemented in your inherited class
- end
- def PageNo
- # Get current page number
- @page
- end
- def SetDrawColor(r,g=-1,b=-1)
- # Set color for all stroking operations
- if (r==0 and g==0 and b==0) or g==-1
- @DrawColor=sprintf('%.3f G',r/255.0)
- else
- @DrawColor=sprintf('%.3f %.3f %.3f RG',r/255.0,g/255.0,b/255.0)
- end
- out(@DrawColor) if(@page>0)
- end
- def SetFillColor(r,g=-1,b=-1)
- # Set color for all filling operations
- if (r==0 and g==0 and b==0) or g==-1
- @FillColor=sprintf('%.3f g',r/255.0)
- else
- @FillColor=sprintf('%.3f %.3f %.3f rg',r/255.0,g/255.0,b/255.0)
- end
- @ColorFlag=(@FillColor!=@TextColor)
- out(@FillColor) if(@page>0)
- end
- def SetTextColor(r,g=-1,b=-1)
- # Set color for text
- if (r==0 and g==0 and b==0) or g==-1
- @TextColor=sprintf('%.3f g',r/255.0)
- else
- @TextColor=sprintf('%.3f %.3f %.3f rg',r/255.0,g/255.0,b/255.0)
- end
- @ColorFlag=(@FillColor!=@TextColor)
- end
-
- def GetCharWidth(widths, index)
- if index.is_a?(String)
- widths[index.ord]
- else
- widths[index]
- end
- end
- def GetStringWidth(s)
- # Get width of a string in the current font
- cw=@CurrentFont['cw']
- w=0
- s.each_byte do |c|
- w=w+GetCharWidth(cw, c)
- end
- w*@FontSize/1000.0
- end
- def SetLineWidth(width)
- # Set line width
- @LineWidth=width
- out(sprintf('%.2f w',width*@k)) if @page>0
- end
- def Circle(mid_x, mid_y, radius, style='')
- mid_y = (@h-mid_y)*@k
- out(sprintf("q\n")) # postscript content in pdf
- # init line type etc. with /GSD gs G g (grey) RG rg (RGB) w=line witdh etc.
- out(sprintf("1 j\n")) # line join
- # translate ("move") circle to mid_y, mid_y
- out(sprintf("1 0 0 1 %f %f cm", mid_x, mid_y))
- kappa = 0.5522847498307933984022516322796
- # Quadrant 1
- x_s = 0.0 # 12 o'clock
- y_s = 0.0 + radius
- x_e = 0.0 + radius # 3 o'clock
- y_e = 0.0
- out(sprintf("%f %f m\n", x_s, y_s)) # move to 12 o'clock
- # cubic bezier control point 1, start height and kappa * radius to the right
- bx_e1 = x_s + (radius * kappa)
- by_e1 = y_s
- # cubic bezier control point 2, end and kappa * radius above
- bx_e2 = x_e
- by_e2 = y_e + (radius * kappa)
- # draw cubic bezier from current point to x_e/y_e with bx_e1/by_e1 and bx_e2/by_e2 as bezier control points
- out(sprintf("%f %f %f %f %f %f c\n", bx_e1, by_e1, bx_e2, by_e2, x_e, y_e))
- # Quadrant 2
- x_s = x_e
- y_s = y_e # 3 o'clock
- x_e = 0.0
- y_e = 0.0 - radius # 6 o'clock
- bx_e1 = x_s # cubic bezier point 1
- by_e1 = y_s - (radius * kappa)
- bx_e2 = x_e + (radius * kappa) # cubic bezier point 2
- by_e2 = y_e
- out(sprintf("%f %f %f %f %f %f c\n", bx_e1, by_e1, bx_e2, by_e2, x_e, y_e))
- # Quadrant 3
- x_s = x_e
- y_s = y_e # 6 o'clock
- x_e = 0.0 - radius
- y_e = 0.0 # 9 o'clock
- bx_e1 = x_s - (radius * kappa) # cubic bezier point 1
- by_e1 = y_s
- bx_e2 = x_e # cubic bezier point 2
- by_e2 = y_e - (radius * kappa)
- out(sprintf("%f %f %f %f %f %f c\n", bx_e1, by_e1, bx_e2, by_e2, x_e, y_e))
- # Quadrant 4
- x_s = x_e
- y_s = y_e # 9 o'clock
- x_e = 0.0
- y_e = 0.0 + radius # 12 o'clock
- bx_e1 = x_s # cubic bezier point 1
- by_e1 = y_s + (radius * kappa)
- bx_e2 = x_e - (radius * kappa) # cubic bezier point 2
- by_e2 = y_e
- out(sprintf("%f %f %f %f %f %f c\n", bx_e1, by_e1, bx_e2, by_e2, x_e, y_e))
- if style=='F'
- op='f'
- elsif style=='FD' or style=='DF'
- op='b'
- else
- op='s'
- end
- out(sprintf("#{op}\n")) # stroke circle, do not fill and close path
- # for filling etc. b, b*, f, f*
- out(sprintf("Q\n")) # finish postscript in PDF
- end
-
- def Line(x1, y1, x2, y2)
- # Draw a line
- out(sprintf('%.2f %.2f m %.2f %.2f l S',
- x1*@k,(@h-y1)*@k,x2*@k,(@h-y2)*@k))
- end
- def Rect(x, y, w, h, style='')
- # Draw a rectangle
- if style=='F'
- op='f'
- elsif style=='FD' or style=='DF'
- op='B'
- else
- op='S'
- end
- # x y width height re
- out(sprintf('%.2f %.2f %.2f %.2f re %s', x*@k,(@h-y)*@k,w*@k,-h*@k,op))
- end
- def AddFont(family, style='', file='')
- # Add a TrueType or Type1 font
- family = family.downcase
- family = 'helvetica' if family == 'arial'
- style = style.upcase
- style = 'BI' if style == 'IB'
- fontkey = family + style
- if @fonts.has_key?(fontkey)
- self.Error("Font already added: #{family} #{style}")
- end
- file = family.gsub(' ', '') + style.downcase + '.rb' if file == ''
- if self.class.const_defined? 'FPDF_FONTPATH'
- if FPDF_FONTPATH[-1,1] == '/'
- file = FPDF_FONTPATH + file
- else
- file = FPDF_FONTPATH + '/' + file
- end
- end
-
- # Changed from "require file" to fix bug reported by Hans Allis.
- load file
- if FontDef.desc.nil?
- self.Error("Could not include font definition file #{file}")
- end
- i = @fonts.length + 1
- @fonts[fontkey] = {'i' => i,
- 'type' => FontDef.type,
- 'name' => FontDef.name,
- 'desc' => FontDef.desc,
- 'up' => FontDef.up,
- 'ut' => FontDef.ut,
- 'cw' => FontDef.cw,
- 'enc' => FontDef.enc,
- 'file' => FontDef.file
- }
- if FontDef.diff
- # Search existing encodings
- unless @diffs.include?(FontDef.diff)
- @diffs.push(FontDef.diff)
- @fonts[fontkey]['diff'] = @diffs.length - 1
- end
- end
- if FontDef.file
- if FontDef.type == 'TrueType'
- @FontFiles[FontDef.file] = {'length1' => FontDef.originalsize}
- else
- @FontFiles[FontDef.file] = {'length1' => FontDef.size1, 'length2' => FontDef.size2}
- end
- end
- return self
- end
- def SetFont(family, style='', size=0)
- # Select a font; size given in points
- family.downcase!
- family=@FontFamily if family==''
- if family=='arial'
- family='helvetica'
- elsif family=='symbol' or family=='zapfdingbats'
- style=''
- end
- style.upcase!
- unless style.index('U').nil?
- @underline=true
- style.gsub!('U','')
- else
- @underline=false;
- end
- style='BI' if style=='IB'
- size=@FontSizePt if size==0
- # Test if font is already selected
- return if @FontFamily==family and
- @FontStyle==style and @FontSizePt==size
- # Test if used for the first time
- fontkey=family+style
- unless @fonts.has_key?(fontkey)
- if @CoreFonts.has_key?(fontkey)
- unless Charwidths.has_key?(fontkey)
- raise 'Font unavailable'
- end
- @fonts[fontkey]={
- 'i'=>@fonts.size,
- 'type'=>'core',
- 'name'=>@CoreFonts[fontkey],
- 'up'=>-100,
- 'ut'=>50,
- 'cw'=>Charwidths[fontkey]}
- else
- raise 'Font unavailable'
- end
- end
- #Select it
- @FontFamily=family
- @FontStyle=style;
- @FontSizePt=size
- @FontSize=size/@k;
- @CurrentFont=@fonts[fontkey]
- if @page>0
- out(sprintf('BT /F%d %.2f Tf ET', @CurrentFont['i'], @FontSizePt))
- end
- end
- def SetFontSize(size)
- # Set font size in points
- return if @FontSizePt==size
- @FontSizePt=size
- @FontSize=size/@k
- if @page>0
- out(sprintf('BT /F%d %.2f Tf ET',@CurrentFont['i'],@FontSizePt))
- end
- end
- def AddLink
- # Create a new internal link
- @links.push([0, 0])
- @links.size
- end
- def SetLink(link, y=0, page=-1)
- # Set destination of internal link
- y=@y if y==-1
- page=@page if page==-1
- @links[link]=[page, y]
- end
- def Link(x, y, w, h, link)
- # Put a link on the page
- @PageLinks[@page]=Array.new unless @PageLinks.has_key?(@Page)
- @PageLinks[@page].push([x*@k,@hPt-y*@k,w*@k,h*@k,link])
- end
- def Text(x, y, txt)
- # Output a string
- s=sprintf('BT %.2f %.2f Td (%s) Tj ET',x*@k,(@h-y)*@k, escape(txt));
- s=s+' '+dounderline(x,y,txt) if @underline and txt!=''
- s='q '+@TextColor+' '+s+' Q' if @ColorFlag
- out(s)
- end
- def AcceptPageBreak
- # Accept automatic page break or not
- @AutoPageBreak
- end
- def BreakThePage?(h)
- if (@y + h) > @PageBreakTrigger and !@InFooter and self.AcceptPageBreak
- true
- else
- false
- end
- end
-
- def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='')
- # Output a cell
- if self.BreakThePage?(h)
- # Automatic page break
- x=@x
- ws=@ws
- if ws>0
- @ws=0
- out('0 Tw')
- end
- self.AddPage(@CurOrientation)
- @x=x
- if ws>0
- @ws=ws
- out(sprintf('%.3f Tw',ws*@k))
- end
- end
- w=@w-@rMargin-@x if w==0
- s=''
- if fill==1 or border==1
- if fill==1
- op=(border==1) ? 'B' : 'f'
- else
- op='S'
- end
- s=sprintf('%.2f %.2f %.2f %.2f re %s ',@x*@k,(@h-@y)*@k,w*@k,-h*@k,op)
- end
- if border.is_a? String
- x=@x
- y=@y
- unless border.index('L').nil?
- s=s+sprintf('%.2f %.2f m %.2f %.2f l S ',
- x*@k,(@h-y)*@k,x*@k,(@h-(y+h))*@k)
- end
- unless border.index('T').nil?
- s=s+sprintf('%.2f %.2f m %.2f %.2f l S ',
- x*@k,(@h-y)*@k,(x+w)*@k,(@h-y)*@k)
- end
- unless border.index('R').nil?
- s=s+sprintf('%.2f %.2f m %.2f %.2f l S ',
- (x+w)*@k,(@h-y)*@k,(x+w)*@k,(@h-(y+h))*@k)
- end
- unless border.index('B').nil?
- s=s+sprintf('%.2f %.2f m %.2f %.2f l S ',
- x*@k,(@h-(y+h))*@k,(x+w)*@k,(@h-(y+h))*@k)
- end
- end
- if txt!=''
- if align=='R'
- dx=w-@cMargin-self.GetStringWidth(txt)
- elsif align=='C'
- dx=(w-self.GetStringWidth(txt))/2
- else
- dx=@cMargin
- end
- if @ColorFlag
- s=s+'q '+@TextColor+' '
- end
- s=s+sprintf('BT %.2f %.2f Td (%s) Tj ET',
- (@x+dx)*@k,(@h-(@y+0.5*h+0.3*@FontSize))*@k,escape(txt))
- s=s+' '+dounderline(@x+dx,@y+0.5*h+0.3*@FontSize,txt) if @underline
- s=s+' Q' if @ColorFlag
- if link and link != ''
- Link(@x+dx,@y+0.5*h-0.5*@FontSize,GetStringWidth(txt),@FontSize,link)
- end
- end
- out(s) if s
- @lasth=h
- if ln>0
- # Go to next line
- @y=@y+h
- @x=@lMargin if ln==1
- else
- @x=@x+w
- end
- end
- def MultiCell(w,h,txt,border=0,align='J',fill=0)
- # Output text with automatic or explicit line breaks
- cw=@CurrentFont['cw']
- w=@w-@rMargin-@x if w==0
- wmax=(w-2*@cMargin)*1000/@FontSize
- s=txt.gsub("\r",'')
- nb=s.length
- nb=nb-1 if nb>0 and s[nb-1].chr=="\n"
- b=0
- if border!=0
- if border==1
- border='LTRB'
- b='LRT'
- b2='LR'
- else
- b2=''
- b2='L' unless border.index('L').nil?
- b2=b2+'R' unless border.index('R').nil?
- b=(not border.index('T').nil?) ? (b2+'T') : b2
- end
- end
- sep=-1
- to_index=0
- from_j=0
- l=0
- ns=0
- nl=1
- while to_index<nb
- # Get next character
- char=s[to_index]
- if char=="\n"[0]
- # Explicit line break
- if @ws>0
- @ws=0
- out('0 Tw')
- end
- #Ed Moss
- end_i = to_index == 0 ? 0 : to_index - 1
- # Changed from s[from_j..to_index] to fix bug reported by Hans Allis.
- self.Cell(w,h,s[from_j..end_i],b,2,align,fill)
- #
- to_index=to_index+1
- sep=-1
- from_j=to_index
- l=0
- ns=0
- nl=nl+1
- b=b2 if border and nl==2
- else
- if char==' '[0]
- sep=to_index
- ls=l
- ns=ns+1
- end
- l=l+GetCharWidth(cw, char)
- if l>wmax
- # Automatic line break
- if sep==-1
- to_index=to_index+1 if to_index==from_j
- if @ws>0
- @ws=0
- out('0 Tw')
- end
- #Ed Moss
- self.Cell(w,h,s[from_j..to_index-1],b,2,align,fill)
- #
- else
- if align=='J'
- @ws=(ns>1) ? (wmax-ls)/1000.0*@FontSize/(ns-1) : 0
- out(sprintf('%.3f Tw',@ws*@k))
- end
- self.Cell(w,h,s[from_j..sep],b,2,align,fill)
- to_index=sep+1
- end
- sep=-1
- from_j=to_index
- l=0
- ns=0
- nl=nl+1
- b=b2 if border and nl==2
- else
- to_index=to_index+1
- end
- end
- end
- # Last chunk
- if @ws>0
- @ws=0
- out('0 Tw')
- end
- b=b+'B' if border!=0 and not border.index('B').nil?
- self.Cell(w,h,s[from_j..to_index],b,2,align,fill)
- @x=@lMargin
- end
-
- def Write(h,txt,link='')
- # Output text in flowing mode
- cw=@CurrentFont['cw']
- w=@w-@rMargin-@x
- wmax=(w-2*@cMargin)*1000/@FontSize
- s=txt.gsub("\r",'')
- nb=s.length
- sep=-1
- i=0
- j=0
- l=0
- nl=1
- while i<nb
- # Get next character
- c=s[i]
- if c=="\n"[0]
- # Explicit line break
- self.Cell(w,h,s[j,i-j],0,2,'',0,link)
- i=i+1
- sep=-1
- j=i
- l=0
- if nl==1
- @x=@lMargin
- w=@w-@rMargin-@x
- wmax=(w-2*@cMargin)*1000/@FontSize
- end
- nl=nl+1
- next
- end
- if c==' '[0]
- sep=i
- ls=l
- end
- l=l+GetCharWidth(cw, c);
- if l>wmax
- # Automatic line break
- if sep==-1
- if @x>@lMargin
- # Move to next line
- @x=@lMargin
- @y=@y+h
- w=@w-@rMargin-@x
- wmax=(w-2*@cMargin)*1000/@FontSize
- i=i+1
- nl=nl+1
- next
- end
- i=i+1 if i==j
- self.Cell(w,h,s[j,i-j],0,2,'',0,link)
- else
- self.Cell(w,h,s[j,sep-j],0,2,'',0,link)
- i=sep+1
- end
- sep=-1
- j=i
- l=0
- if nl==1
- @x=@lMargin
- w=@w-@rMargin-@x
- wmax=(w-2*@cMargin)*1000/@FontSize
- end
- nl=nl+1
- else
- i=i+1
- end
- end
- # Last chunk
- self.Cell(l/1000.0*@FontSize,h,s[j,i],0,0,'',0,link) if i!=j
- end
-
- def Image(file,x,y,w=0,h=0,type='',link='')
- # Put an image on the page
- unless @images.has_key?(file)
- # First use of image, get info
- if type==''
- pos=file.rindex('.')
- if pos.nil?
- self.Error('Image file has no extension and no type was '+
- 'specified: '+file)
- end
- type=file[pos+1..-1]
- end
- type.downcase!
- if type=='jpg' or type=='jpeg'
- info=parsejpg(file)
- elsif type=='png'
- info=parsepng(file)
- else
- self.Error('Unsupported image file type: '+type)
- end
- info['i']=@images.length+1
- @images[file]=info
- else
- info=@images[file]
- end
- #Ed Moss
- if(w==0 && h==0)
- #Put image at 72 dpi
- w=info['w']/@k;
- h=info['h']/@k;
- end
- #
- # Automatic width or height calculation
- w=h*info['w']/info['h'] if w==0
- h=w*info['h']/info['w'] if h==0
- out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q',
- w*@k,h*@k,x*@k,(@h-(y+h))*@k,info['i']))
- Link(x,y,w,h,link) if link and link != ''
- end
-
- def Ln(h='')
- # Line feed; default value is last cell height
- @x=@lMargin
- if h.kind_of?(String)
- @y=@y+@lasth
- else
- @y=@y+h
- end
- end
- def GetX
- # Get x position
- @x
- end
- def SetX(x)
- # Set x position
- if x>=0
- @x=x
- else
- @x=@w+x
- end
- end
- def GetY
- # Get y position
- @y
- end
- def SetY(y)
- # Set y position and reset x
- @x=@lMargin
- if y>=0
- @y=y
- else
- @y=@h+y
- end
- end
- def SetXY(x,y)
- # Set x and y positions
- SetY(y)
- SetX(x)
- end
-
- def Output(file=nil)
- # Output PDF to file or return as a string
-
- # Finish document if necessary
- self.Close if(@state<3)
-
- if file.nil?
- # Return as a string
- return @buffer
- else
- # Save file locally
- open(file,'wb') do |f|
- f.write(@buffer)
- end
- end
- end
- private
-
- def putpages
- nb=@page
- unless @AliasNbPages.nil? or @AliasNbPages==''
- # Replace number of pages
- 1.upto(nb) do |n|
- @pages[n].gsub!(@AliasNbPages,nb.to_s)
- end
- end
- if @DefOrientation=='P'
- wPt=@fwPt
- hPt=@fhPt
- else
- wPt=@fhPt
- hPt=@fwPt
- end
- filter=(@compress) ? '/Filter /FlateDecode ' : ''
- 1.upto(nb) do |n|
- # Page
- newobj
- out('<</Type /Page')
- out('/Parent 1 0 R')
- unless @OrientationChanges[n].nil?
- out(sprintf('/MediaBox [0 0 %.2f %.2f]',hPt,wPt))
- end
- out('/Resources 2 0 R')
- if @PageLinks[n]
- # Links
- annots='/Annots ['
- @PageLinks[n].each do |pl|
- rect=sprintf('%.2f %.2f %.2f %.2f',
- pl[0],pl[1],pl[0]+pl[2],pl[1]-pl[3])
- annots=annots+'<</Type /Annot /Subtype /Link /Rect ['+rect+
- '] /Border [0 0 0] '
- if pl[4].kind_of?(String)
- annots=annots+'/A <</S /URI /URI '+textstring(pl[4])+
- '>>>>'
- else
- l=@links[pl[4]]
- h=@OrientationChanges[l[0]].nil? ? hPt : wPt
- annots=annots+sprintf(
- '/Dest [%d 0 R /XYZ 0 %.2f null]>>',
- 1+2*l[0],h-l[1]*@k)
- end
- end
- out(annots+']')
- end
- out('/Contents '+(@n+1).to_s+' 0 R>>')
- out('endobj')
- # Page content
- p=(@compress) ? Zlib::Deflate.deflate(@pages[n]) : @pages[n]
- newobj
- out('<<'+filter+'/Length '+p.length.to_s+'>>')
- putstream(p)
- out('endobj')
- end
- # Pages root
- @offsets[1]=@buffer.length
- out('1 0 obj')
- out('<</Type /Pages')
- kids='/Kids ['
- nb.times do |i|
- kids=kids+(3+2*i).to_s+' 0 R '
- end
- out(kids+']')
- out('/Count '+nb.to_s)
- out(sprintf('/MediaBox [0 0 %.2f %.2f]',wPt,hPt))
- out('>>')
- out('endobj')
- end
-
- def putfonts
- nf=@n
- @diffs.each do |diff|
- # Encodings
- newobj
- out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences '+
- '['+diff+']>>')
- out('endobj')
- end
- @FontFiles.each do |file, info|
- # Font file embedding
- newobj
- @FontFiles[file]['n'] = @n
- if self.class.const_defined? 'FPDF_FONTPATH' then
- if FPDF_FONTPATH[-1,1] == '/' then
- file = FPDF_FONTPATH + file
- else
- file = FPDF_FONTPATH + '/' + file
- end
- end
- size = File.size(file)
- unless File.exists?(file)
- Error('Font file not found')
- end
- out('<</Length ' + size.to_s)
- if file[-2, 2] == '.z' then
- out('/Filter /FlateDecode')
- end
- out('/Length1 ' + info['length1'])
- out('/Length2 ' + info['length2'] + ' /Length3 0') if info['length2']
- out('>>')
- open(file, 'rb') do |f|
- putstream(f.read())
- end
- out('endobj')
- end
- file = 0
- @fonts.each do |k, font|
- # Font objects
- @fonts[k]['n']=@n+1
- type=font['type']
- name=font['name']
- if type=='core'
- # Standard font
- newobj
- out('<</Type /Font')
- out('/BaseFont /'+name)
- out('/Subtype /Type1')
- if name!='Symbol' and name!='ZapfDingbats'
- out('/Encoding /WinAnsiEncoding')
- end
- out('>>')
- out('endobj')
- elsif type=='Type1' or type=='TrueType'
- # Additional Type1 or TrueType font
- newobj
- out('<</Type /Font')
- out('/BaseFont /'+name)
- out('/Subtype /'+type)
- out('/FirstChar 32 /LastChar 255')
- out('/Widths '+(@n+1).to_s+' 0 R')
- out('/FontDescriptor '+(@n+2).to_s+' 0 R')
- if font['enc'] and font['enc'] != ''
- unless font['diff'].nil?
- out('/Encoding '+(nf+font['diff']).to_s+' 0 R')
- else
- out('/Encoding /WinAnsiEncoding')
- end
- end
- out('>>')
- out('endobj')
- # Widths
- newobj
- cw=font['cw']
- s='['
- 32.upto(255) do |i|
- s << GetCharWidth(cw, i).to_s + ' '
- end
- out(s+']')
- out('endobj')
- # Descriptor
- newobj
- s='<</Type /FontDescriptor /FontName /'+name
- font['desc'].each …
Large files files are truncated, but you can click here to view the full file