rbpdf 1.21.2 → 1.21.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +12 -0
- data/README.md +1 -1
- data/lib/core/mini_magick.rb +12 -2
- data/lib/core/rmagick.rb +1 -0
- data/lib/htmlcolors.rb +1 -0
- data/lib/rbpdf/version.rb +3 -2
- data/lib/rbpdf.rb +2195 -564
- data/rbpdf.gemspec +1 -1
- metadata +3 -6
data/lib/rbpdf.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# coding: ASCII-8BIT
|
2
|
+
# frozen_string_literal: true
|
2
3
|
#============================================================+
|
3
4
|
# File name : rbpdf.rb
|
4
5
|
# Begin : 2002-08-03
|
@@ -59,6 +60,12 @@ rescue LoadError
|
|
59
60
|
# MiniMagick is not available
|
60
61
|
end
|
61
62
|
|
63
|
+
begin
|
64
|
+
require 'marcel' unless Object.const_defined?(:Marcel)
|
65
|
+
rescue LoadError
|
66
|
+
# Marcel is not available
|
67
|
+
end
|
68
|
+
|
62
69
|
unless Object.const_defined?(:MiniMagick)
|
63
70
|
begin
|
64
71
|
# RMagick 2.14.0
|
@@ -234,7 +241,7 @@ class RBPDF
|
|
234
241
|
# This is the class constructor.
|
235
242
|
# It allows to set up the page format, the orientation and
|
236
243
|
# the measure unit used in all the methods (except for the font sizes).
|
237
|
-
# @since 1.0
|
244
|
+
# [@since 1.0]
|
238
245
|
# [@param string :orientation]
|
239
246
|
# page orientation. Possible values are (case insensitive):
|
240
247
|
# * P or Portrait (default)
|
@@ -330,13 +337,16 @@ class RBPDF
|
|
330
337
|
@listindent ||= 0
|
331
338
|
@listindentlevel ||= 0
|
332
339
|
@lispacer ||= ""
|
340
|
+
@li_position_x = nil
|
333
341
|
|
334
342
|
# bookmark
|
335
343
|
@outlines ||= []
|
336
344
|
|
337
345
|
# --- javascript and form ---
|
338
|
-
@javascript ||= ''
|
339
|
-
@js_objects ||=
|
346
|
+
@javascript ||= +''
|
347
|
+
@js_objects ||= {}
|
348
|
+
@js_start_obj_id ||= 300000
|
349
|
+
@js_obj_id ||= 300000
|
340
350
|
|
341
351
|
@dpi = 72.0
|
342
352
|
@newpagegroup ||= []
|
@@ -394,6 +404,7 @@ class RBPDF
|
|
394
404
|
@page_obj_id ||= []
|
395
405
|
@embedded_start_obj_id ||= 100000
|
396
406
|
@form_obj_id ||= []
|
407
|
+
@default_form_prop ||= {'lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>[255, 255, 255], 'strokeColor'=>[128, 128, 128]}
|
397
408
|
@apxo_start_obj_id ||= 400000
|
398
409
|
@apxo_obj_id ||= 400000
|
399
410
|
@annotation_fonts ||= {}
|
@@ -444,8 +455,9 @@ class RBPDF
|
|
444
455
|
if @diskcache
|
445
456
|
@buffer ||= nil
|
446
457
|
else
|
447
|
-
@buffer ||= ''
|
458
|
+
@buffer ||= +''
|
448
459
|
end
|
460
|
+
@tmp_buffer = nil
|
449
461
|
@pages ||= []
|
450
462
|
@prev_pages ||= []
|
451
463
|
@state ||= 0
|
@@ -525,18 +537,9 @@ class RBPDF
|
|
525
537
|
@href ||= {}
|
526
538
|
@fontlist ||= []
|
527
539
|
getFontsList()
|
528
|
-
@fgcolor =
|
529
|
-
@
|
530
|
-
@
|
531
|
-
@fgcolor['B'] = 0
|
532
|
-
@strokecolor = ActiveSupport::OrderedHash.new
|
533
|
-
@strokecolor['R'] = 0
|
534
|
-
@strokecolor['G'] = 0
|
535
|
-
@strokecolor['B'] = 0
|
536
|
-
@bgcolor = ActiveSupport::OrderedHash.new
|
537
|
-
@bgcolor['R'] = 255
|
538
|
-
@bgcolor['G'] = 255
|
539
|
-
@bgcolor['B'] = 255
|
540
|
+
@fgcolor = [0, 0, 0]
|
541
|
+
@strokecolor = [0, 0, 0]
|
542
|
+
@bgcolor = [255, 255, 255]
|
540
543
|
@extgstates ||= []
|
541
544
|
|
542
545
|
# user's rights
|
@@ -1452,7 +1455,7 @@ class RBPDF
|
|
1452
1455
|
#
|
1453
1456
|
# Defines the title of the document.
|
1454
1457
|
# [@param string :title] The title.
|
1455
|
-
# [@access public
|
1458
|
+
# [@access public]
|
1456
1459
|
# [@since 1.2]
|
1457
1460
|
# [@see] SetAuthor(), SetCreator(), SetKeywords(), SetSubject()
|
1458
1461
|
#
|
@@ -2295,20 +2298,15 @@ class RBPDF
|
|
2295
2298
|
if (col2 == -1) and (col3 == -1) and (col4 == -1)
|
2296
2299
|
# Grey scale
|
2297
2300
|
@draw_color = sprintf('%.3f G', col1 / 255.0)
|
2298
|
-
@strokecolor
|
2301
|
+
@strokecolor = [col1]
|
2299
2302
|
elsif col4 == -1
|
2300
2303
|
# RGB
|
2301
2304
|
@draw_color = sprintf('%.3f %.3f %.3f RG', col1 / 255.0, col2 / 255.0, col3 / 255.0)
|
2302
|
-
@strokecolor
|
2303
|
-
@strokecolor['G'] = col2
|
2304
|
-
@strokecolor['B'] = col3
|
2305
|
+
@strokecolor = [col1, col2, col3]
|
2305
2306
|
else
|
2306
2307
|
# CMYK
|
2307
2308
|
@draw_color = sprintf('%.3f %.3f %.3f %.3f K', col1 / 100.0, col2 / 100.0, col3 / 100.0, col4 / 100.0)
|
2308
|
-
@strokecolor
|
2309
|
-
@strokecolor['M'] = col2
|
2310
|
-
@strokecolor['Y'] = col3
|
2311
|
-
@strokecolor['K'] = col4
|
2309
|
+
@strokecolor = [col1, col2, col3, col4]
|
2312
2310
|
end
|
2313
2311
|
if (@page>0)
|
2314
2312
|
out(@draw_color + ' ')
|
@@ -2368,20 +2366,15 @@ class RBPDF
|
|
2368
2366
|
if (col2 == -1) and (col3 == -1) and (col4 == -1)
|
2369
2367
|
# Grey scale
|
2370
2368
|
@fill_color = sprintf('%.3f g', col1 / 255.0)
|
2371
|
-
@bgcolor
|
2369
|
+
@bgcolor = [col1]
|
2372
2370
|
elsif col4 == -1
|
2373
2371
|
# RGB
|
2374
2372
|
@fill_color = sprintf('%.3f %.3f %.3f rg', col1 / 255.0, col2 / 255.0, col3 / 255.0)
|
2375
|
-
@bgcolor
|
2376
|
-
@bgcolor['G'] = col2
|
2377
|
-
@bgcolor['B'] = col3
|
2373
|
+
@bgcolor = [col1, col2, col3]
|
2378
2374
|
else
|
2379
2375
|
# CMYK
|
2380
2376
|
@fill_color = sprintf('%.3f %.3f %.3f %.3f k', col1 / 100.0, col2 / 100.0, col3 / 100.0, col4 / 100.0)
|
2381
|
-
@bgcolor
|
2382
|
-
@bgcolor['M'] = col2
|
2383
|
-
@bgcolor['Y'] = col3
|
2384
|
-
@bgcolor['K'] = col4
|
2377
|
+
@bgcolor = [col1, col2, col3, col4]
|
2385
2378
|
end
|
2386
2379
|
|
2387
2380
|
@color_flag = (@fill_color != @text_color)
|
@@ -2458,20 +2451,16 @@ class RBPDF
|
|
2458
2451
|
if (col2 == -1) and (col3 == -1) and (col4 == -1)
|
2459
2452
|
# Grey scale
|
2460
2453
|
@text_color = sprintf('%.3f g', col1 / 255.0)
|
2461
|
-
@fgcolor
|
2454
|
+
@fgcolor = [col1]
|
2462
2455
|
elsif col4 == -1
|
2463
2456
|
# RGB
|
2464
2457
|
@text_color = sprintf('%.3f %.3f %.3f rg', col1 / 255.0, col2 / 255.0, col3 / 255.0)
|
2465
|
-
@fgcolor
|
2466
|
-
|
2467
|
-
@fgcolor['B'] = col3
|
2458
|
+
@fgcolor = [col1, col2, col3]
|
2459
|
+
|
2468
2460
|
else
|
2469
2461
|
# CMYK
|
2470
2462
|
@text_color = sprintf('%.3f %.3f %.3f %.3f k', col1 / 100.0, col2 / 100.0, col3 / 100.0, col4 / 100.0)
|
2471
|
-
@fgcolor
|
2472
|
-
@fgcolor['M'] = col2
|
2473
|
-
@fgcolor['Y'] = col3
|
2474
|
-
@fgcolor['K'] = col4
|
2463
|
+
@fgcolor = [col1, col2, col3, col4]
|
2475
2464
|
end
|
2476
2465
|
@color_flag = (@fill_color != @text_color)
|
2477
2466
|
end
|
@@ -2663,7 +2652,7 @@ class RBPDF
|
|
2663
2652
|
end
|
2664
2653
|
|
2665
2654
|
tempstyle = style.upcase
|
2666
|
-
style = ''
|
2655
|
+
style = +''
|
2667
2656
|
# underline
|
2668
2657
|
if tempstyle.index('U') != nil
|
2669
2658
|
@underline = true
|
@@ -3464,8 +3453,8 @@ class RBPDF
|
|
3464
3453
|
# [@see] Cell()
|
3465
3454
|
#
|
3466
3455
|
def getCellCode(w, h=0, txt='', border=0, ln=0, align='', fill=0, link=nil, stretch=0, ignore_min_height=false, calign='T', valign='M')
|
3467
|
-
txt = '' if txt.nil?
|
3468
|
-
rs = "" # string to be returned
|
3456
|
+
txt = +'' if txt.nil?
|
3457
|
+
rs = +"" # string to be returned
|
3469
3458
|
txt = removeSHY(txt)
|
3470
3459
|
if !ignore_min_height
|
3471
3460
|
min_cell_height = @font_size * @cell_height_ratio
|
@@ -3547,7 +3536,7 @@ class RBPDF
|
|
3547
3536
|
w = @w - @r_margin - x
|
3548
3537
|
end
|
3549
3538
|
end
|
3550
|
-
s = '';
|
3539
|
+
s = +'';
|
3551
3540
|
# fill and borders
|
3552
3541
|
if (fill == 1) or (border.to_i == 1)
|
3553
3542
|
if (fill == 1)
|
@@ -4025,7 +4014,9 @@ class RBPDF
|
|
4025
4014
|
ccode = getCellCode(w, h, '', border, 1, '', fill, '', 0, true)
|
4026
4015
|
@lasth = prevLastH
|
4027
4016
|
|
4028
|
-
if
|
4017
|
+
if @tmp_buffer
|
4018
|
+
@tmp_buffer = "#{ccode}\n#{@tmp_buffer}"
|
4019
|
+
elsif (border != 0) or (fill == 1)
|
4029
4020
|
if !@transfmrk[@page].nil?
|
4030
4021
|
pagemark = @transfmrk[@page]
|
4031
4022
|
@transfmrk[@page] += (ccode + "\n").length
|
@@ -4081,7 +4072,7 @@ class RBPDF
|
|
4081
4072
|
# * T: top
|
4082
4073
|
# * R: right
|
4083
4074
|
# * B: bottom
|
4084
|
-
# [@param string multicell position
|
4075
|
+
# [@param string multicell :position] 'start', 'middle', 'end'
|
4085
4076
|
# [@return mixed] border mode
|
4086
4077
|
# [@access protected]
|
4087
4078
|
# [@since 4.4.002 (2008-12-09)]
|
@@ -4091,7 +4082,7 @@ class RBPDF
|
|
4091
4082
|
return 1
|
4092
4083
|
end
|
4093
4084
|
return 0 if border == 0
|
4094
|
-
cborder = ''
|
4085
|
+
cborder = +''
|
4095
4086
|
case position
|
4096
4087
|
when 'start'
|
4097
4088
|
if border == 1
|
@@ -4686,7 +4677,7 @@ class RBPDF
|
|
4686
4677
|
# [@access public]
|
4687
4678
|
#
|
4688
4679
|
def UTF8ArrSubString(strarr, start=0, last=strarr.size)
|
4689
|
-
string = ""
|
4680
|
+
string = +""
|
4690
4681
|
start.upto(last - 1) do |i|
|
4691
4682
|
string << unichr(strarr[i])
|
4692
4683
|
end
|
@@ -4704,7 +4695,7 @@ class RBPDF
|
|
4704
4695
|
# [@since 4.5.037 (2009-04-07)]
|
4705
4696
|
#
|
4706
4697
|
def UniArrSubString(uniarr, start=0, last=uniarr.length)
|
4707
|
-
string = ''
|
4698
|
+
string = +''
|
4708
4699
|
start.upto(last - 1) do |i|
|
4709
4700
|
string << uniarr[i]
|
4710
4701
|
end
|
@@ -5156,7 +5147,7 @@ class RBPDF
|
|
5156
5147
|
end
|
5157
5148
|
bpc=!a['bits'].nil? ? a['bits'] : 8;
|
5158
5149
|
#Read whole file
|
5159
|
-
data
|
5150
|
+
data=+'';
|
5160
5151
|
open(file,'rb') do |f|
|
5161
5152
|
data << f.read()
|
5162
5153
|
end
|
@@ -5269,9 +5260,9 @@ class RBPDF
|
|
5269
5260
|
f.read(4)
|
5270
5261
|
parms='/DecodeParms <</Predictor 15 /Colors ' + (ct == 2 ? 3 : 1).to_s + ' /BitsPerComponent ' + bpc.to_s + ' /Columns ' + w.to_s + '>>'
|
5271
5262
|
# Scan chunks looking for palette, transparency and image data
|
5272
|
-
pal = ''
|
5273
|
-
trns = ''
|
5274
|
-
data = ''
|
5263
|
+
pal = +''
|
5264
|
+
trns = +''
|
5265
|
+
data = +''
|
5275
5266
|
begin
|
5276
5267
|
n = freadint(f)
|
5277
5268
|
type = f.read(4)
|
@@ -5704,7 +5695,7 @@ class RBPDF
|
|
5704
5695
|
self.instance_variables.each { |val|
|
5705
5696
|
if destroyall or ((val != '@internal_encoding') and (val != '@state') and (val != '@bufferlen') and (val != '@buffer') and (val != '@diskcache') and (val != '@sign') and (val != '@signature_data') and (val != '@signature_max_length') and (val != '@byterange_string'))
|
5706
5697
|
if (!preserve_objcopy or (val.to_s != '@objcopy')) and !val.nil?
|
5707
|
-
|
5698
|
+
instance_variable_set(val, nil)
|
5708
5699
|
end
|
5709
5700
|
end
|
5710
5701
|
}
|
@@ -5866,7 +5857,7 @@ protected
|
|
5866
5857
|
temppage = temppage.gsub(@epsmarker, '')
|
5867
5858
|
#Page
|
5868
5859
|
@page_obj_id[n] = newobj()
|
5869
|
-
out = '<<'
|
5860
|
+
out = +'<<'
|
5870
5861
|
out << ' /Type /Page'
|
5871
5862
|
out << ' /Parent 1 0 R'
|
5872
5863
|
out << ' /LastModified ' + datestring()
|
@@ -5956,7 +5947,7 @@ protected
|
|
5956
5947
|
end
|
5957
5948
|
#Pages root
|
5958
5949
|
@offsets[1]=@bufferlen
|
5959
|
-
out = '1 0 obj << /Type /Pages /Kids ['
|
5950
|
+
out = +'1 0 obj << /Type /Pages /Kids ['
|
5960
5951
|
@page_obj_id.each { |page_obj|
|
5961
5952
|
out << ' ' + page_obj.to_s + ' 0 R' unless page_obj.nil?
|
5962
5953
|
}
|
@@ -5986,9 +5977,9 @@ protected
|
|
5986
5977
|
#
|
5987
5978
|
def getannotsrefs(n)
|
5988
5979
|
unless @page_annots[n] or (@sign and @signature_data['cert_type'])
|
5989
|
-
return ''
|
5980
|
+
return +''
|
5990
5981
|
end
|
5991
|
-
out = ' /Annots ['
|
5982
|
+
out = +' /Annots ['
|
5992
5983
|
if @page_annots[n]
|
5993
5984
|
num_annots = @page_annots[n].length
|
5994
5985
|
0.upto(num_annots - 1) do |i|
|
@@ -6026,28 +6017,27 @@ protected
|
|
6026
6017
|
@page_annots[n].each_with_index { |pl, key|
|
6027
6018
|
# create annotation object for grouping radiobuttons
|
6028
6019
|
if @radiobutton_groups[n] and @radiobutton_groups[n][pl['txt']] and @radiobutton_groups[n][pl['txt']].is_a?(Array)
|
6029
|
-
annots = '<<'
|
6020
|
+
annots = +'<<'
|
6030
6021
|
annots << ' /Type /Annot'
|
6031
6022
|
annots << ' /Subtype /Widget'
|
6032
6023
|
annots << ' /T ' + dataannobjstring(pl['txt'])
|
6033
6024
|
annots << ' /FT /Btn'
|
6034
6025
|
annots << ' /Ff 49152'
|
6035
6026
|
annots << ' /Kids ['
|
6027
|
+
defval = nil
|
6036
6028
|
@radiobutton_groups[n][pl['txt']].each {|data|
|
6037
|
-
annots <<
|
6029
|
+
annots << " #{data['kid']} 0 R"
|
6038
6030
|
if data['def'] != 'Off'
|
6039
6031
|
defval = data['def']
|
6040
6032
|
end
|
6041
6033
|
}
|
6042
6034
|
annots << ' ]'
|
6043
|
-
if defval
|
6044
|
-
annots << ' /V /' + defval
|
6045
|
-
end
|
6035
|
+
annots << " /V /#{defval}" if defval
|
6046
6036
|
annots << ' >>'
|
6047
6037
|
@annot_obj_id += 1
|
6048
6038
|
@offsets[@annot_obj_id] = @bufferlen
|
6049
|
-
out(@annot_obj_id
|
6050
|
-
@form_obj_id
|
6039
|
+
out("#{@annot_obj_id} 0 obj #{annots} endobj")
|
6040
|
+
@form_obj_id << @annot_obj_id
|
6051
6041
|
# store object id to be used on Parent entry of Kids
|
6052
6042
|
@radiobutton_groups[n][pl['txt']] = @annot_obj_id
|
6053
6043
|
end
|
@@ -6063,7 +6053,7 @@ protected
|
|
6063
6053
|
d = pl['h'] * @k
|
6064
6054
|
rect = sprintf('%.2f %.2f %.2f %.2f', a, b, a + c, b + d)
|
6065
6055
|
# create new annotation object
|
6066
|
-
annots = '<</Type /Annot'
|
6056
|
+
annots = +'<</Type /Annot'
|
6067
6057
|
annots << ' /Subtype /' + pl['opt']['subtype']
|
6068
6058
|
annots << ' /Rect [' + rect + ']'
|
6069
6059
|
ft = ['Btn', 'Tx', 'Ch', 'Sig']
|
@@ -6105,7 +6095,7 @@ protected
|
|
6105
6095
|
else
|
6106
6096
|
val = pl['opt']['f'].to_i
|
6107
6097
|
end
|
6108
|
-
annots <<
|
6098
|
+
annots << " /F #{val}"
|
6109
6099
|
end
|
6110
6100
|
# annots << ' /AP '
|
6111
6101
|
# annots << ' /AS '
|
@@ -6114,24 +6104,23 @@ protected
|
|
6114
6104
|
end
|
6115
6105
|
if pl['opt']['ap']
|
6116
6106
|
# appearance stream
|
6117
|
-
annots << ' /AP << ' + pl['opt']['ap'] + ' >>'
|
6118
6107
|
annots << ' /AP <<'
|
6119
6108
|
if pl['opt']['ap'].is_a?(Hash)
|
6120
6109
|
pl['opt']['ap'].each {|apmode, apdef|
|
6121
6110
|
# apmode can be: n = normal; r = rollover; d = down
|
6122
6111
|
annots << ' /' + apmode.upcase
|
6123
|
-
if apdef.is_a?(
|
6112
|
+
if apdef.is_a?(Hash)
|
6124
6113
|
annots << ' <<'
|
6125
6114
|
apdef.each {|apstate, stream|
|
6126
6115
|
# reference to XObject that define the appearance for this mode-state
|
6127
6116
|
apsobjid = putAPXObject(c, d, stream)
|
6128
|
-
annots <<
|
6117
|
+
annots << " /#{apstate} #{apsobjid} 0 R"
|
6129
6118
|
}
|
6130
6119
|
annots << ' >>'
|
6131
6120
|
else
|
6132
6121
|
# reference to XObject that define the appearance for this mode
|
6133
6122
|
apsobjid = putAPXObject(c, d, apdef)
|
6134
|
-
annots <<
|
6123
|
+
annots << " #{apsobjid} 0 R"
|
6135
6124
|
end
|
6136
6125
|
}
|
6137
6126
|
else
|
@@ -6143,7 +6132,7 @@ protected
|
|
6143
6132
|
annots << ' /BS <<'
|
6144
6133
|
annots << ' /Type /Border'
|
6145
6134
|
if !pl['opt']['bs']['w'].nil?
|
6146
|
-
annots <<
|
6135
|
+
annots << " /W #{pl['opt']['bs']['w']}"
|
6147
6136
|
end
|
6148
6137
|
bstyles = ['S', 'D', 'B', 'I', 'U']
|
6149
6138
|
if !pl['opt']['bs']['s'].nil? and bstyles.include?(pl['opt']['bs']['s'])
|
@@ -6205,7 +6194,7 @@ protected
|
|
6205
6194
|
if !pl['opt']['t'].nil? and pl['opt']['t'].is_a?(String)
|
6206
6195
|
annots << ' /T ' + textannobjstring(pl['opt']['t'])
|
6207
6196
|
end
|
6208
|
-
# annots
|
6197
|
+
# annots << ' /Popup '
|
6209
6198
|
if !pl['opt']['ca'].nil?
|
6210
6199
|
annots << ' /CA ' + sprintf("%.4f", pl['opt']['ca'].to_f)
|
6211
6200
|
end
|
@@ -6420,9 +6409,9 @@ protected
|
|
6420
6409
|
end # end MK
|
6421
6410
|
|
6422
6411
|
# --- Entries for field dictionaries ---
|
6423
|
-
if @radiobutton_groups[n][pl['txt']]
|
6412
|
+
if @radiobutton_groups[n] and @radiobutton_groups[n][pl['txt']]
|
6424
6413
|
# set parent
|
6425
|
-
annots <<
|
6414
|
+
annots << " /Parent #{@radiobutton_groups[n][pl['txt']]} 0 R"
|
6426
6415
|
end
|
6427
6416
|
if pl['opt']['t'] and pl['opt']['t'].is_a?(String)
|
6428
6417
|
annots << ' /T ' + dataannobjstring(pl['opt']['t'])
|
@@ -6443,7 +6432,7 @@ protected
|
|
6443
6432
|
else
|
6444
6433
|
flag = pl['opt']['ff'].to_i
|
6445
6434
|
end
|
6446
|
-
annots <<
|
6435
|
+
annots << " /Ff #{flag}"
|
6447
6436
|
end
|
6448
6437
|
if pl['opt']['maxlen']
|
6449
6438
|
annots << ' /MaxLen ' + pl['opt']['maxlen'].to_i.to_s
|
@@ -6529,9 +6518,9 @@ protected
|
|
6529
6518
|
@offsets[@annot_obj_id] = @bufferlen
|
6530
6519
|
out(@annot_obj_id.to_s + ' 0 obj ' + annots + ' endobj')
|
6531
6520
|
|
6532
|
-
if formfield and ! @radiobutton_groups[n][pl['txt']]
|
6521
|
+
if formfield and !(@radiobutton_groups[n] and @radiobutton_groups[n][pl['txt']])
|
6533
6522
|
# store reference of form object
|
6534
|
-
@form_obj_id
|
6523
|
+
@form_obj_id << @annot_obj_id
|
6535
6524
|
end
|
6536
6525
|
}
|
6537
6526
|
end # end for each page
|
@@ -6563,7 +6552,7 @@ protected
|
|
6563
6552
|
rect = sprintf('%.2f %.2f', w, h)
|
6564
6553
|
out << ' /BBox [0 0 ' + rect + ']'
|
6565
6554
|
out << ' /Matrix [1 0 0 1 0 0]'
|
6566
|
-
out << ' /Resources
|
6555
|
+
out << ' /Resources 2 0 R'
|
6567
6556
|
out << ' /Length ' + stream.length.to_s
|
6568
6557
|
out << ' >>'
|
6569
6558
|
out << ' ' + getstream(stream)
|
@@ -6855,7 +6844,7 @@ protected
|
|
6855
6844
|
subsetglyphs = subsetglyphs_tmp
|
6856
6845
|
|
6857
6846
|
# build new glyf table with only used glyphs
|
6858
|
-
glyf = ''
|
6847
|
+
glyf = +''
|
6859
6848
|
glyfSize = 0
|
6860
6849
|
# create new empty indexToLoc table
|
6861
6850
|
newIndexToLoc = Array.new(indexToLoc.length, 0)
|
@@ -6871,7 +6860,7 @@ protected
|
|
6871
6860
|
end
|
6872
6861
|
}
|
6873
6862
|
# build new loca table
|
6874
|
-
loca = ''
|
6863
|
+
loca = +''
|
6875
6864
|
if short_offset
|
6876
6865
|
newIndexToLoc.each {|offset|
|
6877
6866
|
loca << [offset / 2].pack('n')
|
@@ -6933,7 +6922,7 @@ protected
|
|
6933
6922
|
table['glyf']['offset'] = offset
|
6934
6923
|
table['glyf']['checkSum'] = getTTFtableChecksum(table['glyf']['data'], table['glyf']['length'])
|
6935
6924
|
# rebuild font
|
6936
|
-
font = ''
|
6925
|
+
font = +''
|
6937
6926
|
font << [0x10000].pack('N') # sfnt version
|
6938
6927
|
numTables = table.length
|
6939
6928
|
font << [numTables].pack('n') # numTables
|
@@ -7074,7 +7063,7 @@ protected
|
|
7074
7063
|
end
|
7075
7064
|
}
|
7076
7065
|
# output data
|
7077
|
-
w = ''
|
7066
|
+
w = +''
|
7078
7067
|
range.each_with_index {|ws, k|
|
7079
7068
|
if ws and ws.uniq.length == 1
|
7080
7069
|
# interval mode is more compact
|
@@ -7149,7 +7138,7 @@ protected
|
|
7149
7138
|
end
|
7150
7139
|
newobj()
|
7151
7140
|
@font_files[file]['n'] = @n
|
7152
|
-
out = '<</Length '+ font.length.to_s
|
7141
|
+
out = +'<</Length '+ font.length.to_s
|
7153
7142
|
if compressed
|
7154
7143
|
out << ' /Filter /FlateDecode'
|
7155
7144
|
end
|
@@ -7163,7 +7152,7 @@ protected
|
|
7163
7152
|
out(out)
|
7164
7153
|
end
|
7165
7154
|
end
|
7166
|
-
@fontkeys.
|
7155
|
+
@fontkeys.each_with_index do |k, i|
|
7167
7156
|
#Font objects
|
7168
7157
|
setFontSubBuffer(k, 'n', @n + 1)
|
7169
7158
|
font = getFontBuffer(k)
|
@@ -7172,7 +7161,7 @@ protected
|
|
7172
7161
|
if (type=='core')
|
7173
7162
|
# standard core font
|
7174
7163
|
obj_id = newobj()
|
7175
|
-
out = '<</Type /Font'
|
7164
|
+
out = +'<</Type /Font'
|
7176
7165
|
out << ' /Subtype /Type1'
|
7177
7166
|
out << ' /BaseFont /' + name
|
7178
7167
|
out << ' /Name /F' + font['i'].to_s
|
@@ -7181,14 +7170,14 @@ protected
|
|
7181
7170
|
end
|
7182
7171
|
if name.downcase == 'helvetica'
|
7183
7172
|
# add default font for annotations
|
7184
|
-
@annotation_fonts['helvetica'] =
|
7173
|
+
@annotation_fonts['helvetica'] = i
|
7185
7174
|
end
|
7186
7175
|
out << ' >> endobj'
|
7187
7176
|
out(out)
|
7188
7177
|
elsif (type=='Type1' || type=='TrueType')
|
7189
7178
|
# additional Type1 or TrueType font
|
7190
7179
|
obj_id = newobj()
|
7191
|
-
out = '<</Type /Font'
|
7180
|
+
out = +'<</Type /Font'
|
7192
7181
|
out << ' /Subtype /' + type
|
7193
7182
|
out << ' /BaseFont /' + name
|
7194
7183
|
out << ' /Name /F' + font['i'].to_s
|
@@ -7232,9 +7221,9 @@ protected
|
|
7232
7221
|
Error('Unsupported font type: ' + type)
|
7233
7222
|
end
|
7234
7223
|
obj_id = self.send(mtd,font)
|
7235
|
-
# store object ID for current font
|
7236
|
-
@font_obj_ids[k] = obj_id
|
7237
7224
|
end
|
7225
|
+
# store object ID for current font
|
7226
|
+
@font_obj_ids[k] = obj_id
|
7238
7227
|
end
|
7239
7228
|
end
|
7240
7229
|
|
@@ -7248,7 +7237,7 @@ protected
|
|
7248
7237
|
# [@since 1.52.0.TC005 (2005-01-05)]
|
7249
7238
|
#
|
7250
7239
|
def puttruetypeunicode(font)
|
7251
|
-
fontname = ''
|
7240
|
+
fontname = +''
|
7252
7241
|
if font['subset']
|
7253
7242
|
# change name for font subsetting
|
7254
7243
|
subtag = sprintf('%06u', font['i'])
|
@@ -7259,7 +7248,7 @@ protected
|
|
7259
7248
|
# Type0 Font
|
7260
7249
|
# A composite font composed of other fonts, organized hierarchically
|
7261
7250
|
obj_id = newobj()
|
7262
|
-
out = '<</Type /Font'
|
7251
|
+
out = +'<</Type /Font'
|
7263
7252
|
out << ' /Subtype /Type0'
|
7264
7253
|
out << ' /BaseFont /' + fontname + ''
|
7265
7254
|
out << ' /Name /F' + font['i'].to_s
|
@@ -7280,7 +7269,7 @@ protected
|
|
7280
7269
|
# CIDFontType2
|
7281
7270
|
# A CIDFont whose glyph descriptions are based on TrueType font technology
|
7282
7271
|
newobj();
|
7283
|
-
out = '<</Type /Font'
|
7272
|
+
out = +'<</Type /Font'
|
7284
7273
|
out << ' /Subtype /CIDFontType2'
|
7285
7274
|
out << ' /BaseFont /' + fontname
|
7286
7275
|
|
@@ -7301,7 +7290,7 @@ protected
|
|
7301
7290
|
# Font descriptor
|
7302
7291
|
# A font descriptor describing the CIDFont default metrics other than its glyph widths
|
7303
7292
|
newobj();
|
7304
|
-
out = '<</Type /FontDescriptor'
|
7293
|
+
out = +'<</Type /FontDescriptor'
|
7305
7294
|
out << ' /FontName /' + fontname
|
7306
7295
|
font['desc'].each do |key, value|
|
7307
7296
|
if value.is_a? Float
|
@@ -7339,7 +7328,7 @@ protected
|
|
7339
7328
|
Error('Font file not found: ' + ctgfile)
|
7340
7329
|
end
|
7341
7330
|
size = File.size(fontfile)
|
7342
|
-
out = '<</Length ' + size.to_s + ''
|
7331
|
+
out = +'<</Length ' + size.to_s + ''
|
7343
7332
|
if (fontfile[-2,2] == '.z') # check file extension
|
7344
7333
|
# Decompresses data encoded using the public-domain
|
7345
7334
|
# zlib/deflate compression method, reproducing the
|
@@ -7392,7 +7381,7 @@ protected
|
|
7392
7381
|
longname = name
|
7393
7382
|
end
|
7394
7383
|
obj_id = newobj()
|
7395
|
-
out = '<</Type /Font'
|
7384
|
+
out = +'<</Type /Font'
|
7396
7385
|
out << ' /Subtype /Type0'
|
7397
7386
|
out << ' /BaseFont /' + longname
|
7398
7387
|
out << ' /Name /F' + font['i'].to_s
|
@@ -7403,7 +7392,7 @@ protected
|
|
7403
7392
|
out << ' >> endobj'
|
7404
7393
|
out(out)
|
7405
7394
|
newobj()
|
7406
|
-
out = '<</Type /Font'
|
7395
|
+
out = +'<</Type /Font'
|
7407
7396
|
out << ' /Subtype /CIDFontType0'
|
7408
7397
|
out << ' /BaseFont /' + name
|
7409
7398
|
cidinfo = '/Registry ' + datastring(font['cidinfo']['Registry'])
|
@@ -7440,7 +7429,7 @@ protected
|
|
7440
7429
|
info = getImageBuffer(file)
|
7441
7430
|
newobj();
|
7442
7431
|
setImageSubBuffer(file, 'n', @n)
|
7443
|
-
out = '<</Type /XObject'
|
7432
|
+
out = +'<</Type /XObject'
|
7444
7433
|
out << ' /Subtype /Image'
|
7445
7434
|
out << ' /Width ' + info['w'].to_s
|
7446
7435
|
out << ' /Height ' + info['h'].to_s
|
@@ -7463,7 +7452,7 @@ protected
|
|
7463
7452
|
out << ' ' + info['parms']
|
7464
7453
|
end
|
7465
7454
|
if (!info['trns'].nil? and info['trns'].kind_of?(Array))
|
7466
|
-
trns
|
7455
|
+
trns=+'';
|
7467
7456
|
count_info = info['trns'].length
|
7468
7457
|
count_info.times do |i|
|
7469
7458
|
trns << info['trns'][i].to_s + ' ' + info['trns'][i].to_s + ' '
|
@@ -7496,14 +7485,14 @@ protected
|
|
7496
7485
|
|
7497
7486
|
#
|
7498
7487
|
# Output Spot Colors Resources.
|
7499
|
-
# [@access protected
|
7488
|
+
# [@access protected]
|
7500
7489
|
# [@since 4.0.024 (2008-09-12)]
|
7501
7490
|
#
|
7502
7491
|
def putspotcolors()
|
7503
7492
|
@spot_colors.each { |name, color|
|
7504
7493
|
newobj()
|
7505
7494
|
@spot_colors[name]['n'] = @n
|
7506
|
-
out = '[/Separation /' + name.gsub(' ', '#20')
|
7495
|
+
out = +'[/Separation /' + name.gsub(' ', '#20')
|
7507
7496
|
out << ' /DeviceCMYK <<'
|
7508
7497
|
out << ' /Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0]'
|
7509
7498
|
out << ' ' + sprintf('/C1 [%.4f %.4f %.4f %.4f] ', color['c']/100.0, color['m']/100.0, color['y']/100.0, color['k']/100.0)
|
@@ -7518,7 +7507,7 @@ protected
|
|
7518
7507
|
# [@access protected]
|
7519
7508
|
#
|
7520
7509
|
def putresourcedict()
|
7521
|
-
out = '2 0 obj'
|
7510
|
+
out = +'2 0 obj'
|
7522
7511
|
out << ' << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'
|
7523
7512
|
out << ' /Font <<'
|
7524
7513
|
@fontkeys.each do |fontkey|
|
@@ -7547,23 +7536,28 @@ protected
|
|
7547
7536
|
end
|
7548
7537
|
}
|
7549
7538
|
out << ' >>'
|
7550
|
-
|
7539
|
+
|
7551
7540
|
# gradient patterns
|
7552
7541
|
if @gradients and !@gradients.empty?
|
7553
7542
|
out << ' /Pattern <<'
|
7554
|
-
@gradients.each_with_index
|
7555
|
-
|
7556
|
-
|
7543
|
+
@gradients.each_with_index do |grad, id|
|
7544
|
+
next unless grad
|
7545
|
+
|
7546
|
+
out << " /p#{id} #{grad['pattern']} 0 R"
|
7547
|
+
end
|
7557
7548
|
out << ' >>'
|
7558
7549
|
end
|
7559
7550
|
# gradient shadings
|
7560
7551
|
if @gradients and !@gradients.empty?
|
7561
7552
|
out << ' /Shading <<'
|
7562
|
-
@gradients.each_with_index
|
7563
|
-
|
7564
|
-
|
7553
|
+
@gradients.each_with_index do |grad, id|
|
7554
|
+
next unless grad
|
7555
|
+
|
7556
|
+
out << " /Sh#{id} #{grad['id']} 0 R"
|
7557
|
+
end
|
7565
7558
|
out << ' >>'
|
7566
7559
|
end
|
7560
|
+
=begin
|
7567
7561
|
# spot colors
|
7568
7562
|
if @spot_colors and !@spot_colors.empty?
|
7569
7563
|
out << ' /ColorSpace <<'
|
@@ -7585,16 +7579,18 @@ protected
|
|
7585
7579
|
mapLinksToHtmlAnchors()
|
7586
7580
|
putextgstates()
|
7587
7581
|
putocg()
|
7588
|
-
putfonts()
|
7589
|
-
putimages()
|
7582
|
+
putfonts()
|
7583
|
+
putimages()
|
7590
7584
|
putspotcolors()
|
7585
|
+
putshaders()
|
7591
7586
|
|
7592
7587
|
#Resource dictionary
|
7593
7588
|
@offsets[2]=@bufferlen
|
7594
|
-
putresourcedict()
|
7589
|
+
putresourcedict()
|
7595
7590
|
putbookmarks()
|
7596
7591
|
putEmbeddedFiles()
|
7597
7592
|
putannotsobjs()
|
7593
|
+
putjavascript()
|
7598
7594
|
# encryption
|
7599
7595
|
|
7600
7596
|
### T.B.D ### TCPDF 5.0.000 ###
|
@@ -7607,7 +7603,7 @@ protected
|
|
7607
7603
|
#
|
7608
7604
|
def putinfo()
|
7609
7605
|
newobj()
|
7610
|
-
out = '<<'
|
7606
|
+
out = +'<<'
|
7611
7607
|
if !empty_string(@title)
|
7612
7608
|
# The document's title.
|
7613
7609
|
out << ' /Title ' + textstring(@title)
|
@@ -7651,13 +7647,13 @@ protected
|
|
7651
7647
|
#
|
7652
7648
|
def putcatalog()
|
7653
7649
|
newobj()
|
7654
|
-
out = '<< /Type /Catalog'
|
7650
|
+
out = +'<< /Type /Catalog'
|
7655
7651
|
out << ' /Pages 1 0 R'
|
7656
|
-
if
|
7652
|
+
if @zoom_mode == 'fullpage'
|
7657
7653
|
out << ' /OpenAction [3 0 R /Fit]'
|
7658
|
-
elsif
|
7654
|
+
elsif @zoom_mode == 'fullwidth'
|
7659
7655
|
out << ' /OpenAction [3 0 R /FitH null]'
|
7660
|
-
elsif
|
7656
|
+
elsif @zoom_mode == 'real'
|
7661
7657
|
out << ' /OpenAction [3 0 R /XYZ null null 1]'
|
7662
7658
|
elsif @zoom_mode.is_a?(Numeric)
|
7663
7659
|
out << ' /OpenAction [3 0 R /XYZ null null ' + (@zoom_mode/100.0).to_s + ']'
|
@@ -7674,7 +7670,7 @@ protected
|
|
7674
7670
|
end
|
7675
7671
|
out << ' /Names <<'
|
7676
7672
|
if !@javascript.empty? or !@js_objects.empty?
|
7677
|
-
out <<
|
7673
|
+
out << " /JavaScript #{@n_js} 0 R"
|
7678
7674
|
end
|
7679
7675
|
out << ' >>'
|
7680
7676
|
|
@@ -7687,9 +7683,43 @@ protected
|
|
7687
7683
|
v = @n_ocg_view.to_s + ' 0 R'
|
7688
7684
|
as = '<</Event /Print /OCGs [' + p + ' ' + v + '] /Category [/Print]>> <</Event /View /OCGs [' + p + ' ' + v + '] /Category [/View]>>'
|
7689
7685
|
out << ' /OCProperties <</OCGs [' + p + ' ' + v + '] /D <</ON [' + p + '] /OFF [' + v + '] /AS [' + as + ']>>>>'
|
7686
|
+
# AcroForm
|
7687
|
+
if !@form_obj_id.empty? || (@sign && @signature_data['cert_type'])
|
7688
|
+
out << ' /AcroForm<<'
|
7689
|
+
objrefs = +''
|
7690
|
+
if @sign && @signature_data['cert_type']
|
7691
|
+
objrefs << "#{@sig_obj_id} 0 R"
|
7692
|
+
end
|
7693
|
+
@form_obj_id.each{|objid|
|
7694
|
+
objrefs << " #{objid} 0 R"
|
7695
|
+
}
|
7696
|
+
out << " /Fields [#{objrefs}]"
|
7697
|
+
if @sign && @signature_data['cert_type']
|
7698
|
+
out << ' /SigFlags 3'
|
7699
|
+
end
|
7690
7700
|
|
7691
|
-
|
7692
|
-
|
7701
|
+
#out << ' /CO '
|
7702
|
+
unless @annotation_fonts.empty?
|
7703
|
+
out << ' /DR <<'
|
7704
|
+
out << ' /Font <<'
|
7705
|
+
@annotation_fonts.each {|font, fontkey|
|
7706
|
+
out << " /F#{fontkey + 1} #{@font_obj_ids[font]} 0 R"
|
7707
|
+
}
|
7708
|
+
out << ' >> >>'
|
7709
|
+
end
|
7710
|
+
out << " /DA (/F#{@fontkeys.index('helvetica') + 1} 0 Tf 0 g)"
|
7711
|
+
out << ' /Q ' + (@rtl ? '2' : '0')
|
7712
|
+
#out << ' /XFA '
|
7713
|
+
out << ' >>'
|
7714
|
+
# signatures
|
7715
|
+
if @sign && @signature_data['cert_type']
|
7716
|
+
if @signature_data['cert_type'] > 0
|
7717
|
+
out << " /Perms<</DocMDP #{@sig_obj_id + 1} 0 R>>"
|
7718
|
+
else
|
7719
|
+
out << " /Perms<</UR3 #{@sig_obj_id + 1} 0 R>>"
|
7720
|
+
end
|
7721
|
+
end
|
7722
|
+
end
|
7693
7723
|
out << ' >> endobj'
|
7694
7724
|
out(out)
|
7695
7725
|
end
|
@@ -7702,7 +7732,7 @@ protected
|
|
7702
7732
|
# [@access protected]
|
7703
7733
|
#
|
7704
7734
|
def putviewerpreferences()
|
7705
|
-
out = '/ViewerPreferences <<'
|
7735
|
+
out = +'/ViewerPreferences <<'
|
7706
7736
|
if @rtl
|
7707
7737
|
out << ' /Direction /R2L'
|
7708
7738
|
else
|
@@ -7756,7 +7786,7 @@ protected
|
|
7756
7786
|
end
|
7757
7787
|
end
|
7758
7788
|
if @viewer_preferences['PrintPageRange']
|
7759
|
-
print_page_range_num = ''
|
7789
|
+
print_page_range_num = +''
|
7760
7790
|
@viewer_preferences['PrintPageRange'].each { |v|
|
7761
7791
|
print_page_range_num << ' ' + (v - 1).to_s + ''
|
7762
7792
|
}
|
@@ -7775,7 +7805,7 @@ protected
|
|
7775
7805
|
# [@access protected]
|
7776
7806
|
#
|
7777
7807
|
def puttrailer()
|
7778
|
-
out = 'trailer <<'
|
7808
|
+
out = +'trailer <<'
|
7779
7809
|
out << ' /Size ' + (@n+1).to_s
|
7780
7810
|
out << ' /Root ' + @n.to_s + ' 0 R'
|
7781
7811
|
out << ' /Info ' + (@n-1).to_s + ' 0 R'
|
@@ -7833,6 +7863,20 @@ protected
|
|
7833
7863
|
out(sprintf('%010d 00000 n ', @offsets[i]))
|
7834
7864
|
end
|
7835
7865
|
end
|
7866
|
+
# Javascript Objects
|
7867
|
+
if @js_obj_id > @js_start_obj_id
|
7868
|
+
out((@js_start_obj_id + 1).to_s + ' ' + (@js_obj_id - @js_start_obj_id).to_s)
|
7869
|
+
(@js_start_obj_id + 1).upto(@js_obj_id) do |i|
|
7870
|
+
out(sprintf('%010d 00000 n ', @offsets[i]))
|
7871
|
+
end
|
7872
|
+
end
|
7873
|
+
# Appearance streams XObjects
|
7874
|
+
if @apxo_obj_id > @apxo_start_obj_id
|
7875
|
+
out((@apxo_start_obj_id + 1).to_s + ' ' + (@apxo_obj_id - @apxo_start_obj_id).to_s)
|
7876
|
+
(@apxo_start_obj_id + 1).upto(@apxo_obj_id) do |i|
|
7877
|
+
out(sprintf('%010d 00000 n ', @offsets[i]))
|
7878
|
+
end
|
7879
|
+
end
|
7836
7880
|
#Trailer
|
7837
7881
|
puttrailer();
|
7838
7882
|
out('startxref');
|
@@ -7872,7 +7916,7 @@ protected
|
|
7872
7916
|
#
|
7873
7917
|
def beginpage(orientation='', format='')
|
7874
7918
|
@page += 1;
|
7875
|
-
setPageBuffer(@page, '')
|
7919
|
+
setPageBuffer(@page, +'')
|
7876
7920
|
# initialize array for graphics tranformation positions inside a page buffer
|
7877
7921
|
@state=2;
|
7878
7922
|
if empty_string(orientation)
|
@@ -8024,7 +8068,6 @@ protected
|
|
8024
8068
|
# [@access protected]
|
8025
8069
|
#
|
8026
8070
|
def escape(s)
|
8027
|
-
# Add \ before \, ( and )
|
8028
8071
|
s.gsub('\\','\\\\\\').gsub('(','\\(').gsub(')','\\)').gsub(13.chr, '\r')
|
8029
8072
|
end
|
8030
8073
|
|
@@ -8108,9 +8151,9 @@ protected
|
|
8108
8151
|
|
8109
8152
|
#
|
8110
8153
|
# get raw output stream.
|
8111
|
-
# @param string :s string to output.
|
8112
|
-
# @param int :n object reference for encryption mode
|
8113
|
-
# @access protected
|
8154
|
+
# [@param string :s] string to output.
|
8155
|
+
# [@param int :n] object reference for encryption mode
|
8156
|
+
# [@access protected]
|
8114
8157
|
#
|
8115
8158
|
def getrawstream(s, n=0)
|
8116
8159
|
if n <= 0
|
@@ -8122,9 +8165,9 @@ protected
|
|
8122
8165
|
|
8123
8166
|
#
|
8124
8167
|
# Format output stream
|
8125
|
-
# @param string :s string to output.
|
8126
|
-
# @param int :n object reference for encryption mode
|
8127
|
-
# @access protected
|
8168
|
+
# [@param string :s] string to output.
|
8169
|
+
# [@param int :n] object reference for encryption mode
|
8170
|
+
# [@access protected]
|
8128
8171
|
#
|
8129
8172
|
def getstream(s, n=0)
|
8130
8173
|
"stream\n" + getrawstream(s, n=0) + "\nendstream"
|
@@ -8146,8 +8189,11 @@ protected
|
|
8146
8189
|
# [@access protected]
|
8147
8190
|
#
|
8148
8191
|
def out(s)
|
8149
|
-
s.force_encoding('ASCII-8BIT') if s.respond_to?(:force_encoding)
|
8150
|
-
|
8192
|
+
s = (+s).force_encoding('ASCII-8BIT') if s.respond_to?(:force_encoding)
|
8193
|
+
|
8194
|
+
if @tmp_buffer
|
8195
|
+
@tmp_buffer << "#{s}\n"
|
8196
|
+
elsif (@state==2)
|
8151
8197
|
if !@in_footer and !@footerlen[@page].nil? and (@footerlen[@page] > 0)
|
8152
8198
|
# puts data before page footer
|
8153
8199
|
pagebuff = getPageBuffer(@page)
|
@@ -8320,7 +8366,7 @@ protected
|
|
8320
8366
|
if !@is_unicode
|
8321
8367
|
return str # string is not in unicode
|
8322
8368
|
end
|
8323
|
-
outstr = '' # string to be returned
|
8369
|
+
outstr = +'' # string to be returned
|
8324
8370
|
unicode = UTF8StringToArray(str) # array containing UTF-8 unicode values
|
8325
8371
|
unicode.each {|char|
|
8326
8372
|
if char < 256
|
@@ -8404,7 +8450,7 @@ protected
|
|
8404
8450
|
# [@see] UTF8ToUTF16BE()
|
8405
8451
|
#
|
8406
8452
|
def arrUTF8ToUTF16BE(unicode, setbom=true)
|
8407
|
-
outstr = ""; # string to be returned
|
8453
|
+
outstr = +""; # string to be returned
|
8408
8454
|
if (setbom)
|
8409
8455
|
outstr << "\xFE\xFF"; # Byte Order Mark (BOM)
|
8410
8456
|
end
|
@@ -8610,7 +8656,16 @@ public
|
|
8610
8656
|
# [@return array] RGB color or empty array in case of error.
|
8611
8657
|
# [@access public]
|
8612
8658
|
#
|
8613
|
-
def
|
8659
|
+
def convert_html_color_to_dec_array(color = "#FFFFFF")
|
8660
|
+
returncolor = _convert_html_color_to_dec(color)
|
8661
|
+
if returncolor.is_a? Hash
|
8662
|
+
returncolor.values
|
8663
|
+
else
|
8664
|
+
returncolor
|
8665
|
+
end
|
8666
|
+
end
|
8667
|
+
|
8668
|
+
private def _convert_html_color_to_dec(color = "#FFFFFF")
|
8614
8669
|
color = color.gsub(/[\s]*/, '') # remove extra spaces
|
8615
8670
|
color = color.downcase
|
8616
8671
|
if !(dotpos = color.index('.')).nil?
|
@@ -8620,7 +8675,6 @@ public
|
|
8620
8675
|
if color.length == 0
|
8621
8676
|
return []
|
8622
8677
|
end
|
8623
|
-
returncolor = ActiveSupport::OrderedHash.new
|
8624
8678
|
# RGB ARRAY
|
8625
8679
|
if color[0,3] == 'rgb'
|
8626
8680
|
codes = color.sub(/^rgb\(/, '')
|
@@ -8635,6 +8689,7 @@ public
|
|
8635
8689
|
if color[0,4] == 'cmyk'
|
8636
8690
|
codes = color.sub(/^cmyk\(/, '')
|
8637
8691
|
codes = codes.gsub(')', '')
|
8692
|
+
returncolor = codes.split(',', 4)
|
8638
8693
|
returncolor[0] = returncolor[0].to_i
|
8639
8694
|
returncolor[1] = returncolor[1].to_i
|
8640
8695
|
returncolor[2] = returncolor[2].to_i
|
@@ -8653,6 +8708,7 @@ public
|
|
8653
8708
|
color_code = color.sub(/^#/, "")
|
8654
8709
|
end
|
8655
8710
|
# RGB VALUE
|
8711
|
+
returncolor = {}
|
8656
8712
|
case color_code.length
|
8657
8713
|
when 3
|
8658
8714
|
# three-digit hexadecimal representation
|
@@ -8672,6 +8728,11 @@ public
|
|
8672
8728
|
end
|
8673
8729
|
return returncolor
|
8674
8730
|
end
|
8731
|
+
|
8732
|
+
def convertHTMLColorToDec(color = "#FFFFFF")
|
8733
|
+
warn("#{__callee__} is deprecated, use convert_html_color_to_dec_array instead.", uplevel: 1)
|
8734
|
+
_convert_html_color_to_dec(color)
|
8735
|
+
end
|
8675
8736
|
alias_method :convert_html_color_to_dec, :convertHTMLColorToDec
|
8676
8737
|
|
8677
8738
|
#
|
@@ -8796,7 +8857,7 @@ public
|
|
8796
8857
|
tm[5] = y - tm[0] * y - tm[1] * x
|
8797
8858
|
|
8798
8859
|
# generate the transformation matrix
|
8799
|
-
|
8860
|
+
transform(tm)
|
8800
8861
|
end
|
8801
8862
|
alias_method :rotate, :Rotate
|
8802
8863
|
|
@@ -8807,7 +8868,7 @@ public
|
|
8807
8868
|
# [@since 2.1.000 (2008-01-07)]
|
8808
8869
|
# [@see] StartTransform(), StopTransform()
|
8809
8870
|
#
|
8810
|
-
def
|
8871
|
+
def transform(tm)
|
8811
8872
|
out(sprintf('%.3f %.3f %.3f %.3f %.3f %.3f cm', tm[0], tm[1], tm[2], tm[3], tm[4], tm[5]))
|
8812
8873
|
# add tranformation matrix
|
8813
8874
|
@transfmatrix[@transfmatrix_key].push 'a' => tm[0], 'b' => tm[1], 'c' => tm[2], 'd' => tm[3], 'e' => tm[4], 'f' => tm[5]
|
@@ -8816,7 +8877,7 @@ public
|
|
8816
8877
|
@transfmrk[@page] = @pagelen[@page]
|
8817
8878
|
end
|
8818
8879
|
end
|
8819
|
-
protected :
|
8880
|
+
protected :transform
|
8820
8881
|
|
8821
8882
|
# END TRANSFORMATIONS SECTION -------------------------
|
8822
8883
|
|
@@ -8893,6 +8954,7 @@ public
|
|
8893
8954
|
end
|
8894
8955
|
if !style['dash'].nil?
|
8895
8956
|
dash = style['dash']
|
8957
|
+
phase = style['phase'].to_i
|
8896
8958
|
dash_string = ''
|
8897
8959
|
if dash != 0 and dash != ''
|
8898
8960
|
if dash.is_a?(String) && dash =~ /^.+,/
|
@@ -8900,15 +8962,17 @@ public
|
|
8900
8962
|
else
|
8901
8963
|
tab = [dash]
|
8902
8964
|
end
|
8903
|
-
dash_string = ''
|
8965
|
+
dash_string = +''
|
8904
8966
|
tab.each_with_index { |v, i|
|
8905
8967
|
if i != 0
|
8906
8968
|
dash_string << ' '
|
8907
8969
|
end
|
8908
8970
|
dash_string << sprintf("%.2f", v.to_f)
|
8909
8971
|
}
|
8972
|
+
else
|
8973
|
+
phase = 0
|
8910
8974
|
end
|
8911
|
-
|
8975
|
+
|
8912
8976
|
@linestyle_dash = sprintf("[%s] %.2f d", dash_string, phase)
|
8913
8977
|
out(@linestyle_dash)
|
8914
8978
|
end
|
@@ -9012,13 +9076,13 @@ public
|
|
9012
9076
|
# [@param float :y1] Ordinate of first point
|
9013
9077
|
# [@param float :x2] Abscissa of second point
|
9014
9078
|
# [@param float :y2]] Ordinate of second point
|
9015
|
-
# [@param hash :style] Line style. Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty
|
9079
|
+
# [@param hash :style] Line style. Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty Hash).
|
9016
9080
|
# [@access public]
|
9017
9081
|
# [@since 1.0]
|
9018
9082
|
# [@see] SetLineWidth(), SetDrawColor(), SetLineStyle()
|
9019
9083
|
#
|
9020
|
-
def Line(x1, y1, x2, y2, style=
|
9021
|
-
if style.is_a?
|
9084
|
+
def Line(x1, y1, x2, y2, style={})
|
9085
|
+
if style.is_a?(Hash) && !style.empty?
|
9022
9086
|
SetLineStyle(style)
|
9023
9087
|
end
|
9024
9088
|
outPoint(x1, y1)
|
@@ -9283,8 +9347,8 @@ public
|
|
9283
9347
|
# * all: Line style of all lines. Array like for {@link SetLineStyle SetLineStyle}.
|
9284
9348
|
# * 0 to (:np - 1): Line style of each line. Array like for {@link SetLineStyle SetLineStyle}.
|
9285
9349
|
# If a key is not present or is null, not draws the line. Default value is default line style (empty array).
|
9286
|
-
# [@param array :fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array).
|
9287
|
-
# [@param boolean :closed if true the polygon is closes, otherwise will remain open
|
9350
|
+
# [@param array :fill_color] Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array).
|
9351
|
+
# [@param boolean :closed] if true the polygon is closes, otherwise will remain open
|
9288
9352
|
# [@access public]
|
9289
9353
|
# [@since 4.8.003 (2009-09-15)]
|
9290
9354
|
#
|
@@ -10307,7 +10371,7 @@ public
|
|
10307
10371
|
|
10308
10372
|
#
|
10309
10373
|
# Create a bookmark PDF string.
|
10310
|
-
# [@access
|
10374
|
+
# [@access protected]
|
10311
10375
|
# [@author] Olivier Plathey, Nicola Asuni
|
10312
10376
|
# [@since 2.1.002 (2008-02-12)]
|
10313
10377
|
#
|
@@ -10370,165 +10434,1083 @@ public
|
|
10370
10434
|
protected :putbookmarks
|
10371
10435
|
|
10372
10436
|
# --- JAVASCRIPT ------------------------------------------------------
|
10373
|
-
# --- FORM FIELDS -----------------------------------------------------
|
10374
|
-
# --- END FORMS FIELDS ------------------------------------------------
|
10375
|
-
|
10376
10437
|
#
|
10377
|
-
#
|
10378
|
-
#
|
10379
|
-
# [@param int :page] starting group page (leave empty for next page).
|
10438
|
+
# Adds a javascript
|
10439
|
+
# [@param string :script] Javascript code
|
10380
10440
|
# [@access public]
|
10381
|
-
# [@
|
10441
|
+
# [@author Johannes G�ntert, Nicola Asuni]
|
10442
|
+
# [@since 2.1.002 (2008-02-12)]
|
10382
10443
|
#
|
10383
|
-
def
|
10384
|
-
|
10385
|
-
page = @page + 1
|
10386
|
-
end
|
10387
|
-
@newpagegroup[page] = true
|
10444
|
+
def IncludeJS(script)
|
10445
|
+
@javascript << script
|
10388
10446
|
end
|
10389
|
-
alias_method :start_page_group, :startPageGroup
|
10390
10447
|
|
10391
10448
|
#
|
10392
|
-
#
|
10393
|
-
#
|
10394
|
-
# [@param
|
10449
|
+
# Adds a javascript object and return object ID
|
10450
|
+
# [@param string :script] Javascript code
|
10451
|
+
# [@param boolean :onload] if true executes this object when opening the document
|
10452
|
+
# [@return int] internal object ID
|
10395
10453
|
# [@access public]
|
10396
|
-
# [@
|
10397
|
-
# [@
|
10454
|
+
# [@author Nicola Asuni]
|
10455
|
+
# [@since 4.8.000 (2009-09-07)]
|
10398
10456
|
#
|
10399
|
-
def
|
10400
|
-
@
|
10457
|
+
def addJavascriptObject(script, onload = false)
|
10458
|
+
@js_obj_id += 1
|
10459
|
+
@js_objects[@js_obj_id] = {'js' => script, 'onload' => onload}
|
10460
|
+
@js_obj_id
|
10401
10461
|
end
|
10402
|
-
alias_method :alias_nb_pages, :AliasNbPages
|
10403
10462
|
|
10404
10463
|
#
|
10405
|
-
#
|
10406
|
-
#
|
10407
|
-
# [@
|
10408
|
-
# [@
|
10409
|
-
# [@since 4.0.018 (2008-08-08)]
|
10410
|
-
# [@see] AliasNbPages(), PageNo(), Footer()
|
10464
|
+
# Create a javascript PDF string.
|
10465
|
+
# [@access protected]
|
10466
|
+
# [@author Johannes G�ntert, Nicola Asuni]
|
10467
|
+
# [@since 2.1.002 (2008-02-12)]
|
10411
10468
|
#
|
10412
|
-
def
|
10413
|
-
if
|
10414
|
-
|
10469
|
+
def putjavascript()
|
10470
|
+
return if @javascript.empty? && @js_objects.empty?
|
10471
|
+
|
10472
|
+
if @javascript.index 'this.addField'
|
10473
|
+
# @setUserRights() unless @ur
|
10474
|
+
|
10475
|
+
# the following two lines are used to avoid form fields duplication after saving
|
10476
|
+
# The addField method only works on Acrobat Writer, unless the document is signed with Adobe private key (UR3)
|
10477
|
+
jsa = sprintf("ftcpdfdocsaved=this.addField('%s','%s',%d,[%.2f,%.2f,%.2f,%.2f]);", 'tcpdfdocsaved', 'text', 0, 0, 1, 0, 1)
|
10478
|
+
jsb = "getField('tcpdfdocsaved').value='saved';"
|
10479
|
+
@javascript = "#{jsa}\n#{@javascript}\n#{jsb}"
|
10480
|
+
end
|
10481
|
+
@n_js = newobj()
|
10482
|
+
out = +' << /Names ['
|
10483
|
+
unless @javascript.empty?
|
10484
|
+
out << " (EmbeddedJS) #{@n + 1} 0 R"
|
10485
|
+
end
|
10486
|
+
unless @js_objects.empty?
|
10487
|
+
@js_objects.each{|key, val|
|
10488
|
+
out << " (JS#{key}) #{key} 0 R" if val['onload']
|
10489
|
+
}
|
10490
|
+
end
|
10491
|
+
out << ' ] >> endobj'
|
10492
|
+
out(out)
|
10493
|
+
# default Javascript object
|
10494
|
+
unless @javascript.empty?
|
10495
|
+
newobj()
|
10496
|
+
out = +'<< /S /JavaScript'
|
10497
|
+
out << " /JS #{textstring(@javascript)}"
|
10498
|
+
out << ' >> endobj'
|
10499
|
+
out(out)
|
10500
|
+
end
|
10501
|
+
# additional Javascript objects
|
10502
|
+
unless @js_objects.empty?
|
10503
|
+
@js_objects.each {|key, val|
|
10504
|
+
@offsets[key] = @bufferlen
|
10505
|
+
out = "#{key} 0 obj\n << /S /JavaScript /JS #{textstring(val['js'])} >> endobj"
|
10506
|
+
out(out)
|
10507
|
+
}
|
10415
10508
|
end
|
10416
|
-
return @alias_nb_pages
|
10417
10509
|
end
|
10418
|
-
|
10510
|
+
protected :putjavascript
|
10419
10511
|
|
10420
10512
|
#
|
10421
|
-
#
|
10422
|
-
#
|
10423
|
-
# [@
|
10424
|
-
# [@
|
10425
|
-
# [@since
|
10426
|
-
# [@see] getAliasNbPages(), PageNo(), Footer()
|
10513
|
+
# Convert color to javascript color.
|
10514
|
+
# [@param string :color] color name or #RRGGBB
|
10515
|
+
# [@access protected]
|
10516
|
+
# [@author Denis Van Nuffelen, Nicola Asuni]
|
10517
|
+
# [@since 2.1.002 (2008-02-12)]
|
10427
10518
|
#
|
10428
|
-
def
|
10429
|
-
|
10430
|
-
|
10519
|
+
def JScolor(color)
|
10520
|
+
aColors = ['transparent', 'black', 'white', 'red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'dkGray', 'gray', 'ltGray']
|
10521
|
+
if color[0] == '#'
|
10522
|
+
return sprintf("['RGB',%.3f,%.3f,%.3f]", color[1, 2].to_i(16) / 255, color[3, 2].to_i(16) / 255, color[5, 2].to_i(16) / 255)
|
10523
|
+
end
|
10524
|
+
|
10525
|
+
unless aColors.include? color
|
10526
|
+
Error('Invalid color: ' + color)
|
10527
|
+
end
|
10528
|
+
'color.' + color
|
10431
10529
|
end
|
10432
|
-
|
10530
|
+
protected :JScolor
|
10433
10531
|
|
10434
10532
|
#
|
10435
|
-
#
|
10436
|
-
#
|
10437
|
-
# [@
|
10438
|
-
# [@
|
10439
|
-
# [@
|
10440
|
-
# [@
|
10533
|
+
# Adds a javascript form field.
|
10534
|
+
# [@param string :type] field type
|
10535
|
+
# [@param string :name] field name
|
10536
|
+
# [@param int :x] horizontal position
|
10537
|
+
# [@param int :y] vertical position
|
10538
|
+
# [@param int :w] width
|
10539
|
+
# [@param int :h] height
|
10540
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10541
|
+
# [@access protected]
|
10542
|
+
# [@author Denis Van Nuffelen, Nicola Asuni]
|
10543
|
+
# [@since 2.1.002 (2008-02-12)]
|
10441
10544
|
#
|
10442
|
-
def
|
10443
|
-
|
10444
|
-
|
10545
|
+
def addfield(type, name, x, y, w, h, prop)
|
10546
|
+
x = x - w if @rtl
|
10547
|
+
|
10548
|
+
# the followind avoid fields duplication after saving the document
|
10549
|
+
@javascript << "if(getField('tcpdfdocsaved').value != 'saved') {"
|
10550
|
+
k = @k
|
10551
|
+
@javascript << "f#{name}=this.addField('#{name}','#{type}',#{PageNo() - 1},[#{sprintf("%.2f,%.2f,%.2f,%.2f", x * k, (@h - y) * k + 1, (x + w) * k, (@h - y - h) * k + 1)}]);\n"
|
10552
|
+
@javascript << "f#{name}.textSize=#{@font_size_pt};\n"
|
10553
|
+
prop.each {|k, v|
|
10554
|
+
val = k[-5..-1] == 'Color' ? JScolor(v) : "'#{v}'"
|
10555
|
+
@javascript << "f#{name}.#{k}=#{val};\n"
|
10556
|
+
}
|
10557
|
+
if @rtl
|
10558
|
+
@x -= w
|
10559
|
+
else
|
10560
|
+
@x += w
|
10445
10561
|
end
|
10446
|
-
|
10562
|
+
@javascript << '}'
|
10447
10563
|
end
|
10448
|
-
|
10564
|
+
protected :addfield
|
10565
|
+
|
10566
|
+
# --- FORM FIELDS -----------------------------------------------------
|
10449
10567
|
|
10450
10568
|
#
|
10451
|
-
#
|
10452
|
-
# [@
|
10569
|
+
# Convert JavaScript form fields properties array to Annotation Properties array.
|
10570
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10571
|
+
# [@return array of annotation properties]
|
10572
|
+
# [@access protected]
|
10573
|
+
# [@author Nicola Asuni]
|
10574
|
+
# [@since 4.8.000 (2009-09-06)]
|
10575
|
+
#
|
10576
|
+
def getAnnotOptFromJSProp(prop)
|
10577
|
+
# the annotation options area already defined
|
10578
|
+
return prop['aopt'] if prop['aopt'].is_a?(Array)
|
10579
|
+
|
10580
|
+
opt = {} # value to be returned
|
10581
|
+
# alignment: Controls how the text is laid out within the text field.
|
10582
|
+
if prop['alignment']
|
10583
|
+
opt['q'] = case prop['alignment']
|
10584
|
+
when 'left'; 0
|
10585
|
+
when 'center'; 1
|
10586
|
+
when 'right'; 2
|
10587
|
+
else @rtl ? 2 : 0
|
10588
|
+
end
|
10589
|
+
end
|
10590
|
+
# lineWidth: Specifies the thickness of the border when stroking the perimeter of a field's rectangle.
|
10591
|
+
if prop['lineWidth']
|
10592
|
+
linewidth = prop['lineWidth'].to_i
|
10593
|
+
else
|
10594
|
+
linewidth = 1
|
10595
|
+
end
|
10596
|
+
# borderStyle: The border style for a field.
|
10597
|
+
case prop['borderStyle']
|
10598
|
+
when 'border.d', 'dashed'
|
10599
|
+
opt['border'] = [0, 0, linewidth, [3, 2]]
|
10600
|
+
opt['bs'] = {'w'=>linewidth, 's'=>'D', 'd'=>[3, 2]}
|
10601
|
+
when 'border.b', 'beveled'
|
10602
|
+
opt['border'] = [0, 0, linewidth]
|
10603
|
+
opt['bs'] = {'w'=>linewidth, 's'=>'B'}
|
10604
|
+
when 'border.i', 'inset'
|
10605
|
+
opt['border'] = [0, 0, linewidth]
|
10606
|
+
opt['bs'] = {'w'=>linewidth, 's'=>'I'}
|
10607
|
+
when 'border.u', 'underline'
|
10608
|
+
opt['border'] = [0, 0, linewidth]
|
10609
|
+
opt['bs'] = {'w'=>linewidth, 's'=>'U'}
|
10610
|
+
else # 'border.s', 'solid'
|
10611
|
+
opt['border'] = [0, 0, linewidth]
|
10612
|
+
opt['bs'] = {'w'=>linewidth, 's'=>'S'}
|
10613
|
+
end
|
10614
|
+
|
10615
|
+
opt['border'] = prop['border'] if prop['border'].is_a?(Array)
|
10616
|
+
opt['mk'] ||= {}
|
10617
|
+
opt['mk']['if'] ||= {}
|
10618
|
+
opt['mk']['if']['a'] = [0.5, 0.5]
|
10619
|
+
# buttonAlignX: Controls how space is distributed from the left of the button face with respect to the icon.
|
10620
|
+
opt['mk']['if']['a'][0] = prop['buttonAlignX'] if prop['buttonAlignX']
|
10621
|
+
# buttonAlignY: Controls how unused space is distributed from the bottom of the button face with respect to the icon.
|
10622
|
+
opt['mk']['if']['a'][1] = prop['buttonAlignY'] if prop['buttonAlignY']
|
10623
|
+
# buttonFitBounds: If true, the extent to which the icon may be scaled is set to the bounds of the button field.
|
10624
|
+
opt['mk']['if']['fb'] = true if prop['buttonFitBounds'] && (prop['buttonFitBounds'] == 'true')
|
10625
|
+
# buttonScaleHow: Controls how the icon is scaled (if necessary) to fit inside the button face.
|
10626
|
+
case prop['buttonScaleHow']
|
10627
|
+
when 'scaleHow.proportional'; opt['mk']['if']['s'] = 'P'
|
10628
|
+
when 'scaleHow.anamorphic'; opt['mk']['if']['s'] = 'A'
|
10629
|
+
end
|
10630
|
+
# buttonScaleWhen: Controls when an icon is scaled to fit inside the button face.
|
10631
|
+
case prop['buttonScaleWhen']
|
10632
|
+
when 'scaleWhen.always'; opt['mk']['if']['sw'] = 'A'
|
10633
|
+
when 'scaleWhen.never'; opt['mk']['if']['sw'] = 'N'
|
10634
|
+
when 'scaleWhen.tooBig'; opt['mk']['if']['sw'] = 'B'
|
10635
|
+
when 'scaleWhen.tooSmall'; opt['mk']['if']['sw'] = 'S'
|
10636
|
+
end
|
10637
|
+
# buttonPosition: Controls how the text and the icon of the button are positioned with respect to each other within the button face.
|
10638
|
+
case prop['buttonPosition']
|
10639
|
+
when 0, 'position.textOnly'; opt['mk']['tp'] = 0
|
10640
|
+
when 1, 'position.iconOnly'; opt['mk']['tp'] = 1
|
10641
|
+
when 2, 'position.iconTextV'; opt['mk']['tp'] = 2
|
10642
|
+
when 3, 'position.textIconV'; opt['mk']['tp'] = 3
|
10643
|
+
when 4, 'position.iconTextH'; opt['mk']['tp'] = 4
|
10644
|
+
when 5, 'position.textIconH'; opt['mk']['tp'] = 5
|
10645
|
+
when 6, 'position.overlay'; opt['mk']['tp'] = 6
|
10646
|
+
end
|
10647
|
+
# fillColor: Specifies the background color for a field.
|
10648
|
+
if prop['fillColor']
|
10649
|
+
if prop['fillColor'].is_a? Array
|
10650
|
+
opt['mk']['bg'] = prop['fillColor']
|
10651
|
+
else
|
10652
|
+
opt['mk']['bg'] = convert_html_color_to_dec_array(prop['fillColor'])
|
10653
|
+
end
|
10654
|
+
end
|
10655
|
+
# strokeColor: Specifies the stroke color for a field that is used to stroke the rectangle of the field with a line as large as the line width.
|
10656
|
+
if prop['strokeColor']
|
10657
|
+
if prop['strokeColor'].is_a? Array
|
10658
|
+
opt['mk']['bc'] = prop['strokeColor']
|
10659
|
+
else
|
10660
|
+
opt['mk']['bc'] = convert_html_color_to_dec_array(prop['strokeColor'])
|
10661
|
+
end
|
10662
|
+
end
|
10663
|
+
# rotation: The rotation of a widget in counterclockwise increments.
|
10664
|
+
opt['mk']['r'] = prop['rotation'] if prop['rotation']
|
10665
|
+
# charLimit: Limits the number of characters that a user can type into a text field.
|
10666
|
+
opt['maxlen'] = prop['charLimit'].to_i if prop['charLimit']
|
10667
|
+
|
10668
|
+
ff ||= 0
|
10669
|
+
# readonly: The read-only characteristic of a field. If a field is read-only, the user can see the field but cannot change it.
|
10670
|
+
ff |= 1 << 0 if prop['readonly'] == 'true'
|
10671
|
+
# required: Specifies whether a field requires a value.
|
10672
|
+
ff |= 1 << 1 if prop['required'] == 'true'
|
10673
|
+
# multiline: Controls how text is wrapped within the field.
|
10674
|
+
ff |= 1 << 12 if prop['multiline'] == 'true'
|
10675
|
+
# password: Specifies whether the field should display asterisks when data is entered in the field.
|
10676
|
+
ff |= 1 << 13 if prop['password'] == 'true'
|
10677
|
+
# NoToggleToOff: If set, exactly one radio button shall be selected at all times; selecting the currently selected button has no effect.
|
10678
|
+
ff |= 1 << 14 if prop['NoToggleToOff'] == 'true'
|
10679
|
+
# Radio: If set, the field is a set of radio buttons.
|
10680
|
+
ff |= 1 << 15 if prop['Radio'] == 'true'
|
10681
|
+
# Pushbutton: If set, the field is a pushbutton that does not retain a permanent value.
|
10682
|
+
ff |= 1 << 16 if prop['Pushbutton'] == 'true'
|
10683
|
+
# Combo: If set, the field is a combo box; if clear, the field is a list box.
|
10684
|
+
ff |= 1 << 17 if prop['Combo'] == 'true'
|
10685
|
+
# editable: Controls whether a combo box is editable.
|
10686
|
+
ff |= 1 << 18 if prop['editable'] == 'true'
|
10687
|
+
# Sort: If set, the field's option items shall be sorted alphabetically.
|
10688
|
+
ff |= 1 << 19 if prop['Sort'] == 'true'
|
10689
|
+
# fileSelect: If true, sets the file-select flag in the Options tab of the text field (Field is Used for File Selection).
|
10690
|
+
ff |= 1 << 20 if prop['fileSelect'] == 'true'
|
10691
|
+
# multipleSelection: If true, indicates that a list box allows a multiple selection of items.
|
10692
|
+
ff |= 1 << 21 if prop['multipleSelection'] == 'true'
|
10693
|
+
# doNotSpellCheck: If true, spell checking is not performed on this editable text field.
|
10694
|
+
ff |= 1 << 22 if prop['doNotSpellCheck'] == 'true'
|
10695
|
+
# doNotScroll: If true, the text field does not scroll and the user, therefore, is limited by the rectangular region designed for the field.
|
10696
|
+
ff |= 1 << 23 if prop['doNotScroll'] == 'true'
|
10697
|
+
# comb: If set to true, the field background is drawn as series of boxes (one for each character in the value of the field) and each character of the content is drawn within those boxes. The number of boxes drawn is determined from the charLimit property. It applies only to text fields. The setter will also raise if any of the following field properties are also set multiline, password, and fileSelect. A side-effect of setting this property is that the doNotScroll property is also set.
|
10698
|
+
ff |= 1 << 24 if prop['comb'] == 'true'
|
10699
|
+
# radiosInUnison: If false, even if a group of radio buttons have the same name and export value, they behave in a mutually exclusive fashion, like HTML radio buttons.
|
10700
|
+
ff |= 1 << 25 if prop['radiosInUnison'] == 'true'
|
10701
|
+
# richText: If true, the field allows rich text formatting.
|
10702
|
+
ff |= 1 << 25 if prop['richText'] == 'true'
|
10703
|
+
# commitOnSelChange: Controls whether a field value is committed after a selection change.
|
10704
|
+
ff |= 1 << 26 if prop['commitOnSelChange'] == 'true'
|
10705
|
+
opt['ff'] = ff
|
10706
|
+
|
10707
|
+
# defaultValue: The default value of a field - that is, the value that the field is set to when the form is reset.
|
10708
|
+
opt['dv'] = prop['defaultValue'] if prop['defaultValue']
|
10709
|
+
f = 1 << 2 # default value for annotation flags
|
10710
|
+
# readonly: The read-only characteristic of a field. If a field is read-only, the user can see the field but cannot change it.
|
10711
|
+
if prop['readonly'] == 'true'
|
10712
|
+
f |= 1 << 6
|
10713
|
+
end
|
10714
|
+
# display: Controls whether the field is hidden or visible on screen and in print.
|
10715
|
+
case prop['display']
|
10716
|
+
when 'display.visible'
|
10717
|
+
#
|
10718
|
+
when 'display.hidden'
|
10719
|
+
f |= 1 << 1
|
10720
|
+
when 'display.noPrint'
|
10721
|
+
f &= ~(1 << 2)
|
10722
|
+
when 'display.noView'
|
10723
|
+
f |= 1 << 5
|
10724
|
+
end
|
10725
|
+
opt['f'] = f
|
10726
|
+
|
10727
|
+
# currentValueIndices: Reads and writes single or multiple values of a list box or combo box.
|
10728
|
+
opt['i'] = prop['currentValueIndices'] if prop['currentValueIndices'].is_a?(Array)
|
10729
|
+
# value: The value of the field data that the user has entered.
|
10730
|
+
if prop['value']
|
10731
|
+
if prop['value'].is_a?(Array)
|
10732
|
+
opt['opt'] = []
|
10733
|
+
prop['value'].each_with_index {|v, i|
|
10734
|
+
# exportValues: An array of strings representing the export values for the field.
|
10735
|
+
if prop['exportValues'] && prop['exportValues'][i]
|
10736
|
+
opt['opt'][i] = [prop['exportValues'][i], v]
|
10737
|
+
else
|
10738
|
+
opt['opt'][i] = v
|
10739
|
+
end
|
10740
|
+
}
|
10741
|
+
else
|
10742
|
+
opt['v'] = prop['value']
|
10743
|
+
end
|
10744
|
+
end
|
10745
|
+
# richValue: This property specifies the text contents and formatting of a rich text field.
|
10746
|
+
opt['rv'] = prop['richValue'] if prop['richValue']
|
10747
|
+
# submitName: If nonempty, used during form submission instead of name. Only applicable if submitting in HTML format (that is, URL-encoded).
|
10748
|
+
opt['tm'] = prop['submitName'] if prop['submitName']
|
10749
|
+
# name: Fully qualified field name.
|
10750
|
+
opt['t'] = prop['name'] if prop['name']
|
10751
|
+
# userName: The user name (short description string) of the field.
|
10752
|
+
opt['tu'] = prop['userName'] if prop['userName']
|
10753
|
+
# highlight: Defines how a button reacts when a user clicks it.
|
10754
|
+
case prop['highlight']
|
10755
|
+
when 'none', 'highlight.n'; opt['h'] = 'N'
|
10756
|
+
when 'invert', 'highlight.i'; opt['h'] = 'i'
|
10757
|
+
when 'push', 'highlight.p'; opt['h'] = 'P'
|
10758
|
+
when 'outline', 'highlight.o'; opt['h'] = 'O'
|
10759
|
+
end
|
10760
|
+
# Unsupported options:
|
10761
|
+
# - calcOrderIndex: Changes the calculation order of fields in the document.
|
10762
|
+
# - delay: Delays the redrawing of a field's appearance.
|
10763
|
+
# - defaultStyle: This property defines the default style attributes for the form field.
|
10764
|
+
# - style: Allows the user to set the glyph style of a check box or radio button.
|
10765
|
+
# - textColor, textFont, textSize
|
10766
|
+
opt
|
10767
|
+
end
|
10768
|
+
protected :getAnnotOptFromJSProp
|
10769
|
+
|
10770
|
+
#
|
10771
|
+
# Set default properties for form fields.
|
10772
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10453
10773
|
# [@access public]
|
10454
|
-
# [@
|
10774
|
+
# [@author Nicola Asuni]
|
10775
|
+
# [@since 4.8.000 (2009-09-06)]
|
10455
10776
|
#
|
10456
|
-
def
|
10457
|
-
|
10777
|
+
def setFormDefaultProp(prop = [])
|
10778
|
+
@default_form_prop = prop
|
10458
10779
|
end
|
10459
|
-
alias_method :
|
10780
|
+
alias_method :set_form_default_prop, :setFormDefaultProp
|
10460
10781
|
|
10461
10782
|
#
|
10462
|
-
#
|
10783
|
+
# Return the default properties for form fields.
|
10784
|
+
# [@return array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10463
10785
|
# [@access public]
|
10464
|
-
# [@
|
10465
|
-
# [@
|
10786
|
+
# [@author Nicola Asuni]
|
10787
|
+
# [@since 4.8.000 (2009-09-06)]
|
10466
10788
|
#
|
10467
|
-
def
|
10468
|
-
|
10789
|
+
def getFormDefaultProp()
|
10790
|
+
@default_form_prop
|
10469
10791
|
end
|
10470
|
-
alias_method :
|
10792
|
+
alias_method :get_form_default_prop, :getFormDefaultProp
|
10471
10793
|
|
10472
10794
|
#
|
10473
|
-
#
|
10474
|
-
#
|
10475
|
-
#
|
10476
|
-
# [@
|
10795
|
+
# Creates a text field
|
10796
|
+
# [@param string :name] field name
|
10797
|
+
# [@param float :w] Width of the rectangle
|
10798
|
+
# [@param float :h] Height of the rectangle
|
10799
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10800
|
+
# [@param array :opt] annotation parameters. Possible values are described on official PDF32000_2008 reference.
|
10801
|
+
# [@param float :x] Abscissa of the upper-left corner of the rectangle
|
10802
|
+
# [@param float :y] Ordinate of the upper-left corner of the rectangle
|
10803
|
+
# [@param boolean :js] if true put the field using JavaScript (requires Acrobat Writer to be rendered).
|
10477
10804
|
# [@access public]
|
10478
|
-
# [@
|
10805
|
+
# [@author Nicola Asuni]
|
10806
|
+
# [@since 4.8.000 (2009-09-07)]
|
10479
10807
|
#
|
10480
|
-
def
|
10481
|
-
|
10482
|
-
|
10808
|
+
def TextField(name, w, h, prop = {}, opt = {}, x = '', y = '', js = false)
|
10809
|
+
x = @x if x == ''
|
10810
|
+
y = @y if y == ''
|
10811
|
+
|
10812
|
+
if js
|
10813
|
+
addfield('text', name, x, y, w, h, prop)
|
10814
|
+
return
|
10815
|
+
end
|
10816
|
+
# get default style
|
10817
|
+
prop = getFormDefaultProp.merge prop
|
10818
|
+
# get annotation data
|
10819
|
+
popt = getAnnotOptFromJSProp(prop)
|
10820
|
+
# set default appearance stream
|
10821
|
+
font = @font_family
|
10822
|
+
fontkey = @fontkeys.index font
|
10823
|
+
unless @annotation_fonts.include? fontkey
|
10824
|
+
@annotation_fonts[font] = fontkey
|
10825
|
+
end
|
10826
|
+
fontstyle = sprintf("/F%d %.2f Tf %s", fontkey + 1, @font_size_pt, @text_color)
|
10827
|
+
popt['da'] = fontstyle
|
10828
|
+
popt['ap'] = {}
|
10829
|
+
|
10830
|
+
if opt['v'] && !empty_string(opt['v'])
|
10831
|
+
# set Appearances
|
10832
|
+
popt['ap']['n'] = +"/Tx BMC q #{fontstyle} "
|
10833
|
+
gvars = getGraphicVars()
|
10834
|
+
@h = h
|
10835
|
+
@w = w
|
10836
|
+
@t_margin = 0
|
10837
|
+
@c_margin = 0.2
|
10838
|
+
|
10839
|
+
@tmp_buffer = +''
|
10840
|
+
multi_cell(w, h, opt['v'], 0, '', 0, 0, 0.2, 0, true, 0, false, true, 0)
|
10841
|
+
popt['ap']['n'] << @tmp_buffer
|
10842
|
+
@tmp_buffer = nil
|
10843
|
+
popt['ap']['n'] << 'Q EMC'
|
10844
|
+
|
10845
|
+
# restore previous values
|
10846
|
+
setGraphicVars(gvars, true)
|
10847
|
+
else
|
10848
|
+
popt['ap']['n'] = "q BT #{fontstyle} ET Q"
|
10849
|
+
end
|
10850
|
+
|
10851
|
+
# merge options
|
10852
|
+
opt = popt.merge opt
|
10853
|
+
# remove some conflicting options
|
10854
|
+
opt.delete :bs
|
10855
|
+
# set remaining annotation data
|
10856
|
+
opt['Subtype'] = 'Widget'
|
10857
|
+
opt['ft'] = 'Tx'
|
10858
|
+
opt['t'] = name
|
10859
|
+
#
|
10860
|
+
# Additional annotation's parameters (check _putannotsobj() method):
|
10861
|
+
# opt['f']
|
10862
|
+
# opt['ap']
|
10863
|
+
# opt['as']
|
10864
|
+
# opt['bs']
|
10865
|
+
# opt['be']
|
10866
|
+
# opt['c']
|
10867
|
+
# opt['border']
|
10868
|
+
# opt['h']
|
10869
|
+
# opt['mk']
|
10870
|
+
# opt['mk']['r']
|
10871
|
+
# opt['mk']['bc']
|
10872
|
+
# opt['mk']['bg']
|
10873
|
+
# opt['mk']['ca']
|
10874
|
+
# opt['mk']['rc']
|
10875
|
+
# opt['mk']['ac']
|
10876
|
+
# opt['mk']['i']
|
10877
|
+
# opt['mk']['ri']
|
10878
|
+
# opt['mk']['ix']
|
10879
|
+
# opt['mk']['if']
|
10880
|
+
# opt['mk']['if']['sw']
|
10881
|
+
# opt['mk']['if']['s']
|
10882
|
+
# opt['mk']['if']['a']
|
10883
|
+
# opt['mk']['if']['fb']
|
10884
|
+
# opt['mk']['tp']
|
10885
|
+
# opt['tu']
|
10886
|
+
# opt['tm']
|
10887
|
+
# opt['ff']
|
10888
|
+
# opt['v']
|
10889
|
+
# opt['dv']
|
10890
|
+
# opt['a']
|
10891
|
+
# opt['aa']
|
10892
|
+
# opt['q']
|
10893
|
+
Annotation(x, y, w, h, name, opt, 0)
|
10894
|
+
if @rtl
|
10895
|
+
@x -= w
|
10896
|
+
else
|
10897
|
+
@x += w
|
10483
10898
|
end
|
10484
|
-
return @currpagegroup
|
10485
10899
|
end
|
10486
|
-
alias_method :
|
10900
|
+
alias_method :text_field, :TextField
|
10487
10901
|
|
10488
10902
|
#
|
10489
|
-
#
|
10490
|
-
#
|
10491
|
-
#
|
10492
|
-
# [@
|
10903
|
+
# Creates a RadioButton field
|
10904
|
+
# [@param string :name] field name
|
10905
|
+
# [@param int :w] width
|
10906
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10907
|
+
# [@param array :opt] annotation parameters. Possible values are described on official PDF32000_2008 reference.
|
10908
|
+
# [@param string :onvalue] value to be returned if selected.
|
10909
|
+
# [@param boolean :checked] define the initial state.
|
10910
|
+
# [@param float :x] Abscissa of the upper-left corner of the rectangle
|
10911
|
+
# [@param float :y] Ordinate of the upper-left corner of the rectangle
|
10912
|
+
# [@param boolean :js] if true put the field using JavaScript (requires Acrobat Writer to be rendered).
|
10493
10913
|
# [@access public]
|
10494
|
-
# [@
|
10914
|
+
# [@author Nicola Asuni]
|
10915
|
+
# [@since 4.8.000 (2009-09-07)]
|
10495
10916
|
#
|
10496
|
-
def
|
10497
|
-
|
10498
|
-
|
10917
|
+
def RadioButton(name, w, prop = {}, opt = {}, onvalue = 'On', checked = false, x = '', y = '', js = false)
|
10918
|
+
x = @x if x == ''
|
10919
|
+
y = @y if y == ''
|
10920
|
+
|
10921
|
+
if js
|
10922
|
+
addfield('radiobutton', name, x, y, w, w, prop)
|
10923
|
+
return
|
10499
10924
|
end
|
10500
|
-
return @currpagegroup.gsub('{nb', '{pnb')
|
10501
|
-
end
|
10502
|
-
alias_method :get_page_num_group_alias, :getPageNumGroupAlias
|
10503
10925
|
|
10504
|
-
|
10505
|
-
|
10506
|
-
|
10507
|
-
|
10508
|
-
|
10509
|
-
|
10510
|
-
|
10511
|
-
|
10512
|
-
|
10926
|
+
onvalue = 'On' if empty_string(onvalue)
|
10927
|
+
defval = checked ? onvalue : 'Off'
|
10928
|
+
# set data for parent group
|
10929
|
+
@radiobutton_groups[@page] ||= {}
|
10930
|
+
unless @radiobutton_groups[@page][name]
|
10931
|
+
@radiobutton_groups[@page][name] = []
|
10932
|
+
@annot_obj_id += 1
|
10933
|
+
@radio_groups << @annot_obj_id
|
10934
|
+
end
|
10935
|
+
# save object ID to be added on Kids entry on parent object
|
10936
|
+
@radiobutton_groups[@page][name] << {'kid' => @annot_obj_id + 1, 'def' => defval}
|
10937
|
+
# get default style
|
10938
|
+
prop = getFormDefaultProp.merge prop
|
10939
|
+
prop['NoToggleToOff'] = 'true'
|
10940
|
+
prop['Radio'] = 'true'
|
10941
|
+
prop['borderStyle'] = 'inset'
|
10942
|
+
# get annotation data
|
10943
|
+
popt = getAnnotOptFromJSProp(prop)
|
10944
|
+
# set additional default values
|
10945
|
+
font = 'zapfdingbats'
|
10946
|
+
AddFont(font)
|
10947
|
+
fontkey = @fontkeys.index font
|
10948
|
+
unless @annotation_fonts.include? fontkey
|
10949
|
+
@annotation_fonts[font] = fontkey
|
10950
|
+
end
|
10951
|
+
fontstyle = sprintf('/F%d %.2f Tf', fontkey + 1, @font_size_pt)
|
10952
|
+
popt['da'] = "#{fontstyle} #{@text_color}"
|
10953
|
+
popt['ap'] = {}
|
10954
|
+
popt['ap']['n'] = {}
|
10955
|
+
popt['ap']['n'][onvalue] = "q #{@text_color} BT #{fontstyle} 0 0 Td (n) Tj ET Q"
|
10956
|
+
popt['ap']['n']['Off'] = "q #{@text_color} BT #{fontstyle} 0 0 Td (o) Tj ET Q"
|
10957
|
+
popt['mk'] ||= {}
|
10958
|
+
popt['mk']['ca'] = '(l)'
|
10959
|
+
# merge options
|
10960
|
+
opt = popt.merge opt
|
10961
|
+
# set remaining annotation data
|
10962
|
+
opt['Subtype'] = 'Widget'
|
10963
|
+
opt['ft'] = 'Btn'
|
10964
|
+
if checked
|
10965
|
+
opt['v'] = ["/#{onvalue}"]
|
10966
|
+
opt['as'] = onvalue
|
10967
|
+
else
|
10968
|
+
opt['as'] = 'Off'
|
10969
|
+
end
|
10970
|
+
Annotation(x, y, w, w, name, opt, 0)
|
10971
|
+
if @rtl
|
10972
|
+
@x -= w
|
10973
|
+
else
|
10974
|
+
@x += w
|
10975
|
+
end
|
10513
10976
|
end
|
10514
|
-
|
10977
|
+
alias_method :radio_button, :RadioButton
|
10515
10978
|
|
10516
10979
|
#
|
10517
|
-
#
|
10518
|
-
#
|
10519
|
-
# [@param int :
|
10520
|
-
# [@
|
10521
|
-
# [@
|
10522
|
-
# [@
|
10980
|
+
# Creates a List-box field
|
10981
|
+
# [@param string :name] field name
|
10982
|
+
# [@param int :w] width
|
10983
|
+
# [@param int :h] height
|
10984
|
+
# [@param array :values] array containing the list of values.
|
10985
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10986
|
+
# [@param array :opt] annotation parameters. Possible values are described on official PDF32000_2008 reference.
|
10987
|
+
# [@param float :x] Abscissa of the upper-left corner of the rectangle
|
10988
|
+
# [@param float :y] Ordinate of the upper-left corner of the rectangle
|
10989
|
+
# [@param boolean :js] if true put the field using JavaScript (requires Acrobat Writer to be rendered).
|
10990
|
+
# [@access public]
|
10991
|
+
# [@author Nicola Asuni]
|
10992
|
+
# [@since 4.8.000 (2009-09-07)]
|
10523
10993
|
#
|
10524
|
-
def
|
10525
|
-
|
10994
|
+
def ListBox(name, w, h, values, prop = {}, opt = {}, x = '', y = '', js = false)
|
10995
|
+
x = @x if x == ''
|
10996
|
+
y = @y if y == ''
|
10997
|
+
|
10998
|
+
if js
|
10999
|
+
addfield('listbox', name, x, y, w, h, prop)
|
11000
|
+
s = +''
|
11001
|
+
values.each {|v|
|
11002
|
+
if v.is_a?(Array)
|
11003
|
+
s << "['#{v[0]}','#{v[1]}'],"
|
11004
|
+
else
|
11005
|
+
s << "'#{v}',"
|
11006
|
+
end
|
11007
|
+
}
|
11008
|
+
@javascript << "f#{name}.setItems([#{s[0...-1]}]);\n"
|
11009
|
+
return
|
11010
|
+
end
|
11011
|
+
# get default style
|
11012
|
+
prop = getFormDefaultProp.merge prop
|
11013
|
+
# get annotation data
|
11014
|
+
popt = getAnnotOptFromJSProp(prop)
|
11015
|
+
# set additional default values
|
11016
|
+
font = @font_family
|
11017
|
+
fontkey = @fontkeys.index font
|
11018
|
+
unless @annotation_fonts.include? fontkey
|
11019
|
+
@annotation_fonts[font] = fontkey
|
11020
|
+
end
|
11021
|
+
s = +''
|
11022
|
+
values.each {|v|
|
11023
|
+
if v.is_a?(Array)
|
11024
|
+
s << "#{v[1]}\n"
|
11025
|
+
else
|
11026
|
+
s << "#{v}\n"
|
11027
|
+
end
|
11028
|
+
}
|
11029
|
+
|
11030
|
+
fontstyle = sprintf('/F%d %.2f Tf %s', fontkey + 1, @font_size_pt, @text_color)
|
11031
|
+
popt['da'] = fontstyle
|
11032
|
+
popt['ap'] = {}
|
11033
|
+
# set Appearances
|
11034
|
+
popt['ap']['n'] = +"/Tx BMC q #{fontstyle} "
|
11035
|
+
gvars = getGraphicVars()
|
11036
|
+
@h = h
|
11037
|
+
@w = w
|
11038
|
+
@t_margin = 0
|
11039
|
+
@c_margin = 0.2
|
11040
|
+
|
11041
|
+
@tmp_buffer = +''
|
11042
|
+
multi_cell(w, h, s, 0, '', 0, 0, 0.2, 0, true, 0, false, true, 0)
|
11043
|
+
popt['ap']['n'] << @tmp_buffer
|
11044
|
+
popt['ap']['n'] << 'Q EMC'
|
11045
|
+
@tmp_buffer = nil
|
11046
|
+
|
11047
|
+
# restore previous values
|
11048
|
+
setGraphicVars(gvars, true)
|
11049
|
+
|
11050
|
+
# merge options
|
11051
|
+
opt = popt.merge opt
|
11052
|
+
# set remaining annotation data
|
11053
|
+
opt['Subtype'] = 'Widget'
|
11054
|
+
opt['ft'] = 'Ch'
|
11055
|
+
opt['t'] = name
|
11056
|
+
opt['opt'] = values
|
11057
|
+
Annotation(x, y, w, h, name, opt, 0)
|
11058
|
+
if @rtl
|
11059
|
+
@x -= w
|
11060
|
+
else
|
11061
|
+
@x += w
|
11062
|
+
end
|
10526
11063
|
end
|
10527
|
-
|
11064
|
+
alias_method :list_box, :ListBox
|
10528
11065
|
|
10529
11066
|
#
|
10530
|
-
#
|
10531
|
-
# [@
|
11067
|
+
# Creates a Combo-box field
|
11068
|
+
# [@param string :name] field name
|
11069
|
+
# [@param int :w] width
|
11070
|
+
# [@param int :h] height
|
11071
|
+
# [@param array :values] array containing the list of values.
|
11072
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
11073
|
+
# [@param array :opt] annotation parameters. Possible values are described on official PDF32000_2008 reference.
|
11074
|
+
# [@param float :x] Abscissa of the upper-left corner of the rectangle
|
11075
|
+
# [@param float :y] Ordinate of the upper-left corner of the rectangle
|
11076
|
+
# [@param boolean :js] if true put the field using JavaScript (requires Acrobat Writer to be rendered).
|
11077
|
+
# [@access public]
|
11078
|
+
# [@author Nicola Asuni]
|
11079
|
+
# [@since 4.8.000 (2009-09-07)]
|
11080
|
+
#
|
11081
|
+
def ComboBox(name, w, h, values, prop = {}, opt = {}, x = '', y = '', js = false)
|
11082
|
+
x = @x if x == ''
|
11083
|
+
y = @y if y == ''
|
11084
|
+
|
11085
|
+
if js
|
11086
|
+
addfield('combobox', name, x, y, w, h, prop)
|
11087
|
+
s = +''
|
11088
|
+
values.each {|v|
|
11089
|
+
if v.is_a?(Array)
|
11090
|
+
s << "['#{v[0]}','#{v[1]}'],"
|
11091
|
+
else
|
11092
|
+
s << "'#{v}',"
|
11093
|
+
end
|
11094
|
+
}
|
11095
|
+
@javascript << "f#{name}.setItems([#{s[0...-1]}]);\n"
|
11096
|
+
return
|
11097
|
+
end
|
11098
|
+
# get default style
|
11099
|
+
prop = getFormDefaultProp.merge prop
|
11100
|
+
prop['Combo'] = 'true'
|
11101
|
+
# get annotation data
|
11102
|
+
popt = getAnnotOptFromJSProp(prop)
|
11103
|
+
# set additional default options
|
11104
|
+
font = @font_family
|
11105
|
+
fontkey = @fontkeys.index font
|
11106
|
+
unless @annotation_fonts.include? fontkey
|
11107
|
+
@annotation_fonts[font] = fontkey
|
11108
|
+
end
|
11109
|
+
|
11110
|
+
s = +''
|
11111
|
+
values.each {|v|
|
11112
|
+
if v.is_a?(Array)
|
11113
|
+
s << "#{v[1]}\n"
|
11114
|
+
else
|
11115
|
+
s << "#{v}\n"
|
11116
|
+
end
|
11117
|
+
}
|
11118
|
+
fontstyle = sprintf('/F%d %.2f Tf %s', fontkey + 1, @font_size_pt, @text_color)
|
11119
|
+
popt['da'] = fontstyle
|
11120
|
+
popt['ap'] = {}
|
11121
|
+
# set Appearances
|
11122
|
+
popt['ap']['n'] = +"/Tx BMC q #{fontstyle} "
|
11123
|
+
gvars = getGraphicVars()
|
11124
|
+
@h = h
|
11125
|
+
@w = w
|
11126
|
+
@t_margin = 0
|
11127
|
+
@c_margin = 0.2
|
11128
|
+
|
11129
|
+
@tmp_buffer = +''
|
11130
|
+
multi_cell(w, h, s, 0, '', 0, 0, 0.2, 0, true, 0, false, true, 0)
|
11131
|
+
popt['ap']['n'] << @tmp_buffer
|
11132
|
+
popt['ap']['n'] << 'Q EMC'
|
11133
|
+
@tmp_buffer = nil
|
11134
|
+
|
11135
|
+
# restore previous values
|
11136
|
+
setGraphicVars(gvars, true)
|
11137
|
+
|
11138
|
+
# merge options
|
11139
|
+
opt = popt.merge opt
|
11140
|
+
# set remaining annotation data
|
11141
|
+
opt['Subtype'] = 'Widget'
|
11142
|
+
opt['ft'] = 'Ch'
|
11143
|
+
opt['t'] = name
|
11144
|
+
opt['opt'] = values
|
11145
|
+
Annotation(x, y, w, h, name, opt, 0)
|
11146
|
+
if @rtl
|
11147
|
+
@x -= w
|
11148
|
+
else
|
11149
|
+
@x += w
|
11150
|
+
end
|
11151
|
+
end
|
11152
|
+
alias_method :combo_box, :ComboBox
|
11153
|
+
|
11154
|
+
#
|
11155
|
+
# Creates a CheckBox field
|
11156
|
+
# [@param string :name] field name
|
11157
|
+
# [@param int :w] width
|
11158
|
+
# [@param boolean :checked] define the initial state.
|
11159
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
11160
|
+
# [@param array :opt] annotation parameters. Possible values are described on official PDF32000_2008 reference.
|
11161
|
+
# [@param string :onvalue] value to be returned if selected.
|
11162
|
+
# [@param float :x] Abscissa of the upper-left corner of the rectangle
|
11163
|
+
# [@param float :y] Ordinate of the upper-left corner of the rectangle
|
11164
|
+
# [@param boolean :js] if true put the field using JavaScript (requires Acrobat Writer to be rendered).
|
11165
|
+
# [@access public]
|
11166
|
+
# [@author Nicola Asuni]
|
11167
|
+
# [@since 4.8.000 (2009-09-07)]
|
11168
|
+
#
|
11169
|
+
def CheckBox(name, w, checked=false, prop = {}, opt = {}, onvalue = 'Yes', x = '', y = '', js = false)
|
11170
|
+
x = @x if x == ''
|
11171
|
+
y = @y if y == ''
|
11172
|
+
|
11173
|
+
if js
|
11174
|
+
addfield('checkbox', name, x, y, w, w, prop)
|
11175
|
+
return
|
11176
|
+
end
|
11177
|
+
|
11178
|
+
prop['value'] ||= ['Yes']
|
11179
|
+
# get default style
|
11180
|
+
prop = getFormDefaultProp.merge prop
|
11181
|
+
prop['borderStyle'] = 'inset'
|
11182
|
+
# get annotation data
|
11183
|
+
popt = getAnnotOptFromJSProp(prop)
|
11184
|
+
# set additional default options
|
11185
|
+
font = 'zapfdingbats'
|
11186
|
+
AddFont(font)
|
11187
|
+
fontkey = @fontkeys.index font
|
11188
|
+
unless @annotation_fonts.include? fontkey
|
11189
|
+
@annotation_fonts[font] = fontkey
|
11190
|
+
end
|
11191
|
+
fontstyle = sprintf('/F%d %.2f Tf', fontkey + 1, @font_size_pt)
|
11192
|
+
popt['da'] = "#{fontstyle} #{@text_color}"
|
11193
|
+
popt['ap'] = {}
|
11194
|
+
popt['ap']['n'] = {}
|
11195
|
+
popt['ap']['n']['Yes'] = "q #{@text_color} BT #{fontstyle} 0 0 Td (n) Tj ET Q"
|
11196
|
+
popt['ap']['n']['Off'] = "q #{@text_color} BT #{fontstyle} 0 0 Td (o) Tj ET Q"
|
11197
|
+
|
11198
|
+
# merge options
|
11199
|
+
opt = popt.merge opt
|
11200
|
+
# set remaining annotation data
|
11201
|
+
opt['Subtype'] = 'Widget'
|
11202
|
+
opt['ft'] = 'Btn'
|
11203
|
+
opt['t'] = name
|
11204
|
+
if empty_string(onvalue)
|
11205
|
+
onvalue = 'Yes'
|
11206
|
+
end
|
11207
|
+
opt['opt'] = [onvalue]
|
11208
|
+
if checked
|
11209
|
+
opt['v'] = ['/Yes']
|
11210
|
+
opt['as'] = 'Yes'
|
11211
|
+
else
|
11212
|
+
opt['v'] = ['/Off']
|
11213
|
+
opt['as'] = 'Off'
|
11214
|
+
end
|
11215
|
+
Annotation(x, y, w, w, name, opt, 0)
|
11216
|
+
if @rtl
|
11217
|
+
@x -= w
|
11218
|
+
else
|
11219
|
+
@x += w
|
11220
|
+
end
|
11221
|
+
end
|
11222
|
+
alias_method :check_box, :CheckBox
|
11223
|
+
|
11224
|
+
#
|
11225
|
+
# Creates a button field
|
11226
|
+
# [@param string :name] field name
|
11227
|
+
# [@param int :w] width
|
11228
|
+
# [@param int :h] height
|
11229
|
+
# [@param string :caption] caption.
|
11230
|
+
# [@param mixed :action] action triggered by pressing the button. Use a string to specify a javascript action. Use an array to specify a form action options as on section 12.7.5 of PDF32000_2008.
|
11231
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
11232
|
+
# [@param array :opt] annotation parameters. Possible values are described on official PDF32000_2008 reference.
|
11233
|
+
# [@param float :x] Abscissa of the upper-left corner of the rectangle
|
11234
|
+
# [@param float :y] Ordinate of the upper-left corner of the rectangle
|
11235
|
+
# [@param boolean :js] if true put the field using JavaScript (requires Acrobat Writer to be rendered).
|
11236
|
+
# [@access public]
|
11237
|
+
# [@author Nicola Asuni]
|
11238
|
+
# [@since 4.8.000 (2009-09-07)]
|
11239
|
+
#
|
11240
|
+
def Button(name, w, h, caption, action, prop = {}, opt = {}, x = '', y = '', js = false)
|
11241
|
+
x = @x if x == ''
|
11242
|
+
y = @y if y == ''
|
11243
|
+
|
11244
|
+
if js
|
11245
|
+
addfield('button', name, x, y, w, h, prop)
|
11246
|
+
@javascript << "f#{name}.buttonSetCaption('#{caption}');\n"
|
11247
|
+
@javascript << "f#{name}.setAction('MouseUp','#{action}');\n"
|
11248
|
+
@javascript << "f#{name}.highlight='push';\n"
|
11249
|
+
@javascript << "f#{name}.print=false;\n"
|
11250
|
+
return
|
11251
|
+
end
|
11252
|
+
# get default style
|
11253
|
+
prop = getFormDefaultProp.merge prop
|
11254
|
+
prop['Pushbutton'] = 'true'
|
11255
|
+
prop['highlight'] = 'push'
|
11256
|
+
prop['display'] = 'display.noPrint'
|
11257
|
+
# get annotation data
|
11258
|
+
popt = getAnnotOptFromJSProp(prop)
|
11259
|
+
# set additional default options
|
11260
|
+
popt['mk'] ||= {}
|
11261
|
+
popt['mk']['ca'] = textstring(caption)
|
11262
|
+
popt['mk']['rc'] = textstring(caption)
|
11263
|
+
popt['mk']['ac'] = textstring(caption)
|
11264
|
+
font = @font_family
|
11265
|
+
fontkey = @fontkeys.index font
|
11266
|
+
unless @annotation_fonts.include? fontkey
|
11267
|
+
@annotation_fonts[font] = fontkey
|
11268
|
+
end
|
11269
|
+
fontstyle = sprintf('/F%d %.2f Tf %s', fontkey + 1, @font_size_pt, @text_color)
|
11270
|
+
popt['da'] = fontstyle
|
11271
|
+
popt['ap'] = {}
|
11272
|
+
# set Appearances
|
11273
|
+
popt['ap']['n'] = +"/Tx BMC q #{fontstyle} 0.800 g\n"
|
11274
|
+
|
11275
|
+
gvars = getGraphicVars()
|
11276
|
+
@h = h
|
11277
|
+
@w = w
|
11278
|
+
@c_margin *= 1.6
|
11279
|
+
|
11280
|
+
@tmp_buffer = +''
|
11281
|
+
SetLineStyle({'width' => 1.0, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => [231]})
|
11282
|
+
SetFillColor(204)
|
11283
|
+
multi_cell(w, h, caption, 1, 'C', 1, 0, 0, 0, true)
|
11284
|
+
popt['ap']['n'] << @tmp_buffer
|
11285
|
+
popt['ap']['n'] << 'Q EMC'
|
11286
|
+
@tmp_buffer = nil
|
11287
|
+
|
11288
|
+
# restore previous values
|
11289
|
+
setGraphicVars(gvars, true)
|
11290
|
+
|
11291
|
+
# merge options
|
11292
|
+
opt = popt.merge opt
|
11293
|
+
# set remaining annotation data
|
11294
|
+
opt['Subtype'] = 'Widget'
|
11295
|
+
opt['ft'] = 'Btn'
|
11296
|
+
opt['t'] = caption
|
11297
|
+
opt['v'] = name
|
11298
|
+
unless action.empty?
|
11299
|
+
if action.is_a?(Hash)
|
11300
|
+
# form action options as on section 12.7.5 of PDF32000_2008.
|
11301
|
+
opt['aa'] = +'/D <<'
|
11302
|
+
bmode = ['SubmitForm', 'ResetForm', 'ImportData']
|
11303
|
+
action.each {|key, val|
|
11304
|
+
if (key == 'S') && bmode.include?(val)
|
11305
|
+
opt['aa'] << " /S /#{val}"
|
11306
|
+
elsif (key == 'F') && !val.empty?
|
11307
|
+
opt['aa'] << " /F #{datastring(val)}"
|
11308
|
+
elsif (key == 'Fields') && val.is_a?(Array) && !val.empty?
|
11309
|
+
opt['aa'] << ' /Fields ['
|
11310
|
+
val.each {|field|
|
11311
|
+
opt['aa'] << " #{textstring(field)}"
|
11312
|
+
}
|
11313
|
+
opt['aa'] << ']'
|
11314
|
+
elsif key == 'Flags'
|
11315
|
+
ff = 0
|
11316
|
+
if val.is_a?(Array)
|
11317
|
+
val.each {|flag|
|
11318
|
+
case flag
|
11319
|
+
when 'Include/Exclude'; ff |= 1 << 0
|
11320
|
+
when 'IncludeNoValueFields'; ff |= 1 << 1
|
11321
|
+
when 'ExportFormat'; ff |= 1 << 2
|
11322
|
+
when 'GetMethod'; ff |= 1 << 3
|
11323
|
+
when 'SubmitCoordinates'; ff |= 1 << 4
|
11324
|
+
when 'XFDF'; ff |= 1 << 5
|
11325
|
+
when 'IncludeAppendSaves'; ff |= 1 << 6
|
11326
|
+
when 'IncludeAnnotations'; ff |= 1 << 7
|
11327
|
+
when 'SubmitPDF'; ff |= 1 << 8
|
11328
|
+
when 'CanonicalFormat'; ff |= 1 << 9
|
11329
|
+
when 'ExclNonUserAnnots'; ff |= 1 << 10
|
11330
|
+
when 'ExclFKey'; ff |= 1 << 11
|
11331
|
+
when 'EmbedForm'; ff |= 1 << 13
|
11332
|
+
end
|
11333
|
+
}
|
11334
|
+
else
|
11335
|
+
ff = val.to_i
|
11336
|
+
end
|
11337
|
+
opt['aa'] << " /Flags #{ff}"
|
11338
|
+
end
|
11339
|
+
}
|
11340
|
+
opt['aa'] << ' >>'
|
11341
|
+
else
|
11342
|
+
# Javascript action or raw action command
|
11343
|
+
js_obj_id = addJavascriptObject(action)
|
11344
|
+
opt['aa'] = "/D #{js_obj_id} 0 R"
|
11345
|
+
end
|
11346
|
+
end
|
11347
|
+
Annotation(x, y, w, h, name, opt, 0)
|
11348
|
+
if @rtl
|
11349
|
+
@x -= w
|
11350
|
+
else
|
11351
|
+
@x += w
|
11352
|
+
end
|
11353
|
+
end
|
11354
|
+
alias_method :button, :Button
|
11355
|
+
|
11356
|
+
# --- END FORMS FIELDS ------------------------------------------------
|
11357
|
+
|
11358
|
+
#
|
11359
|
+
# Create a new page group.
|
11360
|
+
# * NOTE: call this function before calling AddPage()
|
11361
|
+
# [@param int :page] starting group page (leave empty for next page).
|
11362
|
+
# [@access public]
|
11363
|
+
# [@since 3.0.000 (2008-03-27)]
|
11364
|
+
#
|
11365
|
+
def startPageGroup(page=0)
|
11366
|
+
if !page.is_a? Integer or page.zero?
|
11367
|
+
page = @page + 1
|
11368
|
+
end
|
11369
|
+
@newpagegroup[page] = true
|
11370
|
+
end
|
11371
|
+
alias_method :start_page_group, :startPageGroup
|
11372
|
+
|
11373
|
+
#
|
11374
|
+
# Defines an alias for the total number of pages.
|
11375
|
+
# It will be substituted as the document is closed.
|
11376
|
+
# [@param string :alias] The alias.
|
11377
|
+
# [@access public]
|
11378
|
+
# [@since 1.4]
|
11379
|
+
# [@see] getAliasNbPages(), PageNo(), Footer()
|
11380
|
+
#
|
11381
|
+
def AliasNbPages(alias_nb ='{nb}')
|
11382
|
+
@alias_nb_pages = alias_nb
|
11383
|
+
end
|
11384
|
+
alias_method :alias_nb_pages, :AliasNbPages
|
11385
|
+
|
11386
|
+
#
|
11387
|
+
# Returns the string alias used for the total number of pages.
|
11388
|
+
# If the current font is unicode type, the returned string is surrounded by additional curly braces.
|
11389
|
+
# [@return string]
|
11390
|
+
# [@access public]
|
11391
|
+
# [@since 4.0.018 (2008-08-08)]
|
11392
|
+
# [@see] AliasNbPages(), PageNo(), Footer()
|
11393
|
+
#
|
11394
|
+
def getAliasNbPages()
|
11395
|
+
if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont0')
|
11396
|
+
return '{' + @alias_nb_pages + '}'
|
11397
|
+
end
|
11398
|
+
return @alias_nb_pages
|
11399
|
+
end
|
11400
|
+
alias_method :get_alias_nb_pages, :getAliasNbPages
|
11401
|
+
|
11402
|
+
#
|
11403
|
+
# Defines an alias for the page number.
|
11404
|
+
# It will be substituted as the document is closed.
|
11405
|
+
# [@param string :alias] The alias.
|
11406
|
+
# [@access public]
|
11407
|
+
# [@since 4.5.000 (2009-01-02)]
|
11408
|
+
# [@see] getAliasNbPages(), PageNo(), Footer()
|
11409
|
+
#
|
11410
|
+
def AliasNumPage(alias_num='{pnb}')
|
11411
|
+
# Define an alias for total number of pages
|
11412
|
+
@alias_num_page = alias_num
|
11413
|
+
end
|
11414
|
+
alias_method :alias_num_page, :AliasNumPage
|
11415
|
+
|
11416
|
+
#
|
11417
|
+
# Returns the string alias used for the page number.
|
11418
|
+
# If the current font is unicode type, the returned string is surrounded by additional curly braces.
|
11419
|
+
# [@return string]
|
11420
|
+
# [@access public]
|
11421
|
+
# [@since 4.5.000 (2009-01-02)]
|
11422
|
+
# [@see] AliasNbPages(), PageNo(), Footer()
|
11423
|
+
#
|
11424
|
+
def getAliasNumPage()
|
11425
|
+
if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont0')
|
11426
|
+
return '{' + @alias_num_page + '}'
|
11427
|
+
end
|
11428
|
+
return @alias_num_page
|
11429
|
+
end
|
11430
|
+
alias_method :get_alias_num_page, :getAliasNumPage
|
11431
|
+
|
11432
|
+
#
|
11433
|
+
# Return the current page in the group.
|
11434
|
+
# [@return] current page in the group
|
11435
|
+
# [@access public]
|
11436
|
+
# [@since 3.0.000 (2008-03-27)]
|
11437
|
+
#
|
11438
|
+
def getGroupPageNo()
|
11439
|
+
return @pagegroups[@currpagegroup]
|
11440
|
+
end
|
11441
|
+
alias_method :get_group_page_no, :getGroupPageNo
|
11442
|
+
|
11443
|
+
#
|
11444
|
+
# Returns the current group page number formatted as a string.
|
11445
|
+
# [@access public]
|
11446
|
+
# [@since 4.3.003 (2008-11-18)]
|
11447
|
+
# [@see] PaneNo(), formatPageNumber()
|
11448
|
+
#
|
11449
|
+
def getGroupPageNoFormatted()
|
11450
|
+
return formatPageNumber(getGroupPageNo())
|
11451
|
+
end
|
11452
|
+
alias_method :get_group_page_no_formatted, :getGroupPageNoFormatted
|
11453
|
+
|
11454
|
+
#
|
11455
|
+
# Return the alias of the current page group
|
11456
|
+
# If the current font is unicode type, the returned string is surrounded by additional curly braces.
|
11457
|
+
# (will be replaced by the total number of pages in this group).
|
11458
|
+
# [@return] alias of the current page group
|
11459
|
+
# [@access public]
|
11460
|
+
# [@since 3.0.000 (2008-03-27)]
|
11461
|
+
#
|
11462
|
+
def getPageGroupAlias()
|
11463
|
+
if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont1')
|
11464
|
+
return '{' + @currpagegroup + '}'
|
11465
|
+
end
|
11466
|
+
return @currpagegroup
|
11467
|
+
end
|
11468
|
+
alias_method :get_page_group_alias, :getPageGroupAlias
|
11469
|
+
|
11470
|
+
#
|
11471
|
+
# Return the alias for the page number on the current page group
|
11472
|
+
# If the current font is unicode type, the returned string is surrounded by additional curly braces.
|
11473
|
+
# (will be replaced by the total number of pages in this group).
|
11474
|
+
# [@return] alias of the current page group
|
11475
|
+
# [@access public]
|
11476
|
+
# [@since 4.5.000 (2009-01-02)]
|
11477
|
+
#
|
11478
|
+
def getPageNumGroupAlias()
|
11479
|
+
if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont0')
|
11480
|
+
return '{' + @currpagegroup.gsub('{nb', '{pnb') +'}'
|
11481
|
+
end
|
11482
|
+
return @currpagegroup.gsub('{nb', '{pnb')
|
11483
|
+
end
|
11484
|
+
alias_method :get_page_num_group_alias, :getPageNumGroupAlias
|
11485
|
+
|
11486
|
+
#
|
11487
|
+
# Format the page numbers.
|
11488
|
+
# This method can be overriden for custom formats.
|
11489
|
+
# [@param int :num] page number
|
11490
|
+
# [@access protected]
|
11491
|
+
# [@since 4.2.005 (2008-11-06)]
|
11492
|
+
#
|
11493
|
+
def formatPageNumber(num)
|
11494
|
+
return number_with_delimiter(num, :delimiter => ",")
|
11495
|
+
end
|
11496
|
+
protected :formatPageNumber
|
11497
|
+
|
11498
|
+
#
|
11499
|
+
# Format the page numbers on the Table Of Content.
|
11500
|
+
# This method can be overriden for custom formats.
|
11501
|
+
# [@param int :num] page number
|
11502
|
+
# [@access protected]
|
11503
|
+
# [@since 4.5.001 (2009-01-04)]
|
11504
|
+
# [@see] addTOC(), addHTMLTOC()
|
11505
|
+
#
|
11506
|
+
def formatTOCPageNumber(num)
|
11507
|
+
return number_with_delimiter(num, :delimiter => ",")
|
11508
|
+
end
|
11509
|
+
protected :formatTOCPageNumber
|
11510
|
+
|
11511
|
+
#
|
11512
|
+
# Returns the current page number formatted as a string.
|
11513
|
+
# [@access public]
|
10532
11514
|
# [@since 4.2.005 (2008-11-06)]
|
10533
11515
|
# [@see] PaneNo(), formatPageNumber()
|
10534
11516
|
#
|
@@ -10627,7 +11609,7 @@ public
|
|
10627
11609
|
newobj()
|
10628
11610
|
@extgstates[i] ||= {}
|
10629
11611
|
@extgstates[i]['n'] = @n
|
10630
|
-
out = '<< /Type /ExtGState'
|
11612
|
+
out = +'<< /Type /ExtGState'
|
10631
11613
|
if @extgstates[i]['parms']
|
10632
11614
|
@extgstates[i]['parms'].each {|k, v|
|
10633
11615
|
if v.is_a? Float
|
@@ -10761,6 +11743,434 @@ public
|
|
10761
11743
|
end
|
10762
11744
|
alias_method :set_viewer_preferences, :setViewerPreferences
|
10763
11745
|
|
11746
|
+
#
|
11747
|
+
# Paints a linear colour gradient.
|
11748
|
+
# [@param float :x] abscissa of the top left corner of the rectangle.
|
11749
|
+
# [@param float :y] ordinate of the top left corner of the rectangle.
|
11750
|
+
# [@param float :w] width of the rectangle.
|
11751
|
+
# [@param float :h] height of the rectangle.
|
11752
|
+
# [@param array :col1] first color (Grayscale, RGB or CMYK components).
|
11753
|
+
# [@param array :col2] second color (Grayscale, RGB or CMYK components).
|
11754
|
+
# [@param array :coords] array of the form (x1, y1, x2, y2) which defines the gradient vector (see linear_gradient_coords.jpg). The default value is from left to right (x1=0, y1=0, x2=1, y2=0).
|
11755
|
+
# [@since 3.1.000 (2008-06-09)]
|
11756
|
+
# [@access public]
|
11757
|
+
#
|
11758
|
+
def LinearGradient(x, y, w, h, col1=[], col2=[], coords=[0,0,1,0])
|
11759
|
+
Clip(x, y, w, h)
|
11760
|
+
Gradient(2, coords, [{'color' => col1, 'offset' => 0, 'exponent' => 1}, {'color' => col2, 'offset' => 1, 'exponent' => 1}], [], false)
|
11761
|
+
end
|
11762
|
+
alias_method :linear_gradient, :LinearGradient
|
11763
|
+
|
11764
|
+
#
|
11765
|
+
# Paints a radial colour gradient.
|
11766
|
+
# [@param float :x] abscissa of the top left corner of the rectangle.
|
11767
|
+
# [@param float :y] ordinate of the top left corner of the rectangle.
|
11768
|
+
# [@param float :w] width of the rectangle.
|
11769
|
+
# [@param float :h] height of the rectangle.
|
11770
|
+
# [@param array :col1] first color (Grayscale, RGB or CMYK components).
|
11771
|
+
# [@param array :col2] second color (Grayscale, RGB or CMYK components).
|
11772
|
+
# [@param array :coords] array of the form (fx, fy, cx, cy, r) where (fx, fy) is the starting point of the gradient with color1, (cx, cy) is the center of the circle with color2, and r is the radius of the circle (see radial_gradient_coords.jpg). (fx, fy) should be inside the circle, otherwise some areas will not be defined.
|
11773
|
+
# [@since 3.1.000 (2008-06-09)]
|
11774
|
+
# [@access public]
|
11775
|
+
#
|
11776
|
+
def RadialGradient(x, y, w, h, col1=[], col2=[], coords=[0.5,0.5,0.5,0.5,1])
|
11777
|
+
Clip(x, y, w, h)
|
11778
|
+
Gradient(3, coords, [{'color' => col1, 'offset' => 0, 'exponent' => 1}, {'color' => col2, 'offset' => 1, 'exponent' => 1}], [], false)
|
11779
|
+
end
|
11780
|
+
alias_method :radial_gradient, :RadialGradient
|
11781
|
+
|
11782
|
+
#
|
11783
|
+
# Paints a coons patch mesh.
|
11784
|
+
# [@param float :x] abscissa of the top left corner of the rectangle.
|
11785
|
+
# [@param float :y] ordinate of the top left corner of the rectangle.
|
11786
|
+
# [@param float :w] width of the rectangle.
|
11787
|
+
# [@param float :h] height of the rectangle.
|
11788
|
+
# [@param array :col1] first color (lower left corner) (RGB components).
|
11789
|
+
# [@param array :col2] second color (lower right corner) (RGB components).
|
11790
|
+
# [@param array :col3] third color (upper right corner) (RGB components).
|
11791
|
+
# [@param array :col4] fourth color (upper left corner) (RGB components).
|
11792
|
+
# [@param array :coords] <ul><li>for one patch mesh: array(float x1, float y1, .... float x12, float y12): 12 pairs of coordinates (normally from 0 to 1) which specify the Bezier control points that define the patch. First pair is the lower left edge point, next is its right control point (control point 2). Then the other points are defined in the order: control point 1, edge point, control point 2 going counter-clockwise around the patch. Last (x12, y12) is the first edge point's left control point (control point 1).</li><li>for two or more patch meshes: array[number of patches]: arrays with the following keys for each patch: f: where to put that patch (0 = first patch, 1, 2, 3 = right, top and left of precedent patch - I didn't figure this out completely - just try and error ;-) points: 12 pairs of coordinates of the Bezier control points as above for the first patch, 8 pairs of coordinates for the following patches, ignoring the coordinates already defined by the precedent patch (I also didn't figure out the order of these - also: try and see what's happening) colors: must be 4 colors for the first patch, 2 colors for the following patches</li></ul>
|
11793
|
+
# [@param array :coords_min] minimum value used by the coordinates. If a coordinate's value is smaller than this it will be cut to coords_min. default: 0
|
11794
|
+
# [@param array :coords_max] maximum value used by the coordinates. If a coordinate's value is greater than this it will be cut to coords_max. default: 1
|
11795
|
+
# [@param boolean :antialias] A flag indicating whether to filter the shading function to prevent aliasing artifacts.
|
11796
|
+
# [@since 3.1.000 (2008-06-09)]
|
11797
|
+
# [@access public]
|
11798
|
+
#
|
11799
|
+
def CoonsPatchMesh(x, y, w, h, col1=[], col2=[], col3=[], col4=[], coords=[0.00,0.0,0.33,0.00,0.67,0.00,1.00,0.00,1.00,0.33,1.00,0.67,1.00,1.00,0.67,1.00,0.33,1.00,0.00,1.00,0.00,0.67,0.00,0.33], coords_min=0, coords_max=1, antialias=false)
|
11800
|
+
Clip(x, y, w, h)
|
11801
|
+
n = @gradients.size + 1
|
11802
|
+
@gradients[n] = {}
|
11803
|
+
@gradients[n]['type'] = 6 #coons patch mesh
|
11804
|
+
@gradients[n]['coords'] = []
|
11805
|
+
@gradients[n]['antialias'] = antialias
|
11806
|
+
@gradients[n]['colors'] = []
|
11807
|
+
@gradients[n]['transparency'] = false
|
11808
|
+
# check the coords array if it is the simple array or the multi patch array
|
11809
|
+
if coords[0].is_a? Hash
|
11810
|
+
# multi patch array
|
11811
|
+
patch_array = coords
|
11812
|
+
else
|
11813
|
+
# simple array -> convert to multi patch array
|
11814
|
+
if col1[1].nil?
|
11815
|
+
col1[1] = col1[2] = col1[0]
|
11816
|
+
end
|
11817
|
+
if col2[1].nil?
|
11818
|
+
col2[1] = col2[2] = col2[0]
|
11819
|
+
end
|
11820
|
+
if col3[1].nil?
|
11821
|
+
col3[1] = col3[2] = col3[0]
|
11822
|
+
end
|
11823
|
+
if col4[1].nil?
|
11824
|
+
col4[1] = col4[2] = col4[0]
|
11825
|
+
end
|
11826
|
+
patch_array = []
|
11827
|
+
patch_array[0] = {}
|
11828
|
+
patch_array[0]['f'] = 0
|
11829
|
+
patch_array[0]['points'] = coords
|
11830
|
+
patch_array[0]['colors'] = []
|
11831
|
+
patch_array[0]['colors'][0] = {}
|
11832
|
+
patch_array[0]['colors'][0]['r'] = col1[0]
|
11833
|
+
patch_array[0]['colors'][0]['g'] = col1[1]
|
11834
|
+
patch_array[0]['colors'][0]['b'] = col1[2]
|
11835
|
+
patch_array[0]['colors'][1] = {}
|
11836
|
+
patch_array[0]['colors'][1]['r'] = col2[0]
|
11837
|
+
patch_array[0]['colors'][1]['g'] = col2[1]
|
11838
|
+
patch_array[0]['colors'][1]['b'] = col2[2]
|
11839
|
+
patch_array[0]['colors'][2] = {}
|
11840
|
+
patch_array[0]['colors'][2]['r'] = col3[0]
|
11841
|
+
patch_array[0]['colors'][2]['g'] = col3[1]
|
11842
|
+
patch_array[0]['colors'][2]['b'] = col3[2]
|
11843
|
+
patch_array[0]['colors'][3] = {}
|
11844
|
+
patch_array[0]['colors'][3]['r'] = col4[0]
|
11845
|
+
patch_array[0]['colors'][3]['g'] = col4[1]
|
11846
|
+
patch_array[0]['colors'][3]['b'] = col4[2]
|
11847
|
+
end
|
11848
|
+
bpcd = 65535 #16 bits per coordinate
|
11849
|
+
# build the data stream
|
11850
|
+
@gradients[n]['stream'] = +''
|
11851
|
+
count_patch = patch_array.size
|
11852
|
+
count_patch.times do |i|
|
11853
|
+
@gradients[n]['stream'] << (patch_array[i]['f']).chr # start with the edge flag as 8 bit
|
11854
|
+
count_points = patch_array[i]['points'].size
|
11855
|
+
count_points.times do |j|
|
11856
|
+
# each point as 16 bit
|
11857
|
+
patch_array[i]['points'][j] = ((patch_array[i]['points'][j] - coords_min) / (coords_max - coords_min)) * bpcd
|
11858
|
+
if patch_array[i]['points'][j] < 0
|
11859
|
+
patch_array[i]['points'][j] = 0
|
11860
|
+
end
|
11861
|
+
if patch_array[i]['points'][j] > bpcd
|
11862
|
+
patch_array[i]['points'][j] = bpcd
|
11863
|
+
end
|
11864
|
+
@gradients[n]['stream'] << ((patch_array[i]['points'][j] / 256.0).floor).chr
|
11865
|
+
@gradients[n]['stream'] << ((patch_array[i]['points'][j] % 256.0).floor).chr
|
11866
|
+
end
|
11867
|
+
count_cols = patch_array[i]['colors'].size
|
11868
|
+
count_cols.times do |j|
|
11869
|
+
# each color component as 8 bit
|
11870
|
+
@gradients[n]['stream'] << (patch_array[i]['colors'][j]['r']).chr
|
11871
|
+
@gradients[n]['stream'] << (patch_array[i]['colors'][j]['g']).chr
|
11872
|
+
@gradients[n]['stream'] << (patch_array[i]['colors'][j]['b']).chr
|
11873
|
+
end
|
11874
|
+
end
|
11875
|
+
# paint the gradient
|
11876
|
+
out("/Sh#{n} sh")
|
11877
|
+
# restore previous Graphic State
|
11878
|
+
out('Q')
|
11879
|
+
end
|
11880
|
+
alias_method :coons_patch_mesh, :CoonsPatchMesh
|
11881
|
+
|
11882
|
+
#
|
11883
|
+
# Set a rectangular clipping area.
|
11884
|
+
# [@param float :x] abscissa of the top left corner of the rectangle (or top right corner for RTL mode).
|
11885
|
+
# [@param float :y] ordinate of the top left corner of the rectangle.
|
11886
|
+
# [@param float :w] width of the rectangle.
|
11887
|
+
# [@param float :h] height of the rectangle.
|
11888
|
+
# [@since 3.1.000 (2008-06-09)]
|
11889
|
+
# [@access protected]
|
11890
|
+
#
|
11891
|
+
def Clip(x, y, w, h)
|
11892
|
+
x = @w - x - w if @rtl
|
11893
|
+
|
11894
|
+
# save current Graphic State
|
11895
|
+
s = +'q'
|
11896
|
+
# set clipping area
|
11897
|
+
s << sprintf(' %.2f %.2f %.2f %.2f re W n', x * @k, (@h - y) * @k, w * @k, -h * @k)
|
11898
|
+
# set up transformation matrix for gradient
|
11899
|
+
s << sprintf(' %.3f 0 0 %.3f %.3f %.3f cm', w * @k, h * @k, x * @k, (@h - (y + h)) * @k)
|
11900
|
+
out(s)
|
11901
|
+
end
|
11902
|
+
protected :Clip
|
11903
|
+
|
11904
|
+
#
|
11905
|
+
# Output gradient.
|
11906
|
+
# [@param int :type] type of gradient (1 Function-based shading; 2 Axial shading; 3 Radial shading; 4 Free-form Gouraud-shaded triangle mesh; 5 Lattice-form Gouraud-shaded triangle mesh; 6 Coons patch mesh; 7 Tensor-product patch mesh). (Not all types are currently supported)
|
11907
|
+
# [@param array :coords] array of coordinates.
|
11908
|
+
# [@param array :stops] array gradient color components: color = array of GRAY, RGB or CMYK color components; offset = (0 to 1) represents a location along the gradient vector; exponent = exponent of the exponential interpolation function (default = 1).
|
11909
|
+
# [@param array :background] An array of colour components appropriate to the colour space, specifying a single background colour value.
|
11910
|
+
# [@param boolean :antialias] A flag indicating whether to filter the shading function to prevent aliasing artifacts.
|
11911
|
+
# [@since 3.1.000 (2008-06-09)]
|
11912
|
+
# [@access public]
|
11913
|
+
#
|
11914
|
+
def Gradient(type, coords, stops, background=[], antialias=false)
|
11915
|
+
n = @gradients.size + 1
|
11916
|
+
@gradients[n] = {}
|
11917
|
+
@gradients[n]['type'] = type
|
11918
|
+
@gradients[n]['coords'] = coords
|
11919
|
+
@gradients[n]['antialias'] = antialias
|
11920
|
+
@gradients[n]['colors'] = []
|
11921
|
+
@gradients[n]['transparency'] = false
|
11922
|
+
# color space
|
11923
|
+
numcolspace = stops[0]['color'].size
|
11924
|
+
bcolor = background
|
11925
|
+
case numcolspace
|
11926
|
+
when 4 # CMYK
|
11927
|
+
@gradients[n]['colspace'] = 'DeviceCMYK'
|
11928
|
+
unless background.empty?
|
11929
|
+
@gradients[n]['background'] = sprintf('%.3f %.3f %.3f %.3f', bcolor[0]/100.0, bcolor[1]/100.0, bcolor[2]/100.0, bcolor[3]/100.0)
|
11930
|
+
end
|
11931
|
+
when 3 # RGB
|
11932
|
+
@gradients[n]['colspace'] = 'DeviceRGB'
|
11933
|
+
unless background.empty?
|
11934
|
+
@gradients[n]['background'] = sprintf('%.3f %.3f %.3f', bcolor[0]/255.0, bcolor[1]/255.0, bcolor[2]/255.0)
|
11935
|
+
end
|
11936
|
+
when 1 # Gray scale
|
11937
|
+
@gradients[n]['colspace'] = 'DeviceGray'
|
11938
|
+
unless background.empty?
|
11939
|
+
@gradients[n]['background'] = sprintf('%.3f', bcolor[0]/255.0)
|
11940
|
+
end
|
11941
|
+
end
|
11942
|
+
num_stops = stops.size
|
11943
|
+
last_stop_id = num_stops - 1
|
11944
|
+
stops.each_with_index do |stop, key|
|
11945
|
+
@gradients[n]['colors'][key] = {}
|
11946
|
+
# offset represents a location along the gradient vector
|
11947
|
+
if stop['offset']
|
11948
|
+
@gradients[n]['colors'][key]['offset'] = stop['offset']
|
11949
|
+
else
|
11950
|
+
if key == 0
|
11951
|
+
@gradients[n]['colors'][key]['offset'] = 0
|
11952
|
+
elsif key == last_stop_id
|
11953
|
+
@gradients[n]['colors'][key]['offset'] = 1
|
11954
|
+
else
|
11955
|
+
offsetstep = (1 - @gradients[n]['colors'][key - 1]['offset']) / (num_stops - key)
|
11956
|
+
@gradients[n]['colors'][key]['offset'] = @gradients[n]['colors'][key - 1]['offset'] + offsetstep
|
11957
|
+
end
|
11958
|
+
end
|
11959
|
+
if stop['opacity']
|
11960
|
+
@gradients[n]['colors'][key]['opacity'] = stop['opacity']
|
11961
|
+
if stop['opacity'] < 1
|
11962
|
+
@gradients[n]['transparency'] = true
|
11963
|
+
end
|
11964
|
+
else
|
11965
|
+
@gradients[n]['colors'][key]['opacity'] = 1
|
11966
|
+
end
|
11967
|
+
# exponent for the exponential interpolation function
|
11968
|
+
if stop['exponent']
|
11969
|
+
@gradients[n]['colors'][key]['exponent'] = stop['exponent']
|
11970
|
+
else
|
11971
|
+
@gradients[n]['colors'][key]['exponent'] = 1
|
11972
|
+
end
|
11973
|
+
# set colors
|
11974
|
+
color = stop['color']
|
11975
|
+
case numcolspace
|
11976
|
+
when 4 # CMYK
|
11977
|
+
@gradients[n]['colors'][key]['color'] = sprintf('%.3f %.3f %.3f %.3f', color[0]/100.0, color[1]/100.0, color[2]/100.0, color[3]/100.0)
|
11978
|
+
when 3 # RGB
|
11979
|
+
@gradients[n]['colors'][key]['color'] = sprintf('%.3f %.3f %.3f', color[0]/255.0, color[1]/255.0, color[2]/255.0)
|
11980
|
+
when 1 # Gray scale
|
11981
|
+
@gradients[n]['colors'][key]['color'] = sprintf('%.3f', color[0]/255.0)
|
11982
|
+
end
|
11983
|
+
end
|
11984
|
+
if @gradients[n]['transparency']
|
11985
|
+
# paint luminosity gradient
|
11986
|
+
out("/TGS#{n} gs")
|
11987
|
+
end
|
11988
|
+
# paint the gradient
|
11989
|
+
out("/Sh#{n} sh")
|
11990
|
+
# restore previous Graphic State
|
11991
|
+
out('Q')
|
11992
|
+
end
|
11993
|
+
alias_method :gradient, :Gradient
|
11994
|
+
|
11995
|
+
#
|
11996
|
+
# Output gradient shaders.
|
11997
|
+
# [@since 3.1.000 (2008-06-09)]
|
11998
|
+
# [@access protected]
|
11999
|
+
#
|
12000
|
+
def putshaders()
|
12001
|
+
idt = @gradients.size #index for transparency gradients
|
12002
|
+
@gradients.each_with_index do |grad, id|
|
12003
|
+
next unless grad
|
12004
|
+
|
12005
|
+
if (grad['type'] == 2) || (grad['type'] == 3)
|
12006
|
+
newobj()
|
12007
|
+
fc = @n
|
12008
|
+
out = +'<<'
|
12009
|
+
out << ' /FunctionType 3'
|
12010
|
+
out << ' /Domain [0 1]'
|
12011
|
+
functions = +''
|
12012
|
+
bounds = +''
|
12013
|
+
encode = +''
|
12014
|
+
i = 1
|
12015
|
+
num_cols = grad['colors'].size
|
12016
|
+
lastcols = num_cols - 1
|
12017
|
+
1.upto(num_cols - 1) do |i|
|
12018
|
+
functions << "#{fc + i} 0 R "
|
12019
|
+
if i < lastcols
|
12020
|
+
bounds << sprintf('%.3f ', grad['colors'][i]['offset'])
|
12021
|
+
end
|
12022
|
+
encode << '0 1 '
|
12023
|
+
end
|
12024
|
+
out << " /Functions [#{functions.strip}]"
|
12025
|
+
out << " /Bounds [#{bounds.strip}]"
|
12026
|
+
out << " /Encode [#{encode.strip}]"
|
12027
|
+
out << ' >>'
|
12028
|
+
out << ' endobj'
|
12029
|
+
out(out)
|
12030
|
+
1.upto(num_cols - 1) do |i|
|
12031
|
+
newobj()
|
12032
|
+
out = +'<<'
|
12033
|
+
out << ' /FunctionType 2'
|
12034
|
+
out << ' /Domain [0 1]'
|
12035
|
+
out << " /C0 [#{grad['colors'][i - 1]['color']}]"
|
12036
|
+
out << " /C1 [#{grad['colors'][i]['color']}]"
|
12037
|
+
out << " /N #{grad['colors'][i]['exponent']}"
|
12038
|
+
out << ' >>'
|
12039
|
+
out << ' endobj'
|
12040
|
+
out(out)
|
12041
|
+
end
|
12042
|
+
# set transparency fuctions
|
12043
|
+
if grad['transparency']
|
12044
|
+
newobj()
|
12045
|
+
ft = @n
|
12046
|
+
out = +'<<'
|
12047
|
+
out << ' /FunctionType 3'
|
12048
|
+
out << ' /Domain [0 1]'
|
12049
|
+
functions = +''
|
12050
|
+
i = 1
|
12051
|
+
num_cols = grad['colors'].size
|
12052
|
+
1.upto(num_cols - 1) do |i|
|
12053
|
+
functions << "#{ft + i} 0 R "
|
12054
|
+
end
|
12055
|
+
out << " /Functions [#{functions.strip}]"
|
12056
|
+
out << " /Bounds [#{bounds.strip}]"
|
12057
|
+
out << " /Encode [#{encode.strip}]"
|
12058
|
+
out << ' >>'
|
12059
|
+
out << ' endobj'
|
12060
|
+
out(out)
|
12061
|
+
1.upto(num_cols - 1) do |i|
|
12062
|
+
newobj()
|
12063
|
+
out = +'<<'
|
12064
|
+
out << ' /FunctionType 2'
|
12065
|
+
out << ' /Domain [0 1]'
|
12066
|
+
out << " /C0 [#{grad['colors'][(i - 1)]['opacity']}]"
|
12067
|
+
out << " /C1 [#{grad['colors'][i]['opacity']}]"
|
12068
|
+
out << " /N #{grad['colors'][i]['exponent']}"
|
12069
|
+
out << ' >>'
|
12070
|
+
out << ' endobj'
|
12071
|
+
out(out)
|
12072
|
+
end
|
12073
|
+
end
|
12074
|
+
end
|
12075
|
+
# set shading object
|
12076
|
+
newobj()
|
12077
|
+
out = +"<< /ShadingType #{grad['type']}"
|
12078
|
+
if grad['colspace']
|
12079
|
+
out << " /ColorSpace /#{grad['colspace']}"
|
12080
|
+
else
|
12081
|
+
out << ' /ColorSpace /DeviceRGB'
|
12082
|
+
end
|
12083
|
+
if grad['background'] && !grad['background'].empty?
|
12084
|
+
out << " /Background [#{grad['background']}]"
|
12085
|
+
end
|
12086
|
+
if grad['antialias'] == true
|
12087
|
+
out << ' /AntiAlias true'
|
12088
|
+
end
|
12089
|
+
case grad['type']
|
12090
|
+
when 2
|
12091
|
+
out << sprintf(' /Coords [%.3f %.3f %.3f %.3f]', grad['coords'][0], grad['coords'][1], grad['coords'][2], grad['coords'][3])
|
12092
|
+
out << ' /Domain [0 1]'
|
12093
|
+
out << " /Function #{fc} 0 R"
|
12094
|
+
out << ' /Extend [true true]'
|
12095
|
+
out << ' >>'
|
12096
|
+
when 3
|
12097
|
+
# x0, y0, r0, x1, y1, r1
|
12098
|
+
# at this this time radius of inner circle is 0
|
12099
|
+
out << sprintf(' /Coords [%.3f %.3f 0 %.3f %.3f %.3f]', grad['coords'][0], grad['coords'][1], grad['coords'][2], grad['coords'][3], grad['coords'][4])
|
12100
|
+
out << ' /Domain [0 1]'
|
12101
|
+
out << " /Function #{fc} 0 R"
|
12102
|
+
out << ' /Extend [true true]'
|
12103
|
+
out << ' >>'
|
12104
|
+
when 6
|
12105
|
+
out << ' /BitsPerCoordinate 16'
|
12106
|
+
out << ' /BitsPerComponent 8'
|
12107
|
+
out << ' /Decode[0 1 0 1 0 1 0 1 0 1]'
|
12108
|
+
out << ' /BitsPerFlag 8'
|
12109
|
+
out << " /Length #{grad['stream'].length} >> "
|
12110
|
+
out << getstream(grad['stream'])
|
12111
|
+
end
|
12112
|
+
out << ' endobj'
|
12113
|
+
out(out)
|
12114
|
+
if grad['transparency']
|
12115
|
+
shading_transparency = out.gsub(%r{/ColorSpace /[^\s]+}mi, '/ColorSpace /DeviceGray')
|
12116
|
+
shading_transparency = shading_transparency.gsub(%r{/Function [0-9]+ }mi, "/Function #{ft} ")
|
12117
|
+
end
|
12118
|
+
@gradients[id]['id'] = @n
|
12119
|
+
# set pattern object
|
12120
|
+
newobj()
|
12121
|
+
out = +'<< /Type /Pattern /PatternType 2'
|
12122
|
+
out << " /Shading #{@gradients[id]['id']} 0 R"
|
12123
|
+
out << ' >> endobj'
|
12124
|
+
out(out)
|
12125
|
+
@gradients[id]['pattern'] = @n
|
12126
|
+
# set shading and pattern for transparency mask
|
12127
|
+
if grad['transparency']
|
12128
|
+
# luminosity pattern
|
12129
|
+
idgs = id + idt
|
12130
|
+
newobj()
|
12131
|
+
out(shading_transparency)
|
12132
|
+
@gradients[idgs] = {}
|
12133
|
+
@gradients[idgs]['id'] = @n
|
12134
|
+
newobj()
|
12135
|
+
out = +'<< /Type /Pattern /PatternType 2'
|
12136
|
+
out << " /Shading #{@gradients[idgs]['id']} 0 R"
|
12137
|
+
out << ' >> endobj'
|
12138
|
+
out(out)
|
12139
|
+
@gradients[idgs]['pattern'] = @n
|
12140
|
+
# luminosity XObject
|
12141
|
+
newobj()
|
12142
|
+
filter = ''
|
12143
|
+
stream = "q /a0 gs /Pattern cs /p#{idgs} scn 0 0 #{@w_pt} #{@h_pt} re f Q"
|
12144
|
+
if @compress
|
12145
|
+
filter = ' /Filter /FlateDecode'
|
12146
|
+
stream = Zlib::Deflate.deflate(stream)
|
12147
|
+
end
|
12148
|
+
out = +"<< /Type /XObject /Subtype /Form /FormType 1#{filter}"
|
12149
|
+
out << " /Length #{stream.length}"
|
12150
|
+
out << " /BBox [0 0 #{@w_pt} #{@h_pt}]"
|
12151
|
+
out << ' /Group << /Type /Group /S /Transparency /CS /DeviceGray >>'
|
12152
|
+
out << ' /Resources <<'
|
12153
|
+
out << ' /ExtGState << /a0 << /ca 1 /CA 1 >> >>'
|
12154
|
+
out << " /Pattern << /p#{idgs} #{@gradients[idgs]['pattern']} 0 R >>"
|
12155
|
+
out << ' >>'
|
12156
|
+
out << ' >> '
|
12157
|
+
out << getstream(stream)
|
12158
|
+
out << ' endobj'
|
12159
|
+
out(out)
|
12160
|
+
# SMask
|
12161
|
+
newobj()
|
12162
|
+
out = +"<< /Type /Mask /S /Luminosity /G #{@n - 1} 0 R >> endobj"
|
12163
|
+
out(out)
|
12164
|
+
# ExtGState
|
12165
|
+
newobj()
|
12166
|
+
out = +"<< /Type /ExtGState /SMask #{@n - 1} 0 R /AIS false >> endobj"
|
12167
|
+
out(out)
|
12168
|
+
@extgstates << {'n' => @n, 'name' => "TGS#{id}"}
|
12169
|
+
end
|
12170
|
+
end
|
12171
|
+
end
|
12172
|
+
protected :putshaders
|
12173
|
+
|
10764
12174
|
#
|
10765
12175
|
# Draw the sector of a circle.
|
10766
12176
|
# It can be used for instance to render pie charts.
|
@@ -11112,7 +12522,6 @@ protected
|
|
11112
12522
|
if dom[key]['attribute'] and dom[key]['attribute']['class'] and !dom[key]['attribute']['class'].empty?
|
11113
12523
|
selector_class = dom[key]['attribute']['class'].downcase
|
11114
12524
|
end
|
11115
|
-
id = ''
|
11116
12525
|
if dom[key]['attribute'] and dom[key]['attribute']['id'] and !dom[key]['attribute']['id'].empty?
|
11117
12526
|
selector_id = dom[key]['attribute']['id'].downcase
|
11118
12527
|
end
|
@@ -11229,7 +12638,7 @@ protected
|
|
11229
12638
|
# [@since 5.1.000 (2010-05-25)]
|
11230
12639
|
#
|
11231
12640
|
def getTagStyleFromCSS(dom, key, css)
|
11232
|
-
tagstyle = '' # style to be returned
|
12641
|
+
tagstyle = +'' # style to be returned
|
11233
12642
|
# get all styles that apply
|
11234
12643
|
css.each { |selector, style|
|
11235
12644
|
# remove specificity
|
@@ -11299,7 +12708,7 @@ protected
|
|
11299
12708
|
uri.split('/').each {|path|
|
11300
12709
|
uri_path = uri_path.join(path)
|
11301
12710
|
}
|
11302
|
-
cssdata = ''
|
12711
|
+
cssdata = +''
|
11303
12712
|
next unless File.exist?(uri_path)
|
11304
12713
|
|
11305
12714
|
open(uri_path) do |f|
|
@@ -11378,7 +12787,39 @@ protected
|
|
11378
12787
|
html = html_a + html_b + html[(pos + 6)..-1]
|
11379
12788
|
offset = (html_a + html_b).length
|
11380
12789
|
end
|
12790
|
+
|
12791
|
+
offset = 0
|
12792
|
+
while (offset < html.length) && (pos = html.index('</textarea>', offset))
|
12793
|
+
html_a = html[0, offset]
|
12794
|
+
html_b = html[offset, pos - offset + 11]
|
12795
|
+
while html_b =~ %r@<textarea([^\>]*)>(.*?)\n(.*?)</textarea>@mi
|
12796
|
+
# preserve newlines on <textarea> tag
|
12797
|
+
html_b.gsub!(%r@<textarea([^\>]*)>(.*?)\n(.*?)</textarea>@mi, "<textarea\\1>\\2<TBR>\\3</textarea>")
|
12798
|
+
html_b.gsub!(%r@<textarea([^\>]*)>(.*?)[\"](.*?)</textarea>@mi, "<textarea\\1>\\2''\\3</textarea>")
|
12799
|
+
end
|
12800
|
+
html = html_a + html_b + html[(pos + 11)..-1]
|
12801
|
+
offset = html_a.length + html_b.length
|
12802
|
+
end
|
12803
|
+
html.gsub!(/([\s]*)<option/mi, "<option")
|
12804
|
+
html.gsub!(%r@</option>([\s]*)@mi, "</option>")
|
12805
|
+
offset = 0
|
12806
|
+
while (offset < html.length) && (pos = html.index('</option>', offset))
|
12807
|
+
html_a = html[0, offset]
|
12808
|
+
html_b = html[offset, pos - offset + 9]
|
12809
|
+
while html_b =~ %r@<option([^\>]*)>(.*?)</option>@mi
|
12810
|
+
html_b.gsub!(%r@<option([\s]+)value=\"([^\"]*)\"([^\>]*)>(.*?)</option>@mi, "\\2\t\\4\r")
|
12811
|
+
html_b.gsub!(%r@<option([^\>]*)>(.*?)</option>@mi, "\\2\r")
|
12812
|
+
end
|
12813
|
+
html = html_a + html_b + html[(pos + 9)..-1]
|
12814
|
+
offset = html_a.length + html_b.length
|
12815
|
+
end
|
12816
|
+
html.gsub!(/<select([^\>]*)>/mi, "<select\\1 opt=\"")
|
12817
|
+
html.gsub!(%r@([\s]+)</select>@mi, "\" />")
|
11381
12818
|
html.gsub!(/[\n]/, " ")
|
12819
|
+
|
12820
|
+
# restore textarea newlines
|
12821
|
+
html.gsub!('<TBR>', "\n")
|
12822
|
+
|
11382
12823
|
# remove extra spaces from code
|
11383
12824
|
html.gsub!(/[\s]+<\/(table|tr|td|th|ul|ol|li|dl|dt|dd)>/, '</\\1>')
|
11384
12825
|
html.gsub!(/[\s]+<(tr|td|th|ul|ol|li|dl|dt|dd|br)/, '<\\1')
|
@@ -11389,6 +12830,8 @@ protected
|
|
11389
12830
|
html.gsub!(/[\s]*<img/, ' <img')
|
11390
12831
|
html.gsub!(/<img([^\>]*)>/xi, '<img\\1><span><marker style="font-size:0"/></span>')
|
11391
12832
|
html.gsub!(/<xre/, '<pre') # restore pre tag
|
12833
|
+
html.gsub!(/<textarea([^\>]*)>/xi, '<textarea\\1 value="')
|
12834
|
+
html.gsub!(/<\/textarea>/, '" />')
|
11392
12835
|
|
11393
12836
|
# trim string
|
11394
12837
|
html.gsub!(/^[\s]+/, '')
|
@@ -11418,7 +12861,7 @@ protected
|
|
11418
12861
|
dom[key]['fill'] = ((@textrendermode % 2) == 0)
|
11419
12862
|
dom[key]['clip'] = (@textrendermode > 3)
|
11420
12863
|
dom[key]['line-height'] = @cell_height_ratio
|
11421
|
-
dom[key]['bgcolor'] =
|
12864
|
+
dom[key]['bgcolor'] = []
|
11422
12865
|
dom[key]['fgcolor'] = @fgcolor.dup # color
|
11423
12866
|
dom[key]['strokecolor'] = @strokecolor.dup
|
11424
12867
|
|
@@ -11483,7 +12926,7 @@ protected
|
|
11483
12926
|
dom[grandparent]['cols'] = dom[(dom[key]['parent'])]['cols']
|
11484
12927
|
end
|
11485
12928
|
if (dom[key]['value'] == 'td') or (dom[key]['value'] == 'th')
|
11486
|
-
dom[(dom[key]['parent'])]['content'] = ''
|
12929
|
+
dom[(dom[key]['parent'])]['content'] = +''
|
11487
12930
|
(dom[key]['parent'] + 1).upto(key - 1) do |i|
|
11488
12931
|
dom[(dom[key]['parent'])]['content'] << a[dom[i]['elkey']]
|
11489
12932
|
end
|
@@ -11520,7 +12963,7 @@ protected
|
|
11520
12963
|
# *** opening html tag
|
11521
12964
|
dom[key]['opening'] = true
|
11522
12965
|
dom[key]['parent'] = level[-1]
|
11523
|
-
if element[-1, 1] == '/' or (dom[key]['value'] =~ /(br|img|hr)/)
|
12966
|
+
if element[-1, 1] == '/' or (dom[key]['value'] =~ /(br|img|hr|input)/)
|
11524
12967
|
# self-closing tag
|
11525
12968
|
dom[key]['self'] = true
|
11526
12969
|
else
|
@@ -11546,7 +12989,7 @@ protected
|
|
11546
12989
|
dom[key]['text-indent'] = dom[parentkey]['text-indent']
|
11547
12990
|
end
|
11548
12991
|
# get attributes
|
11549
|
-
attr_array = element.scan(/([^=\s]
|
12992
|
+
attr_array = element.scan(/([^=\s]+)[\s]*(?:=[\s]*"([^"]*)")*/)[1..-1]
|
11550
12993
|
dom[key]['attribute'] = {} # reset attribute array
|
11551
12994
|
attr_array.each do |name, value|
|
11552
12995
|
dom[key]['attribute'][name.downcase] = value
|
@@ -11636,7 +13079,7 @@ protected
|
|
11636
13079
|
end
|
11637
13080
|
end
|
11638
13081
|
# font style
|
11639
|
-
dom[key]['fontstyle'] ||= ""
|
13082
|
+
dom[key]['fontstyle'] ||= +""
|
11640
13083
|
if !dom[key]['style']['font-weight'].nil? and (dom[key]['style']['font-weight'][0,1].downcase == 'b')
|
11641
13084
|
dom[key]['fontstyle'] << 'B'
|
11642
13085
|
end
|
@@ -11645,13 +13088,13 @@ protected
|
|
11645
13088
|
end
|
11646
13089
|
# font color
|
11647
13090
|
if !empty_string(dom[key]['style']['color'])
|
11648
|
-
dom[key]['fgcolor'] =
|
13091
|
+
dom[key]['fgcolor'] = convert_html_color_to_dec_array(dom[key]['style']['color'])
|
11649
13092
|
elsif dom[key]['value'] == 'a'
|
11650
13093
|
dom[key]['fgcolor'] = @html_link_color_array
|
11651
13094
|
end
|
11652
13095
|
# background color
|
11653
13096
|
if !empty_string(dom[key]['style']['background-color'])
|
11654
|
-
dom[key]['bgcolor'] =
|
13097
|
+
dom[key]['bgcolor'] = convert_html_color_to_dec_array(dom[key]['style']['background-color'])
|
11655
13098
|
end
|
11656
13099
|
# text-decoration
|
11657
13100
|
if !dom[key]['style']['text-decoration'].nil?
|
@@ -11814,17 +13257,17 @@ protected
|
|
11814
13257
|
end
|
11815
13258
|
# set foreground color attribute
|
11816
13259
|
if !empty_string(dom[key]['attribute']['color'])
|
11817
|
-
dom[key]['fgcolor'] =
|
13260
|
+
dom[key]['fgcolor'] = convert_html_color_to_dec_array(dom[key]['attribute']['color'])
|
11818
13261
|
elsif (dom[key]['style'].nil? or dom[key]['style']['color'].nil?) and (dom[key]['value'] == 'a')
|
11819
13262
|
dom[key]['fgcolor'] = @html_link_color_array
|
11820
13263
|
end
|
11821
13264
|
# set background color attribute
|
11822
13265
|
if !empty_string(dom[key]['attribute']['bgcolor'])
|
11823
|
-
dom[key]['bgcolor'] =
|
13266
|
+
dom[key]['bgcolor'] = convert_html_color_to_dec_array(dom[key]['attribute']['bgcolor'])
|
11824
13267
|
end
|
11825
13268
|
# set stroke color attribute
|
11826
13269
|
if !empty_string(dom[key]['attribute']['strokecolor'])
|
11827
|
-
dom[key]['strokecolor'] =
|
13270
|
+
dom[key]['strokecolor'] = convert_html_color_to_dec_array(dom[key]['attribute']['strokecolor'])
|
11828
13271
|
end
|
11829
13272
|
# check for width attribute
|
11830
13273
|
if !dom[key]['attribute']['width'].nil?
|
@@ -11982,8 +13425,9 @@ public
|
|
11982
13425
|
def sanitize_html(html)
|
11983
13426
|
# Escape '<' character for not tag case.
|
11984
13427
|
html = html.gsub(%r{(<+)([^/a-zA-Z])}){CGI.escapeHTML($1) + $2}.gsub(%r{</([^a-zA-Z])}){'</' + $1}
|
11985
|
-
|
11986
|
-
|
13428
|
+
"%s" % sanitize(html,
|
13429
|
+
:tags=> %w(a b blockquote body br dd del div dl dt em font form h1 h2 h3 h4 h5 h6 hr i img input label li ol option p pre select small span strong sub sup table td textarea th thead tr tt u ins ul),
|
13430
|
+
:attributes => %w(cellspacing cellpadding bgcolor color value width height src size colspan rowspan style align border face href name dir class id nobr stroke strokecolor fill nested tablehead cols rows type action enctype method maxlength onclick multiple checked disabled))
|
11987
13431
|
end
|
11988
13432
|
protected :sanitize_html
|
11989
13433
|
|
@@ -12083,6 +13527,7 @@ public
|
|
12083
13527
|
prev_listordered = @listordered
|
12084
13528
|
prev_listcount = @listcount
|
12085
13529
|
prev_lispacer = @lispacer
|
13530
|
+
prev_li_position_x = @li_position_x
|
12086
13531
|
@listnum = 0
|
12087
13532
|
@listordered = []
|
12088
13533
|
@listcount = []
|
@@ -12172,8 +13617,8 @@ public
|
|
12172
13617
|
# restore previous object
|
12173
13618
|
rollbackTransaction(true)
|
12174
13619
|
# restore previous values
|
12175
|
-
this_method_vars.each {|vkey
|
12176
|
-
|
13620
|
+
this_method_vars.each {|vkey, vval|
|
13621
|
+
binding.local_variable_set(vkey, vval)
|
12177
13622
|
}
|
12178
13623
|
# add a page (or trig AcceptPageBreak() for multicolumn mode)
|
12179
13624
|
pre_y = @y
|
@@ -12946,7 +14391,7 @@ public
|
|
12946
14391
|
len1 = dom[key]['value'].length
|
12947
14392
|
lsp = len1 - dom[key]['value'].lstrip.length
|
12948
14393
|
rsp = len1 - dom[key]['value'].rstrip.length
|
12949
|
-
tmpstr = ''
|
14394
|
+
tmpstr = +''
|
12950
14395
|
if rsp > 0
|
12951
14396
|
tmpstr << dom[key]['value'][-rsp..-1]
|
12952
14397
|
end
|
@@ -13036,7 +14481,7 @@ public
|
|
13036
14481
|
rollbackTransaction(true)
|
13037
14482
|
# restore previous values
|
13038
14483
|
this_method_vars.each {|vkey , vval|
|
13039
|
-
|
14484
|
+
binding.local_variable_set(vkey, vval)
|
13040
14485
|
}
|
13041
14486
|
# add a page (or trig AcceptPageBreak() for multicolumn mode)
|
13042
14487
|
pre_y = @y
|
@@ -13155,6 +14600,7 @@ public
|
|
13155
14600
|
@listordered = prev_listordered
|
13156
14601
|
@listcount = prev_listcount
|
13157
14602
|
@lispacer = prev_lispacer
|
14603
|
+
@li_position_x = prev_li_position_x
|
13158
14604
|
dom = nil
|
13159
14605
|
rescue => err
|
13160
14606
|
Error('writeHTML Error.', err)
|
@@ -13471,6 +14917,7 @@ public
|
|
13471
14917
|
@lispacer = '!'
|
13472
14918
|
end
|
13473
14919
|
end
|
14920
|
+
@li_position_x = @x
|
13474
14921
|
when 'blockquote'
|
13475
14922
|
if @rtl
|
13476
14923
|
@r_margin += @listindent
|
@@ -13494,6 +14941,166 @@ public
|
|
13494
14941
|
SetXY(GetX(), GetY() + ((0.3 * @font_size_pt) / @k))
|
13495
14942
|
when 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
|
13496
14943
|
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
14944
|
+
|
14945
|
+
# Form fields (since 4.8.000 - 2009-09-07)
|
14946
|
+
when 'form'
|
14947
|
+
if tag['attribute']['action']
|
14948
|
+
@form_action = tag['attribute']['action']
|
14949
|
+
else
|
14950
|
+
@form_action = @@k_path_url + request&.base_url.to_s
|
14951
|
+
end
|
14952
|
+
if tag['attribute']['enctype']
|
14953
|
+
@form_enctype = tag['attribute']['enctype']
|
14954
|
+
else
|
14955
|
+
@form_enctype = 'application/x-www-form-urlencoded'
|
14956
|
+
end
|
14957
|
+
if tag['attribute']['method']
|
14958
|
+
@form_mode = tag['attribute']['method']
|
14959
|
+
else
|
14960
|
+
@form_mode = 'post'
|
14961
|
+
end
|
14962
|
+
when 'input'
|
14963
|
+
if tag['attribute']['type'] == 'checkbox' || (tag['attribute']['name'] && !empty_string(tag['attribute']['name']))
|
14964
|
+
name = tag['attribute']['name'] || rand.to_s
|
14965
|
+
prop = {}
|
14966
|
+
opt = {}
|
14967
|
+
if tag['attribute']['value'] && !empty_string(tag['attribute']['value'])
|
14968
|
+
value = tag['attribute']['value']
|
14969
|
+
end
|
14970
|
+
if tag['attribute']['maxlength'] && !empty_string(tag['attribute']['maxlength'])
|
14971
|
+
opt['maxlen'] = tag['attribute']['maxlength'].to_i
|
14972
|
+
end
|
14973
|
+
h = @font_size * @cell_height_ratio
|
14974
|
+
if tag['attribute']['size'] && !empty_string(tag['attribute']['size'])
|
14975
|
+
w = tag['attribute']['size'].to_i * GetStringWidth(32.chr) * 2
|
14976
|
+
else
|
14977
|
+
w = h
|
14978
|
+
end
|
14979
|
+
if tag['attribute'].key? 'disabled'
|
14980
|
+
prop['readonly'] = 'true'
|
14981
|
+
end
|
14982
|
+
if tag['attribute'].key? 'checked'
|
14983
|
+
checked = true
|
14984
|
+
else
|
14985
|
+
checked = false
|
14986
|
+
end
|
14987
|
+
|
14988
|
+
case tag['attribute']['type']
|
14989
|
+
when 'text'
|
14990
|
+
opt['v'] = value if value
|
14991
|
+
TextField(name, w, h, prop, opt, '', '', false)
|
14992
|
+
when 'password'
|
14993
|
+
opt['v'] = value if value
|
14994
|
+
prop['password'] = 'true'
|
14995
|
+
TextField(name, w, h, prop, opt, '', '', false)
|
14996
|
+
when 'checkbox'
|
14997
|
+
CheckBox(name, w, checked, prop, opt, value, '', '', false)
|
14998
|
+
when 'radio'
|
14999
|
+
RadioButton(name, w, prop, opt, value, checked, '', '', false)
|
15000
|
+
when 'submit'
|
15001
|
+
w = GetStringWidth(value) * 1.5
|
15002
|
+
h *= 1.6
|
15003
|
+
prop = {'lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>[196, 196, 196], 'strokeColor'=>[255, 255, 255]}
|
15004
|
+
action = {}
|
15005
|
+
action['S'] = 'SubmitForm'
|
15006
|
+
action['F'] = @form_action
|
15007
|
+
action['Flags'] = ['ExportFormat'] unless @form_enctype == 'FDF'
|
15008
|
+
action['Flags'] = ['GetMethod'] if @form_mode == 'get'
|
15009
|
+
Button(name, w, h, value, action, prop, opt, '', '', false)
|
15010
|
+
when 'reset'
|
15011
|
+
w = GetStringWidth(value) * 1.5
|
15012
|
+
h *= 1.6
|
15013
|
+
prop = {'lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>[196, 196, 196], 'strokeColor'=>[255, 255, 255]}
|
15014
|
+
Button(name, w, h, value, {'S'=>'ResetForm'}, prop, opt, '', '', false)
|
15015
|
+
when 'file'
|
15016
|
+
prop['fileSelect'] = 'true'
|
15017
|
+
TextField(name, w, h, prop, opt, '', '', false)
|
15018
|
+
value ||= '*'
|
15019
|
+
w = GetStringWidth(value) * 2
|
15020
|
+
h *= 1.2
|
15021
|
+
prop = {'lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>[196, 196, 196], 'strokeColor'=>[255, 255, 255]}
|
15022
|
+
jsaction = "var f=this.getField('#{name}'); f.browseForFileToSubmit();"
|
15023
|
+
Button('FB_' + name, w, h, value, jsaction, prop, opt, '', '', false)
|
15024
|
+
when 'hidden'
|
15025
|
+
opt['v'] = value if value
|
15026
|
+
opt['f'] = ['invisible', 'hidden']
|
15027
|
+
TextField(name, 0, 0, prop, opt, '', '', false)
|
15028
|
+
when 'image'
|
15029
|
+
# THIS TYPE MUST BE FIXED
|
15030
|
+
if tag['attribute']['src'] && !empty_string(tag['attribute']['src'])
|
15031
|
+
img = tag['attribute']['src']
|
15032
|
+
value = 'img'
|
15033
|
+
#opt['mk'] = {'i'=>img, 'tp'=>1, 'if'=>{'sw'=>'A', 's'=>'A', 'fb'=>false}}
|
15034
|
+
if tag['attribute']['onclick'] && !tag['attribute']['onclick'].empty?
|
15035
|
+
jsaction = tag['attribute']['onclick']
|
15036
|
+
else
|
15037
|
+
jsaction = ''
|
15038
|
+
end
|
15039
|
+
Button(name, w, h, value, jsaction, prop, opt, '', '', false)
|
15040
|
+
end
|
15041
|
+
when 'button'
|
15042
|
+
w = GetStringWidth(value) * 1.5
|
15043
|
+
h *= 1.6
|
15044
|
+
prop = {'lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>[196, 196, 196], 'strokeColor'=>[255, 255, 255]}
|
15045
|
+
if tag['attribute']['onclick'] && !tag['attribute']['onclick'].empty?
|
15046
|
+
jsaction = tag['attribute']['onclick']
|
15047
|
+
else
|
15048
|
+
jsaction = ''
|
15049
|
+
end
|
15050
|
+
Button(name, w, h, value, jsaction, prop, opt, '', '', false)
|
15051
|
+
end
|
15052
|
+
end
|
15053
|
+
when 'textarea'
|
15054
|
+
if tag['attribute']['name'] && !empty_string(tag['attribute']['name'])
|
15055
|
+
prop = {}
|
15056
|
+
opt = {}
|
15057
|
+
name = tag['attribute']['name']
|
15058
|
+
if tag['attribute']['value'] && !empty_string(tag['attribute']['value'])
|
15059
|
+
opt['v'] = tag['attribute']['value']
|
15060
|
+
end
|
15061
|
+
if tag['attribute']['cols'] && !empty_string(tag['attribute']['cols'])
|
15062
|
+
w = tag['attribute']['cols'].to_i * GetStringWidth(32.chr) * 2
|
15063
|
+
else
|
15064
|
+
w = 40
|
15065
|
+
end
|
15066
|
+
if tag['attribute']['rows'] && !empty_string(tag['attribute']['rows'])
|
15067
|
+
h = tag['attribute']['rows'].to_i * @font_size * @cell_height_ratio
|
15068
|
+
else
|
15069
|
+
h = 10
|
15070
|
+
end
|
15071
|
+
prop['multiline'] = 'true'
|
15072
|
+
TextField(name, w, h, prop, opt, '', '', false)
|
15073
|
+
end
|
15074
|
+
when 'select'
|
15075
|
+
if tag['attribute']['name'] && !empty_string(tag['attribute']['name']) && tag['attribute']['opt'] && !empty_string(tag['attribute']['opt'])
|
15076
|
+
h = @font_size * @cell_height_ratio
|
15077
|
+
if tag['attribute']['size'] && !empty_string(tag['attribute']['size'])
|
15078
|
+
h *= (tag['attribute']['size'].to_i + 1)
|
15079
|
+
end
|
15080
|
+
prop = {}
|
15081
|
+
opt = {}
|
15082
|
+
name = tag['attribute']['name']
|
15083
|
+
w = 0
|
15084
|
+
options = tag['attribute']['opt'].split("\r")
|
15085
|
+
values = []
|
15086
|
+
options.each {|val|
|
15087
|
+
if val.index("\t")
|
15088
|
+
opts = val.split("\t")
|
15089
|
+
values << opts
|
15090
|
+
w = [w, GetStringWidth(opts[1])].max
|
15091
|
+
else
|
15092
|
+
values << val
|
15093
|
+
w = [w, GetStringWidth(val)].max
|
15094
|
+
end
|
15095
|
+
}
|
15096
|
+
w *= 2
|
15097
|
+
if tag['attribute'].key? 'multiple'
|
15098
|
+
prop['multipleSelection'] = 'true'
|
15099
|
+
ListBox(name, w, h, values, prop, opt, '', '', false)
|
15100
|
+
else
|
15101
|
+
ComboBox(name, w, h, values, prop, opt, '', '', false)
|
15102
|
+
end
|
15103
|
+
end
|
13497
15104
|
end
|
13498
15105
|
|
13499
15106
|
if dom[key]['self'] and dom[key]['attribute']['pagebreakafter']
|
@@ -13569,317 +15176,325 @@ public
|
|
13569
15176
|
end
|
13570
15177
|
# Closing tag
|
13571
15178
|
case (tag['value'])
|
13572
|
-
|
13573
|
-
|
13574
|
-
|
13575
|
-
|
13576
|
-
|
15179
|
+
when 'tr'
|
15180
|
+
table_el = dom[(dom[key]['parent'])]['parent']
|
15181
|
+
if parent['endy'].nil?
|
15182
|
+
dom[(dom[key]['parent'])]['endy'] = @y
|
15183
|
+
parent['endy'] = @y
|
15184
|
+
end
|
15185
|
+
if parent['endpage'].nil?
|
15186
|
+
dom[(dom[key]['parent'])]['endpage'] = @page
|
15187
|
+
parent['endpage'] = @page
|
15188
|
+
end
|
15189
|
+
# update row-spanned cells
|
15190
|
+
if !dom[table_el]['rowspans'].nil?
|
15191
|
+
dom[table_el]['rowspans'].each_with_index { |trwsp, k|
|
15192
|
+
dom[table_el]['rowspans'][k]['rowspan'] -= 1
|
15193
|
+
if dom[table_el]['rowspans'][k]['rowspan'] == 0
|
15194
|
+
if dom[table_el]['rowspans'][k]['endpage'] == parent['endpage']
|
15195
|
+
dom[(dom[key]['parent'])]['endy'] = [dom[table_el]['rowspans'][k]['endy'], parent['endy']].max
|
15196
|
+
elsif dom[table_el]['rowspans'][k]['endpage'] > parent['endpage']
|
15197
|
+
dom[(dom[key]['parent'])]['endy'] = dom[table_el]['rowspans'][k]['endy']
|
15198
|
+
dom[(dom[key]['parent'])]['endpage'] = dom[table_el]['rowspans'][k]['endpage']
|
15199
|
+
end
|
15200
|
+
end
|
15201
|
+
}
|
15202
|
+
# report new endy and endpage to the rowspanned cells
|
15203
|
+
dom[table_el]['rowspans'].each_with_index { |trwsp, k|
|
15204
|
+
if dom[table_el]['rowspans'][k]['rowspan'] == 0
|
15205
|
+
dom[table_el]['rowspans'][k]['endpage'] = [dom[table_el]['rowspans'][k]['endpage'], dom[(dom[key]['parent'])]['endpage']].max
|
15206
|
+
dom[(dom[key]['parent'])]['endpage'] = dom[table_el]['rowspans'][k]['endpage']
|
15207
|
+
dom[table_el]['rowspans'][k]['endy'] = [dom[table_el]['rowspans'][k]['endy'], dom[(dom[key]['parent'])]['endy']].max
|
15208
|
+
dom[(dom[key]['parent'])]['endy'] = dom[table_el]['rowspans'][k]['endy']
|
15209
|
+
end
|
15210
|
+
}
|
15211
|
+
# update remaining rowspanned cells
|
15212
|
+
dom[table_el]['rowspans'].each_with_index { |trwsp, k|
|
15213
|
+
if dom[table_el]['rowspans'][k]['rowspan'] == 0
|
15214
|
+
dom[table_el]['rowspans'][k]['endpage'] = dom[(dom[key]['parent'])]['endpage']
|
15215
|
+
dom[table_el]['rowspans'][k]['endy'] = dom[(dom[key]['parent'])]['endy']
|
15216
|
+
end
|
15217
|
+
}
|
15218
|
+
end
|
15219
|
+
if (@num_columns > 1) and (dom[(dom[key]['parent'])]['endy'] >= (@page_break_trigger - @lasth)) and (@y < dom[(dom[key]['parent'])]['endy'])
|
15220
|
+
Ln(0, cell)
|
15221
|
+
else
|
15222
|
+
setPage(dom[(dom[key]['parent'])]['endpage']);
|
15223
|
+
@y = dom[(dom[key]['parent'])]['endy']
|
15224
|
+
if !dom[table_el]['attribute']['cellspacing'].nil?
|
15225
|
+
cellspacing = getHTMLUnitToUnits(dom[table_el]['attribute']['cellspacing'], 1, 'px')
|
15226
|
+
@y += cellspacing
|
13577
15227
|
end
|
13578
|
-
|
13579
|
-
|
13580
|
-
|
15228
|
+
Ln(0, cell)
|
15229
|
+
@x = parent['startx']
|
15230
|
+
# account for booklet mode
|
15231
|
+
if parent['startpage'] and @page > parent['startpage']
|
15232
|
+
if @rtl and (@pagedim[@page]['orm'] != @pagedim[parent['startpage']]['orm'])
|
15233
|
+
@x -= @pagedim[@page]['orm'] - @pagedim[parent['startpage']]['orm']
|
15234
|
+
elsif !@rtl and (@pagedim[@page]['olm'] != @pagedim[parent['startpage']]['olm'])
|
15235
|
+
@x += @pagedim[@page]['olm'] - @pagedim[parent['startpage']]['olm']
|
15236
|
+
end
|
13581
15237
|
end
|
15238
|
+
end
|
15239
|
+
when 'table'
|
15240
|
+
if dom[(dom[key]['parent'])]['attribute']['tablehead'] and dom[(dom[key]['parent'])]['attribute']['tablehead'] == "1"
|
15241
|
+
# closing tag used for the thead part
|
15242
|
+
in_table_head = true
|
15243
|
+
@in_thead = false
|
15244
|
+
end
|
15245
|
+
|
15246
|
+
table_el = parent
|
15247
|
+
# draw borders
|
15248
|
+
if (!table_el['attribute']['border'].nil? and (table_el['attribute']['border'].to_i > 0)) or (!table_el['style'].nil? and !table_el['style']['border'].nil? and (table_el['style']['border'].to_i > 0))
|
15249
|
+
border = 1
|
15250
|
+
else
|
15251
|
+
border = 0
|
15252
|
+
end
|
15253
|
+
|
15254
|
+
startpage = 0
|
15255
|
+
end_page = 0
|
15256
|
+
# fix bottom line alignment of last line before page break
|
15257
|
+
dom[(dom[key]['parent'])]['trids'].each_with_index { |trkey, j|
|
13582
15258
|
# update row-spanned cells
|
13583
|
-
if !dom[
|
13584
|
-
dom[
|
13585
|
-
|
13586
|
-
|
13587
|
-
if dom[table_el]['rowspans'][k]['endpage'] == parent['endpage']
|
13588
|
-
dom[(dom[key]['parent'])]['endy'] = [dom[table_el]['rowspans'][k]['endy'], parent['endy']].max
|
13589
|
-
elsif dom[table_el]['rowspans'][k]['endpage'] > parent['endpage']
|
13590
|
-
dom[(dom[key]['parent'])]['endy'] = dom[table_el]['rowspans'][k]['endy']
|
13591
|
-
dom[(dom[key]['parent'])]['endpage'] = dom[table_el]['rowspans'][k]['endpage']
|
13592
|
-
end
|
13593
|
-
end
|
13594
|
-
}
|
13595
|
-
# report new endy and endpage to the rowspanned cells
|
13596
|
-
dom[table_el]['rowspans'].each_with_index { |trwsp, k|
|
13597
|
-
if dom[table_el]['rowspans'][k]['rowspan'] == 0
|
13598
|
-
dom[table_el]['rowspans'][k]['endpage'] = [dom[table_el]['rowspans'][k]['endpage'], dom[(dom[key]['parent'])]['endpage']].max
|
13599
|
-
dom[(dom[key]['parent'])]['endpage'] = dom[table_el]['rowspans'][k]['endpage']
|
13600
|
-
dom[table_el]['rowspans'][k]['endy'] = [dom[table_el]['rowspans'][k]['endy'], dom[(dom[key]['parent'])]['endy']].max
|
13601
|
-
dom[(dom[key]['parent'])]['endy'] = dom[table_el]['rowspans'][k]['endy']
|
15259
|
+
if !dom[(dom[key]['parent'])]['rowspans'].nil?
|
15260
|
+
dom[(dom[key]['parent'])]['rowspans'].each_with_index { |trwsp, k|
|
15261
|
+
if trwsp['trid'] == trkey
|
15262
|
+
dom[(dom[key]['parent'])]['rowspans'][k]['mrowspan'] -= 1
|
13602
15263
|
end
|
13603
|
-
|
13604
|
-
|
13605
|
-
dom[table_el]['rowspans'].each_with_index { |trwsp, k|
|
13606
|
-
if dom[table_el]['rowspans'][k]['rowspan'] == 0
|
13607
|
-
dom[table_el]['rowspans'][k]['endpage'] = dom[(dom[key]['parent'])]['endpage']
|
13608
|
-
dom[table_el]['rowspans'][k]['endy'] = dom[(dom[key]['parent'])]['endy']
|
15264
|
+
if defined?(prevtrkey) and (trwsp['trid'] == prevtrkey) and (trwsp['mrowspan'] >= 0)
|
15265
|
+
dom[(dom[key]['parent'])]['rowspans'][k]['trid'] = trkey
|
13609
15266
|
end
|
13610
15267
|
}
|
13611
15268
|
end
|
13612
|
-
if (
|
13613
|
-
|
13614
|
-
|
13615
|
-
setPage(dom[(dom[key]['parent'])]['endpage']);
|
13616
|
-
@y = dom[(dom[key]['parent'])]['endy']
|
13617
|
-
if !dom[table_el]['attribute']['cellspacing'].nil?
|
13618
|
-
cellspacing = getHTMLUnitToUnits(dom[table_el]['attribute']['cellspacing'], 1, 'px')
|
13619
|
-
@y += cellspacing
|
13620
|
-
end
|
13621
|
-
Ln(0, cell)
|
13622
|
-
@x = parent['startx']
|
13623
|
-
# account for booklet mode
|
13624
|
-
if parent['startpage'] and @page > parent['startpage']
|
13625
|
-
if @rtl and (@pagedim[@page]['orm'] != @pagedim[parent['startpage']]['orm'])
|
13626
|
-
@x -= @pagedim[@page]['orm'] - @pagedim[parent['startpage']]['orm']
|
13627
|
-
elsif !@rtl and (@pagedim[@page]['olm'] != @pagedim[parent['startpage']]['olm'])
|
13628
|
-
@x += @pagedim[@page]['olm'] - @pagedim[parent['startpage']]['olm']
|
13629
|
-
end
|
13630
|
-
end
|
13631
|
-
end
|
13632
|
-
when 'table'
|
13633
|
-
if dom[(dom[key]['parent'])]['attribute']['tablehead'] and dom[(dom[key]['parent'])]['attribute']['tablehead'] == "1"
|
13634
|
-
# closing tag used for the thead part
|
13635
|
-
in_table_head = true
|
13636
|
-
@in_thead = false
|
13637
|
-
end
|
13638
|
-
|
13639
|
-
table_el = parent
|
13640
|
-
# draw borders
|
13641
|
-
if (!table_el['attribute']['border'].nil? and (table_el['attribute']['border'].to_i > 0)) or (!table_el['style'].nil? and !table_el['style']['border'].nil? and (table_el['style']['border'].to_i > 0))
|
13642
|
-
border = 1
|
13643
|
-
else
|
13644
|
-
border = 0
|
13645
|
-
end
|
13646
|
-
|
13647
|
-
startpage = 0
|
13648
|
-
end_page = 0
|
13649
|
-
# fix bottom line alignment of last line before page break
|
13650
|
-
dom[(dom[key]['parent'])]['trids'].each_with_index { |trkey, j|
|
15269
|
+
if defined?(prevtrkey) and (dom[trkey]['startpage'] > dom[prevtrkey]['endpage'])
|
15270
|
+
pgendy = @pagedim[dom[prevtrkey]['endpage']]['hk'] - @pagedim[dom[prevtrkey]['endpage']]['bm']
|
15271
|
+
dom[prevtrkey]['endy'] = pgendy
|
13651
15272
|
# update row-spanned cells
|
13652
15273
|
if !dom[(dom[key]['parent'])]['rowspans'].nil?
|
13653
15274
|
dom[(dom[key]['parent'])]['rowspans'].each_with_index { |trwsp, k|
|
13654
|
-
if trwsp['trid'] == trkey
|
13655
|
-
dom[(dom[key]['parent'])]['rowspans'][k]['
|
13656
|
-
|
13657
|
-
if defined?(prevtrkey) and (trwsp['trid'] == prevtrkey) and (trwsp['mrowspan'] >= 0)
|
13658
|
-
dom[(dom[key]['parent'])]['rowspans'][k]['trid'] = trkey
|
15275
|
+
if (trwsp['trid'] == trkey) and (trwsp['mrowspan'] > 1) and (trwsp['endpage'] == dom[prevtrkey]['endpage'])
|
15276
|
+
dom[(dom[key]['parent'])]['rowspans'][k]['endy'] = pgendy
|
15277
|
+
dom[(dom[key]['parent'])]['rowspans'][k]['mrowspan'] = -1
|
13659
15278
|
end
|
13660
15279
|
}
|
13661
15280
|
end
|
13662
|
-
|
13663
|
-
|
13664
|
-
|
13665
|
-
|
13666
|
-
|
13667
|
-
|
13668
|
-
|
13669
|
-
|
13670
|
-
|
13671
|
-
|
13672
|
-
|
13673
|
-
|
15281
|
+
end
|
15282
|
+
prevtrkey = trkey
|
15283
|
+
table_el = dom[(dom[key]['parent'])].dup
|
15284
|
+
}
|
15285
|
+
# for each row
|
15286
|
+
table_el['trids'].each_with_index { |trkey, j|
|
15287
|
+
parent = dom[trkey]
|
15288
|
+
# for each cell on the row
|
15289
|
+
parent['cellpos'].each_with_index { |cellpos, k|
|
15290
|
+
if !cellpos['rowspanid'].nil? and (cellpos['rowspanid'] >= 0)
|
15291
|
+
cellpos['startx'] = table_el['rowspans'][(cellpos['rowspanid'])]['startx']
|
15292
|
+
cellpos['endx'] = table_el['rowspans'][(cellpos['rowspanid'])]['endx']
|
15293
|
+
endy = table_el['rowspans'][(cellpos['rowspanid'])]['endy']
|
15294
|
+
startpage = table_el['rowspans'][(cellpos['rowspanid'])]['startpage']
|
15295
|
+
end_page = table_el['rowspans'][(cellpos['rowspanid'])]['endpage']
|
15296
|
+
else
|
15297
|
+
endy = parent['endy']
|
15298
|
+
startpage = parent['startpage']
|
15299
|
+
end_page = parent['endpage']
|
13674
15300
|
end
|
13675
|
-
|
13676
|
-
|
13677
|
-
|
13678
|
-
|
13679
|
-
|
13680
|
-
|
13681
|
-
|
13682
|
-
|
13683
|
-
|
13684
|
-
|
13685
|
-
|
13686
|
-
|
13687
|
-
|
13688
|
-
|
13689
|
-
|
13690
|
-
|
13691
|
-
|
13692
|
-
end_page = parent['endpage']
|
13693
|
-
end
|
13694
|
-
cellpos['startx'] ||= 0
|
13695
|
-
if end_page > startpage
|
13696
|
-
# design borders around HTML cells.
|
13697
|
-
startpage.upto(end_page) do |page|
|
13698
|
-
setPage(page)
|
13699
|
-
if page == startpage
|
13700
|
-
@y = parent['starty'] # put cursor at the beginning of row on the first page
|
13701
|
-
ch = getPageHeight() - parent['starty'] - getBreakMargin()
|
13702
|
-
cborder = getBorderMode(border, position='start')
|
13703
|
-
elsif page == end_page
|
13704
|
-
@y = @t_margin # put cursor at the beginning of last page
|
13705
|
-
ch = endy - @t_margin
|
13706
|
-
cborder = getBorderMode(border, position='end')
|
13707
|
-
else
|
13708
|
-
@y = @t_margin # put cursor at the beginning of the current page
|
13709
|
-
ch = getPageHeight() - @t_margin - getBreakMargin()
|
13710
|
-
cborder = getBorderMode(border, position='middle')
|
13711
|
-
end
|
13712
|
-
if !cellpos['bgcolor'].nil? and (cellpos['bgcolor'] != false)
|
13713
|
-
SetFillColorArray(cellpos['bgcolor'])
|
13714
|
-
fill = 1
|
13715
|
-
else
|
13716
|
-
fill = 0
|
13717
|
-
end
|
13718
|
-
cw = (cellpos['endx'] - cellpos['startx']).abs
|
13719
|
-
@x = cellpos['startx']
|
13720
|
-
# account for margin changes
|
13721
|
-
if page > startpage
|
13722
|
-
if @rtl and (@pagedim[page]['orm'] != @pagedim[startpage]['orm'])
|
13723
|
-
@x -= @pagedim[page]['orm'] - @pagedim[startpage]['orm']
|
13724
|
-
elsif !@rtl and (@pagedim[page]['lm'] != @pagedim[startpage]['olm'])
|
13725
|
-
@x += @pagedim[page]['olm'] - @pagedim[startpage]['olm']
|
13726
|
-
end
|
13727
|
-
end
|
13728
|
-
|
13729
|
-
prevLastH = @lasth
|
13730
|
-
# design a cell around the text
|
13731
|
-
ccode = @fill_color + "\n" + getCellCode(cw, ch, '', cborder, 1, '', fill, '', 0, true)
|
13732
|
-
@lasth = prevLastH
|
13733
|
-
|
13734
|
-
if (cborder != 0) or (fill == 1)
|
13735
|
-
pagebuff = getPageBuffer(@page)
|
13736
|
-
pstart = pagebuff[0, @intmrk[@page]]
|
13737
|
-
pend = pagebuff[@intmrk[@page]..-1]
|
13738
|
-
setPageBuffer(@page, pstart + ccode + "\n" + pend)
|
13739
|
-
@intmrk[@page] += (ccode + "\n").length
|
13740
|
-
end
|
15301
|
+
cellpos['startx'] ||= 0
|
15302
|
+
if end_page > startpage
|
15303
|
+
# design borders around HTML cells.
|
15304
|
+
startpage.upto(end_page) do |page|
|
15305
|
+
setPage(page)
|
15306
|
+
if page == startpage
|
15307
|
+
@y = parent['starty'] # put cursor at the beginning of row on the first page
|
15308
|
+
ch = getPageHeight() - parent['starty'] - getBreakMargin()
|
15309
|
+
cborder = getBorderMode(border, position='start')
|
15310
|
+
elsif page == end_page
|
15311
|
+
@y = @t_margin # put cursor at the beginning of last page
|
15312
|
+
ch = endy - @t_margin
|
15313
|
+
cborder = getBorderMode(border, position='end')
|
15314
|
+
else
|
15315
|
+
@y = @t_margin # put cursor at the beginning of the current page
|
15316
|
+
ch = getPageHeight() - @t_margin - getBreakMargin()
|
15317
|
+
cborder = getBorderMode(border, position='middle')
|
13741
15318
|
end
|
13742
|
-
else
|
13743
|
-
setPage(startpage)
|
13744
15319
|
if !cellpos['bgcolor'].nil? and (cellpos['bgcolor'] != false)
|
13745
15320
|
SetFillColorArray(cellpos['bgcolor'])
|
13746
15321
|
fill = 1
|
13747
15322
|
else
|
13748
15323
|
fill = 0
|
13749
15324
|
end
|
13750
|
-
@x = cellpos['startx']
|
13751
|
-
@y = parent['starty']
|
13752
15325
|
cw = (cellpos['endx'] - cellpos['startx']).abs
|
13753
|
-
|
15326
|
+
@x = cellpos['startx']
|
15327
|
+
# account for margin changes
|
15328
|
+
if page > startpage
|
15329
|
+
if @rtl and (@pagedim[page]['orm'] != @pagedim[startpage]['orm'])
|
15330
|
+
@x -= @pagedim[page]['orm'] - @pagedim[startpage]['orm']
|
15331
|
+
elsif !@rtl and (@pagedim[page]['lm'] != @pagedim[startpage]['olm'])
|
15332
|
+
@x += @pagedim[page]['olm'] - @pagedim[startpage]['olm']
|
15333
|
+
end
|
15334
|
+
end
|
13754
15335
|
|
13755
15336
|
prevLastH = @lasth
|
13756
15337
|
# design a cell around the text
|
13757
|
-
ccode = @fill_color + "\n" + getCellCode(cw, ch, '',
|
15338
|
+
ccode = @fill_color + "\n" + getCellCode(cw, ch, '', cborder, 1, '', fill, '', 0, true)
|
13758
15339
|
@lasth = prevLastH
|
13759
15340
|
|
13760
|
-
if (
|
13761
|
-
if !@transfmrk[@page].nil?
|
13762
|
-
pagemark = @transfmrk[@page]
|
13763
|
-
@transfmrk[@page] += (ccode + "\n").length
|
13764
|
-
elsif @in_footer
|
13765
|
-
pagemark = @footerpos[@page]
|
13766
|
-
@footerpos[@page] += (ccode + "\n").length
|
13767
|
-
else
|
13768
|
-
pagemark = @intmrk[@page]
|
13769
|
-
@intmrk[@page] += (ccode + "\n").length
|
13770
|
-
end
|
15341
|
+
if (cborder != 0) or (fill == 1)
|
13771
15342
|
pagebuff = getPageBuffer(@page)
|
13772
|
-
pstart = pagebuff[0,
|
13773
|
-
pend = pagebuff[
|
15343
|
+
pstart = pagebuff[0, @intmrk[@page]]
|
15344
|
+
pend = pagebuff[@intmrk[@page]..-1]
|
13774
15345
|
setPageBuffer(@page, pstart + ccode + "\n" + pend)
|
15346
|
+
@intmrk[@page] += (ccode + "\n").length
|
13775
15347
|
end
|
13776
15348
|
end
|
13777
|
-
|
13778
|
-
|
13779
|
-
|
13780
|
-
|
13781
|
-
|
13782
|
-
|
13783
|
-
|
13784
|
-
|
13785
|
-
|
13786
|
-
|
13787
|
-
|
13788
|
-
|
15349
|
+
else
|
15350
|
+
setPage(startpage)
|
15351
|
+
if !cellpos['bgcolor'].nil? and (cellpos['bgcolor'] != false)
|
15352
|
+
SetFillColorArray(cellpos['bgcolor'])
|
15353
|
+
fill = 1
|
15354
|
+
else
|
15355
|
+
fill = 0
|
15356
|
+
end
|
15357
|
+
@x = cellpos['startx']
|
15358
|
+
@y = parent['starty']
|
15359
|
+
cw = (cellpos['endx'] - cellpos['startx']).abs
|
15360
|
+
ch = endy - parent['starty']
|
15361
|
+
|
15362
|
+
prevLastH = @lasth
|
15363
|
+
# design a cell around the text
|
15364
|
+
ccode = @fill_color + "\n" + getCellCode(cw, ch, '', border, 1, '', fill, '', 0, true)
|
15365
|
+
@lasth = prevLastH
|
15366
|
+
|
15367
|
+
if (border != 0) or (fill == 1)
|
15368
|
+
if !@transfmrk[@page].nil?
|
15369
|
+
pagemark = @transfmrk[@page]
|
15370
|
+
@transfmrk[@page] += (ccode + "\n").length
|
15371
|
+
elsif @in_footer
|
15372
|
+
pagemark = @footerpos[@page]
|
15373
|
+
@footerpos[@page] += (ccode + "\n").length
|
15374
|
+
else
|
15375
|
+
pagemark = @intmrk[@page]
|
15376
|
+
@intmrk[@page] += (ccode + "\n").length
|
15377
|
+
end
|
15378
|
+
pagebuff = getPageBuffer(@page)
|
15379
|
+
pstart = pagebuff[0, pagemark]
|
15380
|
+
pend = pagebuff[pagemark..-1]
|
15381
|
+
setPageBuffer(@page, pstart + ccode + "\n" + pend)
|
13789
15382
|
end
|
13790
15383
|
end
|
13791
15384
|
}
|
13792
|
-
if !
|
13793
|
-
|
13794
|
-
|
13795
|
-
|
15385
|
+
if !table_el['attribute']['cellspacing'].nil?
|
15386
|
+
cellspacing = getHTMLUnitToUnits(table_el['attribute']['cellspacing'], 1, 'px')
|
15387
|
+
@y += cellspacing
|
15388
|
+
end
|
15389
|
+
Ln(0, cell)
|
15390
|
+
@x = parent['startx']
|
15391
|
+
if end_page > startpage
|
15392
|
+
if @rtl and (@pagedim[end_page]['orm'] != @pagedim[startpage]['orm'])
|
15393
|
+
@x += @pagedim[end_page]['orm'] - @pagedim[startpage]['orm']
|
15394
|
+
elsif !@rtl and (@pagedim[end_page]['olm'] != @pagedim[startpage]['olm'])
|
15395
|
+
@x += @pagedim[end_page]['olm'] - @pagedim[startpage]['olm']
|
13796
15396
|
end
|
13797
|
-
@lasth = @font_size * @cell_height_ratio
|
13798
|
-
if (@page == @numpages - 1) and @pageopen[@numpages]
|
13799
|
-
# remove last blank page
|
13800
|
-
deletePage(@numpages)
|
13801
|
-
end
|
13802
|
-
if !@thead_margins['top'].nil?
|
13803
|
-
# restore top margin
|
13804
|
-
@t_margin = @thead_margins['top']
|
13805
|
-
@pagedim[@page]['tm'] = @t_margin
|
13806
|
-
end
|
13807
|
-
if table_el['attribute']['nested'].nil? or (table_el['attribute']['nested'] != 'true')
|
13808
|
-
# reset main table header
|
13809
|
-
@thead = ''
|
13810
|
-
@thead_margins = {}
|
13811
|
-
end
|
13812
|
-
end
|
13813
|
-
if tag['block']
|
13814
|
-
unless dom[(dom[key]['parent'])]['attribute']['tablehead'] and dom[(dom[key]['parent'])]['attribute']['tablehead'] == "1" ### fix ###
|
13815
|
-
addHTMLVertSpace(hbz / 2, 0, cell, (dom[key+1].nil? or (dom[key+1]['value'] != 'table'))) ### fix ###
|
13816
|
-
end
|
13817
|
-
end
|
13818
|
-
when 'a'
|
13819
|
-
@href = {}
|
13820
|
-
@html_anchor = nil
|
13821
|
-
when 'sup'
|
13822
|
-
SetXY(GetX(), GetY() + (0.7 * parent['fontsize'] / @k))
|
13823
|
-
when 'sub'
|
13824
|
-
SetXY(GetX(), GetY() - (0.3 * parent['fontsize'] / @k))
|
13825
|
-
when 'div'
|
13826
|
-
addHTMLVertSpace(hbz, 0, cell, firstorlast)
|
13827
|
-
when 'blockquote'
|
13828
|
-
if @rtl
|
13829
|
-
@r_margin -= @listindent
|
13830
|
-
else
|
13831
|
-
@l_margin -= @listindent
|
13832
15397
|
end
|
13833
|
-
|
13834
|
-
|
13835
|
-
|
13836
|
-
|
13837
|
-
|
13838
|
-
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
13839
|
-
@premode = false
|
13840
|
-
when 'dl'
|
13841
|
-
@listnum -= 1
|
13842
|
-
if @listnum <= 0
|
13843
|
-
@listnum = 0
|
13844
|
-
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
13845
|
-
else
|
13846
|
-
addHTMLVertSpace(0, 0, cell, firstorlast)
|
15398
|
+
}
|
15399
|
+
if !in_table_head
|
15400
|
+
# we are not inside a thead section
|
15401
|
+
if dom[(parent['parent'])]['attribute']['cellpadding'] ### fix ###
|
15402
|
+
@c_margin = @old_c_margin
|
13847
15403
|
end
|
13848
15404
|
@lasth = @font_size * @cell_height_ratio
|
13849
|
-
|
13850
|
-
|
13851
|
-
|
13852
|
-
when 'dd'
|
13853
|
-
@lispacer = ''
|
13854
|
-
if @rtl
|
13855
|
-
@r_margin -= @listindent
|
13856
|
-
else
|
13857
|
-
@l_margin -= @listindent
|
15405
|
+
if (@page == @numpages - 1) and @pageopen[@numpages]
|
15406
|
+
# remove last blank page
|
15407
|
+
deletePage(@numpages)
|
13858
15408
|
end
|
13859
|
-
|
13860
|
-
|
13861
|
-
|
13862
|
-
|
13863
|
-
@lispacer = ''
|
13864
|
-
if @rtl
|
13865
|
-
@r_margin -= @listindent
|
13866
|
-
else
|
13867
|
-
@l_margin -= @listindent
|
15409
|
+
if !@thead_margins['top'].nil?
|
15410
|
+
# restore top margin
|
15411
|
+
@t_margin = @thead_margins['top']
|
15412
|
+
@pagedim[@page]['tm'] = @t_margin
|
13868
15413
|
end
|
13869
|
-
|
13870
|
-
|
13871
|
-
@
|
13872
|
-
|
13873
|
-
else
|
13874
|
-
addHTMLVertSpace(0, 0, cell, firstorlast)
|
15414
|
+
if table_el['attribute']['nested'].nil? or (table_el['attribute']['nested'] != 'true')
|
15415
|
+
# reset main table header
|
15416
|
+
@thead = ''
|
15417
|
+
@thead_margins = {}
|
13875
15418
|
end
|
13876
|
-
|
13877
|
-
|
13878
|
-
|
15419
|
+
end
|
15420
|
+
if tag['block']
|
15421
|
+
unless dom[(dom[key]['parent'])]['attribute']['tablehead'] and dom[(dom[key]['parent'])]['attribute']['tablehead'] == "1" ### fix ###
|
15422
|
+
addHTMLVertSpace(hbz / 2, 0, cell, (dom[key+1].nil? or (dom[key+1]['value'] != 'table'))) ### fix ###
|
15423
|
+
end
|
15424
|
+
end
|
15425
|
+
when 'a'
|
15426
|
+
@href = {}
|
15427
|
+
@html_anchor = nil
|
15428
|
+
when 'sup'
|
15429
|
+
SetXY(GetX(), GetY() + (0.7 * parent['fontsize'] / @k))
|
15430
|
+
when 'sub'
|
15431
|
+
SetXY(GetX(), GetY() - (0.3 * parent['fontsize'] / @k))
|
15432
|
+
when 'div'
|
15433
|
+
addHTMLVertSpace(hbz, 0, cell, firstorlast)
|
15434
|
+
when 'blockquote'
|
15435
|
+
if @rtl
|
15436
|
+
@r_margin -= @listindent
|
15437
|
+
else
|
15438
|
+
@l_margin -= @listindent
|
15439
|
+
end
|
15440
|
+
@listindentlevel -= 1
|
15441
|
+
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
15442
|
+
when 'p'
|
15443
|
+
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
15444
|
+
when 'pre'
|
15445
|
+
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
15446
|
+
@premode = false
|
15447
|
+
when 'dl'
|
15448
|
+
@listnum -= 1
|
15449
|
+
if @listnum <= 0
|
15450
|
+
@listnum = 0
|
15451
|
+
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
15452
|
+
else
|
13879
15453
|
addHTMLVertSpace(0, 0, cell, firstorlast)
|
13880
|
-
|
15454
|
+
end
|
15455
|
+
@lasth = @font_size * @cell_height_ratio
|
15456
|
+
when 'dt'
|
15457
|
+
@lispacer = ''
|
15458
|
+
@li_position_x = nil
|
15459
|
+
addHTMLVertSpace(0, 0, cell, firstorlast)
|
15460
|
+
when 'dd'
|
15461
|
+
@lispacer = ''
|
15462
|
+
@li_position_x = nil
|
15463
|
+
if @rtl
|
15464
|
+
@r_margin -= @listindent
|
15465
|
+
else
|
15466
|
+
@l_margin -= @listindent
|
15467
|
+
end
|
15468
|
+
@listindentlevel -= 1
|
15469
|
+
addHTMLVertSpace(0, 0, cell, firstorlast)
|
15470
|
+
when 'ul', 'ol'
|
15471
|
+
@listnum -= 1
|
15472
|
+
@lispacer = ''
|
15473
|
+
@li_position_x = nil
|
15474
|
+
if @rtl
|
15475
|
+
@r_margin -= @listindent
|
15476
|
+
else
|
15477
|
+
@l_margin -= @listindent
|
15478
|
+
end
|
15479
|
+
@listindentlevel -= 1
|
15480
|
+
if @listnum <= 0
|
15481
|
+
@listnum = 0
|
13881
15482
|
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
15483
|
+
else
|
15484
|
+
addHTMLVertSpace(0, 0, cell, firstorlast)
|
15485
|
+
end
|
15486
|
+
@lasth = @font_size * @cell_height_ratio
|
15487
|
+
when 'li'
|
15488
|
+
@lispacer = ''
|
15489
|
+
@li_position_x = nil
|
15490
|
+
addHTMLVertSpace(0, 0, cell, firstorlast)
|
15491
|
+
when 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
|
15492
|
+
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
15493
|
+
when 'form' # Form fields (since 4.8.000 - 2009-09-07)
|
15494
|
+
@form_action = ''
|
15495
|
+
@form_enctype = 'application/x-www-form-urlencoded'
|
13882
15496
|
end
|
15497
|
+
|
13883
15498
|
if dom[(dom[key]['parent'])]['attribute']['pagebreakafter']
|
13884
15499
|
pba = dom[(dom[key]['parent'])]['attribute']['pagebreakafter']
|
13885
15500
|
# check for pagebreak
|
@@ -14114,11 +15729,12 @@ protected
|
|
14114
15729
|
#
|
14115
15730
|
def putHtmlListBullet(listdepth, listtype='', size=10)
|
14116
15731
|
size /= @k
|
14117
|
-
fill = ''
|
15732
|
+
fill = +''
|
14118
15733
|
color = @fgcolor
|
14119
15734
|
width = 0
|
14120
15735
|
textitem = ''
|
14121
15736
|
tmpx = @x
|
15737
|
+
@x = @li_position_x
|
14122
15738
|
lspace = GetStringWidth(' ')
|
14123
15739
|
if listtype == '!'
|
14124
15740
|
# set default list type for unordered list
|
@@ -14132,7 +15748,7 @@ protected
|
|
14132
15748
|
# unordered types
|
14133
15749
|
when 'none'
|
14134
15750
|
when 'disc', 'circle'
|
14135
|
-
fill = 'F' if listtype == 'disc'
|
15751
|
+
fill = +'F' if listtype == 'disc'
|
14136
15752
|
fill << 'D'
|
14137
15753
|
r = size / 6.0
|
14138
15754
|
lspace += 2 * r
|
@@ -14190,6 +15806,7 @@ protected
|
|
14190
15806
|
end
|
14191
15807
|
@x = tmpx
|
14192
15808
|
@lispacer = ''
|
15809
|
+
@li_position_x = nil
|
14193
15810
|
end
|
14194
15811
|
|
14195
15812
|
#
|
@@ -14206,6 +15823,7 @@ protected
|
|
14206
15823
|
'rMargin' => @r_margin,
|
14207
15824
|
'lMargin' => @l_margin,
|
14208
15825
|
'cMargin' => @c_margin,
|
15826
|
+
'tMargin' => @t_margin,
|
14209
15827
|
'LineWidth' => @line_width,
|
14210
15828
|
'linestyleWidth' => @linestyle_width,
|
14211
15829
|
'linestyleCap' => @linestyle_cap,
|
@@ -14226,24 +15844,31 @@ protected
|
|
14226
15844
|
'listordered' => @listordered,
|
14227
15845
|
'listcount' => @listcount,
|
14228
15846
|
'lispacer' => @lispacer,
|
14229
|
-
'
|
15847
|
+
'li_position_x' => @li_position_x,
|
15848
|
+
'lasth' => @lasth,
|
15849
|
+
'h' => @h,
|
15850
|
+
'w' => @w,
|
15851
|
+
'x' => @x,
|
15852
|
+
'y' => @y,
|
14230
15853
|
}
|
14231
15854
|
return grapvars
|
14232
15855
|
end
|
14233
15856
|
|
14234
15857
|
#
|
14235
15858
|
# Set graphic variables.
|
14236
|
-
# [@param :gvars]
|
15859
|
+
# [@param array :gvars] graphic variables
|
15860
|
+
# [@param bool :option] set additional parameters
|
14237
15861
|
# [@access protected]
|
14238
15862
|
# [@since 4.2.010 (2008-11-14)]
|
14239
15863
|
#
|
14240
|
-
def setGraphicVars(gvars)
|
15864
|
+
def setGraphicVars(gvars, option = false)
|
14241
15865
|
@font_family = gvars['FontFamily']
|
14242
15866
|
@font_style = gvars['FontStyle']
|
14243
15867
|
@font_size_pt = gvars['FontSizePt']
|
14244
15868
|
@r_margin = gvars['rMargin']
|
14245
15869
|
@l_margin = gvars['lMargin']
|
14246
15870
|
@c_margin = gvars['cMargin']
|
15871
|
+
@t_margin = gvars['tMargin']
|
14247
15872
|
@line_width = gvars['LineWidth']
|
14248
15873
|
@linestyle_width = gvars['linestyleWidth']
|
14249
15874
|
@linestyle_cap = gvars['linestyleCap']
|
@@ -14264,7 +15889,14 @@ protected
|
|
14264
15889
|
@listordered = gvars['listordered']
|
14265
15890
|
@listcount = gvars['listcount']
|
14266
15891
|
@lispacer = gvars['lispacer']
|
14267
|
-
|
15892
|
+
@li_position_x = gvars['li_position_x']
|
15893
|
+
if option
|
15894
|
+
@lasth = gvars['lasth']
|
15895
|
+
@h = gvars['h']
|
15896
|
+
@w = gvars['w']
|
15897
|
+
@x = gvars['x']
|
15898
|
+
@y = gvars['y']
|
15899
|
+
end
|
14268
15900
|
out('' + @linestyle_width + ' ' + @linestyle_cap + ' ' + @linestyle_join + ' ' + @linestyle_dash + ' ' + @draw_color + ' ' + @fill_color + '')
|
14269
15901
|
unless empty_string(@font_family)
|
14270
15902
|
SetFont(@font_family, @font_style, @font_size_pt)
|
@@ -14329,7 +15961,7 @@ protected
|
|
14329
15961
|
#
|
14330
15962
|
def readDiskCache(filename)
|
14331
15963
|
filename = filename.path
|
14332
|
-
data = ''
|
15964
|
+
data = +''
|
14333
15965
|
open( filename,'rb') do |f|
|
14334
15966
|
data << f.read()
|
14335
15967
|
end
|
@@ -14671,18 +16303,17 @@ public
|
|
14671
16303
|
#global jfrompage, jtopage
|
14672
16304
|
#jfrompage = frompage
|
14673
16305
|
#jtopage = topage
|
14674
|
-
|
14675
|
-
#
|
14676
|
-
#
|
14677
|
-
#
|
14678
|
-
#
|
14679
|
-
#
|
14680
|
-
#
|
14681
|
-
#
|
14682
|
-
#
|
14683
|
-
#
|
14684
|
-
|
14685
|
-
# return "this.addField(\'".$matches[1]."\',\'".$matches[2]."\',".$newpage."";'), $tmpjavascript);
|
16306
|
+
#tmpjavascript =~ /this\.addField\(\'([^\']*)\',\'([^\']*)\',([0-9]+)/
|
16307
|
+
#pagenum = $3.to_i + 1
|
16308
|
+
#if (pagenum >= jtopage) && (pagenum < jfrompage)
|
16309
|
+
# newpage = pagenum + 1
|
16310
|
+
#elsif pagenum == jfrompage
|
16311
|
+
# newpage = jtopage
|
16312
|
+
#else
|
16313
|
+
# newpage = pagenum
|
16314
|
+
#end
|
16315
|
+
#newpage -= 1
|
16316
|
+
#@javascript = "this.addField(\'" + $1 + "\',\'" + $2 + "\'," + newpage + ""
|
14686
16317
|
|
14687
16318
|
# return to last page
|
14688
16319
|
lastPage(true)
|
@@ -15156,7 +16787,7 @@ public
|
|
15156
16787
|
if this_self
|
15157
16788
|
objvars = @objcopy.instance_variables
|
15158
16789
|
objvars.each {|key|
|
15159
|
-
|
16790
|
+
instance_variable_set(key, @objcopy.instance_variable_get(key)) if key.to_s != '@objcopy'
|
15160
16791
|
}
|
15161
16792
|
end
|
15162
16793
|
return @objcopy
|
@@ -15293,7 +16924,7 @@ public
|
|
15293
16924
|
# [@param string :default] default style
|
15294
16925
|
# [@param boolean :mode] if true enable rasterization, false otherwise.
|
15295
16926
|
# [@author] Nicola Asuni
|
15296
|
-
# [@access protected
|
16927
|
+
# [@access protected]
|
15297
16928
|
# [@since 5.0.000 (2010-04-30)]
|
15298
16929
|
#
|
15299
16930
|
def getPathPaintOperator(style, default='S')
|