pdf-core 0.6.1 → 0.7.0

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.
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  # Describes PDF page geometries
4
2
  #
5
3
  # Copyright April 2008, Gregory Brown. All Rights Reserved.
@@ -8,7 +6,6 @@
8
6
 
9
7
  module PDF
10
8
  module Core
11
-
12
9
  # Dimensions pulled from PDF::Writer, rubyforge.org/projects/ruby-pdf
13
10
  #
14
11
  # All of these dimensions are in PDF Points (1/72 inch)
@@ -68,59 +65,58 @@ module PDF
68
65
  # TABLOID:: => 792.00 x 1224.00
69
66
  #
70
67
  module PageGeometry
71
-
72
- SIZES = { "4A0" => [4767.87, 6740.79],
73
- "2A0" => [3370.39, 4767.87],
74
- "A0" => [2383.94, 3370.39],
75
- "A1" => [1683.78, 2383.94],
76
- "A2" => [1190.55, 1683.78],
77
- "A3" => [841.89, 1190.55],
78
- "A4" => [595.28, 841.89],
79
- "A5" => [419.53, 595.28],
80
- "A6" => [297.64, 419.53],
81
- "A7" => [209.76, 297.64],
82
- "A8" => [147.40, 209.76],
83
- "A9" => [104.88, 147.40],
84
- "A10" => [73.70, 104.88],
85
- "B0" => [2834.65, 4008.19],
86
- "B1" => [2004.09, 2834.65],
87
- "B2" => [1417.32, 2004.09],
88
- "B3" => [1000.63, 1417.32],
89
- "B4" => [708.66, 1000.63],
90
- "B5" => [498.90, 708.66],
91
- "B6" => [354.33, 498.90],
92
- "B7" => [249.45, 354.33],
93
- "B8" => [175.75, 249.45],
94
- "B9" => [124.72, 175.75],
95
- "B10" => [87.87, 124.72],
96
- "C0" => [2599.37, 3676.54],
97
- "C1" => [1836.85, 2599.37],
98
- "C2" => [1298.27, 1836.85],
99
- "C3" => [918.43, 1298.27],
100
- "C4" => [649.13, 918.43],
101
- "C5" => [459.21, 649.13],
102
- "C6" => [323.15, 459.21],
103
- "C7" => [229.61, 323.15],
104
- "C8" => [161.57, 229.61],
105
- "C9" => [113.39, 161.57],
106
- "C10" => [79.37, 113.39],
107
- "RA0" => [2437.80, 3458.27],
108
- "RA1" => [1729.13, 2437.80],
109
- "RA2" => [1218.90, 1729.13],
110
- "RA3" => [864.57, 1218.90],
111
- "RA4" => [609.45, 864.57],
112
- "SRA0" => [2551.18, 3628.35],
113
- "SRA1" => [1814.17, 2551.18],
114
- "SRA2" => [1275.59, 1814.17],
115
- "SRA3" => [907.09, 1275.59],
116
- "SRA4" => [637.80, 907.09],
117
- "EXECUTIVE" => [521.86, 756.00],
118
- "FOLIO" => [612.00, 936.00],
119
- "LEGAL" => [612.00, 1008.00],
120
- "LETTER" => [612.00, 792.00],
121
- "TABLOID" => [792.00, 1224.00] }
122
-
68
+ SIZES = {
69
+ '4A0' => [4767.87, 6740.79],
70
+ '2A0' => [3370.39, 4767.87],
71
+ 'A0' => [2383.94, 3370.39],
72
+ 'A1' => [1683.78, 2383.94],
73
+ 'A2' => [1190.55, 1683.78],
74
+ 'A3' => [841.89, 1190.55],
75
+ 'A4' => [595.28, 841.89],
76
+ 'A5' => [419.53, 595.28],
77
+ 'A6' => [297.64, 419.53],
78
+ 'A7' => [209.76, 297.64],
79
+ 'A8' => [147.40, 209.76],
80
+ 'A9' => [104.88, 147.40],
81
+ 'A10' => [73.70, 104.88],
82
+ 'B0' => [2834.65, 4008.19],
83
+ 'B1' => [2004.09, 2834.65],
84
+ 'B2' => [1417.32, 2004.09],
85
+ 'B3' => [1000.63, 1417.32],
86
+ 'B4' => [708.66, 1000.63],
87
+ 'B5' => [498.90, 708.66],
88
+ 'B6' => [354.33, 498.90],
89
+ 'B7' => [249.45, 354.33],
90
+ 'B8' => [175.75, 249.45],
91
+ 'B9' => [124.72, 175.75],
92
+ 'B10' => [87.87, 124.72],
93
+ 'C0' => [2599.37, 3676.54],
94
+ 'C1' => [1836.85, 2599.37],
95
+ 'C2' => [1298.27, 1836.85],
96
+ 'C3' => [918.43, 1298.27],
97
+ 'C4' => [649.13, 918.43],
98
+ 'C5' => [459.21, 649.13],
99
+ 'C6' => [323.15, 459.21],
100
+ 'C7' => [229.61, 323.15],
101
+ 'C8' => [161.57, 229.61],
102
+ 'C9' => [113.39, 161.57],
103
+ 'C10' => [79.37, 113.39],
104
+ 'RA0' => [2437.80, 3458.27],
105
+ 'RA1' => [1729.13, 2437.80],
106
+ 'RA2' => [1218.90, 1729.13],
107
+ 'RA3' => [864.57, 1218.90],
108
+ 'RA4' => [609.45, 864.57],
109
+ 'SRA0' => [2551.18, 3628.35],
110
+ 'SRA1' => [1814.17, 2551.18],
111
+ 'SRA2' => [1275.59, 1814.17],
112
+ 'SRA3' => [907.09, 1275.59],
113
+ 'SRA4' => [637.80, 907.09],
114
+ 'EXECUTIVE' => [521.86, 756.00],
115
+ 'FOLIO' => [612.00, 936.00],
116
+ 'LEGAL' => [612.00, 1008.00],
117
+ 'LETTER' => [612.00, 792.00],
118
+ 'TABLOID' => [792.00, 1224.00]
119
+ }.freeze
123
120
  end
124
121
  end
125
122
  end
126
-
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
- #
3
1
  # pdf_object.rb : Handles Ruby to PDF object serialization
4
2
  #
5
3
  # Copyright April 2008, Gregory Brown. All Rights Reserved.
@@ -17,85 +15,87 @@ module PDF
17
15
  end
18
16
 
19
17
  def real_params(array)
20
- array.map { |e| real(e) }.join(" ")
18
+ array.map { |e| real(e) }.join(' ')
21
19
  end
22
20
 
23
21
  def utf8_to_utf16(str)
24
- "\xFE\xFF".force_encoding(::Encoding::UTF_16BE) + str.encode(::Encoding::UTF_16BE)
22
+ "\xFE\xFF".force_encoding(::Encoding::UTF_16BE) +
23
+ str.encode(::Encoding::UTF_16BE)
25
24
  end
26
25
 
27
26
  # encodes any string into a hex representation. The result is a string
28
27
  # with only 0-9 and a-f characters. That result is valid ASCII so tag
29
28
  # it as such to account for behaviour of different ruby VMs
30
29
  def string_to_hex(str)
31
- str.unpack("H*").first.force_encoding(::Encoding::US_ASCII)
30
+ str.unpack('H*').first.force_encoding(::Encoding::US_ASCII)
32
31
  end
33
32
 
34
33
  # Serializes Ruby objects to their PDF equivalents. Most primitive objects
35
34
  # will work as expected, but please note that Name objects are represented
36
- # by Ruby Symbol objects and Dictionary objects are represented by Ruby hashes
37
- # (keyed by symbols)
35
+ # by Ruby Symbol objects and Dictionary objects are represented by Ruby
36
+ # hashes (keyed by symbols)
38
37
  #
39
38
  # Examples:
40
39
  #
41
- # PdfObject(true) #=> "true"
42
- # PdfObject(false) #=> "false"
43
- # PdfObject(1.2124) #=> "1.2124"
44
- # PdfObject("foo bar") #=> "(foo bar)"
45
- # PdfObject(:Symbol) #=> "/Symbol"
46
- # PdfObject(["foo",:bar, [1,2]]) #=> "[foo /bar [1 2]]"
40
+ # pdf_object(true) #=> "true"
41
+ # pdf_object(false) #=> "false"
42
+ # pdf_object(1.2124) #=> "1.2124"
43
+ # pdf_object('foo bar') #=> "(foo bar)"
44
+ # pdf_object(:Symbol) #=> "/Symbol"
45
+ # pdf_object(['foo',:bar, [1,2]]) #=> "[foo /bar [1 2]]"
47
46
  #
48
- def PdfObject(obj, in_content_stream = false)
49
- case(obj)
50
- when NilClass then "null"
51
- when TrueClass then "true"
52
- when FalseClass then "false"
47
+ def pdf_object(obj, in_content_stream = false)
48
+ case obj
49
+ when NilClass then 'null'
50
+ when TrueClass then 'true'
51
+ when FalseClass then 'false'
53
52
  when Numeric
54
- obj = real(obj) unless obj.kind_of?(Integer)
53
+ obj = real(obj) unless obj.is_a?(Integer)
55
54
 
56
- String(obj) # NOTE: this can fail on huge floating point numbers,
57
- # but it seems unlikely to ever happen in practice.
55
+ # NOTE: this can fail on huge floating point numbers, but it seems
56
+ # unlikely to ever happen in practice.
57
+ String(obj)
58
58
  when Array
59
- "[" << obj.map { |e| PdfObject(e, in_content_stream) }.join(' ') << "]"
59
+ '[' << obj.map { |e| pdf_object(e, in_content_stream) }.join(' ') << ']'
60
60
  when PDF::Core::LiteralString
61
61
  obj = obj.gsub(/[\\\n\r\t\b\f\(\)]/) { |m| "\\#{m}" }
62
62
  "(#{obj})"
63
63
  when Time
64
- obj = obj.strftime("D:%Y%m%d%H%M%S%z").chop.chop + "'00'"
64
+ obj = obj.strftime('D:%Y%m%d%H%M%S%z').chop.chop + "'00'"
65
65
  obj = obj.gsub(/[\\\n\r\t\b\f\(\)]/) { |m| "\\#{m}" }
66
66
  "(#{obj})"
67
67
  when PDF::Core::ByteString
68
- "<" << obj.unpack("H*").first << ">"
68
+ '<' << obj.unpack('H*').first << '>'
69
69
  when String
70
70
  obj = utf8_to_utf16(obj) unless in_content_stream
71
- "<" << string_to_hex(obj) << ">"
72
- when Symbol
73
- "/" + obj.to_s.unpack("C*").map { |n|
74
- if n < 33 || n > 126 || [35,40,41,47,60,62].include?(n)
75
- "#" + n.to_s(16).upcase
71
+ '<' << string_to_hex(obj) << '>'
72
+ when Symbol
73
+ '/' + obj.to_s.unpack('C*').map do |n|
74
+ if n < 33 || n > 126 || [35, 40, 41, 47, 60, 62].include?(n)
75
+ '#' + n.to_s(16).upcase
76
76
  else
77
- [n].pack("C*")
77
+ [n].pack('C*')
78
78
  end
79
- }.join
79
+ end.join
80
80
  when ::Hash
81
- output = "<< "
82
- obj.each do |k,v|
83
- unless String === k || Symbol === k
81
+ output = '<< '
82
+ obj.each do |k, v|
83
+ unless k.is_a?(String) || k.is_a?(Symbol)
84
84
  raise PDF::Core::Errors::FailedObjectConversion,
85
- "A PDF Dictionary must be keyed by names"
85
+ 'A PDF Dictionary must be keyed by names'
86
86
  end
87
- output << PdfObject(k.to_sym, in_content_stream) << " " <<
88
- PdfObject(v, in_content_stream) << "\n"
87
+ output << pdf_object(k.to_sym, in_content_stream) << ' ' <<
88
+ pdf_object(v, in_content_stream) << "\n"
89
89
  end
90
- output << ">>"
90
+ output << '>>'
91
91
  when PDF::Core::Reference
92
92
  obj.to_s
93
93
  when PDF::Core::NameTree::Node
94
- PdfObject(obj.to_hash)
94
+ pdf_object(obj.to_hash)
95
95
  when PDF::Core::NameTree::Value
96
- PdfObject(obj.name) + " " + PdfObject(obj.value)
96
+ pdf_object(obj.name) + ' ' + pdf_object(obj.value)
97
97
  when PDF::Core::OutlineRoot, PDF::Core::OutlineItem
98
- PdfObject(obj.to_hash)
98
+ pdf_object(obj.to_hash)
99
99
  else
100
100
  raise PDF::Core::Errors::FailedObjectConversion,
101
101
  "This object cannot be serialized to PDF (#{obj.inspect})"
@@ -1,16 +1,14 @@
1
- # encoding: utf-8
2
-
3
1
  # reference.rb : Implementation of PDF indirect objects
4
2
  #
5
3
  # Copyright April 2008, Gregory Brown. All Rights Reserved.
6
4
  #
7
5
  # This is free software. Please see the LICENSE and COPYING files for details.
8
6
 
7
+ require 'pdf/core/utils'
9
8
 
10
9
  module PDF
11
10
  module Core
12
11
  class Reference #:nodoc:
13
-
14
12
  attr_accessor :gen, :data, :offset, :stream, :identifier
15
13
 
16
14
  def initialize(id, data)
@@ -22,17 +20,20 @@ module PDF
22
20
 
23
21
  def object
24
22
  output = "#{@identifier} #{gen} obj\n"
25
- unless @stream.empty?
26
- output << PDF::Core::PdfObject(data.merge @stream.data) << "\n" << @stream.object
23
+ if @stream.empty?
24
+ output << PDF::Core.pdf_object(data) << "\n"
27
25
  else
28
- output << PDF::Core::PdfObject(data) << "\n"
26
+ output << PDF::Core.pdf_object(data.merge(@stream.data)) <<
27
+ "\n" << @stream.object
29
28
  end
30
29
 
31
30
  output << "endobj\n"
32
31
  end
33
32
 
34
33
  def <<(io)
35
- raise "Cannot attach stream to non-dictionary object" unless @data.is_a?(::Hash)
34
+ unless @data.is_a?(::Hash)
35
+ raise 'Cannot attach stream to non-dictionary object'
36
+ end
36
37
  (@stream ||= Stream.new) << io
37
38
  end
38
39
 
@@ -43,22 +44,22 @@ module PDF
43
44
  # Creates a deep copy of this ref. If +share+ is provided, shares the
44
45
  # given dictionary entries between the old ref and the new.
45
46
  #
46
- def deep_copy(share=[])
47
+ def deep_copy(share = [])
47
48
  r = dup
48
49
 
49
50
  case r.data
50
51
  when ::Hash
51
52
  # Copy each entry not in +share+.
52
53
  (r.data.keys - share).each do |k|
53
- r.data[k] = Marshal.load(Marshal.dump(r.data[k]))
54
+ r.data[k] = Utils.deep_clone(r.data[k])
54
55
  end
55
56
  when PDF::Core::NameTree::Node
56
57
  r.data = r.data.deep_copy
57
58
  else
58
- r.data = Marshal.load(Marshal.dump(r.data))
59
+ r.data = Utils.deep_clone(r.data)
59
60
  end
60
61
 
61
- r.stream = Marshal.load(Marshal.dump(r.stream))
62
+ r.stream = Utils.deep_clone(r.stream)
62
63
  r
63
64
  end
64
65
 
@@ -68,11 +69,5 @@ module PDF
68
69
  @stream = other_ref.stream
69
70
  end
70
71
  end
71
-
72
- module_function
73
-
74
- def Reference(*args, &block) #:nodoc:
75
- Reference.new(*args, &block)
76
- end
77
72
  end
78
73
  end
@@ -1,4 +1,4 @@
1
- require "stringio"
1
+ require 'stringio'
2
2
 
3
3
  module PDF
4
4
  module Core
@@ -6,7 +6,7 @@ module PDF
6
6
  def initialize(state)
7
7
  @state = state
8
8
  @state.populate_pages_from_store(self)
9
-
9
+
10
10
  min_version(state.store.min_version) if state.store.min_version
11
11
 
12
12
  @page_number = 0
@@ -14,8 +14,8 @@ module PDF
14
14
 
15
15
  attr_reader :state
16
16
 
17
- # Creates a new Reference and adds it to the Document's object
18
- # list. The +data+ argument is anything that Prawn::PdfObject() can convert.
17
+ # Creates a new Reference and adds it to the Document's object list. The
18
+ # +data+ argument is anything that Prawn.pdf_object() can convert.
19
19
  #
20
20
  # Returns the identifier which points to the reference in the ObjectStore
21
21
  #
@@ -50,7 +50,7 @@ module PDF
50
50
  #
51
51
  # pdf.add_content("#{PDF::Core.real_params([x1, y1])} m") # move
52
52
  # pdf.add_content("#{PDF::Core.real_params([ x2, y2 ])} l") # draw path
53
- # pdf.add_content("S") # stroke
53
+ # pdf.add_content('S') # stroke
54
54
  #
55
55
  def add_content(str)
56
56
  save_graphics_state if graphic_state.nil?
@@ -62,7 +62,7 @@ module PDF
62
62
  # dictionary do not incur the additional overhead.
63
63
  #
64
64
  def names
65
- state.store.root.data[:Names] ||= ref!(:Type => :Names)
65
+ state.store.root.data[:Names] ||= ref!(Type: :Names)
66
66
  end
67
67
 
68
68
  # Returns true if the Names dictionary is in use for this document.
@@ -80,29 +80,36 @@ module PDF
80
80
  # Defines a block to be called just before a new page is started.
81
81
  #
82
82
  def on_page_create(&block)
83
- if block_given?
84
- state.on_page_create_callback = block
85
- else
86
- state.on_page_create_callback = nil
87
- end
83
+ state.on_page_create_callback =
84
+ if block_given?
85
+ block
86
+ end
88
87
  end
89
88
 
90
89
  def start_new_page(options = {})
91
- if last_page = state.page
90
+ last_page = state.page
91
+ if last_page
92
92
  last_page_size = last_page.size
93
93
  last_page_layout = last_page.layout
94
94
  last_page_margins = last_page.margins
95
95
  end
96
96
 
97
- page_options = {:size => options[:size] || last_page_size,
98
- :layout => options[:layout] || last_page_layout,
99
- :margins => last_page_margins}
97
+ page_options = {
98
+ size: options[:size] || last_page_size,
99
+ layout: options[:layout] || last_page_layout,
100
+ margins: last_page_margins
101
+ }
100
102
  if last_page
101
- new_graphic_state = last_page.graphic_state.dup if last_page.graphic_state
103
+ if last_page.graphic_state
104
+ new_graphic_state = last_page.graphic_state.dup
105
+ end
102
106
 
103
- #erase the color space so that it gets reset on new page for fussy pdf-readers
104
- new_graphic_state.color_space = {} if new_graphic_state
105
- page_options.merge!(:graphic_state => new_graphic_state)
107
+ # Erase the color space so that it gets reset on new page for fussy
108
+ # pdf-readers
109
+ if new_graphic_state
110
+ new_graphic_state.color_space = {}
111
+ end
112
+ page_options[:graphic_state] = new_graphic_state
106
113
  end
107
114
 
108
115
  state.page = PDF::Core::Page.new(self, page_options)
@@ -121,10 +128,10 @@ module PDF
121
128
  # draw on it.
122
129
  #
123
130
  # See Prawn::Document#number_pages for a sample usage of this capability.
124
-
131
+
125
132
  def go_to_page(k)
126
133
  @page_number = k
127
- state.page = state.pages[k-1]
134
+ state.page = state.pages[k - 1]
128
135
  end
129
136
 
130
137
  def finalize_all_page_contents
@@ -169,10 +176,10 @@ module PDF
169
176
 
170
177
  # Renders the PDF document to file.
171
178
  #
172
- # pdf.render_file "foo.pdf"
179
+ # pdf.render_file 'foo.pdf'
173
180
  #
174
181
  def render_file(filename)
175
- File.open(filename, "wb") { |f| render(f) }
182
+ File.open(filename, 'wb') { |f| render(f) }
176
183
  end
177
184
 
178
185
  # Write out the PDF Header, as per spec 3.4.1
@@ -201,7 +208,7 @@ module PDF
201
208
  output << "0 #{state.store.size + 1}\n"
202
209
  output << "0000000000 65535 f \n"
203
210
  state.store.each do |ref|
204
- output.printf("%010d", ref.offset)
211
+ output.printf('%010d', ref.offset)
205
212
  output << " 00000 n \n"
206
213
  end
207
214
  end
@@ -209,24 +216,26 @@ module PDF
209
216
  # Write out the PDF Trailer, as per spec 3.4.4
210
217
  #
211
218
  def render_trailer(output)
212
- trailer_hash = {:Size => state.store.size + 1,
213
- :Root => state.store.root,
214
- :Info => state.store.info}
219
+ trailer_hash = {
220
+ Size: state.store.size + 1,
221
+ Root: state.store.root,
222
+ Info: state.store.info
223
+ }
215
224
  trailer_hash.merge!(state.trailer) if state.trailer
216
225
 
217
226
  output << "trailer\n"
218
- output << PDF::Core::PdfObject(trailer_hash) << "\n"
227
+ output << PDF::Core.pdf_object(trailer_hash) << "\n"
219
228
  output << "startxref\n"
220
229
  output << @xref_offset << "\n"
221
- output << "%%EOF" << "\n"
230
+ output << '%%EOF' << "\n"
222
231
  end
223
232
 
224
233
  def open_graphics_state
225
- add_content "q"
234
+ add_content 'q'
226
235
  end
227
236
 
228
237
  def close_graphics_state
229
- add_content "Q"
238
+ add_content 'Q'
230
239
  end
231
240
 
232
241
  def save_graphics_state(graphic_state = nil)
@@ -242,7 +251,7 @@ module PDF
242
251
  # false otherwise
243
252
  #
244
253
  def compression_enabled?
245
- !!state.compress
254
+ state.compress
246
255
  end
247
256
 
248
257
  # Pops the last saved graphics state off the graphics state stack and