@@ -1,1550 +1,1558 | |||||
1 | # Ruby FPDF 1.53d |
|
1 | # Ruby FPDF 1.53d | |
2 | # FPDF 1.53 by Olivier Plathey ported to Ruby by Brian Ollenberger |
|
2 | # FPDF 1.53 by Olivier Plathey ported to Ruby by Brian Ollenberger | |
3 | # Copyright 2005 Brian Ollenberger |
|
3 | # Copyright 2005 Brian Ollenberger | |
4 | # Please retain this entire copyright notice. If you distribute any |
|
4 | # Please retain this entire copyright notice. If you distribute any | |
5 | # modifications, place an additional comment here that clearly indicates |
|
5 | # modifications, place an additional comment here that clearly indicates | |
6 | # that it was modified. You may (but are not send any useful modifications that you make |
|
6 | # that it was modified. You may (but are not send any useful modifications that you make | |
7 | # back to me at http://zeropluszero.com/software/fpdf/ |
|
7 | # back to me at http://zeropluszero.com/software/fpdf/ | |
8 |
|
8 | |||
9 | # Bug fixes, examples, external fonts, JPEG support, and upgrade to version |
|
9 | # Bug fixes, examples, external fonts, JPEG support, and upgrade to version | |
10 | # 1.53 contributed by Kim Shrier. |
|
10 | # 1.53 contributed by Kim Shrier. | |
11 | # |
|
11 | # | |
12 | # Bookmark support contributed by Sylvain Lafleur. |
|
12 | # Bookmark support contributed by Sylvain Lafleur. | |
13 | # |
|
13 | # | |
14 | # EPS support contributed by Thiago Jackiw, ported from the PHP version by Valentin Schmidt. |
|
14 | # EPS support contributed by Thiago Jackiw, ported from the PHP version by Valentin Schmidt. | |
15 | # |
|
15 | # | |
16 | # Bookmarks contributed by Sylvain Lafleur. |
|
16 | # Bookmarks contributed by Sylvain Lafleur. | |
17 | # |
|
17 | # | |
18 | # 1.53 contributed by Ed Moss |
|
18 | # 1.53 contributed by Ed Moss | |
19 | # Handle '\n' at the beginning of a string |
|
19 | # Handle '\n' at the beginning of a string | |
20 | # Bookmarks contributed by Sylvain Lafleur. |
|
20 | # Bookmarks contributed by Sylvain Lafleur. | |
21 |
|
21 | |||
22 | require 'date' |
|
22 | require 'date' | |
23 | require 'zlib' |
|
23 | require 'zlib' | |
24 |
|
24 | |||
25 | class FPDF |
|
25 | class FPDF | |
26 | FPDF_VERSION = '1.53d' |
|
26 | FPDF_VERSION = '1.53d' | |
27 |
|
27 | |||
28 | Charwidths = { |
|
28 | Charwidths = { | |
29 | '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], |
|
29 | '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], | |
30 |
|
30 | |||
31 | '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], |
|
31 | '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], | |
32 |
|
32 | |||
33 | '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], |
|
33 | '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], | |
34 |
|
34 | |||
35 | '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], |
|
35 | '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], | |
36 |
|
36 | |||
37 | '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], |
|
37 | '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], | |
38 |
|
38 | |||
39 | '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], |
|
39 | '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], | |
40 |
|
40 | |||
41 | '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], |
|
41 | '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], | |
42 |
|
42 | |||
43 | '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], |
|
43 | '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], | |
44 |
|
44 | |||
45 | '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], |
|
45 | '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], | |
46 |
|
46 | |||
47 | '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], |
|
47 | '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], | |
48 |
|
48 | |||
49 | '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], |
|
49 | '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], | |
50 |
|
50 | |||
51 | '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], |
|
51 | '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], | |
52 |
|
52 | |||
53 | '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], |
|
53 | '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], | |
54 |
|
54 | |||
55 | '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] |
|
55 | '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] | |
56 | } |
|
56 | } | |
57 |
|
57 | |||
58 | def initialize(orientation='P', unit='mm', format='A4') |
|
58 | def initialize(orientation='P', unit='mm', format='A4') | |
59 | # Initialization of properties |
|
59 | # Initialization of properties | |
60 | @page=0 |
|
60 | @page=0 | |
61 | @n=2 |
|
61 | @n=2 | |
62 | @buffer='' |
|
62 | @buffer='' | |
63 | @pages=[] |
|
63 | @pages=[] | |
64 | @OrientationChanges=[] |
|
64 | @OrientationChanges=[] | |
65 | @state=0 |
|
65 | @state=0 | |
66 | @fonts={} |
|
66 | @fonts={} | |
67 | @FontFiles={} |
|
67 | @FontFiles={} | |
68 | @diffs=[] |
|
68 | @diffs=[] | |
69 | @images={} |
|
69 | @images={} | |
70 | @links=[] |
|
70 | @links=[] | |
71 | @PageLinks={} |
|
71 | @PageLinks={} | |
72 | @InFooter=false |
|
72 | @InFooter=false | |
73 | @FontFamily='' |
|
73 | @FontFamily='' | |
74 | @FontStyle='' |
|
74 | @FontStyle='' | |
75 | @FontSizePt=12 |
|
75 | @FontSizePt=12 | |
76 | @underline= false |
|
76 | @underline= false | |
77 | @DrawColor='0 G' |
|
77 | @DrawColor='0 G' | |
78 | @FillColor='0 g' |
|
78 | @FillColor='0 g' | |
79 | @TextColor='0 g' |
|
79 | @TextColor='0 g' | |
80 | @ColorFlag=false |
|
80 | @ColorFlag=false | |
81 | @ws=0 |
|
81 | @ws=0 | |
82 | @offsets=[] |
|
82 | @offsets=[] | |
83 |
|
83 | |||
84 | # Standard fonts |
|
84 | # Standard fonts | |
85 | @CoreFonts={} |
|
85 | @CoreFonts={} | |
86 | @CoreFonts['courier']='Courier' |
|
86 | @CoreFonts['courier']='Courier' | |
87 | @CoreFonts['courierB']='Courier-Bold' |
|
87 | @CoreFonts['courierB']='Courier-Bold' | |
88 | @CoreFonts['courierI']='Courier-Oblique' |
|
88 | @CoreFonts['courierI']='Courier-Oblique' | |
89 | @CoreFonts['courierBI']='Courier-BoldOblique' |
|
89 | @CoreFonts['courierBI']='Courier-BoldOblique' | |
90 | @CoreFonts['helvetica']='Helvetica' |
|
90 | @CoreFonts['helvetica']='Helvetica' | |
91 | @CoreFonts['helveticaB']='Helvetica-Bold' |
|
91 | @CoreFonts['helveticaB']='Helvetica-Bold' | |
92 | @CoreFonts['helveticaI']='Helvetica-Oblique' |
|
92 | @CoreFonts['helveticaI']='Helvetica-Oblique' | |
93 | @CoreFonts['helveticaBI']='Helvetica-BoldOblique' |
|
93 | @CoreFonts['helveticaBI']='Helvetica-BoldOblique' | |
94 | @CoreFonts['times']='Times-Roman' |
|
94 | @CoreFonts['times']='Times-Roman' | |
95 | @CoreFonts['timesB']='Times-Bold' |
|
95 | @CoreFonts['timesB']='Times-Bold' | |
96 | @CoreFonts['timesI']='Times-Italic' |
|
96 | @CoreFonts['timesI']='Times-Italic' | |
97 | @CoreFonts['timesBI']='Times-BoldItalic' |
|
97 | @CoreFonts['timesBI']='Times-BoldItalic' | |
98 | @CoreFonts['symbol']='Symbol' |
|
98 | @CoreFonts['symbol']='Symbol' | |
99 | @CoreFonts['zapfdingbats']='ZapfDingbats' |
|
99 | @CoreFonts['zapfdingbats']='ZapfDingbats' | |
100 |
|
100 | |||
101 | # Scale factor |
|
101 | # Scale factor | |
102 | if unit=='pt' |
|
102 | if unit=='pt' | |
103 | @k=1 |
|
103 | @k=1 | |
104 | elsif unit=='mm' |
|
104 | elsif unit=='mm' | |
105 | @k=72/25.4 |
|
105 | @k=72/25.4 | |
106 | elsif unit=='cm' |
|
106 | elsif unit=='cm' | |
107 | @k=72/2.54; |
|
107 | @k=72/2.54; | |
108 | elsif unit=='in' |
|
108 | elsif unit=='in' | |
109 | @k=72 |
|
109 | @k=72 | |
110 | else |
|
110 | else | |
111 | raise 'Incorrect unit: '+unit |
|
111 | raise 'Incorrect unit: '+unit | |
112 | end |
|
112 | end | |
113 |
|
113 | |||
114 | # Page format |
|
114 | # Page format | |
115 | if format.is_a? String |
|
115 | if format.is_a? String | |
116 | format.downcase! |
|
116 | format.downcase! | |
117 | if format=='a3' |
|
117 | if format=='a3' | |
118 | format=[841.89,1190.55] |
|
118 | format=[841.89,1190.55] | |
119 | elsif format=='a4' |
|
119 | elsif format=='a4' | |
120 | format=[595.28,841.89] |
|
120 | format=[595.28,841.89] | |
121 | elsif format=='a5' |
|
121 | elsif format=='a5' | |
122 | format=[420.94,595.28] |
|
122 | format=[420.94,595.28] | |
123 | elsif format=='letter' |
|
123 | elsif format=='letter' | |
124 | format=[612,792] |
|
124 | format=[612,792] | |
125 | elsif format=='legal' |
|
125 | elsif format=='legal' | |
126 | format=[612,1008] |
|
126 | format=[612,1008] | |
127 | else |
|
127 | else | |
128 | raise 'Unknown page format: '+format |
|
128 | raise 'Unknown page format: '+format | |
129 | end |
|
129 | end | |
130 | @fwPt,@fhPt=format |
|
130 | @fwPt,@fhPt=format | |
131 | else |
|
131 | else | |
132 | @fwPt=format[0]*@k |
|
132 | @fwPt=format[0]*@k | |
133 | @fhPt=format[1]*@k |
|
133 | @fhPt=format[1]*@k | |
134 | end |
|
134 | end | |
135 | @fw=@fwPt/@k; |
|
135 | @fw=@fwPt/@k; | |
136 | @fh=@fhPt/@k; |
|
136 | @fh=@fhPt/@k; | |
137 |
|
137 | |||
138 | # Page orientation |
|
138 | # Page orientation | |
139 | orientation.downcase! |
|
139 | orientation.downcase! | |
140 | if orientation=='p' or orientation=='portrait' |
|
140 | if orientation=='p' or orientation=='portrait' | |
141 | @DefOrientation='P' |
|
141 | @DefOrientation='P' | |
142 | @wPt=@fwPt |
|
142 | @wPt=@fwPt | |
143 | @hPt=@fhPt |
|
143 | @hPt=@fhPt | |
144 | elsif orientation=='l' or orientation=='landscape' |
|
144 | elsif orientation=='l' or orientation=='landscape' | |
145 | @DefOrientation='L' |
|
145 | @DefOrientation='L' | |
146 | @wPt=@fhPt |
|
146 | @wPt=@fhPt | |
147 | @hPt=@fwPt |
|
147 | @hPt=@fwPt | |
148 | else |
|
148 | else | |
149 | raise 'Incorrect orientation: '+orientation |
|
149 | raise 'Incorrect orientation: '+orientation | |
150 | end |
|
150 | end | |
151 | @CurOrientation=@DefOrientation |
|
151 | @CurOrientation=@DefOrientation | |
152 | @w=@wPt/@k |
|
152 | @w=@wPt/@k | |
153 | @h=@hPt/@k |
|
153 | @h=@hPt/@k | |
154 |
|
154 | |||
155 | # Page margins (1 cm) |
|
155 | # Page margins (1 cm) | |
156 | margin=28.35/@k |
|
156 | margin=28.35/@k | |
157 | SetMargins(margin,margin) |
|
157 | SetMargins(margin,margin) | |
158 | # Interior cell margin (1 mm) |
|
158 | # Interior cell margin (1 mm) | |
159 | @cMargin=margin/10 |
|
159 | @cMargin=margin/10 | |
160 | # Line width (0.2 mm) |
|
160 | # Line width (0.2 mm) | |
161 | @LineWidth=0.567/@k |
|
161 | @LineWidth=0.567/@k | |
162 | # Automatic page break |
|
162 | # Automatic page break | |
163 | SetAutoPageBreak(true,2*margin) |
|
163 | SetAutoPageBreak(true,2*margin) | |
164 | # Full width display mode |
|
164 | # Full width display mode | |
165 | SetDisplayMode('fullwidth') |
|
165 | SetDisplayMode('fullwidth') | |
166 | # Enable compression |
|
166 | # Enable compression | |
167 | SetCompression(true) |
|
167 | SetCompression(true) | |
168 | # Set default PDF version number |
|
168 | # Set default PDF version number | |
169 | @PDFVersion='1.3' |
|
169 | @PDFVersion='1.3' | |
170 | end |
|
170 | end | |
171 |
|
171 | |||
172 | def SetMargins(left, top, right=-1) |
|
172 | def SetMargins(left, top, right=-1) | |
173 | # Set left, top and right margins |
|
173 | # Set left, top and right margins | |
174 | @lMargin=left |
|
174 | @lMargin=left | |
175 | @tMargin=top |
|
175 | @tMargin=top | |
176 | right=left if right==-1 |
|
176 | right=left if right==-1 | |
177 | @rMargin=right |
|
177 | @rMargin=right | |
178 | end |
|
178 | end | |
179 |
|
179 | |||
180 | def SetLeftMargin(margin) |
|
180 | def SetLeftMargin(margin) | |
181 | # Set left margin |
|
181 | # Set left margin | |
182 | @lMargin=margin |
|
182 | @lMargin=margin | |
183 | @x=margin if @page>0 and @x<margin |
|
183 | @x=margin if @page>0 and @x<margin | |
184 | end |
|
184 | end | |
185 |
|
185 | |||
186 | def SetTopMargin(margin) |
|
186 | def SetTopMargin(margin) | |
187 | # Set top margin |
|
187 | # Set top margin | |
188 | @tMargin=margin |
|
188 | @tMargin=margin | |
189 | end |
|
189 | end | |
190 |
|
190 | |||
191 | def SetRightMargin(margin) |
|
191 | def SetRightMargin(margin) | |
192 | #Set right margin |
|
192 | #Set right margin | |
193 | @rMargin=margin |
|
193 | @rMargin=margin | |
194 | end |
|
194 | end | |
195 |
|
195 | |||
196 | def SetAutoPageBreak(auto, margin=0) |
|
196 | def SetAutoPageBreak(auto, margin=0) | |
197 | # Set auto page break mode and triggering margin |
|
197 | # Set auto page break mode and triggering margin | |
198 | @AutoPageBreak=auto |
|
198 | @AutoPageBreak=auto | |
199 | @bMargin=margin |
|
199 | @bMargin=margin | |
200 | @PageBreakTrigger=@h-margin |
|
200 | @PageBreakTrigger=@h-margin | |
201 | end |
|
201 | end | |
202 |
|
202 | |||
203 | def SetDisplayMode(zoom, layout='continuous') |
|
203 | def SetDisplayMode(zoom, layout='continuous') | |
204 | # Set display mode in viewer |
|
204 | # Set display mode in viewer | |
205 | if zoom=='fullpage' or zoom=='fullwidth' or zoom=='real' or |
|
205 | if zoom=='fullpage' or zoom=='fullwidth' or zoom=='real' or | |
206 | zoom=='default' or not zoom.kind_of? String |
|
206 | zoom=='default' or not zoom.kind_of? String | |
207 |
|
207 | |||
208 | @ZoomMode=zoom; |
|
208 | @ZoomMode=zoom; | |
209 | elsif zoom=='zoom' |
|
209 | elsif zoom=='zoom' | |
210 | @ZoomMode=layout |
|
210 | @ZoomMode=layout | |
211 | else |
|
211 | else | |
212 | raise 'Incorrect zoom display mode: '+zoom |
|
212 | raise 'Incorrect zoom display mode: '+zoom | |
213 | end |
|
213 | end | |
214 | if layout=='single' or layout=='continuous' or layout=='two' or |
|
214 | if layout=='single' or layout=='continuous' or layout=='two' or | |
215 | layout=='default' |
|
215 | layout=='default' | |
216 |
|
216 | |||
217 | @LayoutMode=layout |
|
217 | @LayoutMode=layout | |
218 | elsif zoom!='zoom' |
|
218 | elsif zoom!='zoom' | |
219 | raise 'Incorrect layout display mode: '+layout |
|
219 | raise 'Incorrect layout display mode: '+layout | |
220 | end |
|
220 | end | |
221 | end |
|
221 | end | |
222 |
|
222 | |||
223 | def SetCompression(compress) |
|
223 | def SetCompression(compress) | |
224 | # Set page compression |
|
224 | # Set page compression | |
225 | @compress = compress |
|
225 | @compress = compress | |
226 | end |
|
226 | end | |
227 |
|
227 | |||
228 | def SetTitle(title) |
|
228 | def SetTitle(title) | |
229 | # Title of document |
|
229 | # Title of document | |
230 | @title=title |
|
230 | @title=title | |
231 | end |
|
231 | end | |
232 |
|
232 | |||
233 | def SetSubject(subject) |
|
233 | def SetSubject(subject) | |
234 | # Subject of document |
|
234 | # Subject of document | |
235 | @subject=subject |
|
235 | @subject=subject | |
236 | end |
|
236 | end | |
237 |
|
237 | |||
238 | def SetAuthor(author) |
|
238 | def SetAuthor(author) | |
239 | # Author of document |
|
239 | # Author of document | |
240 | @author=author |
|
240 | @author=author | |
241 | end |
|
241 | end | |
242 |
|
242 | |||
243 | def SetKeywords(keywords) |
|
243 | def SetKeywords(keywords) | |
244 | # Keywords of document |
|
244 | # Keywords of document | |
245 | @keywords=keywords |
|
245 | @keywords=keywords | |
246 | end |
|
246 | end | |
247 |
|
247 | |||
248 | def SetCreator(creator) |
|
248 | def SetCreator(creator) | |
249 | # Creator of document |
|
249 | # Creator of document | |
250 | @creator=creator |
|
250 | @creator=creator | |
251 | end |
|
251 | end | |
252 |
|
252 | |||
253 | def AliasNbPages(aliasnb='{nb}') |
|
253 | def AliasNbPages(aliasnb='{nb}') | |
254 | # Define an alias for total number of pages |
|
254 | # Define an alias for total number of pages | |
255 | @AliasNbPages=aliasnb |
|
255 | @AliasNbPages=aliasnb | |
256 | end |
|
256 | end | |
257 |
|
257 | |||
258 | def Error(msg) |
|
258 | def Error(msg) | |
259 | raise 'FPDF error: '+msg |
|
259 | raise 'FPDF error: '+msg | |
260 | end |
|
260 | end | |
261 |
|
261 | |||
262 | def Open |
|
262 | def Open | |
263 | # Begin document |
|
263 | # Begin document | |
264 | @state=1 |
|
264 | @state=1 | |
265 | end |
|
265 | end | |
266 |
|
266 | |||
267 | def Close |
|
267 | def Close | |
268 | # Terminate document |
|
268 | # Terminate document | |
269 | return if @state==3 |
|
269 | return if @state==3 | |
270 | self.AddPage if @page==0 |
|
270 | self.AddPage if @page==0 | |
271 | # Page footer |
|
271 | # Page footer | |
272 | @InFooter=true |
|
272 | @InFooter=true | |
273 | self.Footer |
|
273 | self.Footer | |
274 | @InFooter=false |
|
274 | @InFooter=false | |
275 | # Close page |
|
275 | # Close page | |
276 | endpage |
|
276 | endpage | |
277 | # Close document |
|
277 | # Close document | |
278 | enddoc |
|
278 | enddoc | |
279 | end |
|
279 | end | |
280 |
|
280 | |||
281 | def AddPage(orientation='') |
|
281 | def AddPage(orientation='') | |
282 | # Start a new page |
|
282 | # Start a new page | |
283 | self.Open if @state==0 |
|
283 | self.Open if @state==0 | |
284 | family=@FontFamily |
|
284 | family=@FontFamily | |
285 | style=@FontStyle+(@underline ? 'U' : '') |
|
285 | style=@FontStyle+(@underline ? 'U' : '') | |
286 | size=@FontSizePt |
|
286 | size=@FontSizePt | |
287 | lw=@LineWidth |
|
287 | lw=@LineWidth | |
288 | dc=@DrawColor |
|
288 | dc=@DrawColor | |
289 | fc=@FillColor |
|
289 | fc=@FillColor | |
290 | tc=@TextColor |
|
290 | tc=@TextColor | |
291 | cf=@ColorFlag |
|
291 | cf=@ColorFlag | |
292 | if @page>0 |
|
292 | if @page>0 | |
293 | # Page footer |
|
293 | # Page footer | |
294 | @InFooter=true |
|
294 | @InFooter=true | |
295 | self.Footer |
|
295 | self.Footer | |
296 | @InFooter=false |
|
296 | @InFooter=false | |
297 | # Close page |
|
297 | # Close page | |
298 | endpage |
|
298 | endpage | |
299 | end |
|
299 | end | |
300 | # Start new page |
|
300 | # Start new page | |
301 | beginpage(orientation) |
|
301 | beginpage(orientation) | |
302 | # Set line cap style to square |
|
302 | # Set line cap style to square | |
303 | out('2 J') |
|
303 | out('2 J') | |
304 | # Set line width |
|
304 | # Set line width | |
305 | @LineWidth=lw |
|
305 | @LineWidth=lw | |
306 | out(sprintf('%.2f w',lw*@k)) |
|
306 | out(sprintf('%.2f w',lw*@k)) | |
307 | # Set font |
|
307 | # Set font | |
308 | SetFont(family,style,size) if family |
|
308 | SetFont(family,style,size) if family | |
309 | # Set colors |
|
309 | # Set colors | |
310 | @DrawColor=dc |
|
310 | @DrawColor=dc | |
311 | out(dc) if dc!='0 G' |
|
311 | out(dc) if dc!='0 G' | |
312 | @FillColor=fc |
|
312 | @FillColor=fc | |
313 | out(fc) if fc!='0 g' |
|
313 | out(fc) if fc!='0 g' | |
314 | @TextColor=tc |
|
314 | @TextColor=tc | |
315 | @ColorFlag=cf |
|
315 | @ColorFlag=cf | |
316 | # Page header |
|
316 | # Page header | |
317 | self.Header |
|
317 | self.Header | |
318 | # Restore line width |
|
318 | # Restore line width | |
319 | if @LineWidth!=lw |
|
319 | if @LineWidth!=lw | |
320 | @LineWidth=lw |
|
320 | @LineWidth=lw | |
321 | out(sprintf('%.2f w',lw*@k)) |
|
321 | out(sprintf('%.2f w',lw*@k)) | |
322 | end |
|
322 | end | |
323 | # Restore font |
|
323 | # Restore font | |
324 | self.SetFont(family,style,size) if family |
|
324 | self.SetFont(family,style,size) if family | |
325 | # Restore colors |
|
325 | # Restore colors | |
326 | if @DrawColor!=dc |
|
326 | if @DrawColor!=dc | |
327 | @DrawColor=dc |
|
327 | @DrawColor=dc | |
328 | out(dc) |
|
328 | out(dc) | |
329 | end |
|
329 | end | |
330 | if @FillColor!=fc |
|
330 | if @FillColor!=fc | |
331 | @FillColor=fc |
|
331 | @FillColor=fc | |
332 | out(fc) |
|
332 | out(fc) | |
333 | end |
|
333 | end | |
334 | @TextColor=tc |
|
334 | @TextColor=tc | |
335 | @ColorFlag=cf |
|
335 | @ColorFlag=cf | |
336 | end |
|
336 | end | |
337 |
|
337 | |||
338 | def Header |
|
338 | def Header | |
339 | # To be implemented in your inherited class |
|
339 | # To be implemented in your inherited class | |
340 | end |
|
340 | end | |
341 |
|
341 | |||
342 | def Footer |
|
342 | def Footer | |
343 | # To be implemented in your inherited class |
|
343 | # To be implemented in your inherited class | |
344 | end |
|
344 | end | |
345 |
|
345 | |||
346 | def PageNo |
|
346 | def PageNo | |
347 | # Get current page number |
|
347 | # Get current page number | |
348 | @page |
|
348 | @page | |
349 | end |
|
349 | end | |
350 |
|
350 | |||
351 | def SetDrawColor(r,g=-1,b=-1) |
|
351 | def SetDrawColor(r,g=-1,b=-1) | |
352 | # Set color for all stroking operations |
|
352 | # Set color for all stroking operations | |
353 | if (r==0 and g==0 and b==0) or g==-1 |
|
353 | if (r==0 and g==0 and b==0) or g==-1 | |
354 | @DrawColor=sprintf('%.3f G',r/255.0) |
|
354 | @DrawColor=sprintf('%.3f G',r/255.0) | |
355 | else |
|
355 | else | |
356 | @DrawColor=sprintf('%.3f %.3f %.3f RG',r/255.0,g/255.0,b/255.0) |
|
356 | @DrawColor=sprintf('%.3f %.3f %.3f RG',r/255.0,g/255.0,b/255.0) | |
357 | end |
|
357 | end | |
358 | out(@DrawColor) if(@page>0) |
|
358 | out(@DrawColor) if(@page>0) | |
359 | end |
|
359 | end | |
360 |
|
360 | |||
361 | def SetFillColor(r,g=-1,b=-1) |
|
361 | def SetFillColor(r,g=-1,b=-1) | |
362 | # Set color for all filling operations |
|
362 | # Set color for all filling operations | |
363 | if (r==0 and g==0 and b==0) or g==-1 |
|
363 | if (r==0 and g==0 and b==0) or g==-1 | |
364 | @FillColor=sprintf('%.3f g',r/255.0) |
|
364 | @FillColor=sprintf('%.3f g',r/255.0) | |
365 | else |
|
365 | else | |
366 | @FillColor=sprintf('%.3f %.3f %.3f rg',r/255.0,g/255.0,b/255.0) |
|
366 | @FillColor=sprintf('%.3f %.3f %.3f rg',r/255.0,g/255.0,b/255.0) | |
367 | end |
|
367 | end | |
368 | @ColorFlag=(@FillColor!=@TextColor) |
|
368 | @ColorFlag=(@FillColor!=@TextColor) | |
369 | out(@FillColor) if(@page>0) |
|
369 | out(@FillColor) if(@page>0) | |
370 | end |
|
370 | end | |
371 |
|
371 | |||
372 | def SetTextColor(r,g=-1,b=-1) |
|
372 | def SetTextColor(r,g=-1,b=-1) | |
373 | # Set color for text |
|
373 | # Set color for text | |
374 | if (r==0 and g==0 and b==0) or g==-1 |
|
374 | if (r==0 and g==0 and b==0) or g==-1 | |
375 | @TextColor=sprintf('%.3f g',r/255.0) |
|
375 | @TextColor=sprintf('%.3f g',r/255.0) | |
376 | else |
|
376 | else | |
377 | @TextColor=sprintf('%.3f %.3f %.3f rg',r/255.0,g/255.0,b/255.0) |
|
377 | @TextColor=sprintf('%.3f %.3f %.3f rg',r/255.0,g/255.0,b/255.0) | |
378 | end |
|
378 | end | |
379 | @ColorFlag=(@FillColor!=@TextColor) |
|
379 | @ColorFlag=(@FillColor!=@TextColor) | |
380 | end |
|
380 | end | |
|
381 | ||||
|
382 | def GetCharWidth(widths, index) | |||
|
383 | if index.is_a?(String) | |||
|
384 | widths[index.ord] | |||
|
385 | else | |||
|
386 | widths[index] | |||
|
387 | end | |||
|
388 | end | |||
381 |
|
389 | |||
382 | def GetStringWidth(s) |
|
390 | def GetStringWidth(s) | |
383 | # Get width of a string in the current font |
|
391 | # Get width of a string in the current font | |
384 | cw=@CurrentFont['cw'] |
|
392 | cw=@CurrentFont['cw'] | |
385 | w=0 |
|
393 | w=0 | |
386 | s.each_byte do |c| |
|
394 | s.each_byte do |c| | |
387 |
w=w+cw |
|
395 | w=w+GetCharWidth(cw, c) | |
388 | end |
|
396 | end | |
389 | w*@FontSize/1000.0 |
|
397 | w*@FontSize/1000.0 | |
390 | end |
|
398 | end | |
391 |
|
399 | |||
392 | def SetLineWidth(width) |
|
400 | def SetLineWidth(width) | |
393 | # Set line width |
|
401 | # Set line width | |
394 | @LineWidth=width |
|
402 | @LineWidth=width | |
395 | out(sprintf('%.2f w',width*@k)) if @page>0 |
|
403 | out(sprintf('%.2f w',width*@k)) if @page>0 | |
396 | end |
|
404 | end | |
397 |
|
405 | |||
398 | def Line(x1, y1, x2, y2) |
|
406 | def Line(x1, y1, x2, y2) | |
399 | # Draw a line |
|
407 | # Draw a line | |
400 | out(sprintf('%.2f %.2f m %.2f %.2f l S', |
|
408 | out(sprintf('%.2f %.2f m %.2f %.2f l S', | |
401 | x1*@k,(@h-y1)*@k,x2*@k,(@h-y2)*@k)) |
|
409 | x1*@k,(@h-y1)*@k,x2*@k,(@h-y2)*@k)) | |
402 | end |
|
410 | end | |
403 |
|
411 | |||
404 | def Rect(x, y, w, h, style='') |
|
412 | def Rect(x, y, w, h, style='') | |
405 | # Draw a rectangle |
|
413 | # Draw a rectangle | |
406 | if style=='F' |
|
414 | if style=='F' | |
407 | op='f' |
|
415 | op='f' | |
408 | elsif style=='FD' or style=='DF' |
|
416 | elsif style=='FD' or style=='DF' | |
409 | op='B' |
|
417 | op='B' | |
410 | else |
|
418 | else | |
411 | op='S' |
|
419 | op='S' | |
412 | end |
|
420 | end | |
413 | out(sprintf('%.2f %.2f %.2f %.2f re %s', x*@k,(@h-y)*@k,w*@k,-h*@k,op)) |
|
421 | out(sprintf('%.2f %.2f %.2f %.2f re %s', x*@k,(@h-y)*@k,w*@k,-h*@k,op)) | |
414 | end |
|
422 | end | |
415 |
|
423 | |||
416 | def AddFont(family, style='', file='') |
|
424 | def AddFont(family, style='', file='') | |
417 | # Add a TrueType or Type1 font |
|
425 | # Add a TrueType or Type1 font | |
418 | family = family.downcase |
|
426 | family = family.downcase | |
419 | family = 'helvetica' if family == 'arial' |
|
427 | family = 'helvetica' if family == 'arial' | |
420 |
|
428 | |||
421 | style = style.upcase |
|
429 | style = style.upcase | |
422 | style = 'BI' if style == 'IB' |
|
430 | style = 'BI' if style == 'IB' | |
423 |
|
431 | |||
424 | fontkey = family + style |
|
432 | fontkey = family + style | |
425 |
|
433 | |||
426 | if @fonts.has_key?(fontkey) |
|
434 | if @fonts.has_key?(fontkey) | |
427 | self.Error("Font already added: #{family} #{style}") |
|
435 | self.Error("Font already added: #{family} #{style}") | |
428 | end |
|
436 | end | |
429 |
|
437 | |||
430 | file = family.gsub(' ', '') + style.downcase + '.rb' if file == '' |
|
438 | file = family.gsub(' ', '') + style.downcase + '.rb' if file == '' | |
431 |
|
439 | |||
432 | if self.class.const_defined? 'FPDF_FONTPATH' |
|
440 | if self.class.const_defined? 'FPDF_FONTPATH' | |
433 | if FPDF_FONTPATH[-1,1] == '/' |
|
441 | if FPDF_FONTPATH[-1,1] == '/' | |
434 | file = FPDF_FONTPATH + file |
|
442 | file = FPDF_FONTPATH + file | |
435 | else |
|
443 | else | |
436 | file = FPDF_FONTPATH + '/' + file |
|
444 | file = FPDF_FONTPATH + '/' + file | |
437 | end |
|
445 | end | |
438 | end |
|
446 | end | |
439 |
|
447 | |||
440 | # Changed from "require file" to fix bug reported by Hans Allis. |
|
448 | # Changed from "require file" to fix bug reported by Hans Allis. | |
441 | load file |
|
449 | load file | |
442 |
|
450 | |||
443 | if FontDef.desc.nil? |
|
451 | if FontDef.desc.nil? | |
444 | self.Error("Could not include font definition file #{file}") |
|
452 | self.Error("Could not include font definition file #{file}") | |
445 | end |
|
453 | end | |
446 |
|
454 | |||
447 | i = @fonts.length + 1 |
|
455 | i = @fonts.length + 1 | |
448 |
|
456 | |||
449 | @fonts[fontkey] = {'i' => i, |
|
457 | @fonts[fontkey] = {'i' => i, | |
450 | 'type' => FontDef.type, |
|
458 | 'type' => FontDef.type, | |
451 | 'name' => FontDef.name, |
|
459 | 'name' => FontDef.name, | |
452 | 'desc' => FontDef.desc, |
|
460 | 'desc' => FontDef.desc, | |
453 | 'up' => FontDef.up, |
|
461 | 'up' => FontDef.up, | |
454 | 'ut' => FontDef.ut, |
|
462 | 'ut' => FontDef.ut, | |
455 | 'cw' => FontDef.cw, |
|
463 | 'cw' => FontDef.cw, | |
456 | 'enc' => FontDef.enc, |
|
464 | 'enc' => FontDef.enc, | |
457 | 'file' => FontDef.file |
|
465 | 'file' => FontDef.file | |
458 | } |
|
466 | } | |
459 |
|
467 | |||
460 | if FontDef.diff |
|
468 | if FontDef.diff | |
461 | # Search existing encodings |
|
469 | # Search existing encodings | |
462 | unless @diffs.include?(FontDef.diff) |
|
470 | unless @diffs.include?(FontDef.diff) | |
463 | @diffs.push(FontDef.diff) |
|
471 | @diffs.push(FontDef.diff) | |
464 | @fonts[fontkey]['diff'] = @diffs.length - 1 |
|
472 | @fonts[fontkey]['diff'] = @diffs.length - 1 | |
465 | end |
|
473 | end | |
466 | end |
|
474 | end | |
467 |
|
475 | |||
468 | if FontDef.file |
|
476 | if FontDef.file | |
469 | if FontDef.type == 'TrueType' |
|
477 | if FontDef.type == 'TrueType' | |
470 | @FontFiles[FontDef.file] = {'length1' => FontDef.originalsize} |
|
478 | @FontFiles[FontDef.file] = {'length1' => FontDef.originalsize} | |
471 | else |
|
479 | else | |
472 | @FontFiles[FontDef.file] = {'length1' => FontDef.size1, 'length2' => FontDef.size2} |
|
480 | @FontFiles[FontDef.file] = {'length1' => FontDef.size1, 'length2' => FontDef.size2} | |
473 | end |
|
481 | end | |
474 | end |
|
482 | end | |
475 |
|
483 | |||
476 | return self |
|
484 | return self | |
477 | end |
|
485 | end | |
478 |
|
486 | |||
479 | def SetFont(family, style='', size=0) |
|
487 | def SetFont(family, style='', size=0) | |
480 | # Select a font; size given in points |
|
488 | # Select a font; size given in points | |
481 | family.downcase! |
|
489 | family.downcase! | |
482 | family=@FontFamily if family=='' |
|
490 | family=@FontFamily if family=='' | |
483 | if family=='arial' |
|
491 | if family=='arial' | |
484 | family='helvetica' |
|
492 | family='helvetica' | |
485 | elsif family=='symbol' or family=='zapfdingbats' |
|
493 | elsif family=='symbol' or family=='zapfdingbats' | |
486 | style='' |
|
494 | style='' | |
487 | end |
|
495 | end | |
488 | style.upcase! |
|
496 | style.upcase! | |
489 | unless style.index('U').nil? |
|
497 | unless style.index('U').nil? | |
490 | @underline=true |
|
498 | @underline=true | |
491 | style.gsub!('U','') |
|
499 | style.gsub!('U','') | |
492 | else |
|
500 | else | |
493 | @underline=false; |
|
501 | @underline=false; | |
494 | end |
|
502 | end | |
495 | style='BI' if style=='IB' |
|
503 | style='BI' if style=='IB' | |
496 | size=@FontSizePt if size==0 |
|
504 | size=@FontSizePt if size==0 | |
497 | # Test if font is already selected |
|
505 | # Test if font is already selected | |
498 | return if @FontFamily==family and |
|
506 | return if @FontFamily==family and | |
499 | @FontStyle==style and @FontSizePt==size |
|
507 | @FontStyle==style and @FontSizePt==size | |
500 | # Test if used for the first time |
|
508 | # Test if used for the first time | |
501 | fontkey=family+style |
|
509 | fontkey=family+style | |
502 | unless @fonts.has_key?(fontkey) |
|
510 | unless @fonts.has_key?(fontkey) | |
503 | if @CoreFonts.has_key?(fontkey) |
|
511 | if @CoreFonts.has_key?(fontkey) | |
504 | unless Charwidths.has_key?(fontkey) |
|
512 | unless Charwidths.has_key?(fontkey) | |
505 | raise 'Font unavailable' |
|
513 | raise 'Font unavailable' | |
506 | end |
|
514 | end | |
507 | @fonts[fontkey]={ |
|
515 | @fonts[fontkey]={ | |
508 | 'i'=>@fonts.size, |
|
516 | 'i'=>@fonts.size, | |
509 | 'type'=>'core', |
|
517 | 'type'=>'core', | |
510 | 'name'=>@CoreFonts[fontkey], |
|
518 | 'name'=>@CoreFonts[fontkey], | |
511 | 'up'=>-100, |
|
519 | 'up'=>-100, | |
512 | 'ut'=>50, |
|
520 | 'ut'=>50, | |
513 | 'cw'=>Charwidths[fontkey]} |
|
521 | 'cw'=>Charwidths[fontkey]} | |
514 | else |
|
522 | else | |
515 | raise 'Font unavailable' |
|
523 | raise 'Font unavailable' | |
516 | end |
|
524 | end | |
517 | end |
|
525 | end | |
518 |
|
526 | |||
519 | #Select it |
|
527 | #Select it | |
520 | @FontFamily=family |
|
528 | @FontFamily=family | |
521 | @FontStyle=style; |
|
529 | @FontStyle=style; | |
522 | @FontSizePt=size |
|
530 | @FontSizePt=size | |
523 | @FontSize=size/@k; |
|
531 | @FontSize=size/@k; | |
524 | @CurrentFont=@fonts[fontkey] |
|
532 | @CurrentFont=@fonts[fontkey] | |
525 | if @page>0 |
|
533 | if @page>0 | |
526 | out(sprintf('BT /F%d %.2f Tf ET', @CurrentFont['i'], @FontSizePt)) |
|
534 | out(sprintf('BT /F%d %.2f Tf ET', @CurrentFont['i'], @FontSizePt)) | |
527 | end |
|
535 | end | |
528 | end |
|
536 | end | |
529 |
|
537 | |||
530 | def SetFontSize(size) |
|
538 | def SetFontSize(size) | |
531 | # Set font size in points |
|
539 | # Set font size in points | |
532 | return if @FontSizePt==size |
|
540 | return if @FontSizePt==size | |
533 | @FontSizePt=size |
|
541 | @FontSizePt=size | |
534 | @FontSize=size/@k |
|
542 | @FontSize=size/@k | |
535 | if @page>0 |
|
543 | if @page>0 | |
536 | out(sprintf('BT /F%d %.2f Tf ET',@CurrentFont['i'],@FontSizePt)) |
|
544 | out(sprintf('BT /F%d %.2f Tf ET',@CurrentFont['i'],@FontSizePt)) | |
537 | end |
|
545 | end | |
538 | end |
|
546 | end | |
539 |
|
547 | |||
540 | def AddLink |
|
548 | def AddLink | |
541 | # Create a new internal link |
|
549 | # Create a new internal link | |
542 | @links.push([0, 0]) |
|
550 | @links.push([0, 0]) | |
543 | @links.size |
|
551 | @links.size | |
544 | end |
|
552 | end | |
545 |
|
553 | |||
546 | def SetLink(link, y=0, page=-1) |
|
554 | def SetLink(link, y=0, page=-1) | |
547 | # Set destination of internal link |
|
555 | # Set destination of internal link | |
548 | y=@y if y==-1 |
|
556 | y=@y if y==-1 | |
549 | page=@page if page==-1 |
|
557 | page=@page if page==-1 | |
550 | @links[link]=[page, y] |
|
558 | @links[link]=[page, y] | |
551 | end |
|
559 | end | |
552 |
|
560 | |||
553 | def Link(x, y, w, h, link) |
|
561 | def Link(x, y, w, h, link) | |
554 | # Put a link on the page |
|
562 | # Put a link on the page | |
555 | @PageLinks[@page]=Array.new unless @PageLinks.has_key?(@Page) |
|
563 | @PageLinks[@page]=Array.new unless @PageLinks.has_key?(@Page) | |
556 | @PageLinks[@page].push([x*@k,@hPt-y*@k,w*@k,h*@k,link]) |
|
564 | @PageLinks[@page].push([x*@k,@hPt-y*@k,w*@k,h*@k,link]) | |
557 | end |
|
565 | end | |
558 |
|
566 | |||
559 | def Text(x, y, txt) |
|
567 | def Text(x, y, txt) | |
560 | # Output a string |
|
568 | # Output a string | |
561 | txt.gsub!(')', '\\)') |
|
569 | txt.gsub!(')', '\\)') | |
562 | txt.gsub!('(', '\\(') |
|
570 | txt.gsub!('(', '\\(') | |
563 | txt.gsub!('\\', '\\\\') |
|
571 | txt.gsub!('\\', '\\\\') | |
564 | s=sprintf('BT %.2f %.2f Td (%s) Tj ET',x*@k,(@h-y)*@k,txt); |
|
572 | s=sprintf('BT %.2f %.2f Td (%s) Tj ET',x*@k,(@h-y)*@k,txt); | |
565 | s=s+' '+dounderline(x,y,txt) if @underline and txt!='' |
|
573 | s=s+' '+dounderline(x,y,txt) if @underline and txt!='' | |
566 | s='q '+@TextColor+' '+s+' Q' if @ColorFlag |
|
574 | s='q '+@TextColor+' '+s+' Q' if @ColorFlag | |
567 | out(s) |
|
575 | out(s) | |
568 | end |
|
576 | end | |
569 |
|
577 | |||
570 | def AcceptPageBreak |
|
578 | def AcceptPageBreak | |
571 | # Accept automatic page break or not |
|
579 | # Accept automatic page break or not | |
572 | @AutoPageBreak |
|
580 | @AutoPageBreak | |
573 | end |
|
581 | end | |
574 |
|
582 | |||
575 | def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='') |
|
583 | def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='') | |
576 | # Output a cell |
|
584 | # Output a cell | |
577 | if @y+h>@PageBreakTrigger and !@InFooter and self.AcceptPageBreak |
|
585 | if @y+h>@PageBreakTrigger and !@InFooter and self.AcceptPageBreak | |
578 | # Automatic page break |
|
586 | # Automatic page break | |
579 | x=@x |
|
587 | x=@x | |
580 | ws=@ws |
|
588 | ws=@ws | |
581 | if ws>0 |
|
589 | if ws>0 | |
582 | @ws=0 |
|
590 | @ws=0 | |
583 | out('0 Tw') |
|
591 | out('0 Tw') | |
584 | end |
|
592 | end | |
585 | self.AddPage(@CurOrientation) |
|
593 | self.AddPage(@CurOrientation) | |
586 | @x=x |
|
594 | @x=x | |
587 | if ws>0 |
|
595 | if ws>0 | |
588 | @ws=ws |
|
596 | @ws=ws | |
589 | out(sprintf('%.3f Tw',ws*@k)) |
|
597 | out(sprintf('%.3f Tw',ws*@k)) | |
590 | end |
|
598 | end | |
591 | end |
|
599 | end | |
592 | w=@w-@rMargin-@x if w==0 |
|
600 | w=@w-@rMargin-@x if w==0 | |
593 | s='' |
|
601 | s='' | |
594 | if fill==1 or border==1 |
|
602 | if fill==1 or border==1 | |
595 | if fill==1 |
|
603 | if fill==1 | |
596 | op=(border==1) ? 'B' : 'f' |
|
604 | op=(border==1) ? 'B' : 'f' | |
597 | else |
|
605 | else | |
598 | op='S' |
|
606 | op='S' | |
599 | end |
|
607 | end | |
600 | s=sprintf('%.2f %.2f %.2f %.2f re %s ',@x*@k,(@h-@y)*@k,w*@k,-h*@k,op) |
|
608 | s=sprintf('%.2f %.2f %.2f %.2f re %s ',@x*@k,(@h-@y)*@k,w*@k,-h*@k,op) | |
601 | end |
|
609 | end | |
602 | if border.is_a? String |
|
610 | if border.is_a? String | |
603 | x=@x |
|
611 | x=@x | |
604 | y=@y |
|
612 | y=@y | |
605 | unless border.index('L').nil? |
|
613 | unless border.index('L').nil? | |
606 | s=s+sprintf('%.2f %.2f m %.2f %.2f l S ', |
|
614 | s=s+sprintf('%.2f %.2f m %.2f %.2f l S ', | |
607 | x*@k,(@h-y)*@k,x*@k,(@h-(y+h))*@k) |
|
615 | x*@k,(@h-y)*@k,x*@k,(@h-(y+h))*@k) | |
608 | end |
|
616 | end | |
609 | unless border.index('T').nil? |
|
617 | unless border.index('T').nil? | |
610 | s=s+sprintf('%.2f %.2f m %.2f %.2f l S ', |
|
618 | s=s+sprintf('%.2f %.2f m %.2f %.2f l S ', | |
611 | x*@k,(@h-y)*@k,(x+w)*@k,(@h-y)*@k) |
|
619 | x*@k,(@h-y)*@k,(x+w)*@k,(@h-y)*@k) | |
612 | end |
|
620 | end | |
613 | unless border.index('R').nil? |
|
621 | unless border.index('R').nil? | |
614 | s=s+sprintf('%.2f %.2f m %.2f %.2f l S ', |
|
622 | s=s+sprintf('%.2f %.2f m %.2f %.2f l S ', | |
615 | (x+w)*@k,(@h-y)*@k,(x+w)*@k,(@h-(y+h))*@k) |
|
623 | (x+w)*@k,(@h-y)*@k,(x+w)*@k,(@h-(y+h))*@k) | |
616 | end |
|
624 | end | |
617 | unless border.index('B').nil? |
|
625 | unless border.index('B').nil? | |
618 | s=s+sprintf('%.2f %.2f m %.2f %.2f l S ', |
|
626 | s=s+sprintf('%.2f %.2f m %.2f %.2f l S ', | |
619 | x*@k,(@h-(y+h))*@k,(x+w)*@k,(@h-(y+h))*@k) |
|
627 | x*@k,(@h-(y+h))*@k,(x+w)*@k,(@h-(y+h))*@k) | |
620 | end |
|
628 | end | |
621 | end |
|
629 | end | |
622 | if txt!='' |
|
630 | if txt!='' | |
623 | if align=='R' |
|
631 | if align=='R' | |
624 | dx=w-@cMargin-self.GetStringWidth(txt) |
|
632 | dx=w-@cMargin-self.GetStringWidth(txt) | |
625 | elsif align=='C' |
|
633 | elsif align=='C' | |
626 | dx=(w-self.GetStringWidth(txt))/2 |
|
634 | dx=(w-self.GetStringWidth(txt))/2 | |
627 | else |
|
635 | else | |
628 | dx=@cMargin |
|
636 | dx=@cMargin | |
629 | end |
|
637 | end | |
630 | txt = txt.gsub(')', '\\)') |
|
638 | txt = txt.gsub(')', '\\)') | |
631 | txt.gsub!('(', '\\(') |
|
639 | txt.gsub!('(', '\\(') | |
632 | txt.gsub!('\\', '\\\\') |
|
640 | txt.gsub!('\\', '\\\\') | |
633 | if @ColorFlag |
|
641 | if @ColorFlag | |
634 | s=s+'q '+@TextColor+' ' |
|
642 | s=s+'q '+@TextColor+' ' | |
635 | end |
|
643 | end | |
636 | s=s+sprintf('BT %.2f %.2f Td (%s) Tj ET', |
|
644 | s=s+sprintf('BT %.2f %.2f Td (%s) Tj ET', | |
637 | (@x+dx)*@k,(@h-(@y+0.5*h+0.3*@FontSize))*@k,txt) |
|
645 | (@x+dx)*@k,(@h-(@y+0.5*h+0.3*@FontSize))*@k,txt) | |
638 | s=s+' '+dounderline(@x+dx,@y+0.5*h+0.3*@FontSize,txt) if @underline |
|
646 | s=s+' '+dounderline(@x+dx,@y+0.5*h+0.3*@FontSize,txt) if @underline | |
639 | s=s+' Q' if @ColorFlag |
|
647 | s=s+' Q' if @ColorFlag | |
640 | if link and link != '' |
|
648 | if link and link != '' | |
641 | Link(@x+dx,@y+0.5*h-0.5*@FontSize,GetStringWidth(txt),@FontSize,link) |
|
649 | Link(@x+dx,@y+0.5*h-0.5*@FontSize,GetStringWidth(txt),@FontSize,link) | |
642 | end |
|
650 | end | |
643 | end |
|
651 | end | |
644 | out(s) if s |
|
652 | out(s) if s | |
645 | @lasth=h |
|
653 | @lasth=h | |
646 | if ln>0 |
|
654 | if ln>0 | |
647 | # Go to next line |
|
655 | # Go to next line | |
648 | @y=@y+h |
|
656 | @y=@y+h | |
649 | @x=@lMargin if ln==1 |
|
657 | @x=@lMargin if ln==1 | |
650 | else |
|
658 | else | |
651 | @x=@x+w |
|
659 | @x=@x+w | |
652 | end |
|
660 | end | |
653 | end |
|
661 | end | |
654 |
|
662 | |||
655 | def MultiCell(w,h,txt,border=0,align='J',fill=0) |
|
663 | def MultiCell(w,h,txt,border=0,align='J',fill=0) | |
656 | # Output text with automatic or explicit line breaks |
|
664 | # Output text with automatic or explicit line breaks | |
657 | cw=@CurrentFont['cw'] |
|
665 | cw=@CurrentFont['cw'] | |
658 | w=@w-@rMargin-@x if w==0 |
|
666 | w=@w-@rMargin-@x if w==0 | |
659 | wmax=(w-2*@cMargin)*1000/@FontSize |
|
667 | wmax=(w-2*@cMargin)*1000/@FontSize | |
660 | s=txt.gsub('\r','') |
|
668 | s=txt.gsub('\r','') | |
661 | nb=s.length |
|
669 | nb=s.length | |
662 | nb=nb-1 if nb>0 and s[nb-1].chr=='\n' |
|
670 | nb=nb-1 if nb>0 and s[nb-1].chr=='\n' | |
663 | b=0 |
|
671 | b=0 | |
664 | if border!=0 |
|
672 | if border!=0 | |
665 | if border==1 |
|
673 | if border==1 | |
666 | border='LTRB' |
|
674 | border='LTRB' | |
667 | b='LRT' |
|
675 | b='LRT' | |
668 | b2='LR' |
|
676 | b2='LR' | |
669 | else |
|
677 | else | |
670 | b2='' |
|
678 | b2='' | |
671 | b2='L' unless border.index('L').nil? |
|
679 | b2='L' unless border.index('L').nil? | |
672 | b2=b2+'R' unless border.index('R').nil? |
|
680 | b2=b2+'R' unless border.index('R').nil? | |
673 | b=(not border.index('T').nil?) ? (b2+'T') : b2 |
|
681 | b=(not border.index('T').nil?) ? (b2+'T') : b2 | |
674 | end |
|
682 | end | |
675 | end |
|
683 | end | |
676 | sep=-1 |
|
684 | sep=-1 | |
677 | i=0 |
|
685 | i=0 | |
678 | j=0 |
|
686 | j=0 | |
679 | l=0 |
|
687 | l=0 | |
680 | ns=0 |
|
688 | ns=0 | |
681 | nl=1 |
|
689 | nl=1 | |
682 | while i<nb |
|
690 | while i<nb | |
683 | # Get next character |
|
691 | # Get next character | |
684 | c=s[i].chr |
|
692 | c=s[i].chr | |
685 | if c=="\n" |
|
693 | if c=="\n" | |
686 | # Explicit line break |
|
694 | # Explicit line break | |
687 | if @ws>0 |
|
695 | if @ws>0 | |
688 | @ws=0 |
|
696 | @ws=0 | |
689 | out('0 Tw') |
|
697 | out('0 Tw') | |
690 | end |
|
698 | end | |
691 | #Ed Moss |
|
699 | #Ed Moss | |
692 | # Don't let i go negative |
|
700 | # Don't let i go negative | |
693 | end_i = i == 0 ? 0 : i - 1 |
|
701 | end_i = i == 0 ? 0 : i - 1 | |
694 | # Changed from s[j..i] to fix bug reported by Hans Allis. |
|
702 | # Changed from s[j..i] to fix bug reported by Hans Allis. | |
695 | self.Cell(w,h,s[j..end_i],b,2,align,fill) |
|
703 | self.Cell(w,h,s[j..end_i],b,2,align,fill) | |
696 | # |
|
704 | # | |
697 | i=i+1 |
|
705 | i=i+1 | |
698 | sep=-1 |
|
706 | sep=-1 | |
699 | j=i |
|
707 | j=i | |
700 | l=0 |
|
708 | l=0 | |
701 | ns=0 |
|
709 | ns=0 | |
702 | nl=nl+1 |
|
710 | nl=nl+1 | |
703 | b=b2 if border and nl==2 |
|
711 | b=b2 if border and nl==2 | |
704 | else |
|
712 | else | |
705 | if c==' ' |
|
713 | if c==' ' | |
706 | sep=i |
|
714 | sep=i | |
707 | ls=l |
|
715 | ls=l | |
708 | ns=ns+1 |
|
716 | ns=ns+1 | |
709 | end |
|
717 | end | |
710 |
l=l+cw |
|
718 | l=l+GetCharWidth(cw, c[0]) | |
711 | if l>wmax |
|
719 | if l>wmax | |
712 | # Automatic line break |
|
720 | # Automatic line break | |
713 | if sep==-1 |
|
721 | if sep==-1 | |
714 | i=i+1 if i==j |
|
722 | i=i+1 if i==j | |
715 | if @ws>0 |
|
723 | if @ws>0 | |
716 | @ws=0 |
|
724 | @ws=0 | |
717 | out('0 Tw') |
|
725 | out('0 Tw') | |
718 | end |
|
726 | end | |
719 | self.Cell(w,h,s[j..i],b,2,align,fill) |
|
727 | self.Cell(w,h,s[j..i],b,2,align,fill) | |
720 | #Ed Moss |
|
728 | #Ed Moss | |
721 | # Added so that it wouldn't print the last character of the string if it got close |
|
729 | # Added so that it wouldn't print the last character of the string if it got close | |
722 | #FIXME 2006-07-18 Level=0 - but it still puts out an extra new line |
|
730 | #FIXME 2006-07-18 Level=0 - but it still puts out an extra new line | |
723 | i += 1 |
|
731 | i += 1 | |
724 | # |
|
732 | # | |
725 | else |
|
733 | else | |
726 | if align=='J' |
|
734 | if align=='J' | |
727 | @ws=(ns>1) ? (wmax-ls)/1000.0*@FontSize/(ns-1) : 0 |
|
735 | @ws=(ns>1) ? (wmax-ls)/1000.0*@FontSize/(ns-1) : 0 | |
728 | out(sprintf('%.3f Tw',@ws*@k)) |
|
736 | out(sprintf('%.3f Tw',@ws*@k)) | |
729 | end |
|
737 | end | |
730 | self.Cell(w,h,s[j..sep],b,2,align,fill) |
|
738 | self.Cell(w,h,s[j..sep],b,2,align,fill) | |
731 | i=sep+1 |
|
739 | i=sep+1 | |
732 | end |
|
740 | end | |
733 | sep=-1 |
|
741 | sep=-1 | |
734 | j=i |
|
742 | j=i | |
735 | l=0 |
|
743 | l=0 | |
736 | ns=0 |
|
744 | ns=0 | |
737 | nl=nl+1 |
|
745 | nl=nl+1 | |
738 | b=b2 if border and nl==2 |
|
746 | b=b2 if border and nl==2 | |
739 | else |
|
747 | else | |
740 | i=i+1 |
|
748 | i=i+1 | |
741 | end |
|
749 | end | |
742 | end |
|
750 | end | |
743 | end |
|
751 | end | |
744 |
|
752 | |||
745 | # Last chunk |
|
753 | # Last chunk | |
746 | if @ws>0 |
|
754 | if @ws>0 | |
747 | @ws=0 |
|
755 | @ws=0 | |
748 | out('0 Tw') |
|
756 | out('0 Tw') | |
749 | end |
|
757 | end | |
750 | b=b+'B' if border!=0 and not border.index('B').nil? |
|
758 | b=b+'B' if border!=0 and not border.index('B').nil? | |
751 | self.Cell(w,h,s[j..i],b,2,align,fill) |
|
759 | self.Cell(w,h,s[j..i],b,2,align,fill) | |
752 | @x=@lMargin |
|
760 | @x=@lMargin | |
753 | end |
|
761 | end | |
754 |
|
762 | |||
755 | def Write(h,txt,link='') |
|
763 | def Write(h,txt,link='') | |
756 | # Output text in flowing mode |
|
764 | # Output text in flowing mode | |
757 | cw=@CurrentFont['cw'] |
|
765 | cw=@CurrentFont['cw'] | |
758 | w=@w-@rMargin-@x |
|
766 | w=@w-@rMargin-@x | |
759 | wmax=(w-2*@cMargin)*1000/@FontSize |
|
767 | wmax=(w-2*@cMargin)*1000/@FontSize | |
760 | s=txt.gsub("\r",'') |
|
768 | s=txt.gsub("\r",'') | |
761 | nb=s.length |
|
769 | nb=s.length | |
762 | sep=-1 |
|
770 | sep=-1 | |
763 | i=0 |
|
771 | i=0 | |
764 | j=0 |
|
772 | j=0 | |
765 | l=0 |
|
773 | l=0 | |
766 | nl=1 |
|
774 | nl=1 | |
767 | while i<nb |
|
775 | while i<nb | |
768 | # Get next character |
|
776 | # Get next character | |
769 | c=s[i] |
|
777 | c=s[i] | |
770 | if c=="\n"[0] |
|
778 | if c=="\n"[0] | |
771 | # Explicit line break |
|
779 | # Explicit line break | |
772 | self.Cell(w,h,s[j,i-j],0,2,'',0,link) |
|
780 | self.Cell(w,h,s[j,i-j],0,2,'',0,link) | |
773 | i=i+1 |
|
781 | i=i+1 | |
774 | sep=-1 |
|
782 | sep=-1 | |
775 | j=i |
|
783 | j=i | |
776 | l=0 |
|
784 | l=0 | |
777 | if nl==1 |
|
785 | if nl==1 | |
778 | @x=@lMargin |
|
786 | @x=@lMargin | |
779 | w=@w-@rMargin-@x |
|
787 | w=@w-@rMargin-@x | |
780 | wmax=(w-2*@cMargin)*1000/@FontSize |
|
788 | wmax=(w-2*@cMargin)*1000/@FontSize | |
781 | end |
|
789 | end | |
782 | nl=nl+1 |
|
790 | nl=nl+1 | |
783 | next |
|
791 | next | |
784 | end |
|
792 | end | |
785 | if c==' '[0] |
|
793 | if c==' '[0] | |
786 | sep=i |
|
794 | sep=i | |
787 | ls=l |
|
795 | ls=l | |
788 | end |
|
796 | end | |
789 |
l=l+cw |
|
797 | l=l+GetCharWidth(cw, c); | |
790 | if l>wmax |
|
798 | if l>wmax | |
791 | # Automatic line break |
|
799 | # Automatic line break | |
792 | if sep==-1 |
|
800 | if sep==-1 | |
793 | if @x>@lMargin |
|
801 | if @x>@lMargin | |
794 | # Move to next line |
|
802 | # Move to next line | |
795 | @x=@lMargin |
|
803 | @x=@lMargin | |
796 | @y=@y+h |
|
804 | @y=@y+h | |
797 | w=@w-@rMargin-@x |
|
805 | w=@w-@rMargin-@x | |
798 | wmax=(w-2*@cMargin)*1000/@FontSize |
|
806 | wmax=(w-2*@cMargin)*1000/@FontSize | |
799 | i=i+1 |
|
807 | i=i+1 | |
800 | nl=nl+1 |
|
808 | nl=nl+1 | |
801 | next |
|
809 | next | |
802 | end |
|
810 | end | |
803 | i=i+1 if i==j |
|
811 | i=i+1 if i==j | |
804 | self.Cell(w,h,s[j,i-j],0,2,'',0,link) |
|
812 | self.Cell(w,h,s[j,i-j],0,2,'',0,link) | |
805 | else |
|
813 | else | |
806 | self.Cell(w,h,s[j,sep-j],0,2,'',0,link) |
|
814 | self.Cell(w,h,s[j,sep-j],0,2,'',0,link) | |
807 | i=sep+1 |
|
815 | i=sep+1 | |
808 | end |
|
816 | end | |
809 | sep=-1 |
|
817 | sep=-1 | |
810 | j=i |
|
818 | j=i | |
811 | l=0 |
|
819 | l=0 | |
812 | if nl==1 |
|
820 | if nl==1 | |
813 | @x=@lMargin |
|
821 | @x=@lMargin | |
814 | w=@w-@rMargin-@x |
|
822 | w=@w-@rMargin-@x | |
815 | wmax=(w-2*@cMargin)*1000/@FontSize |
|
823 | wmax=(w-2*@cMargin)*1000/@FontSize | |
816 | end |
|
824 | end | |
817 | nl=nl+1 |
|
825 | nl=nl+1 | |
818 | else |
|
826 | else | |
819 | i=i+1 |
|
827 | i=i+1 | |
820 | end |
|
828 | end | |
821 | end |
|
829 | end | |
822 | # Last chunk |
|
830 | # Last chunk | |
823 | self.Cell(l/1000.0*@FontSize,h,s[j,i],0,0,'',0,link) if i!=j |
|
831 | self.Cell(l/1000.0*@FontSize,h,s[j,i],0,0,'',0,link) if i!=j | |
824 | end |
|
832 | end | |
825 |
|
833 | |||
826 | def Image(file,x,y,w=0,h=0,type='',link='') |
|
834 | def Image(file,x,y,w=0,h=0,type='',link='') | |
827 | # Put an image on the page |
|
835 | # Put an image on the page | |
828 | unless @images.has_key?(file) |
|
836 | unless @images.has_key?(file) | |
829 | # First use of image, get info |
|
837 | # First use of image, get info | |
830 | if type=='' |
|
838 | if type=='' | |
831 | pos=file.rindex('.') |
|
839 | pos=file.rindex('.') | |
832 | if pos.nil? |
|
840 | if pos.nil? | |
833 | self.Error('Image file has no extension and no type was '+ |
|
841 | self.Error('Image file has no extension and no type was '+ | |
834 | 'specified: '+file) |
|
842 | 'specified: '+file) | |
835 | end |
|
843 | end | |
836 | type=file[pos+1..-1] |
|
844 | type=file[pos+1..-1] | |
837 | end |
|
845 | end | |
838 | type.downcase! |
|
846 | type.downcase! | |
839 | if type=='jpg' or type=='jpeg' |
|
847 | if type=='jpg' or type=='jpeg' | |
840 | info=parsejpg(file) |
|
848 | info=parsejpg(file) | |
841 | elsif type=='png' |
|
849 | elsif type=='png' | |
842 | info=parsepng(file) |
|
850 | info=parsepng(file) | |
843 | else |
|
851 | else | |
844 | self.Error('Unsupported image file type: '+type) |
|
852 | self.Error('Unsupported image file type: '+type) | |
845 | end |
|
853 | end | |
846 | info['i']=@images.length+1 |
|
854 | info['i']=@images.length+1 | |
847 | @images[file]=info |
|
855 | @images[file]=info | |
848 | else |
|
856 | else | |
849 | info=@images[file] |
|
857 | info=@images[file] | |
850 | end |
|
858 | end | |
851 | #Ed Moss |
|
859 | #Ed Moss | |
852 | if(w==0 && h==0) |
|
860 | if(w==0 && h==0) | |
853 | #Put image at 72 dpi |
|
861 | #Put image at 72 dpi | |
854 | w=info['w']/@k; |
|
862 | w=info['w']/@k; | |
855 | h=info['h']/@k; |
|
863 | h=info['h']/@k; | |
856 | end |
|
864 | end | |
857 | # |
|
865 | # | |
858 | # Automatic width or height calculation |
|
866 | # Automatic width or height calculation | |
859 | w=h*info['w']/info['h'] if w==0 |
|
867 | w=h*info['w']/info['h'] if w==0 | |
860 | h=w*info['h']/info['w'] if h==0 |
|
868 | h=w*info['h']/info['w'] if h==0 | |
861 | out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q', |
|
869 | out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q', | |
862 | w*@k,h*@k,x*@k,(@h-(y+h))*@k,info['i'])) |
|
870 | w*@k,h*@k,x*@k,(@h-(y+h))*@k,info['i'])) | |
863 | Link(x,y,w,h,link) if link and link != '' |
|
871 | Link(x,y,w,h,link) if link and link != '' | |
864 | end |
|
872 | end | |
865 |
|
873 | |||
866 | def Ln(h='') |
|
874 | def Ln(h='') | |
867 | # Line feed; default value is last cell height |
|
875 | # Line feed; default value is last cell height | |
868 | @x=@lMargin |
|
876 | @x=@lMargin | |
869 | if h.kind_of?(String) |
|
877 | if h.kind_of?(String) | |
870 | @y=@y+@lasth |
|
878 | @y=@y+@lasth | |
871 | else |
|
879 | else | |
872 | @y=@y+h |
|
880 | @y=@y+h | |
873 | end |
|
881 | end | |
874 | end |
|
882 | end | |
875 |
|
883 | |||
876 | def GetX |
|
884 | def GetX | |
877 | # Get x position |
|
885 | # Get x position | |
878 | @x |
|
886 | @x | |
879 | end |
|
887 | end | |
880 |
|
888 | |||
881 | def SetX(x) |
|
889 | def SetX(x) | |
882 | # Set x position |
|
890 | # Set x position | |
883 | if x>=0 |
|
891 | if x>=0 | |
884 | @x=x |
|
892 | @x=x | |
885 | else |
|
893 | else | |
886 | @x=@w+x |
|
894 | @x=@w+x | |
887 | end |
|
895 | end | |
888 | end |
|
896 | end | |
889 |
|
897 | |||
890 | def GetY |
|
898 | def GetY | |
891 | # Get y position |
|
899 | # Get y position | |
892 | @y |
|
900 | @y | |
893 | end |
|
901 | end | |
894 |
|
902 | |||
895 | def SetY(y) |
|
903 | def SetY(y) | |
896 | # Set y position and reset x |
|
904 | # Set y position and reset x | |
897 | @x=@lMargin |
|
905 | @x=@lMargin | |
898 | if y>=0 |
|
906 | if y>=0 | |
899 | @y=y |
|
907 | @y=y | |
900 | else |
|
908 | else | |
901 | @y=@h+y |
|
909 | @y=@h+y | |
902 | end |
|
910 | end | |
903 | end |
|
911 | end | |
904 |
|
912 | |||
905 | def SetXY(x,y) |
|
913 | def SetXY(x,y) | |
906 | # Set x and y positions |
|
914 | # Set x and y positions | |
907 | SetY(y) |
|
915 | SetY(y) | |
908 | SetX(x) |
|
916 | SetX(x) | |
909 | end |
|
917 | end | |
910 |
|
918 | |||
911 | def Output(file=nil) |
|
919 | def Output(file=nil) | |
912 | # Output PDF to file or return as a string |
|
920 | # Output PDF to file or return as a string | |
913 |
|
921 | |||
914 | # Finish document if necessary |
|
922 | # Finish document if necessary | |
915 | self.Close if(@state<3) |
|
923 | self.Close if(@state<3) | |
916 |
|
924 | |||
917 | if file.nil? |
|
925 | if file.nil? | |
918 | # Return as a string |
|
926 | # Return as a string | |
919 | return @buffer |
|
927 | return @buffer | |
920 | else |
|
928 | else | |
921 | # Save file locally |
|
929 | # Save file locally | |
922 | open(file,'wb') do |f| |
|
930 | open(file,'wb') do |f| | |
923 | f.write(@buffer) |
|
931 | f.write(@buffer) | |
924 | end |
|
932 | end | |
925 | end |
|
933 | end | |
926 | end |
|
934 | end | |
927 |
|
935 | |||
928 | private |
|
936 | private | |
929 |
|
937 | |||
930 | def putpages |
|
938 | def putpages | |
931 | nb=@page |
|
939 | nb=@page | |
932 | unless @AliasNbPages.nil? or @AliasNbPages=='' |
|
940 | unless @AliasNbPages.nil? or @AliasNbPages=='' | |
933 | # Replace number of pages |
|
941 | # Replace number of pages | |
934 | 1.upto(nb) do |n| |
|
942 | 1.upto(nb) do |n| | |
935 | @pages[n].gsub!(@AliasNbPages,nb.to_s) |
|
943 | @pages[n].gsub!(@AliasNbPages,nb.to_s) | |
936 | end |
|
944 | end | |
937 | end |
|
945 | end | |
938 | if @DefOrientation=='P' |
|
946 | if @DefOrientation=='P' | |
939 | wPt=@fwPt |
|
947 | wPt=@fwPt | |
940 | hPt=@fhPt |
|
948 | hPt=@fhPt | |
941 | else |
|
949 | else | |
942 | wPt=@fhPt |
|
950 | wPt=@fhPt | |
943 | hPt=@fwPt |
|
951 | hPt=@fwPt | |
944 | end |
|
952 | end | |
945 | filter=(@compress) ? '/Filter /FlateDecode ' : '' |
|
953 | filter=(@compress) ? '/Filter /FlateDecode ' : '' | |
946 | 1.upto(nb) do |n| |
|
954 | 1.upto(nb) do |n| | |
947 | # Page |
|
955 | # Page | |
948 | newobj |
|
956 | newobj | |
949 | out('<</Type /Page') |
|
957 | out('<</Type /Page') | |
950 | out('/Parent 1 0 R') |
|
958 | out('/Parent 1 0 R') | |
951 | unless @OrientationChanges[n].nil? |
|
959 | unless @OrientationChanges[n].nil? | |
952 | out(sprintf('/MediaBox [0 0 %.2f %.2f]',hPt,wPt)) |
|
960 | out(sprintf('/MediaBox [0 0 %.2f %.2f]',hPt,wPt)) | |
953 | end |
|
961 | end | |
954 | out('/Resources 2 0 R') |
|
962 | out('/Resources 2 0 R') | |
955 | if @PageLinks[n] |
|
963 | if @PageLinks[n] | |
956 | # Links |
|
964 | # Links | |
957 | annots='/Annots [' |
|
965 | annots='/Annots [' | |
958 | @PageLinks[n].each do |pl| |
|
966 | @PageLinks[n].each do |pl| | |
959 | rect=sprintf('%.2f %.2f %.2f %.2f', |
|
967 | rect=sprintf('%.2f %.2f %.2f %.2f', | |
960 | pl[0],pl[1],pl[0]+pl[2],pl[1]-pl[3]) |
|
968 | pl[0],pl[1],pl[0]+pl[2],pl[1]-pl[3]) | |
961 | annots=annots+'<</Type /Annot /Subtype /Link /Rect ['+rect+ |
|
969 | annots=annots+'<</Type /Annot /Subtype /Link /Rect ['+rect+ | |
962 | '] /Border [0 0 0] ' |
|
970 | '] /Border [0 0 0] ' | |
963 | if pl[4].kind_of?(String) |
|
971 | if pl[4].kind_of?(String) | |
964 | annots=annots+'/A <</S /URI /URI '+textstring(pl[4])+ |
|
972 | annots=annots+'/A <</S /URI /URI '+textstring(pl[4])+ | |
965 | '>>>>' |
|
973 | '>>>>' | |
966 | else |
|
974 | else | |
967 | l=@links[pl[4]] |
|
975 | l=@links[pl[4]] | |
968 | h=@OrientationChanges[l[0]].nil? ? hPt : wPt |
|
976 | h=@OrientationChanges[l[0]].nil? ? hPt : wPt | |
969 | annots=annots+sprintf( |
|
977 | annots=annots+sprintf( | |
970 | '/Dest [%d 0 R /XYZ 0 %.2f null]>>', |
|
978 | '/Dest [%d 0 R /XYZ 0 %.2f null]>>', | |
971 | 1+2*l[0],h-l[1]*@k) |
|
979 | 1+2*l[0],h-l[1]*@k) | |
972 | end |
|
980 | end | |
973 | end |
|
981 | end | |
974 | out(annots+']') |
|
982 | out(annots+']') | |
975 | end |
|
983 | end | |
976 | out('/Contents '+(@n+1).to_s+' 0 R>>') |
|
984 | out('/Contents '+(@n+1).to_s+' 0 R>>') | |
977 | out('endobj') |
|
985 | out('endobj') | |
978 | # Page content |
|
986 | # Page content | |
979 | p=(@compress) ? Zlib::Deflate.deflate(@pages[n]) : @pages[n] |
|
987 | p=(@compress) ? Zlib::Deflate.deflate(@pages[n]) : @pages[n] | |
980 | newobj |
|
988 | newobj | |
981 | out('<<'+filter+'/Length '+p.length.to_s+'>>') |
|
989 | out('<<'+filter+'/Length '+p.length.to_s+'>>') | |
982 | putstream(p) |
|
990 | putstream(p) | |
983 | out('endobj') |
|
991 | out('endobj') | |
984 | end |
|
992 | end | |
985 | # Pages root |
|
993 | # Pages root | |
986 | @offsets[1]=@buffer.length |
|
994 | @offsets[1]=@buffer.length | |
987 | out('1 0 obj') |
|
995 | out('1 0 obj') | |
988 | out('<</Type /Pages') |
|
996 | out('<</Type /Pages') | |
989 | kids='/Kids [' |
|
997 | kids='/Kids [' | |
990 | nb.times do |i| |
|
998 | nb.times do |i| | |
991 | kids=kids+(3+2*i).to_s+' 0 R ' |
|
999 | kids=kids+(3+2*i).to_s+' 0 R ' | |
992 | end |
|
1000 | end | |
993 | out(kids+']') |
|
1001 | out(kids+']') | |
994 | out('/Count '+nb.to_s) |
|
1002 | out('/Count '+nb.to_s) | |
995 | out(sprintf('/MediaBox [0 0 %.2f %.2f]',wPt,hPt)) |
|
1003 | out(sprintf('/MediaBox [0 0 %.2f %.2f]',wPt,hPt)) | |
996 | out('>>') |
|
1004 | out('>>') | |
997 | out('endobj') |
|
1005 | out('endobj') | |
998 | end |
|
1006 | end | |
999 |
|
1007 | |||
1000 | def putfonts |
|
1008 | def putfonts | |
1001 | nf=@n |
|
1009 | nf=@n | |
1002 | @diffs.each do |diff| |
|
1010 | @diffs.each do |diff| | |
1003 | # Encodings |
|
1011 | # Encodings | |
1004 | newobj |
|
1012 | newobj | |
1005 | out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences '+ |
|
1013 | out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences '+ | |
1006 | '['+diff+']>>') |
|
1014 | '['+diff+']>>') | |
1007 | out('endobj') |
|
1015 | out('endobj') | |
1008 | end |
|
1016 | end | |
1009 |
|
1017 | |||
1010 | @FontFiles.each do |file, info| |
|
1018 | @FontFiles.each do |file, info| | |
1011 | # Font file embedding |
|
1019 | # Font file embedding | |
1012 | newobj |
|
1020 | newobj | |
1013 | @FontFiles[file]['n'] = @n |
|
1021 | @FontFiles[file]['n'] = @n | |
1014 |
|
1022 | |||
1015 | if self.class.const_defined? 'FPDF_FONTPATH' then |
|
1023 | if self.class.const_defined? 'FPDF_FONTPATH' then | |
1016 | if FPDF_FONTPATH[-1,1] == '/' then |
|
1024 | if FPDF_FONTPATH[-1,1] == '/' then | |
1017 | file = FPDF_FONTPATH + file |
|
1025 | file = FPDF_FONTPATH + file | |
1018 | else |
|
1026 | else | |
1019 | file = FPDF_FONTPATH + '/' + file |
|
1027 | file = FPDF_FONTPATH + '/' + file | |
1020 | end |
|
1028 | end | |
1021 | end |
|
1029 | end | |
1022 |
|
1030 | |||
1023 | size = File.size(file) |
|
1031 | size = File.size(file) | |
1024 | unless File.exists?(file) |
|
1032 | unless File.exists?(file) | |
1025 | Error('Font file not found') |
|
1033 | Error('Font file not found') | |
1026 | end |
|
1034 | end | |
1027 |
|
1035 | |||
1028 | out('<</Length ' + size.to_s) |
|
1036 | out('<</Length ' + size.to_s) | |
1029 |
|
1037 | |||
1030 | if file[-2, 2] == '.z' then |
|
1038 | if file[-2, 2] == '.z' then | |
1031 | out('/Filter /FlateDecode') |
|
1039 | out('/Filter /FlateDecode') | |
1032 | end |
|
1040 | end | |
1033 | out('/Length1 ' + info['length1']) |
|
1041 | out('/Length1 ' + info['length1']) | |
1034 | out('/Length2 ' + info['length2'] + ' /Length3 0') if info['length2'] |
|
1042 | out('/Length2 ' + info['length2'] + ' /Length3 0') if info['length2'] | |
1035 | out('>>') |
|
1043 | out('>>') | |
1036 | open(file, 'rb') do |f| |
|
1044 | open(file, 'rb') do |f| | |
1037 | putstream(f.read()) |
|
1045 | putstream(f.read()) | |
1038 | end |
|
1046 | end | |
1039 | out('endobj') |
|
1047 | out('endobj') | |
1040 | end |
|
1048 | end | |
1041 |
|
1049 | |||
1042 | file = 0 |
|
1050 | file = 0 | |
1043 | @fonts.each do |k, font| |
|
1051 | @fonts.each do |k, font| | |
1044 | # Font objects |
|
1052 | # Font objects | |
1045 | @fonts[k]['n']=@n+1 |
|
1053 | @fonts[k]['n']=@n+1 | |
1046 | type=font['type'] |
|
1054 | type=font['type'] | |
1047 | name=font['name'] |
|
1055 | name=font['name'] | |
1048 | if type=='core' |
|
1056 | if type=='core' | |
1049 | # Standard font |
|
1057 | # Standard font | |
1050 | newobj |
|
1058 | newobj | |
1051 | out('<</Type /Font') |
|
1059 | out('<</Type /Font') | |
1052 | out('/BaseFont /'+name) |
|
1060 | out('/BaseFont /'+name) | |
1053 | out('/Subtype /Type1') |
|
1061 | out('/Subtype /Type1') | |
1054 | if name!='Symbol' and name!='ZapfDingbats' |
|
1062 | if name!='Symbol' and name!='ZapfDingbats' | |
1055 | out('/Encoding /WinAnsiEncoding') |
|
1063 | out('/Encoding /WinAnsiEncoding') | |
1056 | end |
|
1064 | end | |
1057 | out('>>') |
|
1065 | out('>>') | |
1058 | out('endobj') |
|
1066 | out('endobj') | |
1059 | elsif type=='Type1' or type=='TrueType' |
|
1067 | elsif type=='Type1' or type=='TrueType' | |
1060 | # Additional Type1 or TrueType font |
|
1068 | # Additional Type1 or TrueType font | |
1061 | newobj |
|
1069 | newobj | |
1062 | out('<</Type /Font') |
|
1070 | out('<</Type /Font') | |
1063 | out('/BaseFont /'+name) |
|
1071 | out('/BaseFont /'+name) | |
1064 | out('/Subtype /'+type) |
|
1072 | out('/Subtype /'+type) | |
1065 | out('/FirstChar 32 /LastChar 255') |
|
1073 | out('/FirstChar 32 /LastChar 255') | |
1066 | out('/Widths '+(@n+1).to_s+' 0 R') |
|
1074 | out('/Widths '+(@n+1).to_s+' 0 R') | |
1067 | out('/FontDescriptor '+(@n+2).to_s+' 0 R') |
|
1075 | out('/FontDescriptor '+(@n+2).to_s+' 0 R') | |
1068 | if font['enc'] and font['enc'] != '' |
|
1076 | if font['enc'] and font['enc'] != '' | |
1069 | unless font['diff'].nil? |
|
1077 | unless font['diff'].nil? | |
1070 | out('/Encoding '+(nf+font['diff']).to_s+' 0 R') |
|
1078 | out('/Encoding '+(nf+font['diff']).to_s+' 0 R') | |
1071 | else |
|
1079 | else | |
1072 | out('/Encoding /WinAnsiEncoding') |
|
1080 | out('/Encoding /WinAnsiEncoding') | |
1073 | end |
|
1081 | end | |
1074 | end |
|
1082 | end | |
1075 | out('>>') |
|
1083 | out('>>') | |
1076 | out('endobj') |
|
1084 | out('endobj') | |
1077 | # Widths |
|
1085 | # Widths | |
1078 | newobj |
|
1086 | newobj | |
1079 | cw=font['cw'] |
|
1087 | cw=font['cw'] | |
1080 | s='[' |
|
1088 | s='[' | |
1081 | 32.upto(255) do |i| |
|
1089 | 32.upto(255) do |i| | |
1082 |
s << cw |
|
1090 | s << GetCharWidth(cw, i).to_s + ' ' | |
1083 | end |
|
1091 | end | |
1084 | out(s+']') |
|
1092 | out(s+']') | |
1085 | out('endobj') |
|
1093 | out('endobj') | |
1086 | # Descriptor |
|
1094 | # Descriptor | |
1087 | newobj |
|
1095 | newobj | |
1088 | s='<</Type /FontDescriptor /FontName /'+name |
|
1096 | s='<</Type /FontDescriptor /FontName /'+name | |
1089 | font['desc'].each do |k, v| |
|
1097 | font['desc'].each do |k, v| | |
1090 | s << ' /'+k+' '+v |
|
1098 | s << ' /'+k+' '+v | |
1091 | end |
|
1099 | end | |
1092 | file=font['file'] |
|
1100 | file=font['file'] | |
1093 | if file |
|
1101 | if file | |
1094 | s << ' /FontFile'+(type=='Type1' ? '' : '2')+' '+ |
|
1102 | s << ' /FontFile'+(type=='Type1' ? '' : '2')+' '+ | |
1095 | @FontFiles[file]['n'].to_s+' 0 R' |
|
1103 | @FontFiles[file]['n'].to_s+' 0 R' | |
1096 | end |
|
1104 | end | |
1097 | out(s+'>>') |
|
1105 | out(s+'>>') | |
1098 | out('endobj') |
|
1106 | out('endobj') | |
1099 | else |
|
1107 | else | |
1100 | # Allow for additional types |
|
1108 | # Allow for additional types | |
1101 | mtd='put'+type.downcase |
|
1109 | mtd='put'+type.downcase | |
1102 | unless self.respond_to?(mtd) |
|
1110 | unless self.respond_to?(mtd) | |
1103 | self.Error('Unsupported font type: '+type) |
|
1111 | self.Error('Unsupported font type: '+type) | |
1104 | end |
|
1112 | end | |
1105 | self.send(mtd, font) |
|
1113 | self.send(mtd, font) | |
1106 | end |
|
1114 | end | |
1107 | end |
|
1115 | end | |
1108 | end |
|
1116 | end | |
1109 |
|
1117 | |||
1110 | def putimages |
|
1118 | def putimages | |
1111 | filter=(@compress) ? '/Filter /FlateDecode ' : '' |
|
1119 | filter=(@compress) ? '/Filter /FlateDecode ' : '' | |
1112 | @images.each do |file, info| |
|
1120 | @images.each do |file, info| | |
1113 | newobj |
|
1121 | newobj | |
1114 | @images[file]['n']=@n |
|
1122 | @images[file]['n']=@n | |
1115 | out('<</Type /XObject') |
|
1123 | out('<</Type /XObject') | |
1116 | out('/Subtype /Image') |
|
1124 | out('/Subtype /Image') | |
1117 | out('/Width '+info['w'].to_s) |
|
1125 | out('/Width '+info['w'].to_s) | |
1118 | out('/Height '+info['h'].to_s) |
|
1126 | out('/Height '+info['h'].to_s) | |
1119 | if info['cs']=='Indexed' |
|
1127 | if info['cs']=='Indexed' | |
1120 | out("/ColorSpace [/Indexed /DeviceRGB #{info['pal'].length/3-1} #{(@n+1)} 0 R]") |
|
1128 | out("/ColorSpace [/Indexed /DeviceRGB #{info['pal'].length/3-1} #{(@n+1)} 0 R]") | |
1121 | else |
|
1129 | else | |
1122 | out('/ColorSpace /'+info['cs']) |
|
1130 | out('/ColorSpace /'+info['cs']) | |
1123 | if info['cs']=='DeviceCMYK' |
|
1131 | if info['cs']=='DeviceCMYK' | |
1124 | out('/Decode [1 0 1 0 1 0 1 0]') |
|
1132 | out('/Decode [1 0 1 0 1 0 1 0]') | |
1125 | end |
|
1133 | end | |
1126 | end |
|
1134 | end | |
1127 | out('/BitsPerComponent '+info['bpc'].to_s) |
|
1135 | out('/BitsPerComponent '+info['bpc'].to_s) | |
1128 | out('/Filter /'+info['f']) if info['f'] |
|
1136 | out('/Filter /'+info['f']) if info['f'] | |
1129 | unless info['parms'].nil? |
|
1137 | unless info['parms'].nil? | |
1130 | out(info['parms']) |
|
1138 | out(info['parms']) | |
1131 | end |
|
1139 | end | |
1132 | if info['trns'] and info['trns'].kind_of?(Array) |
|
1140 | if info['trns'] and info['trns'].kind_of?(Array) | |
1133 | trns='' |
|
1141 | trns='' | |
1134 | info['trns'].length.times do |i| |
|
1142 | info['trns'].length.times do |i| | |
1135 | trns=trns+info['trns'][i].to_s+' '+info['trns'][i].to_s+' ' |
|
1143 | trns=trns+info['trns'][i].to_s+' '+info['trns'][i].to_s+' ' | |
1136 | end |
|
1144 | end | |
1137 | out('/Mask ['+trns+']') |
|
1145 | out('/Mask ['+trns+']') | |
1138 | end |
|
1146 | end | |
1139 | out('/Length '+info['data'].length.to_s+'>>') |
|
1147 | out('/Length '+info['data'].length.to_s+'>>') | |
1140 | putstream(info['data']) |
|
1148 | putstream(info['data']) | |
1141 | @images[file]['data']=nil |
|
1149 | @images[file]['data']=nil | |
1142 | out('endobj') |
|
1150 | out('endobj') | |
1143 | # Palette |
|
1151 | # Palette | |
1144 | if info['cs']=='Indexed' |
|
1152 | if info['cs']=='Indexed' | |
1145 | newobj |
|
1153 | newobj | |
1146 | pal=(@compress) ? Zlib::Deflate.deflate(info['pal']) : info['pal'] |
|
1154 | pal=(@compress) ? Zlib::Deflate.deflate(info['pal']) : info['pal'] | |
1147 | out('<<'+filter+'/Length '+pal.length.to_s+'>>') |
|
1155 | out('<<'+filter+'/Length '+pal.length.to_s+'>>') | |
1148 | putstream(pal) |
|
1156 | putstream(pal) | |
1149 | out('endobj') |
|
1157 | out('endobj') | |
1150 | end |
|
1158 | end | |
1151 | end |
|
1159 | end | |
1152 | end |
|
1160 | end | |
1153 |
|
1161 | |||
1154 | def putxobjectdict |
|
1162 | def putxobjectdict | |
1155 | @images.each_value do |image| |
|
1163 | @images.each_value do |image| | |
1156 | out('/I'+image['i'].to_s+' '+image['n'].to_s+' 0 R') |
|
1164 | out('/I'+image['i'].to_s+' '+image['n'].to_s+' 0 R') | |
1157 | end |
|
1165 | end | |
1158 | end |
|
1166 | end | |
1159 |
|
1167 | |||
1160 | def putresourcedict |
|
1168 | def putresourcedict | |
1161 | out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]') |
|
1169 | out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]') | |
1162 | out('/Font <<') |
|
1170 | out('/Font <<') | |
1163 | @fonts.each_value do |font| |
|
1171 | @fonts.each_value do |font| | |
1164 | out('/F'+font['i'].to_s+' '+font['n'].to_s+' 0 R') |
|
1172 | out('/F'+font['i'].to_s+' '+font['n'].to_s+' 0 R') | |
1165 | end |
|
1173 | end | |
1166 | out('>>') |
|
1174 | out('>>') | |
1167 | out('/XObject <<') |
|
1175 | out('/XObject <<') | |
1168 | putxobjectdict |
|
1176 | putxobjectdict | |
1169 | out('>>') |
|
1177 | out('>>') | |
1170 | end |
|
1178 | end | |
1171 |
|
1179 | |||
1172 | def putresources |
|
1180 | def putresources | |
1173 | putfonts |
|
1181 | putfonts | |
1174 | putimages |
|
1182 | putimages | |
1175 | # Resource dictionary |
|
1183 | # Resource dictionary | |
1176 | @offsets[2]=@buffer.length |
|
1184 | @offsets[2]=@buffer.length | |
1177 | out('2 0 obj') |
|
1185 | out('2 0 obj') | |
1178 | out('<<') |
|
1186 | out('<<') | |
1179 | putresourcedict |
|
1187 | putresourcedict | |
1180 | out('>>') |
|
1188 | out('>>') | |
1181 | out('endobj') |
|
1189 | out('endobj') | |
1182 | end |
|
1190 | end | |
1183 |
|
1191 | |||
1184 | def putinfo |
|
1192 | def putinfo | |
1185 | out('/Producer '+textstring('Ruby FPDF '+FPDF_VERSION)); |
|
1193 | out('/Producer '+textstring('Ruby FPDF '+FPDF_VERSION)); | |
1186 | unless @title.nil? |
|
1194 | unless @title.nil? | |
1187 | out('/Title '+textstring(@title)) |
|
1195 | out('/Title '+textstring(@title)) | |
1188 | end |
|
1196 | end | |
1189 | unless @subject.nil? |
|
1197 | unless @subject.nil? | |
1190 | out('/Subject '+textstring(@subject)) |
|
1198 | out('/Subject '+textstring(@subject)) | |
1191 | end |
|
1199 | end | |
1192 | unless @author.nil? |
|
1200 | unless @author.nil? | |
1193 | out('/Author '+textstring(@author)) |
|
1201 | out('/Author '+textstring(@author)) | |
1194 | end |
|
1202 | end | |
1195 | unless @keywords.nil? |
|
1203 | unless @keywords.nil? | |
1196 | out('/Keywords '+textstring(@keywords)) |
|
1204 | out('/Keywords '+textstring(@keywords)) | |
1197 | end |
|
1205 | end | |
1198 | unless @creator.nil? |
|
1206 | unless @creator.nil? | |
1199 | out('/Creator '+textstring(@creator)) |
|
1207 | out('/Creator '+textstring(@creator)) | |
1200 | end |
|
1208 | end | |
1201 | out('/CreationDate '+textstring('D: '+DateTime.now.to_s)) |
|
1209 | out('/CreationDate '+textstring('D: '+DateTime.now.to_s)) | |
1202 | end |
|
1210 | end | |
1203 |
|
1211 | |||
1204 | def putcatalog |
|
1212 | def putcatalog | |
1205 | out('/Type /Catalog') |
|
1213 | out('/Type /Catalog') | |
1206 | out('/Pages 1 0 R') |
|
1214 | out('/Pages 1 0 R') | |
1207 | if @ZoomMode=='fullpage' |
|
1215 | if @ZoomMode=='fullpage' | |
1208 | out('/OpenAction [3 0 R /Fit]') |
|
1216 | out('/OpenAction [3 0 R /Fit]') | |
1209 | elsif @ZoomMode=='fullwidth' |
|
1217 | elsif @ZoomMode=='fullwidth' | |
1210 | out('/OpenAction [3 0 R /FitH null]') |
|
1218 | out('/OpenAction [3 0 R /FitH null]') | |
1211 | elsif @ZoomMode=='real' |
|
1219 | elsif @ZoomMode=='real' | |
1212 | out('/OpenAction [3 0 R /XYZ null null 1]') |
|
1220 | out('/OpenAction [3 0 R /XYZ null null 1]') | |
1213 | elsif not @ZoomMode.kind_of?(String) |
|
1221 | elsif not @ZoomMode.kind_of?(String) | |
1214 | out('/OpenAction [3 0 R /XYZ null null '+(@ZoomMode/100)+']') |
|
1222 | out('/OpenAction [3 0 R /XYZ null null '+(@ZoomMode/100)+']') | |
1215 | end |
|
1223 | end | |
1216 |
|
1224 | |||
1217 | if @LayoutMode=='single' |
|
1225 | if @LayoutMode=='single' | |
1218 | out('/PageLayout /SinglePage') |
|
1226 | out('/PageLayout /SinglePage') | |
1219 | elsif @LayoutMode=='continuous' |
|
1227 | elsif @LayoutMode=='continuous' | |
1220 | out('/PageLayout /OneColumn') |
|
1228 | out('/PageLayout /OneColumn') | |
1221 | elsif @LayoutMode=='two' |
|
1229 | elsif @LayoutMode=='two' | |
1222 | out('/PageLayout /TwoColumnLeft') |
|
1230 | out('/PageLayout /TwoColumnLeft') | |
1223 | end |
|
1231 | end | |
1224 | end |
|
1232 | end | |
1225 |
|
1233 | |||
1226 | def putheader |
|
1234 | def putheader | |
1227 | out('%PDF-'+@PDFVersion) |
|
1235 | out('%PDF-'+@PDFVersion) | |
1228 | end |
|
1236 | end | |
1229 |
|
1237 | |||
1230 | def puttrailer |
|
1238 | def puttrailer | |
1231 | out('/Size '+(@n+1).to_s) |
|
1239 | out('/Size '+(@n+1).to_s) | |
1232 | out('/Root '+@n.to_s+' 0 R') |
|
1240 | out('/Root '+@n.to_s+' 0 R') | |
1233 | out('/Info '+(@n-1).to_s+' 0 R') |
|
1241 | out('/Info '+(@n-1).to_s+' 0 R') | |
1234 | end |
|
1242 | end | |
1235 |
|
1243 | |||
1236 | def enddoc |
|
1244 | def enddoc | |
1237 | putheader |
|
1245 | putheader | |
1238 | putpages |
|
1246 | putpages | |
1239 | putresources |
|
1247 | putresources | |
1240 | # Info |
|
1248 | # Info | |
1241 | newobj |
|
1249 | newobj | |
1242 | out('<<') |
|
1250 | out('<<') | |
1243 | putinfo |
|
1251 | putinfo | |
1244 | out('>>') |
|
1252 | out('>>') | |
1245 | out('endobj') |
|
1253 | out('endobj') | |
1246 | # Catalog |
|
1254 | # Catalog | |
1247 | newobj |
|
1255 | newobj | |
1248 | out('<<') |
|
1256 | out('<<') | |
1249 | putcatalog |
|
1257 | putcatalog | |
1250 | out('>>') |
|
1258 | out('>>') | |
1251 | out('endobj') |
|
1259 | out('endobj') | |
1252 | # Cross-ref |
|
1260 | # Cross-ref | |
1253 | o=@buffer.length |
|
1261 | o=@buffer.length | |
1254 | out('xref') |
|
1262 | out('xref') | |
1255 | out('0 '+(@n+1).to_s) |
|
1263 | out('0 '+(@n+1).to_s) | |
1256 | out('0000000000 65535 f ') |
|
1264 | out('0000000000 65535 f ') | |
1257 | 1.upto(@n) do |i| |
|
1265 | 1.upto(@n) do |i| | |
1258 | out(sprintf('%010d 00000 n ',@offsets[i])) |
|
1266 | out(sprintf('%010d 00000 n ',@offsets[i])) | |
1259 | end |
|
1267 | end | |
1260 | # Trailer |
|
1268 | # Trailer | |
1261 | out('trailer') |
|
1269 | out('trailer') | |
1262 | out('<<') |
|
1270 | out('<<') | |
1263 | puttrailer |
|
1271 | puttrailer | |
1264 | out('>>') |
|
1272 | out('>>') | |
1265 | out('startxref') |
|
1273 | out('startxref') | |
1266 | out(o) |
|
1274 | out(o) | |
1267 | out('%%EOF') |
|
1275 | out('%%EOF') | |
1268 | state=3 |
|
1276 | state=3 | |
1269 | end |
|
1277 | end | |
1270 |
|
1278 | |||
1271 | def beginpage(orientation) |
|
1279 | def beginpage(orientation) | |
1272 | @page=@page+1 |
|
1280 | @page=@page+1 | |
1273 | @pages[@page]='' |
|
1281 | @pages[@page]='' | |
1274 | @state=2 |
|
1282 | @state=2 | |
1275 | @x=@lMargin |
|
1283 | @x=@lMargin | |
1276 | @y=@tMargin |
|
1284 | @y=@tMargin | |
1277 | @lasth=0 |
|
1285 | @lasth=0 | |
1278 | @FontFamily='' |
|
1286 | @FontFamily='' | |
1279 | # Page orientation |
|
1287 | # Page orientation | |
1280 | if orientation=='' |
|
1288 | if orientation=='' | |
1281 | orientation=@DefOrientation |
|
1289 | orientation=@DefOrientation | |
1282 | else |
|
1290 | else | |
1283 | orientation=orientation[0].chr.upcase |
|
1291 | orientation=orientation[0].chr.upcase | |
1284 | if orientation!=@DefOrientation |
|
1292 | if orientation!=@DefOrientation | |
1285 | @OrientationChanges[@page]=true |
|
1293 | @OrientationChanges[@page]=true | |
1286 | end |
|
1294 | end | |
1287 | end |
|
1295 | end | |
1288 | if orientation!=@CurOrientation |
|
1296 | if orientation!=@CurOrientation | |
1289 | # Change orientation |
|
1297 | # Change orientation | |
1290 | if orientation=='P' |
|
1298 | if orientation=='P' | |
1291 | @wPt=@fwPt |
|
1299 | @wPt=@fwPt | |
1292 | @hPt=@fhPt |
|
1300 | @hPt=@fhPt | |
1293 | @w=@fw |
|
1301 | @w=@fw | |
1294 | @h=@fh |
|
1302 | @h=@fh | |
1295 | else |
|
1303 | else | |
1296 | @wPt=@fhPt |
|
1304 | @wPt=@fhPt | |
1297 | @hPt=@fwPt |
|
1305 | @hPt=@fwPt | |
1298 | @w=@fh |
|
1306 | @w=@fh | |
1299 | @h=@fw |
|
1307 | @h=@fw | |
1300 | end |
|
1308 | end | |
1301 | @PageBreakTrigger=@h-@bMargin |
|
1309 | @PageBreakTrigger=@h-@bMargin | |
1302 | @CurOrientation=orientation |
|
1310 | @CurOrientation=orientation | |
1303 | end |
|
1311 | end | |
1304 | end |
|
1312 | end | |
1305 |
|
1313 | |||
1306 | def endpage |
|
1314 | def endpage | |
1307 | # End of page contents |
|
1315 | # End of page contents | |
1308 | @state=1 |
|
1316 | @state=1 | |
1309 | end |
|
1317 | end | |
1310 |
|
1318 | |||
1311 | def newobj |
|
1319 | def newobj | |
1312 | # Begin a new object |
|
1320 | # Begin a new object | |
1313 | @n=@n+1 |
|
1321 | @n=@n+1 | |
1314 | @offsets[@n]=@buffer.length |
|
1322 | @offsets[@n]=@buffer.length | |
1315 | out(@n.to_s+' 0 obj') |
|
1323 | out(@n.to_s+' 0 obj') | |
1316 | end |
|
1324 | end | |
1317 |
|
1325 | |||
1318 | def dounderline(x,y,txt) |
|
1326 | def dounderline(x,y,txt) | |
1319 | # Underline text |
|
1327 | # Underline text | |
1320 | up=@CurrentFont['up'] |
|
1328 | up=@CurrentFont['up'] | |
1321 | ut=@CurrentFont['ut'] |
|
1329 | ut=@CurrentFont['ut'] | |
1322 | w=GetStringWidth(txt)+@ws*txt.count(' ') |
|
1330 | w=GetStringWidth(txt)+@ws*txt.count(' ') | |
1323 | sprintf('%.2f %.2f %.2f %.2f re f', |
|
1331 | sprintf('%.2f %.2f %.2f %.2f re f', | |
1324 | x*@k,(@h-(y-up/1000.0*@FontSize))*@k,w*@k,-ut/1000.0*@FontSizePt) |
|
1332 | x*@k,(@h-(y-up/1000.0*@FontSize))*@k,w*@k,-ut/1000.0*@FontSizePt) | |
1325 | end |
|
1333 | end | |
1326 |
|
1334 | |||
1327 | def parsejpg(file) |
|
1335 | def parsejpg(file) | |
1328 | # Extract info from a JPEG file |
|
1336 | # Extract info from a JPEG file | |
1329 | a=extractjpginfo(file) |
|
1337 | a=extractjpginfo(file) | |
1330 | raise "Missing or incorrect JPEG file: #{file}" if a.nil? |
|
1338 | raise "Missing or incorrect JPEG file: #{file}" if a.nil? | |
1331 |
|
1339 | |||
1332 | if a['channels'].nil? || a['channels']==3 then |
|
1340 | if a['channels'].nil? || a['channels']==3 then | |
1333 | colspace='DeviceRGB' |
|
1341 | colspace='DeviceRGB' | |
1334 | elsif a['channels']==4 then |
|
1342 | elsif a['channels']==4 then | |
1335 | colspace='DeviceCMYK' |
|
1343 | colspace='DeviceCMYK' | |
1336 | else |
|
1344 | else | |
1337 | colspace='DeviceGray' |
|
1345 | colspace='DeviceGray' | |
1338 | end |
|
1346 | end | |
1339 | bpc= a['bits'] ? a['bits'].to_i : 8 |
|
1347 | bpc= a['bits'] ? a['bits'].to_i : 8 | |
1340 |
|
1348 | |||
1341 | # Read whole file |
|
1349 | # Read whole file | |
1342 | data = nil |
|
1350 | data = nil | |
1343 | open(file, 'rb') do |f| |
|
1351 | open(file, 'rb') do |f| | |
1344 | data = f.read |
|
1352 | data = f.read | |
1345 | end |
|
1353 | end | |
1346 | return {'w'=>a['width'],'h'=>a['height'],'cs'=>colspace,'bpc'=>bpc,'f'=>'DCTDecode','data'=>data} |
|
1354 | return {'w'=>a['width'],'h'=>a['height'],'cs'=>colspace,'bpc'=>bpc,'f'=>'DCTDecode','data'=>data} | |
1347 | end |
|
1355 | end | |
1348 |
|
1356 | |||
1349 | def parsepng(file) |
|
1357 | def parsepng(file) | |
1350 | # Extract info from a PNG file |
|
1358 | # Extract info from a PNG file | |
1351 | f=open(file,'rb') |
|
1359 | f=open(file,'rb') | |
1352 | # Check signature |
|
1360 | # Check signature | |
1353 | unless f.read(8)==137.chr+'PNG'+13.chr+10.chr+26.chr+10.chr |
|
1361 | unless f.read(8)==137.chr+'PNG'+13.chr+10.chr+26.chr+10.chr | |
1354 | self.Error('Not a PNG file: '+file) |
|
1362 | self.Error('Not a PNG file: '+file) | |
1355 | end |
|
1363 | end | |
1356 | # Read header chunk |
|
1364 | # Read header chunk | |
1357 | f.read(4) |
|
1365 | f.read(4) | |
1358 | if f.read(4)!='IHDR' |
|
1366 | if f.read(4)!='IHDR' | |
1359 | self.Error('Incorrect PNG file: '+file) |
|
1367 | self.Error('Incorrect PNG file: '+file) | |
1360 | end |
|
1368 | end | |
1361 | w=freadint(f) |
|
1369 | w=freadint(f) | |
1362 | h=freadint(f) |
|
1370 | h=freadint(f) | |
1363 | bpc=f.read(1)[0] |
|
1371 | bpc=f.read(1)[0] | |
1364 | if bpc>8 |
|
1372 | if bpc>8 | |
1365 | self.Error('16-bit depth not supported: '+file) |
|
1373 | self.Error('16-bit depth not supported: '+file) | |
1366 | end |
|
1374 | end | |
1367 | ct=f.read(1)[0] |
|
1375 | ct=f.read(1)[0] | |
1368 | if ct==0 |
|
1376 | if ct==0 | |
1369 | colspace='DeviceGray' |
|
1377 | colspace='DeviceGray' | |
1370 | elsif ct==2 |
|
1378 | elsif ct==2 | |
1371 | colspace='DeviceRGB' |
|
1379 | colspace='DeviceRGB' | |
1372 | elsif ct==3 |
|
1380 | elsif ct==3 | |
1373 | colspace='Indexed' |
|
1381 | colspace='Indexed' | |
1374 | else |
|
1382 | else | |
1375 | self.Error('Alpha channel not supported: '+file) |
|
1383 | self.Error('Alpha channel not supported: '+file) | |
1376 | end |
|
1384 | end | |
1377 | if f.read(1)[0]!=0 |
|
1385 | if f.read(1)[0]!=0 | |
1378 | self.Error('Unknown compression method: '+file) |
|
1386 | self.Error('Unknown compression method: '+file) | |
1379 | end |
|
1387 | end | |
1380 | if f.read(1)[0]!=0 |
|
1388 | if f.read(1)[0]!=0 | |
1381 | self.Error('Unknown filter method: '+file) |
|
1389 | self.Error('Unknown filter method: '+file) | |
1382 | end |
|
1390 | end | |
1383 | if f.read(1)[0]!=0 |
|
1391 | if f.read(1)[0]!=0 | |
1384 | self.Error('Interlacing not supported: '+file) |
|
1392 | self.Error('Interlacing not supported: '+file) | |
1385 | end |
|
1393 | end | |
1386 | f.read(4) |
|
1394 | f.read(4) | |
1387 | parms='/DecodeParms <</Predictor 15 /Colors '+(ct==2 ? '3' : '1')+ |
|
1395 | parms='/DecodeParms <</Predictor 15 /Colors '+(ct==2 ? '3' : '1')+ | |
1388 | ' /BitsPerComponent '+bpc.to_s+' /Columns '+w.to_s+'>>' |
|
1396 | ' /BitsPerComponent '+bpc.to_s+' /Columns '+w.to_s+'>>' | |
1389 | # Scan chunks looking for palette, transparency and image data |
|
1397 | # Scan chunks looking for palette, transparency and image data | |
1390 | pal='' |
|
1398 | pal='' | |
1391 | trns='' |
|
1399 | trns='' | |
1392 | data='' |
|
1400 | data='' | |
1393 | begin |
|
1401 | begin | |
1394 | n=freadint(f) |
|
1402 | n=freadint(f) | |
1395 | type=f.read(4) |
|
1403 | type=f.read(4) | |
1396 | if type=='PLTE' |
|
1404 | if type=='PLTE' | |
1397 | # Read palette |
|
1405 | # Read palette | |
1398 | pal=f.read(n) |
|
1406 | pal=f.read(n) | |
1399 | f.read(4) |
|
1407 | f.read(4) | |
1400 | elsif type=='tRNS' |
|
1408 | elsif type=='tRNS' | |
1401 | # Read transparency info |
|
1409 | # Read transparency info | |
1402 | t=f.read(n) |
|
1410 | t=f.read(n) | |
1403 | if ct==0 |
|
1411 | if ct==0 | |
1404 | trns=[t[1]] |
|
1412 | trns=[t[1]] | |
1405 | elsif ct==2 |
|
1413 | elsif ct==2 | |
1406 | trns=[t[1],t[3],t[5]] |
|
1414 | trns=[t[1],t[3],t[5]] | |
1407 | else |
|
1415 | else | |
1408 | pos=t.index(0) |
|
1416 | pos=t.index(0) | |
1409 | trns=[pos] unless pos.nil? |
|
1417 | trns=[pos] unless pos.nil? | |
1410 | end |
|
1418 | end | |
1411 | f.read(4) |
|
1419 | f.read(4) | |
1412 | elsif type=='IDAT' |
|
1420 | elsif type=='IDAT' | |
1413 | # Read image data block |
|
1421 | # Read image data block | |
1414 | data << f.read(n) |
|
1422 | data << f.read(n) | |
1415 | f.read(4) |
|
1423 | f.read(4) | |
1416 | elsif type=='IEND' |
|
1424 | elsif type=='IEND' | |
1417 | break |
|
1425 | break | |
1418 | else |
|
1426 | else | |
1419 | f.read(n+4) |
|
1427 | f.read(n+4) | |
1420 | end |
|
1428 | end | |
1421 | end while n |
|
1429 | end while n | |
1422 | if colspace=='Indexed' and pal=='' |
|
1430 | if colspace=='Indexed' and pal=='' | |
1423 | self.Error('Missing palette in '+file) |
|
1431 | self.Error('Missing palette in '+file) | |
1424 | end |
|
1432 | end | |
1425 | f.close |
|
1433 | f.close | |
1426 | {'w'=>w,'h'=>h,'cs'=>colspace,'bpc'=>bpc,'f'=>'FlateDecode', |
|
1434 | {'w'=>w,'h'=>h,'cs'=>colspace,'bpc'=>bpc,'f'=>'FlateDecode', | |
1427 | 'parms'=>parms,'pal'=>pal,'trns'=>trns,'data'=>data} |
|
1435 | 'parms'=>parms,'pal'=>pal,'trns'=>trns,'data'=>data} | |
1428 | end |
|
1436 | end | |
1429 |
|
1437 | |||
1430 | def freadint(f) |
|
1438 | def freadint(f) | |
1431 | # Read a 4-byte integer from file |
|
1439 | # Read a 4-byte integer from file | |
1432 | a = f.read(4).unpack('N') |
|
1440 | a = f.read(4).unpack('N') | |
1433 | return a[0] |
|
1441 | return a[0] | |
1434 | end |
|
1442 | end | |
1435 |
|
1443 | |||
1436 | def freadshort(f) |
|
1444 | def freadshort(f) | |
1437 | a = f.read(2).unpack('n') |
|
1445 | a = f.read(2).unpack('n') | |
1438 | return a[0] |
|
1446 | return a[0] | |
1439 | end |
|
1447 | end | |
1440 |
|
1448 | |||
1441 | def freadbyte(f) |
|
1449 | def freadbyte(f) | |
1442 | a = f.read(1).unpack('C') |
|
1450 | a = f.read(1).unpack('C') | |
1443 | return a[0] |
|
1451 | return a[0] | |
1444 | end |
|
1452 | end | |
1445 |
|
1453 | |||
1446 | def textstring(s) |
|
1454 | def textstring(s) | |
1447 | # Format a text string |
|
1455 | # Format a text string | |
1448 | '('+escape(s)+')' |
|
1456 | '('+escape(s)+')' | |
1449 | end |
|
1457 | end | |
1450 |
|
1458 | |||
1451 | def escape(s) |
|
1459 | def escape(s) | |
1452 | # Add \ before \, ( and ) |
|
1460 | # Add \ before \, ( and ) | |
1453 | s.gsub('\\','\\\\').gsub('(','\\(').gsub(')','\\)') |
|
1461 | s.gsub('\\','\\\\').gsub('(','\\(').gsub(')','\\)') | |
1454 | end |
|
1462 | end | |
1455 |
|
1463 | |||
1456 | def putstream(s) |
|
1464 | def putstream(s) | |
1457 | out('stream') |
|
1465 | out('stream') | |
1458 | out(s) |
|
1466 | out(s) | |
1459 | out('endstream') |
|
1467 | out('endstream') | |
1460 | end |
|
1468 | end | |
1461 |
|
1469 | |||
1462 | def out(s) |
|
1470 | def out(s) | |
1463 | # Add a line to the document |
|
1471 | # Add a line to the document | |
1464 | if @state==2 |
|
1472 | if @state==2 | |
1465 | @pages[@page]=@pages[@page]+s+"\n" |
|
1473 | @pages[@page]=@pages[@page]+s+"\n" | |
1466 | else |
|
1474 | else | |
1467 | @buffer=@buffer+s.to_s+"\n" |
|
1475 | @buffer=@buffer+s.to_s+"\n" | |
1468 | end |
|
1476 | end | |
1469 | end |
|
1477 | end | |
1470 |
|
1478 | |||
1471 | # jpeg marker codes |
|
1479 | # jpeg marker codes | |
1472 |
|
1480 | |||
1473 | M_SOF0 = 0xc0 |
|
1481 | M_SOF0 = 0xc0 | |
1474 | M_SOF1 = 0xc1 |
|
1482 | M_SOF1 = 0xc1 | |
1475 | M_SOF2 = 0xc2 |
|
1483 | M_SOF2 = 0xc2 | |
1476 | M_SOF3 = 0xc3 |
|
1484 | M_SOF3 = 0xc3 | |
1477 |
|
1485 | |||
1478 | M_SOF5 = 0xc5 |
|
1486 | M_SOF5 = 0xc5 | |
1479 | M_SOF6 = 0xc6 |
|
1487 | M_SOF6 = 0xc6 | |
1480 | M_SOF7 = 0xc7 |
|
1488 | M_SOF7 = 0xc7 | |
1481 |
|
1489 | |||
1482 | M_SOF9 = 0xc9 |
|
1490 | M_SOF9 = 0xc9 | |
1483 | M_SOF10 = 0xca |
|
1491 | M_SOF10 = 0xca | |
1484 | M_SOF11 = 0xcb |
|
1492 | M_SOF11 = 0xcb | |
1485 |
|
1493 | |||
1486 | M_SOF13 = 0xcd |
|
1494 | M_SOF13 = 0xcd | |
1487 | M_SOF14 = 0xce |
|
1495 | M_SOF14 = 0xce | |
1488 | M_SOF15 = 0xcf |
|
1496 | M_SOF15 = 0xcf | |
1489 |
|
1497 | |||
1490 | M_SOI = 0xd8 |
|
1498 | M_SOI = 0xd8 | |
1491 | M_EOI = 0xd9 |
|
1499 | M_EOI = 0xd9 | |
1492 | M_SOS = 0xda |
|
1500 | M_SOS = 0xda | |
1493 |
|
1501 | |||
1494 | def extractjpginfo(file) |
|
1502 | def extractjpginfo(file) | |
1495 | result = nil |
|
1503 | result = nil | |
1496 |
|
1504 | |||
1497 | open(file, "rb") do |f| |
|
1505 | open(file, "rb") do |f| | |
1498 | marker = jpegnextmarker(f) |
|
1506 | marker = jpegnextmarker(f) | |
1499 |
|
1507 | |||
1500 | if marker != M_SOI |
|
1508 | if marker != M_SOI | |
1501 | return nil |
|
1509 | return nil | |
1502 | end |
|
1510 | end | |
1503 |
|
1511 | |||
1504 | while true |
|
1512 | while true | |
1505 | marker = jpegnextmarker(f) |
|
1513 | marker = jpegnextmarker(f) | |
1506 |
|
1514 | |||
1507 | case marker |
|
1515 | case marker | |
1508 | when M_SOF0, M_SOF1, M_SOF2, M_SOF3, |
|
1516 | when M_SOF0, M_SOF1, M_SOF2, M_SOF3, | |
1509 | M_SOF5, M_SOF6, M_SOF7, M_SOF9, |
|
1517 | M_SOF5, M_SOF6, M_SOF7, M_SOF9, | |
1510 | M_SOF10, M_SOF11, M_SOF13, M_SOF14, |
|
1518 | M_SOF10, M_SOF11, M_SOF13, M_SOF14, | |
1511 | M_SOF15 then |
|
1519 | M_SOF15 then | |
1512 |
|
1520 | |||
1513 | length = freadshort(f) |
|
1521 | length = freadshort(f) | |
1514 |
|
1522 | |||
1515 | if result.nil? |
|
1523 | if result.nil? | |
1516 | result = {} |
|
1524 | result = {} | |
1517 |
|
1525 | |||
1518 | result['bits'] = freadbyte(f) |
|
1526 | result['bits'] = freadbyte(f) | |
1519 | result['height'] = freadshort(f) |
|
1527 | result['height'] = freadshort(f) | |
1520 | result['width'] = freadshort(f) |
|
1528 | result['width'] = freadshort(f) | |
1521 | result['channels'] = freadbyte(f) |
|
1529 | result['channels'] = freadbyte(f) | |
1522 |
|
1530 | |||
1523 | f.seek(length - 8, IO::SEEK_CUR) |
|
1531 | f.seek(length - 8, IO::SEEK_CUR) | |
1524 | else |
|
1532 | else | |
1525 | f.seek(length - 2, IO::SEEK_CUR) |
|
1533 | f.seek(length - 2, IO::SEEK_CUR) | |
1526 | end |
|
1534 | end | |
1527 | when M_SOS, M_EOI then |
|
1535 | when M_SOS, M_EOI then | |
1528 | return result |
|
1536 | return result | |
1529 | else |
|
1537 | else | |
1530 | length = freadshort(f) |
|
1538 | length = freadshort(f) | |
1531 | f.seek(length - 2, IO::SEEK_CUR) |
|
1539 | f.seek(length - 2, IO::SEEK_CUR) | |
1532 | end |
|
1540 | end | |
1533 | end |
|
1541 | end | |
1534 | end |
|
1542 | end | |
1535 | end |
|
1543 | end | |
1536 |
|
1544 | |||
1537 | def jpegnextmarker(f) |
|
1545 | def jpegnextmarker(f) | |
1538 | while true |
|
1546 | while true | |
1539 | # look for 0xff |
|
1547 | # look for 0xff | |
1540 | while (c = freadbyte(f)) != 0xff |
|
1548 | while (c = freadbyte(f)) != 0xff | |
1541 | end |
|
1549 | end | |
1542 |
|
1550 | |||
1543 | c = freadbyte(f) |
|
1551 | c = freadbyte(f) | |
1544 |
|
1552 | |||
1545 | if c != 0 |
|
1553 | if c != 0 | |
1546 | return c |
|
1554 | return c | |
1547 | end |
|
1555 | end | |
1548 | end |
|
1556 | end | |
1549 | end |
|
1557 | end | |
1550 | end |
|
1558 | end |
General Comments 0
You need to be logged in to leave comments.
Login now