rbpdf 1.21.1 → 1.21.3
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 +9 -0
- data/lib/rbpdf/version.rb +1 -1
- data/lib/rbpdf.rb +1528 -328
- metadata +2 -2
data/lib/rbpdf.rb
CHANGED
@@ -234,7 +234,7 @@ class RBPDF
|
|
234
234
|
# This is the class constructor.
|
235
235
|
# It allows to set up the page format, the orientation and
|
236
236
|
# the measure unit used in all the methods (except for the font sizes).
|
237
|
-
# @since 1.0
|
237
|
+
# [@since 1.0]
|
238
238
|
# [@param string :orientation]
|
239
239
|
# page orientation. Possible values are (case insensitive):
|
240
240
|
# * P or Portrait (default)
|
@@ -330,13 +330,16 @@ class RBPDF
|
|
330
330
|
@listindent ||= 0
|
331
331
|
@listindentlevel ||= 0
|
332
332
|
@lispacer ||= ""
|
333
|
+
@li_position_x = nil
|
333
334
|
|
334
335
|
# bookmark
|
335
336
|
@outlines ||= []
|
336
337
|
|
337
338
|
# --- javascript and form ---
|
338
339
|
@javascript ||= ''
|
339
|
-
@js_objects ||=
|
340
|
+
@js_objects ||= {}
|
341
|
+
@js_start_obj_id ||= 300000
|
342
|
+
@js_obj_id ||= 300000
|
340
343
|
|
341
344
|
@dpi = 72.0
|
342
345
|
@newpagegroup ||= []
|
@@ -394,6 +397,7 @@ class RBPDF
|
|
394
397
|
@page_obj_id ||= []
|
395
398
|
@embedded_start_obj_id ||= 100000
|
396
399
|
@form_obj_id ||= []
|
400
|
+
@default_form_prop ||= {'lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>[255, 255, 255], 'strokeColor'=>[128, 128, 128]}
|
397
401
|
@apxo_start_obj_id ||= 400000
|
398
402
|
@apxo_obj_id ||= 400000
|
399
403
|
@annotation_fonts ||= {}
|
@@ -446,6 +450,7 @@ class RBPDF
|
|
446
450
|
else
|
447
451
|
@buffer ||= ''
|
448
452
|
end
|
453
|
+
@tmp_buffer = nil
|
449
454
|
@pages ||= []
|
450
455
|
@prev_pages ||= []
|
451
456
|
@state ||= 0
|
@@ -4025,7 +4030,9 @@ class RBPDF
|
|
4025
4030
|
ccode = getCellCode(w, h, '', border, 1, '', fill, '', 0, true)
|
4026
4031
|
@lasth = prevLastH
|
4027
4032
|
|
4028
|
-
if
|
4033
|
+
if @tmp_buffer
|
4034
|
+
@tmp_buffer = "#{ccode}\n#{@tmp_buffer}"
|
4035
|
+
elsif (border != 0) or (fill == 1)
|
4029
4036
|
if !@transfmrk[@page].nil?
|
4030
4037
|
pagemark = @transfmrk[@page]
|
4031
4038
|
@transfmrk[@page] += (ccode + "\n").length
|
@@ -6033,21 +6040,20 @@ protected
|
|
6033
6040
|
annots << ' /FT /Btn'
|
6034
6041
|
annots << ' /Ff 49152'
|
6035
6042
|
annots << ' /Kids ['
|
6043
|
+
defval = nil
|
6036
6044
|
@radiobutton_groups[n][pl['txt']].each {|data|
|
6037
|
-
annots <<
|
6045
|
+
annots << " #{data['kid']} 0 R"
|
6038
6046
|
if data['def'] != 'Off'
|
6039
6047
|
defval = data['def']
|
6040
6048
|
end
|
6041
6049
|
}
|
6042
6050
|
annots << ' ]'
|
6043
|
-
if defval
|
6044
|
-
annots << ' /V /' + defval
|
6045
|
-
end
|
6051
|
+
annots << " /V /#{defval}" if defval
|
6046
6052
|
annots << ' >>'
|
6047
6053
|
@annot_obj_id += 1
|
6048
6054
|
@offsets[@annot_obj_id] = @bufferlen
|
6049
|
-
out(@annot_obj_id
|
6050
|
-
@form_obj_id
|
6055
|
+
out("#{@annot_obj_id} 0 obj #{annots} endobj")
|
6056
|
+
@form_obj_id << @annot_obj_id
|
6051
6057
|
# store object id to be used on Parent entry of Kids
|
6052
6058
|
@radiobutton_groups[n][pl['txt']] = @annot_obj_id
|
6053
6059
|
end
|
@@ -6105,7 +6111,7 @@ protected
|
|
6105
6111
|
else
|
6106
6112
|
val = pl['opt']['f'].to_i
|
6107
6113
|
end
|
6108
|
-
annots <<
|
6114
|
+
annots << " /F #{val}"
|
6109
6115
|
end
|
6110
6116
|
# annots << ' /AP '
|
6111
6117
|
# annots << ' /AS '
|
@@ -6114,24 +6120,23 @@ protected
|
|
6114
6120
|
end
|
6115
6121
|
if pl['opt']['ap']
|
6116
6122
|
# appearance stream
|
6117
|
-
annots << ' /AP << ' + pl['opt']['ap'] + ' >>'
|
6118
6123
|
annots << ' /AP <<'
|
6119
6124
|
if pl['opt']['ap'].is_a?(Hash)
|
6120
6125
|
pl['opt']['ap'].each {|apmode, apdef|
|
6121
6126
|
# apmode can be: n = normal; r = rollover; d = down
|
6122
6127
|
annots << ' /' + apmode.upcase
|
6123
|
-
if apdef.is_a?(
|
6128
|
+
if apdef.is_a?(Hash)
|
6124
6129
|
annots << ' <<'
|
6125
6130
|
apdef.each {|apstate, stream|
|
6126
6131
|
# reference to XObject that define the appearance for this mode-state
|
6127
6132
|
apsobjid = putAPXObject(c, d, stream)
|
6128
|
-
annots <<
|
6133
|
+
annots << " /#{apstate} #{apsobjid} 0 R"
|
6129
6134
|
}
|
6130
6135
|
annots << ' >>'
|
6131
6136
|
else
|
6132
6137
|
# reference to XObject that define the appearance for this mode
|
6133
6138
|
apsobjid = putAPXObject(c, d, apdef)
|
6134
|
-
annots <<
|
6139
|
+
annots << " #{apsobjid} 0 R"
|
6135
6140
|
end
|
6136
6141
|
}
|
6137
6142
|
else
|
@@ -6143,7 +6148,7 @@ protected
|
|
6143
6148
|
annots << ' /BS <<'
|
6144
6149
|
annots << ' /Type /Border'
|
6145
6150
|
if !pl['opt']['bs']['w'].nil?
|
6146
|
-
annots <<
|
6151
|
+
annots << " /W #{pl['opt']['bs']['w']}"
|
6147
6152
|
end
|
6148
6153
|
bstyles = ['S', 'D', 'B', 'I', 'U']
|
6149
6154
|
if !pl['opt']['bs']['s'].nil? and bstyles.include?(pl['opt']['bs']['s'])
|
@@ -6205,7 +6210,7 @@ protected
|
|
6205
6210
|
if !pl['opt']['t'].nil? and pl['opt']['t'].is_a?(String)
|
6206
6211
|
annots << ' /T ' + textannobjstring(pl['opt']['t'])
|
6207
6212
|
end
|
6208
|
-
# annots
|
6213
|
+
# annots << ' /Popup '
|
6209
6214
|
if !pl['opt']['ca'].nil?
|
6210
6215
|
annots << ' /CA ' + sprintf("%.4f", pl['opt']['ca'].to_f)
|
6211
6216
|
end
|
@@ -6420,9 +6425,9 @@ protected
|
|
6420
6425
|
end # end MK
|
6421
6426
|
|
6422
6427
|
# --- Entries for field dictionaries ---
|
6423
|
-
if @radiobutton_groups[n][pl['txt']]
|
6428
|
+
if @radiobutton_groups[n] and @radiobutton_groups[n][pl['txt']]
|
6424
6429
|
# set parent
|
6425
|
-
annots <<
|
6430
|
+
annots << " /Parent #{@radiobutton_groups[n][pl['txt']]} 0 R"
|
6426
6431
|
end
|
6427
6432
|
if pl['opt']['t'] and pl['opt']['t'].is_a?(String)
|
6428
6433
|
annots << ' /T ' + dataannobjstring(pl['opt']['t'])
|
@@ -6443,7 +6448,7 @@ protected
|
|
6443
6448
|
else
|
6444
6449
|
flag = pl['opt']['ff'].to_i
|
6445
6450
|
end
|
6446
|
-
annots <<
|
6451
|
+
annots << " /Ff #{flag}"
|
6447
6452
|
end
|
6448
6453
|
if pl['opt']['maxlen']
|
6449
6454
|
annots << ' /MaxLen ' + pl['opt']['maxlen'].to_i.to_s
|
@@ -6529,9 +6534,9 @@ protected
|
|
6529
6534
|
@offsets[@annot_obj_id] = @bufferlen
|
6530
6535
|
out(@annot_obj_id.to_s + ' 0 obj ' + annots + ' endobj')
|
6531
6536
|
|
6532
|
-
if formfield and ! @radiobutton_groups[n][pl['txt']]
|
6537
|
+
if formfield and !(@radiobutton_groups[n] and @radiobutton_groups[n][pl['txt']])
|
6533
6538
|
# store reference of form object
|
6534
|
-
@form_obj_id
|
6539
|
+
@form_obj_id << @annot_obj_id
|
6535
6540
|
end
|
6536
6541
|
}
|
6537
6542
|
end # end for each page
|
@@ -6563,7 +6568,7 @@ protected
|
|
6563
6568
|
rect = sprintf('%.2f %.2f', w, h)
|
6564
6569
|
out << ' /BBox [0 0 ' + rect + ']'
|
6565
6570
|
out << ' /Matrix [1 0 0 1 0 0]'
|
6566
|
-
out << ' /Resources
|
6571
|
+
out << ' /Resources 2 0 R'
|
6567
6572
|
out << ' /Length ' + stream.length.to_s
|
6568
6573
|
out << ' >>'
|
6569
6574
|
out << ' ' + getstream(stream)
|
@@ -7163,7 +7168,7 @@ protected
|
|
7163
7168
|
out(out)
|
7164
7169
|
end
|
7165
7170
|
end
|
7166
|
-
@fontkeys.
|
7171
|
+
@fontkeys.each_with_index do |k, i|
|
7167
7172
|
#Font objects
|
7168
7173
|
setFontSubBuffer(k, 'n', @n + 1)
|
7169
7174
|
font = getFontBuffer(k)
|
@@ -7181,7 +7186,7 @@ protected
|
|
7181
7186
|
end
|
7182
7187
|
if name.downcase == 'helvetica'
|
7183
7188
|
# add default font for annotations
|
7184
|
-
@annotation_fonts['helvetica'] =
|
7189
|
+
@annotation_fonts['helvetica'] = i
|
7185
7190
|
end
|
7186
7191
|
out << ' >> endobj'
|
7187
7192
|
out(out)
|
@@ -7232,9 +7237,9 @@ protected
|
|
7232
7237
|
Error('Unsupported font type: ' + type)
|
7233
7238
|
end
|
7234
7239
|
obj_id = self.send(mtd,font)
|
7235
|
-
# store object ID for current font
|
7236
|
-
@font_obj_ids[k] = obj_id
|
7237
7240
|
end
|
7241
|
+
# store object ID for current font
|
7242
|
+
@font_obj_ids[k] = obj_id
|
7238
7243
|
end
|
7239
7244
|
end
|
7240
7245
|
|
@@ -7595,6 +7600,7 @@ protected
|
|
7595
7600
|
putbookmarks()
|
7596
7601
|
putEmbeddedFiles()
|
7597
7602
|
putannotsobjs()
|
7603
|
+
putjavascript()
|
7598
7604
|
# encryption
|
7599
7605
|
|
7600
7606
|
### T.B.D ### TCPDF 5.0.000 ###
|
@@ -7653,11 +7659,11 @@ protected
|
|
7653
7659
|
newobj()
|
7654
7660
|
out = '<< /Type /Catalog'
|
7655
7661
|
out << ' /Pages 1 0 R'
|
7656
|
-
if
|
7662
|
+
if @zoom_mode == 'fullpage'
|
7657
7663
|
out << ' /OpenAction [3 0 R /Fit]'
|
7658
|
-
elsif
|
7664
|
+
elsif @zoom_mode == 'fullwidth'
|
7659
7665
|
out << ' /OpenAction [3 0 R /FitH null]'
|
7660
|
-
elsif
|
7666
|
+
elsif @zoom_mode == 'real'
|
7661
7667
|
out << ' /OpenAction [3 0 R /XYZ null null 1]'
|
7662
7668
|
elsif @zoom_mode.is_a?(Numeric)
|
7663
7669
|
out << ' /OpenAction [3 0 R /XYZ null null ' + (@zoom_mode/100.0).to_s + ']'
|
@@ -7674,7 +7680,7 @@ protected
|
|
7674
7680
|
end
|
7675
7681
|
out << ' /Names <<'
|
7676
7682
|
if !@javascript.empty? or !@js_objects.empty?
|
7677
|
-
out <<
|
7683
|
+
out << " /JavaScript #{@n_js} 0 R"
|
7678
7684
|
end
|
7679
7685
|
out << ' >>'
|
7680
7686
|
|
@@ -7687,9 +7693,43 @@ protected
|
|
7687
7693
|
v = @n_ocg_view.to_s + ' 0 R'
|
7688
7694
|
as = '<</Event /Print /OCGs [' + p + ' ' + v + '] /Category [/Print]>> <</Event /View /OCGs [' + p + ' ' + v + '] /Category [/View]>>'
|
7689
7695
|
out << ' /OCProperties <</OCGs [' + p + ' ' + v + '] /D <</ON [' + p + '] /OFF [' + v + '] /AS [' + as + ']>>>>'
|
7696
|
+
# AcroForm
|
7697
|
+
if !@form_obj_id.empty? || (@sign && @signature_data['cert_type'])
|
7698
|
+
out << ' /AcroForm<<'
|
7699
|
+
objrefs = ''
|
7700
|
+
if @sign && @signature_data['cert_type']
|
7701
|
+
objrefs << "#{@sig_obj_id} 0 R"
|
7702
|
+
end
|
7703
|
+
@form_obj_id.each{|objid|
|
7704
|
+
objrefs << " #{objid} 0 R"
|
7705
|
+
}
|
7706
|
+
out << " /Fields [#{objrefs}]"
|
7707
|
+
if @sign && @signature_data['cert_type']
|
7708
|
+
out << ' /SigFlags 3'
|
7709
|
+
end
|
7690
7710
|
|
7691
|
-
|
7692
|
-
|
7711
|
+
#out << ' /CO '
|
7712
|
+
unless @annotation_fonts.empty?
|
7713
|
+
out << ' /DR <<'
|
7714
|
+
out << ' /Font <<'
|
7715
|
+
@annotation_fonts.each {|font, fontkey|
|
7716
|
+
out << " /F#{fontkey + 1} #{@font_obj_ids[font]} 0 R"
|
7717
|
+
}
|
7718
|
+
out << ' >> >>'
|
7719
|
+
end
|
7720
|
+
out << " /DA (/F#{@fontkeys.index('helvetica') + 1} 0 Tf 0 g)"
|
7721
|
+
out << ' /Q ' + (@rtl ? '2' : '0')
|
7722
|
+
#out << ' /XFA '
|
7723
|
+
out << ' >>'
|
7724
|
+
# signatures
|
7725
|
+
if @sign && @signature_data['cert_type']
|
7726
|
+
if @signature_data['cert_type'] > 0
|
7727
|
+
out << " /Perms<</DocMDP #{@sig_obj_id + 1} 0 R>>"
|
7728
|
+
else
|
7729
|
+
out << " /Perms<</UR3 #{@sig_obj_id + 1} 0 R>>"
|
7730
|
+
end
|
7731
|
+
end
|
7732
|
+
end
|
7693
7733
|
out << ' >> endobj'
|
7694
7734
|
out(out)
|
7695
7735
|
end
|
@@ -7833,6 +7873,20 @@ protected
|
|
7833
7873
|
out(sprintf('%010d 00000 n ', @offsets[i]))
|
7834
7874
|
end
|
7835
7875
|
end
|
7876
|
+
# Javascript Objects
|
7877
|
+
if @js_obj_id > @js_start_obj_id
|
7878
|
+
out((@js_start_obj_id + 1).to_s + ' ' + (@js_obj_id - @js_start_obj_id).to_s)
|
7879
|
+
(@js_start_obj_id + 1).upto(@js_obj_id) do |i|
|
7880
|
+
out(sprintf('%010d 00000 n ', @offsets[i]))
|
7881
|
+
end
|
7882
|
+
end
|
7883
|
+
# Appearance streams XObjects
|
7884
|
+
if @apxo_obj_id > @apxo_start_obj_id
|
7885
|
+
out((@apxo_start_obj_id + 1).to_s + ' ' + (@apxo_obj_id - @apxo_start_obj_id).to_s)
|
7886
|
+
(@apxo_start_obj_id + 1).upto(@apxo_obj_id) do |i|
|
7887
|
+
out(sprintf('%010d 00000 n ', @offsets[i]))
|
7888
|
+
end
|
7889
|
+
end
|
7836
7890
|
#Trailer
|
7837
7891
|
puttrailer();
|
7838
7892
|
out('startxref');
|
@@ -8108,9 +8162,9 @@ protected
|
|
8108
8162
|
|
8109
8163
|
#
|
8110
8164
|
# get raw output stream.
|
8111
|
-
# @param string :s string to output.
|
8112
|
-
# @param int :n object reference for encryption mode
|
8113
|
-
# @access protected
|
8165
|
+
# [@param string :s] string to output.
|
8166
|
+
# [@param int :n] object reference for encryption mode
|
8167
|
+
# [@access protected]
|
8114
8168
|
#
|
8115
8169
|
def getrawstream(s, n=0)
|
8116
8170
|
if n <= 0
|
@@ -8122,9 +8176,9 @@ protected
|
|
8122
8176
|
|
8123
8177
|
#
|
8124
8178
|
# Format output stream
|
8125
|
-
# @param string :s string to output.
|
8126
|
-
# @param int :n object reference for encryption mode
|
8127
|
-
# @access protected
|
8179
|
+
# [@param string :s] string to output.
|
8180
|
+
# [@param int :n] object reference for encryption mode
|
8181
|
+
# [@access protected]
|
8128
8182
|
#
|
8129
8183
|
def getstream(s, n=0)
|
8130
8184
|
"stream\n" + getrawstream(s, n=0) + "\nendstream"
|
@@ -8147,7 +8201,10 @@ protected
|
|
8147
8201
|
#
|
8148
8202
|
def out(s)
|
8149
8203
|
s.force_encoding('ASCII-8BIT') if s.respond_to?(:force_encoding)
|
8150
|
-
|
8204
|
+
|
8205
|
+
if @tmp_buffer
|
8206
|
+
@tmp_buffer << "#{s}\n"
|
8207
|
+
elsif (@state==2)
|
8151
8208
|
if !@in_footer and !@footerlen[@page].nil? and (@footerlen[@page] > 0)
|
8152
8209
|
# puts data before page footer
|
8153
8210
|
pagebuff = getPageBuffer(@page)
|
@@ -10317,7 +10374,7 @@ public
|
|
10317
10374
|
return
|
10318
10375
|
end
|
10319
10376
|
# sort outlines by page and original position
|
10320
|
-
@outlines = @outlines.sort_by {|x| x[:p]}
|
10377
|
+
@outlines = @outlines.sort_by {|x| [x[:p], x[:y]] }
|
10321
10378
|
lru = []
|
10322
10379
|
level = 0
|
10323
10380
|
@outlines.each_with_index do |o, i|
|
@@ -10370,7 +10427,924 @@ public
|
|
10370
10427
|
protected :putbookmarks
|
10371
10428
|
|
10372
10429
|
# --- JAVASCRIPT ------------------------------------------------------
|
10430
|
+
#
|
10431
|
+
# Adds a javascript
|
10432
|
+
# [@param string :script] Javascript code
|
10433
|
+
# [@access public]
|
10434
|
+
# [@author Johannes G�ntert, Nicola Asuni]
|
10435
|
+
# [@since 2.1.002 (2008-02-12)]
|
10436
|
+
#
|
10437
|
+
def IncludeJS(script)
|
10438
|
+
@javascript << script
|
10439
|
+
end
|
10440
|
+
|
10441
|
+
#
|
10442
|
+
# Adds a javascript object and return object ID
|
10443
|
+
# [@param string :script] Javascript code
|
10444
|
+
# [@param boolean :onload] if true executes this object when opening the document
|
10445
|
+
# [@return int] internal object ID
|
10446
|
+
# [@access public]
|
10447
|
+
# [@author Nicola Asuni]
|
10448
|
+
# [@since 4.8.000 (2009-09-07)]
|
10449
|
+
#
|
10450
|
+
def addJavascriptObject(script, onload = false)
|
10451
|
+
@js_obj_id += 1
|
10452
|
+
@js_objects[@js_obj_id] = {'js' => script, 'onload' => onload}
|
10453
|
+
@js_obj_id
|
10454
|
+
end
|
10455
|
+
|
10456
|
+
#
|
10457
|
+
# Create a javascript PDF string.
|
10458
|
+
# [@access protected]
|
10459
|
+
# [@author Johannes G�ntert, Nicola Asuni]
|
10460
|
+
# [@since 2.1.002 (2008-02-12)]
|
10461
|
+
#
|
10462
|
+
def putjavascript()
|
10463
|
+
return if @javascript.empty? && @js_objects.empty?
|
10464
|
+
|
10465
|
+
if @javascript.index 'this.addField'
|
10466
|
+
# @setUserRights() unless @ur
|
10467
|
+
|
10468
|
+
# the following two lines are used to avoid form fields duplication after saving
|
10469
|
+
# The addField method only works on Acrobat Writer, unless the document is signed with Adobe private key (UR3)
|
10470
|
+
jsa = sprintf("ftcpdfdocsaved=this.addField('%s','%s',%d,[%.2f,%.2f,%.2f,%.2f]);", 'tcpdfdocsaved', 'text', 0, 0, 1, 0, 1)
|
10471
|
+
jsb = "getField('tcpdfdocsaved').value='saved';"
|
10472
|
+
@javascript = "#{jsa}\n#{@javascript}\n#{jsb}"
|
10473
|
+
end
|
10474
|
+
@n_js = newobj()
|
10475
|
+
out = ' << /Names ['
|
10476
|
+
unless @javascript.empty?
|
10477
|
+
out << " (EmbeddedJS) #{@n + 1} 0 R"
|
10478
|
+
end
|
10479
|
+
unless @js_objects.empty?
|
10480
|
+
@js_objects.each{|key, val|
|
10481
|
+
out << " (JS#{key}) #{key} 0 R" if val['onload']
|
10482
|
+
}
|
10483
|
+
end
|
10484
|
+
out << ' ] >> endobj'
|
10485
|
+
out(out)
|
10486
|
+
# default Javascript object
|
10487
|
+
unless @javascript.empty?
|
10488
|
+
newobj()
|
10489
|
+
out = '<< /S /JavaScript'
|
10490
|
+
out << " /JS #{textstring(@javascript)}"
|
10491
|
+
out << ' >> endobj'
|
10492
|
+
out(out)
|
10493
|
+
end
|
10494
|
+
# additional Javascript objects
|
10495
|
+
unless @js_objects.empty?
|
10496
|
+
@js_objects.each {|key, val|
|
10497
|
+
@offsets[key] = @bufferlen
|
10498
|
+
out = "#{key} 0 obj\n << /S /JavaScript /JS #{textstring(val['js'])} >> endobj"
|
10499
|
+
out(out)
|
10500
|
+
}
|
10501
|
+
end
|
10502
|
+
end
|
10503
|
+
|
10504
|
+
#
|
10505
|
+
# Convert color to javascript color.
|
10506
|
+
# [@param string :color] color name or #RRGGBB
|
10507
|
+
# [@access protected}
|
10508
|
+
# [@author Denis Van Nuffelen, Nicola Asuni]
|
10509
|
+
# [@since 2.1.002 (2008-02-12)]
|
10510
|
+
#
|
10511
|
+
def JScolor(color)
|
10512
|
+
aColors = ['transparent', 'black', 'white', 'red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'dkGray', 'gray', 'ltGray']
|
10513
|
+
if color[0] == '#'
|
10514
|
+
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)
|
10515
|
+
end
|
10516
|
+
|
10517
|
+
unless aColors.include? color
|
10518
|
+
Error('Invalid color: ' + color)
|
10519
|
+
end
|
10520
|
+
'color.' + color
|
10521
|
+
end
|
10522
|
+
protected :JScolor
|
10523
|
+
|
10524
|
+
#
|
10525
|
+
# Adds a javascript form field.
|
10526
|
+
# [@param string :type] field type
|
10527
|
+
# [@param string :name] field name
|
10528
|
+
# [@param int :x] horizontal position
|
10529
|
+
# [@param int :y] vertical position
|
10530
|
+
# [@param int :w] width
|
10531
|
+
# [@param int :h] height
|
10532
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10533
|
+
# [@access protected]
|
10534
|
+
# [@author Denis Van Nuffelen, Nicola Asuni]
|
10535
|
+
# [@since 2.1.002 (2008-02-12)]
|
10536
|
+
#
|
10537
|
+
def addfield(type, name, x, y, w, h, prop)
|
10538
|
+
x = x - w if @rtl
|
10539
|
+
|
10540
|
+
# the followind avoid fields duplication after saving the document
|
10541
|
+
@javascript << "if(getField('tcpdfdocsaved').value != 'saved') {"
|
10542
|
+
k = @k
|
10543
|
+
@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"
|
10544
|
+
@javascript << "f#{name}.textSize=#{@font_size_pt};\n"
|
10545
|
+
prop.each {|k, v|
|
10546
|
+
val = k[-5..-1] == 'Color' ? JScolor(v) : "'#{v}'"
|
10547
|
+
@javascript << "f#{name}.#{k}=#{val};\n"
|
10548
|
+
}
|
10549
|
+
if @rtl
|
10550
|
+
@x -= w
|
10551
|
+
else
|
10552
|
+
@x += w
|
10553
|
+
end
|
10554
|
+
@javascript << '}'
|
10555
|
+
end
|
10556
|
+
protected :addfield
|
10557
|
+
|
10373
10558
|
# --- FORM FIELDS -----------------------------------------------------
|
10559
|
+
|
10560
|
+
#
|
10561
|
+
# Convert JavaScript form fields properties array to Annotation Properties array.
|
10562
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10563
|
+
# [@return array of annotation properties]
|
10564
|
+
# [@access protected]
|
10565
|
+
# [@author Nicola Asuni]
|
10566
|
+
# [@since 4.8.000 (2009-09-06)]
|
10567
|
+
#
|
10568
|
+
def getAnnotOptFromJSProp(prop)
|
10569
|
+
# the annotation options area already defined
|
10570
|
+
return prop['aopt'] if prop['aopt'].is_a?(Array)
|
10571
|
+
|
10572
|
+
opt = {} # value to be returned
|
10573
|
+
# alignment: Controls how the text is laid out within the text field.
|
10574
|
+
if prop['alignment']
|
10575
|
+
opt['q'] = case prop['alignment']
|
10576
|
+
when 'left'; 0
|
10577
|
+
when 'center'; 1
|
10578
|
+
when 'right'; 2
|
10579
|
+
else @rtl ? 2 : 0
|
10580
|
+
end
|
10581
|
+
end
|
10582
|
+
# lineWidth: Specifies the thickness of the border when stroking the perimeter of a field's rectangle.
|
10583
|
+
if prop['lineWidth']
|
10584
|
+
linewidth = prop['lineWidth'].to_i
|
10585
|
+
else
|
10586
|
+
linewidth = 1
|
10587
|
+
end
|
10588
|
+
# borderStyle: The border style for a field.
|
10589
|
+
case prop['borderStyle']
|
10590
|
+
when 'border.d', 'dashed'
|
10591
|
+
opt['border'] = [0, 0, linewidth, [3, 2]]
|
10592
|
+
opt['bs'] = {'w'=>linewidth, 's'=>'D', 'd'=>[3, 2]}
|
10593
|
+
when 'border.b', 'beveled'
|
10594
|
+
opt['border'] = [0, 0, linewidth]
|
10595
|
+
opt['bs'] = {'w'=>linewidth, 's'=>'B'}
|
10596
|
+
when 'border.i', 'inset'
|
10597
|
+
opt['border'] = [0, 0, linewidth]
|
10598
|
+
opt['bs'] = {'w'=>linewidth, 's'=>'I'}
|
10599
|
+
when 'border.u', 'underline'
|
10600
|
+
opt['border'] = [0, 0, linewidth]
|
10601
|
+
opt['bs'] = {'w'=>linewidth, 's'=>'U'}
|
10602
|
+
else # 'border.s', 'solid'
|
10603
|
+
opt['border'] = [0, 0, linewidth]
|
10604
|
+
opt['bs'] = {'w'=>linewidth, 's'=>'S'}
|
10605
|
+
end
|
10606
|
+
|
10607
|
+
opt['border'] = prop['border'] if prop['border'].is_a?(Array)
|
10608
|
+
opt['mk'] ||= {}
|
10609
|
+
opt['mk']['if'] ||= {}
|
10610
|
+
opt['mk']['if']['a'] = [0.5, 0.5]
|
10611
|
+
# buttonAlignX: Controls how space is distributed from the left of the button face with respect to the icon.
|
10612
|
+
opt['mk']['if']['a'][0] = prop['buttonAlignX'] if prop['buttonAlignX']
|
10613
|
+
# buttonAlignY: Controls how unused space is distributed from the bottom of the button face with respect to the icon.
|
10614
|
+
opt['mk']['if']['a'][1] = prop['buttonAlignY'] if prop['buttonAlignY']
|
10615
|
+
# buttonFitBounds: If true, the extent to which the icon may be scaled is set to the bounds of the button field.
|
10616
|
+
opt['mk']['if']['fb'] = true if prop['buttonFitBounds'] && (prop['buttonFitBounds'] == 'true')
|
10617
|
+
# buttonScaleHow: Controls how the icon is scaled (if necessary) to fit inside the button face.
|
10618
|
+
case prop['buttonScaleHow']
|
10619
|
+
when 'scaleHow.proportional'; opt['mk']['if']['s'] = 'P'
|
10620
|
+
when 'scaleHow.anamorphic'; opt['mk']['if']['s'] = 'A'
|
10621
|
+
end
|
10622
|
+
# buttonScaleWhen: Controls when an icon is scaled to fit inside the button face.
|
10623
|
+
case prop['buttonScaleWhen']
|
10624
|
+
when 'scaleWhen.always'; opt['mk']['if']['sw'] = 'A'
|
10625
|
+
when 'scaleWhen.never'; opt['mk']['if']['sw'] = 'N'
|
10626
|
+
when 'scaleWhen.tooBig'; opt['mk']['if']['sw'] = 'B'
|
10627
|
+
when 'scaleWhen.tooSmall'; opt['mk']['if']['sw'] = 'S'
|
10628
|
+
end
|
10629
|
+
# buttonPosition: Controls how the text and the icon of the button are positioned with respect to each other within the button face.
|
10630
|
+
case prop['buttonPosition']
|
10631
|
+
when 0, 'position.textOnly'; opt['mk']['tp'] = 0
|
10632
|
+
when 1, 'position.iconOnly'; opt['mk']['tp'] = 1
|
10633
|
+
when 2, 'position.iconTextV'; opt['mk']['tp'] = 2
|
10634
|
+
when 3, 'position.textIconV'; opt['mk']['tp'] = 3
|
10635
|
+
when 4, 'position.iconTextH'; opt['mk']['tp'] = 4
|
10636
|
+
when 5, 'position.textIconH'; opt['mk']['tp'] = 5
|
10637
|
+
when 6, 'position.overlay'; opt['mk']['tp'] = 6
|
10638
|
+
end
|
10639
|
+
# fillColor: Specifies the background color for a field.
|
10640
|
+
if prop['fillColor']
|
10641
|
+
if prop['fillColor'].is_a? Array
|
10642
|
+
opt['mk']['bg'] = prop['fillColor']
|
10643
|
+
else
|
10644
|
+
opt['mk']['bg'] = convertHTMLColorToDec(prop['fillColor'])
|
10645
|
+
end
|
10646
|
+
end
|
10647
|
+
# 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.
|
10648
|
+
if prop['strokeColor']
|
10649
|
+
if prop['strokeColor'].is_a? Array
|
10650
|
+
opt['mk']['bc'] = prop['strokeColor']
|
10651
|
+
else
|
10652
|
+
opt['mk']['bc'] = convertHTMLColorToDec(prop['strokeColor'])
|
10653
|
+
end
|
10654
|
+
end
|
10655
|
+
# rotation: The rotation of a widget in counterclockwise increments.
|
10656
|
+
opt['mk']['r'] = prop['rotation'] if prop['rotation']
|
10657
|
+
# charLimit: Limits the number of characters that a user can type into a text field.
|
10658
|
+
opt['maxlen'] = prop['charLimit'].to_i if prop['charLimit']
|
10659
|
+
|
10660
|
+
ff ||= 0
|
10661
|
+
# readonly: The read-only characteristic of a field. If a field is read-only, the user can see the field but cannot change it.
|
10662
|
+
ff |= 1 << 0 if prop['readonly'] == 'true'
|
10663
|
+
# required: Specifies whether a field requires a value.
|
10664
|
+
ff |= 1 << 1 if prop['required'] == 'true'
|
10665
|
+
# multiline: Controls how text is wrapped within the field.
|
10666
|
+
ff |= 1 << 12 if prop['multiline'] == 'true'
|
10667
|
+
# password: Specifies whether the field should display asterisks when data is entered in the field.
|
10668
|
+
ff |= 1 << 13 if prop['password'] == 'true'
|
10669
|
+
# NoToggleToOff: If set, exactly one radio button shall be selected at all times; selecting the currently selected button has no effect.
|
10670
|
+
ff |= 1 << 14 if prop['NoToggleToOff'] == 'true'
|
10671
|
+
# Radio: If set, the field is a set of radio buttons.
|
10672
|
+
ff |= 1 << 15 if prop['Radio'] == 'true'
|
10673
|
+
# Pushbutton: If set, the field is a pushbutton that does not retain a permanent value.
|
10674
|
+
ff |= 1 << 16 if prop['Pushbutton'] == 'true'
|
10675
|
+
# Combo: If set, the field is a combo box; if clear, the field is a list box.
|
10676
|
+
ff |= 1 << 17 if prop['Combo'] == 'true'
|
10677
|
+
# editable: Controls whether a combo box is editable.
|
10678
|
+
ff |= 1 << 18 if prop['editable'] == 'true'
|
10679
|
+
# Sort: If set, the field's option items shall be sorted alphabetically.
|
10680
|
+
ff |= 1 << 19 if prop['Sort'] == 'true'
|
10681
|
+
# fileSelect: If true, sets the file-select flag in the Options tab of the text field (Field is Used for File Selection).
|
10682
|
+
ff |= 1 << 20 if prop['fileSelect'] == 'true'
|
10683
|
+
# multipleSelection: If true, indicates that a list box allows a multiple selection of items.
|
10684
|
+
ff |= 1 << 21 if prop['multipleSelection'] == 'true'
|
10685
|
+
# doNotSpellCheck: If true, spell checking is not performed on this editable text field.
|
10686
|
+
ff |= 1 << 22 if prop['doNotSpellCheck'] == 'true'
|
10687
|
+
# doNotScroll: If true, the text field does not scroll and the user, therefore, is limited by the rectangular region designed for the field.
|
10688
|
+
ff |= 1 << 23 if prop['doNotScroll'] == 'true'
|
10689
|
+
# 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.
|
10690
|
+
ff |= 1 << 24 if prop['comb'] == 'true'
|
10691
|
+
# 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.
|
10692
|
+
ff |= 1 << 25 if prop['radiosInUnison'] == 'true'
|
10693
|
+
# richText: If true, the field allows rich text formatting.
|
10694
|
+
ff |= 1 << 25 if prop['richText'] == 'true'
|
10695
|
+
# commitOnSelChange: Controls whether a field value is committed after a selection change.
|
10696
|
+
ff |= 1 << 26 if prop['commitOnSelChange'] == 'true'
|
10697
|
+
opt['ff'] = ff
|
10698
|
+
|
10699
|
+
# defaultValue: The default value of a field - that is, the value that the field is set to when the form is reset.
|
10700
|
+
opt['dv'] = prop['defaultValue'] if prop['defaultValue']
|
10701
|
+
f = 1 << 2 # default value for annotation flags
|
10702
|
+
# readonly: The read-only characteristic of a field. If a field is read-only, the user can see the field but cannot change it.
|
10703
|
+
if prop['readonly'] == 'true'
|
10704
|
+
f |= 1 << 6
|
10705
|
+
end
|
10706
|
+
# display: Controls whether the field is hidden or visible on screen and in print.
|
10707
|
+
case prop['display']
|
10708
|
+
when 'display.visible'
|
10709
|
+
#
|
10710
|
+
when 'display.hidden'
|
10711
|
+
f |= 1 << 1
|
10712
|
+
when 'display.noPrint'
|
10713
|
+
f &= ~(1 << 2)
|
10714
|
+
when 'display.noView'
|
10715
|
+
f |= 1 << 5
|
10716
|
+
end
|
10717
|
+
opt['f'] = f
|
10718
|
+
|
10719
|
+
# currentValueIndices: Reads and writes single or multiple values of a list box or combo box.
|
10720
|
+
opt['i'] = prop['currentValueIndices'] if prop['currentValueIndices'].is_a?(Array)
|
10721
|
+
# value: The value of the field data that the user has entered.
|
10722
|
+
if prop['value']
|
10723
|
+
if prop['value'].is_a?(Array)
|
10724
|
+
opt['opt'] = []
|
10725
|
+
prop['value'].each_with_index {|v, i|
|
10726
|
+
# exportValues: An array of strings representing the export values for the field.
|
10727
|
+
if prop['exportValues'] && prop['exportValues'][i]
|
10728
|
+
opt['opt'][i] = [prop['exportValues'][i], v]
|
10729
|
+
else
|
10730
|
+
opt['opt'][i] = v
|
10731
|
+
end
|
10732
|
+
}
|
10733
|
+
else
|
10734
|
+
opt['v'] = prop['value']
|
10735
|
+
end
|
10736
|
+
end
|
10737
|
+
# richValue: This property specifies the text contents and formatting of a rich text field.
|
10738
|
+
opt['rv'] = prop['richValue'] if prop['richValue']
|
10739
|
+
# submitName: If nonempty, used during form submission instead of name. Only applicable if submitting in HTML format (that is, URL-encoded).
|
10740
|
+
opt['tm'] = prop['submitName'] if prop['submitName']
|
10741
|
+
# name: Fully qualified field name.
|
10742
|
+
opt['t'] = prop['name'] if prop['name']
|
10743
|
+
# userName: The user name (short description string) of the field.
|
10744
|
+
opt['tu'] = prop['userName'] if prop['userName']
|
10745
|
+
# highlight: Defines how a button reacts when a user clicks it.
|
10746
|
+
case prop['highlight']
|
10747
|
+
when 'none', 'highlight.n'; opt['h'] = 'N'
|
10748
|
+
when 'invert', 'highlight.i'; opt['h'] = 'i'
|
10749
|
+
when 'push', 'highlight.p'; opt['h'] = 'P'
|
10750
|
+
when 'outline', 'highlight.o'; opt['h'] = 'O'
|
10751
|
+
end
|
10752
|
+
# Unsupported options:
|
10753
|
+
# - calcOrderIndex: Changes the calculation order of fields in the document.
|
10754
|
+
# - delay: Delays the redrawing of a field's appearance.
|
10755
|
+
# - defaultStyle: This property defines the default style attributes for the form field.
|
10756
|
+
# - style: Allows the user to set the glyph style of a check box or radio button.
|
10757
|
+
# - textColor, textFont, textSize
|
10758
|
+
opt
|
10759
|
+
end
|
10760
|
+
protected :getAnnotOptFromJSProp
|
10761
|
+
|
10762
|
+
#
|
10763
|
+
# Set default properties for form fields.
|
10764
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10765
|
+
# [@access public]
|
10766
|
+
# [@author Nicola Asuni]
|
10767
|
+
# [@since 4.8.000 (2009-09-06)]
|
10768
|
+
#
|
10769
|
+
def setFormDefaultProp(prop = [])
|
10770
|
+
@default_form_prop = prop
|
10771
|
+
end
|
10772
|
+
alias_method :set_form_default_prop, :setFormDefaultProp
|
10773
|
+
|
10774
|
+
#
|
10775
|
+
# Return the default properties for form fields.
|
10776
|
+
# [@return array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10777
|
+
# [@access public]
|
10778
|
+
# [@author Nicola Asuni]
|
10779
|
+
# [@since 4.8.000 (2009-09-06)]
|
10780
|
+
#
|
10781
|
+
def getFormDefaultProp()
|
10782
|
+
@default_form_prop
|
10783
|
+
end
|
10784
|
+
alias_method :get_form_default_prop, :getFormDefaultProp
|
10785
|
+
|
10786
|
+
#
|
10787
|
+
# Creates a text field
|
10788
|
+
# [@param string :name] field name
|
10789
|
+
# [@param float :w] Width of the rectangle
|
10790
|
+
# [@param float :h] Height of the rectangle
|
10791
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10792
|
+
# [@param array :opt] annotation parameters. Possible values are described on official PDF32000_2008 reference.
|
10793
|
+
# [@param float :x] Abscissa of the upper-left corner of the rectangle
|
10794
|
+
# [@param float :y] Ordinate of the upper-left corner of the rectangle
|
10795
|
+
# [@param boolean :js] if true put the field using JavaScript (requires Acrobat Writer to be rendered).
|
10796
|
+
# [@access public]
|
10797
|
+
# [@author Nicola Asuni]
|
10798
|
+
# [@since 4.8.000 (2009-09-07)]
|
10799
|
+
#
|
10800
|
+
def TextField(name, w, h, prop = {}, opt = {}, x = '', y = '', js = false)
|
10801
|
+
x = @x if x == ''
|
10802
|
+
y = @y if y == ''
|
10803
|
+
|
10804
|
+
if js
|
10805
|
+
addfield('text', name, x, y, w, h, prop)
|
10806
|
+
return
|
10807
|
+
end
|
10808
|
+
# get default style
|
10809
|
+
prop = getFormDefaultProp.merge prop
|
10810
|
+
# get annotation data
|
10811
|
+
popt = getAnnotOptFromJSProp(prop)
|
10812
|
+
# set default appearance stream
|
10813
|
+
font = @font_family
|
10814
|
+
fontkey = @fontkeys.index font
|
10815
|
+
unless @annotation_fonts.include? fontkey
|
10816
|
+
@annotation_fonts[font] = fontkey
|
10817
|
+
end
|
10818
|
+
fontstyle = sprintf("/F%d %.2f Tf %s", fontkey + 1, @font_size_pt, @text_color)
|
10819
|
+
popt['da'] = fontstyle
|
10820
|
+
popt['ap'] = {}
|
10821
|
+
|
10822
|
+
if opt['v'] && !empty_string(opt['v'])
|
10823
|
+
# set Appearances
|
10824
|
+
popt['ap']['n'] = "/Tx BMC q #{fontstyle} "
|
10825
|
+
gvars = getGraphicVars()
|
10826
|
+
@h = h
|
10827
|
+
@w = w
|
10828
|
+
@t_margin = 0
|
10829
|
+
@c_margin = 0.2
|
10830
|
+
|
10831
|
+
@tmp_buffer = ''
|
10832
|
+
multi_cell(w, h, opt['v'], 0, '', 0, 0, 0.2, 0, true, 0, false, true, 0)
|
10833
|
+
popt['ap']['n'] << @tmp_buffer
|
10834
|
+
@tmp_buffer = nil
|
10835
|
+
popt['ap']['n'] << 'Q EMC'
|
10836
|
+
|
10837
|
+
# restore previous values
|
10838
|
+
setGraphicVars(gvars, true)
|
10839
|
+
else
|
10840
|
+
popt['ap']['n'] = "q BT #{fontstyle} ET Q"
|
10841
|
+
end
|
10842
|
+
|
10843
|
+
# merge options
|
10844
|
+
opt = popt.merge opt
|
10845
|
+
# remove some conflicting options
|
10846
|
+
opt.delete :bs
|
10847
|
+
# set remaining annotation data
|
10848
|
+
opt['Subtype'] = 'Widget'
|
10849
|
+
opt['ft'] = 'Tx'
|
10850
|
+
opt['t'] = name
|
10851
|
+
#
|
10852
|
+
# Additional annotation's parameters (check _putannotsobj() method):
|
10853
|
+
# opt['f']
|
10854
|
+
# opt['ap']
|
10855
|
+
# opt['as']
|
10856
|
+
# opt['bs']
|
10857
|
+
# opt['be']
|
10858
|
+
# opt['c']
|
10859
|
+
# opt['border']
|
10860
|
+
# opt['h']
|
10861
|
+
# opt['mk']
|
10862
|
+
# opt['mk']['r']
|
10863
|
+
# opt['mk']['bc']
|
10864
|
+
# opt['mk']['bg']
|
10865
|
+
# opt['mk']['ca']
|
10866
|
+
# opt['mk']['rc']
|
10867
|
+
# opt['mk']['ac']
|
10868
|
+
# opt['mk']['i']
|
10869
|
+
# opt['mk']['ri']
|
10870
|
+
# opt['mk']['ix']
|
10871
|
+
# opt['mk']['if']
|
10872
|
+
# opt['mk']['if']['sw']
|
10873
|
+
# opt['mk']['if']['s']
|
10874
|
+
# opt['mk']['if']['a']
|
10875
|
+
# opt['mk']['if']['fb']
|
10876
|
+
# opt['mk']['tp']
|
10877
|
+
# opt['tu']
|
10878
|
+
# opt['tm']
|
10879
|
+
# opt['ff']
|
10880
|
+
# opt['v']
|
10881
|
+
# opt['dv']
|
10882
|
+
# opt['a']
|
10883
|
+
# opt['aa']
|
10884
|
+
# opt['q']
|
10885
|
+
Annotation(x, y, w, h, name, opt, 0)
|
10886
|
+
if @rtl
|
10887
|
+
@x -= w
|
10888
|
+
else
|
10889
|
+
@x += w
|
10890
|
+
end
|
10891
|
+
end
|
10892
|
+
alias_method :text_field, :TextField
|
10893
|
+
|
10894
|
+
#
|
10895
|
+
# Creates a RadioButton field
|
10896
|
+
# [@param string :name] field name
|
10897
|
+
# [@param int :w] width
|
10898
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10899
|
+
# [@param array :opt] annotation parameters. Possible values are described on official PDF32000_2008 reference.
|
10900
|
+
# [@param string :onvalue] value to be returned if selected.
|
10901
|
+
# [@param boolean :checked] define the initial state.
|
10902
|
+
# [@param float :x] Abscissa of the upper-left corner of the rectangle
|
10903
|
+
# [@param float :y] Ordinate of the upper-left corner of the rectangle
|
10904
|
+
# [@param boolean :js] if true put the field using JavaScript (requires Acrobat Writer to be rendered).
|
10905
|
+
# [@access public]
|
10906
|
+
# [@author Nicola Asuni]
|
10907
|
+
# [@since 4.8.000 (2009-09-07)]
|
10908
|
+
#
|
10909
|
+
def RadioButton(name, w, prop = {}, opt = {}, onvalue = 'On', checked = false, x = '', y = '', js = false)
|
10910
|
+
x = @x if x == ''
|
10911
|
+
y = @y if y == ''
|
10912
|
+
|
10913
|
+
if js
|
10914
|
+
addfield('radiobutton', name, x, y, w, w, prop)
|
10915
|
+
return
|
10916
|
+
end
|
10917
|
+
|
10918
|
+
onvalue = 'On' if empty_string(onvalue)
|
10919
|
+
defval = checked ? onvalue : 'Off'
|
10920
|
+
# set data for parent group
|
10921
|
+
@radiobutton_groups[@page] ||= {}
|
10922
|
+
unless @radiobutton_groups[@page][name]
|
10923
|
+
@radiobutton_groups[@page][name] = []
|
10924
|
+
@annot_obj_id += 1
|
10925
|
+
@radio_groups << @annot_obj_id
|
10926
|
+
end
|
10927
|
+
# save object ID to be added on Kids entry on parent object
|
10928
|
+
@radiobutton_groups[@page][name] << {'kid' => @annot_obj_id + 1, 'def' => defval}
|
10929
|
+
# get default style
|
10930
|
+
prop = getFormDefaultProp.merge prop
|
10931
|
+
prop['NoToggleToOff'] = 'true'
|
10932
|
+
prop['Radio'] = 'true'
|
10933
|
+
prop['borderStyle'] = 'inset'
|
10934
|
+
# get annotation data
|
10935
|
+
popt = getAnnotOptFromJSProp(prop)
|
10936
|
+
# set additional default values
|
10937
|
+
font = 'zapfdingbats'
|
10938
|
+
AddFont(font)
|
10939
|
+
fontkey = @fontkeys.index font
|
10940
|
+
unless @annotation_fonts.include? fontkey
|
10941
|
+
@annotation_fonts[font] = fontkey
|
10942
|
+
end
|
10943
|
+
fontstyle = sprintf('/F%d %.2f Tf', fontkey + 1, @font_size_pt)
|
10944
|
+
popt['da'] = "#{fontstyle} #{@text_color}"
|
10945
|
+
popt['ap'] = {}
|
10946
|
+
popt['ap']['n'] = {}
|
10947
|
+
popt['ap']['n'][onvalue] = "q #{@text_color} BT #{fontstyle} 0 0 Td (n) Tj ET Q"
|
10948
|
+
popt['ap']['n']['Off'] = "q #{@text_color} BT #{fontstyle} 0 0 Td (o) Tj ET Q"
|
10949
|
+
popt['mk'] ||= {}
|
10950
|
+
popt['mk']['ca'] = '(l)'
|
10951
|
+
# merge options
|
10952
|
+
opt = popt.merge opt
|
10953
|
+
# set remaining annotation data
|
10954
|
+
opt['Subtype'] = 'Widget'
|
10955
|
+
opt['ft'] = 'Btn'
|
10956
|
+
if checked
|
10957
|
+
opt['v'] = ["/#{onvalue}"]
|
10958
|
+
opt['as'] = onvalue
|
10959
|
+
else
|
10960
|
+
opt['as'] = 'Off'
|
10961
|
+
end
|
10962
|
+
Annotation(x, y, w, w, name, opt, 0)
|
10963
|
+
if @rtl
|
10964
|
+
@x -= w
|
10965
|
+
else
|
10966
|
+
@x += w
|
10967
|
+
end
|
10968
|
+
end
|
10969
|
+
alias_method :radio_button, :RadioButton
|
10970
|
+
|
10971
|
+
#
|
10972
|
+
# Creates a List-box field
|
10973
|
+
# [@param string :name] field name
|
10974
|
+
# [@param int :w] width
|
10975
|
+
# [@param int :h] height
|
10976
|
+
# [@param array :values] array containing the list of values.
|
10977
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
10978
|
+
# [@param array :opt] annotation parameters. Possible values are described on official PDF32000_2008 reference.
|
10979
|
+
# [@param float :x] Abscissa of the upper-left corner of the rectangle
|
10980
|
+
# [@param float :y] Ordinate of the upper-left corner of the rectangle
|
10981
|
+
# [@param boolean :js] if true put the field using JavaScript (requires Acrobat Writer to be rendered).
|
10982
|
+
# [@access public]
|
10983
|
+
# [@author Nicola Asuni]
|
10984
|
+
# [@since 4.8.000 (2009-09-07)]
|
10985
|
+
#
|
10986
|
+
def ListBox(name, w, h, values, prop = {}, opt = {}, x = '', y = '', js = false)
|
10987
|
+
x = @x if x == ''
|
10988
|
+
y = @y if y == ''
|
10989
|
+
|
10990
|
+
if js
|
10991
|
+
addfield('listbox', name, x, y, w, h, prop)
|
10992
|
+
s = ''
|
10993
|
+
values.each {|v|
|
10994
|
+
if v.is_a?(Array)
|
10995
|
+
s << "['#{v[0]}','#{v[1]}'],"
|
10996
|
+
else
|
10997
|
+
s << "'#{v}',"
|
10998
|
+
end
|
10999
|
+
}
|
11000
|
+
@javascript << "f#{name}.setItems([#{s[0...-1]}]);\n"
|
11001
|
+
return
|
11002
|
+
end
|
11003
|
+
# get default style
|
11004
|
+
prop = getFormDefaultProp.merge prop
|
11005
|
+
# get annotation data
|
11006
|
+
popt = getAnnotOptFromJSProp(prop)
|
11007
|
+
# set additional default values
|
11008
|
+
font = @font_family
|
11009
|
+
fontkey = @fontkeys.index font
|
11010
|
+
unless @annotation_fonts.include? fontkey
|
11011
|
+
@annotation_fonts[font] = fontkey
|
11012
|
+
end
|
11013
|
+
s = ''
|
11014
|
+
values.each {|v|
|
11015
|
+
if v.is_a?(Array)
|
11016
|
+
s << "#{v[1]}\n"
|
11017
|
+
else
|
11018
|
+
s << "#{v}\n"
|
11019
|
+
end
|
11020
|
+
}
|
11021
|
+
|
11022
|
+
fontstyle = sprintf('/F%d %.2f Tf %s', fontkey + 1, @font_size_pt, @text_color)
|
11023
|
+
popt['da'] = fontstyle
|
11024
|
+
popt['ap'] = {}
|
11025
|
+
# set Appearances
|
11026
|
+
popt['ap']['n'] = "/Tx BMC q #{fontstyle} "
|
11027
|
+
gvars = getGraphicVars()
|
11028
|
+
@h = h
|
11029
|
+
@w = w
|
11030
|
+
@t_margin = 0
|
11031
|
+
@c_margin = 0.2
|
11032
|
+
|
11033
|
+
@tmp_buffer = ''
|
11034
|
+
multi_cell(w, h, s, 0, '', 0, 0, 0.2, 0, true, 0, false, true, 0)
|
11035
|
+
popt['ap']['n'] << @tmp_buffer
|
11036
|
+
popt['ap']['n'] << 'Q EMC'
|
11037
|
+
@tmp_buffer = nil
|
11038
|
+
|
11039
|
+
# restore previous values
|
11040
|
+
setGraphicVars(gvars, true)
|
11041
|
+
|
11042
|
+
# merge options
|
11043
|
+
opt = popt.merge opt
|
11044
|
+
# set remaining annotation data
|
11045
|
+
opt['Subtype'] = 'Widget'
|
11046
|
+
opt['ft'] = 'Ch'
|
11047
|
+
opt['t'] = name
|
11048
|
+
opt['opt'] = values
|
11049
|
+
Annotation(x, y, w, h, name, opt, 0)
|
11050
|
+
if @rtl
|
11051
|
+
@x -= w
|
11052
|
+
else
|
11053
|
+
@x += w
|
11054
|
+
end
|
11055
|
+
end
|
11056
|
+
alias_method :list_box, :ListBox
|
11057
|
+
|
11058
|
+
#
|
11059
|
+
# Creates a Combo-box field
|
11060
|
+
# [@param string :name] field name
|
11061
|
+
# [@param int :w] width
|
11062
|
+
# [@param int :h] height
|
11063
|
+
# [@param array :values] array containing the list of values.
|
11064
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
11065
|
+
# [@param array :opt] annotation parameters. Possible values are described on official PDF32000_2008 reference.
|
11066
|
+
# [@param float :x] Abscissa of the upper-left corner of the rectangle
|
11067
|
+
# [@param float :y] Ordinate of the upper-left corner of the rectangle
|
11068
|
+
# [@param boolean :js] if true put the field using JavaScript (requires Acrobat Writer to be rendered).
|
11069
|
+
# [@access public]
|
11070
|
+
# [@author Nicola Asuni]
|
11071
|
+
# [@since 4.8.000 (2009-09-07)]
|
11072
|
+
#
|
11073
|
+
def ComboBox(name, w, h, values, prop = {}, opt = {}, x = '', y = '', js = false)
|
11074
|
+
x = @x if x == ''
|
11075
|
+
y = @y if y == ''
|
11076
|
+
|
11077
|
+
if js
|
11078
|
+
addfield('combobox', name, x, y, w, h, prop)
|
11079
|
+
s = ''
|
11080
|
+
values.each {|v|
|
11081
|
+
if v.is_a?(Array)
|
11082
|
+
s << "['#{v[0]}','#{v[1]}'],"
|
11083
|
+
else
|
11084
|
+
s << "'#{v}',"
|
11085
|
+
end
|
11086
|
+
}
|
11087
|
+
@javascript << "f#{name}.setItems([#{s[0...-1]}]);\n"
|
11088
|
+
return
|
11089
|
+
end
|
11090
|
+
# get default style
|
11091
|
+
prop = getFormDefaultProp.merge prop
|
11092
|
+
prop['Combo'] = 'true'
|
11093
|
+
# get annotation data
|
11094
|
+
popt = getAnnotOptFromJSProp(prop)
|
11095
|
+
# set additional default options
|
11096
|
+
font = @font_family
|
11097
|
+
fontkey = @fontkeys.index font
|
11098
|
+
unless @annotation_fonts.include? fontkey
|
11099
|
+
@annotation_fonts[font] = fontkey
|
11100
|
+
end
|
11101
|
+
|
11102
|
+
s = ''
|
11103
|
+
values.each {|v|
|
11104
|
+
if v.is_a?(Array)
|
11105
|
+
s << "#{v[1]}\n"
|
11106
|
+
else
|
11107
|
+
s << "#{v}\n"
|
11108
|
+
end
|
11109
|
+
}
|
11110
|
+
fontstyle = sprintf('/F%d %.2f Tf %s', fontkey + 1, @font_size_pt, @text_color)
|
11111
|
+
popt['da'] = fontstyle
|
11112
|
+
popt['ap'] = {}
|
11113
|
+
# set Appearances
|
11114
|
+
popt['ap']['n'] = "/Tx BMC q #{fontstyle} "
|
11115
|
+
gvars = getGraphicVars()
|
11116
|
+
@h = h
|
11117
|
+
@w = w
|
11118
|
+
@t_margin = 0
|
11119
|
+
@c_margin = 0.2
|
11120
|
+
|
11121
|
+
@tmp_buffer = ''
|
11122
|
+
multi_cell(w, h, s, 0, '', 0, 0, 0.2, 0, true, 0, false, true, 0)
|
11123
|
+
popt['ap']['n'] << @tmp_buffer
|
11124
|
+
popt['ap']['n'] << 'Q EMC'
|
11125
|
+
@tmp_buffer = nil
|
11126
|
+
|
11127
|
+
# restore previous values
|
11128
|
+
setGraphicVars(gvars, true)
|
11129
|
+
|
11130
|
+
# merge options
|
11131
|
+
opt = popt.merge opt
|
11132
|
+
# set remaining annotation data
|
11133
|
+
opt['Subtype'] = 'Widget'
|
11134
|
+
opt['ft'] = 'Ch'
|
11135
|
+
opt['t'] = name
|
11136
|
+
opt['opt'] = values
|
11137
|
+
Annotation(x, y, w, h, name, opt, 0)
|
11138
|
+
if @rtl
|
11139
|
+
@x -= w
|
11140
|
+
else
|
11141
|
+
@x += w
|
11142
|
+
end
|
11143
|
+
end
|
11144
|
+
alias_method :combo_box, :ComboBox
|
11145
|
+
|
11146
|
+
#
|
11147
|
+
# Creates a CheckBox field
|
11148
|
+
# [@param string :name] field name
|
11149
|
+
# [@param int :w] width
|
11150
|
+
# [@param boolean :checked] define the initial state.
|
11151
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
11152
|
+
# [@param array :opt] annotation parameters. Possible values are described on official PDF32000_2008 reference.
|
11153
|
+
# [@param string :onvalue] value to be returned if selected.
|
11154
|
+
# [@param float :x] Abscissa of the upper-left corner of the rectangle
|
11155
|
+
# [@param float :y] Ordinate of the upper-left corner of the rectangle
|
11156
|
+
# [@param boolean :js] if true put the field using JavaScript (requires Acrobat Writer to be rendered).
|
11157
|
+
# [@access public]
|
11158
|
+
# [@author Nicola Asuni]
|
11159
|
+
# [@since 4.8.000 (2009-09-07)]
|
11160
|
+
#
|
11161
|
+
def CheckBox(name, w, checked=false, prop = {}, opt = {}, onvalue = 'Yes', x = '', y = '', js = false)
|
11162
|
+
x = @x if x == ''
|
11163
|
+
y = @y if y == ''
|
11164
|
+
|
11165
|
+
if js
|
11166
|
+
addfield('checkbox', name, x, y, w, w, prop)
|
11167
|
+
return
|
11168
|
+
end
|
11169
|
+
|
11170
|
+
prop['value'] ||= ['Yes']
|
11171
|
+
# get default style
|
11172
|
+
prop = getFormDefaultProp.merge prop
|
11173
|
+
prop['borderStyle'] = 'inset'
|
11174
|
+
# get annotation data
|
11175
|
+
popt = getAnnotOptFromJSProp(prop)
|
11176
|
+
# set additional default options
|
11177
|
+
font = 'zapfdingbats'
|
11178
|
+
AddFont(font)
|
11179
|
+
fontkey = @fontkeys.index font
|
11180
|
+
unless @annotation_fonts.include? fontkey
|
11181
|
+
@annotation_fonts[font] = fontkey
|
11182
|
+
end
|
11183
|
+
fontstyle = sprintf('/F%d %.2f Tf', fontkey + 1, @font_size_pt)
|
11184
|
+
popt['da'] = "#{fontstyle} #{@text_color}"
|
11185
|
+
popt['ap'] = {}
|
11186
|
+
popt['ap']['n'] = {}
|
11187
|
+
popt['ap']['n']['Yes'] = "q #{@text_color} BT #{fontstyle} 0 0 Td (n) Tj ET Q"
|
11188
|
+
popt['ap']['n']['Off'] = "q #{@text_color} BT #{fontstyle} 0 0 Td (o) Tj ET Q"
|
11189
|
+
|
11190
|
+
# merge options
|
11191
|
+
opt = popt.merge opt
|
11192
|
+
# set remaining annotation data
|
11193
|
+
opt['Subtype'] = 'Widget'
|
11194
|
+
opt['ft'] = 'Btn'
|
11195
|
+
opt['t'] = name
|
11196
|
+
if empty_string(onvalue)
|
11197
|
+
onvalue = 'Yes'
|
11198
|
+
end
|
11199
|
+
opt['opt'] = [onvalue]
|
11200
|
+
if checked
|
11201
|
+
opt['v'] = ['/Yes']
|
11202
|
+
opt['as'] = 'Yes'
|
11203
|
+
else
|
11204
|
+
opt['v'] = ['/Off']
|
11205
|
+
opt['as'] = 'Off'
|
11206
|
+
end
|
11207
|
+
Annotation(x, y, w, w, name, opt, 0)
|
11208
|
+
if @rtl
|
11209
|
+
@x -= w
|
11210
|
+
else
|
11211
|
+
@x += w
|
11212
|
+
end
|
11213
|
+
end
|
11214
|
+
alias_method :check_box, :CheckBox
|
11215
|
+
|
11216
|
+
#
|
11217
|
+
# Creates a button field
|
11218
|
+
# [@param string :name] field name
|
11219
|
+
# [@param int :w] width
|
11220
|
+
# [@param int :h] height
|
11221
|
+
# [@param string :caption] caption.
|
11222
|
+
# [@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.
|
11223
|
+
# [@param array :prop] javascript field properties. Possible values are described on official Javascript for Acrobat API reference.
|
11224
|
+
# [@param array :opt] annotation parameters. Possible values are described on official PDF32000_2008 reference.
|
11225
|
+
# [@param float :x] Abscissa of the upper-left corner of the rectangle
|
11226
|
+
# [@param float :y] Ordinate of the upper-left corner of the rectangle
|
11227
|
+
# [@param boolean :js] if true put the field using JavaScript (requires Acrobat Writer to be rendered).
|
11228
|
+
# [@access public]
|
11229
|
+
# [@author Nicola Asuni]
|
11230
|
+
# [@since 4.8.000 (2009-09-07)]
|
11231
|
+
#
|
11232
|
+
def Button(name, w, h, caption, action, prop = {}, opt = {}, x = '', y = '', js = false)
|
11233
|
+
x = @x if x == ''
|
11234
|
+
y = @y if y == ''
|
11235
|
+
|
11236
|
+
if js
|
11237
|
+
addfield('button', name, x, y, w, h, prop)
|
11238
|
+
@javascript << "f#{name}.buttonSetCaption('#{caption}');\n"
|
11239
|
+
@javascript << "f#{name}.setAction('MouseUp','#{action}');\n"
|
11240
|
+
@javascript << "f#{name}.highlight='push';\n"
|
11241
|
+
@javascript << "f#{name}.print=false;\n"
|
11242
|
+
return
|
11243
|
+
end
|
11244
|
+
# get default style
|
11245
|
+
prop = getFormDefaultProp.merge prop
|
11246
|
+
prop['Pushbutton'] = 'true'
|
11247
|
+
prop['highlight'] = 'push'
|
11248
|
+
prop['display'] = 'display.noPrint'
|
11249
|
+
# get annotation data
|
11250
|
+
popt = getAnnotOptFromJSProp(prop)
|
11251
|
+
# set additional default options
|
11252
|
+
popt['mk'] ||= {}
|
11253
|
+
popt['mk']['ca'] = textstring(caption)
|
11254
|
+
popt['mk']['rc'] = textstring(caption)
|
11255
|
+
popt['mk']['ac'] = textstring(caption)
|
11256
|
+
font = @font_family
|
11257
|
+
fontkey = @fontkeys.index font
|
11258
|
+
unless @annotation_fonts.include? fontkey
|
11259
|
+
@annotation_fonts[font] = fontkey
|
11260
|
+
end
|
11261
|
+
fontstyle = sprintf('/F%d %.2f Tf %s', fontkey + 1, @font_size_pt, @text_color)
|
11262
|
+
popt['da'] = fontstyle
|
11263
|
+
popt['ap'] = {}
|
11264
|
+
# set Appearances
|
11265
|
+
popt['ap']['n'] = "/Tx BMC q #{fontstyle} 0.800 g\n"
|
11266
|
+
|
11267
|
+
gvars = getGraphicVars()
|
11268
|
+
@h = h
|
11269
|
+
@w = w
|
11270
|
+
@c_margin *= 1.6
|
11271
|
+
|
11272
|
+
@tmp_buffer = ''
|
11273
|
+
SetLineStyle({'width' => 1.0, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => [231]})
|
11274
|
+
SetFillColor(204)
|
11275
|
+
multi_cell(w, h, caption, 1, 'C', 1, 0, 0, 0, true)
|
11276
|
+
popt['ap']['n'] << @tmp_buffer
|
11277
|
+
popt['ap']['n'] << 'Q EMC'
|
11278
|
+
@tmp_buffer = nil
|
11279
|
+
|
11280
|
+
# restore previous values
|
11281
|
+
setGraphicVars(gvars, true)
|
11282
|
+
|
11283
|
+
# merge options
|
11284
|
+
opt = popt.merge opt
|
11285
|
+
# set remaining annotation data
|
11286
|
+
opt['Subtype'] = 'Widget'
|
11287
|
+
opt['ft'] = 'Btn'
|
11288
|
+
opt['t'] = caption
|
11289
|
+
opt['v'] = name
|
11290
|
+
unless action.empty?
|
11291
|
+
if action.is_a?(Hash)
|
11292
|
+
# form action options as on section 12.7.5 of PDF32000_2008.
|
11293
|
+
opt['aa'] = '/D <<'
|
11294
|
+
bmode = ['SubmitForm', 'ResetForm', 'ImportData']
|
11295
|
+
action.each {|key, val|
|
11296
|
+
if (key == 'S') && bmode.include?(val)
|
11297
|
+
opt['aa'] << " /S /#{val}"
|
11298
|
+
elsif (key == 'F') && !val.empty?
|
11299
|
+
opt['aa'] << " /F #{datastring(val)}"
|
11300
|
+
elsif (key == 'Fields') && val.is_a?(Array) && !val.empty?
|
11301
|
+
opt['aa'] << ' /Fields ['
|
11302
|
+
val.each {|field|
|
11303
|
+
opt['aa'] << " #{textstring(field)}"
|
11304
|
+
}
|
11305
|
+
opt['aa'] << ']'
|
11306
|
+
elsif key == 'Flags'
|
11307
|
+
ff = 0
|
11308
|
+
if val.is_a?(Array)
|
11309
|
+
val.each {|flag|
|
11310
|
+
case flag
|
11311
|
+
when 'Include/Exclude'; ff |= 1 << 0
|
11312
|
+
when 'IncludeNoValueFields'; ff |= 1 << 1
|
11313
|
+
when 'ExportFormat'; ff |= 1 << 2
|
11314
|
+
when 'GetMethod'; ff |= 1 << 3
|
11315
|
+
when 'SubmitCoordinates'; ff |= 1 << 4
|
11316
|
+
when 'XFDF'; ff |= 1 << 5
|
11317
|
+
when 'IncludeAppendSaves'; ff |= 1 << 6
|
11318
|
+
when 'IncludeAnnotations'; ff |= 1 << 7
|
11319
|
+
when 'SubmitPDF'; ff |= 1 << 8
|
11320
|
+
when 'CanonicalFormat'; ff |= 1 << 9
|
11321
|
+
when 'ExclNonUserAnnots'; ff |= 1 << 10
|
11322
|
+
when 'ExclFKey'; ff |= 1 << 11
|
11323
|
+
when 'EmbedForm'; ff |= 1 << 13
|
11324
|
+
end
|
11325
|
+
}
|
11326
|
+
else
|
11327
|
+
ff = val.to_i
|
11328
|
+
end
|
11329
|
+
opt['aa'] << " /Flags #{ff}"
|
11330
|
+
end
|
11331
|
+
}
|
11332
|
+
opt['aa'] << ' >>'
|
11333
|
+
else
|
11334
|
+
# Javascript action or raw action command
|
11335
|
+
js_obj_id = addJavascriptObject(action)
|
11336
|
+
opt['aa'] = "/D #{js_obj_id} 0 R"
|
11337
|
+
end
|
11338
|
+
end
|
11339
|
+
Annotation(x, y, w, h, name, opt, 0)
|
11340
|
+
if @rtl
|
11341
|
+
@x -= w
|
11342
|
+
else
|
11343
|
+
@x += w
|
11344
|
+
end
|
11345
|
+
end
|
11346
|
+
alias_method :button, :Button
|
11347
|
+
|
10374
11348
|
# --- END FORMS FIELDS ------------------------------------------------
|
10375
11349
|
|
10376
11350
|
#
|
@@ -11378,7 +12352,39 @@ protected
|
|
11378
12352
|
html = html_a + html_b + html[(pos + 6)..-1]
|
11379
12353
|
offset = (html_a + html_b).length
|
11380
12354
|
end
|
12355
|
+
|
12356
|
+
offset = 0
|
12357
|
+
while (offset < html.length) && (pos = html.index('</textarea>', offset))
|
12358
|
+
html_a = html[0, offset]
|
12359
|
+
html_b = html[offset, pos - offset + 11]
|
12360
|
+
while html_b =~ %r@<textarea([^\>]*)>(.*?)\n(.*?)</textarea>@mi
|
12361
|
+
# preserve newlines on <textarea> tag
|
12362
|
+
html_b.gsub!(%r@<textarea([^\>]*)>(.*?)\n(.*?)</textarea>@mi, "<textarea\\1>\\2<TBR>\\3</textarea>")
|
12363
|
+
html_b.gsub!(%r@<textarea([^\>]*)>(.*?)[\"](.*?)</textarea>@mi, "<textarea\\1>\\2''\\3</textarea>")
|
12364
|
+
end
|
12365
|
+
html = html_a + html_b + html[(pos + 11)..-1]
|
12366
|
+
offset = html_a.length + html_b.length
|
12367
|
+
end
|
12368
|
+
html.gsub!(/([\s]*)<option/mi, "<option")
|
12369
|
+
html.gsub!(%r@</option>([\s]*)@mi, "</option>")
|
12370
|
+
offset = 0
|
12371
|
+
while (offset < html.length) && (pos = html.index('</option>', offset))
|
12372
|
+
html_a = html[0, offset]
|
12373
|
+
html_b = html[offset, pos - offset + 9]
|
12374
|
+
while html_b =~ %r@<option([^\>]*)>(.*?)</option>@mi
|
12375
|
+
html_b.gsub!(%r@<option([\s]+)value=\"([^\"]*)\"([^\>]*)>(.*?)</option>@mi, "\\2\t\\4\r")
|
12376
|
+
html_b.gsub!(%r@<option([^\>]*)>(.*?)</option>@mi, "\\2\r")
|
12377
|
+
end
|
12378
|
+
html = html_a + html_b + html[(pos + 9)..-1]
|
12379
|
+
offset = html_a.length + html_b.length
|
12380
|
+
end
|
12381
|
+
html.gsub!(/<select([^\>]*)>/mi, "<select\\1 opt=\"")
|
12382
|
+
html.gsub!(%r@([\s]+)</select>@mi, "\" />")
|
11381
12383
|
html.gsub!(/[\n]/, " ")
|
12384
|
+
|
12385
|
+
# restore textarea newlines
|
12386
|
+
html.gsub!('<TBR>', "\n")
|
12387
|
+
|
11382
12388
|
# remove extra spaces from code
|
11383
12389
|
html.gsub!(/[\s]+<\/(table|tr|td|th|ul|ol|li|dl|dt|dd)>/, '</\\1>')
|
11384
12390
|
html.gsub!(/[\s]+<(tr|td|th|ul|ol|li|dl|dt|dd|br)/, '<\\1')
|
@@ -11389,6 +12395,8 @@ protected
|
|
11389
12395
|
html.gsub!(/[\s]*<img/, ' <img')
|
11390
12396
|
html.gsub!(/<img([^\>]*)>/xi, '<img\\1><span><marker style="font-size:0"/></span>')
|
11391
12397
|
html.gsub!(/<xre/, '<pre') # restore pre tag
|
12398
|
+
html.gsub!(/<textarea([^\>]*)>/xi, '<textarea\\1 value="')
|
12399
|
+
html.gsub!(/<\/textarea>/, '" />')
|
11392
12400
|
|
11393
12401
|
# trim string
|
11394
12402
|
html.gsub!(/^[\s]+/, '')
|
@@ -11520,7 +12528,7 @@ protected
|
|
11520
12528
|
# *** opening html tag
|
11521
12529
|
dom[key]['opening'] = true
|
11522
12530
|
dom[key]['parent'] = level[-1]
|
11523
|
-
if element[-1, 1] == '/' or (dom[key]['value'] =~ /(br|img|hr)/)
|
12531
|
+
if element[-1, 1] == '/' or (dom[key]['value'] =~ /(br|img|hr|input)/)
|
11524
12532
|
# self-closing tag
|
11525
12533
|
dom[key]['self'] = true
|
11526
12534
|
else
|
@@ -11546,7 +12554,7 @@ protected
|
|
11546
12554
|
dom[key]['text-indent'] = dom[parentkey]['text-indent']
|
11547
12555
|
end
|
11548
12556
|
# get attributes
|
11549
|
-
attr_array = element.scan(/([^=\s]
|
12557
|
+
attr_array = element.scan(/([^=\s]+)[\s]*(?:=[\s]*"([^"]*)")*/)[1..-1]
|
11550
12558
|
dom[key]['attribute'] = {} # reset attribute array
|
11551
12559
|
attr_array.each do |name, value|
|
11552
12560
|
dom[key]['attribute'][name.downcase] = value
|
@@ -11982,8 +12990,9 @@ public
|
|
11982
12990
|
def sanitize_html(html)
|
11983
12991
|
# Escape '<' character for not tag case.
|
11984
12992
|
html = html.gsub(%r{(<+)([^/a-zA-Z])}){CGI.escapeHTML($1) + $2}.gsub(%r{</([^a-zA-Z])}){'</' + $1}
|
11985
|
-
|
11986
|
-
|
12993
|
+
"%s" % sanitize(html,
|
12994
|
+
: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),
|
12995
|
+
: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
12996
|
end
|
11988
12997
|
protected :sanitize_html
|
11989
12998
|
|
@@ -12083,6 +13092,7 @@ public
|
|
12083
13092
|
prev_listordered = @listordered
|
12084
13093
|
prev_listcount = @listcount
|
12085
13094
|
prev_lispacer = @lispacer
|
13095
|
+
prev_li_position_x = @li_position_x
|
12086
13096
|
@listnum = 0
|
12087
13097
|
@listordered = []
|
12088
13098
|
@listcount = []
|
@@ -12960,7 +13970,7 @@ public
|
|
12960
13970
|
if !@premode
|
12961
13971
|
prelen = dom[key]['value'].length
|
12962
13972
|
if isRTLTextDir()
|
12963
|
-
dom[key]['value'] = dom[key]['value'].rstrip
|
13973
|
+
dom[key]['value'] = dom[key]['value'].rstrip
|
12964
13974
|
else
|
12965
13975
|
dom[key]['value'] = dom[key]['value'].lstrip
|
12966
13976
|
end
|
@@ -13155,6 +14165,7 @@ public
|
|
13155
14165
|
@listordered = prev_listordered
|
13156
14166
|
@listcount = prev_listcount
|
13157
14167
|
@lispacer = prev_lispacer
|
14168
|
+
@li_position_x = prev_li_position_x
|
13158
14169
|
dom = nil
|
13159
14170
|
rescue => err
|
13160
14171
|
Error('writeHTML Error.', err)
|
@@ -13471,6 +14482,7 @@ public
|
|
13471
14482
|
@lispacer = '!'
|
13472
14483
|
end
|
13473
14484
|
end
|
14485
|
+
@li_position_x = @x
|
13474
14486
|
when 'blockquote'
|
13475
14487
|
if @rtl
|
13476
14488
|
@r_margin += @listindent
|
@@ -13494,6 +14506,166 @@ public
|
|
13494
14506
|
SetXY(GetX(), GetY() + ((0.3 * @font_size_pt) / @k))
|
13495
14507
|
when 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
|
13496
14508
|
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
14509
|
+
|
14510
|
+
# Form fields (since 4.8.000 - 2009-09-07)
|
14511
|
+
when 'form'
|
14512
|
+
if tag['attribute']['action']
|
14513
|
+
@form_action = tag['attribute']['action']
|
14514
|
+
else
|
14515
|
+
@form_action = @@k_path_url + request&.base_url.to_s
|
14516
|
+
end
|
14517
|
+
if tag['attribute']['enctype']
|
14518
|
+
@form_enctype = tag['attribute']['enctype']
|
14519
|
+
else
|
14520
|
+
@form_enctype = 'application/x-www-form-urlencoded'
|
14521
|
+
end
|
14522
|
+
if tag['attribute']['method']
|
14523
|
+
@form_mode = tag['attribute']['method']
|
14524
|
+
else
|
14525
|
+
@form_mode = 'post'
|
14526
|
+
end
|
14527
|
+
when 'input'
|
14528
|
+
if tag['attribute']['type'] == 'checkbox' || (tag['attribute']['name'] && !empty_string(tag['attribute']['name']))
|
14529
|
+
name = tag['attribute']['name'] || rand.to_s
|
14530
|
+
prop = {}
|
14531
|
+
opt = {}
|
14532
|
+
if tag['attribute']['value'] && !empty_string(tag['attribute']['value'])
|
14533
|
+
value = tag['attribute']['value']
|
14534
|
+
end
|
14535
|
+
if tag['attribute']['maxlength'] && !empty_string(tag['attribute']['maxlength'])
|
14536
|
+
opt['maxlen'] = tag['attribute']['maxlength'].to_i
|
14537
|
+
end
|
14538
|
+
h = @font_size * @cell_height_ratio
|
14539
|
+
if tag['attribute']['size'] && !empty_string(tag['attribute']['size'])
|
14540
|
+
w = tag['attribute']['size'].to_i * GetStringWidth(32.chr) * 2
|
14541
|
+
else
|
14542
|
+
w = h
|
14543
|
+
end
|
14544
|
+
if tag['attribute'].key? 'disabled'
|
14545
|
+
prop['readonly'] = 'true'
|
14546
|
+
end
|
14547
|
+
if tag['attribute'].key? 'checked'
|
14548
|
+
checked = true
|
14549
|
+
else
|
14550
|
+
checked = false
|
14551
|
+
end
|
14552
|
+
|
14553
|
+
case tag['attribute']['type']
|
14554
|
+
when 'text'
|
14555
|
+
opt['v'] = value if value
|
14556
|
+
TextField(name, w, h, prop, opt, '', '', false)
|
14557
|
+
when 'password'
|
14558
|
+
opt['v'] = value if value
|
14559
|
+
prop['password'] = 'true'
|
14560
|
+
TextField(name, w, h, prop, opt, '', '', false)
|
14561
|
+
when 'checkbox'
|
14562
|
+
CheckBox(name, w, checked, prop, opt, value, '', '', false)
|
14563
|
+
when 'radio'
|
14564
|
+
RadioButton(name, w, prop, opt, value, checked, '', '', false)
|
14565
|
+
when 'submit'
|
14566
|
+
w = GetStringWidth(value) * 1.5
|
14567
|
+
h *= 1.6
|
14568
|
+
prop = {'lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>[196, 196, 196], 'strokeColor'=>[255, 255, 255]}
|
14569
|
+
action = {}
|
14570
|
+
action['S'] = 'SubmitForm'
|
14571
|
+
action['F'] = @form_action
|
14572
|
+
action['Flags'] = ['ExportFormat'] unless @form_enctype == 'FDF'
|
14573
|
+
action['Flags'] = ['GetMethod'] if @form_mode == 'get'
|
14574
|
+
Button(name, w, h, value, action, prop, opt, '', '', false)
|
14575
|
+
when 'reset'
|
14576
|
+
w = GetStringWidth(value) * 1.5
|
14577
|
+
h *= 1.6
|
14578
|
+
prop = {'lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>[196, 196, 196], 'strokeColor'=>[255, 255, 255]}
|
14579
|
+
Button(name, w, h, value, {'S'=>'ResetForm'}, prop, opt, '', '', false)
|
14580
|
+
when 'file'
|
14581
|
+
prop['fileSelect'] = 'true'
|
14582
|
+
TextField(name, w, h, prop, opt, '', '', false)
|
14583
|
+
value ||= '*'
|
14584
|
+
w = GetStringWidth(value) * 2
|
14585
|
+
h *= 1.2
|
14586
|
+
prop = {'lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>[196, 196, 196], 'strokeColor'=>[255, 255, 255]}
|
14587
|
+
jsaction = "var f=this.getField('#{name}'); f.browseForFileToSubmit();"
|
14588
|
+
Button('FB_' + name, w, h, value, jsaction, prop, opt, '', '', false)
|
14589
|
+
when 'hidden'
|
14590
|
+
opt['v'] = value if value
|
14591
|
+
opt['f'] = ['invisible', 'hidden']
|
14592
|
+
TextField(name, 0, 0, prop, opt, '', '', false)
|
14593
|
+
when 'image'
|
14594
|
+
# THIS TYPE MUST BE FIXED
|
14595
|
+
if tag['attribute']['src'] && !empty_string(tag['attribute']['src'])
|
14596
|
+
img = tag['attribute']['src']
|
14597
|
+
value = 'img'
|
14598
|
+
#opt['mk'] = {'i'=>img, 'tp'=>1, 'if'=>{'sw'=>'A', 's'=>'A', 'fb'=>false}}
|
14599
|
+
if tag['attribute']['onclick'] && !tag['attribute']['onclick'].empty?
|
14600
|
+
jsaction = tag['attribute']['onclick']
|
14601
|
+
else
|
14602
|
+
jsaction = ''
|
14603
|
+
end
|
14604
|
+
Button(name, w, h, value, jsaction, prop, opt, '', '', false)
|
14605
|
+
end
|
14606
|
+
when 'button'
|
14607
|
+
w = GetStringWidth(value) * 1.5
|
14608
|
+
h *= 1.6
|
14609
|
+
prop = {'lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>[196, 196, 196], 'strokeColor'=>[255, 255, 255]}
|
14610
|
+
if tag['attribute']['onclick'] && !tag['attribute']['onclick'].empty?
|
14611
|
+
jsaction = tag['attribute']['onclick']
|
14612
|
+
else
|
14613
|
+
jsaction = ''
|
14614
|
+
end
|
14615
|
+
Button(name, w, h, value, jsaction, prop, opt, '', '', false)
|
14616
|
+
end
|
14617
|
+
end
|
14618
|
+
when 'textarea'
|
14619
|
+
if tag['attribute']['name'] && !empty_string(tag['attribute']['name'])
|
14620
|
+
prop = {}
|
14621
|
+
opt = {}
|
14622
|
+
name = tag['attribute']['name']
|
14623
|
+
if tag['attribute']['value'] && !empty_string(tag['attribute']['value'])
|
14624
|
+
opt['v'] = tag['attribute']['value']
|
14625
|
+
end
|
14626
|
+
if tag['attribute']['cols'] && !empty_string(tag['attribute']['cols'])
|
14627
|
+
w = tag['attribute']['cols'].to_i * GetStringWidth(32.chr) * 2
|
14628
|
+
else
|
14629
|
+
w = 40
|
14630
|
+
end
|
14631
|
+
if tag['attribute']['rows'] && !empty_string(tag['attribute']['rows'])
|
14632
|
+
h = tag['attribute']['rows'].to_i * @font_size * @cell_height_ratio
|
14633
|
+
else
|
14634
|
+
h = 10
|
14635
|
+
end
|
14636
|
+
prop['multiline'] = 'true'
|
14637
|
+
TextField(name, w, h, prop, opt, '', '', false)
|
14638
|
+
end
|
14639
|
+
when 'select'
|
14640
|
+
if tag['attribute']['name'] && !empty_string(tag['attribute']['name']) && tag['attribute']['opt'] && !empty_string(tag['attribute']['opt'])
|
14641
|
+
h = @font_size * @cell_height_ratio
|
14642
|
+
if tag['attribute']['size'] && !empty_string(tag['attribute']['size'])
|
14643
|
+
h *= (tag['attribute']['size'].to_i + 1)
|
14644
|
+
end
|
14645
|
+
prop = {}
|
14646
|
+
opt = {}
|
14647
|
+
name = tag['attribute']['name']
|
14648
|
+
w = 0
|
14649
|
+
options = tag['attribute']['opt'].split("\r")
|
14650
|
+
values = []
|
14651
|
+
options.each {|val|
|
14652
|
+
if val.index("\t")
|
14653
|
+
opts = val.split("\t")
|
14654
|
+
values << opts
|
14655
|
+
w = [w, GetStringWidth(opts[1])].max
|
14656
|
+
else
|
14657
|
+
values << val
|
14658
|
+
w = [w, GetStringWidth(val)].max
|
14659
|
+
end
|
14660
|
+
}
|
14661
|
+
w *= 2
|
14662
|
+
if tag['attribute'].key? 'multiple'
|
14663
|
+
prop['multipleSelection'] = 'true'
|
14664
|
+
ListBox(name, w, h, values, prop, opt, '', '', false)
|
14665
|
+
else
|
14666
|
+
ComboBox(name, w, h, values, prop, opt, '', '', false)
|
14667
|
+
end
|
14668
|
+
end
|
13497
14669
|
end
|
13498
14670
|
|
13499
14671
|
if dom[key]['self'] and dom[key]['attribute']['pagebreakafter']
|
@@ -13569,317 +14741,325 @@ public
|
|
13569
14741
|
end
|
13570
14742
|
# Closing tag
|
13571
14743
|
case (tag['value'])
|
13572
|
-
|
13573
|
-
|
13574
|
-
|
13575
|
-
|
13576
|
-
|
14744
|
+
when 'tr'
|
14745
|
+
table_el = dom[(dom[key]['parent'])]['parent']
|
14746
|
+
if parent['endy'].nil?
|
14747
|
+
dom[(dom[key]['parent'])]['endy'] = @y
|
14748
|
+
parent['endy'] = @y
|
14749
|
+
end
|
14750
|
+
if parent['endpage'].nil?
|
14751
|
+
dom[(dom[key]['parent'])]['endpage'] = @page
|
14752
|
+
parent['endpage'] = @page
|
14753
|
+
end
|
14754
|
+
# update row-spanned cells
|
14755
|
+
if !dom[table_el]['rowspans'].nil?
|
14756
|
+
dom[table_el]['rowspans'].each_with_index { |trwsp, k|
|
14757
|
+
dom[table_el]['rowspans'][k]['rowspan'] -= 1
|
14758
|
+
if dom[table_el]['rowspans'][k]['rowspan'] == 0
|
14759
|
+
if dom[table_el]['rowspans'][k]['endpage'] == parent['endpage']
|
14760
|
+
dom[(dom[key]['parent'])]['endy'] = [dom[table_el]['rowspans'][k]['endy'], parent['endy']].max
|
14761
|
+
elsif dom[table_el]['rowspans'][k]['endpage'] > parent['endpage']
|
14762
|
+
dom[(dom[key]['parent'])]['endy'] = dom[table_el]['rowspans'][k]['endy']
|
14763
|
+
dom[(dom[key]['parent'])]['endpage'] = dom[table_el]['rowspans'][k]['endpage']
|
14764
|
+
end
|
14765
|
+
end
|
14766
|
+
}
|
14767
|
+
# report new endy and endpage to the rowspanned cells
|
14768
|
+
dom[table_el]['rowspans'].each_with_index { |trwsp, k|
|
14769
|
+
if dom[table_el]['rowspans'][k]['rowspan'] == 0
|
14770
|
+
dom[table_el]['rowspans'][k]['endpage'] = [dom[table_el]['rowspans'][k]['endpage'], dom[(dom[key]['parent'])]['endpage']].max
|
14771
|
+
dom[(dom[key]['parent'])]['endpage'] = dom[table_el]['rowspans'][k]['endpage']
|
14772
|
+
dom[table_el]['rowspans'][k]['endy'] = [dom[table_el]['rowspans'][k]['endy'], dom[(dom[key]['parent'])]['endy']].max
|
14773
|
+
dom[(dom[key]['parent'])]['endy'] = dom[table_el]['rowspans'][k]['endy']
|
14774
|
+
end
|
14775
|
+
}
|
14776
|
+
# update remaining rowspanned cells
|
14777
|
+
dom[table_el]['rowspans'].each_with_index { |trwsp, k|
|
14778
|
+
if dom[table_el]['rowspans'][k]['rowspan'] == 0
|
14779
|
+
dom[table_el]['rowspans'][k]['endpage'] = dom[(dom[key]['parent'])]['endpage']
|
14780
|
+
dom[table_el]['rowspans'][k]['endy'] = dom[(dom[key]['parent'])]['endy']
|
14781
|
+
end
|
14782
|
+
}
|
14783
|
+
end
|
14784
|
+
if (@num_columns > 1) and (dom[(dom[key]['parent'])]['endy'] >= (@page_break_trigger - @lasth)) and (@y < dom[(dom[key]['parent'])]['endy'])
|
14785
|
+
Ln(0, cell)
|
14786
|
+
else
|
14787
|
+
setPage(dom[(dom[key]['parent'])]['endpage']);
|
14788
|
+
@y = dom[(dom[key]['parent'])]['endy']
|
14789
|
+
if !dom[table_el]['attribute']['cellspacing'].nil?
|
14790
|
+
cellspacing = getHTMLUnitToUnits(dom[table_el]['attribute']['cellspacing'], 1, 'px')
|
14791
|
+
@y += cellspacing
|
13577
14792
|
end
|
13578
|
-
|
13579
|
-
|
13580
|
-
|
14793
|
+
Ln(0, cell)
|
14794
|
+
@x = parent['startx']
|
14795
|
+
# account for booklet mode
|
14796
|
+
if parent['startpage'] and @page > parent['startpage']
|
14797
|
+
if @rtl and (@pagedim[@page]['orm'] != @pagedim[parent['startpage']]['orm'])
|
14798
|
+
@x -= @pagedim[@page]['orm'] - @pagedim[parent['startpage']]['orm']
|
14799
|
+
elsif !@rtl and (@pagedim[@page]['olm'] != @pagedim[parent['startpage']]['olm'])
|
14800
|
+
@x += @pagedim[@page]['olm'] - @pagedim[parent['startpage']]['olm']
|
14801
|
+
end
|
13581
14802
|
end
|
14803
|
+
end
|
14804
|
+
when 'table'
|
14805
|
+
if dom[(dom[key]['parent'])]['attribute']['tablehead'] and dom[(dom[key]['parent'])]['attribute']['tablehead'] == "1"
|
14806
|
+
# closing tag used for the thead part
|
14807
|
+
in_table_head = true
|
14808
|
+
@in_thead = false
|
14809
|
+
end
|
14810
|
+
|
14811
|
+
table_el = parent
|
14812
|
+
# draw borders
|
14813
|
+
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))
|
14814
|
+
border = 1
|
14815
|
+
else
|
14816
|
+
border = 0
|
14817
|
+
end
|
14818
|
+
|
14819
|
+
startpage = 0
|
14820
|
+
end_page = 0
|
14821
|
+
# fix bottom line alignment of last line before page break
|
14822
|
+
dom[(dom[key]['parent'])]['trids'].each_with_index { |trkey, j|
|
13582
14823
|
# 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
|
14824
|
+
if !dom[(dom[key]['parent'])]['rowspans'].nil?
|
14825
|
+
dom[(dom[key]['parent'])]['rowspans'].each_with_index { |trwsp, k|
|
14826
|
+
if trwsp['trid'] == trkey
|
14827
|
+
dom[(dom[key]['parent'])]['rowspans'][k]['mrowspan'] -= 1
|
13593
14828
|
end
|
13594
|
-
|
13595
|
-
|
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']
|
14829
|
+
if defined?(prevtrkey) and (trwsp['trid'] == prevtrkey) and (trwsp['mrowspan'] >= 0)
|
14830
|
+
dom[(dom[key]['parent'])]['rowspans'][k]['trid'] = trkey
|
13602
14831
|
end
|
13603
14832
|
}
|
13604
|
-
# update remaining rowspanned cells
|
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']
|
13609
|
-
end
|
13610
|
-
}
|
13611
|
-
end
|
13612
|
-
if (@num_columns > 1) and (dom[(dom[key]['parent'])]['endy'] >= (@page_break_trigger - @lasth)) and (@y < dom[(dom[key]['parent'])]['endy'])
|
13613
|
-
Ln(0, cell)
|
13614
|
-
else
|
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
14833
|
end
|
13646
|
-
|
13647
|
-
|
13648
|
-
|
13649
|
-
# fix bottom line alignment of last line before page break
|
13650
|
-
dom[(dom[key]['parent'])]['trids'].each_with_index { |trkey, j|
|
14834
|
+
if defined?(prevtrkey) and (dom[trkey]['startpage'] > dom[prevtrkey]['endpage'])
|
14835
|
+
pgendy = @pagedim[dom[prevtrkey]['endpage']]['hk'] - @pagedim[dom[prevtrkey]['endpage']]['bm']
|
14836
|
+
dom[prevtrkey]['endy'] = pgendy
|
13651
14837
|
# update row-spanned cells
|
13652
14838
|
if !dom[(dom[key]['parent'])]['rowspans'].nil?
|
13653
14839
|
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
|
14840
|
+
if (trwsp['trid'] == trkey) and (trwsp['mrowspan'] > 1) and (trwsp['endpage'] == dom[prevtrkey]['endpage'])
|
14841
|
+
dom[(dom[key]['parent'])]['rowspans'][k]['endy'] = pgendy
|
14842
|
+
dom[(dom[key]['parent'])]['rowspans'][k]['mrowspan'] = -1
|
13659
14843
|
end
|
13660
14844
|
}
|
13661
14845
|
end
|
13662
|
-
|
13663
|
-
|
13664
|
-
|
13665
|
-
|
13666
|
-
|
13667
|
-
|
13668
|
-
|
13669
|
-
|
13670
|
-
|
13671
|
-
|
13672
|
-
|
13673
|
-
|
14846
|
+
end
|
14847
|
+
prevtrkey = trkey
|
14848
|
+
table_el = dom[(dom[key]['parent'])].dup
|
14849
|
+
}
|
14850
|
+
# for each row
|
14851
|
+
table_el['trids'].each_with_index { |trkey, j|
|
14852
|
+
parent = dom[trkey]
|
14853
|
+
# for each cell on the row
|
14854
|
+
parent['cellpos'].each_with_index { |cellpos, k|
|
14855
|
+
if !cellpos['rowspanid'].nil? and (cellpos['rowspanid'] >= 0)
|
14856
|
+
cellpos['startx'] = table_el['rowspans'][(cellpos['rowspanid'])]['startx']
|
14857
|
+
cellpos['endx'] = table_el['rowspans'][(cellpos['rowspanid'])]['endx']
|
14858
|
+
endy = table_el['rowspans'][(cellpos['rowspanid'])]['endy']
|
14859
|
+
startpage = table_el['rowspans'][(cellpos['rowspanid'])]['startpage']
|
14860
|
+
end_page = table_el['rowspans'][(cellpos['rowspanid'])]['endpage']
|
14861
|
+
else
|
14862
|
+
endy = parent['endy']
|
14863
|
+
startpage = parent['startpage']
|
14864
|
+
end_page = parent['endpage']
|
13674
14865
|
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
|
14866
|
+
cellpos['startx'] ||= 0
|
14867
|
+
if end_page > startpage
|
14868
|
+
# design borders around HTML cells.
|
14869
|
+
startpage.upto(end_page) do |page|
|
14870
|
+
setPage(page)
|
14871
|
+
if page == startpage
|
14872
|
+
@y = parent['starty'] # put cursor at the beginning of row on the first page
|
14873
|
+
ch = getPageHeight() - parent['starty'] - getBreakMargin()
|
14874
|
+
cborder = getBorderMode(border, position='start')
|
14875
|
+
elsif page == end_page
|
14876
|
+
@y = @t_margin # put cursor at the beginning of last page
|
14877
|
+
ch = endy - @t_margin
|
14878
|
+
cborder = getBorderMode(border, position='end')
|
14879
|
+
else
|
14880
|
+
@y = @t_margin # put cursor at the beginning of the current page
|
14881
|
+
ch = getPageHeight() - @t_margin - getBreakMargin()
|
14882
|
+
cborder = getBorderMode(border, position='middle')
|
13741
14883
|
end
|
13742
|
-
else
|
13743
|
-
setPage(startpage)
|
13744
14884
|
if !cellpos['bgcolor'].nil? and (cellpos['bgcolor'] != false)
|
13745
14885
|
SetFillColorArray(cellpos['bgcolor'])
|
13746
14886
|
fill = 1
|
13747
14887
|
else
|
13748
14888
|
fill = 0
|
13749
14889
|
end
|
13750
|
-
@x = cellpos['startx']
|
13751
|
-
@y = parent['starty']
|
13752
14890
|
cw = (cellpos['endx'] - cellpos['startx']).abs
|
13753
|
-
|
14891
|
+
@x = cellpos['startx']
|
14892
|
+
# account for margin changes
|
14893
|
+
if page > startpage
|
14894
|
+
if @rtl and (@pagedim[page]['orm'] != @pagedim[startpage]['orm'])
|
14895
|
+
@x -= @pagedim[page]['orm'] - @pagedim[startpage]['orm']
|
14896
|
+
elsif !@rtl and (@pagedim[page]['lm'] != @pagedim[startpage]['olm'])
|
14897
|
+
@x += @pagedim[page]['olm'] - @pagedim[startpage]['olm']
|
14898
|
+
end
|
14899
|
+
end
|
13754
14900
|
|
13755
14901
|
prevLastH = @lasth
|
13756
14902
|
# design a cell around the text
|
13757
|
-
ccode = @fill_color + "\n" + getCellCode(cw, ch, '',
|
14903
|
+
ccode = @fill_color + "\n" + getCellCode(cw, ch, '', cborder, 1, '', fill, '', 0, true)
|
13758
14904
|
@lasth = prevLastH
|
13759
14905
|
|
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
|
14906
|
+
if (cborder != 0) or (fill == 1)
|
13771
14907
|
pagebuff = getPageBuffer(@page)
|
13772
|
-
pstart = pagebuff[0,
|
13773
|
-
pend = pagebuff[
|
14908
|
+
pstart = pagebuff[0, @intmrk[@page]]
|
14909
|
+
pend = pagebuff[@intmrk[@page]..-1]
|
13774
14910
|
setPageBuffer(@page, pstart + ccode + "\n" + pend)
|
14911
|
+
@intmrk[@page] += (ccode + "\n").length
|
13775
14912
|
end
|
13776
14913
|
end
|
13777
|
-
|
13778
|
-
|
13779
|
-
|
13780
|
-
|
13781
|
-
|
13782
|
-
|
13783
|
-
|
13784
|
-
|
13785
|
-
|
13786
|
-
|
13787
|
-
|
13788
|
-
|
14914
|
+
else
|
14915
|
+
setPage(startpage)
|
14916
|
+
if !cellpos['bgcolor'].nil? and (cellpos['bgcolor'] != false)
|
14917
|
+
SetFillColorArray(cellpos['bgcolor'])
|
14918
|
+
fill = 1
|
14919
|
+
else
|
14920
|
+
fill = 0
|
14921
|
+
end
|
14922
|
+
@x = cellpos['startx']
|
14923
|
+
@y = parent['starty']
|
14924
|
+
cw = (cellpos['endx'] - cellpos['startx']).abs
|
14925
|
+
ch = endy - parent['starty']
|
14926
|
+
|
14927
|
+
prevLastH = @lasth
|
14928
|
+
# design a cell around the text
|
14929
|
+
ccode = @fill_color + "\n" + getCellCode(cw, ch, '', border, 1, '', fill, '', 0, true)
|
14930
|
+
@lasth = prevLastH
|
14931
|
+
|
14932
|
+
if (border != 0) or (fill == 1)
|
14933
|
+
if !@transfmrk[@page].nil?
|
14934
|
+
pagemark = @transfmrk[@page]
|
14935
|
+
@transfmrk[@page] += (ccode + "\n").length
|
14936
|
+
elsif @in_footer
|
14937
|
+
pagemark = @footerpos[@page]
|
14938
|
+
@footerpos[@page] += (ccode + "\n").length
|
14939
|
+
else
|
14940
|
+
pagemark = @intmrk[@page]
|
14941
|
+
@intmrk[@page] += (ccode + "\n").length
|
14942
|
+
end
|
14943
|
+
pagebuff = getPageBuffer(@page)
|
14944
|
+
pstart = pagebuff[0, pagemark]
|
14945
|
+
pend = pagebuff[pagemark..-1]
|
14946
|
+
setPageBuffer(@page, pstart + ccode + "\n" + pend)
|
13789
14947
|
end
|
13790
14948
|
end
|
13791
14949
|
}
|
13792
|
-
if !
|
13793
|
-
|
13794
|
-
|
13795
|
-
|
14950
|
+
if !table_el['attribute']['cellspacing'].nil?
|
14951
|
+
cellspacing = getHTMLUnitToUnits(table_el['attribute']['cellspacing'], 1, 'px')
|
14952
|
+
@y += cellspacing
|
14953
|
+
end
|
14954
|
+
Ln(0, cell)
|
14955
|
+
@x = parent['startx']
|
14956
|
+
if end_page > startpage
|
14957
|
+
if @rtl and (@pagedim[end_page]['orm'] != @pagedim[startpage]['orm'])
|
14958
|
+
@x += @pagedim[end_page]['orm'] - @pagedim[startpage]['orm']
|
14959
|
+
elsif !@rtl and (@pagedim[end_page]['olm'] != @pagedim[startpage]['olm'])
|
14960
|
+
@x += @pagedim[end_page]['olm'] - @pagedim[startpage]['olm']
|
13796
14961
|
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
14962
|
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)
|
14963
|
+
}
|
14964
|
+
if !in_table_head
|
14965
|
+
# we are not inside a thead section
|
14966
|
+
if dom[(parent['parent'])]['attribute']['cellpadding'] ### fix ###
|
14967
|
+
@c_margin = @old_c_margin
|
13847
14968
|
end
|
13848
14969
|
@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
|
14970
|
+
if (@page == @numpages - 1) and @pageopen[@numpages]
|
14971
|
+
# remove last blank page
|
14972
|
+
deletePage(@numpages)
|
13858
14973
|
end
|
13859
|
-
|
13860
|
-
|
13861
|
-
|
13862
|
-
|
13863
|
-
@lispacer = ''
|
13864
|
-
if @rtl
|
13865
|
-
@r_margin -= @listindent
|
13866
|
-
else
|
13867
|
-
@l_margin -= @listindent
|
14974
|
+
if !@thead_margins['top'].nil?
|
14975
|
+
# restore top margin
|
14976
|
+
@t_margin = @thead_margins['top']
|
14977
|
+
@pagedim[@page]['tm'] = @t_margin
|
13868
14978
|
end
|
13869
|
-
|
13870
|
-
|
13871
|
-
@
|
13872
|
-
|
13873
|
-
else
|
13874
|
-
addHTMLVertSpace(0, 0, cell, firstorlast)
|
14979
|
+
if table_el['attribute']['nested'].nil? or (table_el['attribute']['nested'] != 'true')
|
14980
|
+
# reset main table header
|
14981
|
+
@thead = ''
|
14982
|
+
@thead_margins = {}
|
13875
14983
|
end
|
13876
|
-
|
13877
|
-
|
13878
|
-
|
14984
|
+
end
|
14985
|
+
if tag['block']
|
14986
|
+
unless dom[(dom[key]['parent'])]['attribute']['tablehead'] and dom[(dom[key]['parent'])]['attribute']['tablehead'] == "1" ### fix ###
|
14987
|
+
addHTMLVertSpace(hbz / 2, 0, cell, (dom[key+1].nil? or (dom[key+1]['value'] != 'table'))) ### fix ###
|
14988
|
+
end
|
14989
|
+
end
|
14990
|
+
when 'a'
|
14991
|
+
@href = {}
|
14992
|
+
@html_anchor = nil
|
14993
|
+
when 'sup'
|
14994
|
+
SetXY(GetX(), GetY() + (0.7 * parent['fontsize'] / @k))
|
14995
|
+
when 'sub'
|
14996
|
+
SetXY(GetX(), GetY() - (0.3 * parent['fontsize'] / @k))
|
14997
|
+
when 'div'
|
14998
|
+
addHTMLVertSpace(hbz, 0, cell, firstorlast)
|
14999
|
+
when 'blockquote'
|
15000
|
+
if @rtl
|
15001
|
+
@r_margin -= @listindent
|
15002
|
+
else
|
15003
|
+
@l_margin -= @listindent
|
15004
|
+
end
|
15005
|
+
@listindentlevel -= 1
|
15006
|
+
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
15007
|
+
when 'p'
|
15008
|
+
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
15009
|
+
when 'pre'
|
15010
|
+
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
15011
|
+
@premode = false
|
15012
|
+
when 'dl'
|
15013
|
+
@listnum -= 1
|
15014
|
+
if @listnum <= 0
|
15015
|
+
@listnum = 0
|
15016
|
+
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
15017
|
+
else
|
13879
15018
|
addHTMLVertSpace(0, 0, cell, firstorlast)
|
13880
|
-
|
15019
|
+
end
|
15020
|
+
@lasth = @font_size * @cell_height_ratio
|
15021
|
+
when 'dt'
|
15022
|
+
@lispacer = ''
|
15023
|
+
@li_position_x = nil
|
15024
|
+
addHTMLVertSpace(0, 0, cell, firstorlast)
|
15025
|
+
when 'dd'
|
15026
|
+
@lispacer = ''
|
15027
|
+
@li_position_x = nil
|
15028
|
+
if @rtl
|
15029
|
+
@r_margin -= @listindent
|
15030
|
+
else
|
15031
|
+
@l_margin -= @listindent
|
15032
|
+
end
|
15033
|
+
@listindentlevel -= 1
|
15034
|
+
addHTMLVertSpace(0, 0, cell, firstorlast)
|
15035
|
+
when 'ul', 'ol'
|
15036
|
+
@listnum -= 1
|
15037
|
+
@lispacer = ''
|
15038
|
+
@li_position_x = nil
|
15039
|
+
if @rtl
|
15040
|
+
@r_margin -= @listindent
|
15041
|
+
else
|
15042
|
+
@l_margin -= @listindent
|
15043
|
+
end
|
15044
|
+
@listindentlevel -= 1
|
15045
|
+
if @listnum <= 0
|
15046
|
+
@listnum = 0
|
13881
15047
|
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
15048
|
+
else
|
15049
|
+
addHTMLVertSpace(0, 0, cell, firstorlast)
|
15050
|
+
end
|
15051
|
+
@lasth = @font_size * @cell_height_ratio
|
15052
|
+
when 'li'
|
15053
|
+
@lispacer = ''
|
15054
|
+
@li_position_x = nil
|
15055
|
+
addHTMLVertSpace(0, 0, cell, firstorlast)
|
15056
|
+
when 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
|
15057
|
+
addHTMLVertSpace(hbz, hb, cell, firstorlast)
|
15058
|
+
when 'form' # Form fields (since 4.8.000 - 2009-09-07)
|
15059
|
+
@form_action = ''
|
15060
|
+
@form_enctype = 'application/x-www-form-urlencoded'
|
13882
15061
|
end
|
15062
|
+
|
13883
15063
|
if dom[(dom[key]['parent'])]['attribute']['pagebreakafter']
|
13884
15064
|
pba = dom[(dom[key]['parent'])]['attribute']['pagebreakafter']
|
13885
15065
|
# check for pagebreak
|
@@ -14119,6 +15299,7 @@ protected
|
|
14119
15299
|
width = 0
|
14120
15300
|
textitem = ''
|
14121
15301
|
tmpx = @x
|
15302
|
+
@x = @li_position_x
|
14122
15303
|
lspace = GetStringWidth(' ')
|
14123
15304
|
if listtype == '!'
|
14124
15305
|
# set default list type for unordered list
|
@@ -14190,6 +15371,7 @@ protected
|
|
14190
15371
|
end
|
14191
15372
|
@x = tmpx
|
14192
15373
|
@lispacer = ''
|
15374
|
+
@li_position_x = nil
|
14193
15375
|
end
|
14194
15376
|
|
14195
15377
|
#
|
@@ -14206,6 +15388,7 @@ protected
|
|
14206
15388
|
'rMargin' => @r_margin,
|
14207
15389
|
'lMargin' => @l_margin,
|
14208
15390
|
'cMargin' => @c_margin,
|
15391
|
+
'tMargin' => @t_margin,
|
14209
15392
|
'LineWidth' => @line_width,
|
14210
15393
|
'linestyleWidth' => @linestyle_width,
|
14211
15394
|
'linestyleCap' => @linestyle_cap,
|
@@ -14226,24 +15409,31 @@ protected
|
|
14226
15409
|
'listordered' => @listordered,
|
14227
15410
|
'listcount' => @listcount,
|
14228
15411
|
'lispacer' => @lispacer,
|
14229
|
-
'
|
15412
|
+
'li_position_x' => @li_position_x,
|
15413
|
+
'lasth' => @lasth,
|
15414
|
+
'h' => @h,
|
15415
|
+
'w' => @w,
|
15416
|
+
'x' => @x,
|
15417
|
+
'y' => @y,
|
14230
15418
|
}
|
14231
15419
|
return grapvars
|
14232
15420
|
end
|
14233
15421
|
|
14234
15422
|
#
|
14235
15423
|
# Set graphic variables.
|
14236
|
-
# [@param :gvars]
|
15424
|
+
# [@param array :gvars] graphic variables
|
15425
|
+
# [@param bool :option] set additional parameters
|
14237
15426
|
# [@access protected]
|
14238
15427
|
# [@since 4.2.010 (2008-11-14)]
|
14239
15428
|
#
|
14240
|
-
def setGraphicVars(gvars)
|
15429
|
+
def setGraphicVars(gvars, option = false)
|
14241
15430
|
@font_family = gvars['FontFamily']
|
14242
15431
|
@font_style = gvars['FontStyle']
|
14243
15432
|
@font_size_pt = gvars['FontSizePt']
|
14244
15433
|
@r_margin = gvars['rMargin']
|
14245
15434
|
@l_margin = gvars['lMargin']
|
14246
15435
|
@c_margin = gvars['cMargin']
|
15436
|
+
@t_margin = gvars['tMargin']
|
14247
15437
|
@line_width = gvars['LineWidth']
|
14248
15438
|
@linestyle_width = gvars['linestyleWidth']
|
14249
15439
|
@linestyle_cap = gvars['linestyleCap']
|
@@ -14264,7 +15454,14 @@ protected
|
|
14264
15454
|
@listordered = gvars['listordered']
|
14265
15455
|
@listcount = gvars['listcount']
|
14266
15456
|
@lispacer = gvars['lispacer']
|
14267
|
-
|
15457
|
+
@li_position_x = gvars['li_position_x']
|
15458
|
+
if option
|
15459
|
+
@lasth = gvars['lasth']
|
15460
|
+
@h = gvars['h']
|
15461
|
+
@w = gvars['w']
|
15462
|
+
@x = gvars['x']
|
15463
|
+
@y = gvars['y']
|
15464
|
+
end
|
14268
15465
|
out('' + @linestyle_width + ' ' + @linestyle_cap + ' ' + @linestyle_join + ' ' + @linestyle_dash + ' ' + @draw_color + ' ' + @fill_color + '')
|
14269
15466
|
unless empty_string(@font_family)
|
14270
15467
|
SetFont(@font_family, @font_style, @font_size_pt)
|
@@ -14671,18 +15868,17 @@ public
|
|
14671
15868
|
#global jfrompage, jtopage
|
14672
15869
|
#jfrompage = frompage
|
14673
15870
|
#jtopage = topage
|
14674
|
-
|
14675
|
-
#
|
14676
|
-
#
|
14677
|
-
#
|
14678
|
-
#
|
14679
|
-
#
|
14680
|
-
#
|
14681
|
-
#
|
14682
|
-
#
|
14683
|
-
#
|
14684
|
-
|
14685
|
-
# return "this.addField(\'".$matches[1]."\',\'".$matches[2]."\',".$newpage."";'), $tmpjavascript);
|
15871
|
+
#tmpjavascript =~ /this\.addField\(\'([^\']*)\',\'([^\']*)\',([0-9]+)/
|
15872
|
+
#pagenum = $3.to_i + 1
|
15873
|
+
#if (pagenum >= jtopage) && (pagenum < jfrompage)
|
15874
|
+
# newpage = pagenum + 1
|
15875
|
+
#elsif pagenum == jfrompage
|
15876
|
+
# newpage = jtopage
|
15877
|
+
#else
|
15878
|
+
# newpage = pagenum
|
15879
|
+
#end
|
15880
|
+
#newpage -= 1
|
15881
|
+
#@javascript = "this.addField(\'" + $1 + "\',\'" + $2 + "\'," + newpage + ""
|
14686
15882
|
|
14687
15883
|
# return to last page
|
14688
15884
|
lastPage(true)
|
@@ -14865,6 +16061,8 @@ public
|
|
14865
16061
|
else
|
14866
16062
|
gap = ''
|
14867
16063
|
end
|
16064
|
+
# sort outlines by page and original position
|
16065
|
+
@outlines = @outlines.sort_by {|x| [x[:p], x[:y]] }
|
14868
16066
|
@outlines.each_with_index do |outline, key|
|
14869
16067
|
if @rtl
|
14870
16068
|
aligntext = 'R'
|
@@ -15004,6 +16202,8 @@ public
|
|
15004
16202
|
@html_link_color_array = []
|
15005
16203
|
@html_link_font_style = ''
|
15006
16204
|
page_first = getPage()
|
16205
|
+
# sort outlines by page and original position
|
16206
|
+
@outlines = @outlines.sort_by {|x| [x[:p], x[:y]] }
|
15007
16207
|
@outlines.each_with_index do |outline, key|
|
15008
16208
|
if empty_string(page)
|
15009
16209
|
pagenum = outline[:p].to_s
|