hexapdf 0.11.3 → 0.11.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: bd20872b69a7358f9bef26a12e1ea57368c3305d
4
- data.tar.gz: 1d107e0db8ec876d24ea19d7f75e3c7229ca284c
2
+ SHA256:
3
+ metadata.gz: baa354ef4d01aa8a9348cfb584d9e255ee253c04b0f927ea16361c45ca904d46
4
+ data.tar.gz: 2be95e4cd431bf772815ce4788f7ca25b132de2faec665bbdaf0982f73fea489
5
5
  SHA512:
6
- metadata.gz: 64085653fc25ae248aabd54bc71250ab06f6d533657fe9d0803581b1f555f2858ee3602afcea74904755c290ada68c3cf4c4feb303623606febecdc34579bc7f
7
- data.tar.gz: d8c8ab19a87badc8a732984d914b65c6cd7aa0dbbbcb8e1bc64339a13dcb4be0a1d33f641bba90b380273cb3faf6e188c979b44df473bd2f952196f40619779f
6
+ metadata.gz: 3e1bf0748678d022163457de1df628e080f7df261e5cb01ac09bae7f8560f05477f901a5e7b17c04111aea958458e0c0ff3c8d3beeda7119ddcd2913e906915b
7
+ data.tar.gz: 792ebec34b3f1010ae53867b2e4cce93bb2b472f504606a87f0f8fe651d8cae94c8d4bb99b69e972e9813955a76d9401319dbbb01084b67ea352d210d2656b73
@@ -1,3 +1,54 @@
1
+ ## 0.11.8 - 2020-06-11
2
+
3
+ ### Fixed
4
+
5
+ * Serialization of special `/` (zero-length name) object in dictionaries and
6
+ arrays
7
+
8
+
9
+ ## 0.11.7 - 2020-06-10
10
+
11
+ ### Fixed
12
+
13
+ * Deletion of object streams in [HexaPDF::Task::Optimize] to avoid accessing
14
+ then invalid object streams
15
+ * [HexaPDF::Task::Optimize] to work correctly when deleting object streams and
16
+ generating xref streams
17
+
18
+
19
+ ## 0.11.6 - 2020-05-27
20
+
21
+ ### Fixed
22
+
23
+ * [HexaPDF::Layout::TextBox] to respect the set width and height when fitting
24
+ and splitting the box
25
+
26
+
27
+ ## 0.11.5 - 2020-01-27
28
+
29
+ ### Changed
30
+
31
+ * [HexaPDF::Font::TrueType::Table::CmapSubtable] to lazily parse the subtable
32
+ * [HexaPDF::Font::TrueType::Table::Hmtx] to lazily parse the width data
33
+ * CLI command `hexapdf image2pdf` to use the last argument as output file
34
+ instead of the first (same order as `merge`)
35
+ * Automatically require the HexaPDF C extension if it is installed
36
+
37
+ ### Fixed
38
+
39
+ * Wrong line length calculation for variable width layouting when a text box is
40
+ too wide and needs to be broken into parts
41
+ * CLI command `hexapdf image2pdf` so that treating a PDF as image works
42
+
43
+
44
+ ## 0.11.4 - 2019-12-28
45
+
46
+ ### Fixed
47
+
48
+ * Memory consumption problem of PNG image loader when using images with alpha
49
+ channel
50
+
51
+
1
52
  ## 0.11.3 - 2019-11-27
2
53
 
3
54
  ### Fixed
@@ -99,15 +99,15 @@ module HexaPDF
99
99
  @margins = [0, 0, 0, 0]
100
100
  end
101
101
 
102
- def execute(out_file, *images) #:nodoc:
102
+ def execute(*images, out_file) #:nodoc:
103
103
  maybe_raise_on_existing_file(out_file)
104
104
 
105
105
  out = HexaPDF::Document.new
106
106
 
107
107
  images.each do |image_file|
108
108
  image = out.images.add(image_file)
109
- iw = image.info.width.to_f
110
- ih = image.info.height.to_f
109
+ iw = image.width.to_f
110
+ ih = image.height.to_f
111
111
  if @scale != :fit
112
112
  iw *= 72 / @scale
113
113
  ih *= 72 / @scale
@@ -52,6 +52,11 @@ require 'hexapdf/image_loader'
52
52
  require 'hexapdf/font_loader'
53
53
  require 'hexapdf/layout'
54
54
 
55
+ begin
56
+ require 'hexapdf/cext'
57
+ rescue LoadError
58
+ end
59
+
55
60
  # == HexaPDF API Documentation
56
61
  #
57
62
  # Here are some pointers to more in depth information:
@@ -107,6 +107,8 @@ module HexaPDF
107
107
  # Deletes the given page object from the document's page tree (but *not* from the document).
108
108
  #
109
109
  # Returns the page object, or +nil+ if the page object was not in the page tree.
110
+ #
111
+ # Also see: HexaPDF::Type::PageTreeNode#delete_page
110
112
  def delete(page)
111
113
  @document.catalog.pages.delete_page(page)
112
114
  end
@@ -118,6 +120,8 @@ module HexaPDF
118
120
  # document).
119
121
  #
120
122
  # Returns the page object, or +nil+ if the index was invalid.
123
+ #
124
+ # Also see: HexaPDF::Type::PageTreeNode#delete_page
121
125
  def delete_at(index)
122
126
  @document.catalog.pages.delete_page(index)
123
127
  end
@@ -73,9 +73,14 @@ module HexaPDF
73
73
  attr_accessor :language
74
74
 
75
75
  # The complete code map.
76
+ #
77
+ # Is only fully initialized for existing fonts when a mapping is first accessed via #[].
76
78
  attr_accessor :code_map
77
79
 
78
80
  # The complete gid map.
81
+ #
82
+ # Is only fully initialized for existing fonts when a mapping is first accessed via
83
+ # #gid_to_code.
79
84
  attr_accessor :gid_map
80
85
 
81
86
  # Creates a new subtable.
@@ -127,7 +132,22 @@ module HexaPDF
127
132
  elsif [0, 2, 4, 6].include?(@format)
128
133
  length, @language = io.read(4).unpack('n2')
129
134
  end
130
- supported = true
135
+
136
+ return false unless [0, 2, 4, 6, 10, 12].include?(@format)
137
+ offset = io.pos
138
+ @code_map = lambda do |code|
139
+ parse_mapping(io, offset, length)
140
+ @code_map[code]
141
+ end
142
+ @gid_map = lambda do |gid|
143
+ parse_mapping(io, offset, length)
144
+ @gid_map[gid]
145
+ end
146
+ true
147
+ end
148
+
149
+ def parse_mapping(io, offset, length)
150
+ io.pos = offset
131
151
  @code_map, @gid_map = case @format
132
152
  when 0 then Format0.parse(io, length)
133
153
  when 2 then Format2.parse(io, length)
@@ -135,12 +155,9 @@ module HexaPDF
135
155
  when 6 then Format6.parse(io, length)
136
156
  when 10 then Format10.parse(io, length)
137
157
  when 12 then Format12.parse(io, length)
138
- else
139
- supported = false
140
- [{}, {}]
141
158
  end
142
- supported
143
159
  end
160
+ private :parse_mapping
144
161
 
145
162
  def inspect #:nodoc:
146
163
  "#<#{self.class.name} (#{platform_id}, #{encoding_id}, #{language}, " \
@@ -51,7 +51,7 @@ module HexaPDF
51
51
  # the :left_side_bearing.
52
52
  Metric = Struct.new(:advance_width, :left_side_bearing)
53
53
 
54
- # An array of Metric objects, one for each glyph in the font.
54
+ # A hash of glyph ID to Metric objects mapping.
55
55
  attr_accessor :horizontal_metrics
56
56
 
57
57
  # Returns the Metric object for the give glyph ID.
@@ -63,10 +63,20 @@ module HexaPDF
63
63
 
64
64
  def parse_table #:nodoc:
65
65
  nr_entries = font[:hhea].num_of_long_hor_metrics
66
- @horizontal_metrics = Array.new(nr_entries) { Metric.new(*read_formatted(4, 'ns>')) }
67
- last_advance_width = @horizontal_metrics[-1].advance_width
68
- read_formatted(directory_entry.length - 4 * nr_entries, 's>*').map do |lsb|
69
- @horizontal_metrics << Metric.new(last_advance_width, lsb)
66
+ max_id = nr_entries + (directory_entry.length - 4 * nr_entries) / 2
67
+ @horizontal_metrics = Hash.new do |hash, glyph_id|
68
+ return nil if glyph_id >= max_id
69
+ if glyph_id >= nr_entries
70
+ with_io_pos(directory_entry.offset + 4 * nr_entries + (glyph_id - nr_entries) * 2) do
71
+ hash[glyph_id] = Metric.new(@horizontal_metrics[nr_entries - 1].advance_width,
72
+ *read_formatted(2, 's>'))
73
+ end
74
+ else
75
+ with_io_pos(directory_entry.offset + 4 * glyph_id) do
76
+ hash[glyph_id] = Metric.new(*read_formatted(4, 'ns>'))
77
+ end
78
+ end
79
+ hash[glyph_id]
70
80
  end
71
81
  end
72
82
 
@@ -361,12 +361,12 @@ module HexaPDF
361
361
  image_data << data.getbyte(0)
362
362
  mask_data << data.getbyte(0)
363
363
  while i < bytes_per_row
364
- image_data << data.byteslice(i, bytes_per_colors)
364
+ bytes_per_colors.times {|j| image_data << data.getbyte(i + j) }
365
365
  i += bytes_per_colors
366
- mask_data << data.byteslice(i, bytes_per_alpha)
366
+ bytes_per_alpha.times {|j| mask_data << data.getbyte(i + j) }
367
367
  i += bytes_per_alpha
368
368
  end
369
- data[0, bytes_per_row] = ''
369
+ data = data[bytes_per_row..-1]
370
370
  end
371
371
  end
372
372
 
@@ -64,6 +64,9 @@ module HexaPDF
64
64
  #
65
65
  # Also see TextLayouter#style for other style properties taken into account.
66
66
  def fit(available_width, available_height, frame)
67
+ return false if (@initial_width > 0 && @initial_width > available_width) ||
68
+ (@initial_height > 0 && @initial_height > available_height)
69
+
67
70
  @width = @height = 0
68
71
  @result = if style.position == :flow
69
72
  @tl.fit(@items, frame.width_specification, frame.contour_line.bbox.height)
@@ -74,8 +77,8 @@ module HexaPDF
74
77
  height = (@initial_height > 0 ? @initial_height : available_height) - @height
75
78
  @tl.fit(@items, width, height)
76
79
  end
77
- @width += @result.lines.max_by(&:width)&.width || 0
78
- @height += @result.height
80
+ @width += (@initial_width > 0 ? width : @result.lines.max_by(&:width)&.width || 0)
81
+ @height += (@initial_height > 0 ? height : @result.height)
79
82
  if style.last_line_gap && @result.lines.last
80
83
  @height += style.line_spacing.gap(@result.lines.last, @result.lines.last)
81
84
  end
@@ -86,7 +89,9 @@ module HexaPDF
86
89
  # Splits the text box into two boxes if necessary and possible.
87
90
  def split(available_width, available_height, frame)
88
91
  fit(available_width, available_height, frame) unless @result
89
- if @result.remaining_items.empty?
92
+ if @width > available_width || @height > available_height
93
+ [nil, self]
94
+ elsif @result.remaining_items.empty?
90
95
  [self]
91
96
  elsif @result.lines.empty?
92
97
  [nil, self]
@@ -751,6 +751,7 @@ module HexaPDF
751
751
 
752
752
  while true
753
753
  too_wide_box = nil
754
+ line_height = 0
754
755
 
755
756
  rest = style.text_line_wrapping_algorithm.call(rest, width_block) do |line, item|
756
757
  # make sure empty lines broken by mandatory paragraph breaks are not empty
@@ -187,7 +187,7 @@ module HexaPDF
187
187
  begin
188
188
  str = obj.to_s.dup.force_encoding(Encoding::BINARY)
189
189
  str.gsub!(NAME_REGEXP, NAME_SUBSTS)
190
- "/#{str}"
190
+ str.empty? ? "/ " : "/#{str}"
191
191
  end
192
192
  end
193
193
 
@@ -127,13 +127,18 @@ module HexaPDF
127
127
  when :delete
128
128
  doc.revisions.each_with_index do |rev, rev_index|
129
129
  xref_stream = false
130
+ objects_to_delete = []
130
131
  rev.each do |obj|
131
- if obj.type == :ObjStm || (obj.type == :XRef && xref_streams == :delete)
132
- rev.delete(obj)
132
+ if obj.type == :ObjStm
133
+ objects_to_delete << obj
134
+ elsif obj.type == :XRef
135
+ xref_stream = true
136
+ objects_to_delete << obj if xref_streams == :delete
133
137
  else
134
138
  delete_fields_with_defaults(obj)
135
139
  end
136
140
  end
141
+ objects_to_delete.each {|obj| rev.delete(obj) }
137
142
  if xref_streams == :generate && !xref_stream
138
143
  doc.add({Type: :XRef}, revision: rev_index)
139
144
  end
@@ -143,11 +148,12 @@ module HexaPDF
143
148
  xref_stream = false
144
149
  count = 0
145
150
  objstms = [doc.wrap({Type: :ObjStm})]
151
+ old_objstms = []
146
152
  rev.each do |obj|
147
153
  if obj.type == :XRef
148
154
  xref_stream = true
149
155
  elsif obj.type == :ObjStm
150
- rev.delete(obj)
156
+ old_objstms << obj
151
157
  end
152
158
  delete_fields_with_defaults(obj)
153
159
 
@@ -160,6 +166,7 @@ module HexaPDF
160
166
  count = 0
161
167
  end
162
168
  end
169
+ old_objstms.each {|objstm| rev.delete(objstm) }
163
170
  objstms.each {|objstm| doc.add(objstm, revision: rev_index) }
164
171
  doc.add({Type: :XRef}, revision: rev_index) unless xref_stream
165
172
  end
@@ -37,6 +37,6 @@
37
37
  module HexaPDF
38
38
 
39
39
  # The version of HexaPDF.
40
- VERSION = '0.11.3'
40
+ VERSION = '0.11.8'
41
41
 
42
42
  end
@@ -43,14 +43,14 @@ describe HexaPDF::Font::TrueType::Table::CmapSubtable do
43
43
 
44
44
  it "works for format 0" do
45
45
  t = table([0, 262, 0].pack('n3') + [255].pack('C*') + (0..254).to_a.pack('C*'))
46
+ assert_equal(0, t.gid_to_code(255))
47
+ assert_equal(234, t.gid_to_code(233))
48
+
46
49
  assert_equal(255, t[0])
47
50
  assert_equal(233, t[234])
48
51
  assert_nil(t[256])
49
52
 
50
- assert_equal(0, t.gid_to_code(255))
51
- assert_equal(234, t.gid_to_code(233))
52
-
53
- assert_raises(HexaPDF::Error) { table([0, 20, 0].pack('n3') + "a" * 20) }
53
+ assert_raises(HexaPDF::Error) { table([0, 20, 0].pack('n3') + "a" * 20)[0] }
54
54
  end
55
55
 
56
56
  it "works for format 2" do
@@ -5,7 +5,7 @@ require_relative 'common'
5
5
  require 'hexapdf/font/true_type/table/hhea'
6
6
  require 'hexapdf/font/true_type/table/hmtx'
7
7
 
8
- describe HexaPDF::Font::TrueType::Table::Hhea do
8
+ describe HexaPDF::Font::TrueType::Table::Hmtx do
9
9
  before do
10
10
  data = [1, -2, 3, -4, 5, -6].pack('ns>ns>s>2')
11
11
  set_up_stub_true_type_font(data)
@@ -17,14 +17,14 @@ describe HexaPDF::Font::TrueType::Table::Hhea do
17
17
  describe "initialize" do
18
18
  it "reads the data from the associated file" do
19
19
  table = create_table(:Hmtx)
20
- assert_equal(1, table[0].advance_width)
21
- assert_equal(-2, table[0].left_side_bearing)
22
- assert_equal(3, table[1].advance_width)
23
- assert_equal(-4, table[1].left_side_bearing)
24
20
  assert_equal(3, table[2].advance_width)
25
21
  assert_equal(5, table[2].left_side_bearing)
26
22
  assert_equal(3, table[3].advance_width)
27
23
  assert_equal(-6, table[3].left_side_bearing)
24
+ assert_equal(1, table[0].advance_width)
25
+ assert_equal(-2, table[0].left_side_bearing)
26
+ assert_equal(3, table[1].advance_width)
27
+ assert_equal(-4, table[1].left_side_bearing)
28
28
  end
29
29
  end
30
30
  end
@@ -31,11 +31,11 @@ describe HexaPDF::Layout::TextBox do
31
31
  end
32
32
 
33
33
  it "respects the set width and height" do
34
- box = create_box([@inline_box] * 5, width: 40, height: 50, style: {padding: 10})
34
+ box = create_box([@inline_box], width: 40, height: 50, style: {padding: 10})
35
35
  assert(box.fit(100, 100, @frame))
36
36
  assert_equal(40, box.width)
37
37
  assert_equal(50, box.height)
38
- assert_equal([20, 20, 10], box.instance_variable_get(:@result).lines.map(&:width))
38
+ assert_equal([10], box.instance_variable_get(:@result).lines.map(&:width))
39
39
  end
40
40
 
41
41
  it "fits into the frame's outline" do
@@ -52,6 +52,16 @@ describe HexaPDF::Layout::TextBox do
52
52
  assert_equal(50, box.width)
53
53
  assert_equal(20, box.height)
54
54
  end
55
+
56
+ it "can't fit the text box if the set width is bigger than the available width" do
57
+ box = create_box([@inline_box], width: 101)
58
+ refute(box.fit(100, 100, @frame))
59
+ end
60
+
61
+ it "can't fit the text box if the set height is bigger than the available height" do
62
+ box = create_box([@inline_box], height: 101)
63
+ refute(box.fit(100, 100, @frame))
64
+ end
55
65
  end
56
66
 
57
67
  describe "split" do
@@ -70,6 +80,14 @@ describe HexaPDF::Layout::TextBox do
70
80
  assert_equal([nil, box], box.split(5, 20, @frame))
71
81
  end
72
82
 
83
+ it "works if the whole text box doesn't fits" do
84
+ box = create_box([@inline_box], width: 102)
85
+ assert_equal([nil, box], box.split(100, 100, @frame))
86
+
87
+ box = create_box([@inline_box], height: 102)
88
+ assert_equal([nil, box], box.split(100, 100, @frame))
89
+ end
90
+
73
91
  it "splits the box if necessary" do
74
92
  box = create_box([@inline_box] * 10)
75
93
  boxes = box.split(50, 10, @frame)
@@ -556,18 +556,37 @@ describe HexaPDF::Layout::TextLayouter do
556
556
  end
557
557
  end
558
558
 
559
- it "breaks a text fragment into parts if it is wider than the available width" do
560
- str = " Thisisaverylongstring"
561
- frag = HexaPDF::Layout::TextFragment.create(str, font: @font)
562
- result = @layouter.fit([frag], 20, 100)
563
- assert(result.remaining_items.empty?)
564
- assert_equal(:success, result.status)
565
- assert_equal(str.strip.length, result.lines.sum {|l| l.items.sum {|i| i.items.count } })
566
- assert_equal(45, result.height)
559
+ describe "breaks a text fragment into parts if it is wider than the available width" do
560
+ before do
561
+ @str = " This is averylongstring"
562
+ @frag = HexaPDF::Layout::TextFragment.create(@str, font: @font)
563
+ end
567
564
 
568
- result = @layouter.fit([frag], 1, 100)
569
- assert_equal(str.strip.length, result.remaining_items.count)
570
- assert_equal(:box_too_wide, result.status)
565
+ it "works with fixed width" do
566
+ result = @layouter.fit([@frag], 20, 100)
567
+ assert(result.remaining_items.empty?)
568
+ assert_equal(:success, result.status)
569
+ assert_equal(@str.delete(" ").length, result.lines.sum {|l| l.items.sum {|i| i.items.count } })
570
+ assert_equal(54, result.height)
571
+
572
+ result = @layouter.fit([@frag], 1, 100)
573
+ assert_equal(8, result.remaining_items.count)
574
+ assert_equal(:box_too_wide, result.status)
575
+ end
576
+
577
+ it "works with variable width" do
578
+ width_block = lambda do |height, line_height|
579
+ # 'averylongstring' would fit when only considering height but not height + line_height
580
+ if height + line_height < 15
581
+ 63
582
+ else
583
+ 10
584
+ end
585
+ end
586
+ result = @layouter.fit([@frag], width_block, 30)
587
+ assert_equal(:height, result.status)
588
+ assert_equal([26.95, 9.44, 7.77], result.lines.map {|l| l.width.round(3) })
589
+ end
571
590
  end
572
591
 
573
592
  describe "horizontal alignment" do
@@ -7,13 +7,15 @@ require 'hexapdf/task/optimize'
7
7
  describe HexaPDF::Task::Optimize do
8
8
  class TestType < HexaPDF::Dictionary
9
9
 
10
+ define_type :Test
10
11
  define_field :Optional, type: Symbol, default: :Optional
11
12
 
12
13
  end
13
14
 
14
15
  before do
16
+ HexaPDF::GlobalConfiguration['object.type_map'][:Test] = TestType
15
17
  @doc = HexaPDF::Document.new
16
- @obj1 = @doc.add(@doc.wrap({Optional: :Optional}, type: TestType))
18
+ @obj1 = @doc.add({Type: :Test, Optional: :Optional})
17
19
  @doc.trailer[:Test] = @doc.wrap(@obj1)
18
20
  @doc.revisions.add
19
21
  @obj2 = @doc.add({Type: :UsedEntry})
@@ -22,6 +24,10 @@ describe HexaPDF::Task::Optimize do
22
24
  @obj1[:Test] = @doc.wrap(@obj4, type: TestType)
23
25
  end
24
26
 
27
+ after do
28
+ HexaPDF::GlobalConfiguration['object.type_map'].delete(:Test)
29
+ end
30
+
25
31
  def assert_objstms_generated
26
32
  assert(@doc.revisions.all? {|rev| rev.any? {|obj| obj.type == :ObjStm } })
27
33
  assert(@doc.revisions.all? {|rev| rev.any? {|obj| obj.type == :XRef } })
@@ -40,7 +46,7 @@ describe HexaPDF::Task::Optimize do
40
46
  end
41
47
 
42
48
  def assert_default_deleted
43
- refute(@obj1.value.key?(:Optional))
49
+ refute(@doc.object(1).key?(:Optional))
44
50
  end
45
51
 
46
52
  describe "compact" do
@@ -84,21 +90,29 @@ describe HexaPDF::Task::Optimize do
84
90
  end
85
91
 
86
92
  describe "object_streams" do
87
- it "generates object streams" do
93
+ def reload_document_with_objstm_from_io
94
+ io = StringIO.new
88
95
  objstm = @doc.add({Type: :ObjStm})
89
- xref = @doc.add({Type: :XRef})
96
+ @doc.add({Type: :XRef})
97
+ objstm.add_object(@doc.add({Type: :Test}))
98
+ @doc.write(io)
99
+ io.rewind
100
+ @doc = HexaPDF::Document.new(io: io)
101
+ end
102
+
103
+ it "generates object streams" do
90
104
  210.times { @doc.add(5) }
105
+ objstm = @doc.add({Type: :ObjStm})
106
+ reload_document_with_objstm_from_io
91
107
  @doc.task(:optimize, object_streams: :generate)
92
108
  assert_objstms_generated
93
109
  assert_default_deleted
94
110
  assert_nil(@doc.object(objstm).value)
95
- assert(3, @doc.revisions.current.find_all {|obj| obj.type == :ObjStm }.size)
96
- assert([xref], @doc.revisions.current.find_all {|obj| obj.type == :XRef })
111
+ assert_equal(2, @doc.revisions.current.find_all {|obj| obj.type == :ObjStm }.size)
97
112
  end
98
113
 
99
114
  it "deletes object and xref streams" do
100
- @doc.add({Type: :ObjStm})
101
- @doc.add({Type: :XRef})
115
+ reload_document_with_objstm_from_io
102
116
  @doc.task(:optimize, object_streams: :delete, xref_streams: :delete)
103
117
  assert_no_objstms
104
118
  assert_no_xrefstms
@@ -107,9 +121,11 @@ describe HexaPDF::Task::Optimize do
107
121
 
108
122
  it "deletes object and generates xref streams" do
109
123
  @doc.add({Type: :ObjStm})
124
+ xref = @doc.add({Type: :XRef})
110
125
  @doc.task(:optimize, object_streams: :delete, xref_streams: :generate)
111
126
  assert_no_objstms
112
127
  assert_xrefstms_generated
128
+ assert_equal([xref], @doc.revisions.current.find_all {|obj| obj.type == :XRef })
113
129
  assert_default_deleted
114
130
  end
115
131
  end
@@ -75,18 +75,18 @@ describe HexaPDF::Serializer do
75
75
  assert_serialized('/lime#20Green', 'lime Green'.intern)
76
76
  assert_serialized('/paired#28#29parentheses', 'paired()parentheses'.intern)
77
77
  assert_serialized('/The_Key_of_F#23_Minor', 'The_Key_of_F#_Minor'.intern)
78
- assert_serialized('/', ''.intern)
78
+ assert_serialized('/ ', ''.intern)
79
79
  assert_serialized('/H#c3#b6#c3#9fgang', "Hößgang".intern)
80
80
  assert_serialized('/H#e8lp', "H\xE8lp".force_encoding('BINARY').intern)
81
81
  end
82
82
 
83
83
  it "serializes arrays" do
84
- assert_serialized("[-12 2.4321/Name true(345)true]", [-12, 2.4321, :Name, true, '345', true])
84
+ assert_serialized("[-12/ 2.4321/Name true(345)true]", [-12, :"", 2.4321, :Name, true, '345', true])
85
85
  assert_serialized("[]", [])
86
86
  end
87
87
 
88
88
  it "serializes hashes" do
89
- assert_serialized("<</hallo 5/other true/name[5]>>", hallo: 5, other: true, name: [5])
89
+ assert_serialized("<</hallo 5/ true/other true/name[5]>>", hallo: 5, "": true, other: true, name: [5])
90
90
  assert_serialized("<<>>", {})
91
91
  end
92
92
 
@@ -40,7 +40,7 @@ describe HexaPDF::Writer do
40
40
  219
41
41
  %%EOF
42
42
  3 0 obj
43
- <</Producer(HexaPDF version 0.11.3)>>
43
+ <</Producer(HexaPDF version 0.11.8)>>
44
44
  endobj
45
45
  xref
46
46
  3 1
@@ -72,7 +72,7 @@ describe HexaPDF::Writer do
72
72
  141
73
73
  %%EOF
74
74
  6 0 obj
75
- <</Producer(HexaPDF version 0.11.3)>>
75
+ <</Producer(HexaPDF version 0.11.8)>>
76
76
  endobj
77
77
  2 0 obj
78
78
  <</Length 10>>stream
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hexapdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.3
4
+ version: 0.11.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Leitner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-27 00:00:00.000000000 Z
11
+ date: 2020-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmdparse
@@ -102,11 +102,9 @@ extensions: []
102
102
  extra_rdoc_files: []
103
103
  files:
104
104
  - CHANGELOG.md
105
- - CONTRIBUTERS
106
105
  - LICENSE
107
106
  - README.md
108
107
  - Rakefile
109
- - VERSION
110
108
  - agpl-3.0.txt
111
109
  - bin/hexapdf
112
110
  - data/hexapdf/afm/Courier-Bold.afm
@@ -401,7 +399,6 @@ files:
401
399
  - lib/hexapdf/version.rb
402
400
  - lib/hexapdf/writer.rb
403
401
  - lib/hexapdf/xref_section.rb
404
- - man/man1/hexapdf.1
405
402
  - test/data/aes-test-vectors/CBCGFSbox-128-decrypt.data.gz
406
403
  - test/data/aes-test-vectors/CBCGFSbox-128-encrypt.data.gz
407
404
  - test/data/aes-test-vectors/CBCGFSbox-192-decrypt.data.gz
@@ -637,8 +634,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
637
634
  - !ruby/object:Gem::Version
638
635
  version: '0'
639
636
  requirements: []
640
- rubyforge_project:
641
- rubygems_version: 2.6.14.4
637
+ rubygems_version: 3.0.3
642
638
  signing_key:
643
639
  specification_version: 4
644
640
  summary: HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
@@ -1,5 +0,0 @@
1
- Count Name
2
- ======= ====
3
- 1095 Thomas Leitner <t_leitner@gmx.at>
4
- 1 Stanislav (Stas) Katkov <sk@skylup.com>
5
- 1 Daniel Kraus <bovender@bovender.de>
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.11.3
File without changes