Chris@1296
|
1 #============================================================+
|
Chris@1296
|
2 # File name : tcpdf.rb
|
Chris@1296
|
3 # Begin : 2002-08-03
|
Chris@1296
|
4 # Last Update : 2007-03-20
|
Chris@1296
|
5 # Author : Nicola Asuni
|
Chris@1296
|
6 # Version : 1.53.0.TC031
|
Chris@1296
|
7 # License : GNU LGPL (http://www.gnu.org/copyleft/lesser.html)
|
Chris@1296
|
8 #
|
Chris@1296
|
9 # Description : This is a Ruby class for generating PDF files
|
Chris@1296
|
10 # on-the-fly without requiring external
|
Chris@1296
|
11 # extensions.
|
Chris@1296
|
12 #
|
Chris@1296
|
13 # IMPORTANT:
|
Chris@1296
|
14 # This class is an extension and improvement of the Public Domain
|
Chris@1296
|
15 # FPDF class by Olivier Plathey (http://www.fpdf.org).
|
Chris@1296
|
16 #
|
Chris@1296
|
17 # Main changes by Nicola Asuni:
|
Chris@1296
|
18 # Ruby porting;
|
Chris@1296
|
19 # UTF-8 Unicode support;
|
Chris@1296
|
20 # code refactoring;
|
Chris@1296
|
21 # source code clean up;
|
Chris@1296
|
22 # code style and formatting;
|
Chris@1296
|
23 # source code documentation using phpDocumentor (www.phpdoc.org);
|
Chris@1296
|
24 # All ISO page formats were included;
|
Chris@1296
|
25 # image scale factor;
|
Chris@1296
|
26 # includes methods to parse and printsome XHTML code, supporting the following elements: h1, h2, h3, h4, h5, h6, b, u, i, a, img, p, br, strong, em, font, blockquote, li, ul, ol, hr, td, th, tr, table, sup, sub, small;
|
Chris@1296
|
27 # includes a method to print various barcode formats using an improved version of "Generic Barcode Render Class" by Karim Mribti (http://www.mribti.com/barcode/) (require GD library: http://www.boutell.com/gd/);
|
Chris@1296
|
28 # defines standard Header() and Footer() methods.
|
Chris@1296
|
29 #
|
Chris@1296
|
30 # Ported to Ruby by Ed Moss 2007-08-06
|
Chris@1296
|
31 #
|
Chris@1296
|
32 #============================================================+
|
Chris@1296
|
33
|
Chris@1296
|
34 require 'tempfile'
|
Chris@1296
|
35 require 'core/rmagick'
|
Chris@1296
|
36
|
Chris@1296
|
37 #
|
Chris@1296
|
38 # TCPDF Class.
|
Chris@1296
|
39 # @package com.tecnick.tcpdf
|
Chris@1296
|
40 #
|
Chris@1296
|
41
|
Chris@1296
|
42 @@version = "1.53.0.TC031"
|
Chris@1296
|
43 @@fpdf_charwidths = {}
|
Chris@1296
|
44
|
Chris@1296
|
45 PDF_PRODUCER = 'TCPDF via RFPDF 1.53.0.TC031 (http://tcpdf.sourceforge.net)'
|
Chris@1296
|
46
|
Chris@1296
|
47 module TCPDFFontDescriptor
|
Chris@1296
|
48 @@descriptors = { 'freesans' => {} }
|
Chris@1296
|
49 @@font_name = 'freesans'
|
Chris@1296
|
50
|
Chris@1296
|
51 def self.font(font_name)
|
Chris@1296
|
52 @@descriptors[font_name.gsub(".rb", "")]
|
Chris@1296
|
53 end
|
Chris@1296
|
54
|
Chris@1296
|
55 def self.define(font_name = 'freesans')
|
Chris@1296
|
56 @@descriptors[font_name] ||= {}
|
Chris@1296
|
57 yield @@descriptors[font_name]
|
Chris@1296
|
58 end
|
Chris@1296
|
59 end
|
Chris@1296
|
60
|
Chris@1296
|
61 # This is a Ruby class for generating PDF files on-the-fly without requiring external extensions.<br>
|
Chris@1296
|
62 # This class is an extension and improvement of the FPDF class by Olivier Plathey (http://www.fpdf.org).<br>
|
Chris@1296
|
63 # This version contains some changes: [porting to Ruby, support for UTF-8 Unicode, code style and formatting, php documentation (www.phpdoc.org), ISO page formats, minor improvements, image scale factor]<br>
|
Chris@1296
|
64 # TCPDF project (http://tcpdf.sourceforge.net) is based on the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org).<br>
|
Chris@1296
|
65 # To add your own TTF fonts please read /fonts/README.TXT
|
Chris@1296
|
66 # @name TCPDF
|
Chris@1296
|
67 # @package com.tecnick.tcpdf
|
Chris@1296
|
68 # @@version 1.53.0.TC031
|
Chris@1296
|
69 # @author Nicola Asuni
|
Chris@1296
|
70 # @link http://tcpdf.sourceforge.net
|
Chris@1296
|
71 # @license http://www.gnu.org/copyleft/lesser.html LGPL
|
Chris@1296
|
72 #
|
Chris@1296
|
73 class TCPDF
|
Chris@1296
|
74 include RFPDF
|
Chris@1296
|
75 include Core::RFPDF
|
Chris@1296
|
76 include RFPDF::Math
|
Chris@1296
|
77
|
Chris@1296
|
78 def logger
|
Chris@1296
|
79 Rails.logger
|
Chris@1296
|
80 end
|
Chris@1296
|
81
|
Chris@1296
|
82 cattr_accessor :k_cell_height_ratio
|
Chris@1296
|
83 @@k_cell_height_ratio = 1.25
|
Chris@1296
|
84
|
Chris@1296
|
85 cattr_accessor :k_blank_image
|
Chris@1296
|
86 @@k_blank_image = ""
|
Chris@1296
|
87
|
Chris@1296
|
88 cattr_accessor :k_small_ratio
|
Chris@1296
|
89 @@k_small_ratio = 2/3.0
|
Chris@1296
|
90
|
Chris@1296
|
91 cattr_accessor :k_path_cache
|
Chris@1296
|
92 @@k_path_cache = Rails.root.join('tmp')
|
Chris@1296
|
93
|
Chris@1296
|
94 cattr_accessor :k_path_url_cache
|
Chris@1296
|
95 @@k_path_url_cache = Rails.root.join('tmp')
|
Chris@1296
|
96
|
Chris@1296
|
97 attr_accessor :barcode
|
Chris@1296
|
98
|
Chris@1296
|
99 attr_accessor :buffer
|
Chris@1296
|
100
|
Chris@1296
|
101 attr_accessor :diffs
|
Chris@1296
|
102
|
Chris@1296
|
103 attr_accessor :color_flag
|
Chris@1296
|
104
|
Chris@1296
|
105 attr_accessor :default_table_columns
|
Chris@1296
|
106
|
Chris@1296
|
107 attr_accessor :max_table_columns
|
Chris@1296
|
108
|
Chris@1296
|
109 attr_accessor :default_font
|
Chris@1296
|
110
|
Chris@1296
|
111 attr_accessor :draw_color
|
Chris@1296
|
112
|
Chris@1296
|
113 attr_accessor :encoding
|
Chris@1296
|
114
|
Chris@1296
|
115 attr_accessor :fill_color
|
Chris@1296
|
116
|
Chris@1296
|
117 attr_accessor :fonts
|
Chris@1296
|
118
|
Chris@1296
|
119 attr_accessor :font_family
|
Chris@1296
|
120
|
Chris@1296
|
121 attr_accessor :font_files
|
Chris@1296
|
122
|
Chris@1296
|
123 cattr_accessor :font_path
|
Chris@1296
|
124
|
Chris@1296
|
125 attr_accessor :font_style
|
Chris@1296
|
126
|
Chris@1296
|
127 attr_accessor :font_size_pt
|
Chris@1296
|
128
|
Chris@1296
|
129 attr_accessor :header_width
|
Chris@1296
|
130
|
Chris@1296
|
131 attr_accessor :header_logo
|
Chris@1296
|
132
|
Chris@1296
|
133 attr_accessor :header_logo_width
|
Chris@1296
|
134
|
Chris@1296
|
135 attr_accessor :header_title
|
Chris@1296
|
136
|
Chris@1296
|
137 attr_accessor :header_string
|
Chris@1296
|
138
|
Chris@1296
|
139 attr_accessor :images
|
Chris@1296
|
140
|
Chris@1296
|
141 attr_accessor :img_scale
|
Chris@1296
|
142
|
Chris@1296
|
143 attr_accessor :in_footer
|
Chris@1296
|
144
|
Chris@1296
|
145 attr_accessor :is_unicode
|
Chris@1296
|
146
|
Chris@1296
|
147 attr_accessor :lasth
|
Chris@1296
|
148
|
Chris@1296
|
149 attr_accessor :links
|
Chris@1296
|
150
|
Chris@1296
|
151 attr_accessor :list_ordered
|
Chris@1296
|
152
|
Chris@1296
|
153 attr_accessor :list_count
|
Chris@1296
|
154
|
Chris@1296
|
155 attr_accessor :li_spacer
|
Chris@1296
|
156
|
Chris@1296
|
157 attr_accessor :n
|
Chris@1296
|
158
|
Chris@1296
|
159 attr_accessor :offsets
|
Chris@1296
|
160
|
Chris@1296
|
161 attr_accessor :orientation_changes
|
Chris@1296
|
162
|
Chris@1296
|
163 attr_accessor :page
|
Chris@1296
|
164
|
Chris@1296
|
165 attr_accessor :page_links
|
Chris@1296
|
166
|
Chris@1296
|
167 attr_accessor :pages
|
Chris@1296
|
168
|
Chris@1296
|
169 attr_accessor :pdf_version
|
Chris@1296
|
170
|
Chris@1296
|
171 attr_accessor :prevfill_color
|
Chris@1296
|
172
|
Chris@1296
|
173 attr_accessor :prevtext_color
|
Chris@1296
|
174
|
Chris@1296
|
175 attr_accessor :print_header
|
Chris@1296
|
176
|
Chris@1296
|
177 attr_accessor :print_footer
|
Chris@1296
|
178
|
Chris@1296
|
179 attr_accessor :state
|
Chris@1296
|
180
|
Chris@1296
|
181 attr_accessor :tableborder
|
Chris@1296
|
182
|
Chris@1296
|
183 attr_accessor :tdbegin
|
Chris@1296
|
184
|
Chris@1296
|
185 attr_accessor :tdwidth
|
Chris@1296
|
186
|
Chris@1296
|
187 attr_accessor :tdheight
|
Chris@1296
|
188
|
Chris@1296
|
189 attr_accessor :tdalign
|
Chris@1296
|
190
|
Chris@1296
|
191 attr_accessor :tdfill
|
Chris@1296
|
192
|
Chris@1296
|
193 attr_accessor :tempfontsize
|
Chris@1296
|
194
|
Chris@1296
|
195 attr_accessor :text_color
|
Chris@1296
|
196
|
Chris@1296
|
197 attr_accessor :underline
|
Chris@1296
|
198
|
Chris@1296
|
199 attr_accessor :ws
|
Chris@1296
|
200
|
Chris@1296
|
201 #
|
Chris@1296
|
202 # This is the class constructor.
|
Chris@1296
|
203 # It allows to set up the page format, the orientation and
|
Chris@1296
|
204 # the measure unit used in all the methods (except for the font sizes).
|
Chris@1296
|
205 # @since 1.0
|
Chris@1296
|
206 # @param string :orientation page orientation. Possible values are (case insensitive):<ul><li>P or Portrait (default)</li><li>L or Landscape</li></ul>
|
Chris@1296
|
207 # @param string :unit User measure unit. Possible values are:<ul><li>pt: point</li><li>mm: millimeter (default)</li><li>cm: centimeter</li><li>in: inch</li></ul><br />A point equals 1/72 of inch, that is to say about 0.35 mm (an inch being 2.54 cm). This is a very common unit in typography; font sizes are expressed in that unit.
|
Chris@1296
|
208 # @param mixed :format The format used for pages. It can be either one of the following values (case insensitive) or a custom format in the form of a two-element array containing the width and the height (expressed in the unit given by unit).<ul><li>4A0</li><li>2A0</li><li>A0</li><li>A1</li><li>A2</li><li>A3</li><li>A4 (default)</li><li>A5</li><li>A6</li><li>A7</li><li>A8</li><li>A9</li><li>A10</li><li>B0</li><li>B1</li><li>B2</li><li>B3</li><li>B4</li><li>B5</li><li>B6</li><li>B7</li><li>B8</li><li>B9</li><li>B10</li><li>C0</li><li>C1</li><li>C2</li><li>C3</li><li>C4</li><li>C5</li><li>C6</li><li>C7</li><li>C8</li><li>C9</li><li>C10</li><li>RA0</li><li>RA1</li><li>RA2</li><li>RA3</li><li>RA4</li><li>SRA0</li><li>SRA1</li><li>SRA2</li><li>SRA3</li><li>SRA4</li><li>LETTER</li><li>LEGAL</li><li>EXECUTIVE</li><li>FOLIO</li></ul>
|
Chris@1296
|
209 # @param boolean :unicode TRUE means that the input text is unicode (default = true)
|
Chris@1296
|
210 # @param String :encoding charset encoding; default is UTF-8
|
Chris@1296
|
211 #
|
Chris@1296
|
212 def initialize(orientation = 'P', unit = 'mm', format = 'A4', unicode = true, encoding = "UTF-8")
|
Chris@1296
|
213
|
Chris@1296
|
214 # Set internal character encoding to ASCII#
|
Chris@1296
|
215 #FIXME 2007-05-25 (EJM) Level=0 -
|
Chris@1296
|
216 # if (respond_to?("mb_internal_encoding") and mb_internal_encoding())
|
Chris@1296
|
217 # @internal_encoding = mb_internal_encoding();
|
Chris@1296
|
218 # mb_internal_encoding("ASCII");
|
Chris@1296
|
219 # }
|
Chris@1296
|
220
|
Chris@1296
|
221 #Some checks
|
Chris@1296
|
222 dochecks();
|
Chris@1296
|
223
|
Chris@1296
|
224 #Initialization of properties
|
Chris@1296
|
225 @barcode ||= false
|
Chris@1296
|
226 @buffer ||= ''
|
Chris@1296
|
227 @diffs ||= []
|
Chris@1296
|
228 @color_flag ||= false
|
Chris@1296
|
229 @default_table_columns ||= 4
|
Chris@1296
|
230 @table_columns ||= 0
|
Chris@1296
|
231 @max_table_columns ||= []
|
Chris@1296
|
232 @tr_id ||= 0
|
Chris@1296
|
233 @max_td_page ||= []
|
Chris@1296
|
234 @max_td_y ||= []
|
Chris@1296
|
235 @t_columns ||= 0
|
Chris@1296
|
236 @default_font ||= "FreeSans" if unicode
|
Chris@1296
|
237 @default_font ||= "Helvetica"
|
Chris@1296
|
238 @draw_color ||= '0 G'
|
Chris@1296
|
239 @encoding ||= "UTF-8"
|
Chris@1296
|
240 @fill_color ||= '0 g'
|
Chris@1296
|
241 @fonts ||= {}
|
Chris@1296
|
242 @font_family ||= ''
|
Chris@1296
|
243 @font_files ||= {}
|
Chris@1296
|
244 @font_style ||= ''
|
Chris@1296
|
245 @font_size ||= 12
|
Chris@1296
|
246 @font_size_pt ||= 12
|
Chris@1296
|
247 @header_width ||= 0
|
Chris@1296
|
248 @header_logo ||= ""
|
Chris@1296
|
249 @header_logo_width ||= 30
|
Chris@1296
|
250 @header_title ||= ""
|
Chris@1296
|
251 @header_string ||= ""
|
Chris@1296
|
252 @images ||= {}
|
Chris@1296
|
253 @img_scale ||= 1
|
Chris@1296
|
254 @in_footer ||= false
|
Chris@1296
|
255 @is_unicode = unicode
|
Chris@1296
|
256 @lasth ||= 0
|
Chris@1296
|
257 @links ||= []
|
Chris@1296
|
258 @list_ordered ||= []
|
Chris@1296
|
259 @list_count ||= []
|
Chris@1296
|
260 @li_spacer ||= ""
|
Chris@1296
|
261 @li_count ||= 0
|
Chris@1296
|
262 @spacer ||= ""
|
Chris@1296
|
263 @quote_count ||= 0
|
Chris@1296
|
264 @prevquote_count ||= 0
|
Chris@1296
|
265 @quote_top ||= []
|
Chris@1296
|
266 @quote_page ||= []
|
Chris@1296
|
267 @n ||= 2
|
Chris@1296
|
268 @offsets ||= []
|
Chris@1296
|
269 @orientation_changes ||= []
|
Chris@1296
|
270 @page ||= 0
|
Chris@1296
|
271 @page_links ||= {}
|
Chris@1296
|
272 @pages ||= []
|
Chris@1296
|
273 @pdf_version ||= "1.3"
|
Chris@1296
|
274 @prevfill_color ||= [255,255,255]
|
Chris@1296
|
275 @prevtext_color ||= [0,0,0]
|
Chris@1296
|
276 @print_header ||= false
|
Chris@1296
|
277 @print_footer ||= false
|
Chris@1296
|
278 @state ||= 0
|
Chris@1296
|
279 @tableborder ||= 0
|
Chris@1296
|
280 @tdbegin ||= false
|
Chris@1296
|
281 @tdtext ||= ''
|
Chris@1296
|
282 @tdwidth ||= 0
|
Chris@1296
|
283 @tdheight ||= 0
|
Chris@1296
|
284 @tdalign ||= "L"
|
Chris@1296
|
285 @tdfill ||= 0
|
Chris@1296
|
286 @tempfontsize ||= 10
|
Chris@1296
|
287 @text_color ||= '0 g'
|
Chris@1296
|
288 @underline ||= false
|
Chris@1296
|
289 @deleted ||= false
|
Chris@1296
|
290 @ws ||= 0
|
Chris@1296
|
291
|
Chris@1296
|
292 #Standard Unicode fonts
|
Chris@1296
|
293 @core_fonts = {
|
Chris@1296
|
294 'courier'=>'Courier',
|
Chris@1296
|
295 'courierB'=>'Courier-Bold',
|
Chris@1296
|
296 'courierI'=>'Courier-Oblique',
|
Chris@1296
|
297 'courierBI'=>'Courier-BoldOblique',
|
Chris@1296
|
298 'helvetica'=>'Helvetica',
|
Chris@1296
|
299 'helveticaB'=>'Helvetica-Bold',
|
Chris@1296
|
300 'helveticaI'=>'Helvetica-Oblique',
|
Chris@1296
|
301 'helveticaBI'=>'Helvetica-BoldOblique',
|
Chris@1296
|
302 'times'=>'Times-Roman',
|
Chris@1296
|
303 'timesB'=>'Times-Bold',
|
Chris@1296
|
304 'timesI'=>'Times-Italic',
|
Chris@1296
|
305 'timesBI'=>'Times-BoldItalic',
|
Chris@1296
|
306 'symbol'=>'Symbol',
|
Chris@1296
|
307 'zapfdingbats'=>'ZapfDingbats'}
|
Chris@1296
|
308
|
Chris@1296
|
309 #Scale factor
|
Chris@1296
|
310 case unit.downcase
|
Chris@1296
|
311 when 'pt' ; @k=1
|
Chris@1296
|
312 when 'mm' ; @k=72/25.4
|
Chris@1296
|
313 when 'cm' ; @k=72/2.54
|
Chris@1296
|
314 when 'in' ; @k=72
|
Chris@1296
|
315 else Error("Incorrect unit: #{unit}")
|
Chris@1296
|
316 end
|
Chris@1296
|
317
|
Chris@1296
|
318 #Page format
|
Chris@1296
|
319 if format.is_a?(String)
|
Chris@1296
|
320 # Page formats (45 standard ISO paper formats and 4 american common formats).
|
Chris@1296
|
321 # Paper cordinates are calculated in this way: (inches# 72) where (1 inch = 2.54 cm)
|
Chris@1296
|
322 case (format.upcase)
|
Chris@1296
|
323 when '4A0' ; format = [4767.87,6740.79]
|
Chris@1296
|
324 when '2A0' ; format = [3370.39,4767.87]
|
Chris@1296
|
325 when 'A0' ; format = [2383.94,3370.39]
|
Chris@1296
|
326 when 'A1' ; format = [1683.78,2383.94]
|
Chris@1296
|
327 when 'A2' ; format = [1190.55,1683.78]
|
Chris@1296
|
328 when 'A3' ; format = [841.89,1190.55]
|
Chris@1296
|
329 when 'A4' ; format = [595.28,841.89] # ; default
|
Chris@1296
|
330 when 'A5' ; format = [419.53,595.28]
|
Chris@1296
|
331 when 'A6' ; format = [297.64,419.53]
|
Chris@1296
|
332 when 'A7' ; format = [209.76,297.64]
|
Chris@1296
|
333 when 'A8' ; format = [147.40,209.76]
|
Chris@1296
|
334 when 'A9' ; format = [104.88,147.40]
|
Chris@1296
|
335 when 'A10' ; format = [73.70,104.88]
|
Chris@1296
|
336 when 'B0' ; format = [2834.65,4008.19]
|
Chris@1296
|
337 when 'B1' ; format = [2004.09,2834.65]
|
Chris@1296
|
338 when 'B2' ; format = [1417.32,2004.09]
|
Chris@1296
|
339 when 'B3' ; format = [1000.63,1417.32]
|
Chris@1296
|
340 when 'B4' ; format = [708.66,1000.63]
|
Chris@1296
|
341 when 'B5' ; format = [498.90,708.66]
|
Chris@1296
|
342 when 'B6' ; format = [354.33,498.90]
|
Chris@1296
|
343 when 'B7' ; format = [249.45,354.33]
|
Chris@1296
|
344 when 'B8' ; format = [175.75,249.45]
|
Chris@1296
|
345 when 'B9' ; format = [124.72,175.75]
|
Chris@1296
|
346 when 'B10' ; format = [87.87,124.72]
|
Chris@1296
|
347 when 'C0' ; format = [2599.37,3676.54]
|
Chris@1296
|
348 when 'C1' ; format = [1836.85,2599.37]
|
Chris@1296
|
349 when 'C2' ; format = [1298.27,1836.85]
|
Chris@1296
|
350 when 'C3' ; format = [918.43,1298.27]
|
Chris@1296
|
351 when 'C4' ; format = [649.13,918.43]
|
Chris@1296
|
352 when 'C5' ; format = [459.21,649.13]
|
Chris@1296
|
353 when 'C6' ; format = [323.15,459.21]
|
Chris@1296
|
354 when 'C7' ; format = [229.61,323.15]
|
Chris@1296
|
355 when 'C8' ; format = [161.57,229.61]
|
Chris@1296
|
356 when 'C9' ; format = [113.39,161.57]
|
Chris@1296
|
357 when 'C10' ; format = [79.37,113.39]
|
Chris@1296
|
358 when 'RA0' ; format = [2437.80,3458.27]
|
Chris@1296
|
359 when 'RA1' ; format = [1729.13,2437.80]
|
Chris@1296
|
360 when 'RA2' ; format = [1218.90,1729.13]
|
Chris@1296
|
361 when 'RA3' ; format = [864.57,1218.90]
|
Chris@1296
|
362 when 'RA4' ; format = [609.45,864.57]
|
Chris@1296
|
363 when 'SRA0' ; format = [2551.18,3628.35]
|
Chris@1296
|
364 when 'SRA1' ; format = [1814.17,2551.18]
|
Chris@1296
|
365 when 'SRA2' ; format = [1275.59,1814.17]
|
Chris@1296
|
366 when 'SRA3' ; format = [907.09,1275.59]
|
Chris@1296
|
367 when 'SRA4' ; format = [637.80,907.09]
|
Chris@1296
|
368 when 'LETTER' ; format = [612.00,792.00]
|
Chris@1296
|
369 when 'LEGAL' ; format = [612.00,1008.00]
|
Chris@1296
|
370 when 'EXECUTIVE' ; format = [521.86,756.00]
|
Chris@1296
|
371 when 'FOLIO' ; format = [612.00,936.00]
|
Chris@1296
|
372 #else then Error("Unknown page format: #{format}"
|
Chris@1296
|
373 end
|
Chris@1296
|
374 @fw_pt = format[0]
|
Chris@1296
|
375 @fh_pt = format[1]
|
Chris@1296
|
376 else
|
Chris@1296
|
377 @fw_pt = format[0]*@k
|
Chris@1296
|
378 @fh_pt = format[1]*@k
|
Chris@1296
|
379 end
|
Chris@1296
|
380
|
Chris@1296
|
381 @fw = @fw_pt/@k
|
Chris@1296
|
382 @fh = @fh_pt/@k
|
Chris@1296
|
383
|
Chris@1296
|
384 #Page orientation
|
Chris@1296
|
385 orientation = orientation.downcase
|
Chris@1296
|
386 if orientation == 'p' or orientation == 'portrait'
|
Chris@1296
|
387 @def_orientation = 'P'
|
Chris@1296
|
388 @w_pt = @fw_pt
|
Chris@1296
|
389 @h_pt = @fh_pt
|
Chris@1296
|
390 elsif orientation == 'l' or orientation == 'landscape'
|
Chris@1296
|
391 @def_orientation = 'L'
|
Chris@1296
|
392 @w_pt = @fh_pt
|
Chris@1296
|
393 @h_pt = @fw_pt
|
Chris@1296
|
394 else
|
Chris@1296
|
395 Error("Incorrect orientation: #{orientation}")
|
Chris@1296
|
396 end
|
Chris@1296
|
397
|
Chris@1296
|
398 @fw = @w_pt/@k
|
Chris@1296
|
399 @fh = @h_pt/@k
|
Chris@1296
|
400
|
Chris@1296
|
401 @cur_orientation = @def_orientation
|
Chris@1296
|
402 @w = @w_pt/@k
|
Chris@1296
|
403 @h = @h_pt/@k
|
Chris@1296
|
404 #Page margins (1 cm)
|
Chris@1296
|
405 margin = 28.35/@k
|
Chris@1296
|
406 SetMargins(margin, margin)
|
Chris@1296
|
407 #Interior cell margin (1 mm)
|
Chris@1296
|
408 @c_margin = margin / 10
|
Chris@1296
|
409 #Line width (0.2 mm)
|
Chris@1296
|
410 @line_width = 0.567 / @k
|
Chris@1296
|
411 #Automatic page break
|
Chris@1296
|
412 SetAutoPageBreak(true, 2 * margin)
|
Chris@1296
|
413 #Full width display mode
|
Chris@1296
|
414 SetDisplayMode('fullwidth')
|
Chris@1296
|
415 #Compression
|
Chris@1296
|
416 SetCompression(true)
|
Chris@1296
|
417 #Set default PDF version number
|
Chris@1296
|
418 @pdf_version = "1.3"
|
Chris@1296
|
419
|
Chris@1296
|
420 @encoding = encoding
|
Chris@1296
|
421 @b = 0
|
Chris@1296
|
422 @i = 0
|
Chris@1296
|
423 @u = 0
|
Chris@1296
|
424 @href = ''
|
Chris@1296
|
425 @fontlist = ["arial", "times", "courier", "helvetica", "symbol"]
|
Chris@1296
|
426 @issetfont = false
|
Chris@1296
|
427 @issetcolor = false
|
Chris@1296
|
428
|
Chris@1296
|
429 SetFillColor(200, 200, 200, true)
|
Chris@1296
|
430 SetTextColor(0, 0, 0, true)
|
Chris@1296
|
431 end
|
Chris@1296
|
432
|
Chris@1296
|
433 #
|
Chris@1296
|
434 # Set the image scale.
|
Chris@1296
|
435 # @param float :scale image scale.
|
Chris@1296
|
436 # @author Nicola Asuni
|
Chris@1296
|
437 # @since 1.5.2
|
Chris@1296
|
438 #
|
Chris@1296
|
439 def SetImageScale(scale)
|
Chris@1296
|
440 @img_scale = scale;
|
Chris@1296
|
441 end
|
Chris@1296
|
442 alias_method :set_image_scale, :SetImageScale
|
Chris@1296
|
443
|
Chris@1296
|
444 #
|
Chris@1296
|
445 # Returns the image scale.
|
Chris@1296
|
446 # @return float image scale.
|
Chris@1296
|
447 # @author Nicola Asuni
|
Chris@1296
|
448 # @since 1.5.2
|
Chris@1296
|
449 #
|
Chris@1296
|
450 def GetImageScale()
|
Chris@1296
|
451 return @img_scale;
|
Chris@1296
|
452 end
|
Chris@1296
|
453 alias_method :get_image_scale, :GetImageScale
|
Chris@1296
|
454
|
Chris@1296
|
455 #
|
Chris@1296
|
456 # Returns the page width in units.
|
Chris@1296
|
457 # @return int page width.
|
Chris@1296
|
458 # @author Nicola Asuni
|
Chris@1296
|
459 # @since 1.5.2
|
Chris@1296
|
460 #
|
Chris@1296
|
461 def GetPageWidth()
|
Chris@1296
|
462 return @w;
|
Chris@1296
|
463 end
|
Chris@1296
|
464 alias_method :get_page_width, :GetPageWidth
|
Chris@1296
|
465
|
Chris@1296
|
466 #
|
Chris@1296
|
467 # Returns the page height in units.
|
Chris@1296
|
468 # @return int page height.
|
Chris@1296
|
469 # @author Nicola Asuni
|
Chris@1296
|
470 # @since 1.5.2
|
Chris@1296
|
471 #
|
Chris@1296
|
472 def GetPageHeight()
|
Chris@1296
|
473 return @h;
|
Chris@1296
|
474 end
|
Chris@1296
|
475 alias_method :get_page_height, :GetPageHeight
|
Chris@1296
|
476
|
Chris@1296
|
477 #
|
Chris@1296
|
478 # Returns the page break margin.
|
Chris@1296
|
479 # @return int page break margin.
|
Chris@1296
|
480 # @author Nicola Asuni
|
Chris@1296
|
481 # @since 1.5.2
|
Chris@1296
|
482 #
|
Chris@1296
|
483 def GetBreakMargin()
|
Chris@1296
|
484 return @b_margin;
|
Chris@1296
|
485 end
|
Chris@1296
|
486 alias_method :get_break_margin, :GetBreakMargin
|
Chris@1296
|
487
|
Chris@1296
|
488 #
|
Chris@1296
|
489 # Returns the scale factor (number of points in user unit).
|
Chris@1296
|
490 # @return int scale factor.
|
Chris@1296
|
491 # @author Nicola Asuni
|
Chris@1296
|
492 # @since 1.5.2
|
Chris@1296
|
493 #
|
Chris@1296
|
494 def GetScaleFactor()
|
Chris@1296
|
495 return @k;
|
Chris@1296
|
496 end
|
Chris@1296
|
497 alias_method :get_scale_factor, :GetScaleFactor
|
Chris@1296
|
498
|
Chris@1296
|
499 #
|
Chris@1296
|
500 # Defines the left, top and right margins. By default, they equal 1 cm. Call this method to change them.
|
Chris@1296
|
501 # @param float :left Left margin.
|
Chris@1296
|
502 # @param float :top Top margin.
|
Chris@1296
|
503 # @param float :right Right margin. Default value is the left one.
|
Chris@1296
|
504 # @since 1.0
|
Chris@1296
|
505 # @see SetLeftMargin(), SetTopMargin(), SetRightMargin(), SetAutoPageBreak()
|
Chris@1296
|
506 #
|
Chris@1296
|
507 def SetMargins(left, top, right=-1)
|
Chris@1296
|
508 #Set left, top and right margins
|
Chris@1296
|
509 @l_margin = left
|
Chris@1296
|
510 @t_margin = top
|
Chris@1296
|
511 if (right == -1)
|
Chris@1296
|
512 right = left
|
Chris@1296
|
513 end
|
Chris@1296
|
514 @r_margin = right
|
Chris@1296
|
515 end
|
Chris@1296
|
516 alias_method :set_margins, :SetMargins
|
Chris@1296
|
517
|
Chris@1296
|
518 #
|
Chris@1296
|
519 # Defines the left margin. The method can be called before creating the first page. If the current abscissa gets out of page, it is brought back to the margin.
|
Chris@1296
|
520 # @param float :margin The margin.
|
Chris@1296
|
521 # @since 1.4
|
Chris@1296
|
522 # @see SetTopMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()
|
Chris@1296
|
523 #
|
Chris@1296
|
524 def SetLeftMargin(margin)
|
Chris@1296
|
525 #Set left margin
|
Chris@1296
|
526 @l_margin = margin
|
Chris@1296
|
527 if ((@page>0) and (@x < margin))
|
Chris@1296
|
528 @x = margin
|
Chris@1296
|
529 end
|
Chris@1296
|
530 end
|
Chris@1296
|
531 alias_method :set_left_margin, :SetLeftMargin
|
Chris@1296
|
532
|
Chris@1296
|
533 #
|
Chris@1296
|
534 # Defines the top margin. The method can be called before creating the first page.
|
Chris@1296
|
535 # @param float :margin The margin.
|
Chris@1296
|
536 # @since 1.5
|
Chris@1296
|
537 # @see SetLeftMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()
|
Chris@1296
|
538 #
|
Chris@1296
|
539 def SetTopMargin(margin)
|
Chris@1296
|
540 #Set top margin
|
Chris@1296
|
541 @t_margin = margin
|
Chris@1296
|
542 end
|
Chris@1296
|
543 alias_method :set_top_margin, :SetTopMargin
|
Chris@1296
|
544
|
Chris@1296
|
545 #
|
Chris@1296
|
546 # Defines the right margin. The method can be called before creating the first page.
|
Chris@1296
|
547 # @param float :margin The margin.
|
Chris@1296
|
548 # @since 1.5
|
Chris@1296
|
549 # @see SetLeftMargin(), SetTopMargin(), SetAutoPageBreak(), SetMargins()
|
Chris@1296
|
550 #
|
Chris@1296
|
551 def SetRightMargin(margin)
|
Chris@1296
|
552 #Set right margin
|
Chris@1296
|
553 @r_margin = margin
|
Chris@1296
|
554 end
|
Chris@1296
|
555 alias_method :set_right_margin, :SetRightMargin
|
Chris@1296
|
556
|
Chris@1296
|
557 #
|
Chris@1296
|
558 # Enables or disables the automatic page breaking mode. When enabling, the second parameter is the distance from the bottom of the page that defines the triggering limit. By default, the mode is on and the margin is 2 cm.
|
Chris@1296
|
559 # @param boolean :auto Boolean indicating if mode should be on or off.
|
Chris@1296
|
560 # @param float :margin Distance from the bottom of the page.
|
Chris@1296
|
561 # @since 1.0
|
Chris@1296
|
562 # @see Cell(), MultiCell(), AcceptPageBreak()
|
Chris@1296
|
563 #
|
Chris@1296
|
564 def SetAutoPageBreak(auto, margin=0)
|
Chris@1296
|
565 #Set auto page break mode and triggering margin
|
Chris@1296
|
566 @auto_page_break = auto
|
Chris@1296
|
567 @b_margin = margin
|
Chris@1296
|
568 @page_break_trigger = @h - margin
|
Chris@1296
|
569 end
|
Chris@1296
|
570 alias_method :set_auto_page_break, :SetAutoPageBreak
|
Chris@1296
|
571
|
Chris@1296
|
572 #
|
Chris@1296
|
573 # Defines the way the document is to be displayed by the viewer. The zoom level can be set: pages can be displayed entirely on screen, occupy the full width of the window, use real size, be scaled by a specific zooming factor or use viewer default (configured in the Preferences menu of Acrobat). The page layout can be specified too: single at once, continuous display, two columns or viewer default. By default, documents use the full width mode with continuous display.
|
Chris@1296
|
574 # @param mixed :zoom The zoom to use. It can be one of the following string values or a number indicating the zooming factor to use. <ul><li>fullpage: displays the entire page on screen </li><li>fullwidth: uses maximum width of window</li><li>real: uses real size (equivalent to 100% zoom)</li><li>default: uses viewer default mode</li></ul>
|
Chris@1296
|
575 # @param string :layout The page layout. Possible values are:<ul><li>single: displays one page at once</li><li>continuous: displays pages continuously (default)</li><li>two: displays two pages on two columns</li><li>default: uses viewer default mode</li></ul>
|
Chris@1296
|
576 # @since 1.2
|
Chris@1296
|
577 #
|
Chris@1296
|
578 def SetDisplayMode(zoom, layout = 'continuous')
|
Chris@1296
|
579 #Set display mode in viewer
|
Chris@1296
|
580 if (zoom == 'fullpage' or zoom == 'fullwidth' or zoom == 'real' or zoom == 'default' or !zoom.is_a?(String))
|
Chris@1296
|
581 @zoom_mode = zoom
|
Chris@1296
|
582 else
|
Chris@1296
|
583 Error("Incorrect zoom display mode: #{zoom}")
|
Chris@1296
|
584 end
|
Chris@1296
|
585 if (layout == 'single' or layout == 'continuous' or layout == 'two' or layout == 'default')
|
Chris@1296
|
586 @layout_mode = layout
|
Chris@1296
|
587 else
|
Chris@1296
|
588 Error("Incorrect layout display mode: #{layout}")
|
Chris@1296
|
589 end
|
Chris@1296
|
590 end
|
Chris@1296
|
591 alias_method :set_display_mode, :SetDisplayMode
|
Chris@1296
|
592
|
Chris@1296
|
593 #
|
Chris@1296
|
594 # Activates or deactivates page compression. When activated, the internal representation of each page is compressed, which leads to a compression ratio of about 2 for the resulting document. Compression is on by default.
|
Chris@1296
|
595 # Note: the Zlib extension is required for this feature. If not present, compression will be turned off.
|
Chris@1296
|
596 # @param boolean :compress Boolean indicating if compression must be enabled.
|
Chris@1296
|
597 # @since 1.4
|
Chris@1296
|
598 #
|
Chris@1296
|
599 def SetCompression(compress)
|
Chris@1296
|
600 #Set page compression
|
Chris@1296
|
601 if (respond_to?('gzcompress'))
|
Chris@1296
|
602 @compress = compress
|
Chris@1296
|
603 else
|
Chris@1296
|
604 @compress = false
|
Chris@1296
|
605 end
|
Chris@1296
|
606 end
|
Chris@1296
|
607 alias_method :set_compression, :SetCompression
|
Chris@1296
|
608
|
Chris@1296
|
609 #
|
Chris@1296
|
610 # Defines the title of the document.
|
Chris@1296
|
611 # @param string :title The title.
|
Chris@1296
|
612 # @since 1.2
|
Chris@1296
|
613 # @see SetAuthor(), SetCreator(), SetKeywords(), SetSubject()
|
Chris@1296
|
614 #
|
Chris@1296
|
615 def SetTitle(title)
|
Chris@1296
|
616 #Title of document
|
Chris@1296
|
617 @title = title
|
Chris@1296
|
618 end
|
Chris@1296
|
619 alias_method :set_title, :SetTitle
|
Chris@1296
|
620
|
Chris@1296
|
621 #
|
Chris@1296
|
622 # Defines the subject of the document.
|
Chris@1296
|
623 # @param string :subject The subject.
|
Chris@1296
|
624 # @since 1.2
|
Chris@1296
|
625 # @see SetAuthor(), SetCreator(), SetKeywords(), SetTitle()
|
Chris@1296
|
626 #
|
Chris@1296
|
627 def SetSubject(subject)
|
Chris@1296
|
628 #Subject of document
|
Chris@1296
|
629 @subject = subject
|
Chris@1296
|
630 end
|
Chris@1296
|
631 alias_method :set_subject, :SetSubject
|
Chris@1296
|
632
|
Chris@1296
|
633 #
|
Chris@1296
|
634 # Defines the author of the document.
|
Chris@1296
|
635 # @param string :author The name of the author.
|
Chris@1296
|
636 # @since 1.2
|
Chris@1296
|
637 # @see SetCreator(), SetKeywords(), SetSubject(), SetTitle()
|
Chris@1296
|
638 #
|
Chris@1296
|
639 def SetAuthor(author)
|
Chris@1296
|
640 #Author of document
|
Chris@1296
|
641 @author = author
|
Chris@1296
|
642 end
|
Chris@1296
|
643 alias_method :set_author, :SetAuthor
|
Chris@1296
|
644
|
Chris@1296
|
645 #
|
Chris@1296
|
646 # Associates keywords with the document, generally in the form 'keyword1 keyword2 ...'.
|
Chris@1296
|
647 # @param string :keywords The list of keywords.
|
Chris@1296
|
648 # @since 1.2
|
Chris@1296
|
649 # @see SetAuthor(), SetCreator(), SetSubject(), SetTitle()
|
Chris@1296
|
650 #
|
Chris@1296
|
651 def SetKeywords(keywords)
|
Chris@1296
|
652 #Keywords of document
|
Chris@1296
|
653 @keywords = keywords
|
Chris@1296
|
654 end
|
Chris@1296
|
655 alias_method :set_keywords, :SetKeywords
|
Chris@1296
|
656
|
Chris@1296
|
657 #
|
Chris@1296
|
658 # Defines the creator of the document. This is typically the name of the application that generates the PDF.
|
Chris@1296
|
659 # @param string :creator The name of the creator.
|
Chris@1296
|
660 # @since 1.2
|
Chris@1296
|
661 # @see SetAuthor(), SetKeywords(), SetSubject(), SetTitle()
|
Chris@1296
|
662 #
|
Chris@1296
|
663 def SetCreator(creator)
|
Chris@1296
|
664 #Creator of document
|
Chris@1296
|
665 @creator = creator
|
Chris@1296
|
666 end
|
Chris@1296
|
667 alias_method :set_creator, :SetCreator
|
Chris@1296
|
668
|
Chris@1296
|
669 #
|
Chris@1296
|
670 # Defines an alias for the total number of pages. It will be substituted as the document is closed.<br />
|
Chris@1296
|
671 # <b>Example:</b><br />
|
Chris@1296
|
672 # <pre>
|
Chris@1296
|
673 # class PDF extends TCPDF {
|
Chris@1296
|
674 # def Footer()
|
Chris@1296
|
675 # #Go to 1.5 cm from bottom
|
Chris@1296
|
676 # SetY(-15);
|
Chris@1296
|
677 # #Select Arial italic 8
|
Chris@1296
|
678 # SetFont('Arial','I',8);
|
Chris@1296
|
679 # #Print current and total page numbers
|
Chris@1296
|
680 # Cell(0,10,'Page '.PageNo().'/{nb}',0,0,'C');
|
Chris@1296
|
681 # end
|
Chris@1296
|
682 # }
|
Chris@1296
|
683 # :pdf=new PDF();
|
Chris@1296
|
684 # :pdf->alias_nb_pages();
|
Chris@1296
|
685 # </pre>
|
Chris@1296
|
686 # @param string :alias The alias. Default valuenb}.
|
Chris@1296
|
687 # @since 1.4
|
Chris@1296
|
688 # @see PageNo(), Footer()
|
Chris@1296
|
689 #
|
Chris@1296
|
690 def AliasNbPages(alias_nb ='{nb}')
|
Chris@1296
|
691 #Define an alias for total number of pages
|
Chris@1296
|
692 @alias_nb_pages = escapetext(alias_nb)
|
Chris@1296
|
693 end
|
Chris@1296
|
694 alias_method :alias_nb_pages, :AliasNbPages
|
Chris@1296
|
695
|
Chris@1296
|
696 #
|
Chris@1296
|
697 # This method is automatically called in case of fatal error; it simply outputs the message and halts the execution. An inherited class may override it to customize the error handling but should always halt the script, or the resulting document would probably be invalid.
|
Chris@1296
|
698 # 2004-06-11 :: Nicola Asuni : changed bold tag with strong
|
Chris@1296
|
699 # @param string :msg The error message
|
Chris@1296
|
700 # @since 1.0
|
Chris@1296
|
701 #
|
Chris@1296
|
702 def Error(msg)
|
Chris@1296
|
703 #Fatal error
|
Chris@1296
|
704 raise ("TCPDF error: #{msg}")
|
Chris@1296
|
705 end
|
Chris@1296
|
706 alias_method :error, :Error
|
Chris@1296
|
707
|
Chris@1296
|
708 #
|
Chris@1296
|
709 # This method begins the generation of the PDF document. It is not necessary to call it explicitly because AddPage() does it automatically.
|
Chris@1296
|
710 # Note: no page is created by this method
|
Chris@1296
|
711 # @since 1.0
|
Chris@1296
|
712 # @see AddPage(), Close()
|
Chris@1296
|
713 #
|
Chris@1296
|
714 def Open()
|
Chris@1296
|
715 #Begin document
|
Chris@1296
|
716 @state = 1
|
Chris@1296
|
717 end
|
Chris@1296
|
718 # alias_method :open, :Open
|
Chris@1296
|
719
|
Chris@1296
|
720 #
|
Chris@1296
|
721 # Terminates the PDF document. It is not necessary to call this method explicitly because Output() does it automatically. If the document contains no page, AddPage() is called to prevent from getting an invalid document.
|
Chris@1296
|
722 # @since 1.0
|
Chris@1296
|
723 # @see Open(), Output()
|
Chris@1296
|
724 #
|
Chris@1296
|
725 def Close()
|
Chris@1296
|
726 #Terminate document
|
Chris@1296
|
727 if (@state==3)
|
Chris@1296
|
728 return;
|
Chris@1296
|
729 end
|
Chris@1296
|
730 if (@page==0)
|
Chris@1296
|
731 AddPage();
|
Chris@1296
|
732 end
|
Chris@1296
|
733 #Page footer
|
Chris@1296
|
734 @in_footer=true;
|
Chris@1296
|
735 Footer();
|
Chris@1296
|
736 @in_footer=false;
|
Chris@1296
|
737 #Close page
|
Chris@1296
|
738 endpage();
|
Chris@1296
|
739 #Close document
|
Chris@1296
|
740 enddoc();
|
Chris@1296
|
741 end
|
Chris@1296
|
742 # alias_method :close, :Close
|
Chris@1296
|
743
|
Chris@1296
|
744 #
|
Chris@1296
|
745 # Adds a new page to the document. If a page is already present, the Footer() method is called first to output the footer. Then the page is added, the current position set to the top-left corner according to the left and top margins, and Header() is called to display the header.
|
Chris@1296
|
746 # The font which was set before calling is automatically restored. There is no need to call SetFont() again if you want to continue with the same font. The same is true for colors and line width.
|
Chris@1296
|
747 # The origin of the coordinate system is at the top-left corner and increasing ordinates go downwards.
|
Chris@1296
|
748 # @param string :orientation Page orientation. Possible values are (case insensitive):<ul><li>P or Portrait</li><li>L or Landscape</li></ul> The default value is the one passed to the constructor.
|
Chris@1296
|
749 # @since 1.0
|
Chris@1296
|
750 # @see TCPDF(), Header(), Footer(), SetMargins()
|
Chris@1296
|
751 #
|
Chris@1296
|
752 def AddPage(orientation='')
|
Chris@1296
|
753 #Start a new page
|
Chris@1296
|
754 if (@state==0)
|
Chris@1296
|
755 Open();
|
Chris@1296
|
756 end
|
Chris@1296
|
757 family=@font_family;
|
Chris@1296
|
758 style=@font_style + (@underline ? 'U' : '') + (@deleted ? 'D' : '');
|
Chris@1296
|
759 size=@font_size_pt;
|
Chris@1296
|
760 lw=@line_width;
|
Chris@1296
|
761 dc=@draw_color;
|
Chris@1296
|
762 fc=@fill_color;
|
Chris@1296
|
763 tc=@text_color;
|
Chris@1296
|
764 cf=@color_flag;
|
Chris@1296
|
765 if (@page>0)
|
Chris@1296
|
766 #Page footer
|
Chris@1296
|
767 @in_footer=true;
|
Chris@1296
|
768 Footer();
|
Chris@1296
|
769 @in_footer=false;
|
Chris@1296
|
770 #Close page
|
Chris@1296
|
771 endpage();
|
Chris@1296
|
772 end
|
Chris@1296
|
773 #Start new page
|
Chris@1296
|
774 beginpage(orientation);
|
Chris@1296
|
775 #Set line cap style to square
|
Chris@1296
|
776 out('2 J');
|
Chris@1296
|
777 #Set line width
|
Chris@1296
|
778 @line_width = lw;
|
Chris@1296
|
779 out(sprintf('%.2f w', lw*@k));
|
Chris@1296
|
780 #Set font
|
Chris@1296
|
781 if (family)
|
Chris@1296
|
782 SetFont(family, style, size);
|
Chris@1296
|
783 end
|
Chris@1296
|
784 #Set colors
|
Chris@1296
|
785 @draw_color = dc;
|
Chris@1296
|
786 if (dc!='0 G')
|
Chris@1296
|
787 out(dc);
|
Chris@1296
|
788 end
|
Chris@1296
|
789 @fill_color = fc;
|
Chris@1296
|
790 if (fc!='0 g')
|
Chris@1296
|
791 out(fc);
|
Chris@1296
|
792 end
|
Chris@1296
|
793 @text_color = tc;
|
Chris@1296
|
794 @color_flag = cf;
|
Chris@1296
|
795 #Page header
|
Chris@1296
|
796 Header();
|
Chris@1296
|
797 #Restore line width
|
Chris@1296
|
798 if (@line_width != lw)
|
Chris@1296
|
799 @line_width = lw;
|
Chris@1296
|
800 out(sprintf('%.2f w', lw*@k));
|
Chris@1296
|
801 end
|
Chris@1296
|
802 #Restore font
|
Chris@1296
|
803 if (family)
|
Chris@1296
|
804 SetFont(family, style, size);
|
Chris@1296
|
805 end
|
Chris@1296
|
806 #Restore colors
|
Chris@1296
|
807 if (@draw_color != dc)
|
Chris@1296
|
808 @draw_color = dc;
|
Chris@1296
|
809 out(dc);
|
Chris@1296
|
810 end
|
Chris@1296
|
811 if (@fill_color != fc)
|
Chris@1296
|
812 @fill_color = fc;
|
Chris@1296
|
813 out(fc);
|
Chris@1296
|
814 end
|
Chris@1296
|
815 @text_color = tc;
|
Chris@1296
|
816 @color_flag = cf;
|
Chris@1296
|
817 end
|
Chris@1296
|
818 alias_method :add_page, :AddPage
|
Chris@1296
|
819
|
Chris@1296
|
820 #
|
Chris@1296
|
821 # Rotate object.
|
Chris@1296
|
822 # @param float :angle angle in degrees for counter-clockwise rotation
|
Chris@1296
|
823 # @param int :x abscissa of the rotation center. Default is current x position
|
Chris@1296
|
824 # @param int :y ordinate of the rotation center. Default is current y position
|
Chris@1296
|
825 #
|
Chris@1296
|
826 def Rotate(angle, x="", y="")
|
Chris@1296
|
827
|
Chris@1296
|
828 if (x == '')
|
Chris@1296
|
829 x = @x;
|
Chris@1296
|
830 end
|
Chris@1296
|
831
|
Chris@1296
|
832 if (y == '')
|
Chris@1296
|
833 y = @y;
|
Chris@1296
|
834 end
|
Chris@1296
|
835
|
Chris@1296
|
836 if (@rtl)
|
Chris@1296
|
837 x = @w - x;
|
Chris@1296
|
838 angle = -@angle;
|
Chris@1296
|
839 end
|
Chris@1296
|
840
|
Chris@1296
|
841 y = (@h - y) * @k;
|
Chris@1296
|
842 x *= @k;
|
Chris@1296
|
843
|
Chris@1296
|
844 # calculate elements of transformation matrix
|
Chris@1296
|
845 tm = []
|
Chris@1296
|
846 tm[0] = ::Math::cos(deg2rad(angle));
|
Chris@1296
|
847 tm[1] = ::Math::sin(deg2rad(angle));
|
Chris@1296
|
848 tm[2] = -tm[1];
|
Chris@1296
|
849 tm[3] = tm[0];
|
Chris@1296
|
850 tm[4] = x + tm[1] * y - tm[0] * x;
|
Chris@1296
|
851 tm[5] = y - tm[0] * y - tm[1] * x;
|
Chris@1296
|
852
|
Chris@1296
|
853 # generate the transformation matrix
|
Chris@1296
|
854 Transform(tm);
|
Chris@1296
|
855 end
|
Chris@1296
|
856 alias_method :rotate, :Rotate
|
Chris@1296
|
857
|
Chris@1296
|
858 #
|
Chris@1296
|
859 # Starts a 2D tranformation saving current graphic state.
|
Chris@1296
|
860 # This function must be called before scaling, mirroring, translation, rotation and skewing.
|
Chris@1296
|
861 # Use StartTransform() before, and StopTransform() after the transformations to restore the normal behavior.
|
Chris@1296
|
862 #
|
Chris@1296
|
863 def StartTransform
|
Chris@1296
|
864 out('q');
|
Chris@1296
|
865 end
|
Chris@1296
|
866 alias_method :start_transform, :StartTransform
|
Chris@1296
|
867
|
Chris@1296
|
868 #
|
Chris@1296
|
869 # Stops a 2D tranformation restoring previous graphic state.
|
Chris@1296
|
870 # This function must be called after scaling, mirroring, translation, rotation and skewing.
|
Chris@1296
|
871 # Use StartTransform() before, and StopTransform() after the transformations to restore the normal behavior.
|
Chris@1296
|
872 #
|
Chris@1296
|
873 def StopTransform
|
Chris@1296
|
874 out('Q');
|
Chris@1296
|
875 end
|
Chris@1296
|
876 alias_method :stop_transform, :StopTransform
|
Chris@1296
|
877
|
Chris@1296
|
878 #
|
Chris@1296
|
879 # Apply graphic transformations.
|
Chris@1296
|
880 # @since 2.1.000 (2008-01-07)
|
Chris@1296
|
881 # @see StartTransform(), StopTransform()
|
Chris@1296
|
882 #
|
Chris@1296
|
883 def Transform(tm)
|
Chris@1296
|
884 x = out(sprintf('%.3f %.3f %.3f %.3f %.3f %.3f cm', tm[0], tm[1], tm[2], tm[3], tm[4], tm[5]));
|
Chris@1296
|
885 end
|
Chris@1296
|
886 alias_method :transform, :Transform
|
Chris@1296
|
887
|
Chris@1296
|
888 #
|
Chris@1296
|
889 # Set header data.
|
Chris@1296
|
890 # @param string :ln header image logo
|
Chris@1296
|
891 # @param string :lw header image logo width in mm
|
Chris@1296
|
892 # @param string :ht string to print as title on document header
|
Chris@1296
|
893 # @param string :hs string to print on document header
|
Chris@1296
|
894 #
|
Chris@1296
|
895 def SetHeaderData(ln="", lw=0, ht="", hs="")
|
Chris@1296
|
896 @header_logo = ln || ""
|
Chris@1296
|
897 @header_logo_width = lw || 0
|
Chris@1296
|
898 @header_title = ht || ""
|
Chris@1296
|
899 @header_string = hs || ""
|
Chris@1296
|
900 end
|
Chris@1296
|
901 alias_method :set_header_data, :SetHeaderData
|
Chris@1296
|
902
|
Chris@1296
|
903 #
|
Chris@1296
|
904 # Set header margin.
|
Chris@1296
|
905 # (minimum distance between header and top page margin)
|
Chris@1296
|
906 # @param int :hm distance in millimeters
|
Chris@1296
|
907 #
|
Chris@1296
|
908 def SetHeaderMargin(hm=10)
|
Chris@1296
|
909 @header_margin = hm;
|
Chris@1296
|
910 end
|
Chris@1296
|
911 alias_method :set_header_margin, :SetHeaderMargin
|
Chris@1296
|
912
|
Chris@1296
|
913 #
|
Chris@1296
|
914 # Set footer margin.
|
Chris@1296
|
915 # (minimum distance between footer and bottom page margin)
|
Chris@1296
|
916 # @param int :fm distance in millimeters
|
Chris@1296
|
917 #
|
Chris@1296
|
918 def SetFooterMargin(fm=10)
|
Chris@1296
|
919 @footer_margin = fm;
|
Chris@1296
|
920 end
|
Chris@1296
|
921 alias_method :set_footer_margin, :SetFooterMargin
|
Chris@1296
|
922
|
Chris@1296
|
923 #
|
Chris@1296
|
924 # Set a flag to print page header.
|
Chris@1296
|
925 # @param boolean :val set to true to print the page header (default), false otherwise.
|
Chris@1296
|
926 #
|
Chris@1296
|
927 def SetPrintHeader(val=true)
|
Chris@1296
|
928 @print_header = val;
|
Chris@1296
|
929 end
|
Chris@1296
|
930 alias_method :set_print_header, :SetPrintHeader
|
Chris@1296
|
931
|
Chris@1296
|
932 #
|
Chris@1296
|
933 # Set a flag to print page footer.
|
Chris@1296
|
934 # @param boolean :value set to true to print the page footer (default), false otherwise.
|
Chris@1296
|
935 #
|
Chris@1296
|
936 def SetPrintFooter(val=true)
|
Chris@1296
|
937 @print_footer = val;
|
Chris@1296
|
938 end
|
Chris@1296
|
939 alias_method :set_print_footer, :SetPrintFooter
|
Chris@1296
|
940
|
Chris@1296
|
941 #
|
Chris@1296
|
942 # This method is used to render the page header.
|
Chris@1296
|
943 # It is automatically called by AddPage() and could be overwritten in your own inherited class.
|
Chris@1296
|
944 #
|
Chris@1296
|
945 def Header()
|
Chris@1296
|
946 if (@print_header)
|
Chris@1296
|
947 if (@original_l_margin.nil?)
|
Chris@1296
|
948 @original_l_margin = @l_margin;
|
Chris@1296
|
949 end
|
Chris@1296
|
950 if (@original_r_margin.nil?)
|
Chris@1296
|
951 @original_r_margin = @r_margin;
|
Chris@1296
|
952 end
|
Chris@1296
|
953
|
Chris@1296
|
954 #set current position
|
Chris@1296
|
955 SetXY(@original_l_margin, @header_margin);
|
Chris@1296
|
956
|
Chris@1296
|
957 if ((@header_logo) and (@header_logo != @@k_blank_image))
|
Chris@1296
|
958 Image(@header_logo, @original_l_margin, @header_margin, @header_logo_width);
|
Chris@1296
|
959 else
|
Chris@1296
|
960 @img_rb_y = GetY();
|
Chris@1296
|
961 end
|
Chris@1296
|
962
|
Chris@1296
|
963 cell_height = ((@@k_cell_height_ratio * @header_font[2]) / @k).round(2)
|
Chris@1296
|
964
|
Chris@1296
|
965 header_x = @original_l_margin + (@header_logo_width * 1.05); #set left margin for text data cell
|
Chris@1296
|
966
|
Chris@1296
|
967 # header title
|
Chris@1296
|
968 SetFont(@header_font[0], 'B', @header_font[2] + 1);
|
Chris@1296
|
969 SetX(header_x);
|
Chris@1296
|
970 Cell(@header_width, cell_height, @header_title, 0, 1, 'L');
|
Chris@1296
|
971
|
Chris@1296
|
972 # header string
|
Chris@1296
|
973 SetFont(@header_font[0], @header_font[1], @header_font[2]);
|
Chris@1296
|
974 SetX(header_x);
|
Chris@1296
|
975 MultiCell(@header_width, cell_height, @header_string, 0, 'L', 0);
|
Chris@1296
|
976
|
Chris@1296
|
977 # print an ending header line
|
Chris@1296
|
978 if (@header_width)
|
Chris@1296
|
979 #set style for cell border
|
Chris@1296
|
980 SetLineWidth(0.3);
|
Chris@1296
|
981 SetDrawColor(0, 0, 0);
|
Chris@1296
|
982 SetY(1 + (@img_rb_y > GetY() ? @img_rb_y : GetY()));
|
Chris@1296
|
983 SetX(@original_l_margin);
|
Chris@1296
|
984 Cell(0, 0, '', 'T', 0, 'C');
|
Chris@1296
|
985 end
|
Chris@1296
|
986
|
Chris@1296
|
987 #restore position
|
Chris@1296
|
988 SetXY(@original_l_margin, @t_margin);
|
Chris@1296
|
989 end
|
Chris@1296
|
990 end
|
Chris@1296
|
991 alias_method :header, :Header
|
Chris@1296
|
992
|
Chris@1296
|
993 #
|
Chris@1296
|
994 # This method is used to render the page footer.
|
Chris@1296
|
995 # It is automatically called by AddPage() and could be overwritten in your own inherited class.
|
Chris@1296
|
996 #
|
Chris@1296
|
997 def Footer()
|
Chris@1296
|
998 if (@print_footer)
|
Chris@1296
|
999
|
Chris@1296
|
1000 if (@original_l_margin.nil?)
|
Chris@1296
|
1001 @original_l_margin = @l_margin;
|
Chris@1296
|
1002 end
|
Chris@1296
|
1003 if (@original_r_margin.nil?)
|
Chris@1296
|
1004 @original_r_margin = @r_margin;
|
Chris@1296
|
1005 end
|
Chris@1296
|
1006
|
Chris@1296
|
1007 #set font
|
Chris@1296
|
1008 SetFont(@footer_font[0], @footer_font[1] , @footer_font[2]);
|
Chris@1296
|
1009 #set style for cell border
|
Chris@1296
|
1010 line_width = 0.3;
|
Chris@1296
|
1011 SetLineWidth(line_width);
|
Chris@1296
|
1012 SetDrawColor(0, 0, 0);
|
Chris@1296
|
1013
|
Chris@1296
|
1014 footer_height = ((@@k_cell_height_ratio * @footer_font[2]) / @k).round; #footer height, was , 2)
|
Chris@1296
|
1015 #get footer y position
|
Chris@1296
|
1016 footer_y = @h - @footer_margin - footer_height;
|
Chris@1296
|
1017 #set current position
|
Chris@1296
|
1018 SetXY(@original_l_margin, footer_y);
|
Chris@1296
|
1019
|
Chris@1296
|
1020 #print document barcode
|
Chris@1296
|
1021 if (@barcode)
|
Chris@1296
|
1022 Ln();
|
Chris@1296
|
1023 barcode_width = ((@w - @original_l_margin - @original_r_margin)).round; #max width
|
Chris@1296
|
1024 writeBarcode(@original_l_margin, footer_y + line_width, barcode_width, footer_height - line_width, "C128B", false, false, 2, @barcode);
|
Chris@1296
|
1025 end
|
Chris@1296
|
1026
|
Chris@1296
|
1027 SetXY(@original_l_margin, footer_y);
|
Chris@1296
|
1028
|
Chris@1296
|
1029 #Print page number
|
Chris@1296
|
1030 Cell(0, footer_height, @l['w_page'] + " " + PageNo().to_s + ' / {nb}', 'T', 0, 'R');
|
Chris@1296
|
1031 end
|
Chris@1296
|
1032 end
|
Chris@1296
|
1033 alias_method :footer, :Footer
|
Chris@1296
|
1034
|
Chris@1296
|
1035 #
|
Chris@1296
|
1036 # Returns the current page number.
|
Chris@1296
|
1037 # @return int page number
|
Chris@1296
|
1038 # @since 1.0
|
Chris@1296
|
1039 # @see alias_nb_pages()
|
Chris@1296
|
1040 #
|
Chris@1296
|
1041 def PageNo()
|
Chris@1296
|
1042 #Get current page number
|
Chris@1296
|
1043 return @page;
|
Chris@1296
|
1044 end
|
Chris@1296
|
1045 alias_method :page_no, :PageNo
|
Chris@1296
|
1046
|
Chris@1296
|
1047 #
|
Chris@1296
|
1048 # Defines the color used for all drawing operations (lines, rectangles and cell borders). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page.
|
Chris@1296
|
1049 # @param int :r If g et b are given, red component; if not, indicates the gray level. Value between 0 and 255
|
Chris@1296
|
1050 # @param int :g Green component (between 0 and 255)
|
Chris@1296
|
1051 # @param int :b Blue component (between 0 and 255)
|
Chris@1296
|
1052 # @since 1.3
|
Chris@1296
|
1053 # @see SetFillColor(), SetTextColor(), Line(), Rect(), Cell(), MultiCell()
|
Chris@1296
|
1054 #
|
Chris@1296
|
1055 def SetDrawColor(r, g=-1, b=-1)
|
Chris@1296
|
1056 #Set color for all stroking operations
|
Chris@1296
|
1057 if ((r==0 and g==0 and b==0) or g==-1)
|
Chris@1296
|
1058 @draw_color=sprintf('%.3f G', r/255.0);
|
Chris@1296
|
1059 else
|
Chris@1296
|
1060 @draw_color=sprintf('%.3f %.3f %.3f RG', r/255.0, g/255.0, b/255.0);
|
Chris@1296
|
1061 end
|
Chris@1296
|
1062 if (@page>0)
|
Chris@1296
|
1063 out(@draw_color);
|
Chris@1296
|
1064 end
|
Chris@1296
|
1065 end
|
Chris@1296
|
1066 alias_method :set_draw_color, :SetDrawColor
|
Chris@1296
|
1067
|
Chris@1296
|
1068 #
|
Chris@1296
|
1069 # Defines the color used for all filling operations (filled rectangles and cell backgrounds). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page.
|
Chris@1296
|
1070 # @param int :r If g et b are given, red component; if not, indicates the gray level. Value between 0 and 255
|
Chris@1296
|
1071 # @param int :g Green component (between 0 and 255)
|
Chris@1296
|
1072 # @param int :b Blue component (between 0 and 255)
|
Chris@1296
|
1073 # @param boolean :storeprev if true stores the RGB array on :prevfill_color variable.
|
Chris@1296
|
1074 # @since 1.3
|
Chris@1296
|
1075 # @see SetDrawColor(), SetTextColor(), Rect(), Cell(), MultiCell()
|
Chris@1296
|
1076 #
|
Chris@1296
|
1077 def SetFillColor(r, g=-1, b=-1, storeprev=false)
|
Chris@1296
|
1078 #Set color for all filling operations
|
Chris@1296
|
1079 if ((r==0 and g==0 and b==0) or g==-1)
|
Chris@1296
|
1080 @fill_color=sprintf('%.3f g', r/255.0);
|
Chris@1296
|
1081 else
|
Chris@1296
|
1082 @fill_color=sprintf('%.3f %.3f %.3f rg', r/255.0, g/255.0, b/255.0);
|
Chris@1296
|
1083 end
|
Chris@1296
|
1084 @color_flag=(@fill_color!=@text_color);
|
Chris@1296
|
1085 if (@page>0)
|
Chris@1296
|
1086 out(@fill_color);
|
Chris@1296
|
1087 end
|
Chris@1296
|
1088 if (storeprev)
|
Chris@1296
|
1089 # store color as previous value
|
Chris@1296
|
1090 @prevfill_color = [r, g, b]
|
Chris@1296
|
1091 end
|
Chris@1296
|
1092 end
|
Chris@1296
|
1093 alias_method :set_fill_color, :SetFillColor
|
Chris@1296
|
1094
|
Chris@1296
|
1095 # This hasn't been ported from tcpdf, it's a variation on SetTextColor for setting cmyk colors
|
Chris@1296
|
1096 def SetCmykFillColor(c, m, y, k, storeprev=false)
|
Chris@1296
|
1097 #Set color for all filling operations
|
Chris@1296
|
1098 @fill_color=sprintf('%.3f %.3f %.3f %.3f k', c, m, y, k);
|
Chris@1296
|
1099 @color_flag=(@fill_color!=@text_color);
|
Chris@1296
|
1100 if (storeprev)
|
Chris@1296
|
1101 # store color as previous value
|
Chris@1296
|
1102 @prevtext_color = [c, m, y, k]
|
Chris@1296
|
1103 end
|
Chris@1296
|
1104 if (@page>0)
|
Chris@1296
|
1105 out(@fill_color);
|
Chris@1296
|
1106 end
|
Chris@1296
|
1107 end
|
Chris@1296
|
1108 alias_method :set_cmyk_fill_color, :SetCmykFillColor
|
Chris@1296
|
1109
|
Chris@1296
|
1110 #
|
Chris@1296
|
1111 # Defines the color used for text. It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page.
|
Chris@1296
|
1112 # @param int :r If g et b are given, red component; if not, indicates the gray level. Value between 0 and 255
|
Chris@1296
|
1113 # @param int :g Green component (between 0 and 255)
|
Chris@1296
|
1114 # @param int :b Blue component (between 0 and 255)
|
Chris@1296
|
1115 # @param boolean :storeprev if true stores the RGB array on :prevtext_color variable.
|
Chris@1296
|
1116 # @since 1.3
|
Chris@1296
|
1117 # @see SetDrawColor(), SetFillColor(), Text(), Cell(), MultiCell()
|
Chris@1296
|
1118 #
|
Chris@1296
|
1119 def SetTextColor(r, g=-1, b=-1, storeprev=false)
|
Chris@1296
|
1120 #Set color for text
|
Chris@1296
|
1121 if ((r==0 and :g==0 and :b==0) or :g==-1)
|
Chris@1296
|
1122 @text_color=sprintf('%.3f g', r/255.0);
|
Chris@1296
|
1123 else
|
Chris@1296
|
1124 @text_color=sprintf('%.3f %.3f %.3f rg', r/255.0, g/255.0, b/255.0);
|
Chris@1296
|
1125 end
|
Chris@1296
|
1126 @color_flag=(@fill_color!=@text_color);
|
Chris@1296
|
1127 if (storeprev)
|
Chris@1296
|
1128 # store color as previous value
|
Chris@1296
|
1129 @prevtext_color = [r, g, b]
|
Chris@1296
|
1130 end
|
Chris@1296
|
1131 end
|
Chris@1296
|
1132 alias_method :set_text_color, :SetTextColor
|
Chris@1296
|
1133
|
Chris@1296
|
1134 # This hasn't been ported from tcpdf, it's a variation on SetTextColor for setting cmyk colors
|
Chris@1296
|
1135 def SetCmykTextColor(c, m, y, k, storeprev=false)
|
Chris@1296
|
1136 #Set color for text
|
Chris@1296
|
1137 @text_color=sprintf('%.3f %.3f %.3f %.3f k', c, m, y, k);
|
Chris@1296
|
1138 @color_flag=(@fill_color!=@text_color);
|
Chris@1296
|
1139 if (storeprev)
|
Chris@1296
|
1140 # store color as previous value
|
Chris@1296
|
1141 @prevtext_color = [c, m, y, k]
|
Chris@1296
|
1142 end
|
Chris@1296
|
1143 end
|
Chris@1296
|
1144 alias_method :set_cmyk_text_color, :SetCmykTextColor
|
Chris@1296
|
1145
|
Chris@1296
|
1146 #
|
Chris@1296
|
1147 # Returns the length of a string in user unit. A font must be selected.<br>
|
Chris@1296
|
1148 # Support UTF-8 Unicode [Nicola Asuni, 2005-01-02]
|
Chris@1296
|
1149 # @param string :s The string whose length is to be computed
|
Chris@1296
|
1150 # @return int
|
Chris@1296
|
1151 # @since 1.2
|
Chris@1296
|
1152 #
|
Chris@1296
|
1153 def GetStringWidth(s)
|
Chris@1296
|
1154 #Get width of a string in the current font
|
Chris@1296
|
1155 s = s.to_s;
|
Chris@1296
|
1156 cw = @current_font['cw']
|
Chris@1296
|
1157 w = 0;
|
Chris@1296
|
1158 if (@is_unicode)
|
Chris@1296
|
1159 unicode = UTF8StringToArray(s);
|
Chris@1296
|
1160 unicode.each do |char|
|
Chris@1296
|
1161 if (!cw[char].nil?)
|
Chris@1296
|
1162 w += cw[char];
|
Chris@1296
|
1163 # This should not happen. UTF8StringToArray should guarentee the array is ascii values.
|
Chris@1296
|
1164 # elsif (c!cw[char[0]].nil?)
|
Chris@1296
|
1165 # w += cw[char[0]];
|
Chris@1296
|
1166 # elsif (!cw[char.chr].nil?)
|
Chris@1296
|
1167 # w += cw[char.chr];
|
Chris@1296
|
1168 elsif (!@current_font['desc']['MissingWidth'].nil?)
|
Chris@1296
|
1169 w += @current_font['desc']['MissingWidth']; # set default size
|
Chris@1296
|
1170 else
|
Chris@1296
|
1171 w += 500;
|
Chris@1296
|
1172 end
|
Chris@1296
|
1173 end
|
Chris@1296
|
1174 else
|
Chris@1296
|
1175 s.each_byte do |c|
|
Chris@1296
|
1176 if cw[c.chr]
|
Chris@1296
|
1177 w += cw[c.chr];
|
Chris@1296
|
1178 elsif cw[?c.chr]
|
Chris@1296
|
1179 w += cw[?c.chr]
|
Chris@1296
|
1180 end
|
Chris@1296
|
1181 end
|
Chris@1296
|
1182 end
|
Chris@1296
|
1183 return (w * @font_size / 1000.0);
|
Chris@1296
|
1184 end
|
Chris@1296
|
1185 alias_method :get_string_width, :GetStringWidth
|
Chris@1296
|
1186
|
Chris@1296
|
1187 #
|
Chris@1296
|
1188 # Defines the line width. By default, the value equals 0.2 mm. The method can be called before the first page is created and the value is retained from page to page.
|
Chris@1296
|
1189 # @param float :width The width.
|
Chris@1296
|
1190 # @since 1.0
|
Chris@1296
|
1191 # @see Line(), Rect(), Cell(), MultiCell()
|
Chris@1296
|
1192 #
|
Chris@1296
|
1193 def SetLineWidth(width)
|
Chris@1296
|
1194 #Set line width
|
Chris@1296
|
1195 @line_width = width;
|
Chris@1296
|
1196 if (@page>0)
|
Chris@1296
|
1197 out(sprintf('%.2f w', width*@k));
|
Chris@1296
|
1198 end
|
Chris@1296
|
1199 end
|
Chris@1296
|
1200 alias_method :set_line_width, :SetLineWidth
|
Chris@1296
|
1201
|
Chris@1296
|
1202 #
|
Chris@1296
|
1203 # Draws a line between two points.
|
Chris@1296
|
1204 # @param float :x1 Abscissa of first point
|
Chris@1296
|
1205 # @param float :y1 Ordinate of first point
|
Chris@1296
|
1206 # @param float :x2 Abscissa of second point
|
Chris@1296
|
1207 # @param float :y2 Ordinate of second point
|
Chris@1296
|
1208 # @since 1.0
|
Chris@1296
|
1209 # @see SetLineWidth(), SetDrawColor()
|
Chris@1296
|
1210 #
|
Chris@1296
|
1211 def Line(x1, y1, x2, y2)
|
Chris@1296
|
1212 #Draw a line
|
Chris@1296
|
1213 out(sprintf('%.2f %.2f m %.2f %.2f l S', x1 * @k, (@h - y1) * @k, x2 * @k, (@h - y2) * @k));
|
Chris@1296
|
1214 end
|
Chris@1296
|
1215 alias_method :line, :Line
|
Chris@1296
|
1216
|
Chris@1296
|
1217 def Circle(mid_x, mid_y, radius, style='')
|
Chris@1296
|
1218 mid_y = (@h-mid_y)*@k
|
Chris@1296
|
1219 out(sprintf("q\n")) # postscript content in pdf
|
Chris@1296
|
1220 # init line type etc. with /GSD gs G g (grey) RG rg (RGB) w=line witdh etc.
|
Chris@1296
|
1221 out(sprintf("1 j\n")) # line join
|
Chris@1296
|
1222 # translate ("move") circle to mid_y, mid_y
|
Chris@1296
|
1223 out(sprintf("1 0 0 1 %f %f cm", mid_x, mid_y))
|
Chris@1296
|
1224 kappa = 0.5522847498307933984022516322796
|
Chris@1296
|
1225 # Quadrant 1
|
Chris@1296
|
1226 x_s = 0.0 # 12 o'clock
|
Chris@1296
|
1227 y_s = 0.0 + radius
|
Chris@1296
|
1228 x_e = 0.0 + radius # 3 o'clock
|
Chris@1296
|
1229 y_e = 0.0
|
Chris@1296
|
1230 out(sprintf("%f %f m\n", x_s, y_s)) # move to 12 o'clock
|
Chris@1296
|
1231 # cubic bezier control point 1, start height and kappa * radius to the right
|
Chris@1296
|
1232 bx_e1 = x_s + (radius * kappa)
|
Chris@1296
|
1233 by_e1 = y_s
|
Chris@1296
|
1234 # cubic bezier control point 2, end and kappa * radius above
|
Chris@1296
|
1235 bx_e2 = x_e
|
Chris@1296
|
1236 by_e2 = y_e + (radius * kappa)
|
Chris@1296
|
1237 # draw cubic bezier from current point to x_e/y_e with bx_e1/by_e1 and bx_e2/by_e2 as bezier control points
|
Chris@1296
|
1238 out(sprintf("%f %f %f %f %f %f c\n", bx_e1, by_e1, bx_e2, by_e2, x_e, y_e))
|
Chris@1296
|
1239 # Quadrant 2
|
Chris@1296
|
1240 x_s = x_e
|
Chris@1296
|
1241 y_s = y_e # 3 o'clock
|
Chris@1296
|
1242 x_e = 0.0
|
Chris@1296
|
1243 y_e = 0.0 - radius # 6 o'clock
|
Chris@1296
|
1244 bx_e1 = x_s # cubic bezier point 1
|
Chris@1296
|
1245 by_e1 = y_s - (radius * kappa)
|
Chris@1296
|
1246 bx_e2 = x_e + (radius * kappa) # cubic bezier point 2
|
Chris@1296
|
1247 by_e2 = y_e
|
Chris@1296
|
1248 out(sprintf("%f %f %f %f %f %f c\n", bx_e1, by_e1, bx_e2, by_e2, x_e, y_e))
|
Chris@1296
|
1249 # Quadrant 3
|
Chris@1296
|
1250 x_s = x_e
|
Chris@1296
|
1251 y_s = y_e # 6 o'clock
|
Chris@1296
|
1252 x_e = 0.0 - radius
|
Chris@1296
|
1253 y_e = 0.0 # 9 o'clock
|
Chris@1296
|
1254 bx_e1 = x_s - (radius * kappa) # cubic bezier point 1
|
Chris@1296
|
1255 by_e1 = y_s
|
Chris@1296
|
1256 bx_e2 = x_e # cubic bezier point 2
|
Chris@1296
|
1257 by_e2 = y_e - (radius * kappa)
|
Chris@1296
|
1258 out(sprintf("%f %f %f %f %f %f c\n", bx_e1, by_e1, bx_e2, by_e2, x_e, y_e))
|
Chris@1296
|
1259 # Quadrant 4
|
Chris@1296
|
1260 x_s = x_e
|
Chris@1296
|
1261 y_s = y_e # 9 o'clock
|
Chris@1296
|
1262 x_e = 0.0
|
Chris@1296
|
1263 y_e = 0.0 + radius # 12 o'clock
|
Chris@1296
|
1264 bx_e1 = x_s # cubic bezier point 1
|
Chris@1296
|
1265 by_e1 = y_s + (radius * kappa)
|
Chris@1296
|
1266 bx_e2 = x_e - (radius * kappa) # cubic bezier point 2
|
Chris@1296
|
1267 by_e2 = y_e
|
Chris@1296
|
1268 out(sprintf("%f %f %f %f %f %f c\n", bx_e1, by_e1, bx_e2, by_e2, x_e, y_e))
|
Chris@1296
|
1269 if style=='F'
|
Chris@1296
|
1270 op='f'
|
Chris@1296
|
1271 elsif style=='FD' or style=='DF'
|
Chris@1296
|
1272 op='b'
|
Chris@1296
|
1273 else
|
Chris@1296
|
1274 op='s'
|
Chris@1296
|
1275 end
|
Chris@1296
|
1276 out(sprintf("#{op}\n")) # stroke circle, do not fill and close path
|
Chris@1296
|
1277 # for filling etc. b, b*, f, f*
|
Chris@1296
|
1278 out(sprintf("Q\n")) # finish postscript in PDF
|
Chris@1296
|
1279 end
|
Chris@1296
|
1280 alias_method :circle, :Circle
|
Chris@1296
|
1281
|
Chris@1296
|
1282 #
|
Chris@1296
|
1283 # Outputs a rectangle. It can be drawn (border only), filled (with no border) or both.
|
Chris@1296
|
1284 # @param float :x Abscissa of upper-left corner
|
Chris@1296
|
1285 # @param float :y Ordinate of upper-left corner
|
Chris@1296
|
1286 # @param float :w Width
|
Chris@1296
|
1287 # @param float :h Height
|
Chris@1296
|
1288 # @param string :style Style of rendering. Possible values are:<ul><li>D or empty string: draw (default)</li><li>F: fill</li><li>DF or FD: draw and fill</li></ul>
|
Chris@1296
|
1289 # @since 1.0
|
Chris@1296
|
1290 # @see SetLineWidth(), SetDrawColor(), SetFillColor()
|
Chris@1296
|
1291 #
|
Chris@1296
|
1292 def Rect(x, y, w, h, style='')
|
Chris@1296
|
1293 #Draw a rectangle
|
Chris@1296
|
1294 if (style=='F')
|
Chris@1296
|
1295 op='f';
|
Chris@1296
|
1296 elsif (style=='FD' or style=='DF')
|
Chris@1296
|
1297 op='B';
|
Chris@1296
|
1298 else
|
Chris@1296
|
1299 op='S';
|
Chris@1296
|
1300 end
|
Chris@1296
|
1301 out(sprintf('%.2f %.2f %.2f %.2f re %s', x * @k, (@h - y) * @k, w * @k, -h * @k, op));
|
Chris@1296
|
1302 end
|
Chris@1296
|
1303 alias_method :rect, :Rect
|
Chris@1296
|
1304
|
Chris@1296
|
1305 #
|
Chris@1296
|
1306 # Imports a TrueType or Type1 font and makes it available. It is necessary to generate a font definition file first with the makefont.rb utility. The definition file (and the font file itself when embedding) must be present either in the current directory or in the one indicated by FPDF_FONTPATH if the constant is defined. If it could not be found, the error "Could not include font definition file" is generated.
|
Chris@1296
|
1307 # Support UTF-8 Unicode [Nicola Asuni, 2005-01-02].
|
Chris@1296
|
1308 # <b>Example</b>:<br />
|
Chris@1296
|
1309 # <pre>
|
Chris@1296
|
1310 # :pdf->AddFont('Comic','I');
|
Chris@1296
|
1311 # # is equivalent to:
|
Chris@1296
|
1312 # :pdf->AddFont('Comic','I','comici.rb');
|
Chris@1296
|
1313 # </pre>
|
Chris@1296
|
1314 # @param string :family Font family. The name can be chosen arbitrarily. If it is a standard family name, it will override the corresponding font.
|
Chris@1296
|
1315 # @param string :style Font style. Possible values are (case insensitive):<ul><li>empty string: regular (default)</li><li>B: bold</li><li>I: italic</li><li>BI or IB: bold italic</li></ul>
|
Chris@1296
|
1316 # @param string :file The font definition file. By default, the name is built from the family and style, in lower case with no space.
|
Chris@1296
|
1317 # @since 1.5
|
Chris@1296
|
1318 # @see SetFont()
|
Chris@1296
|
1319 #
|
Chris@1296
|
1320 def AddFont(family, style='', file='')
|
Chris@1296
|
1321 if (family.empty?)
|
Chris@1296
|
1322 return;
|
Chris@1296
|
1323 end
|
Chris@1296
|
1324
|
Chris@1296
|
1325 #Add a TrueType or Type1 font
|
Chris@1296
|
1326 family = family.downcase
|
Chris@1296
|
1327 if ((!@is_unicode) and (family == 'arial'))
|
Chris@1296
|
1328 family = 'helvetica';
|
Chris@1296
|
1329 end
|
Chris@1296
|
1330
|
Chris@1296
|
1331 style=style.upcase
|
Chris@1296
|
1332 style=style.gsub('U','');
|
Chris@1296
|
1333 style=style.gsub('D','');
|
Chris@1296
|
1334 if (style == 'IB')
|
Chris@1296
|
1335 style = 'BI';
|
Chris@1296
|
1336 end
|
Chris@1296
|
1337
|
Chris@1296
|
1338 fontkey = family + style;
|
Chris@1296
|
1339 # check if the font has been already added
|
Chris@1296
|
1340 if !@fonts[fontkey].nil?
|
Chris@1296
|
1341 return;
|
Chris@1296
|
1342 end
|
Chris@1296
|
1343
|
Chris@1296
|
1344 if (file=='')
|
Chris@1296
|
1345 file = family.gsub(' ', '') + style.downcase + '.rb';
|
Chris@1296
|
1346 end
|
Chris@1296
|
1347 font_file_name = getfontpath(file)
|
Chris@1296
|
1348 if (font_file_name.nil?)
|
Chris@1296
|
1349 # try to load the basic file without styles
|
Chris@1296
|
1350 file = family.gsub(' ', '') + '.rb';
|
Chris@1296
|
1351 font_file_name = getfontpath(file)
|
Chris@1296
|
1352 end
|
Chris@1296
|
1353 if font_file_name.nil?
|
Chris@1296
|
1354 Error("Could not find font #{file}.")
|
Chris@1296
|
1355 end
|
Chris@1296
|
1356 require(getfontpath(file))
|
Chris@1296
|
1357 font_desc = TCPDFFontDescriptor.font(file)
|
Chris@1296
|
1358
|
Chris@1296
|
1359 if (font_desc[:name].nil? and @@fpdf_charwidths.nil?)
|
Chris@1296
|
1360 Error('Could not include font definition file');
|
Chris@1296
|
1361 end
|
Chris@1296
|
1362
|
Chris@1296
|
1363 i = @fonts.length+1;
|
Chris@1296
|
1364 if (@is_unicode)
|
Chris@1296
|
1365 @fonts[fontkey] = {'i' => i, 'type' => font_desc[:type], 'name' => font_desc[:name], 'desc' => font_desc[:desc], 'up' => font_desc[:up], 'ut' => font_desc[:ut], 'cw' => font_desc[:cw], 'enc' => font_desc[:enc], 'file' => font_desc[:file], 'ctg' => font_desc[:ctg], 'cMap' => font_desc[:cMap], 'registry' => font_desc[:registry]}
|
Chris@1296
|
1366 @@fpdf_charwidths[fontkey] = font_desc[:cw];
|
Chris@1296
|
1367 else
|
Chris@1296
|
1368 @fonts[fontkey]={'i' => i, 'type'=>'core', 'name'=>@core_fonts[fontkey], 'up'=>-100, 'ut'=>50, 'cw' => font_desc[:cw]}
|
Chris@1296
|
1369 @@fpdf_charwidths[fontkey] = font_desc[:cw];
|
Chris@1296
|
1370 end
|
Chris@1296
|
1371
|
Chris@1296
|
1372 if (!font_desc[:diff].nil? and (!font_desc[:diff].empty?))
|
Chris@1296
|
1373 #Search existing encodings
|
Chris@1296
|
1374 d=0;
|
Chris@1296
|
1375 nb=@diffs.length;
|
Chris@1296
|
1376 1.upto(nb) do |i|
|
Chris@1296
|
1377 if (@diffs[i]== font_desc[:diff])
|
Chris@1296
|
1378 d = i;
|
Chris@1296
|
1379 break;
|
Chris@1296
|
1380 end
|
Chris@1296
|
1381 end
|
Chris@1296
|
1382 if (d==0)
|
Chris@1296
|
1383 d = nb+1;
|
Chris@1296
|
1384 @diffs[d] = font_desc[:diff];
|
Chris@1296
|
1385 end
|
Chris@1296
|
1386 @fonts[fontkey]['diff'] = d;
|
Chris@1296
|
1387 end
|
Chris@1296
|
1388 if (font_desc[:file] and font_desc[:file].length > 0)
|
Chris@1296
|
1389 if (font_desc[:type] == "TrueType") or (font_desc[:type] == "TrueTypeUnicode")
|
Chris@1296
|
1390 @font_files[font_desc[:file]] = {'length1' => font_desc[:originalsize]}
|
Chris@1296
|
1391 else
|
Chris@1296
|
1392 @font_files[font_desc[:file]] = {'length1' => font_desc[:size1], 'length2' => font_desc[:size2]}
|
Chris@1296
|
1393 end
|
Chris@1296
|
1394 end
|
Chris@1296
|
1395 end
|
Chris@1296
|
1396 alias_method :add_font, :AddFont
|
Chris@1296
|
1397
|
Chris@1296
|
1398 #
|
Chris@1296
|
1399 # Sets the font used to print character strings. It is mandatory to call this method at least once before printing text or the resulting document would not be valid.
|
Chris@1296
|
1400 # The font can be either a standard one or a font added via the AddFont() method. Standard fonts use Windows encoding cp1252 (Western Europe).
|
Chris@1296
|
1401 # The method can be called before the first page is created and the font is retained from page to page.
|
Chris@1296
|
1402 # If you just wish to change the current font size, it is simpler to call SetFontSize().
|
Chris@1296
|
1403 # Note: for the standard fonts, the font metric files must be accessible. There are three possibilities for this:<ul><li>They are in the current directory (the one where the running script lies)</li><li>They are in one of the directories defined by the include_path parameter</li><li>They are in the directory defined by the FPDF_FONTPATH constant</li></ul><br />
|
Chris@1296
|
1404 # Example for the last case (note the trailing slash):<br />
|
Chris@1296
|
1405 # <pre>
|
Chris@1296
|
1406 # define('FPDF_FONTPATH','/home/www/font/');
|
Chris@1296
|
1407 # require('tcpdf.rb');
|
Chris@1296
|
1408 #
|
Chris@1296
|
1409 # #Times regular 12
|
Chris@1296
|
1410 # :pdf->SetFont('Times');
|
Chris@1296
|
1411 # #Arial bold 14
|
Chris@1296
|
1412 # :pdf->SetFont('Arial','B',14);
|
Chris@1296
|
1413 # #Removes bold
|
Chris@1296
|
1414 # :pdf->SetFont('');
|
Chris@1296
|
1415 # #Times bold, italic and underlined 14
|
Chris@1296
|
1416 # :pdf->SetFont('Times','BIUD');
|
Chris@1296
|
1417 # </pre><br />
|
Chris@1296
|
1418 # If the file corresponding to the requested font is not found, the error "Could not include font metric file" is generated.
|
Chris@1296
|
1419 # @param string :family Family font. It can be either a name defined by AddFont() or one of the standard families (case insensitive):<ul><li>Courier (fixed-width)</li><li>Helvetica or Arial (synonymous; sans serif)</li><li>Times (serif)</li><li>Symbol (symbolic)</li><li>ZapfDingbats (symbolic)</li></ul>It is also possible to pass an empty string. In that case, the current family is retained.
|
Chris@1296
|
1420 # @param string :style Font style. Possible values are (case insensitive):<ul><li>empty string: regular</li><li>B: bold</li><li>I: italic</li><li>U: underline</li></ul>or any combination. The default value is regular. Bold and italic styles do not apply to Symbol and ZapfDingbats
|
Chris@1296
|
1421 # @param float :size Font size in points. The default value is the current size. If no size has been specified since the beginning of the document, the value taken is 12
|
Chris@1296
|
1422 # @since 1.0
|
Chris@1296
|
1423 # @see AddFont(), SetFontSize(), Cell(), MultiCell(), Write()
|
Chris@1296
|
1424 #
|
Chris@1296
|
1425 def SetFont(family, style='', size=0)
|
Chris@1296
|
1426 # save previous values
|
Chris@1296
|
1427 @prevfont_family = @font_family;
|
Chris@1296
|
1428 @prevfont_style = @font_style;
|
Chris@1296
|
1429
|
Chris@1296
|
1430 family=family.downcase;
|
Chris@1296
|
1431 if (family=='')
|
Chris@1296
|
1432 family=@font_family;
|
Chris@1296
|
1433 end
|
Chris@1296
|
1434 if ((!@is_unicode) and (family == 'arial'))
|
Chris@1296
|
1435 family = 'helvetica';
|
Chris@1296
|
1436 elsif ((family=="symbol") or (family=="zapfdingbats"))
|
Chris@1296
|
1437 style='';
|
Chris@1296
|
1438 end
|
Chris@1296
|
1439
|
Chris@1296
|
1440 style=style.upcase;
|
Chris@1296
|
1441
|
Chris@1296
|
1442 if (style.include?('U'))
|
Chris@1296
|
1443 @underline=true;
|
Chris@1296
|
1444 style= style.gsub('U','');
|
Chris@1296
|
1445 else
|
Chris@1296
|
1446 @underline=false;
|
Chris@1296
|
1447 end
|
Chris@1296
|
1448 if (style.include?('D'))
|
Chris@1296
|
1449 @deleted=true;
|
Chris@1296
|
1450 style= style.gsub('D','');
|
Chris@1296
|
1451 else
|
Chris@1296
|
1452 @deleted=false;
|
Chris@1296
|
1453 end
|
Chris@1296
|
1454 if (style=='IB')
|
Chris@1296
|
1455 style='BI';
|
Chris@1296
|
1456 end
|
Chris@1296
|
1457 if (size==0)
|
Chris@1296
|
1458 size=@font_size_pt;
|
Chris@1296
|
1459 end
|
Chris@1296
|
1460
|
Chris@1296
|
1461 # try to add font (if not already added)
|
Chris@1296
|
1462 AddFont(family, style);
|
Chris@1296
|
1463
|
Chris@1296
|
1464 #Test if font is already selected
|
Chris@1296
|
1465 if ((@font_family == family) and (@font_style == style) and (@font_size_pt == size))
|
Chris@1296
|
1466 return;
|
Chris@1296
|
1467 end
|
Chris@1296
|
1468
|
Chris@1296
|
1469 fontkey = family + style;
|
Chris@1296
|
1470 style = '' if (@fonts[fontkey].nil? and !@fonts[family].nil?)
|
Chris@1296
|
1471
|
Chris@1296
|
1472 #Test if used for the first time
|
Chris@1296
|
1473 if (@fonts[fontkey].nil?)
|
Chris@1296
|
1474 #Check if one of the standard fonts
|
Chris@1296
|
1475 if (!@core_fonts[fontkey].nil?)
|
Chris@1296
|
1476 if @@fpdf_charwidths[fontkey].nil?
|
Chris@1296
|
1477 #Load metric file
|
Chris@1296
|
1478 file = family;
|
Chris@1296
|
1479 if ((family!='symbol') and (family!='zapfdingbats'))
|
Chris@1296
|
1480 file += style.downcase;
|
Chris@1296
|
1481 end
|
Chris@1296
|
1482 if (getfontpath(file + '.rb').nil?)
|
Chris@1296
|
1483 # try to load the basic file without styles
|
Chris@1296
|
1484 file = family;
|
Chris@1296
|
1485 fontkey = family;
|
Chris@1296
|
1486 end
|
Chris@1296
|
1487 require(getfontpath(file + '.rb'));
|
Chris@1296
|
1488 font_desc = TCPDFFontDescriptor.font(file)
|
Chris@1296
|
1489 if ((@is_unicode and ctg.nil?) or ((!@is_unicode) and (@@fpdf_charwidths[fontkey].nil?)) )
|
Chris@1296
|
1490 Error("Could not include font metric file [" + fontkey + "]: " + getfontpath(file + ".rb"));
|
Chris@1296
|
1491 end
|
Chris@1296
|
1492 end
|
Chris@1296
|
1493 i = @fonts.length + 1;
|
Chris@1296
|
1494
|
Chris@1296
|
1495 if (@is_unicode)
|
Chris@1296
|
1496 @fonts[fontkey] = {'i' => i, 'type' => font_desc[:type], 'name' => font_desc[:name], 'desc' => font_desc[:desc], 'up' => font_desc[:up], 'ut' => font_desc[:ut], 'cw' => font_desc[:cw], 'enc' => font_desc[:enc], 'file' => font_desc[:file], 'ctg' => font_desc[:ctg]}
|
Chris@1296
|
1497 @@fpdf_charwidths[fontkey] = font_desc[:cw];
|
Chris@1296
|
1498 else
|
Chris@1296
|
1499 @fonts[fontkey] = {'i' => i, 'type'=>'core', 'name'=>@core_fonts[fontkey], 'up'=>-100, 'ut'=>50, 'cw' => font_desc[:cw]}
|
Chris@1296
|
1500 @@fpdf_charwidths[fontkey] = font_desc[:cw];
|
Chris@1296
|
1501 end
|
Chris@1296
|
1502 else
|
Chris@1296
|
1503 Error('Undefined font: ' + family + ' ' + style);
|
Chris@1296
|
1504 end
|
Chris@1296
|
1505 end
|
Chris@1296
|
1506 #Select it
|
Chris@1296
|
1507 @font_family = family;
|
Chris@1296
|
1508 @font_style = style;
|
Chris@1296
|
1509 @font_size_pt = size;
|
Chris@1296
|
1510 @font_size = size / @k;
|
Chris@1296
|
1511 @current_font = @fonts[fontkey]; # was & may need deep copy?
|
Chris@1296
|
1512 if (@page>0)
|
Chris@1296
|
1513 out(sprintf('BT /F%d %.2f Tf ET', @current_font['i'], @font_size_pt));
|
Chris@1296
|
1514 end
|
Chris@1296
|
1515 end
|
Chris@1296
|
1516 alias_method :set_font, :SetFont
|
Chris@1296
|
1517
|
Chris@1296
|
1518 #
|
Chris@1296
|
1519 # Defines the size of the current font.
|
Chris@1296
|
1520 # @param float :size The size (in points)
|
Chris@1296
|
1521 # @since 1.0
|
Chris@1296
|
1522 # @see SetFont()
|
Chris@1296
|
1523 #
|
Chris@1296
|
1524 def SetFontSize(size)
|
Chris@1296
|
1525 #Set font size in points
|
Chris@1296
|
1526 if (@font_size_pt== size)
|
Chris@1296
|
1527 return;
|
Chris@1296
|
1528 end
|
Chris@1296
|
1529 @font_size_pt = size;
|
Chris@1296
|
1530 @font_size = size.to_f / @k;
|
Chris@1296
|
1531 if (@page > 0)
|
Chris@1296
|
1532 out(sprintf('BT /F%d %.2f Tf ET', @current_font['i'], @font_size_pt));
|
Chris@1296
|
1533 end
|
Chris@1296
|
1534 end
|
Chris@1296
|
1535 alias_method :set_font_size, :SetFontSize
|
Chris@1296
|
1536
|
Chris@1296
|
1537 #
|
Chris@1296
|
1538 # Creates a new internal link and returns its identifier. An internal link is a clickable area which directs to another place within the document.<br />
|
Chris@1296
|
1539 # The identifier can then be passed to Cell(), Write(), Image() or Link(). The destination is defined with SetLink().
|
Chris@1296
|
1540 # @since 1.5
|
Chris@1296
|
1541 # @see Cell(), Write(), Image(), Link(), SetLink()
|
Chris@1296
|
1542 #
|
Chris@1296
|
1543 def AddLink()
|
Chris@1296
|
1544 #Create a new internal link
|
Chris@1296
|
1545 n=@links.length+1;
|
Chris@1296
|
1546 @links[n]=[0,0];
|
Chris@1296
|
1547 return n;
|
Chris@1296
|
1548 end
|
Chris@1296
|
1549 alias_method :add_link, :AddLink
|
Chris@1296
|
1550
|
Chris@1296
|
1551 #
|
Chris@1296
|
1552 # Defines the page and position a link points to
|
Chris@1296
|
1553 # @param int :link The link identifier returned by AddLink()
|
Chris@1296
|
1554 # @param float :y Ordinate of target position; -1 indicates the current position. The default value is 0 (top of page)
|
Chris@1296
|
1555 # @param int :page Number of target page; -1 indicates the current page. This is the default value
|
Chris@1296
|
1556 # @since 1.5
|
Chris@1296
|
1557 # @see AddLink()
|
Chris@1296
|
1558 #
|
Chris@1296
|
1559 def SetLink(link, y=0, page=-1)
|
Chris@1296
|
1560 #Set destination of internal link
|
Chris@1296
|
1561 if (y==-1)
|
Chris@1296
|
1562 y=@y;
|
Chris@1296
|
1563 end
|
Chris@1296
|
1564 if (page==-1)
|
Chris@1296
|
1565 page=@page;
|
Chris@1296
|
1566 end
|
Chris@1296
|
1567 @links[link] = [page, y]
|
Chris@1296
|
1568 end
|
Chris@1296
|
1569 alias_method :set_link, :SetLink
|
Chris@1296
|
1570
|
Chris@1296
|
1571 #
|
Chris@1296
|
1572 # Puts a link on a rectangular area of the page. Text or image links are generally put via Cell(), Write() or Image(), but this method can be useful for instance to define a clickable area inside an image.
|
Chris@1296
|
1573 # @param float :x Abscissa of the upper-left corner of the rectangle
|
Chris@1296
|
1574 # @param float :y Ordinate of the upper-left corner of the rectangle
|
Chris@1296
|
1575 # @param float :w Width of the rectangle
|
Chris@1296
|
1576 # @param float :h Height of the rectangle
|
Chris@1296
|
1577 # @param mixed :link URL or identifier returned by AddLink()
|
Chris@1296
|
1578 # @since 1.5
|
Chris@1296
|
1579 # @see AddLink(), Cell(), Write(), Image()
|
Chris@1296
|
1580 #
|
Chris@1296
|
1581 def Link(x, y, w, h, link)
|
Chris@1296
|
1582 #Put a link on the page
|
Chris@1296
|
1583 @page_links ||= Array.new
|
Chris@1296
|
1584 @page_links[@page] ||= Array.new
|
Chris@1296
|
1585 @page_links[@page].push([x * @k, @h_pt - y * @k, w * @k, h*@k, link]);
|
Chris@1296
|
1586 end
|
Chris@1296
|
1587 alias_method :link, :Link
|
Chris@1296
|
1588
|
Chris@1296
|
1589 #
|
Chris@1296
|
1590 # Prints a character string. The origin is on the left of the first charcter, on the baseline. This method allows to place a string precisely on the page, but it is usually easier to use Cell(), MultiCell() or Write() which are the standard methods to print text.
|
Chris@1296
|
1591 # @param float :x Abscissa of the origin
|
Chris@1296
|
1592 # @param float :y Ordinate of the origin
|
Chris@1296
|
1593 # @param string :txt String to print
|
Chris@1296
|
1594 # @since 1.0
|
Chris@1296
|
1595 # @see SetFont(), SetTextColor(), Cell(), MultiCell(), Write()
|
Chris@1296
|
1596 #
|
Chris@1296
|
1597 def Text(x, y, txt)
|
Chris@1296
|
1598 #Output a string
|
Chris@1296
|
1599 s=sprintf('BT %.2f %.2f Td (%s) Tj ET', x * @k, (@h-y) * @k, escapetext(txt));
|
Chris@1296
|
1600 if (@underline and (txt!=''))
|
Chris@1296
|
1601 s += ' ' + dolinetxt(x, y, txt);
|
Chris@1296
|
1602 end
|
Chris@1296
|
1603 if (@color_flag)
|
Chris@1296
|
1604 s='q ' + @text_color + ' ' + s + ' Q';
|
Chris@1296
|
1605 end
|
Chris@1296
|
1606 out(s);
|
Chris@1296
|
1607 end
|
Chris@1296
|
1608 alias_method :text, :Text
|
Chris@1296
|
1609
|
Chris@1296
|
1610 #
|
Chris@1296
|
1611 # Whenever a page break condition is met, the method is called, and the break is issued or not depending on the returned value. The default implementation returns a value according to the mode selected by SetAutoPageBreak().<br />
|
Chris@1296
|
1612 # This method is called automatically and should not be called directly by the application.<br />
|
Chris@1296
|
1613 # <b>Example:</b><br />
|
Chris@1296
|
1614 # The method is overriden in an inherited class in order to obtain a 3 column layout:<br />
|
Chris@1296
|
1615 # <pre>
|
Chris@1296
|
1616 # class PDF extends TCPDF {
|
Chris@1296
|
1617 # var :col=0;
|
Chris@1296
|
1618 #
|
Chris@1296
|
1619 # def SetCol(col)
|
Chris@1296
|
1620 # #Move position to a column
|
Chris@1296
|
1621 # @col = col;
|
Chris@1296
|
1622 # :x=10+:col*65;
|
Chris@1296
|
1623 # SetLeftMargin(x);
|
Chris@1296
|
1624 # SetX(x);
|
Chris@1296
|
1625 # end
|
Chris@1296
|
1626 #
|
Chris@1296
|
1627 # def AcceptPageBreak()
|
Chris@1296
|
1628 # if (@col<2)
|
Chris@1296
|
1629 # #Go to next column
|
Chris@1296
|
1630 # SetCol(@col+1);
|
Chris@1296
|
1631 # SetY(10);
|
Chris@1296
|
1632 # return false;
|
Chris@1296
|
1633 # end
|
Chris@1296
|
1634 # else
|
Chris@1296
|
1635 # #Go back to first column and issue page break
|
Chris@1296
|
1636 # SetCol(0);
|
Chris@1296
|
1637 # return true;
|
Chris@1296
|
1638 # end
|
Chris@1296
|
1639 # end
|
Chris@1296
|
1640 # }
|
Chris@1296
|
1641 #
|
Chris@1296
|
1642 # :pdf=new PDF();
|
Chris@1296
|
1643 # :pdf->Open();
|
Chris@1296
|
1644 # :pdf->AddPage();
|
Chris@1296
|
1645 # :pdf->SetFont('Arial','',12);
|
Chris@1296
|
1646 # for(i=1;:i<=300;:i++)
|
Chris@1296
|
1647 # :pdf->Cell(0,5,"Line :i",0,1);
|
Chris@1296
|
1648 # }
|
Chris@1296
|
1649 # :pdf->Output();
|
Chris@1296
|
1650 # </pre>
|
Chris@1296
|
1651 # @return boolean
|
Chris@1296
|
1652 # @since 1.4
|
Chris@1296
|
1653 # @see SetAutoPageBreak()
|
Chris@1296
|
1654 #
|
Chris@1296
|
1655 def AcceptPageBreak()
|
Chris@1296
|
1656 #Accept automatic page break or not
|
Chris@1296
|
1657 return @auto_page_break;
|
Chris@1296
|
1658 end
|
Chris@1296
|
1659 alias_method :accept_page_break, :AcceptPageBreak
|
Chris@1296
|
1660
|
Chris@1296
|
1661 def BreakThePage?(h)
|
Chris@1296
|
1662 if ((@y + h) > @page_break_trigger and !@in_footer and AcceptPageBreak())
|
Chris@1296
|
1663 true
|
Chris@1296
|
1664 else
|
Chris@1296
|
1665 false
|
Chris@1296
|
1666 end
|
Chris@1296
|
1667 end
|
Chris@1296
|
1668 alias_method :break_the_page?, :BreakThePage?
|
Chris@1296
|
1669 #
|
Chris@1296
|
1670 # Prints a cell (rectangular area) with optional borders, background color and character string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text.<br />
|
Chris@1296
|
1671 # If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting.
|
Chris@1296
|
1672 # @param float :w Cell width. If 0, the cell extends up to the right margin.
|
Chris@1296
|
1673 # @param float :h Cell height. Default value: 0.
|
Chris@1296
|
1674 # @param string :txt String to print. Default value: empty string.
|
Chris@1296
|
1675 # @param mixed :border Indicates if borders must be drawn around the cell. The value can be either a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul>or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul>
|
Chris@1296
|
1676 # @param int :ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>
|
Chris@1296
|
1677 # Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
|
Chris@1296
|
1678 # @param string :align Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align (default value)</li><li>C: center</li><li>R: right align</li></ul>
|
Chris@1296
|
1679 # @param int :fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.
|
Chris@1296
|
1680 # @param mixed :link URL or identifier returned by AddLink().
|
Chris@1296
|
1681 # @since 1.0
|
Chris@1296
|
1682 # @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), AddLink(), Ln(), MultiCell(), Write(), SetAutoPageBreak()
|
Chris@1296
|
1683 #
|
Chris@1296
|
1684 def Cell(w, h=0, txt='', border=0, ln=0, align='', fill=0, link=nil)
|
Chris@1296
|
1685 #Output a cell
|
Chris@1296
|
1686 k=@k;
|
Chris@1296
|
1687 if ((@y + h) > @page_break_trigger and !@in_footer and AcceptPageBreak())
|
Chris@1296
|
1688 #Automatic page break
|
Chris@1296
|
1689 if @pages[@page+1].nil?
|
Chris@1296
|
1690 x = @x;
|
Chris@1296
|
1691 ws = @ws;
|
Chris@1296
|
1692 if (ws > 0)
|
Chris@1296
|
1693 @ws = 0;
|
Chris@1296
|
1694 out('0 Tw');
|
Chris@1296
|
1695 end
|
Chris@1296
|
1696 AddPage(@cur_orientation);
|
Chris@1296
|
1697 @x = x;
|
Chris@1296
|
1698 if (ws > 0)
|
Chris@1296
|
1699 @ws = ws;
|
Chris@1296
|
1700 out(sprintf('%.3f Tw', ws * k));
|
Chris@1296
|
1701 end
|
Chris@1296
|
1702 else
|
Chris@1296
|
1703 @page += 1;
|
Chris@1296
|
1704 @y=@t_margin;
|
Chris@1296
|
1705 end
|
Chris@1296
|
1706 end
|
Chris@1296
|
1707
|
Chris@1296
|
1708 if (w == 0)
|
Chris@1296
|
1709 w = @w - @r_margin - @x;
|
Chris@1296
|
1710 end
|
Chris@1296
|
1711 s = '';
|
Chris@1296
|
1712 if ((fill.to_i == 1) or (border.to_i == 1))
|
Chris@1296
|
1713 if (fill.to_i == 1)
|
Chris@1296
|
1714 op = (border.to_i == 1) ? 'B' : 'f';
|
Chris@1296
|
1715 else
|
Chris@1296
|
1716 op = 'S';
|
Chris@1296
|
1717 end
|
Chris@1296
|
1718 s = sprintf('%.2f %.2f %.2f %.2f re %s ', @x * k, (@h - @y) * k, w * k, -h * k, op);
|
Chris@1296
|
1719 end
|
Chris@1296
|
1720 if (border.is_a?(String))
|
Chris@1296
|
1721 x=@x;
|
Chris@1296
|
1722 y=@y;
|
Chris@1296
|
1723 if (border.include?('L'))
|
Chris@1296
|
1724 s<<sprintf('%.2f %.2f m %.2f %.2f l S ', x*k,(@h-y)*k, x*k,(@h-(y+h))*k);
|
Chris@1296
|
1725 end
|
Chris@1296
|
1726 if (border.include?('T'))
|
Chris@1296
|
1727 s<<sprintf('%.2f %.2f m %.2f %.2f l S ', x*k,(@h-y)*k,(x+w)*k,(@h-y)*k);
|
Chris@1296
|
1728 end
|
Chris@1296
|
1729 if (border.include?('R'))
|
Chris@1296
|
1730 s<<sprintf('%.2f %.2f m %.2f %.2f l S ',(x+w)*k,(@h-y)*k,(x+w)*k,(@h-(y+h))*k);
|
Chris@1296
|
1731 end
|
Chris@1296
|
1732 if (border.include?('B'))
|
Chris@1296
|
1733 s<<sprintf('%.2f %.2f m %.2f %.2f l S ', x*k,(@h-(y+h))*k,(x+w)*k,(@h-(y+h))*k);
|
Chris@1296
|
1734 end
|
Chris@1296
|
1735 end
|
Chris@1296
|
1736 if (txt != '')
|
Chris@1296
|
1737 width = GetStringWidth(txt);
|
Chris@1296
|
1738 if (align == 'R' || align == 'right')
|
Chris@1296
|
1739 dx = w - @c_margin - width;
|
Chris@1296
|
1740 elsif (align=='C' || align == 'center')
|
Chris@1296
|
1741 dx = (w - width)/2;
|
Chris@1296
|
1742 else
|
Chris@1296
|
1743 dx = @c_margin;
|
Chris@1296
|
1744 end
|
Chris@1296
|
1745 if (@color_flag)
|
Chris@1296
|
1746 s << 'q ' + @text_color + ' ';
|
Chris@1296
|
1747 end
|
Chris@1296
|
1748 txt2 = escapetext(txt);
|
Chris@1296
|
1749 s<<sprintf('BT %.2f %.2f Td (%s) Tj ET', (@x + dx) * k, (@h - (@y + 0.5 * h + 0.3 * @font_size)) * k, txt2);
|
Chris@1296
|
1750 if (@underline)
|
Chris@1296
|
1751 s<<' ' + dolinetxt(@x + dx, @y + 0.5 * h + 0.3 * @font_size, txt);
|
Chris@1296
|
1752 end
|
Chris@1296
|
1753 if (@deleted)
|
Chris@1296
|
1754 s<<' ' + dolinetxt(@x + dx, @y + 0.3 * h + 0.2 * @font_size, txt);
|
Chris@1296
|
1755 end
|
Chris@1296
|
1756 if (@color_flag)
|
Chris@1296
|
1757 s<<' Q';
|
Chris@1296
|
1758 end
|
Chris@1296
|
1759 if link && !link.empty?
|
Chris@1296
|
1760 Link(@x + dx, @y + 0.5 * h - 0.5 * @font_size, width, @font_size, link);
|
Chris@1296
|
1761 end
|
Chris@1296
|
1762 end
|
Chris@1296
|
1763 if (s)
|
Chris@1296
|
1764 out(s);
|
Chris@1296
|
1765 end
|
Chris@1296
|
1766 @lasth = h;
|
Chris@1296
|
1767 if (ln.to_i>0)
|
Chris@1296
|
1768 # Go to next line
|
Chris@1296
|
1769 @y += h;
|
Chris@1296
|
1770 if (ln == 1)
|
Chris@1296
|
1771 @x = @l_margin;
|
Chris@1296
|
1772 end
|
Chris@1296
|
1773 else
|
Chris@1296
|
1774 @x += w;
|
Chris@1296
|
1775 end
|
Chris@1296
|
1776 end
|
Chris@1296
|
1777 alias_method :cell, :Cell
|
Chris@1296
|
1778
|
Chris@1296
|
1779 #
|
Chris@1296
|
1780 # This method allows printing text with line breaks. They can be automatic (as soon as the text reaches the right border of the cell) or explicit (via the \n character). As many cells as necessary are output, one below the other.<br />
|
Chris@1296
|
1781 # Text can be aligned, centered or justified. The cell block can be framed and the background painted.
|
Chris@1296
|
1782 # @param float :w Width of cells. If 0, they extend up to the right margin of the page.
|
Chris@1296
|
1783 # @param float :h Height of cells.
|
Chris@1296
|
1784 # @param string :txt String to print
|
Chris@1296
|
1785 # @param mixed :border Indicates if borders must be drawn around the cell block. The value can be either a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul>or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul>
|
Chris@1296
|
1786 # @param string :align Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align</li><li>C: center</li><li>R: right align</li><li>J: justification (default value)</li></ul>
|
Chris@1296
|
1787 # @param int :fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.
|
Chris@1296
|
1788 # @param int :ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right</li><li>1: to the beginning of the next line [DEFAULT]</li><li>2: below</li></ul>
|
Chris@1296
|
1789 # @since 1.3
|
Chris@1296
|
1790 # @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), Cell(), Write(), SetAutoPageBreak()
|
Chris@1296
|
1791 #
|
Chris@1296
|
1792 def MultiCell(w, h, txt, border=0, align='J', fill=0, ln=1)
|
Chris@1296
|
1793
|
Chris@1296
|
1794 # save current position
|
Chris@1296
|
1795 prevx = @x;
|
Chris@1296
|
1796 prevy = @y;
|
Chris@1296
|
1797 prevpage = @page;
|
Chris@1296
|
1798
|
Chris@1296
|
1799 #Output text with automatic or explicit line breaks
|
Chris@1296
|
1800
|
Chris@1296
|
1801 if (w == 0)
|
Chris@1296
|
1802 w = @w - @r_margin - @x;
|
Chris@1296
|
1803 end
|
Chris@1296
|
1804
|
Chris@1296
|
1805 wmax = (w - 3 * @c_margin);
|
Chris@1296
|
1806
|
Chris@1296
|
1807 s = txt.gsub("\r", ''); # remove carriage returns
|
Chris@1296
|
1808 nb = s.length;
|
Chris@1296
|
1809
|
Chris@1296
|
1810 b=0;
|
Chris@1296
|
1811 if (border)
|
Chris@1296
|
1812 if (border==1)
|
Chris@1296
|
1813 border='LTRB';
|
Chris@1296
|
1814 b='LRT';
|
Chris@1296
|
1815 b2='LR';
|
Chris@1296
|
1816 elsif border.is_a?(String)
|
Chris@1296
|
1817 b2='';
|
Chris@1296
|
1818 if (border.include?('L'))
|
Chris@1296
|
1819 b2<<'L';
|
Chris@1296
|
1820 end
|
Chris@1296
|
1821 if (border.include?('R'))
|
Chris@1296
|
1822 b2<<'R';
|
Chris@1296
|
1823 end
|
Chris@1296
|
1824 b=(border.include?('T')) ? b2 + 'T' : b2;
|
Chris@1296
|
1825 end
|
Chris@1296
|
1826 end
|
Chris@1296
|
1827 sep=-1;
|
Chris@1296
|
1828 to_index=0;
|
Chris@1296
|
1829 from_j=0;
|
Chris@1296
|
1830 l=0;
|
Chris@1296
|
1831 ns=0;
|
Chris@1296
|
1832 nl=1;
|
Chris@1296
|
1833
|
Chris@1296
|
1834 while to_index < nb
|
Chris@1296
|
1835 #Get next character
|
Chris@1296
|
1836 c = s[to_index];
|
Chris@1296
|
1837 if c == "\n"[0]
|
Chris@1296
|
1838 #Explicit line break
|
Chris@1296
|
1839 if @ws > 0
|
Chris@1296
|
1840 @ws = 0
|
Chris@1296
|
1841 out('0 Tw')
|
Chris@1296
|
1842 end
|
Chris@1296
|
1843 #Ed Moss - change begin
|
Chris@1296
|
1844 end_i = to_index == 0 ? 0 : to_index - 1
|
Chris@1296
|
1845 # Changed from s[from_j..to_index] to fix bug reported by Hans Allis.
|
Chris@1296
|
1846 from_j = to_index == 0 ? 1 : from_j
|
Chris@1296
|
1847 Cell(w, h, s[from_j..end_i], b, 2, align, fill)
|
Chris@1296
|
1848 #change end
|
Chris@1296
|
1849 to_index += 1
|
Chris@1296
|
1850 sep=-1
|
Chris@1296
|
1851 from_j=to_index
|
Chris@1296
|
1852 l=0
|
Chris@1296
|
1853 ns=0
|
Chris@1296
|
1854 nl += 1
|
Chris@1296
|
1855 b = b2 if border and nl==2
|
Chris@1296
|
1856 next
|
Chris@1296
|
1857 end
|
Chris@1296
|
1858 if (c == " "[0])
|
Chris@1296
|
1859 sep = to_index;
|
Chris@1296
|
1860 ls = l;
|
Chris@1296
|
1861 ns += 1;
|
Chris@1296
|
1862 end
|
Chris@1296
|
1863
|
Chris@1296
|
1864 l = GetStringWidth(s[from_j, to_index - from_j]);
|
Chris@1296
|
1865
|
Chris@1296
|
1866 if (l > wmax)
|
Chris@1296
|
1867 #Automatic line break
|
Chris@1296
|
1868 if (sep == -1)
|
Chris@1296
|
1869 if (to_index == from_j)
|
Chris@1296
|
1870 to_index += 1;
|
Chris@1296
|
1871 end
|
Chris@1296
|
1872 if (@ws > 0)
|
Chris@1296
|
1873 @ws = 0;
|
Chris@1296
|
1874 out('0 Tw');
|
Chris@1296
|
1875 end
|
Chris@1296
|
1876 Cell(w, h, s[from_j..to_index-1], b, 2, align, fill) # my FPDF version
|
Chris@1296
|
1877 else
|
Chris@1296
|
1878 if (align=='J' || align=='justify' || align=='justified')
|
Chris@1296
|
1879 @ws = (ns>1) ? (wmax-ls)/(ns-1) : 0;
|
Chris@1296
|
1880 out(sprintf('%.3f Tw', @ws * @k));
|
Chris@1296
|
1881 end
|
Chris@1296
|
1882 Cell(w, h, s[from_j..sep], b, 2, align, fill);
|
Chris@1296
|
1883 to_index = sep + 1;
|
Chris@1296
|
1884 end
|
Chris@1296
|
1885 sep=-1;
|
Chris@1296
|
1886 from_j = to_index;
|
Chris@1296
|
1887 l=0;
|
Chris@1296
|
1888 ns=0;
|
Chris@1296
|
1889 nl += 1;
|
Chris@1296
|
1890 if (border and (nl==2))
|
Chris@1296
|
1891 b = b2;
|
Chris@1296
|
1892 end
|
Chris@1296
|
1893 else
|
Chris@1296
|
1894 to_index += 1;
|
Chris@1296
|
1895 end
|
Chris@1296
|
1896 end
|
Chris@1296
|
1897 #Last chunk
|
Chris@1296
|
1898 if (@ws>0)
|
Chris@1296
|
1899 @ws=0;
|
Chris@1296
|
1900 out('0 Tw');
|
Chris@1296
|
1901 end
|
Chris@1296
|
1902 if (border.is_a?(String) and border.include?('B'))
|
Chris@1296
|
1903 b<<'B';
|
Chris@1296
|
1904 end
|
Chris@1296
|
1905 Cell(w, h, s[from_j, to_index-from_j], b, 2, align, fill);
|
Chris@1296
|
1906
|
Chris@1296
|
1907 # move cursor to specified position
|
Chris@1296
|
1908 # since 2007-03-03
|
Chris@1296
|
1909 if (ln == 1)
|
Chris@1296
|
1910 # go to the beginning of the next line
|
Chris@1296
|
1911 @x = @l_margin;
|
Chris@1296
|
1912 elsif (ln == 0)
|
Chris@1296
|
1913 # go to the top-right of the cell
|
Chris@1296
|
1914 @page = prevpage;
|
Chris@1296
|
1915 @y = prevy;
|
Chris@1296
|
1916 @x = prevx + w;
|
Chris@1296
|
1917 elsif (ln == 2)
|
Chris@1296
|
1918 # go to the bottom-left of the cell
|
Chris@1296
|
1919 @x = prevx;
|
Chris@1296
|
1920 end
|
Chris@1296
|
1921 end
|
Chris@1296
|
1922 alias_method :multi_cell, :MultiCell
|
Chris@1296
|
1923
|
Chris@1296
|
1924 #
|
Chris@1296
|
1925 # This method prints text from the current position. When the right margin is reached (or the \n character is met) a line break occurs and text continues from the left margin. Upon method exit, the current position is left just at the end of the text. It is possible to put a link on the text.<br />
|
Chris@1296
|
1926 # <b>Example:</b><br />
|
Chris@1296
|
1927 # <pre>
|
Chris@1296
|
1928 # #Begin with regular font
|
Chris@1296
|
1929 # :pdf->SetFont('Arial','',14);
|
Chris@1296
|
1930 # :pdf->Write(5,'Visit ');
|
Chris@1296
|
1931 # #Then put a blue underlined link
|
Chris@1296
|
1932 # :pdf->SetTextColor(0,0,255);
|
Chris@1296
|
1933 # :pdf->SetFont('','U');
|
Chris@1296
|
1934 # :pdf->Write(5,'www.tecnick.com','http://www.tecnick.com');
|
Chris@1296
|
1935 # </pre>
|
Chris@1296
|
1936 # @param float :h Line height
|
Chris@1296
|
1937 # @param string :txt String to print
|
Chris@1296
|
1938 # @param mixed :link URL or identifier returned by AddLink()
|
Chris@1296
|
1939 # @param int :fill Indicates if the background must be painted (1) or transparent (0). Default value: 0.
|
Chris@1296
|
1940 # @since 1.5
|
Chris@1296
|
1941 # @see SetFont(), SetTextColor(), AddLink(), MultiCell(), SetAutoPageBreak()
|
Chris@1296
|
1942 #
|
Chris@1296
|
1943 def Write(h, txt, link=nil, fill=0)
|
Chris@1296
|
1944
|
Chris@1296
|
1945 #Output text in flowing mode
|
Chris@1296
|
1946 w = @w - @r_margin - @x;
|
Chris@1296
|
1947 wmax = (w - 3 * @c_margin);
|
Chris@1296
|
1948
|
Chris@1296
|
1949 s = txt.gsub("\r", '');
|
Chris@1296
|
1950 nb = s.length;
|
Chris@1296
|
1951
|
Chris@1296
|
1952 # handle single space character
|
Chris@1296
|
1953 if ((nb==1) and (s == " "))
|
Chris@1296
|
1954 @x += GetStringWidth(s);
|
Chris@1296
|
1955 return;
|
Chris@1296
|
1956 end
|
Chris@1296
|
1957
|
Chris@1296
|
1958 sep=-1;
|
Chris@1296
|
1959 i=0;
|
Chris@1296
|
1960 j=0;
|
Chris@1296
|
1961 l=0;
|
Chris@1296
|
1962 nl=1;
|
Chris@1296
|
1963 while(i<nb)
|
Chris@1296
|
1964 #Get next character
|
Chris@1296
|
1965 c = s[i];
|
Chris@1296
|
1966 if (c == "\n"[0])
|
Chris@1296
|
1967 #Explicit line break
|
Chris@1296
|
1968 Cell(w, h, s[j,i-j], 0, 2, '', fill, link);
|
Chris@1296
|
1969 i += 1;
|
Chris@1296
|
1970 sep = -1;
|
Chris@1296
|
1971 j = i;
|
Chris@1296
|
1972 l = 0;
|
Chris@1296
|
1973 if (nl == 1)
|
Chris@1296
|
1974 @x = @l_margin;
|
Chris@1296
|
1975 w = @w - @r_margin - @x;
|
Chris@1296
|
1976 wmax = (w - 3 * @c_margin);
|
Chris@1296
|
1977 end
|
Chris@1296
|
1978 nl += 1;
|
Chris@1296
|
1979 next
|
Chris@1296
|
1980 end
|
Chris@1296
|
1981 if (c == " "[0])
|
Chris@1296
|
1982 sep= i;
|
Chris@1296
|
1983 end
|
Chris@1296
|
1984 l = GetStringWidth(s[j, i - j]);
|
Chris@1296
|
1985 if (l > wmax)
|
Chris@1296
|
1986 #Automatic line break (word wrapping)
|
Chris@1296
|
1987 if (sep == -1)
|
Chris@1296
|
1988 if (@x > @l_margin)
|
Chris@1296
|
1989 #Move to next line
|
Chris@1296
|
1990 @x = @l_margin;
|
Chris@1296
|
1991 @y += h;
|
Chris@1296
|
1992 w=@w - @r_margin - @x;
|
Chris@1296
|
1993 wmax=(w - 3 * @c_margin);
|
Chris@1296
|
1994 i += 1
|
Chris@1296
|
1995 nl += 1
|
Chris@1296
|
1996 next
|
Chris@1296
|
1997 end
|
Chris@1296
|
1998 if (i == j)
|
Chris@1296
|
1999 i += 1
|
Chris@1296
|
2000 end
|
Chris@1296
|
2001 Cell(w, h, s[j, (i-1)], 0, 2, '', fill, link);
|
Chris@1296
|
2002 else
|
Chris@1296
|
2003 Cell(w, h, s[j, (sep-j)], 0, 2, '', fill, link);
|
Chris@1296
|
2004 i = sep+1;
|
Chris@1296
|
2005 end
|
Chris@1296
|
2006 sep = -1;
|
Chris@1296
|
2007 j = i;
|
Chris@1296
|
2008 l = 0;
|
Chris@1296
|
2009 if (nl==1)
|
Chris@1296
|
2010 @x = @l_margin;
|
Chris@1296
|
2011 w = @w - @r_margin - @x;
|
Chris@1296
|
2012 wmax = (w - 3 * @c_margin);
|
Chris@1296
|
2013 end
|
Chris@1296
|
2014 nl += 1;
|
Chris@1296
|
2015 else
|
Chris@1296
|
2016 i += 1;
|
Chris@1296
|
2017 end
|
Chris@1296
|
2018 end
|
Chris@1296
|
2019 #Last chunk
|
Chris@1296
|
2020 if (i != j)
|
Chris@1296
|
2021 Cell(GetStringWidth(s[j..i]), h, s[j..i], 0, 0, '', fill, link);
|
Chris@1296
|
2022 end
|
Chris@1296
|
2023 end
|
Chris@1296
|
2024 alias_method :write, :Write
|
Chris@1296
|
2025
|
Chris@1296
|
2026 #
|
Chris@1296
|
2027 # Puts an image in the page. The upper-left corner must be given. The dimensions can be specified in different ways:<ul><li>explicit width and height (expressed in user unit)</li><li>one explicit dimension, the other being calculated automatically in order to keep the original proportions</li><li>no explicit dimension, in which case the image is put at 72 dpi</li></ul>
|
Chris@1296
|
2028 # Supported formats are JPEG and PNG.
|
Chris@1296
|
2029 # For JPEG, all flavors are allowed:<ul><li>gray scales</li><li>true colors (24 bits)</li><li>CMYK (32 bits)</li></ul>
|
Chris@1296
|
2030 # For PNG, are allowed:<ul><li>gray scales on at most 8 bits (256 levels)</li><li>indexed colors</li><li>true colors (24 bits)</li></ul>
|
Chris@1296
|
2031 # but are not supported:<ul><li>Interlacing</li><li>Alpha channel</li></ul>
|
Chris@1296
|
2032 # If a transparent color is defined, it will be taken into account (but will be only interpreted by Acrobat 4 and above).<br />
|
Chris@1296
|
2033 # The format can be specified explicitly or inferred from the file extension.<br />
|
Chris@1296
|
2034 # It is possible to put a link on the image.<br />
|
Chris@1296
|
2035 # Remark: if an image is used several times, only one copy will be embedded in the file.<br />
|
Chris@1296
|
2036 # @param string :file Name of the file containing the image.
|
Chris@1296
|
2037 # @param float :x Abscissa of the upper-left corner.
|
Chris@1296
|
2038 # @param float :y Ordinate of the upper-left corner.
|
Chris@1296
|
2039 # @param float :w Width of the image in the page. If not specified or equal to zero, it is automatically calculated.
|
Chris@1296
|
2040 # @param float :h Height of the image in the page. If not specified or equal to zero, it is automatically calculated.
|
Chris@1296
|
2041 # @param string :type Image format. Possible values are (case insensitive): JPG, JPEG, PNG. If not specified, the type is inferred from the file extension.
|
Chris@1296
|
2042 # @param mixed :link URL or identifier returned by AddLink().
|
Chris@1296
|
2043 # @since 1.1
|
Chris@1296
|
2044 # @see AddLink()
|
Chris@1296
|
2045 #
|
Chris@1296
|
2046 def Image(file, x, y, w=0, h=0, type='', link=nil)
|
Chris@1296
|
2047 #Put an image on the page
|
Chris@1296
|
2048 if (@images[file].nil?)
|
Chris@1296
|
2049 #First use of image, get info
|
Chris@1296
|
2050 if (type == '')
|
Chris@1296
|
2051 pos = File::basename(file).rindex('.');
|
Chris@1296
|
2052 if (pos.nil? or pos == 0)
|
Chris@1296
|
2053 Error('Image file has no extension and no type was specified: ' + file);
|
Chris@1296
|
2054 end
|
Chris@1296
|
2055 pos = file.rindex('.');
|
Chris@1296
|
2056 type = file[pos+1..-1];
|
Chris@1296
|
2057 end
|
Chris@1296
|
2058 type.downcase!
|
Chris@1296
|
2059 if (type == 'jpg' or type == 'jpeg')
|
Chris@1296
|
2060 info=parsejpg(file);
|
Chris@1296
|
2061 elsif (type == 'png')
|
Chris@1296
|
2062 info=parsepng(file);
|
Chris@1296
|
2063 elsif (type == 'gif')
|
Chris@1296
|
2064 tmpFile = imageToPNG(file);
|
Chris@1296
|
2065 info=parsepng(tmpFile.path);
|
Chris@1296
|
2066 tmpFile.delete
|
Chris@1296
|
2067 else
|
Chris@1296
|
2068 #Allow for additional formats
|
Chris@1296
|
2069 mtd='parse' + type;
|
Chris@1296
|
2070 if (!self.respond_to?(mtd))
|
Chris@1296
|
2071 Error('Unsupported image type: ' + type);
|
Chris@1296
|
2072 end
|
Chris@1296
|
2073 info=send(mtd, file);
|
Chris@1296
|
2074 end
|
Chris@1296
|
2075 info['i']=@images.length+1;
|
Chris@1296
|
2076 @images[file] = info;
|
Chris@1296
|
2077 else
|
Chris@1296
|
2078 info=@images[file];
|
Chris@1296
|
2079 end
|
Chris@1296
|
2080 #Automatic width and height calculation if needed
|
Chris@1296
|
2081 if ((w == 0) and (h == 0))
|
Chris@1296
|
2082 rescale_x = (@w - @r_margin - x) / (info['w'] / (@img_scale * @k))
|
Chris@1296
|
2083 rescale_x = 1 if rescale_x >= 1
|
Chris@1296
|
2084 if (y + info['h'] * rescale_x / (@img_scale * @k) > @page_break_trigger and !@in_footer and AcceptPageBreak())
|
Chris@1296
|
2085 #Automatic page break
|
Chris@1296
|
2086 if @pages[@page+1].nil?
|
Chris@1296
|
2087 ws = @ws;
|
Chris@1296
|
2088 if (ws > 0)
|
Chris@1296
|
2089 @ws = 0;
|
Chris@1296
|
2090 out('0 Tw');
|
Chris@1296
|
2091 end
|
Chris@1296
|
2092 AddPage(@cur_orientation);
|
Chris@1296
|
2093 if (ws > 0)
|
Chris@1296
|
2094 @ws = ws;
|
Chris@1296
|
2095 out(sprintf('%.3f Tw', ws * @k));
|
Chris@1296
|
2096 end
|
Chris@1296
|
2097 else
|
Chris@1296
|
2098 @page += 1;
|
Chris@1296
|
2099 end
|
Chris@1296
|
2100 y=@t_margin;
|
Chris@1296
|
2101 end
|
Chris@1296
|
2102 rescale_y = (@page_break_trigger - y) / (info['h'] / (@img_scale * @k))
|
Chris@1296
|
2103 rescale_y = 1 if rescale_y >= 1
|
Chris@1296
|
2104 rescale = rescale_y >= rescale_x ? rescale_x : rescale_y
|
Chris@1296
|
2105
|
Chris@1296
|
2106 #Put image at 72 dpi
|
Chris@1296
|
2107 # 2004-06-14 :: Nicola Asuni, scale factor where added
|
Chris@1296
|
2108 w = info['w'] * rescale / (@img_scale * @k);
|
Chris@1296
|
2109 h = info['h'] * rescale / (@img_scale * @k);
|
Chris@1296
|
2110 elsif (w == 0)
|
Chris@1296
|
2111 w = h * info['w'] / info['h'];
|
Chris@1296
|
2112 elsif (h == 0)
|
Chris@1296
|
2113 h = w * info['h'] / info['w'];
|
Chris@1296
|
2114 end
|
Chris@1296
|
2115 out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q', w*@k, h*@k, x*@k, (@h-(y+h))*@k, info['i']));
|
Chris@1296
|
2116 if (link)
|
Chris@1296
|
2117 Link(x, y, w, h, link);
|
Chris@1296
|
2118 end
|
Chris@1296
|
2119
|
Chris@1296
|
2120 #2002-07-31 - Nicola Asuni
|
Chris@1296
|
2121 # set right-bottom corner coordinates
|
Chris@1296
|
2122 @img_rb_x = x + w;
|
Chris@1296
|
2123 @img_rb_y = y + h;
|
Chris@1296
|
2124 end
|
Chris@1296
|
2125 alias_method :image, :Image
|
Chris@1296
|
2126
|
Chris@1296
|
2127 #
|
Chris@1296
|
2128 # Performs a line break. The current abscissa goes back to the left margin and the ordinate increases by the amount passed in parameter.
|
Chris@1296
|
2129 # @param float :h The height of the break. By default, the value equals the height of the last printed cell.
|
Chris@1296
|
2130 # @since 1.0
|
Chris@1296
|
2131 # @see Cell()
|
Chris@1296
|
2132 #
|
Chris@1296
|
2133 def Ln(h='')
|
Chris@1296
|
2134 #Line feed; default value is last cell height
|
Chris@1296
|
2135 @x=@l_margin;
|
Chris@1296
|
2136 if (h.is_a?(String))
|
Chris@1296
|
2137 @y += @lasth;
|
Chris@1296
|
2138 else
|
Chris@1296
|
2139 @y += h;
|
Chris@1296
|
2140 end
|
Chris@1296
|
2141
|
Chris@1296
|
2142 k=@k;
|
Chris@1296
|
2143 if (@y > @page_break_trigger and !@in_footer and AcceptPageBreak())
|
Chris@1296
|
2144 #Automatic page break
|
Chris@1296
|
2145 if @pages[@page+1].nil?
|
Chris@1296
|
2146 x = @x;
|
Chris@1296
|
2147 ws = @ws;
|
Chris@1296
|
2148 if (ws > 0)
|
Chris@1296
|
2149 @ws = 0;
|
Chris@1296
|
2150 out('0 Tw');
|
Chris@1296
|
2151 end
|
Chris@1296
|
2152 AddPage(@cur_orientation);
|
Chris@1296
|
2153 @x = x;
|
Chris@1296
|
2154 if (ws > 0)
|
Chris@1296
|
2155 @ws = ws;
|
Chris@1296
|
2156 out(sprintf('%.3f Tw', ws * k));
|
Chris@1296
|
2157 end
|
Chris@1296
|
2158 else
|
Chris@1296
|
2159 @page += 1;
|
Chris@1296
|
2160 @y=@t_margin;
|
Chris@1296
|
2161 end
|
Chris@1296
|
2162 end
|
Chris@1296
|
2163
|
Chris@1296
|
2164 end
|
Chris@1296
|
2165 alias_method :ln, :Ln
|
Chris@1296
|
2166
|
Chris@1296
|
2167 #
|
Chris@1296
|
2168 # Returns the abscissa of the current position.
|
Chris@1296
|
2169 # @return float
|
Chris@1296
|
2170 # @since 1.2
|
Chris@1296
|
2171 # @see SetX(), GetY(), SetY()
|
Chris@1296
|
2172 #
|
Chris@1296
|
2173 def GetX()
|
Chris@1296
|
2174 #Get x position
|
Chris@1296
|
2175 return @x;
|
Chris@1296
|
2176 end
|
Chris@1296
|
2177 alias_method :get_x, :GetX
|
Chris@1296
|
2178
|
Chris@1296
|
2179 #
|
Chris@1296
|
2180 # Defines the abscissa of the current position. If the passed value is negative, it is relative to the right of the page.
|
Chris@1296
|
2181 # @param float :x The value of the abscissa.
|
Chris@1296
|
2182 # @since 1.2
|
Chris@1296
|
2183 # @see GetX(), GetY(), SetY(), SetXY()
|
Chris@1296
|
2184 #
|
Chris@1296
|
2185 def SetX(x)
|
Chris@1296
|
2186 #Set x position
|
Chris@1296
|
2187 if (x>=0)
|
Chris@1296
|
2188 @x = x;
|
Chris@1296
|
2189 else
|
Chris@1296
|
2190 @x=@w+x;
|
Chris@1296
|
2191 end
|
Chris@1296
|
2192 end
|
Chris@1296
|
2193 alias_method :set_x, :SetX
|
Chris@1296
|
2194
|
Chris@1296
|
2195 #
|
Chris@1296
|
2196 # Returns the ordinate of the current position.
|
Chris@1296
|
2197 # @return float
|
Chris@1296
|
2198 # @since 1.0
|
Chris@1296
|
2199 # @see SetY(), GetX(), SetX()
|
Chris@1296
|
2200 #
|
Chris@1296
|
2201 def GetY()
|
Chris@1296
|
2202 #Get y position
|
Chris@1296
|
2203 return @y;
|
Chris@1296
|
2204 end
|
Chris@1296
|
2205 alias_method :get_y, :GetY
|
Chris@1296
|
2206
|
Chris@1296
|
2207 #
|
Chris@1296
|
2208 # Moves the current abscissa back to the left margin and sets the ordinate. If the passed value is negative, it is relative to the bottom of the page.
|
Chris@1296
|
2209 # @param float :y The value of the ordinate.
|
Chris@1296
|
2210 # @since 1.0
|
Chris@1296
|
2211 # @see GetX(), GetY(), SetY(), SetXY()
|
Chris@1296
|
2212 #
|
Chris@1296
|
2213 def SetY(y)
|
Chris@1296
|
2214 #Set y position and reset x
|
Chris@1296
|
2215 @x=@l_margin;
|
Chris@1296
|
2216 if (y>=0)
|
Chris@1296
|
2217 @y = y;
|
Chris@1296
|
2218 else
|
Chris@1296
|
2219 @y=@h+y;
|
Chris@1296
|
2220 end
|
Chris@1296
|
2221 end
|
Chris@1296
|
2222 alias_method :set_y, :SetY
|
Chris@1296
|
2223
|
Chris@1296
|
2224 #
|
Chris@1296
|
2225 # Defines the abscissa and ordinate of the current position. If the passed values are negative, they are relative respectively to the right and bottom of the page.
|
Chris@1296
|
2226 # @param float :x The value of the abscissa
|
Chris@1296
|
2227 # @param float :y The value of the ordinate
|
Chris@1296
|
2228 # @since 1.2
|
Chris@1296
|
2229 # @see SetX(), SetY()
|
Chris@1296
|
2230 #
|
Chris@1296
|
2231 def SetXY(x, y)
|
Chris@1296
|
2232 #Set x and y positions
|
Chris@1296
|
2233 SetY(y);
|
Chris@1296
|
2234 SetX(x);
|
Chris@1296
|
2235 end
|
Chris@1296
|
2236 alias_method :set_xy, :SetXY
|
Chris@1296
|
2237
|
Chris@1296
|
2238 #
|
Chris@1296
|
2239 # Send the document to a given destination: string, local file or browser. In the last case, the plug-in may be used (if present) or a download ("Save as" dialog box) may be forced.<br />
|
Chris@1296
|
2240 # The method first calls Close() if necessary to terminate the document.
|
Chris@1296
|
2241 # @param string :name The name of the file. If not given, the document will be sent to the browser (destination I) with the name doc.pdf.
|
Chris@1296
|
2242 # @param string :dest Destination where to send the document. It can take one of the following values:<ul><li>I: send the file inline to the browser. The plug-in is used if available. The name given by name is used when one selects the "Save as" option on the link generating the PDF.</li><li>D: send to the browser and force a file download with the name given by name.</li><li>F: save to a local file with the name given by name.</li><li>S: return the document as a string. name is ignored.</li></ul>If the parameter is not specified but a name is given, destination is F. If no parameter is specified at all, destination is I.<br />
|
Chris@1296
|
2243 # @since 1.0
|
Chris@1296
|
2244 # @see Close()
|
Chris@1296
|
2245 #
|
Chris@1296
|
2246 def Output(name='', dest='')
|
Chris@1296
|
2247 #Output PDF to some destination
|
Chris@1296
|
2248 #Finish document if necessary
|
Chris@1296
|
2249 if (@state < 3)
|
Chris@1296
|
2250 Close();
|
Chris@1296
|
2251 end
|
Chris@1296
|
2252 #Normalize parameters
|
Chris@1296
|
2253 # Boolean no longer supported
|
Chris@1296
|
2254 # if (dest.is_a?(Boolean))
|
Chris@1296
|
2255 # dest = dest ? 'D' : 'F';
|
Chris@1296
|
2256 # end
|
Chris@1296
|
2257 dest = dest.upcase
|
Chris@1296
|
2258 if (dest=='')
|
Chris@1296
|
2259 if (name=='')
|
Chris@1296
|
2260 name='doc.pdf';
|
Chris@1296
|
2261 dest='I';
|
Chris@1296
|
2262 else
|
Chris@1296
|
2263 dest='F';
|
Chris@1296
|
2264 end
|
Chris@1296
|
2265 end
|
Chris@1296
|
2266 case (dest)
|
Chris@1296
|
2267 when 'I'
|
Chris@1296
|
2268 # This is PHP specific code
|
Chris@1296
|
2269 ##Send to standard output
|
Chris@1296
|
2270 # if (ob_get_contents())
|
Chris@1296
|
2271 # Error('Some data has already been output, can\'t send PDF file');
|
Chris@1296
|
2272 # end
|
Chris@1296
|
2273 # if (php_sapi_name()!='cli')
|
Chris@1296
|
2274 # #We send to a browser
|
Chris@1296
|
2275 # header('Content-Type: application/pdf');
|
Chris@1296
|
2276 # if (headers_sent())
|
Chris@1296
|
2277 # Error('Some data has already been output to browser, can\'t send PDF file');
|
Chris@1296
|
2278 # end
|
Chris@1296
|
2279 # header('Content-Length: ' + @buffer.length);
|
Chris@1296
|
2280 # header('Content-disposition: inline; filename="' + name + '"');
|
Chris@1296
|
2281 # end
|
Chris@1296
|
2282 return @buffer;
|
Chris@1296
|
2283
|
Chris@1296
|
2284 when 'D'
|
Chris@1296
|
2285 # PHP specific
|
Chris@1296
|
2286 #Download file
|
Chris@1296
|
2287 # if (ob_get_contents())
|
Chris@1296
|
2288 # Error('Some data has already been output, can\'t send PDF file');
|
Chris@1296
|
2289 # end
|
Chris@1296
|
2290 # if (!_SERVER['HTTP_USER_AGENT'].nil? && SERVER['HTTP_USER_AGENT'].include?('MSIE'))
|
Chris@1296
|
2291 # header('Content-Type: application/force-download');
|
Chris@1296
|
2292 # else
|
Chris@1296
|
2293 # header('Content-Type: application/octet-stream');
|
Chris@1296
|
2294 # end
|
Chris@1296
|
2295 # if (headers_sent())
|
Chris@1296
|
2296 # Error('Some data has already been output to browser, can\'t send PDF file');
|
Chris@1296
|
2297 # end
|
Chris@1296
|
2298 # header('Content-Length: '+ @buffer.length);
|
Chris@1296
|
2299 # header('Content-disposition: attachment; filename="' + name + '"');
|
Chris@1296
|
2300 return @buffer;
|
Chris@1296
|
2301
|
Chris@1296
|
2302 when 'F'
|
Chris@1296
|
2303 open(name,'wb') do |f|
|
Chris@1296
|
2304 f.write(@buffer)
|
Chris@1296
|
2305 end
|
Chris@1296
|
2306 # PHP code
|
Chris@1296
|
2307 # #Save to local file
|
Chris@1296
|
2308 # f=open(name,'wb');
|
Chris@1296
|
2309 # if (!f)
|
Chris@1296
|
2310 # Error('Unable to create output file: ' + name);
|
Chris@1296
|
2311 # end
|
Chris@1296
|
2312 # fwrite(f,@buffer,@buffer.length);
|
Chris@1296
|
2313 # f.close
|
Chris@1296
|
2314
|
Chris@1296
|
2315 when 'S'
|
Chris@1296
|
2316 #Return as a string
|
Chris@1296
|
2317 return @buffer;
|
Chris@1296
|
2318 else
|
Chris@1296
|
2319 Error('Incorrect output destination: ' + dest);
|
Chris@1296
|
2320
|
Chris@1296
|
2321 end
|
Chris@1296
|
2322 return '';
|
Chris@1296
|
2323 end
|
Chris@1296
|
2324 alias_method :output, :Output
|
Chris@1296
|
2325
|
Chris@1296
|
2326 # Protected methods
|
Chris@1296
|
2327
|
Chris@1296
|
2328 #
|
Chris@1296
|
2329 # Check for locale-related bug
|
Chris@1296
|
2330 # @access protected
|
Chris@1296
|
2331 #
|
Chris@1296
|
2332 def dochecks()
|
Chris@1296
|
2333 #Check for locale-related bug
|
Chris@1296
|
2334 if (1.1==1)
|
Chris@1296
|
2335 Error('Don\'t alter the locale before including class file');
|
Chris@1296
|
2336 end
|
Chris@1296
|
2337 #Check for decimal separator
|
Chris@1296
|
2338 if (sprintf('%.1f',1.0)!='1.0')
|
Chris@1296
|
2339 setlocale(LC_NUMERIC,'C');
|
Chris@1296
|
2340 end
|
Chris@1296
|
2341 end
|
Chris@1296
|
2342
|
Chris@1296
|
2343 #
|
Chris@1296
|
2344 # Return fonts path
|
Chris@1296
|
2345 # @access protected
|
Chris@1296
|
2346 #
|
Chris@1296
|
2347 def getfontpath(file)
|
Chris@1296
|
2348 # Is it in the @@font_path?
|
Chris@1296
|
2349 if @@font_path
|
Chris@1296
|
2350 fpath = File.join @@font_path, file
|
Chris@1296
|
2351 if File.exists?(fpath)
|
Chris@1296
|
2352 return fpath
|
Chris@1296
|
2353 end
|
Chris@1296
|
2354 end
|
Chris@1296
|
2355 # Is it in this plugin's font folder?
|
Chris@1296
|
2356 fpath = File.join File.dirname(__FILE__), 'fonts', file
|
Chris@1296
|
2357 if File.exists?(fpath)
|
Chris@1296
|
2358 return fpath
|
Chris@1296
|
2359 end
|
Chris@1296
|
2360 # Could not find it.
|
Chris@1296
|
2361 nil
|
Chris@1296
|
2362 end
|
Chris@1296
|
2363
|
Chris@1296
|
2364 #
|
Chris@1296
|
2365 # Start document
|
Chris@1296
|
2366 # @access protected
|
Chris@1296
|
2367 #
|
Chris@1296
|
2368 def begindoc()
|
Chris@1296
|
2369 #Start document
|
Chris@1296
|
2370 @state=1;
|
Chris@1296
|
2371 out('%PDF-1.3');
|
Chris@1296
|
2372 end
|
Chris@1296
|
2373
|
Chris@1296
|
2374 #
|
Chris@1296
|
2375 # putpages
|
Chris@1296
|
2376 # @access protected
|
Chris@1296
|
2377 #
|
Chris@1296
|
2378 def putpages()
|
Chris@1296
|
2379 nb = @page;
|
Chris@1296
|
2380 if (@alias_nb_pages)
|
Chris@1296
|
2381 nbstr = UTF8ToUTF16BE(nb.to_s, false);
|
Chris@1296
|
2382 #Replace number of pages
|
Chris@1296
|
2383 1.upto(nb) do |n|
|
Chris@1296
|
2384 @pages[n].gsub!(@alias_nb_pages, nbstr)
|
Chris@1296
|
2385 end
|
Chris@1296
|
2386 end
|
Chris@1296
|
2387 if @def_orientation=='P'
|
Chris@1296
|
2388 w_pt=@fw_pt
|
Chris@1296
|
2389 h_pt=@fh_pt
|
Chris@1296
|
2390 else
|
Chris@1296
|
2391 w_pt=@fh_pt
|
Chris@1296
|
2392 h_pt=@fw_pt
|
Chris@1296
|
2393 end
|
Chris@1296
|
2394 filter=(@compress) ? '/Filter /FlateDecode ' : ''
|
Chris@1296
|
2395 1.upto(nb) do |n|
|
Chris@1296
|
2396 #Page
|
Chris@1296
|
2397 newobj
|
Chris@1296
|
2398 out('<</Type /Page')
|
Chris@1296
|
2399 out('/Parent 1 0 R')
|
Chris@1296
|
2400 unless @orientation_changes[n].nil?
|
Chris@1296
|
2401 out(sprintf('/MediaBox [0 0 %.2f %.2f]', h_pt, w_pt))
|
Chris@1296
|
2402 end
|
Chris@1296
|
2403 out('/Resources 2 0 R')
|
Chris@1296
|
2404 if @page_links[n]
|
Chris@1296
|
2405 #Links
|
Chris@1296
|
2406 annots='/Annots ['
|
Chris@1296
|
2407 @page_links[n].each do |pl|
|
Chris@1296
|
2408 rect=sprintf('%.2f %.2f %.2f %.2f', pl[0], pl[1], pl[0]+pl[2], pl[1]-pl[3]);
|
Chris@1296
|
2409 annots<<'<</Type /Annot /Subtype /Link /Rect [' + rect + '] /Border [0 0 0] ';
|
Chris@1296
|
2410 if (pl[4].is_a?(String))
|
Chris@1296
|
2411 annots<<'/A <</S /URI /URI (' + escape(pl[4]) + ')>>>>';
|
Chris@1296
|
2412 else
|
Chris@1296
|
2413 l=@links[pl[4]];
|
Chris@1296
|
2414 h=!@orientation_changes[l[0]].nil? ? w_pt : h_pt;
|
Chris@1296
|
2415 annots<<sprintf('/Dest [%d 0 R /XYZ 0 %.2f null]>>',1+2*l[0], h-l[1]*@k);
|
Chris@1296
|
2416 end
|
Chris@1296
|
2417 end
|
Chris@1296
|
2418 out(annots + ']');
|
Chris@1296
|
2419 end
|
Chris@1296
|
2420 out('/Contents ' + (@n+1).to_s + ' 0 R>>');
|
Chris@1296
|
2421 out('endobj');
|
Chris@1296
|
2422 #Page content
|
Chris@1296
|
2423 p=(@compress) ? gzcompress(@pages[n]) : @pages[n];
|
Chris@1296
|
2424 newobj();
|
Chris@1296
|
2425 out('<<' + filter + '/Length '+ p.length.to_s + '>>');
|
Chris@1296
|
2426 putstream(p);
|
Chris@1296
|
2427 out('endobj');
|
Chris@1296
|
2428 end
|
Chris@1296
|
2429 #Pages root
|
Chris@1296
|
2430 @offsets[1]=@buffer.length;
|
Chris@1296
|
2431 out('1 0 obj');
|
Chris@1296
|
2432 out('<</Type /Pages');
|
Chris@1296
|
2433 kids='/Kids [';
|
Chris@1296
|
2434 0.upto(nb) do |i|
|
Chris@1296
|
2435 kids<<(3+2*i).to_s + ' 0 R ';
|
Chris@1296
|
2436 end
|
Chris@1296
|
2437 out(kids + ']');
|
Chris@1296
|
2438 out('/Count ' + nb.to_s);
|
Chris@1296
|
2439 out(sprintf('/MediaBox [0 0 %.2f %.2f]', w_pt, h_pt));
|
Chris@1296
|
2440 out('>>');
|
Chris@1296
|
2441 out('endobj');
|
Chris@1296
|
2442 end
|
Chris@1296
|
2443
|
Chris@1296
|
2444 #
|
Chris@1296
|
2445 # Adds fonts
|
Chris@1296
|
2446 # putfonts
|
Chris@1296
|
2447 # @access protected
|
Chris@1296
|
2448 #
|
Chris@1296
|
2449 def putfonts()
|
Chris@1296
|
2450 nf=@n;
|
Chris@1296
|
2451 @diffs.each do |diff|
|
Chris@1296
|
2452 #Encodings
|
Chris@1296
|
2453 newobj();
|
Chris@1296
|
2454 out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [' + diff + ']>>');
|
Chris@1296
|
2455 out('endobj');
|
Chris@1296
|
2456 end
|
Chris@1296
|
2457 @font_files.each do |file, info|
|
Chris@1296
|
2458 #Font file embedding
|
Chris@1296
|
2459 newobj();
|
Chris@1296
|
2460 @font_files[file]['n']=@n;
|
Chris@1296
|
2461 font='';
|
Chris@1296
|
2462 open(getfontpath(file),'rb') do |f|
|
Chris@1296
|
2463 font = f.read();
|
Chris@1296
|
2464 end
|
Chris@1296
|
2465 compressed=(file[-2,2]=='.z');
|
Chris@1296
|
2466 if (!compressed && !info['length2'].nil?)
|
Chris@1296
|
2467 header=((font[0][0])==128);
|
Chris@1296
|
2468 if (header)
|
Chris@1296
|
2469 #Strip first binary header
|
Chris@1296
|
2470 font=font[6];
|
Chris@1296
|
2471 end
|
Chris@1296
|
2472 if header && (font[info['length1']][0] == 128)
|
Chris@1296
|
2473 #Strip second binary header
|
Chris@1296
|
2474 font=font[0..info['length1']] + font[info['length1']+6];
|
Chris@1296
|
2475 end
|
Chris@1296
|
2476 end
|
Chris@1296
|
2477 out('<</Length '+ font.length.to_s);
|
Chris@1296
|
2478 if (compressed)
|
Chris@1296
|
2479 out('/Filter /FlateDecode');
|
Chris@1296
|
2480 end
|
Chris@1296
|
2481 out('/Length1 ' + info['length1'].to_s);
|
Chris@1296
|
2482 if (!info['length2'].nil?)
|
Chris@1296
|
2483 out('/Length2 ' + info['length2'].to_s + ' /Length3 0');
|
Chris@1296
|
2484 end
|
Chris@1296
|
2485 out('>>');
|
Chris@1296
|
2486 open(getfontpath(file),'rb') do |f|
|
Chris@1296
|
2487 putstream(font)
|
Chris@1296
|
2488 end
|
Chris@1296
|
2489 out('endobj');
|
Chris@1296
|
2490 end
|
Chris@1296
|
2491 @fonts.each do |k, font|
|
Chris@1296
|
2492 #Font objects
|
Chris@1296
|
2493 @fonts[k]['n']=@n+1;
|
Chris@1296
|
2494 type = font['type'];
|
Chris@1296
|
2495 name = font['name'];
|
Chris@1296
|
2496 if (type=='core')
|
Chris@1296
|
2497 #Standard font
|
Chris@1296
|
2498 newobj();
|
Chris@1296
|
2499 out('<</Type /Font');
|
Chris@1296
|
2500 out('/BaseFont /' + name);
|
Chris@1296
|
2501 out('/Subtype /Type1');
|
Chris@1296
|
2502 if (name!='Symbol' && name!='ZapfDingbats')
|
Chris@1296
|
2503 out('/Encoding /WinAnsiEncoding');
|
Chris@1296
|
2504 end
|
Chris@1296
|
2505 out('>>');
|
Chris@1296
|
2506 out('endobj');
|
Chris@1296
|
2507 elsif type == 'Type0'
|
Chris@1296
|
2508 putType0(font)
|
Chris@1296
|
2509 elsif (type=='Type1' || type=='TrueType')
|
Chris@1296
|
2510 #Additional Type1 or TrueType font
|
Chris@1296
|
2511 newobj();
|
Chris@1296
|
2512 out('<</Type /Font');
|
Chris@1296
|
2513 out('/BaseFont /' + name);
|
Chris@1296
|
2514 out('/Subtype /' + type);
|
Chris@1296
|
2515 out('/FirstChar 32 /LastChar 255');
|
Chris@1296
|
2516 out('/Widths ' + (@n+1).to_s + ' 0 R');
|
Chris@1296
|
2517 out('/FontDescriptor ' + (@n+2).to_s + ' 0 R');
|
Chris@1296
|
2518 if (font['enc'])
|
Chris@1296
|
2519 if (!font['diff'].nil?)
|
Chris@1296
|
2520 out('/Encoding ' + (nf+font['diff']).to_s + ' 0 R');
|
Chris@1296
|
2521 else
|
Chris@1296
|
2522 out('/Encoding /WinAnsiEncoding');
|
Chris@1296
|
2523 end
|
Chris@1296
|
2524 end
|
Chris@1296
|
2525 out('>>');
|
Chris@1296
|
2526 out('endobj');
|
Chris@1296
|
2527 #Widths
|
Chris@1296
|
2528 newobj();
|
Chris@1296
|
2529 cw=font['cw']; # &
|
Chris@1296
|
2530 s='[';
|
Chris@1296
|
2531 32.upto(255) do |i|
|
Chris@1296
|
2532 s << cw[i.chr] + ' ';
|
Chris@1296
|
2533 end
|
Chris@1296
|
2534 out(s + ']');
|
Chris@1296
|
2535 out('endobj');
|
Chris@1296
|
2536 #Descriptor
|
Chris@1296
|
2537 newobj();
|
Chris@1296
|
2538 s='<</Type /FontDescriptor /FontName /' + name;
|
Chris@1296
|
2539 font['desc'].each do |k, v|
|
Chris@1296
|
2540 s<<' /' + k + ' ' + v;
|
Chris@1296
|
2541 end
|
Chris@1296
|
2542 file = font['file'];
|
Chris@1296
|
2543 if (file)
|
Chris@1296
|
2544 s<<' /FontFile' + (type=='Type1' ? '' : '2') + ' ' + @font_files[file]['n'] + ' 0 R';
|
Chris@1296
|
2545 end
|
Chris@1296
|
2546 out(s + '>>');
|
Chris@1296
|
2547 out('endobj');
|
Chris@1296
|
2548 else
|
Chris@1296
|
2549 #Allow for additional types
|
Chris@1296
|
2550 mtd='put' + type.downcase;
|
Chris@1296
|
2551 if (!self.respond_to?(mtd))
|
Chris@1296
|
2552 Error('Unsupported font type: ' + type)
|
Chris@1296
|
2553 else
|
Chris@1296
|
2554 self.send(mtd,font)
|
Chris@1296
|
2555 end
|
Chris@1296
|
2556 end
|
Chris@1296
|
2557 end
|
Chris@1296
|
2558 end
|
Chris@1296
|
2559
|
Chris@1296
|
2560 def putType0(font)
|
Chris@1296
|
2561 #Type0
|
Chris@1296
|
2562 newobj();
|
Chris@1296
|
2563 out('<</Type /Font')
|
Chris@1296
|
2564 out('/Subtype /Type0')
|
Chris@1296
|
2565 out('/BaseFont /'+font['name']+'-'+font['cMap'])
|
Chris@1296
|
2566 out('/Encoding /'+font['cMap'])
|
Chris@1296
|
2567 out('/DescendantFonts ['+(@n+1).to_s+' 0 R]')
|
Chris@1296
|
2568 out('>>')
|
Chris@1296
|
2569 out('endobj')
|
Chris@1296
|
2570 #CIDFont
|
Chris@1296
|
2571 newobj()
|
Chris@1296
|
2572 out('<</Type /Font')
|
Chris@1296
|
2573 out('/Subtype /CIDFontType0')
|
Chris@1296
|
2574 out('/BaseFont /'+font['name'])
|
Chris@1296
|
2575 out('/CIDSystemInfo <</Registry (Adobe) /Ordering ('+font['registry']['ordering']+') /Supplement '+font['registry']['supplement'].to_s+'>>')
|
Chris@1296
|
2576 out('/FontDescriptor '+(@n+1).to_s+' 0 R')
|
Chris@1296
|
2577 w='/W [1 ['
|
Chris@1296
|
2578 font['cw'].keys.sort.each {|key|
|
Chris@1296
|
2579 w+=font['cw'][key].to_s + " "
|
Chris@1296
|
2580 # ActionController::Base::logger.debug key.to_s
|
Chris@1296
|
2581 # ActionController::Base::logger.debug font['cw'][key].to_s
|
Chris@1296
|
2582 }
|
Chris@1296
|
2583 out(w+'] 231 325 500 631 [500] 326 389 500]')
|
Chris@1296
|
2584 out('>>')
|
Chris@1296
|
2585 out('endobj')
|
Chris@1296
|
2586 #Font descriptor
|
Chris@1296
|
2587 newobj()
|
Chris@1296
|
2588 out('<</Type /FontDescriptor')
|
Chris@1296
|
2589 out('/FontName /'+font['name'])
|
Chris@1296
|
2590 out('/Flags 6')
|
Chris@1296
|
2591 out('/FontBBox [0 -200 1000 900]')
|
Chris@1296
|
2592 out('/ItalicAngle 0')
|
Chris@1296
|
2593 out('/Ascent 800')
|
Chris@1296
|
2594 out('/Descent -200')
|
Chris@1296
|
2595 out('/CapHeight 800')
|
Chris@1296
|
2596 out('/StemV 60')
|
Chris@1296
|
2597 out('>>')
|
Chris@1296
|
2598 out('endobj')
|
Chris@1296
|
2599 end
|
Chris@1296
|
2600
|
Chris@1296
|
2601 #
|
Chris@1296
|
2602 # putimages
|
Chris@1296
|
2603 # @access protected
|
Chris@1296
|
2604 #
|
Chris@1296
|
2605 def putimages()
|
Chris@1296
|
2606 filter=(@compress) ? '/Filter /FlateDecode ' : '';
|
Chris@1296
|
2607 @images.each do |file, info| # was while(list(file, info)=each(@images))
|
Chris@1296
|
2608 newobj();
|
Chris@1296
|
2609 @images[file]['n']=@n;
|
Chris@1296
|
2610 out('<</Type /XObject');
|
Chris@1296
|
2611 out('/Subtype /Image');
|
Chris@1296
|
2612 out('/Width ' + info['w'].to_s);
|
Chris@1296
|
2613 out('/Height ' + info['h'].to_s);
|
Chris@1296
|
2614 if (info['cs']=='Indexed')
|
Chris@1296
|
2615 out('/ColorSpace [/Indexed /DeviceRGB ' + (info['pal'].length/3-1).to_s + ' ' + (@n+1).to_s + ' 0 R]');
|
Chris@1296
|
2616 else
|
Chris@1296
|
2617 out('/ColorSpace /' + info['cs']);
|
Chris@1296
|
2618 if (info['cs']=='DeviceCMYK')
|
Chris@1296
|
2619 out('/Decode [1 0 1 0 1 0 1 0]');
|
Chris@1296
|
2620 end
|
Chris@1296
|
2621 end
|
Chris@1296
|
2622 out('/BitsPerComponent ' + info['bpc'].to_s);
|
Chris@1296
|
2623 if (!info['f'].nil?)
|
Chris@1296
|
2624 out('/Filter /' + info['f']);
|
Chris@1296
|
2625 end
|
Chris@1296
|
2626 if (!info['parms'].nil?)
|
Chris@1296
|
2627 out(info['parms']);
|
Chris@1296
|
2628 end
|
Chris@1296
|
2629 if (!info['trns'].nil? and info['trns'].kind_of?(Array))
|
Chris@1296
|
2630 trns='';
|
Chris@1296
|
2631 0.upto(info['trns'].length) do |i|
|
Chris@1296
|
2632 trns << ("#{info['trns'][i]} " * 2);
|
Chris@1296
|
2633 end
|
Chris@1296
|
2634 out('/Mask [' + trns + ']');
|
Chris@1296
|
2635 end
|
Chris@1296
|
2636 out('/Length ' + info['data'].length.to_s + '>>');
|
Chris@1296
|
2637 putstream(info['data']);
|
Chris@1296
|
2638 @images[file]['data']=nil
|
Chris@1296
|
2639 out('endobj');
|
Chris@1296
|
2640 #Palette
|
Chris@1296
|
2641 if (info['cs']=='Indexed')
|
Chris@1296
|
2642 newobj();
|
Chris@1296
|
2643 pal=(@compress) ? gzcompress(info['pal']) : info['pal'];
|
Chris@1296
|
2644 out('<<' + filter + '/Length ' + pal.length.to_s + '>>');
|
Chris@1296
|
2645 putstream(pal);
|
Chris@1296
|
2646 out('endobj');
|
Chris@1296
|
2647 end
|
Chris@1296
|
2648 end
|
Chris@1296
|
2649 end
|
Chris@1296
|
2650
|
Chris@1296
|
2651 #
|
Chris@1296
|
2652 # putxobjectdict
|
Chris@1296
|
2653 # @access protected
|
Chris@1296
|
2654 #
|
Chris@1296
|
2655 def putxobjectdict()
|
Chris@1296
|
2656 @images.each_value do |image|
|
Chris@1296
|
2657 out('/I' + image['i'].to_s + ' ' + image['n'].to_s + ' 0 R');
|
Chris@1296
|
2658 end
|
Chris@1296
|
2659 end
|
Chris@1296
|
2660
|
Chris@1296
|
2661 #
|
Chris@1296
|
2662 # putresourcedict
|
Chris@1296
|
2663 # @access protected
|
Chris@1296
|
2664 #
|
Chris@1296
|
2665 def putresourcedict()
|
Chris@1296
|
2666 out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
|
Chris@1296
|
2667 out('/Font <<');
|
Chris@1296
|
2668 @fonts.each_value do |font|
|
Chris@1296
|
2669 out('/F' + font['i'].to_s + ' ' + font['n'].to_s + ' 0 R');
|
Chris@1296
|
2670 end
|
Chris@1296
|
2671 out('>>');
|
Chris@1296
|
2672 out('/XObject <<');
|
Chris@1296
|
2673 putxobjectdict();
|
Chris@1296
|
2674 out('>>');
|
Chris@1296
|
2675 end
|
Chris@1296
|
2676
|
Chris@1296
|
2677 #
|
Chris@1296
|
2678 # putresources
|
Chris@1296
|
2679 # @access protected
|
Chris@1296
|
2680 #
|
Chris@1296
|
2681 def putresources()
|
Chris@1296
|
2682 putfonts();
|
Chris@1296
|
2683 putimages();
|
Chris@1296
|
2684 #Resource dictionary
|
Chris@1296
|
2685 @offsets[2]=@buffer.length;
|
Chris@1296
|
2686 out('2 0 obj');
|
Chris@1296
|
2687 out('<<');
|
Chris@1296
|
2688 putresourcedict();
|
Chris@1296
|
2689 out('>>');
|
Chris@1296
|
2690 out('endobj');
|
Chris@1296
|
2691 end
|
Chris@1296
|
2692
|
Chris@1296
|
2693 #
|
Chris@1296
|
2694 # putinfo
|
Chris@1296
|
2695 # @access protected
|
Chris@1296
|
2696 #
|
Chris@1296
|
2697 def putinfo()
|
Chris@1296
|
2698 out('/Producer ' + textstring(PDF_PRODUCER));
|
Chris@1296
|
2699 if (!@title.nil?)
|
Chris@1296
|
2700 out('/Title ' + textstring(@title));
|
Chris@1296
|
2701 end
|
Chris@1296
|
2702 if (!@subject.nil?)
|
Chris@1296
|
2703 out('/Subject ' + textstring(@subject));
|
Chris@1296
|
2704 end
|
Chris@1296
|
2705 if (!@author.nil?)
|
Chris@1296
|
2706 out('/Author ' + textstring(@author));
|
Chris@1296
|
2707 end
|
Chris@1296
|
2708 if (!@keywords.nil?)
|
Chris@1296
|
2709 out('/Keywords ' + textstring(@keywords));
|
Chris@1296
|
2710 end
|
Chris@1296
|
2711 if (!@creator.nil?)
|
Chris@1296
|
2712 out('/Creator ' + textstring(@creator));
|
Chris@1296
|
2713 end
|
Chris@1296
|
2714 out('/CreationDate ' + textstring('D:' + Time.now.strftime('%Y%m%d%H%M%S')));
|
Chris@1296
|
2715 end
|
Chris@1296
|
2716
|
Chris@1296
|
2717 #
|
Chris@1296
|
2718 # putcatalog
|
Chris@1296
|
2719 # @access protected
|
Chris@1296
|
2720 #
|
Chris@1296
|
2721 def putcatalog()
|
Chris@1296
|
2722 out('/Type /Catalog');
|
Chris@1296
|
2723 out('/Pages 1 0 R');
|
Chris@1296
|
2724 if (@zoom_mode=='fullpage')
|
Chris@1296
|
2725 out('/OpenAction [3 0 R /Fit]');
|
Chris@1296
|
2726 elsif (@zoom_mode=='fullwidth')
|
Chris@1296
|
2727 out('/OpenAction [3 0 R /FitH null]');
|
Chris@1296
|
2728 elsif (@zoom_mode=='real')
|
Chris@1296
|
2729 out('/OpenAction [3 0 R /XYZ null null 1]');
|
Chris@1296
|
2730 elsif (!@zoom_mode.is_a?(String))
|
Chris@1296
|
2731 out('/OpenAction [3 0 R /XYZ null null ' + (@zoom_mode/100) + ']');
|
Chris@1296
|
2732 end
|
Chris@1296
|
2733 if (@layout_mode=='single')
|
Chris@1296
|
2734 out('/PageLayout /SinglePage');
|
Chris@1296
|
2735 elsif (@layout_mode=='continuous')
|
Chris@1296
|
2736 out('/PageLayout /OneColumn');
|
Chris@1296
|
2737 elsif (@layout_mode=='two')
|
Chris@1296
|
2738 out('/PageLayout /TwoColumnLeft');
|
Chris@1296
|
2739 end
|
Chris@1296
|
2740 end
|
Chris@1296
|
2741
|
Chris@1296
|
2742 #
|
Chris@1296
|
2743 # puttrailer
|
Chris@1296
|
2744 # @access protected
|
Chris@1296
|
2745 #
|
Chris@1296
|
2746 def puttrailer()
|
Chris@1296
|
2747 out('/Size ' + (@n+1).to_s);
|
Chris@1296
|
2748 out('/Root ' + @n.to_s + ' 0 R');
|
Chris@1296
|
2749 out('/Info ' + (@n-1).to_s + ' 0 R');
|
Chris@1296
|
2750 end
|
Chris@1296
|
2751
|
Chris@1296
|
2752 #
|
Chris@1296
|
2753 # putheader
|
Chris@1296
|
2754 # @access protected
|
Chris@1296
|
2755 #
|
Chris@1296
|
2756 def putheader()
|
Chris@1296
|
2757 out('%PDF-' + @pdf_version);
|
Chris@1296
|
2758 end
|
Chris@1296
|
2759
|
Chris@1296
|
2760 #
|
Chris@1296
|
2761 # enddoc
|
Chris@1296
|
2762 # @access protected
|
Chris@1296
|
2763 #
|
Chris@1296
|
2764 def enddoc()
|
Chris@1296
|
2765 putheader();
|
Chris@1296
|
2766 putpages();
|
Chris@1296
|
2767 putresources();
|
Chris@1296
|
2768 #Info
|
Chris@1296
|
2769 newobj();
|
Chris@1296
|
2770 out('<<');
|
Chris@1296
|
2771 putinfo();
|
Chris@1296
|
2772 out('>>');
|
Chris@1296
|
2773 out('endobj');
|
Chris@1296
|
2774 #Catalog
|
Chris@1296
|
2775 newobj();
|
Chris@1296
|
2776 out('<<');
|
Chris@1296
|
2777 putcatalog();
|
Chris@1296
|
2778 out('>>');
|
Chris@1296
|
2779 out('endobj');
|
Chris@1296
|
2780 #Cross-ref
|
Chris@1296
|
2781 o=@buffer.length;
|
Chris@1296
|
2782 out('xref');
|
Chris@1296
|
2783 out('0 ' + (@n+1).to_s);
|
Chris@1296
|
2784 out('0000000000 65535 f ');
|
Chris@1296
|
2785 1.upto(@n) do |i|
|
Chris@1296
|
2786 out(sprintf('%010d 00000 n ',@offsets[i]));
|
Chris@1296
|
2787 end
|
Chris@1296
|
2788 #Trailer
|
Chris@1296
|
2789 out('trailer');
|
Chris@1296
|
2790 out('<<');
|
Chris@1296
|
2791 puttrailer();
|
Chris@1296
|
2792 out('>>');
|
Chris@1296
|
2793 out('startxref');
|
Chris@1296
|
2794 out(o);
|
Chris@1296
|
2795 out('%%EOF');
|
Chris@1296
|
2796 @state=3;
|
Chris@1296
|
2797 end
|
Chris@1296
|
2798
|
Chris@1296
|
2799 #
|
Chris@1296
|
2800 # beginpage
|
Chris@1296
|
2801 # @access protected
|
Chris@1296
|
2802 #
|
Chris@1296
|
2803 def beginpage(orientation)
|
Chris@1296
|
2804 @page += 1;
|
Chris@1296
|
2805 @pages[@page]='';
|
Chris@1296
|
2806 @state=2;
|
Chris@1296
|
2807 @x=@l_margin;
|
Chris@1296
|
2808 @y=@t_margin;
|
Chris@1296
|
2809 @font_family='';
|
Chris@1296
|
2810 #Page orientation
|
Chris@1296
|
2811 if (orientation.empty?)
|
Chris@1296
|
2812 orientation=@def_orientation;
|
Chris@1296
|
2813 else
|
Chris@1296
|
2814 orientation.upcase!
|
Chris@1296
|
2815 if (orientation!=@def_orientation)
|
Chris@1296
|
2816 @orientation_changes[@page]=true;
|
Chris@1296
|
2817 end
|
Chris@1296
|
2818 end
|
Chris@1296
|
2819 if (orientation!=@cur_orientation)
|
Chris@1296
|
2820 #Change orientation
|
Chris@1296
|
2821 if (orientation=='P')
|
Chris@1296
|
2822 @w_pt=@fw_pt;
|
Chris@1296
|
2823 @h_pt=@fh_pt;
|
Chris@1296
|
2824 @w=@fw;
|
Chris@1296
|
2825 @h=@fh;
|
Chris@1296
|
2826 else
|
Chris@1296
|
2827 @w_pt=@fh_pt;
|
Chris@1296
|
2828 @h_pt=@fw_pt;
|
Chris@1296
|
2829 @w=@fh;
|
Chris@1296
|
2830 @h=@fw;
|
Chris@1296
|
2831 end
|
Chris@1296
|
2832 @page_break_trigger=@h-@b_margin;
|
Chris@1296
|
2833 @cur_orientation = orientation;
|
Chris@1296
|
2834 end
|
Chris@1296
|
2835 end
|
Chris@1296
|
2836
|
Chris@1296
|
2837 #
|
Chris@1296
|
2838 # End of page contents
|
Chris@1296
|
2839 # @access protected
|
Chris@1296
|
2840 #
|
Chris@1296
|
2841 def endpage()
|
Chris@1296
|
2842 @state=1;
|
Chris@1296
|
2843 end
|
Chris@1296
|
2844
|
Chris@1296
|
2845 #
|
Chris@1296
|
2846 # Begin a new object
|
Chris@1296
|
2847 # @access protected
|
Chris@1296
|
2848 #
|
Chris@1296
|
2849 def newobj()
|
Chris@1296
|
2850 @n += 1;
|
Chris@1296
|
2851 @offsets[@n]=@buffer.length;
|
Chris@1296
|
2852 out(@n.to_s + ' 0 obj');
|
Chris@1296
|
2853 end
|
Chris@1296
|
2854
|
Chris@1296
|
2855 #
|
Chris@1296
|
2856 # Underline and Deleted text
|
Chris@1296
|
2857 # @access protected
|
Chris@1296
|
2858 #
|
Chris@1296
|
2859 def dolinetxt(x, y, txt)
|
Chris@1296
|
2860 up = @current_font['up'];
|
Chris@1296
|
2861 ut = @current_font['ut'];
|
Chris@1296
|
2862 w = GetStringWidth(txt) + @ws * txt.count(' ');
|
Chris@1296
|
2863 sprintf('%.2f %.2f %.2f %.2f re f', x * @k, (@h - (y - up / 1000.0 * @font_size)) * @k, w * @k, -ut / 1000.0 * @font_size_pt);
|
Chris@1296
|
2864 end
|
Chris@1296
|
2865
|
Chris@1296
|
2866 #
|
Chris@1296
|
2867 # Extract info from a JPEG file
|
Chris@1296
|
2868 # @access protected
|
Chris@1296
|
2869 #
|
Chris@1296
|
2870 def parsejpg(file)
|
Chris@1296
|
2871 a=getimagesize(file);
|
Chris@1296
|
2872 if (a.empty?)
|
Chris@1296
|
2873 Error('Missing or incorrect image file: ' + file);
|
Chris@1296
|
2874 end
|
Chris@1296
|
2875 if (!a[2].nil? and a[2]!='JPEG')
|
Chris@1296
|
2876 Error('Not a JPEG file: ' + file);
|
Chris@1296
|
2877 end
|
Chris@1296
|
2878 if (a['channels'].nil? or a['channels']==3)
|
Chris@1296
|
2879 colspace='DeviceRGB';
|
Chris@1296
|
2880 elsif (a['channels']==4)
|
Chris@1296
|
2881 colspace='DeviceCMYK';
|
Chris@1296
|
2882 else
|
Chris@1296
|
2883 colspace='DeviceGray';
|
Chris@1296
|
2884 end
|
Chris@1296
|
2885 bpc=!a['bits'].nil? ? a['bits'] : 8;
|
Chris@1296
|
2886 #Read whole file
|
Chris@1296
|
2887 data='';
|
Chris@1296
|
2888
|
Chris@1296
|
2889 open(file,'rb') do |f|
|
Chris@1296
|
2890 data<<f.read();
|
Chris@1296
|
2891 end
|
Chris@1296
|
2892
|
Chris@1296
|
2893 return {'w' => a[0],'h' => a[1],'cs' => colspace,'bpc' => bpc,'f'=>'DCTDecode','data' => data}
|
Chris@1296
|
2894 end
|
Chris@1296
|
2895
|
Chris@1296
|
2896 def imageToPNG(file)
|
Chris@1296
|
2897 return unless Object.const_defined?(:Magick)
|
Chris@1296
|
2898
|
Chris@1296
|
2899 img = Magick::ImageList.new(file)
|
Chris@1296
|
2900 img.format = 'PNG' # convert to PNG from gif
|
Chris@1296
|
2901 img.opacity = 0 # PNG alpha channel delete
|
Chris@1296
|
2902
|
Chris@1296
|
2903 #use a temporary file....
|
Chris@1296
|
2904 tmpFile = Tempfile.new(['', '_' + File::basename(file) + '.png'], @@k_path_cache);
|
Chris@1296
|
2905 tmpFile.binmode
|
Chris@1296
|
2906 tmpFile.print img.to_blob
|
Chris@1296
|
2907 tmpFile
|
Chris@1296
|
2908 ensure
|
Chris@1296
|
2909 tmpFile.close
|
Chris@1296
|
2910 end
|
Chris@1296
|
2911
|
Chris@1296
|
2912 #
|
Chris@1296
|
2913 # Extract info from a PNG file
|
Chris@1296
|
2914 # @access protected
|
Chris@1296
|
2915 #
|
Chris@1296
|
2916 def parsepng(file)
|
Chris@1296
|
2917 f=open(file,'rb');
|
Chris@1296
|
2918 #Check signature
|
Chris@1296
|
2919 if (f.read(8)!=137.chr + 'PNG' + 13.chr + 10.chr + 26.chr + 10.chr)
|
Chris@1296
|
2920 Error('Not a PNG file: ' + file);
|
Chris@1296
|
2921 end
|
Chris@1296
|
2922 #Read header chunk
|
Chris@1296
|
2923 f.read(4);
|
Chris@1296
|
2924 if (f.read(4)!='IHDR')
|
Chris@1296
|
2925 Error('Incorrect PNG file: ' + file);
|
Chris@1296
|
2926 end
|
Chris@1296
|
2927 w=freadint(f);
|
Chris@1296
|
2928 h=freadint(f);
|
Chris@1296
|
2929 bpc=f.read(1).unpack('C')[0];
|
Chris@1296
|
2930 if (bpc>8)
|
Chris@1296
|
2931 Error('16-bit depth not supported: ' + file);
|
Chris@1296
|
2932 end
|
Chris@1296
|
2933 ct=f.read(1).unpack('C')[0];
|
Chris@1296
|
2934 if (ct==0)
|
Chris@1296
|
2935 colspace='DeviceGray';
|
Chris@1296
|
2936 elsif (ct==2)
|
Chris@1296
|
2937 colspace='DeviceRGB';
|
Chris@1296
|
2938 elsif (ct==3)
|
Chris@1296
|
2939 colspace='Indexed';
|
Chris@1296
|
2940 else
|
Chris@1296
|
2941 Error('Alpha channel not supported: ' + file);
|
Chris@1296
|
2942 end
|
Chris@1296
|
2943 if (f.read(1).unpack('C')[0] != 0)
|
Chris@1296
|
2944 Error('Unknown compression method: ' + file);
|
Chris@1296
|
2945 end
|
Chris@1296
|
2946 if (f.read(1).unpack('C')[0] != 0)
|
Chris@1296
|
2947 Error('Unknown filter method: ' + file);
|
Chris@1296
|
2948 end
|
Chris@1296
|
2949 if (f.read(1).unpack('C')[0] != 0)
|
Chris@1296
|
2950 Error('Interlacing not supported: ' + file);
|
Chris@1296
|
2951 end
|
Chris@1296
|
2952 f.read(4);
|
Chris@1296
|
2953 parms='/DecodeParms <</Predictor 15 /Colors ' + (ct==2 ? 3 : 1).to_s + ' /BitsPerComponent ' + bpc.to_s + ' /Columns ' + w.to_s + '>>';
|
Chris@1296
|
2954 #Scan chunks looking for palette, transparency and image data
|
Chris@1296
|
2955 pal='';
|
Chris@1296
|
2956 trns='';
|
Chris@1296
|
2957 data='';
|
Chris@1296
|
2958 begin
|
Chris@1296
|
2959 n=freadint(f);
|
Chris@1296
|
2960 type=f.read(4);
|
Chris@1296
|
2961 if (type=='PLTE')
|
Chris@1296
|
2962 #Read palette
|
Chris@1296
|
2963 pal=f.read( n);
|
Chris@1296
|
2964 f.read(4);
|
Chris@1296
|
2965 elsif (type=='tRNS')
|
Chris@1296
|
2966 #Read transparency info
|
Chris@1296
|
2967 t=f.read( n);
|
Chris@1296
|
2968 if (ct==0)
|
Chris@1296
|
2969 trns = t[1].unpack('C')[0]
|
Chris@1296
|
2970 elsif (ct==2)
|
Chris@1296
|
2971 trns = t[[1].unpack('C')[0], t[3].unpack('C')[0], t[5].unpack('C')[0]]
|
Chris@1296
|
2972 else
|
Chris@1296
|
2973 pos=t.index(0.chr);
|
Chris@1296
|
2974 unless (pos.nil?)
|
Chris@1296
|
2975 trns = [pos]
|
Chris@1296
|
2976 end
|
Chris@1296
|
2977 end
|
Chris@1296
|
2978 f.read(4);
|
Chris@1296
|
2979 elsif (type=='IDAT')
|
Chris@1296
|
2980 #Read image data block
|
Chris@1296
|
2981 data<<f.read( n);
|
Chris@1296
|
2982 f.read(4);
|
Chris@1296
|
2983 elsif (type=='IEND')
|
Chris@1296
|
2984 break;
|
Chris@1296
|
2985 else
|
Chris@1296
|
2986 f.read( n+4);
|
Chris@1296
|
2987 end
|
Chris@1296
|
2988 end while(n)
|
Chris@1296
|
2989 if (colspace=='Indexed' and pal.empty?)
|
Chris@1296
|
2990 Error('Missing palette in ' + file);
|
Chris@1296
|
2991 end
|
Chris@1296
|
2992 return {'w' => w, 'h' => h, 'cs' => colspace, 'bpc' => bpc, 'f'=>'FlateDecode', 'parms' => parms, 'pal' => pal, 'trns' => trns, 'data' => data}
|
Chris@1296
|
2993 ensure
|
Chris@1296
|
2994 f.close
|
Chris@1296
|
2995 end
|
Chris@1296
|
2996
|
Chris@1296
|
2997 #
|
Chris@1296
|
2998 # Read a 4-byte integer from file
|
Chris@1296
|
2999 # @access protected
|
Chris@1296
|
3000 #
|
Chris@1296
|
3001 def freadint(f)
|
Chris@1296
|
3002 # Read a 4-byte integer from file
|
Chris@1296
|
3003 a = f.read(4).unpack('N')
|
Chris@1296
|
3004 return a[0]
|
Chris@1296
|
3005 end
|
Chris@1296
|
3006
|
Chris@1296
|
3007 #
|
Chris@1296
|
3008 # Format a text string
|
Chris@1296
|
3009 # @access protected
|
Chris@1296
|
3010 #
|
Chris@1296
|
3011 def textstring(s)
|
Chris@1296
|
3012 if (@is_unicode)
|
Chris@1296
|
3013 #Convert string to UTF-16BE
|
Chris@1296
|
3014 s = UTF8ToUTF16BE(s, true);
|
Chris@1296
|
3015 end
|
Chris@1296
|
3016 return '(' + escape(s) + ')';
|
Chris@1296
|
3017 end
|
Chris@1296
|
3018
|
Chris@1296
|
3019 #
|
Chris@1296
|
3020 # Format a text string
|
Chris@1296
|
3021 # @access protected
|
Chris@1296
|
3022 #
|
Chris@1296
|
3023 def escapetext(s)
|
Chris@1296
|
3024 if (@is_unicode)
|
Chris@1296
|
3025 #Convert string to UTF-16BE
|
Chris@1296
|
3026 s = UTF8ToUTF16BE(s, false);
|
Chris@1296
|
3027 end
|
Chris@1296
|
3028 return escape(s);
|
Chris@1296
|
3029 end
|
Chris@1296
|
3030
|
Chris@1296
|
3031 #
|
Chris@1296
|
3032 # Add \ before \, ( and )
|
Chris@1296
|
3033 # @access protected
|
Chris@1296
|
3034 #
|
Chris@1296
|
3035 def escape(s)
|
Chris@1296
|
3036 # Add \ before \, ( and )
|
Chris@1296
|
3037 s.gsub('\\','\\\\\\').gsub('(','\\(').gsub(')','\\)').gsub(13.chr, '\r')
|
Chris@1296
|
3038 end
|
Chris@1296
|
3039
|
Chris@1296
|
3040 #
|
Chris@1296
|
3041 #
|
Chris@1296
|
3042 # @access protected
|
Chris@1296
|
3043 #
|
Chris@1296
|
3044 def putstream(s)
|
Chris@1296
|
3045 out('stream');
|
Chris@1296
|
3046 out(s);
|
Chris@1296
|
3047 out('endstream');
|
Chris@1296
|
3048 end
|
Chris@1296
|
3049
|
Chris@1296
|
3050 #
|
Chris@1296
|
3051 # Add a line to the document
|
Chris@1296
|
3052 # @access protected
|
Chris@1296
|
3053 #
|
Chris@1296
|
3054 def out(s)
|
Chris@1296
|
3055 if (@state==2)
|
Chris@1296
|
3056 @pages[@page] << s.to_s + "\n";
|
Chris@1296
|
3057 else
|
Chris@1296
|
3058 @buffer << s.to_s + "\n";
|
Chris@1296
|
3059 end
|
Chris@1296
|
3060 end
|
Chris@1296
|
3061
|
Chris@1296
|
3062 #
|
Chris@1296
|
3063 # Adds unicode fonts.<br>
|
Chris@1296
|
3064 # Based on PDF Reference 1.3 (section 5)
|
Chris@1296
|
3065 # @access protected
|
Chris@1296
|
3066 # @author Nicola Asuni
|
Chris@1296
|
3067 # @since 1.52.0.TC005 (2005-01-05)
|
Chris@1296
|
3068 #
|
Chris@1296
|
3069 def puttruetypeunicode(font)
|
Chris@1296
|
3070 # Type0 Font
|
Chris@1296
|
3071 # A composite font composed of other fonts, organized hierarchically
|
Chris@1296
|
3072 newobj();
|
Chris@1296
|
3073 out('<</Type /Font');
|
Chris@1296
|
3074 out('/Subtype /Type0');
|
Chris@1296
|
3075 out('/BaseFont /' + font['name'] + '');
|
Chris@1296
|
3076 out('/Encoding /Identity-H'); #The horizontal identity mapping for 2-byte CIDs; may be used with CIDFonts using any Registry, Ordering, and Supplement values.
|
Chris@1296
|
3077 out('/DescendantFonts [' + (@n + 1).to_s + ' 0 R]');
|
Chris@1296
|
3078 out('/ToUnicode ' + (@n + 2).to_s + ' 0 R');
|
Chris@1296
|
3079 out('>>');
|
Chris@1296
|
3080 out('endobj');
|
Chris@1296
|
3081
|
Chris@1296
|
3082 # CIDFontType2
|
Chris@1296
|
3083 # A CIDFont whose glyph descriptions are based on TrueType font technology
|
Chris@1296
|
3084 newobj();
|
Chris@1296
|
3085 out('<</Type /Font');
|
Chris@1296
|
3086 out('/Subtype /CIDFontType2');
|
Chris@1296
|
3087 out('/BaseFont /' + font['name'] + '');
|
Chris@1296
|
3088 out('/CIDSystemInfo ' + (@n + 2).to_s + ' 0 R');
|
Chris@1296
|
3089 out('/FontDescriptor ' + (@n + 3).to_s + ' 0 R');
|
Chris@1296
|
3090 if (!font['desc']['MissingWidth'].nil?)
|
Chris@1296
|
3091 out('/DW ' + font['desc']['MissingWidth'].to_s + ''); # The default width for glyphs in the CIDFont MissingWidth
|
Chris@1296
|
3092 end
|
Chris@1296
|
3093 w = "";
|
Chris@1296
|
3094 font['cw'].each do |cid, width|
|
Chris@1296
|
3095 w << '' + cid.to_s + ' [' + width.to_s + '] '; # define a specific width for each individual CID
|
Chris@1296
|
3096 end
|
Chris@1296
|
3097 out('/W [' + w + ']'); # A description of the widths for the glyphs in the CIDFont
|
Chris@1296
|
3098 out('/CIDToGIDMap ' + (@n + 4).to_s + ' 0 R');
|
Chris@1296
|
3099 out('>>');
|
Chris@1296
|
3100 out('endobj');
|
Chris@1296
|
3101
|
Chris@1296
|
3102 # ToUnicode
|
Chris@1296
|
3103 # is a stream object that contains the definition of the CMap
|
Chris@1296
|
3104 # (PDF Reference 1.3 chap. 5.9)
|
Chris@1296
|
3105 newobj();
|
Chris@1296
|
3106 out('<</Length 383>>');
|
Chris@1296
|
3107 out('stream');
|
Chris@1296
|
3108 out('/CIDInit /ProcSet findresource begin');
|
Chris@1296
|
3109 out('12 dict begin');
|
Chris@1296
|
3110 out('begincmap');
|
Chris@1296
|
3111 out('/CIDSystemInfo');
|
Chris@1296
|
3112 out('<</Registry (Adobe)');
|
Chris@1296
|
3113 out('/Ordering (UCS)');
|
Chris@1296
|
3114 out('/Supplement 0');
|
Chris@1296
|
3115 out('>> def');
|
Chris@1296
|
3116 out('/CMapName /Adobe-Identity-UCS def');
|
Chris@1296
|
3117 out('/CMapType 2 def');
|
Chris@1296
|
3118 out('1 begincodespacerange');
|
Chris@1296
|
3119 out('<0000> <FFFF>');
|
Chris@1296
|
3120 out('endcodespacerange');
|
Chris@1296
|
3121 out('1 beginbfrange');
|
Chris@1296
|
3122 out('<0000> <FFFF> <0000>');
|
Chris@1296
|
3123 out('endbfrange');
|
Chris@1296
|
3124 out('endcmap');
|
Chris@1296
|
3125 out('CMapName currentdict /CMap defineresource pop');
|
Chris@1296
|
3126 out('end');
|
Chris@1296
|
3127 out('end');
|
Chris@1296
|
3128 out('endstream');
|
Chris@1296
|
3129 out('endobj');
|
Chris@1296
|
3130
|
Chris@1296
|
3131 # CIDSystemInfo dictionary
|
Chris@1296
|
3132 # A dictionary containing entries that define the character collection of the CIDFont.
|
Chris@1296
|
3133 newobj();
|
Chris@1296
|
3134 out('<</Registry (Adobe)'); # A string identifying an issuer of character collections
|
Chris@1296
|
3135 out('/Ordering (UCS)'); # A string that uniquely names a character collection issued by a specific registry
|
Chris@1296
|
3136 out('/Supplement 0'); # The supplement number of the character collection.
|
Chris@1296
|
3137 out('>>');
|
Chris@1296
|
3138 out('endobj');
|
Chris@1296
|
3139
|
Chris@1296
|
3140 # Font descriptor
|
Chris@1296
|
3141 # A font descriptor describing the CIDFont default metrics other than its glyph widths
|
Chris@1296
|
3142 newobj();
|
Chris@1296
|
3143 out('<</Type /FontDescriptor');
|
Chris@1296
|
3144 out('/FontName /' + font['name']);
|
Chris@1296
|
3145 font['desc'].each do |key, value|
|
Chris@1296
|
3146 out('/' + key.to_s + ' ' + value.to_s);
|
Chris@1296
|
3147 end
|
Chris@1296
|
3148 if (font['file'])
|
Chris@1296
|
3149 # A stream containing a TrueType font program
|
Chris@1296
|
3150 out('/FontFile2 ' + @font_files[font['file']]['n'].to_s + ' 0 R');
|
Chris@1296
|
3151 end
|
Chris@1296
|
3152 out('>>');
|
Chris@1296
|
3153 out('endobj');
|
Chris@1296
|
3154
|
Chris@1296
|
3155 # Embed CIDToGIDMap
|
Chris@1296
|
3156 # A specification of the mapping from CIDs to glyph indices
|
Chris@1296
|
3157 newobj();
|
Chris@1296
|
3158 ctgfile = getfontpath(font['ctg'])
|
Chris@1296
|
3159 if (!ctgfile)
|
Chris@1296
|
3160 Error('Font file not found: ' + ctgfile);
|
Chris@1296
|
3161 end
|
Chris@1296
|
3162 size = File.size(ctgfile);
|
Chris@1296
|
3163 out('<</Length ' + size.to_s + '');
|
Chris@1296
|
3164 if (ctgfile[-2,2] == '.z') # check file extension
|
Chris@1296
|
3165 # Decompresses data encoded using the public-domain
|
Chris@1296
|
3166 # zlib/deflate compression method, reproducing the
|
Chris@1296
|
3167 # original text or binary data#
|
Chris@1296
|
3168 out('/Filter /FlateDecode');
|
Chris@1296
|
3169 end
|
Chris@1296
|
3170 out('>>');
|
Chris@1296
|
3171 open(ctgfile, "rb") do |f|
|
Chris@1296
|
3172 putstream(f.read())
|
Chris@1296
|
3173 end
|
Chris@1296
|
3174 out('endobj');
|
Chris@1296
|
3175 end
|
Chris@1296
|
3176
|
Chris@1296
|
3177 #
|
Chris@1296
|
3178 # Converts UTF-8 strings to codepoints array.<br>
|
Chris@1296
|
3179 # Invalid byte sequences will be replaced with 0xFFFD (replacement character)<br>
|
Chris@1296
|
3180 # Based on: http://www.faqs.org/rfcs/rfc3629.html
|
Chris@1296
|
3181 # <pre>
|
Chris@1296
|
3182 # Char. number range | UTF-8 octet sequence
|
Chris@1296
|
3183 # (hexadecimal) | (binary)
|
Chris@1296
|
3184 # --------------------+-----------------------------------------------
|
Chris@1296
|
3185 # 0000 0000-0000 007F | 0xxxxxxx
|
Chris@1296
|
3186 # 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
Chris@1296
|
3187 # 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
Chris@1296
|
3188 # 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
Chris@1296
|
3189 # ---------------------------------------------------------------------
|
Chris@1296
|
3190 #
|
Chris@1296
|
3191 # ABFN notation:
|
Chris@1296
|
3192 # ---------------------------------------------------------------------
|
Chris@1296
|
3193 # UTF8-octets =#( UTF8-char )
|
Chris@1296
|
3194 # UTF8-char = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
|
Chris@1296
|
3195 # UTF8-1 = %x00-7F
|
Chris@1296
|
3196 # UTF8-2 = %xC2-DF UTF8-tail
|
Chris@1296
|
3197 #
|
Chris@1296
|
3198 # UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
|
Chris@1296
|
3199 # %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
|
Chris@1296
|
3200 # UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
|
Chris@1296
|
3201 # %xF4 %x80-8F 2( UTF8-tail )
|
Chris@1296
|
3202 # UTF8-tail = %x80-BF
|
Chris@1296
|
3203 # ---------------------------------------------------------------------
|
Chris@1296
|
3204 # </pre>
|
Chris@1296
|
3205 # @param string :str string to process.
|
Chris@1296
|
3206 # @return array containing codepoints (UTF-8 characters values)
|
Chris@1296
|
3207 # @access protected
|
Chris@1296
|
3208 # @author Nicola Asuni
|
Chris@1296
|
3209 # @since 1.53.0.TC005 (2005-01-05)
|
Chris@1296
|
3210 #
|
Chris@1296
|
3211 def UTF8StringToArray(str)
|
Chris@1296
|
3212 if (!@is_unicode)
|
Chris@1296
|
3213 return str; # string is not in unicode
|
Chris@1296
|
3214 end
|
Chris@1296
|
3215
|
Chris@1296
|
3216 unicode = [] # array containing unicode values
|
Chris@1296
|
3217 bytes = [] # array containing single character byte sequences
|
Chris@1296
|
3218 numbytes = 1; # number of octetc needed to represent the UTF-8 character
|
Chris@1296
|
3219
|
Chris@1296
|
3220 str = str.to_s; # force :str to be a string
|
Chris@1296
|
3221
|
Chris@1296
|
3222 str.each_byte do |char|
|
Chris@1296
|
3223 if (bytes.length == 0) # get starting octect
|
Chris@1296
|
3224 if (char <= 0x7F)
|
Chris@1296
|
3225 unicode << char # use the character "as is" because is ASCII
|
Chris@1296
|
3226 numbytes = 1
|
Chris@1296
|
3227 elsif ((char >> 0x05) == 0x06) # 2 bytes character (0x06 = 110 BIN)
|
Chris@1296
|
3228 bytes << ((char - 0xC0) << 0x06)
|
Chris@1296
|
3229 numbytes = 2
|
Chris@1296
|
3230 elsif ((char >> 0x04) == 0x0E) # 3 bytes character (0x0E = 1110 BIN)
|
Chris@1296
|
3231 bytes << ((char - 0xE0) << 0x0C)
|
Chris@1296
|
3232 numbytes = 3
|
Chris@1296
|
3233 elsif ((char >> 0x03) == 0x1E) # 4 bytes character (0x1E = 11110 BIN)
|
Chris@1296
|
3234 bytes << ((char - 0xF0) << 0x12)
|
Chris@1296
|
3235 numbytes = 4
|
Chris@1296
|
3236 else
|
Chris@1296
|
3237 # use replacement character for other invalid sequences
|
Chris@1296
|
3238 unicode << 0xFFFD
|
Chris@1296
|
3239 bytes = []
|
Chris@1296
|
3240 numbytes = 1
|
Chris@1296
|
3241 end
|
Chris@1296
|
3242 elsif ((char >> 0x06) == 0x02) # bytes 2, 3 and 4 must start with 0x02 = 10 BIN
|
Chris@1296
|
3243 bytes << (char - 0x80)
|
Chris@1296
|
3244 if (bytes.length == numbytes)
|
Chris@1296
|
3245 # compose UTF-8 bytes to a single unicode value
|
Chris@1296
|
3246 char = bytes[0]
|
Chris@1296
|
3247 1.upto(numbytes-1) do |j|
|
Chris@1296
|
3248 char += (bytes[j] << ((numbytes - j - 1) * 0x06))
|
Chris@1296
|
3249 end
|
Chris@1296
|
3250 if (((char >= 0xD800) and (char <= 0xDFFF)) or (char >= 0x10FFFF))
|
Chris@1296
|
3251 # The definition of UTF-8 prohibits encoding character numbers between
|
Chris@1296
|
3252 # U+D800 and U+DFFF, which are reserved for use with the UTF-16
|
Chris@1296
|
3253 # encoding form (as surrogate pairs) and do not directly represent
|
Chris@1296
|
3254 # characters
|
Chris@1296
|
3255 unicode << 0xFFFD; # use replacement character
|
Chris@1296
|
3256 else
|
Chris@1296
|
3257 unicode << char; # add char to array
|
Chris@1296
|
3258 end
|
Chris@1296
|
3259 # reset data for next char
|
Chris@1296
|
3260 bytes = []
|
Chris@1296
|
3261 numbytes = 1;
|
Chris@1296
|
3262 end
|
Chris@1296
|
3263 else
|
Chris@1296
|
3264 # use replacement character for other invalid sequences
|
Chris@1296
|
3265 unicode << 0xFFFD;
|
Chris@1296
|
3266 bytes = []
|
Chris@1296
|
3267 numbytes = 1;
|
Chris@1296
|
3268 end
|
Chris@1296
|
3269 end
|
Chris@1296
|
3270 return unicode;
|
Chris@1296
|
3271 end
|
Chris@1296
|
3272
|
Chris@1296
|
3273 #
|
Chris@1296
|
3274 # Converts UTF-8 strings to UTF16-BE.<br>
|
Chris@1296
|
3275 # Based on: http://www.faqs.org/rfcs/rfc2781.html
|
Chris@1296
|
3276 # <pre>
|
Chris@1296
|
3277 # Encoding UTF-16:
|
Chris@1296
|
3278 #
|
Chris@1296
|
3279 # Encoding of a single character from an ISO 10646 character value to
|
Chris@1296
|
3280 # UTF-16 proceeds as follows. Let U be the character number, no greater
|
Chris@1296
|
3281 # than 0x10FFFF.
|
Chris@1296
|
3282 #
|
Chris@1296
|
3283 # 1) If U < 0x10000, encode U as a 16-bit unsigned integer and
|
Chris@1296
|
3284 # terminate.
|
Chris@1296
|
3285 #
|
Chris@1296
|
3286 # 2) Let U' = U - 0x10000. Because U is less than or equal to 0x10FFFF,
|
Chris@1296
|
3287 # U' must be less than or equal to 0xFFFFF. That is, U' can be
|
Chris@1296
|
3288 # represented in 20 bits.
|
Chris@1296
|
3289 #
|
Chris@1296
|
3290 # 3) Initialize two 16-bit unsigned integers, W1 and W2, to 0xD800 and
|
Chris@1296
|
3291 # 0xDC00, respectively. These integers each have 10 bits free to
|
Chris@1296
|
3292 # encode the character value, for a total of 20 bits.
|
Chris@1296
|
3293 #
|
Chris@1296
|
3294 # 4) Assign the 10 high-order bits of the 20-bit U' to the 10 low-order
|
Chris@1296
|
3295 # bits of W1 and the 10 low-order bits of U' to the 10 low-order
|
Chris@1296
|
3296 # bits of W2. Terminate.
|
Chris@1296
|
3297 #
|
Chris@1296
|
3298 # Graphically, steps 2 through 4 look like:
|
Chris@1296
|
3299 # U' = yyyyyyyyyyxxxxxxxxxx
|
Chris@1296
|
3300 # W1 = 110110yyyyyyyyyy
|
Chris@1296
|
3301 # W2 = 110111xxxxxxxxxx
|
Chris@1296
|
3302 # </pre>
|
Chris@1296
|
3303 # @param string :str string to process.
|
Chris@1296
|
3304 # @param boolean :setbom if true set the Byte Order Mark (BOM = 0xFEFF)
|
Chris@1296
|
3305 # @return string
|
Chris@1296
|
3306 # @access protected
|
Chris@1296
|
3307 # @author Nicola Asuni
|
Chris@1296
|
3308 # @since 1.53.0.TC005 (2005-01-05)
|
Chris@1296
|
3309 # @uses UTF8StringToArray
|
Chris@1296
|
3310 #
|
Chris@1296
|
3311 def UTF8ToUTF16BE(str, setbom=true)
|
Chris@1296
|
3312 if (!@is_unicode)
|
Chris@1296
|
3313 return str; # string is not in unicode
|
Chris@1296
|
3314 end
|
Chris@1296
|
3315 outstr = ""; # string to be returned
|
Chris@1296
|
3316 unicode = UTF8StringToArray(str); # array containing UTF-8 unicode values
|
Chris@1296
|
3317 numitems = unicode.length;
|
Chris@1296
|
3318
|
Chris@1296
|
3319 if (setbom)
|
Chris@1296
|
3320 outstr << "\xFE\xFF"; # Byte Order Mark (BOM)
|
Chris@1296
|
3321 end
|
Chris@1296
|
3322 unicode.each do |char|
|
Chris@1296
|
3323 if (char == 0xFFFD)
|
Chris@1296
|
3324 outstr << "\xFF\xFD"; # replacement character
|
Chris@1296
|
3325 elsif (char < 0x10000)
|
Chris@1296
|
3326 outstr << (char >> 0x08).chr;
|
Chris@1296
|
3327 outstr << (char & 0xFF).chr;
|
Chris@1296
|
3328 else
|
Chris@1296
|
3329 char -= 0x10000;
|
Chris@1296
|
3330 w1 = 0xD800 | (char >> 0x10);
|
Chris@1296
|
3331 w2 = 0xDC00 | (char & 0x3FF);
|
Chris@1296
|
3332 outstr << (w1 >> 0x08).chr;
|
Chris@1296
|
3333 outstr << (w1 & 0xFF).chr;
|
Chris@1296
|
3334 outstr << (w2 >> 0x08).chr;
|
Chris@1296
|
3335 outstr << (w2 & 0xFF).chr;
|
Chris@1296
|
3336 end
|
Chris@1296
|
3337 end
|
Chris@1296
|
3338 return outstr;
|
Chris@1296
|
3339 end
|
Chris@1296
|
3340
|
Chris@1296
|
3341 # ====================================================
|
Chris@1296
|
3342
|
Chris@1296
|
3343 #
|
Chris@1296
|
3344 # Set header font.
|
Chris@1296
|
3345 # @param array :font font
|
Chris@1296
|
3346 # @since 1.1
|
Chris@1296
|
3347 #
|
Chris@1296
|
3348 def SetHeaderFont(font)
|
Chris@1296
|
3349 @header_font = font;
|
Chris@1296
|
3350 end
|
Chris@1296
|
3351 alias_method :set_header_font, :SetHeaderFont
|
Chris@1296
|
3352
|
Chris@1296
|
3353 #
|
Chris@1296
|
3354 # Set footer font.
|
Chris@1296
|
3355 # @param array :font font
|
Chris@1296
|
3356 # @since 1.1
|
Chris@1296
|
3357 #
|
Chris@1296
|
3358 def SetFooterFont(font)
|
Chris@1296
|
3359 @footer_font = font;
|
Chris@1296
|
3360 end
|
Chris@1296
|
3361 alias_method :set_footer_font, :SetFooterFont
|
Chris@1296
|
3362
|
Chris@1296
|
3363 #
|
Chris@1296
|
3364 # Set language array.
|
Chris@1296
|
3365 # @param array :language
|
Chris@1296
|
3366 # @since 1.1
|
Chris@1296
|
3367 #
|
Chris@1296
|
3368 def SetLanguageArray(language)
|
Chris@1296
|
3369 @l = language;
|
Chris@1296
|
3370 end
|
Chris@1296
|
3371 alias_method :set_language_array, :SetLanguageArray
|
Chris@1296
|
3372 #
|
Chris@1296
|
3373 # Set document barcode.
|
Chris@1296
|
3374 # @param string :bc barcode
|
Chris@1296
|
3375 #
|
Chris@1296
|
3376 def SetBarcode(bc="")
|
Chris@1296
|
3377 @barcode = bc;
|
Chris@1296
|
3378 end
|
Chris@1296
|
3379
|
Chris@1296
|
3380 #
|
Chris@1296
|
3381 # Print Barcode.
|
Chris@1296
|
3382 # @param int :x x position in user units
|
Chris@1296
|
3383 # @param int :y y position in user units
|
Chris@1296
|
3384 # @param int :w width in user units
|
Chris@1296
|
3385 # @param int :h height position in user units
|
Chris@1296
|
3386 # @param string :type type of barcode (I25, C128A, C128B, C128C, C39)
|
Chris@1296
|
3387 # @param string :style barcode style
|
Chris@1296
|
3388 # @param string :font font for text
|
Chris@1296
|
3389 # @param int :xres x resolution
|
Chris@1296
|
3390 # @param string :code code to print
|
Chris@1296
|
3391 #
|
Chris@1296
|
3392 def writeBarcode(x, y, w, h, type, style, font, xres, code)
|
Chris@1296
|
3393 require(File.dirname(__FILE__) + "/barcode/barcode.rb");
|
Chris@1296
|
3394 require(File.dirname(__FILE__) + "/barcode/i25object.rb");
|
Chris@1296
|
3395 require(File.dirname(__FILE__) + "/barcode/c39object.rb");
|
Chris@1296
|
3396 require(File.dirname(__FILE__) + "/barcode/c128aobject.rb");
|
Chris@1296
|
3397 require(File.dirname(__FILE__) + "/barcode/c128bobject.rb");
|
Chris@1296
|
3398 require(File.dirname(__FILE__) + "/barcode/c128cobject.rb");
|
Chris@1296
|
3399
|
Chris@1296
|
3400 if (code.empty?)
|
Chris@1296
|
3401 return;
|
Chris@1296
|
3402 end
|
Chris@1296
|
3403
|
Chris@1296
|
3404 if (style.empty?)
|
Chris@1296
|
3405 style = BCS_ALIGN_LEFT;
|
Chris@1296
|
3406 style |= BCS_IMAGE_PNG;
|
Chris@1296
|
3407 style |= BCS_TRANSPARENT;
|
Chris@1296
|
3408 #:style |= BCS_BORDER;
|
Chris@1296
|
3409 #:style |= BCS_DRAW_TEXT;
|
Chris@1296
|
3410 #:style |= BCS_STRETCH_TEXT;
|
Chris@1296
|
3411 #:style |= BCS_REVERSE_COLOR;
|
Chris@1296
|
3412 end
|
Chris@1296
|
3413 if (font.empty?) then font = BCD_DEFAULT_FONT; end
|
Chris@1296
|
3414 if (xres.empty?) then xres = BCD_DEFAULT_XRES; end
|
Chris@1296
|
3415
|
Chris@1296
|
3416 scale_factor = 1.5 * xres * @k;
|
Chris@1296
|
3417 bc_w = (w * scale_factor).round #width in points
|
Chris@1296
|
3418 bc_h = (h * scale_factor).round #height in points
|
Chris@1296
|
3419
|
Chris@1296
|
3420 case (type.upcase)
|
Chris@1296
|
3421 when "I25"
|
Chris@1296
|
3422 obj = I25Object.new(bc_w, bc_h, style, code);
|
Chris@1296
|
3423 when "C128A"
|
Chris@1296
|
3424 obj = C128AObject.new(bc_w, bc_h, style, code);
|
Chris@1296
|
3425 when "C128B"
|
Chris@1296
|
3426 obj = C128BObject.new(bc_w, bc_h, style, code);
|
Chris@1296
|
3427 when "C128C"
|
Chris@1296
|
3428 obj = C128CObject.new(bc_w, bc_h, style, code);
|
Chris@1296
|
3429 when "C39"
|
Chris@1296
|
3430 obj = C39Object.new(bc_w, bc_h, style, code);
|
Chris@1296
|
3431 end
|
Chris@1296
|
3432
|
Chris@1296
|
3433 obj.SetFont(font);
|
Chris@1296
|
3434 obj.DrawObject(xres);
|
Chris@1296
|
3435
|
Chris@1296
|
3436 #use a temporary file....
|
Chris@1296
|
3437 tmpName = tempnam(@@k_path_cache,'img');
|
Chris@1296
|
3438 imagepng(obj.getImage(), tmpName);
|
Chris@1296
|
3439 Image(tmpName, x, y, w, h, 'png');
|
Chris@1296
|
3440 obj.DestroyObject();
|
Chris@1296
|
3441 obj = nil
|
Chris@1296
|
3442 unlink(tmpName);
|
Chris@1296
|
3443 end
|
Chris@1296
|
3444
|
Chris@1296
|
3445 #
|
Chris@1296
|
3446 # Returns the PDF data.
|
Chris@1296
|
3447 #
|
Chris@1296
|
3448 def GetPDFData()
|
Chris@1296
|
3449 if (@state < 3)
|
Chris@1296
|
3450 Close();
|
Chris@1296
|
3451 end
|
Chris@1296
|
3452 return @buffer;
|
Chris@1296
|
3453 end
|
Chris@1296
|
3454
|
Chris@1296
|
3455 # --- HTML PARSER FUNCTIONS ---
|
Chris@1296
|
3456
|
Chris@1296
|
3457 #
|
Chris@1296
|
3458 # Allows to preserve some HTML formatting.<br />
|
Chris@1296
|
3459 # Supports: h1, h2, h3, h4, h5, h6, b, u, i, a, img, p, br, strong, em, ins, del, font, blockquote, li, ul, ol, hr, td, th, tr, table, sup, sub, small
|
Chris@1296
|
3460 # @param string :html text to display
|
Chris@1296
|
3461 # @param boolean :ln if true add a new line after text (default = true)
|
Chris@1296
|
3462 # @param int :fill Indicates if the background must be painted (1) or transparent (0). Default value: 0.
|
Chris@1296
|
3463 #
|
Chris@1296
|
3464 def writeHTML(html, ln=true, fill=0, h=0)
|
Chris@1296
|
3465
|
Chris@1296
|
3466 @lasth = h if h > 0
|
Chris@1296
|
3467 if (@lasth == 0)
|
Chris@1296
|
3468 #set row height
|
Chris@1296
|
3469 @lasth = @font_size * @@k_cell_height_ratio;
|
Chris@1296
|
3470 end
|
Chris@1296
|
3471
|
Chris@1296
|
3472 @href = nil
|
Chris@1296
|
3473 @style = "";
|
Chris@1296
|
3474 @t_cells = [[]];
|
Chris@1296
|
3475 @table_id = 0;
|
Chris@1296
|
3476
|
Chris@1296
|
3477 # pre calculate
|
Chris@1296
|
3478 html.split(/(<[^>]+>)/).each do |element|
|
Chris@1296
|
3479 if "<" == element[0,1]
|
Chris@1296
|
3480 #Tag
|
Chris@1296
|
3481 if (element[1, 1] == '/')
|
Chris@1296
|
3482 closedHTMLTagCalc(element[2..-2].downcase);
|
Chris@1296
|
3483 else
|
Chris@1296
|
3484 #Extract attributes
|
Chris@1296
|
3485 # get tag name
|
Chris@1296
|
3486 tag = element.scan(/([a-zA-Z0-9]*)/).flatten.delete_if {|x| x.length == 0}
|
Chris@1296
|
3487 tag = tag[0].to_s.downcase;
|
Chris@1296
|
3488
|
Chris@1296
|
3489 # get attributes
|
Chris@1296
|
3490 attr_array = element.scan(/([^=\s]*)=["\']?([^"\']*)["\']?/)
|
Chris@1296
|
3491 attrs = {}
|
Chris@1296
|
3492 attr_array.each do |name, value|
|
Chris@1296
|
3493 attrs[name.downcase] = value;
|
Chris@1296
|
3494 end
|
Chris@1296
|
3495 openHTMLTagCalc(tag, attrs);
|
Chris@1296
|
3496 end
|
Chris@1296
|
3497 end
|
Chris@1296
|
3498 end
|
Chris@1296
|
3499 @table_id = 0;
|
Chris@1296
|
3500
|
Chris@1296
|
3501 html.split(/(<[A-Za-z!?\/][^>]*?>)/).each do |element|
|
Chris@1296
|
3502 if "<" == element[0,1]
|
Chris@1296
|
3503 #Tag
|
Chris@1296
|
3504 if (element[1, 1] == '/')
|
Chris@1296
|
3505 closedHTMLTagHandler(element[2..-2].downcase);
|
Chris@1296
|
3506 else
|
Chris@1296
|
3507 #Extract attributes
|
Chris@1296
|
3508 # get tag name
|
Chris@1296
|
3509 tag = element.scan(/([a-zA-Z0-9]*)/).flatten.delete_if {|x| x.length == 0}
|
Chris@1296
|
3510 tag = tag[0].to_s.downcase;
|
Chris@1296
|
3511
|
Chris@1296
|
3512 # get attributes
|
Chris@1296
|
3513 attr_array = element.scan(/([^=\s]*)=["\']?([^"\']*)["\']?/)
|
Chris@1296
|
3514 attrs = {}
|
Chris@1296
|
3515 attr_array.each do |name, value|
|
Chris@1296
|
3516 attrs[name.downcase] = value;
|
Chris@1296
|
3517 end
|
Chris@1296
|
3518 openHTMLTagHandler(tag, attrs, fill);
|
Chris@1296
|
3519 end
|
Chris@1296
|
3520
|
Chris@1296
|
3521 else
|
Chris@1296
|
3522 #Text
|
Chris@1296
|
3523 if (@tdbegin)
|
Chris@1296
|
3524 element.gsub!(/[\t\r\n\f]/, "");
|
Chris@1296
|
3525 @tdtext << element.gsub(/ /, " ");
|
Chris@1296
|
3526 elsif (@href)
|
Chris@1296
|
3527 element.gsub!(/[\t\r\n\f]/, "");
|
Chris@1296
|
3528 addHtmlLink(@href, element, fill);
|
Chris@1296
|
3529 elsif (@pre_state == true and element.length > 0)
|
Chris@1296
|
3530 Write(@lasth, unhtmlentities(element), '', fill);
|
Chris@1296
|
3531 elsif (element.strip.length > 0)
|
Chris@1296
|
3532 element.gsub!(/[\t\r\n\f]/, "");
|
Chris@1296
|
3533 element.gsub!(/ /, " ");
|
Chris@1296
|
3534 Write(@lasth, unhtmlentities(element), '', fill);
|
Chris@1296
|
3535 end
|
Chris@1296
|
3536 end
|
Chris@1296
|
3537 end
|
Chris@1296
|
3538
|
Chris@1296
|
3539 if (ln)
|
Chris@1296
|
3540 Ln(@lasth);
|
Chris@1296
|
3541 end
|
Chris@1296
|
3542 end
|
Chris@1296
|
3543 alias_method :write_html, :writeHTML
|
Chris@1296
|
3544
|
Chris@1296
|
3545 #
|
Chris@1296
|
3546 # Prints a cell (rectangular area) with optional borders, background color and html text string. The upper-left corner of the cell corresponds to the current position. After the call, the current position moves to the right or to the next line.<br />
|
Chris@1296
|
3547 # If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting.
|
Chris@1296
|
3548 # @param float :w Cell width. If 0, the cell extends up to the right margin.
|
Chris@1296
|
3549 # @param float :h Cell minimum height. The cell extends automatically if needed.
|
Chris@1296
|
3550 # @param float :x upper-left corner X coordinate
|
Chris@1296
|
3551 # @param float :y upper-left corner Y coordinate
|
Chris@1296
|
3552 # @param string :html html text to print. Default value: empty string.
|
Chris@1296
|
3553 # @param mixed :border Indicates if borders must be drawn around the cell. The value can be either a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul>or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul>
|
Chris@1296
|
3554 # @param int :ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>
|
Chris@1296
|
3555 # Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
|
Chris@1296
|
3556 # @param int :fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.
|
Chris@1296
|
3557 # @see Cell()
|
Chris@1296
|
3558 #
|
Chris@1296
|
3559 def writeHTMLCell(w, h, x, y, html='', border=0, ln=1, fill=0)
|
Chris@1296
|
3560
|
Chris@1296
|
3561 if (@lasth == 0)
|
Chris@1296
|
3562 #set row height
|
Chris@1296
|
3563 @lasth = @font_size * @@k_cell_height_ratio;
|
Chris@1296
|
3564 end
|
Chris@1296
|
3565
|
Chris@1296
|
3566 if (x == 0)
|
Chris@1296
|
3567 x = GetX();
|
Chris@1296
|
3568 end
|
Chris@1296
|
3569 if (y == 0)
|
Chris@1296
|
3570 y = GetY();
|
Chris@1296
|
3571 end
|
Chris@1296
|
3572
|
Chris@1296
|
3573 # get current page number
|
Chris@1296
|
3574 pagenum = @page;
|
Chris@1296
|
3575
|
Chris@1296
|
3576 SetX(x);
|
Chris@1296
|
3577 SetY(y);
|
Chris@1296
|
3578
|
Chris@1296
|
3579 if (w == 0)
|
Chris@1296
|
3580 w = @fw - x - @r_margin;
|
Chris@1296
|
3581 end
|
Chris@1296
|
3582
|
Chris@1296
|
3583 b=0;
|
Chris@1296
|
3584 if (border)
|
Chris@1296
|
3585 if (border==1)
|
Chris@1296
|
3586 border='LTRB';
|
Chris@1296
|
3587 b='LRT';
|
Chris@1296
|
3588 b2='LR';
|
Chris@1296
|
3589 elsif border.is_a?(String)
|
Chris@1296
|
3590 b2='';
|
Chris@1296
|
3591 if (border.include?('L'))
|
Chris@1296
|
3592 b2<<'L';
|
Chris@1296
|
3593 end
|
Chris@1296
|
3594 if (border.include?('R'))
|
Chris@1296
|
3595 b2<<'R';
|
Chris@1296
|
3596 end
|
Chris@1296
|
3597 b=(border.include?('T')) ? b2 + 'T' : b2;
|
Chris@1296
|
3598 end
|
Chris@1296
|
3599 end
|
Chris@1296
|
3600
|
Chris@1296
|
3601 # store original margin values
|
Chris@1296
|
3602 l_margin = @l_margin;
|
Chris@1296
|
3603 r_margin = @r_margin;
|
Chris@1296
|
3604
|
Chris@1296
|
3605 # set new margin values
|
Chris@1296
|
3606 SetLeftMargin(x);
|
Chris@1296
|
3607 SetRightMargin(@fw - x - w);
|
Chris@1296
|
3608
|
Chris@1296
|
3609 # calculate remaining vertical space on page
|
Chris@1296
|
3610 restspace = GetPageHeight() - GetY() - GetBreakMargin();
|
Chris@1296
|
3611
|
Chris@1296
|
3612 writeHTML(html, true, fill); # write html text
|
Chris@1296
|
3613 SetX(x)
|
Chris@1296
|
3614
|
Chris@1296
|
3615 currentY = GetY();
|
Chris@1296
|
3616 @auto_page_break = false;
|
Chris@1296
|
3617 # check if a new page has been created
|
Chris@1296
|
3618 if (@page > pagenum)
|
Chris@1296
|
3619 # design a cell around the text on first page
|
Chris@1296
|
3620 currentpage = @page;
|
Chris@1296
|
3621 @page = pagenum;
|
Chris@1296
|
3622 SetY(GetPageHeight() - restspace - GetBreakMargin());
|
Chris@1296
|
3623 SetX(x)
|
Chris@1296
|
3624 Cell(w, restspace - 1, "", b, 0, 'L', 0);
|
Chris@1296
|
3625 b = b2;
|
Chris@1296
|
3626 @page += 1;
|
Chris@1296
|
3627 while @page < currentpage
|
Chris@1296
|
3628 SetY(@t_margin); # put cursor at the beginning of text
|
Chris@1296
|
3629 SetX(x)
|
Chris@1296
|
3630 Cell(w, @page_break_trigger - @t_margin, "", b, 0, 'L', 0);
|
Chris@1296
|
3631 @page += 1;
|
Chris@1296
|
3632 end
|
Chris@1296
|
3633 if (border.is_a?(String) and border.include?('B'))
|
Chris@1296
|
3634 b<<'B';
|
Chris@1296
|
3635 end
|
Chris@1296
|
3636 # design a cell around the text on last page
|
Chris@1296
|
3637 SetY(@t_margin); # put cursor at the beginning of text
|
Chris@1296
|
3638 SetX(x)
|
Chris@1296
|
3639 Cell(w, currentY - @t_margin, "", b, 0, 'L', 0);
|
Chris@1296
|
3640 else
|
Chris@1296
|
3641 SetY(y); # put cursor at the beginning of text
|
Chris@1296
|
3642 # design a cell around the text
|
Chris@1296
|
3643 SetX(x)
|
Chris@1296
|
3644 Cell(w, [h, (currentY - y)].max, "", border, 0, 'L', 0);
|
Chris@1296
|
3645 end
|
Chris@1296
|
3646 @auto_page_break = true;
|
Chris@1296
|
3647
|
Chris@1296
|
3648 # restore original margin values
|
Chris@1296
|
3649 SetLeftMargin(l_margin);
|
Chris@1296
|
3650 SetRightMargin(r_margin);
|
Chris@1296
|
3651
|
Chris@1296
|
3652 @lasth = h
|
Chris@1296
|
3653
|
Chris@1296
|
3654 # move cursor to specified position
|
Chris@1296
|
3655 if (ln == 0)
|
Chris@1296
|
3656 # go to the top-right of the cell
|
Chris@1296
|
3657 @x = x + w;
|
Chris@1296
|
3658 @y = y;
|
Chris@1296
|
3659 elsif (ln == 1)
|
Chris@1296
|
3660 # go to the beginning of the next line
|
Chris@1296
|
3661 @x = @l_margin;
|
Chris@1296
|
3662 @y = currentY;
|
Chris@1296
|
3663 elsif (ln == 2)
|
Chris@1296
|
3664 # go to the bottom-left of the cell (below)
|
Chris@1296
|
3665 @x = x;
|
Chris@1296
|
3666 @y = currentY;
|
Chris@1296
|
3667 end
|
Chris@1296
|
3668 end
|
Chris@1296
|
3669 alias_method :write_html_cell, :writeHTMLCell
|
Chris@1296
|
3670
|
Chris@1296
|
3671 #
|
Chris@1296
|
3672 # Check html table tag position.
|
Chris@1296
|
3673 #
|
Chris@1296
|
3674 # @param array :table potision array
|
Chris@1296
|
3675 # @param int :current tr tag id number
|
Chris@1296
|
3676 # @param int :current td tag id number
|
Chris@1296
|
3677 # @access private
|
Chris@1296
|
3678 # @return int : next td_id position.
|
Chris@1296
|
3679 # value 0 mean that can use position.
|
Chris@1296
|
3680 #
|
Chris@1296
|
3681 def checkTableBlockingCellPosition(table, tr_id, td_id )
|
Chris@1296
|
3682 0.upto(tr_id) do |j|
|
Chris@1296
|
3683 0.upto(@t_cells[table][j].size - 1) do |i|
|
Chris@1296
|
3684 if @t_cells[table][j][i]['i0'] <= td_id and td_id <= @t_cells[table][j][i]['i1']
|
Chris@1296
|
3685 if @t_cells[table][j][i]['j0'] <= tr_id and tr_id <= @t_cells[table][j][i]['j1']
|
Chris@1296
|
3686 return @t_cells[table][j][i]['i1'] - td_id + 1;
|
Chris@1296
|
3687 end
|
Chris@1296
|
3688 end
|
Chris@1296
|
3689 end
|
Chris@1296
|
3690 end
|
Chris@1296
|
3691 return 0;
|
Chris@1296
|
3692 end
|
Chris@1296
|
3693
|
Chris@1296
|
3694 #
|
Chris@1296
|
3695 # Calculate opening tags.
|
Chris@1296
|
3696 #
|
Chris@1296
|
3697 # html table cell array : @t_cells
|
Chris@1296
|
3698 #
|
Chris@1296
|
3699 # i0: table cell start position
|
Chris@1296
|
3700 # i1: table cell end position
|
Chris@1296
|
3701 # j0: table row start position
|
Chris@1296
|
3702 # j1: table row end position
|
Chris@1296
|
3703 #
|
Chris@1296
|
3704 # +------+
|
Chris@1296
|
3705 # |i0,j0 |
|
Chris@1296
|
3706 # | i1,j1|
|
Chris@1296
|
3707 # +------+
|
Chris@1296
|
3708 #
|
Chris@1296
|
3709 # example html:
|
Chris@1296
|
3710 # <table>
|
Chris@1296
|
3711 # <tr><td></td><td></td><td></td></tr>
|
Chris@1296
|
3712 # <tr><td colspan=2></td><td></td></tr>
|
Chris@1296
|
3713 # <tr><td rowspan=2></td><td></td><td></td></tr>
|
Chris@1296
|
3714 # <tr><td></td><td></td></tr>
|
Chris@1296
|
3715 # </table>
|
Chris@1296
|
3716 #
|
Chris@1296
|
3717 # i: 0 1 2
|
Chris@1296
|
3718 # j+----+----+----+
|
Chris@1296
|
3719 # :|0,0 |1,0 |2,0 |
|
Chris@1296
|
3720 # 0| 0,0| 1,0| 2,0|
|
Chris@1296
|
3721 # +----+----+----+
|
Chris@1296
|
3722 # |0,1 |2,1 |
|
Chris@1296
|
3723 # 1| 1,1| 2,1|
|
Chris@1296
|
3724 # +----+----+----+
|
Chris@1296
|
3725 # |0,2 |1,2 |2,2 |
|
Chris@1296
|
3726 # 2| | 1,2| 2,2|
|
Chris@1296
|
3727 # + +----+----+
|
Chris@1296
|
3728 # | |1,3 |2,3 |
|
Chris@1296
|
3729 # 3| 0,3| 1,3| 2,3|
|
Chris@1296
|
3730 # +----+----+----+
|
Chris@1296
|
3731 #
|
Chris@1296
|
3732 # html table cell array :
|
Chris@1296
|
3733 # [[[i0=>0,j0=>0,i1=>0,j1=>0],[i0=>1,j0=>0,i1=>1,j1=>0],[i0=>2,j0=>0,i1=>2,j1=>0]],
|
Chris@1296
|
3734 # [[i0=>0,j0=>1,i1=>1,j1=>1],[i0=>2,j0=>1,i1=>2,j1=>1]],
|
Chris@1296
|
3735 # [[i0=>0,j0=>2,i1=>0,j1=>3],[i0=>1,j0=>2,i1=>1,j1=>2],[i0=>2,j0=>2,i1=>2,j1=>2]]
|
Chris@1296
|
3736 # [[i0=>1,j0=>3,i1=>1,j1=>3],[i0=>2,j0=>3,i1=>2,j1=>3]]]
|
Chris@1296
|
3737 #
|
Chris@1296
|
3738 # @param string :tag tag name (in upcase)
|
Chris@1296
|
3739 # @param string :attr tag attribute (in upcase)
|
Chris@1296
|
3740 # @access private
|
Chris@1296
|
3741 #
|
Chris@1296
|
3742 def openHTMLTagCalc(tag, attrs)
|
Chris@1296
|
3743 #Opening tag
|
Chris@1296
|
3744 case (tag)
|
Chris@1296
|
3745 when 'table'
|
Chris@1296
|
3746 @max_table_columns[@table_id] = 0;
|
Chris@1296
|
3747 @t_columns = 0;
|
Chris@1296
|
3748 @tr_id = -1;
|
Chris@1296
|
3749 when 'tr'
|
Chris@1296
|
3750 if @max_table_columns[@table_id] < @t_columns
|
Chris@1296
|
3751 @max_table_columns[@table_id] = @t_columns;
|
Chris@1296
|
3752 end
|
Chris@1296
|
3753 @t_columns = 0;
|
Chris@1296
|
3754 @tr_id += 1;
|
Chris@1296
|
3755 @td_id = -1;
|
Chris@1296
|
3756 @t_cells[@table_id].push []
|
Chris@1296
|
3757 when 'td', 'th'
|
Chris@1296
|
3758 @td_id += 1;
|
Chris@1296
|
3759 if attrs['colspan'].nil? or attrs['colspan'] == ''
|
Chris@1296
|
3760 colspan = 1;
|
Chris@1296
|
3761 else
|
Chris@1296
|
3762 colspan = attrs['colspan'].to_i;
|
Chris@1296
|
3763 end
|
Chris@1296
|
3764 if attrs['rowspan'].nil? or attrs['rowspan'] == ''
|
Chris@1296
|
3765 rowspan = 1;
|
Chris@1296
|
3766 else
|
Chris@1296
|
3767 rowspan = attrs['rowspan'].to_i;
|
Chris@1296
|
3768 end
|
Chris@1296
|
3769
|
Chris@1296
|
3770 i = 0;
|
Chris@1296
|
3771 while true
|
Chris@1296
|
3772 next_i_distance = checkTableBlockingCellPosition(@table_id, @tr_id, @td_id + i);
|
Chris@1296
|
3773 if next_i_distance == 0
|
Chris@1296
|
3774 @t_cells[@table_id][@tr_id].push "i0"=>@td_id + i, "j0"=>@tr_id, "i1"=>(@td_id + i + colspan - 1), "j1"=>@tr_id + rowspan - 1
|
Chris@1296
|
3775 break;
|
Chris@1296
|
3776 end
|
Chris@1296
|
3777 i += next_i_distance;
|
Chris@1296
|
3778 end
|
Chris@1296
|
3779
|
Chris@1296
|
3780 @t_columns += colspan;
|
Chris@1296
|
3781 end
|
Chris@1296
|
3782 end
|
Chris@1296
|
3783
|
Chris@1296
|
3784 #
|
Chris@1296
|
3785 # Calculate closing tags.
|
Chris@1296
|
3786 # @param string :tag tag name (in upcase)
|
Chris@1296
|
3787 # @access private
|
Chris@1296
|
3788 #
|
Chris@1296
|
3789 def closedHTMLTagCalc(tag)
|
Chris@1296
|
3790 #Closing tag
|
Chris@1296
|
3791 case (tag)
|
Chris@1296
|
3792 when 'table'
|
Chris@1296
|
3793 if @max_table_columns[@table_id] < @t_columns
|
Chris@1296
|
3794 @max_table_columns[@table_id] = @t_columns;
|
Chris@1296
|
3795 end
|
Chris@1296
|
3796 @table_id += 1;
|
Chris@1296
|
3797 @t_cells.push []
|
Chris@1296
|
3798 end
|
Chris@1296
|
3799 end
|
Chris@1296
|
3800
|
Chris@1296
|
3801 #
|
Chris@1296
|
3802 # Convert to accessible file path
|
Chris@1296
|
3803 # @param string :attrname image file name
|
Chris@1296
|
3804 #
|
Chris@1296
|
3805 def getImageFilename( attrname )
|
Chris@1296
|
3806 nil
|
Chris@1296
|
3807 end
|
Chris@1296
|
3808
|
Chris@1296
|
3809 #
|
Chris@1296
|
3810 # Process opening tags.
|
Chris@1296
|
3811 # @param string :tag tag name (in upcase)
|
Chris@1296
|
3812 # @param string :attr tag attribute (in upcase)
|
Chris@1296
|
3813 # @param int :fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.
|
Chris@1296
|
3814 # @access private
|
Chris@1296
|
3815 #
|
Chris@1296
|
3816 def openHTMLTagHandler(tag, attrs, fill=0)
|
Chris@1296
|
3817 #Opening tag
|
Chris@1296
|
3818 case (tag)
|
Chris@1296
|
3819 when 'pre'
|
Chris@1296
|
3820 @pre_state = true;
|
Chris@1296
|
3821 @l_margin += 5;
|
Chris@1296
|
3822 @r_margin += 5;
|
Chris@1296
|
3823 @x += 5;
|
Chris@1296
|
3824
|
Chris@1296
|
3825 when 'table'
|
Chris@1296
|
3826 Ln();
|
Chris@1296
|
3827 if @default_table_columns < @max_table_columns[@table_id]
|
Chris@1296
|
3828 @table_columns = @max_table_columns[@table_id];
|
Chris@1296
|
3829 else
|
Chris@1296
|
3830 @table_columns = @default_table_columns;
|
Chris@1296
|
3831 end
|
Chris@1296
|
3832 @l_margin += 5;
|
Chris@1296
|
3833 @r_margin += 5;
|
Chris@1296
|
3834 @x += 5;
|
Chris@1296
|
3835
|
Chris@1296
|
3836 if attrs['border'].nil? or attrs['border'] == ''
|
Chris@1296
|
3837 @tableborder = 0;
|
Chris@1296
|
3838 else
|
Chris@1296
|
3839 @tableborder = attrs['border'];
|
Chris@1296
|
3840 end
|
Chris@1296
|
3841 @tr_id = -1;
|
Chris@1296
|
3842 @max_td_page[0] = @page;
|
Chris@1296
|
3843 @max_td_y[0] = @y;
|
Chris@1296
|
3844
|
Chris@1296
|
3845 when 'tr', 'td', 'th'
|
Chris@1296
|
3846 if tag == 'th'
|
Chris@1296
|
3847 SetStyle('b', true);
|
Chris@1296
|
3848 @tdalign = "C";
|
Chris@1296
|
3849 end
|
Chris@1296
|
3850 if ((!attrs['width'].nil?) and (attrs['width'] != ''))
|
Chris@1296
|
3851 @tdwidth = (attrs['width'].to_i/4);
|
Chris@1296
|
3852 else
|
Chris@1296
|
3853 @tdwidth = ((@w - @l_margin - @r_margin) / @table_columns);
|
Chris@1296
|
3854 end
|
Chris@1296
|
3855
|
Chris@1296
|
3856 if tag == 'tr'
|
Chris@1296
|
3857 @tr_id += 1;
|
Chris@1296
|
3858 @td_id = -1;
|
Chris@1296
|
3859 else
|
Chris@1296
|
3860 @td_id += 1;
|
Chris@1296
|
3861 @x = @l_margin + @tdwidth * @t_cells[@table_id][@tr_id][@td_id]['i0'];
|
Chris@1296
|
3862 end
|
Chris@1296
|
3863
|
Chris@1296
|
3864 if attrs['colspan'].nil? or attrs['border'] == ''
|
Chris@1296
|
3865 @colspan = 1;
|
Chris@1296
|
3866 else
|
Chris@1296
|
3867 @colspan = attrs['colspan'].to_i;
|
Chris@1296
|
3868 end
|
Chris@1296
|
3869 @tdwidth *= @colspan;
|
Chris@1296
|
3870 if ((!attrs['height'].nil?) and (attrs['height'] != ''))
|
Chris@1296
|
3871 @tdheight=(attrs['height'].to_i / @k);
|
Chris@1296
|
3872 else
|
Chris@1296
|
3873 @tdheight = @lasth;
|
Chris@1296
|
3874 end
|
Chris@1296
|
3875 if ((!attrs['align'].nil?) and (attrs['align'] != ''))
|
Chris@1296
|
3876 case (attrs['align'])
|
Chris@1296
|
3877 when 'center'
|
Chris@1296
|
3878 @tdalign = "C";
|
Chris@1296
|
3879 when 'right'
|
Chris@1296
|
3880 @tdalign = "R";
|
Chris@1296
|
3881 when 'left'
|
Chris@1296
|
3882 @tdalign = "L";
|
Chris@1296
|
3883 end
|
Chris@1296
|
3884 end
|
Chris@1296
|
3885 if ((!attrs['bgcolor'].nil?) and (attrs['bgcolor'] != ''))
|
Chris@1296
|
3886 coul = convertColorHexToDec(attrs['bgcolor']);
|
Chris@1296
|
3887 SetFillColor(coul['R'], coul['G'], coul['B']);
|
Chris@1296
|
3888 @tdfill=1;
|
Chris@1296
|
3889 end
|
Chris@1296
|
3890 @tdbegin=true;
|
Chris@1296
|
3891
|
Chris@1296
|
3892 when 'hr'
|
Chris@1296
|
3893 margin = 1;
|
Chris@1296
|
3894 if ((!attrs['width'].nil?) and (attrs['width'] != ''))
|
Chris@1296
|
3895 hrWidth = attrs['width'];
|
Chris@1296
|
3896 else
|
Chris@1296
|
3897 hrWidth = @w - @l_margin - @r_margin - margin;
|
Chris@1296
|
3898 end
|
Chris@1296
|
3899 SetLineWidth(0.2);
|
Chris@1296
|
3900 Line(@x + margin, @y, @x + hrWidth, @y);
|
Chris@1296
|
3901 Ln();
|
Chris@1296
|
3902
|
Chris@1296
|
3903 when 'strong'
|
Chris@1296
|
3904 SetStyle('b', true);
|
Chris@1296
|
3905
|
Chris@1296
|
3906 when 'em'
|
Chris@1296
|
3907 SetStyle('i', true);
|
Chris@1296
|
3908
|
Chris@1296
|
3909 when 'ins'
|
Chris@1296
|
3910 SetStyle('u', true);
|
Chris@1296
|
3911
|
Chris@1296
|
3912 when 'del'
|
Chris@1296
|
3913 SetStyle('d', true);
|
Chris@1296
|
3914
|
Chris@1296
|
3915 when 'b', 'i', 'u'
|
Chris@1296
|
3916 SetStyle(tag, true);
|
Chris@1296
|
3917
|
Chris@1296
|
3918 when 'a'
|
Chris@1296
|
3919 @href = attrs['href'];
|
Chris@1296
|
3920
|
Chris@1296
|
3921 when 'img'
|
Chris@1296
|
3922 if (!attrs['src'].nil?)
|
Chris@1296
|
3923 # Don't generates image inside table tag
|
Chris@1296
|
3924 if (@tdbegin)
|
Chris@1296
|
3925 @tdtext << attrs['src'];
|
Chris@1296
|
3926 return
|
Chris@1296
|
3927 end
|
Chris@1296
|
3928 # Only generates image include a pdf if RMagick is avalaible
|
Chris@1296
|
3929 unless Object.const_defined?(:Magick)
|
Chris@1296
|
3930 Write(@lasth, attrs['src'], '', fill);
|
Chris@1296
|
3931 return
|
Chris@1296
|
3932 end
|
Chris@1296
|
3933 file = getImageFilename(attrs['src'])
|
Chris@1296
|
3934 if (file.nil?)
|
Chris@1296
|
3935 Write(@lasth, attrs['src'], '', fill);
|
Chris@1296
|
3936 return
|
Chris@1296
|
3937 end
|
Chris@1296
|
3938
|
Chris@1296
|
3939 if (attrs['width'].nil?)
|
Chris@1296
|
3940 attrs['width'] = 0;
|
Chris@1296
|
3941 end
|
Chris@1296
|
3942 if (attrs['height'].nil?)
|
Chris@1296
|
3943 attrs['height'] = 0;
|
Chris@1296
|
3944 end
|
Chris@1296
|
3945
|
Chris@1296
|
3946 begin
|
Chris@1296
|
3947 Image(file, GetX(),GetY(), pixelsToMillimeters(attrs['width']), pixelsToMillimeters(attrs['height']));
|
Chris@1296
|
3948 #SetX(@img_rb_x);
|
Chris@1296
|
3949 SetY(@img_rb_y);
|
Chris@1296
|
3950 rescue => err
|
Chris@1296
|
3951 logger.error "pdf: Image: error: #{err.message}"
|
Chris@1296
|
3952 Write(@lasth, attrs['src'], '', fill);
|
Chris@1296
|
3953 end
|
Chris@1296
|
3954 end
|
Chris@1296
|
3955
|
Chris@1296
|
3956 when 'ul', 'ol'
|
Chris@1296
|
3957 if @li_count == 0
|
Chris@1296
|
3958 Ln() if @prevquote_count == @quote_count; # insert Ln for keeping quote lines
|
Chris@1296
|
3959 @prevquote_count = @quote_count;
|
Chris@1296
|
3960 end
|
Chris@1296
|
3961 if @li_state == true
|
Chris@1296
|
3962 Ln();
|
Chris@1296
|
3963 @li_state = false;
|
Chris@1296
|
3964 end
|
Chris@1296
|
3965 if tag == 'ul'
|
Chris@1296
|
3966 @list_ordered[@li_count] = false;
|
Chris@1296
|
3967 else
|
Chris@1296
|
3968 @list_ordered[@li_count] = true;
|
Chris@1296
|
3969 end
|
Chris@1296
|
3970 @list_count[@li_count] = 0;
|
Chris@1296
|
3971 @li_count += 1
|
Chris@1296
|
3972
|
Chris@1296
|
3973 when 'li'
|
Chris@1296
|
3974 Ln() if @li_state == true
|
Chris@1296
|
3975 if (@list_ordered[@li_count - 1])
|
Chris@1296
|
3976 @list_count[@li_count - 1] += 1;
|
Chris@1296
|
3977 @li_spacer = " " * @li_count + (@list_count[@li_count - 1]).to_s + ". ";
|
Chris@1296
|
3978 else
|
Chris@1296
|
3979 #unordered list simbol
|
Chris@1296
|
3980 @li_spacer = " " * @li_count + "- ";
|
Chris@1296
|
3981 end
|
Chris@1296
|
3982 Write(@lasth, @spacer + @li_spacer, '', fill);
|
Chris@1296
|
3983 @li_state = true;
|
Chris@1296
|
3984
|
Chris@1296
|
3985 when 'blockquote'
|
Chris@1296
|
3986 if (@quote_count == 0)
|
Chris@1296
|
3987 SetStyle('i', true);
|
Chris@1296
|
3988 @l_margin += 5;
|
Chris@1296
|
3989 else
|
Chris@1296
|
3990 @l_margin += 5 / 2;
|
Chris@1296
|
3991 end
|
Chris@1296
|
3992 @x = @l_margin;
|
Chris@1296
|
3993 @quote_top[@quote_count] = @y;
|
Chris@1296
|
3994 @quote_page[@quote_count] = @page;
|
Chris@1296
|
3995 @quote_count += 1
|
Chris@1296
|
3996 when 'br'
|
Chris@1296
|
3997 if @tdbegin
|
Chris@1296
|
3998 @tdtext << "\n"
|
Chris@1296
|
3999 return
|
Chris@1296
|
4000 end
|
Chris@1296
|
4001 Ln();
|
Chris@1296
|
4002
|
Chris@1296
|
4003 if (@li_spacer.length > 0)
|
Chris@1296
|
4004 @x += GetStringWidth(@li_spacer);
|
Chris@1296
|
4005 end
|
Chris@1296
|
4006
|
Chris@1296
|
4007 when 'p'
|
Chris@1296
|
4008 Ln();
|
Chris@1296
|
4009 0.upto(@quote_count - 1) do |i|
|
Chris@1296
|
4010 if @quote_page[i] == @page;
|
Chris@1296
|
4011 if @quote_top[i] == @y - @lasth; # fix start line
|
Chris@1296
|
4012 @quote_top[i] = @y;
|
Chris@1296
|
4013 end
|
Chris@1296
|
4014 else
|
Chris@1296
|
4015 if @quote_page[i] == @page - 1;
|
Chris@1296
|
4016 @quote_page[i] = @page; # fix start line
|
Chris@1296
|
4017 @quote_top[i] = @t_margin;
|
Chris@1296
|
4018 end
|
Chris@1296
|
4019 end
|
Chris@1296
|
4020 end
|
Chris@1296
|
4021
|
Chris@1296
|
4022 when 'sup'
|
Chris@1296
|
4023 currentfont_size = @font_size;
|
Chris@1296
|
4024 @tempfontsize = @font_size_pt;
|
Chris@1296
|
4025 SetFontSize(@font_size_pt * @@k_small_ratio);
|
Chris@1296
|
4026 SetXY(GetX(), GetY() - ((currentfont_size - @font_size)*(@@k_small_ratio)));
|
Chris@1296
|
4027
|
Chris@1296
|
4028 when 'sub'
|
Chris@1296
|
4029 currentfont_size = @font_size;
|
Chris@1296
|
4030 @tempfontsize = @font_size_pt;
|
Chris@1296
|
4031 SetFontSize(@font_size_pt * @@k_small_ratio);
|
Chris@1296
|
4032 SetXY(GetX(), GetY() + ((currentfont_size - @font_size)*(@@k_small_ratio)));
|
Chris@1296
|
4033
|
Chris@1296
|
4034 when 'small'
|
Chris@1296
|
4035 currentfont_size = @font_size;
|
Chris@1296
|
4036 @tempfontsize = @font_size_pt;
|
Chris@1296
|
4037 SetFontSize(@font_size_pt * @@k_small_ratio);
|
Chris@1296
|
4038 SetXY(GetX(), GetY() + ((currentfont_size - @font_size)/3));
|
Chris@1296
|
4039
|
Chris@1296
|
4040 when 'font'
|
Chris@1296
|
4041 if (!attrs['color'].nil? and attrs['color']!='')
|
Chris@1296
|
4042 coul = convertColorHexToDec(attrs['color']);
|
Chris@1296
|
4043 SetTextColor(coul['R'], coul['G'], coul['B']);
|
Chris@1296
|
4044 @issetcolor=true;
|
Chris@1296
|
4045 end
|
Chris@1296
|
4046 if (!attrs['face'].nil? and @fontlist.include?(attrs['face'].downcase))
|
Chris@1296
|
4047 SetFont(attrs['face'].downcase);
|
Chris@1296
|
4048 @issetfont=true;
|
Chris@1296
|
4049 end
|
Chris@1296
|
4050 if (!attrs['size'].nil?)
|
Chris@1296
|
4051 headsize = attrs['size'].to_i;
|
Chris@1296
|
4052 else
|
Chris@1296
|
4053 headsize = 0;
|
Chris@1296
|
4054 end
|
Chris@1296
|
4055 currentfont_size = @font_size;
|
Chris@1296
|
4056 @tempfontsize = @font_size_pt;
|
Chris@1296
|
4057 SetFontSize(@font_size_pt + headsize);
|
Chris@1296
|
4058 @lasth = @font_size * @@k_cell_height_ratio;
|
Chris@1296
|
4059
|
Chris@1296
|
4060 when 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
|
Chris@1296
|
4061 Ln();
|
Chris@1296
|
4062 headsize = (4 - tag[1,1].to_f) * 2
|
Chris@1296
|
4063 @tempfontsize = @font_size_pt;
|
Chris@1296
|
4064 SetFontSize(@font_size_pt + headsize);
|
Chris@1296
|
4065 SetStyle('b', true);
|
Chris@1296
|
4066 @lasth = @font_size * @@k_cell_height_ratio;
|
Chris@1296
|
4067
|
Chris@1296
|
4068 end
|
Chris@1296
|
4069 end
|
Chris@1296
|
4070
|
Chris@1296
|
4071 #
|
Chris@1296
|
4072 # Process closing tags.
|
Chris@1296
|
4073 # @param string :tag tag name (in upcase)
|
Chris@1296
|
4074 # @access private
|
Chris@1296
|
4075 #
|
Chris@1296
|
4076 def closedHTMLTagHandler(tag)
|
Chris@1296
|
4077 #Closing tag
|
Chris@1296
|
4078 case (tag)
|
Chris@1296
|
4079 when 'pre'
|
Chris@1296
|
4080 @pre_state = false;
|
Chris@1296
|
4081 @l_margin -= 5;
|
Chris@1296
|
4082 @r_margin -= 5;
|
Chris@1296
|
4083 @x = @l_margin;
|
Chris@1296
|
4084 Ln();
|
Chris@1296
|
4085
|
Chris@1296
|
4086 when 'td','th'
|
Chris@1296
|
4087 base_page = @page;
|
Chris@1296
|
4088 base_x = @x;
|
Chris@1296
|
4089 base_y = @y;
|
Chris@1296
|
4090
|
Chris@1296
|
4091 MultiCell(@tdwidth, @tdheight, unhtmlentities(@tdtext.strip), @tableborder, @tdalign, @tdfill, 1);
|
Chris@1296
|
4092 tr_end = @t_cells[@table_id][@tr_id][@td_id]['j1'] + 1;
|
Chris@1296
|
4093 if @max_td_page[tr_end].nil? or (@max_td_page[tr_end] < @page)
|
Chris@1296
|
4094 @max_td_page[tr_end] = @page
|
Chris@1296
|
4095 @max_td_y[tr_end] = @y
|
Chris@1296
|
4096 elsif (@max_td_page[tr_end] == @page)
|
Chris@1296
|
4097 @max_td_y[tr_end] = @y if @max_td_y[tr_end].nil? or (@max_td_y[tr_end] < @y)
|
Chris@1296
|
4098 end
|
Chris@1296
|
4099
|
Chris@1296
|
4100 @page = base_page;
|
Chris@1296
|
4101 @x = base_x + @tdwidth;
|
Chris@1296
|
4102 @y = base_y;
|
Chris@1296
|
4103 @tdtext = '';
|
Chris@1296
|
4104 @tdbegin = false;
|
Chris@1296
|
4105 @tdwidth = 0;
|
Chris@1296
|
4106 @tdheight = 0;
|
Chris@1296
|
4107 @tdalign = "L";
|
Chris@1296
|
4108 SetStyle('b', false);
|
Chris@1296
|
4109 @tdfill = 0;
|
Chris@1296
|
4110 SetFillColor(@prevfill_color[0], @prevfill_color[1], @prevfill_color[2]);
|
Chris@1296
|
4111
|
Chris@1296
|
4112 when 'tr'
|
Chris@1296
|
4113 @y = @max_td_y[@tr_id + 1];
|
Chris@1296
|
4114 @x = @l_margin;
|
Chris@1296
|
4115 @page = @max_td_page[@tr_id + 1];
|
Chris@1296
|
4116
|
Chris@1296
|
4117 when 'table'
|
Chris@1296
|
4118 # Write Table Line
|
Chris@1296
|
4119 width = (@w - @l_margin - @r_margin) / @table_columns;
|
Chris@1296
|
4120 0.upto(@t_cells[@table_id].size - 1) do |j|
|
Chris@1296
|
4121 0.upto(@t_cells[@table_id][j].size - 1) do |i|
|
Chris@1296
|
4122 @page = @max_td_page[j]
|
Chris@1296
|
4123 i0=@t_cells[@table_id][j][i]['i0'];
|
Chris@1296
|
4124 j0=@t_cells[@table_id][j][i]['j0'];
|
Chris@1296
|
4125 i1=@t_cells[@table_id][j][i]['i1'];
|
Chris@1296
|
4126 j1=@t_cells[@table_id][j][i]['j1'];
|
Chris@1296
|
4127
|
Chris@1296
|
4128 Line(@l_margin + width * i0, @max_td_y[j0], @l_margin + width * (i1+1), @max_td_y[j0]) # top
|
Chris@1296
|
4129 if ( @page == @max_td_page[j1 + 1])
|
Chris@1296
|
4130 Line(@l_margin + width * i0, @max_td_y[j0], @l_margin + width * i0, @max_td_y[j1+1]) # left
|
Chris@1296
|
4131 Line(@l_margin + width * (i1+1), @max_td_y[j0], @l_margin + width * (i1+1), @max_td_y[j1+1]) # right
|
Chris@1296
|
4132 else
|
Chris@1296
|
4133 Line(@l_margin + width * i0, @max_td_y[j0], @l_margin + width * i0, @page_break_trigger) # left
|
Chris@1296
|
4134 Line(@l_margin + width * (i1+1), @max_td_y[j0], @l_margin + width * (i1+1), @page_break_trigger) # right
|
Chris@1296
|
4135 @page += 1;
|
Chris@1296
|
4136 while @page < @max_td_page[j1 + 1]
|
Chris@1296
|
4137 Line(@l_margin + width * i0, @t_margin, @l_margin + width * i0, @page_break_trigger) # left
|
Chris@1296
|
4138 Line(@l_margin + width * (i1+1), @t_margin, @l_margin + width * (i1+1), @page_break_trigger) # right
|
Chris@1296
|
4139 @page += 1;
|
Chris@1296
|
4140 end
|
Chris@1296
|
4141 Line(@l_margin + width * i0, @t_margin, @l_margin + width * i0, @max_td_y[j1+1]) # left
|
Chris@1296
|
4142 Line(@l_margin + width * (i1+1), @t_margin, @l_margin + width * (i1+1), @max_td_y[j1+1]) # right
|
Chris@1296
|
4143 end
|
Chris@1296
|
4144 Line(@l_margin + width * i0, @max_td_y[j1+1], @l_margin + width * (i1+1), @max_td_y[j1+1]) # bottom
|
Chris@1296
|
4145 end
|
Chris@1296
|
4146 end
|
Chris@1296
|
4147
|
Chris@1296
|
4148 @l_margin -= 5;
|
Chris@1296
|
4149 @r_margin -= 5;
|
Chris@1296
|
4150 @tableborder=0;
|
Chris@1296
|
4151 @table_id += 1;
|
Chris@1296
|
4152
|
Chris@1296
|
4153 when 'strong'
|
Chris@1296
|
4154 SetStyle('b', false);
|
Chris@1296
|
4155
|
Chris@1296
|
4156 when 'em'
|
Chris@1296
|
4157 SetStyle('i', false);
|
Chris@1296
|
4158
|
Chris@1296
|
4159 when 'ins'
|
Chris@1296
|
4160 SetStyle('u', false);
|
Chris@1296
|
4161
|
Chris@1296
|
4162 when 'del'
|
Chris@1296
|
4163 SetStyle('d', false);
|
Chris@1296
|
4164
|
Chris@1296
|
4165 when 'b', 'i', 'u'
|
Chris@1296
|
4166 SetStyle(tag, false);
|
Chris@1296
|
4167
|
Chris@1296
|
4168 when 'a'
|
Chris@1296
|
4169 @href = nil;
|
Chris@1296
|
4170
|
Chris@1296
|
4171 when 'p'
|
Chris@1296
|
4172 Ln();
|
Chris@1296
|
4173
|
Chris@1296
|
4174 when 'sup'
|
Chris@1296
|
4175 currentfont_size = @font_size;
|
Chris@1296
|
4176 SetFontSize(@tempfontsize);
|
Chris@1296
|
4177 @tempfontsize = @font_size_pt;
|
Chris@1296
|
4178 SetXY(GetX(), GetY() - ((currentfont_size - @font_size)*(@@k_small_ratio)));
|
Chris@1296
|
4179
|
Chris@1296
|
4180 when 'sub'
|
Chris@1296
|
4181 currentfont_size = @font_size;
|
Chris@1296
|
4182 SetFontSize(@tempfontsize);
|
Chris@1296
|
4183 @tempfontsize = @font_size_pt;
|
Chris@1296
|
4184 SetXY(GetX(), GetY() + ((currentfont_size - @font_size)*(@@k_small_ratio)));
|
Chris@1296
|
4185
|
Chris@1296
|
4186 when 'small'
|
Chris@1296
|
4187 currentfont_size = @font_size;
|
Chris@1296
|
4188 SetFontSize(@tempfontsize);
|
Chris@1296
|
4189 @tempfontsize = @font_size_pt;
|
Chris@1296
|
4190 SetXY(GetX(), GetY() - ((@font_size - currentfont_size)/3));
|
Chris@1296
|
4191
|
Chris@1296
|
4192 when 'font'
|
Chris@1296
|
4193 if (@issetcolor == true)
|
Chris@1296
|
4194 SetTextColor(@prevtext_color[0], @prevtext_color[1], @prevtext_color[2]);
|
Chris@1296
|
4195 end
|
Chris@1296
|
4196 if (@issetfont)
|
Chris@1296
|
4197 @font_family = @prevfont_family;
|
Chris@1296
|
4198 @font_style = @prevfont_style;
|
Chris@1296
|
4199 SetFont(@font_family);
|
Chris@1296
|
4200 @issetfont = false;
|
Chris@1296
|
4201 end
|
Chris@1296
|
4202 currentfont_size = @font_size;
|
Chris@1296
|
4203 SetFontSize(@tempfontsize);
|
Chris@1296
|
4204 @tempfontsize = @font_size_pt;
|
Chris@1296
|
4205 #@text_color = @prevtext_color;
|
Chris@1296
|
4206 @lasth = @font_size * @@k_cell_height_ratio;
|
Chris@1296
|
4207
|
Chris@1296
|
4208 when 'blockquote'
|
Chris@1296
|
4209 @quote_count -= 1
|
Chris@1296
|
4210 if (@quote_page[@quote_count] == @page)
|
Chris@1296
|
4211 Line(@l_margin - 1, @quote_top[@quote_count], @l_margin - 1, @y) # quoto line
|
Chris@1296
|
4212 else
|
Chris@1296
|
4213 cur_page = @page;
|
Chris@1296
|
4214 cur_y = @y;
|
Chris@1296
|
4215 @page = @quote_page[@quote_count];
|
Chris@1296
|
4216 if (@quote_top[@quote_count] < @page_break_trigger)
|
Chris@1296
|
4217 Line(@l_margin - 1, @quote_top[@quote_count], @l_margin - 1, @page_break_trigger) # quoto line
|
Chris@1296
|
4218 end
|
Chris@1296
|
4219 @page += 1;
|
Chris@1296
|
4220 while @page < cur_page
|
Chris@1296
|
4221 Line(@l_margin - 1, @t_margin, @l_margin - 1, @page_break_trigger) # quoto line
|
Chris@1296
|
4222 @page += 1;
|
Chris@1296
|
4223 end
|
Chris@1296
|
4224 @y = cur_y;
|
Chris@1296
|
4225 Line(@l_margin - 1, @t_margin, @l_margin - 1, @y) # quoto line
|
Chris@1296
|
4226 end
|
Chris@1296
|
4227 if (@quote_count <= 0)
|
Chris@1296
|
4228 SetStyle('i', false);
|
Chris@1296
|
4229 @l_margin -= 5;
|
Chris@1296
|
4230 else
|
Chris@1296
|
4231 @l_margin -= 5 / 2;
|
Chris@1296
|
4232 end
|
Chris@1296
|
4233 @x = @l_margin;
|
Chris@1296
|
4234 Ln() if @quote_count == 0
|
Chris@1296
|
4235
|
Chris@1296
|
4236 when 'ul', 'ol'
|
Chris@1296
|
4237 @li_count -= 1
|
Chris@1296
|
4238 if @li_state == true
|
Chris@1296
|
4239 Ln();
|
Chris@1296
|
4240 @li_state = false;
|
Chris@1296
|
4241 end
|
Chris@1296
|
4242
|
Chris@1296
|
4243 when 'li'
|
Chris@1296
|
4244 @li_spacer = "";
|
Chris@1296
|
4245 if @li_state == true
|
Chris@1296
|
4246 Ln();
|
Chris@1296
|
4247 @li_state = false;
|
Chris@1296
|
4248 end
|
Chris@1296
|
4249
|
Chris@1296
|
4250 when 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
|
Chris@1296
|
4251 SetFontSize(@tempfontsize);
|
Chris@1296
|
4252 @tempfontsize = @font_size_pt;
|
Chris@1296
|
4253 SetStyle('b', false);
|
Chris@1296
|
4254 Ln();
|
Chris@1296
|
4255 @lasth = @font_size * @@k_cell_height_ratio;
|
Chris@1296
|
4256
|
Chris@1296
|
4257 if tag == 'h1' or tag == 'h2' or tag == 'h3' or tag == 'h4'
|
Chris@1296
|
4258 margin = 1;
|
Chris@1296
|
4259 hrWidth = @w - @l_margin - @r_margin - margin;
|
Chris@1296
|
4260 if tag == 'h1' or tag == 'h2'
|
Chris@1296
|
4261 SetLineWidth(0.2);
|
Chris@1296
|
4262 else
|
Chris@1296
|
4263 SetLineWidth(0.1);
|
Chris@1296
|
4264 end
|
Chris@1296
|
4265 Line(@x + margin, @y, @x + hrWidth, @y);
|
Chris@1296
|
4266 end
|
Chris@1296
|
4267 end
|
Chris@1296
|
4268 end
|
Chris@1296
|
4269
|
Chris@1296
|
4270 #
|
Chris@1296
|
4271 # Sets font style.
|
Chris@1296
|
4272 # @param string :tag tag name (in lowercase)
|
Chris@1296
|
4273 # @param boolean :enable
|
Chris@1296
|
4274 # @access private
|
Chris@1296
|
4275 #
|
Chris@1296
|
4276 def SetStyle(tag, enable)
|
Chris@1296
|
4277 #Modify style and select corresponding font
|
Chris@1296
|
4278 ['b', 'i', 'u', 'd'].each do |s|
|
Chris@1296
|
4279 if tag.downcase == s
|
Chris@1296
|
4280 if enable
|
Chris@1296
|
4281 @style << s if ! @style.include?(s)
|
Chris@1296
|
4282 else
|
Chris@1296
|
4283 @style = @style.gsub(s,'')
|
Chris@1296
|
4284 end
|
Chris@1296
|
4285 end
|
Chris@1296
|
4286 end
|
Chris@1296
|
4287 SetFont('', @style);
|
Chris@1296
|
4288 end
|
Chris@1296
|
4289
|
Chris@1296
|
4290 #
|
Chris@1296
|
4291 # Output anchor link.
|
Chris@1296
|
4292 # @param string :url link URL
|
Chris@1296
|
4293 # @param string :name link name
|
Chris@1296
|
4294 # @param int :fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.
|
Chris@1296
|
4295 # @access public
|
Chris@1296
|
4296 #
|
Chris@1296
|
4297 def addHtmlLink(url, name, fill=0)
|
Chris@1296
|
4298 #Put a hyperlink
|
Chris@1296
|
4299 SetTextColor(0, 0, 255);
|
Chris@1296
|
4300 SetStyle('u', true);
|
Chris@1296
|
4301 Write(@lasth, name, url, fill);
|
Chris@1296
|
4302 SetStyle('u', false);
|
Chris@1296
|
4303 SetTextColor(0);
|
Chris@1296
|
4304 end
|
Chris@1296
|
4305
|
Chris@1296
|
4306 #
|
Chris@1296
|
4307 # Returns an associative array (keys: R,G,B) from
|
Chris@1296
|
4308 # a hex html code (e.g. #3FE5AA).
|
Chris@1296
|
4309 # @param string :color hexadecimal html color [#rrggbb]
|
Chris@1296
|
4310 # @return array
|
Chris@1296
|
4311 # @access private
|
Chris@1296
|
4312 #
|
Chris@1296
|
4313 def convertColorHexToDec(color = "#000000")
|
Chris@1296
|
4314 tbl_color = {}
|
Chris@1296
|
4315 tbl_color['R'] = color[1,2].hex.to_i;
|
Chris@1296
|
4316 tbl_color['G'] = color[3,2].hex.to_i;
|
Chris@1296
|
4317 tbl_color['B'] = color[5,2].hex.to_i;
|
Chris@1296
|
4318 return tbl_color;
|
Chris@1296
|
4319 end
|
Chris@1296
|
4320
|
Chris@1296
|
4321 #
|
Chris@1296
|
4322 # Converts pixels to millimeters in 72 dpi.
|
Chris@1296
|
4323 # @param int :px pixels
|
Chris@1296
|
4324 # @return float millimeters
|
Chris@1296
|
4325 # @access private
|
Chris@1296
|
4326 #
|
Chris@1296
|
4327 def pixelsToMillimeters(px)
|
Chris@1296
|
4328 return px.to_f * 25.4 / 72;
|
Chris@1296
|
4329 end
|
Chris@1296
|
4330
|
Chris@1296
|
4331 #
|
Chris@1296
|
4332 # Reverse function for htmlentities.
|
Chris@1296
|
4333 # Convert entities in UTF-8.
|
Chris@1296
|
4334 #
|
Chris@1296
|
4335 # @param :text_to_convert Text to convert.
|
Chris@1296
|
4336 # @return string converted
|
Chris@1296
|
4337 #
|
Chris@1296
|
4338 def unhtmlentities(string)
|
Chris@1296
|
4339 CGI.unescapeHTML(string)
|
Chris@1296
|
4340 end
|
Chris@1296
|
4341
|
Chris@1296
|
4342 end # END OF CLASS
|
Chris@1296
|
4343
|
Chris@1296
|
4344 #TODO 2007-05-25 (EJM) Level=0 -
|
Chris@1296
|
4345 #Handle special IE contype request
|
Chris@1296
|
4346 # if (!_SERVER['HTTP_USER_AGENT'].nil? and (_SERVER['HTTP_USER_AGENT']=='contype'))
|
Chris@1296
|
4347 # header('Content-Type: application/pdf');
|
Chris@1296
|
4348 # exit;
|
Chris@1296
|
4349 # }
|