pdf-core 0.5.1 → 0.9.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,4 +1,5 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  #
3
4
  # Implements graphics state saving and restoring
4
5
  #
@@ -7,7 +8,6 @@
7
8
  # This is free software. Please see the LICENSE and COPYING files for details
8
9
  #
9
10
 
10
-
11
11
  module PDF
12
12
  module Core
13
13
  class GraphicStateStack
@@ -34,28 +34,26 @@ module PDF
34
34
  end
35
35
 
36
36
  def present?
37
- stack.size > 0
37
+ !stack.empty?
38
38
  end
39
39
 
40
40
  def empty?
41
41
  stack.empty?
42
42
  end
43
-
44
43
  end
45
44
 
46
45
  # NOTE: This class may be a good candidate for a copy-on-write hash.
47
46
  class GraphicState
48
- attr_accessor :color_space, :dash, :cap_style, :join_style, :line_width,
49
- :fill_color, :stroke_color
47
+ attr_accessor :color_space, :dash, :cap_style, :join_style, :line_width, :fill_color, :stroke_color
50
48
 
51
49
  def initialize(previous_state = nil)
52
50
  if previous_state
53
51
  initialize_copy(previous_state)
54
52
  else
55
53
  @color_space = {}
56
- @fill_color = "000000"
57
- @stroke_color = "000000"
58
- @dash = { :dash => nil, :space => nil, :phase => 0 }
54
+ @fill_color = '000000'
55
+ @stroke_color = '000000'
56
+ @dash = { dash: nil, space: nil, phase: 0 }
59
57
  @cap_style = :butt
60
58
  @join_style = :miter
61
59
  @line_width = 1
@@ -63,17 +61,17 @@ module PDF
63
61
  end
64
62
 
65
63
  def dash_setting
66
- return "[] 0 d" unless @dash[:dash]
64
+ return '[] 0 d' unless @dash[:dash]
67
65
 
68
- if @dash[:dash].kind_of?(Array)
69
- array = @dash[:dash]
70
- else
71
- array = [@dash[:dash], @dash[:space]]
72
- end
73
-
74
-
75
- "[#{PDF::Core.real_params(array)}] "+
76
- "#{PDF::Core.real(@dash[:phase])} d"
66
+ array =
67
+ if @dash[:dash].is_a?(Array)
68
+ @dash[:dash]
69
+ else
70
+ [@dash[:dash], @dash[:space]]
71
+ end
72
+
73
+ "[#{PDF::Core.real_params(array)}] "\
74
+ "#{PDF::Core.real(@dash[:phase])} d"
77
75
  end
78
76
 
79
77
  private
@@ -93,4 +91,3 @@ module PDF
93
91
  end
94
92
  end
95
93
  end
96
-
@@ -1,4 +1,5 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  module PDF
3
4
  module Core
4
5
  # This is used to differentiate strings that must be encoded as
@@ -1,4 +1,6 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
3
+ require 'pdf/core/utils'
2
4
 
3
5
  # name_tree.rb : Implements NameTree for PDF
4
6
  #
@@ -16,7 +18,7 @@ module PDF
16
18
  attr_accessor :parent
17
19
  attr_accessor :ref
18
20
 
19
- def initialize(document, limit, parent=nil)
21
+ def initialize(document, limit, parent = nil)
20
22
  @document = document
21
23
  @children = []
22
24
  @limit = limit
@@ -29,7 +31,7 @@ module PDF
29
31
  end
30
32
 
31
33
  def size
32
- leaf? ? children.size : children.inject(0) { |sum, child| sum + child.size }
34
+ leaf? ? children.size : children.sum(&:size)
33
35
  end
34
36
 
35
37
  def leaf?
@@ -47,10 +49,10 @@ module PDF
47
49
  if leaf?
48
50
  hash[:Names] = children if leaf?
49
51
  else
50
- hash[:Kids] = children.map { |child| child.ref }
52
+ hash[:Kids] = children.map(&:ref)
51
53
  end
52
54
 
53
- return hash
55
+ hash
54
56
  end
55
57
 
56
58
  def least
@@ -76,23 +78,24 @@ module PDF
76
78
  children.insert(insertion_point(value), value)
77
79
  split! if children.length > limit
78
80
  else
79
- fit = children.detect { |child| child >= value }
80
- fit = children.last unless fit
81
+ fit = children.find { |child| child >= value }
82
+ fit ||= children.last
81
83
  fit << value
82
84
  end
83
85
 
84
86
  value
85
87
  end
86
88
 
87
- def >=(value)
88
- children.empty? || children.last >= value
89
+ def >=(other)
90
+ children.empty? || children.last >= other
89
91
  end
90
92
 
91
93
  def split!
92
94
  if parent
93
95
  parent.split(self)
94
96
  else
95
- left, right = new_node(self), new_node(self)
97
+ left = new_node(self)
98
+ right = new_node(self)
96
99
  split_children(self, left, right)
97
100
  children.replace([left, right])
98
101
  end
@@ -103,51 +106,50 @@ module PDF
103
106
  #
104
107
  def deep_copy
105
108
  node = dup
106
- node.instance_variable_set("@children",
107
- Marshal.load(Marshal.dump(children)))
108
- node.instance_variable_set("@ref",
109
- node.ref ? node.ref.deep_copy : nil)
109
+ node.instance_variable_set('@children', Utils.deep_clone(children))
110
+ node.instance_variable_set('@ref', node.ref ? node.ref.deep_copy : nil)
110
111
  node
111
112
  end
112
113
 
113
114
  protected
114
115
 
115
- def split(node)
116
- new_child = new_node(self)
117
- split_children(node, node, new_child)
118
- index = children.index(node)
119
- children.insert(index+1, new_child)
120
- split! if children.length > limit
121
- end
116
+ def split(node)
117
+ new_child = new_node(self)
118
+ split_children(node, node, new_child)
119
+ index = children.index(node)
120
+ children.insert(index + 1, new_child)
121
+ split! if children.length > limit
122
+ end
122
123
 
123
124
  private
124
125
 
125
- def new_node(parent=nil)
126
- node = Node.new(document, limit, parent)
127
- node.ref = document.ref!(node)
128
- return node
129
- end
126
+ def new_node(parent = nil)
127
+ node = Node.new(document, limit, parent)
128
+ node.ref = document.ref!(node)
129
+ node
130
+ end
130
131
 
131
- def split_children(node, left, right)
132
- half = (node.limit+1)/2
132
+ def split_children(node, left, right)
133
+ half = (node.limit + 1) / 2
133
134
 
134
- left_children, right_children = node.children[0...half], node.children[half..-1]
135
+ left_children = node.children[0...half]
136
+ right_children = node.children[half..-1]
135
137
 
136
- left.children.replace(left_children)
137
- right.children.replace(right_children)
138
+ left.children.replace(left_children)
139
+ right.children.replace(right_children)
138
140
 
139
- unless node.leaf?
140
- left_children.each { |child| child.parent = left }
141
- right_children.each { |child| child.parent = right }
142
- end
141
+ unless node.leaf?
142
+ left_children.each { |child| child.parent = left }
143
+ right_children.each { |child| child.parent = right }
143
144
  end
145
+ end
144
146
 
145
- def insertion_point(value)
146
- children.each_with_index do |child, index|
147
- return index if child >= value
148
- end
149
- return children.length
147
+ def insertion_point(value)
148
+ children.each_with_index do |child, index|
149
+ return index if child >= value
150
150
  end
151
+ children.length
152
+ end
151
153
  end
152
154
 
153
155
  class Value #:nodoc:
@@ -157,11 +159,12 @@ module PDF
157
159
  attr_reader :value
158
160
 
159
161
  def initialize(name, value)
160
- @name, @value = PDF::Core::LiteralString.new(name), value
162
+ @name = PDF::Core::LiteralString.new(name)
163
+ @value = value
161
164
  end
162
165
 
163
- def <=>(leaf)
164
- name <=> leaf.name
166
+ def <=>(other)
167
+ name <=> other.name
165
168
  end
166
169
 
167
170
  def inspect
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # Implements PDF object repository
4
4
  #
@@ -18,12 +18,12 @@ module PDF
18
18
  @identifiers = []
19
19
 
20
20
  @info ||= ref(opts[:info] || {}).identifier
21
- @root ||= ref(:Type => :Catalog).identifier
21
+ @root ||= ref(Type: :Catalog).identifier
22
22
  if opts[:print_scaling] == :none
23
- root.data[:ViewerPreferences] = {:PrintScaling => :None}
23
+ root.data[:ViewerPreferences] = { PrintScaling: :None }
24
24
  end
25
25
  if pages.nil?
26
- root.data[:Pages] = ref(:Type => :Pages, :Count => 0, :Kids => [])
26
+ root.data[:Pages] = ref(Type: :Pages, Count: 0, Kids: [])
27
27
  end
28
28
  end
29
29
 
@@ -48,22 +48,23 @@ module PDF
48
48
  end
49
49
 
50
50
  # Adds the given reference to the store and returns the reference object.
51
- # If the object provided is not a PDF::Core::Reference, one is created from the
52
- # arguments provided.
51
+ # If the object provided is not a PDF::Core::Reference, one is created
52
+ # from the arguments provided.
53
53
  #
54
54
  def push(*args, &block)
55
- reference = if args.first.is_a?(PDF::Core::Reference)
56
- args.first
57
- else
58
- PDF::Core::Reference.new(*args, &block)
59
- end
55
+ reference =
56
+ if args.first.is_a?(PDF::Core::Reference)
57
+ args.first
58
+ else
59
+ PDF::Core::Reference.new(*args, &block)
60
+ end
60
61
 
61
62
  @objects[reference.identifier] = reference
62
63
  @identifiers << reference.identifier
63
64
  reference
64
65
  end
65
66
 
66
- alias_method :<<, :push
67
+ alias << push
67
68
 
68
69
  def each
69
70
  @identifiers.each do |id|
@@ -78,7 +79,7 @@ module PDF
78
79
  def size
79
80
  @identifiers.size
80
81
  end
81
- alias_method :length, :size
82
+ alias length size
82
83
 
83
84
  # returns the object ID for a particular page in the document. Pages
84
85
  # are indexed starting at 1 (not 0!).
@@ -90,17 +91,11 @@ module PDF
90
91
  # object_id_for_page(-11)
91
92
  # => 17
92
93
  #
93
- def object_id_for_page(k)
94
- k -= 1 if k > 0
94
+ def object_id_for_page(page)
95
+ page -= 1 if page.positive?
95
96
  flat_page_ids = get_page_objects(pages).flatten
96
- flat_page_ids[k]
97
- end
98
-
99
- def is_utf8?(str)
100
- str.force_encoding(::Encoding::UTF_8)
101
- str.valid_encoding?
97
+ flat_page_ids[page]
102
98
  end
103
99
  end
104
100
  end
105
101
  end
106
-
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PDF
2
4
  module Core
3
5
  class OutlineItem #:nodoc:
@@ -11,11 +13,15 @@ module PDF
11
13
  end
12
14
 
13
15
  def to_hash
14
- hash = { :Title => title,
15
- :Parent => parent,
16
- :Count => closed ? -count : count }
17
- [{:First => first}, {:Last => last}, {:Next => defined?(@next) && @next},
18
- {:Prev => prev}, {:Dest => dest}].each do |h|
16
+ hash = {
17
+ Title: title,
18
+ Parent: parent,
19
+ Count: closed ? -count : count
20
+ }
21
+ [
22
+ { First: first }, { Last: last }, { Next: defined?(@next) && @next },
23
+ { Prev: prev }, { Dest: dest }
24
+ ].each do |h|
19
25
  unless h.values.first.nil?
20
26
  hash.merge!(h)
21
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PDF
2
4
  module Core
3
5
  class OutlineRoot #:nodoc:
@@ -8,7 +10,7 @@ module PDF
8
10
  end
9
11
 
10
12
  def to_hash
11
- {:Type => :Outlines, :Count => count, :First => first, :Last => last}
13
+ { Type: :Outlines, Count: count, First: first, Last: last }
12
14
  end
13
15
  end
14
16
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # prawn/core/page.rb : Implements low-level representation of a PDF page
4
4
  #
@@ -12,21 +12,49 @@ require_relative 'graphics_state'
12
12
  module PDF
13
13
  module Core
14
14
  class Page #:nodoc:
15
- attr_accessor :document, :margins, :stack
15
+ attr_accessor :art_indents, :bleeds, :crops, :document, :margins, :stack, :trims
16
16
  attr_writer :content, :dictionary
17
17
 
18
- def initialize(document, options={})
18
+ ZERO_INDENTS = {
19
+ left: 0,
20
+ bottom: 0,
21
+ right: 0,
22
+ top: 0
23
+ }.freeze
24
+
25
+ def initialize(document, options = {})
19
26
  @document = document
20
- @margins = options[:margins] || { :left => 36,
21
- :right => 36,
22
- :top => 36,
23
- :bottom => 36 }
27
+ @margins = options[:margins] || {
28
+ left: 36,
29
+ right: 36,
30
+ top: 36,
31
+ bottom: 36
32
+ }
33
+ @crops = options[:crops] || ZERO_INDENTS
34
+ @bleeds = options[:bleeds] || ZERO_INDENTS
35
+ @trims = options[:trims] || ZERO_INDENTS
36
+ @art_indents = options[:art_indents] || ZERO_INDENTS
24
37
  @stack = GraphicStateStack.new(options[:graphic_state])
25
- if options[:object_id]
26
- init_from_object(options)
27
- else
28
- init_new_page(options)
29
- end
38
+ @size = options[:size] || 'LETTER'
39
+ @layout = options[:layout] || :portrait
40
+
41
+ @stamp_stream = nil
42
+ @stamp_dictionary = nil
43
+
44
+ @content = document.ref({})
45
+ content << 'q' << "\n"
46
+ @dictionary = document.ref(
47
+ Type: :Page,
48
+ Parent: document.state.store.pages,
49
+ MediaBox: dimensions,
50
+ CropBox: crop_box,
51
+ BleedBox: bleed_box,
52
+ TrimBox: trim_box,
53
+ ArtBox: art_box,
54
+ Contents: content
55
+ )
56
+
57
+ resources[:ProcSet] = %i[PDF Text ImageB ImageC ImageI]
30
58
  end
31
59
 
32
60
  def graphic_state
@@ -45,28 +73,26 @@ module PDF
45
73
  end
46
74
 
47
75
  def size
48
- defined?(@size) && @size || dimensions[2,2]
76
+ defined?(@size) && @size || dimensions[2, 2]
49
77
  end
50
78
 
51
79
  def in_stamp_stream?
52
- !!@stamp_stream
80
+ !@stamp_stream.nil?
53
81
  end
54
82
 
55
83
  def stamp_stream(dictionary)
56
- @stamp_stream = ""
57
84
  @stamp_dictionary = dictionary
85
+ @stamp_stream = @stamp_dictionary.stream
58
86
  graphic_stack_size = stack.stack.size
59
87
 
60
88
  document.save_graphics_state
61
- document.send(:freeze_stamp_graphics)
89
+ document.__send__(:freeze_stamp_graphics)
62
90
  yield if block_given?
63
91
 
64
92
  until graphic_stack_size == stack.stack.size
65
93
  document.restore_graphics_state
66
94
  end
67
95
 
68
- @stamp_dictionary << @stamp_stream
69
-
70
96
  @stamp_stream = nil
71
97
  @stamp_dictionary = nil
72
98
  end
@@ -76,7 +102,8 @@ module PDF
76
102
  end
77
103
 
78
104
  def dictionary
79
- defined?(@stamp_dictionary) && @stamp_dictionary || document.state.store[@dictionary]
105
+ defined?(@stamp_dictionary) && @stamp_dictionary ||
106
+ document.state.store[@dictionary]
80
107
  end
81
108
 
82
109
  def resources
@@ -116,62 +143,67 @@ module PDF
116
143
  dictionary.data[:Contents].each do |stream|
117
144
  stream.stream.compress! if document.compression_enabled?
118
145
  end
119
- else
120
- content.stream.compress! if document.compression_enabled?
146
+ elsif document.compression_enabled?
147
+ content.stream.compress!
121
148
  end
122
149
  end
123
150
 
124
- def imported_page?
125
- @imported_page
126
- end
127
-
128
151
  def dimensions
129
- return inherited_dictionary_value(:MediaBox) if imported_page?
130
-
131
152
  coords = PDF::Core::PageGeometry::SIZES[size] || size
132
- [0,0] + case(layout)
133
- when :portrait
134
- coords
135
- when :landscape
136
- coords.reverse
137
- else
138
- raise PDF::Core::Errors::InvalidPageLayout,
139
- "Layout must be either :portrait or :landscape"
140
- end
153
+ [0, 0] +
154
+ case layout
155
+ when :portrait
156
+ coords
157
+ when :landscape
158
+ coords.reverse
159
+ else
160
+ raise PDF::Core::Errors::InvalidPageLayout,
161
+ 'Layout must be either :portrait or :landscape'
162
+ end
141
163
  end
142
164
 
143
- private
144
-
145
- def init_from_object(options)
146
- @dictionary = options[:object_id].to_i
147
-
148
- unless dictionary.data[:Contents].is_a?(Array) # content only on leafs
149
- @content = dictionary.data[:Contents].identifier
150
- end
151
-
152
- @stamp_stream = nil
153
- @stamp_dictionary = nil
154
- @imported_page = true
165
+ def art_box
166
+ left, bottom, right, top = dimensions
167
+ [
168
+ left + art_indents[:left],
169
+ bottom + art_indents[:bottom],
170
+ right - art_indents[:right],
171
+ top - art_indents[:top]
172
+ ]
155
173
  end
156
174
 
157
- def init_new_page(options)
158
- @size = options[:size] || "LETTER"
159
- @layout = options[:layout] || :portrait
160
-
161
- @stamp_stream = nil
162
- @stamp_dictionary = nil
163
- @imported_page = false
175
+ def bleed_box
176
+ left, bottom, right, top = dimensions
177
+ [
178
+ left + bleeds[:left],
179
+ bottom + bleeds[:bottom],
180
+ right - bleeds[:right],
181
+ top - bleeds[:top]
182
+ ]
183
+ end
164
184
 
165
- @content = document.ref({})
166
- content << "q" << "\n"
167
- @dictionary = document.ref(:Type => :Page,
168
- :Parent => document.state.store.pages,
169
- :MediaBox => dimensions,
170
- :Contents => content)
185
+ def crop_box
186
+ left, bottom, right, top = dimensions
187
+ [
188
+ left + crops[:left],
189
+ bottom + crops[:bottom],
190
+ right - crops[:right],
191
+ top - crops[:top]
192
+ ]
193
+ end
171
194
 
172
- resources[:ProcSet] = [:PDF, :Text, :ImageB, :ImageC, :ImageI]
195
+ def trim_box
196
+ left, bottom, right, top = dimensions
197
+ [
198
+ left + trims[:left],
199
+ bottom + trims[:bottom],
200
+ right - trims[:right],
201
+ top - trims[:top]
202
+ ]
173
203
  end
174
204
 
205
+ private
206
+
175
207
  # some entries in the Page dict can be inherited from parent Pages dicts.
176
208
  #
177
209
  # Starting with the current page dict, this method will walk up the
@@ -183,12 +215,10 @@ module PDF
183
215
  def inherited_dictionary_value(key, local_dict = nil)
184
216
  local_dict ||= dictionary.data
185
217
 
186
- if local_dict.has_key?(key)
218
+ if local_dict.key?(key)
187
219
  local_dict[key]
188
- elsif local_dict.has_key?(:Parent)
220
+ elsif local_dict.key?(:Parent)
189
221
  inherited_dictionary_value(key, local_dict[:Parent].data)
190
- else
191
- nil
192
222
  end
193
223
  end
194
224
  end