combine_pdf 1.0.26 → 1.0.28

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc482ee9da31ce7fc01e92da3936e44407e4879c7058817bb4a57ba0fc0a4165
4
- data.tar.gz: 1dd52423ee639783510a9ad9aa347e9597e2e14d38a11914d05a03b5116006f2
3
+ metadata.gz: 1da4a9ad814eebd6f7b976c238a018a19e6cd1106dea1ebf5d3d51ab1b213ad7
4
+ data.tar.gz: 0fe9ca847a095fb68e2498e03329186d382a856d80e549d83a301f0f0675c9a8
5
5
  SHA512:
6
- metadata.gz: f6ac66c289762c5f2b6473f450e8808e79d9ca9f927b68f083204a93b7f213a433a6fc4076cd3241ff1a17ac7c08297087ab1bf76e58b0dad12e7a0eebc34628
7
- data.tar.gz: a39c619af345d61d7d40ba0d0b0a32438caace2b05512273afe1f21b737de6324dcc483f34234c5123c9ed0508a0db481b4bf90ffc06fce2484922f2c6c7abe0
6
+ metadata.gz: ded304e2d225506a354da76d0165e2d31afffae5537cc30bce2c12228c767825093725b191aa03be08f024437ab15d8431e181d6c9abaefd02f832a494e559b3
7
+ data.tar.gz: c15e1be8a06560ccc966f7e28c4dc84bc05656b33936862dd307afe7744f011bdc17c50107f9595ef44c281e10fc62f1e535f8ef93c24ea438eaa45fc5287e02
@@ -9,7 +9,11 @@ jobs:
9
9
  strategy:
10
10
  fail-fast: false
11
11
  matrix:
12
- ruby: ["2.7", "3.0", "3.1", "3.2"]
12
+ ruby: ["2.7", "3.0", "3.1", "3.2", "3.3"]
13
+ rubyopt: [""]
14
+ include:
15
+ - ruby: "3.3"
16
+ rubyopt: "--enable-frozen-string-literal --debug-frozen-string-literal"
13
17
 
14
18
  steps:
15
19
  - name: Checkout code
@@ -25,4 +29,4 @@ jobs:
25
29
  run: bundle lock
26
30
 
27
31
  - name: Run tests
28
- run: bundle exec rake test
32
+ run: bundle exec rake test RUBYOPT="${{ matrix.rubyopt }}"
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Change Log
2
2
 
3
+ #### Change log v.1.0.28 (2024-11-12)
4
+
5
+ **Fix**: use `require` to load code (instead of `load`). Credit to @casperisfine (Jean byroot Boussier) for PR #216.
6
+
7
+ #### Change log v.1.0.27 (2024-11-10)
8
+
9
+ **Performance**: fix performance issues with `object_id` usage in Ruby 3+. Credit to @amomchilov (Alexander Momchilov) for PR #241.
10
+
11
+ **Performance**: use frozen string literals. Credit to @casperisfine (Jean byroot Boussier) for PR #239.
12
+
3
13
  #### Change log v.1.0.26 (2023-12-22)
4
14
 
5
15
  **Performance**: possible performance bump. Credit to @denislavski (Denislav Naydenov) for opening PR #235.
@@ -1,4 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
+ # frozen_string_literal: true
2
3
 
3
4
  module CombinePDF
4
5
  module_function
@@ -1,4 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
+ # frozen_string_literal: true
2
3
  ########################################################
3
4
  ## Thoughts from reading the ISO 32000-1:2008
4
5
  ## this file is part of the CombinePDF library and the code
@@ -1,4 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
+ # frozen_string_literal: true
2
3
  ########################################################
3
4
  ## Thoughts from reading the ISO 32000-1:2008
4
5
  ## this file is part of the CombinePDF library and the code
@@ -137,7 +138,7 @@ module CombinePDF
137
138
  object_key = @key.dup
138
139
  object_key << [encrypted_id].pack('i')[0..2]
139
140
  object_key << [encrypted_generation].pack('i')[0..1]
140
- object_key << 'sAlT'.force_encoding(Encoding::ASCII_8BIT)
141
+ object_key << 'sAlT'.b
141
142
  key_length = object_key.length < 16 ? object_key.length : 16
142
143
 
143
144
  begin
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CombinePDF
2
4
  class EncryptionError < StandardError
3
5
  end
@@ -1,4 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
+ # frozen_string_literal: true
2
3
  ########################################################
3
4
  ## Thoughts from reading the ISO 32000-1:2008
4
5
  ## this file is part of the CombinePDF library and the code
@@ -1,4 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
+ # frozen_string_literal: true
2
3
  ########################################################
3
4
  ## Thoughts from reading the ISO 32000-1:2008
4
5
  ## this file is part of the CombinePDF library and the code
@@ -1,4 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
+ # frozen_string_literal: true
2
3
  ########################################################
3
4
  ## Thoughts from reading the ISO 32000-1:2008
4
5
  ## this file is part of the CombinePDF library and the code
@@ -214,7 +215,7 @@ module CombinePDF
214
215
  options[:text_padding] = 0 if options[:text_padding].to_f >= 1
215
216
 
216
217
  # create box stream
217
- box_stream = ''
218
+ box_stream = +''
218
219
  # set graphic state for box
219
220
  if options[:box_color] || (options[:border_width].to_i > 0 && options[:border_color])
220
221
  # compute x and y position for text
@@ -290,7 +291,7 @@ module CombinePDF
290
291
  # reset x,y by text alignment - x,y are calculated from the bottom left
291
292
  # each unit (1) is 1/72 Inch
292
293
  # create text stream
293
- text_stream = ''
294
+ text_stream = +''
294
295
  if !text.to_s.empty? && options[:font_size] != 0 && (options[:font_color] || options[:stroke_color])
295
296
  # compute x and y position for text
296
297
  x = options[:x] + (options[:width] * options[:text_padding])
@@ -679,7 +680,7 @@ module CombinePDF
679
680
  insert_content 'Q'
680
681
 
681
682
  # Prep content
682
- @contents = ''
683
+ @contents = +''
683
684
  insert_content @contents
684
685
  @contents
685
686
  end
@@ -788,7 +789,7 @@ module CombinePDF
788
789
  # add to array
789
790
  if out.last.nil? || out.last[0] != fonts[i]
790
791
  out.last[1] << '>' unless out.last.nil?
791
- out << [fonts[i], '<', 0, 0]
792
+ out << [fonts[i], (+'<'), 0, 0]
792
793
  end
793
794
  out.last[1] << (fonts_array[i].cmap.nil? ? (c.unpack('H*')[0]) : fonts_array[i].cmap[c])
794
795
  if fonts_array[i].metrics[c]
@@ -262,7 +262,7 @@ module CombinePDF
262
262
  ##########################################
263
263
  elsif @scanner.scan(/\(/)
264
264
  # warn "Found a literal string"
265
- str = ''.force_encoding(Encoding::ASCII_8BIT)
265
+ str = ''.b
266
266
  count = 1
267
267
  while count > 0 && @scanner.rest?
268
268
  scn = @scanner.scan_until(/[\(\)]/)
@@ -369,7 +369,7 @@ module CombinePDF
369
369
  # the following was dicarded because some PDF files didn't have an EOL marker as required
370
370
  # str = @scanner.scan_until(/(\r\n|\r|\n)endstream/)
371
371
  # instead, a non-strict RegExp is used:
372
-
372
+
373
373
 
374
374
  # raise error if the stream doesn't end.
375
375
  unless @scanner.skip_until(/endstream/)
@@ -379,7 +379,7 @@ module CombinePDF
379
379
  length = 0 if(length < 0)
380
380
  length -= 1 if(@scanner.string[old_pos + length - 1] == "\n")
381
381
  length -= 1 if(@scanner.string[old_pos + length - 1] == "\r")
382
- str = (length > 0) ? @scanner.string.slice(old_pos, length) : ''
382
+ str = (length > 0) ? @scanner.string.slice(old_pos, length) : +''
383
383
 
384
384
  # warn "CombinePDF parser: detected Stream #{str.length} bytes long #{str[0..3]}...#{str[-4..-1]}"
385
385
 
@@ -632,17 +632,17 @@ module CombinePDF
632
632
  #
633
633
  def serialize_objects_and_references
634
634
  obj_dir = {}
635
- objid_cache = {}
635
+ objid_cache = {}.compare_by_identity
636
636
  # create a dictionary for referenced objects (no value resolution at this point)
637
637
  # at the same time, delete duplicates and old versions when objects have multiple versions
638
638
  @parsed.uniq!
639
639
  @parsed.length.times do |i|
640
640
  o = @parsed[i]
641
- objid_cache[o.object_id] = i
641
+ objid_cache[o] = i
642
642
  tmp_key = [o[:indirect_reference_id], o[:indirect_generation_number]]
643
643
  if tmp_found = obj_dir[tmp_key]
644
644
  tmp_found.clear
645
- @parsed[objid_cache[tmp_found.object_id]] = nil
645
+ @parsed[objid_cache[tmp_found]] = nil
646
646
  end
647
647
  obj_dir[tmp_key] = o
648
648
  end
@@ -765,9 +765,9 @@ module CombinePDF
765
765
  # end
766
766
 
767
767
  # # run block of code on evey PDF object (PDF objects are class Hash)
768
- # def each_object(object, limit_references = true, already_visited = {}, &block)
768
+ # def each_object(object, limit_references = true, already_visited = {}.compare_by_identity, &block)
769
769
  # unless limit_references
770
- # already_visited[object.object_id] = true
770
+ # already_visited[object] = true
771
771
  # end
772
772
  # case
773
773
  # when object.is_a?(Array)
@@ -776,7 +776,7 @@ module CombinePDF
776
776
  # yield(object)
777
777
  # unless limit_references && object[:is_reference_only]
778
778
  # object.each do |k,v|
779
- # each_object(v, limit_references, already_visited, &block) unless already_visited[v.object_id]
779
+ # each_object(v, limit_references, already_visited, &block) unless already_visited[v]
780
780
  # end
781
781
  # end
782
782
  # end
@@ -1,4 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
+ # frozen_string_literal: true
2
3
  ########################################################
3
4
  ## Thoughts from reading the ISO 32000-1:2008
4
5
  ## this file is part of the CombinePDF library and the code
@@ -21,19 +22,19 @@ module CombinePDF
21
22
  # this is used for internal operations, such as injectng data using the << operator.
22
23
  def add_referenced()
23
24
  # an existing object map
24
- resolved = {}.dup
25
- existing = {}.dup
26
- should_resolve = [].dup
25
+ resolved = {}.compare_by_identity
26
+ existing = {}
27
+ should_resolve = []
27
28
  #set all existing objects as resolved and register their children for future resolution
28
- @objects.each { |obj| existing[obj] = obj ; resolved[obj.object_id] = obj; should_resolve << obj.values}
29
+ @objects.each { |obj| existing[obj] = obj ; resolved[obj] = obj; should_resolve << obj.values}
29
30
  # loop until should_resolve is empty
30
31
  while should_resolve.any?
31
32
  obj = should_resolve.pop
32
- next if resolved[obj.object_id] # the object exists
33
+ next if resolved[obj] # the object exists
33
34
  if obj.is_a?(Hash)
34
35
  referenced = obj[:referenced_object]
35
36
  if referenced && referenced.any?
36
- tmp = resolved[referenced.object_id]
37
+ tmp = resolved[referenced]
37
38
  if !tmp && referenced[:raw_stream_content]
38
39
  tmp = existing[referenced[:raw_stream_content]]
39
40
  # Avoid endless recursion by limiting it to a number of layers (default == 2)
@@ -42,18 +43,18 @@ module CombinePDF
42
43
  if tmp
43
44
  obj[:referenced_object] = tmp
44
45
  else
45
- resolved[obj.object_id] = referenced
46
+ resolved[obj] = referenced
46
47
  # existing[referenced] = referenced
47
48
  existing[referenced[:raw_stream_content]] = referenced
48
49
  should_resolve << referenced
49
50
  @objects << referenced
50
51
  end
51
52
  else
52
- resolved[obj.object_id] = obj
53
- obj.keys.each { |k| should_resolve << obj[k] unless !obj[k].is_a?(Enumerable) || resolved[obj[k].object_id] }
53
+ resolved[obj] = obj
54
+ obj.keys.each { |k| should_resolve << obj[k] unless !obj[k].is_a?(Enumerable) || resolved[obj[k]] }
54
55
  end
55
56
  elsif obj.is_a?(Array)
56
- resolved[obj.object_id] = obj
57
+ resolved[obj] = obj
57
58
  should_resolve.concat obj
58
59
  end
59
60
  end
@@ -78,14 +79,14 @@ module CombinePDF
78
79
  page_list.concat(with_pages) unless with_pages.empty?
79
80
 
80
81
  # duplicate any non-unique pages - This is a special case to resolve Adobe Acrobat Reader issues (see issues #19 and #81)
81
- uniqueness = {}.dup
82
- page_list.each { |page| page = page[:referenced_object] || page; page = page.dup if uniqueness[page.object_id]; uniqueness[page.object_id] = page }
82
+ uniqueness = {}.compare_by_identity
83
+ page_list.each { |page| page = page[:referenced_object] || page; page = page.dup if uniqueness[page]; uniqueness[page] = page }
83
84
  page_list.clear
84
85
  page_list = uniqueness.values
85
86
  uniqueness.clear
86
87
 
87
88
  # build new Pages object
88
- page_object_kids = [].dup
89
+ page_object_kids = []
89
90
  pages_object = { Type: :Pages, Count: page_list.length, Kids: page_object_kids }
90
91
  pages_object_reference = { referenced_object: pages_object, is_reference_only: true }
91
92
  page_list.each { |pg| pg[:Parent] = pages_object_reference; page_object_kids << ({ referenced_object: pg, is_reference_only: true }) }
@@ -186,17 +187,18 @@ module CombinePDF
186
187
  POSSIBLE_NAME_TREES = [:Dests, :AP, :Pages, :IDS, :Templates, :URLS, :JavaScript, :EmbeddedFiles, :AlternatePresentations, :Renditions].to_set.freeze
187
188
 
188
189
  def rebuild_names(name_tree = nil, base = 'CombinePDF_0000000')
190
+ base = +base
189
191
  if name_tree
190
192
  return nil unless name_tree.is_a?(Hash)
191
193
  name_tree = name_tree[:referenced_object] || name_tree
192
194
  dic = []
193
195
  # map a names tree and return a valid name tree. Do not recourse.
194
196
  should_resolve = [name_tree[:Kids], name_tree[:Names]]
195
- resolved = [].to_set
197
+ resolved = Set.new.compare_by_identity
196
198
  while should_resolve.any?
197
199
  pos = should_resolve.pop
198
200
  if pos.is_a? Array
199
- next if resolved.include?(pos.object_id)
201
+ next if resolved.include?(pos)
200
202
  if pos[0].is_a? String
201
203
  (pos.length / 2).times do |i|
202
204
  dic << (pos[i * 2].clear << base.next!)
@@ -209,16 +211,16 @@ module CombinePDF
209
211
  end
210
212
  elsif pos.is_a? Hash
211
213
  pos = pos[:referenced_object] || pos
212
- next if resolved.include?(pos.object_id)
214
+ next if resolved.include?(pos)
213
215
  should_resolve << pos[:Kids] if pos[:Kids]
214
216
  should_resolve << pos[:Names] if pos[:Names]
215
217
  end
216
- resolved << pos.object_id
218
+ resolved << pos
217
219
  end
218
220
  return { referenced_object: { Names: dic }, is_reference_only: true }
219
221
  end
220
222
  @names ||= @names[:referenced_object]
221
- new_names = { Type: :Names }.dup
223
+ new_names = { Type: :Names }
222
224
  POSSIBLE_NAME_TREES.each do |ntree|
223
225
  if @names[ntree]
224
226
  new_names[ntree] = rebuild_names(@names[ntree], base)
@@ -373,7 +375,7 @@ module CombinePDF
373
375
  private
374
376
 
375
377
  def equal_layers obj1, obj2, layer = CombinePDF.eq_depth_limit
376
- return true if obj1.object_id == obj2.object_id
378
+ return true if obj1.equal?(obj2)
377
379
  if obj1.is_a? Hash
378
380
  return false unless obj2.is_a? Hash
379
381
  return false unless obj1.length == obj2.length
@@ -1,5 +1,6 @@
1
1
  # -*- encoding : utf-8 -*-
2
- ########################################################
2
+ ## frozen_string_literal: true
3
+ #######################################################
3
4
  ## Thoughts from reading the ISO 32000-1:2008
4
5
  ## this file is part of the CombinePDF library and the code
5
6
  ## is subject to the same license.
@@ -93,7 +94,7 @@ module CombinePDF
93
94
  @version = 0
94
95
  @viewer_preferences = {}
95
96
  @info = {}
96
- parser ||= PDFParser.new('')
97
+ parser ||= PDFParser.new(+'')
97
98
  raise TypeError, "initialization error, expecting CombinePDF::PDFParser or nil, but got #{parser.class.name}" unless parser.is_a? PDFParser
98
99
  @objects = parser.parse
99
100
 
@@ -216,7 +217,7 @@ module CombinePDF
216
217
  # when finished, remove the numbering system and keep only pointers
217
218
  remove_old_ids
218
219
  # output the pdf stream
219
- out.join("\n".force_encoding(Encoding::ASCII_8BIT)).force_encoding(Encoding::ASCII_8BIT)
220
+ out.join("\n".b).force_encoding(Encoding::ASCII_8BIT)
220
221
  end
221
222
 
222
223
  # this method returns all the pages cataloged in the catalog.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module CombinePDF
2
3
  ################################################################
3
4
  ## These are common functions, used within the different classes
@@ -123,12 +124,12 @@ module CombinePDF
123
124
  # if the object is not a simple object, it is a dictionary
124
125
  # A dictionary shall be written as a sequence of key-value pairs enclosed in double angle brackets (<<...>>)
125
126
  # (using LESS-THAN SIGNs (3Ch) and GREATER-THAN SIGNs (3Eh)).
126
- out << "<<\n".force_encoding(Encoding::ASCII_8BIT)
127
+ out << "<<\n".b
127
128
  object.each do |key, value|
128
129
  out << "#{object_to_pdf key} #{object_to_pdf value}\n".force_encoding(Encoding::ASCII_8BIT) unless PDF::PRIVATE_HASH_KEYS.include? key
129
130
  end
130
131
  object.delete :Length
131
- out << '>>'.force_encoding(Encoding::ASCII_8BIT)
132
+ out << '>>'.b
132
133
  out << "\nstream\n#{object[:raw_stream_content]}\nendstream".force_encoding(Encoding::ASCII_8BIT) if object[:raw_stream_content]
133
134
  out << "\nendobj\n" if object[:indirect_reference_id]
134
135
  out.join.force_encoding(Encoding::ASCII_8BIT)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CombinePDF
2
- VERSION = '1.0.26'.freeze
4
+ VERSION = '1.0.28'
3
5
  end
data/lib/combine_pdf.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'zlib'
4
5
  require 'securerandom'
@@ -10,21 +11,21 @@ require 'digest'
10
11
  # require the RC4 Gem
11
12
  require 'rc4'
12
13
 
13
- load 'combine_pdf/api.rb'
14
- load 'combine_pdf/renderer.rb'
15
- load 'combine_pdf/page_methods.rb'
16
- load 'combine_pdf/basic_writer.rb'
17
- load 'combine_pdf/decrypt.rb'
18
- load 'combine_pdf/fonts.rb'
19
- load 'combine_pdf/filter.rb'
20
- load 'combine_pdf/parser.rb'
21
- load 'combine_pdf/pdf_public.rb'
22
- load 'combine_pdf/pdf_protected.rb'
23
- load 'combine_pdf/exceptions.rb'
14
+ require 'combine_pdf/api'
15
+ require 'combine_pdf/renderer'
16
+ require 'combine_pdf/page_methods'
17
+ require 'combine_pdf/basic_writer'
18
+ require 'combine_pdf/decrypt'
19
+ require 'combine_pdf/fonts'
20
+ require 'combine_pdf/filter'
21
+ require 'combine_pdf/parser'
22
+ require 'combine_pdf/pdf_public'
23
+ require 'combine_pdf/pdf_protected'
24
+ require 'combine_pdf/exceptions'
24
25
 
25
- # load "combine_pdf/operations.rb"
26
+ # require 'combine_pdf/operations'
26
27
 
27
- load 'combine_pdf/version.rb'
28
+ require 'combine_pdf/version'
28
29
 
29
30
  # This is a pure ruby library to combine/merge, stmap/overlay and number PDF files - as well as to create tables (ment for indexing combined files).
30
31
  #
@@ -12,7 +12,7 @@ class CombinePDFRendererTest < Minitest::Test
12
12
 
13
13
  def test_numeric_array_to_pdf
14
14
  input = [1.234567, 0.000054, 5, -0.000099]
15
- expected = "[1.234567 0.000054 5 -0.000099]".force_encoding('BINARY')
15
+ expected = "[1.234567 0.000054 5 -0.000099]".b
16
16
  actual = TestRenderer.new.test_object(input)
17
17
 
18
18
  assert_equal(expected, actual)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: combine_pdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.26
4
+ version: 1.0.28
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-22 00:00:00.000000000 Z
11
+ date: 2024-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-rc4