hexapdf 0.2.0 → 0.3.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.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -1
  3. data/CONTRIBUTERS +1 -1
  4. data/LICENSE +1 -1
  5. data/Rakefile +1 -1
  6. data/VERSION +1 -1
  7. data/lib/hexapdf.rb +1 -1
  8. data/lib/hexapdf/cli.rb +19 -52
  9. data/lib/hexapdf/cli/command.rb +251 -0
  10. data/lib/hexapdf/cli/{extract.rb → files.rb} +19 -23
  11. data/lib/hexapdf/cli/images.rb +147 -0
  12. data/lib/hexapdf/cli/info.rb +5 -5
  13. data/lib/hexapdf/cli/inspect.rb +13 -12
  14. data/lib/hexapdf/cli/merge.rb +200 -0
  15. data/lib/hexapdf/cli/modify.rb +39 -242
  16. data/lib/hexapdf/cli/optimize.rb +104 -0
  17. data/lib/hexapdf/configuration.rb +1 -1
  18. data/lib/hexapdf/content.rb +1 -1
  19. data/lib/hexapdf/content/canvas.rb +1 -1
  20. data/lib/hexapdf/content/color_space.rb +1 -1
  21. data/lib/hexapdf/content/graphic_object.rb +1 -1
  22. data/lib/hexapdf/content/graphic_object/arc.rb +1 -1
  23. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
  24. data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
  25. data/lib/hexapdf/content/graphics_state.rb +1 -1
  26. data/lib/hexapdf/content/operator.rb +1 -1
  27. data/lib/hexapdf/content/parser.rb +16 -15
  28. data/lib/hexapdf/content/processor.rb +1 -1
  29. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  30. data/lib/hexapdf/data_dir.rb +1 -1
  31. data/lib/hexapdf/dictionary.rb +1 -1
  32. data/lib/hexapdf/dictionary_fields.rb +1 -1
  33. data/lib/hexapdf/document.rb +1 -1
  34. data/lib/hexapdf/document/files.rb +1 -1
  35. data/lib/hexapdf/document/fonts.rb +1 -1
  36. data/lib/hexapdf/document/images.rb +1 -1
  37. data/lib/hexapdf/document/pages.rb +1 -1
  38. data/lib/hexapdf/encryption.rb +1 -1
  39. data/lib/hexapdf/encryption/aes.rb +1 -1
  40. data/lib/hexapdf/encryption/arc4.rb +1 -1
  41. data/lib/hexapdf/encryption/fast_aes.rb +1 -1
  42. data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
  43. data/lib/hexapdf/encryption/identity.rb +1 -1
  44. data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
  45. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  46. data/lib/hexapdf/encryption/security_handler.rb +1 -1
  47. data/lib/hexapdf/encryption/standard_security_handler.rb +1 -1
  48. data/lib/hexapdf/error.rb +1 -1
  49. data/lib/hexapdf/filter.rb +1 -1
  50. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  51. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  52. data/lib/hexapdf/filter/dct_decode.rb +1 -1
  53. data/lib/hexapdf/filter/encryption.rb +1 -1
  54. data/lib/hexapdf/filter/flate_decode.rb +1 -1
  55. data/lib/hexapdf/filter/jpx_decode.rb +1 -1
  56. data/lib/hexapdf/filter/lzw_decode.rb +2 -3
  57. data/lib/hexapdf/filter/predictor.rb +11 -11
  58. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  59. data/lib/hexapdf/font/cmap.rb +1 -1
  60. data/lib/hexapdf/font/cmap/parser.rb +1 -1
  61. data/lib/hexapdf/font/cmap/writer.rb +1 -1
  62. data/lib/hexapdf/font/encoding.rb +1 -1
  63. data/lib/hexapdf/font/encoding/base.rb +1 -1
  64. data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
  65. data/lib/hexapdf/font/encoding/glyph_list.rb +1 -1
  66. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  67. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +1 -1
  68. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  69. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  70. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +1 -1
  71. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  72. data/lib/hexapdf/font/true_type.rb +2 -1
  73. data/lib/hexapdf/font/true_type/font.rb +1 -1
  74. data/lib/hexapdf/font/true_type/subsetter.rb +186 -0
  75. data/lib/hexapdf/font/true_type/table.rb +8 -4
  76. data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
  77. data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +1 -1
  78. data/lib/hexapdf/font/true_type/table/directory.rb +1 -1
  79. data/lib/hexapdf/font/true_type/table/glyf.rb +6 -2
  80. data/lib/hexapdf/font/true_type/table/head.rb +2 -2
  81. data/lib/hexapdf/font/true_type/table/hhea.rb +1 -1
  82. data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -1
  83. data/lib/hexapdf/font/true_type/table/loca.rb +1 -1
  84. data/lib/hexapdf/font/true_type/table/maxp.rb +1 -1
  85. data/lib/hexapdf/font/true_type/table/name.rb +1 -1
  86. data/lib/hexapdf/font/true_type/table/os2.rb +1 -1
  87. data/lib/hexapdf/font/true_type/table/post.rb +1 -1
  88. data/lib/hexapdf/font/true_type_wrapper.rb +56 -8
  89. data/lib/hexapdf/font/type1.rb +1 -1
  90. data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
  91. data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
  92. data/lib/hexapdf/font/type1/font.rb +1 -1
  93. data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
  94. data/lib/hexapdf/font/type1/pfb_parser.rb +1 -1
  95. data/lib/hexapdf/font/type1_wrapper.rb +1 -1
  96. data/lib/hexapdf/font_loader.rb +1 -1
  97. data/lib/hexapdf/font_loader/from_configuration.rb +6 -3
  98. data/lib/hexapdf/font_loader/standard14.rb +1 -1
  99. data/lib/hexapdf/image_loader.rb +1 -1
  100. data/lib/hexapdf/image_loader/jpeg.rb +1 -1
  101. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  102. data/lib/hexapdf/image_loader/png.rb +1 -1
  103. data/lib/hexapdf/importer.rb +1 -1
  104. data/lib/hexapdf/name_tree_node.rb +1 -1
  105. data/lib/hexapdf/number_tree_node.rb +1 -1
  106. data/lib/hexapdf/object.rb +1 -1
  107. data/lib/hexapdf/parser.rb +1 -1
  108. data/lib/hexapdf/rectangle.rb +1 -1
  109. data/lib/hexapdf/reference.rb +1 -1
  110. data/lib/hexapdf/revision.rb +1 -1
  111. data/lib/hexapdf/revisions.rb +13 -15
  112. data/lib/hexapdf/serializer.rb +7 -3
  113. data/lib/hexapdf/stream.rb +1 -1
  114. data/lib/hexapdf/task.rb +1 -1
  115. data/lib/hexapdf/task/dereference.rb +1 -1
  116. data/lib/hexapdf/task/optimize.rb +1 -1
  117. data/lib/hexapdf/tokenizer.rb +12 -12
  118. data/lib/hexapdf/type.rb +1 -1
  119. data/lib/hexapdf/type/catalog.rb +1 -1
  120. data/lib/hexapdf/type/embedded_file.rb +1 -1
  121. data/lib/hexapdf/type/file_specification.rb +1 -1
  122. data/lib/hexapdf/type/font.rb +1 -1
  123. data/lib/hexapdf/type/font_descriptor.rb +1 -1
  124. data/lib/hexapdf/type/font_simple.rb +1 -1
  125. data/lib/hexapdf/type/font_true_type.rb +1 -1
  126. data/lib/hexapdf/type/font_type1.rb +1 -1
  127. data/lib/hexapdf/type/form.rb +1 -1
  128. data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
  129. data/lib/hexapdf/type/image.rb +187 -1
  130. data/lib/hexapdf/type/info.rb +1 -1
  131. data/lib/hexapdf/type/names.rb +1 -1
  132. data/lib/hexapdf/type/object_stream.rb +1 -1
  133. data/lib/hexapdf/type/page.rb +1 -1
  134. data/lib/hexapdf/type/page_tree_node.rb +6 -1
  135. data/lib/hexapdf/type/resources.rb +1 -1
  136. data/lib/hexapdf/type/trailer.rb +2 -2
  137. data/lib/hexapdf/type/viewer_preferences.rb +1 -1
  138. data/lib/hexapdf/type/xref_stream.rb +22 -18
  139. data/lib/hexapdf/utils/bit_field.rb +1 -1
  140. data/lib/hexapdf/utils/bit_stream.rb +16 -32
  141. data/lib/hexapdf/utils/lru_cache.rb +1 -1
  142. data/lib/hexapdf/utils/math_helpers.rb +1 -1
  143. data/lib/hexapdf/utils/object_hash.rb +1 -1
  144. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
  145. data/lib/hexapdf/utils/sorted_tree_node.rb +1 -1
  146. data/lib/hexapdf/version.rb +2 -2
  147. data/lib/hexapdf/writer.rb +2 -1
  148. data/lib/hexapdf/xref_section.rb +6 -1
  149. data/man/man1/hexapdf.1 +194 -115
  150. data/test/data/images/greyscale-1bit.png +0 -0
  151. data/test/data/images/greyscale-2bit.png +0 -0
  152. data/test/data/images/greyscale-8bit.png +0 -0
  153. data/test/data/images/indexed-alpha-4bit.png +0 -0
  154. data/test/data/images/truecolour-8bit.png +0 -0
  155. data/test/hexapdf/content/test_operator.rb +8 -8
  156. data/test/hexapdf/content/test_processor.rb +1 -1
  157. data/test/hexapdf/encryption/test_security_handler.rb +1 -1
  158. data/test/hexapdf/font/test_true_type_wrapper.rb +89 -48
  159. data/test/hexapdf/font/true_type/table/test_glyf.rb +1 -0
  160. data/test/hexapdf/font/true_type/test_subsetter.rb +70 -0
  161. data/test/hexapdf/font/true_type/test_table.rb +16 -0
  162. data/test/hexapdf/font_loader/test_from_configuration.rb +7 -0
  163. data/test/hexapdf/test_document.rb +1 -1
  164. data/test/hexapdf/test_object.rb +1 -1
  165. data/test/hexapdf/test_revisions.rb +34 -8
  166. data/test/hexapdf/test_serializer.rb +3 -0
  167. data/test/hexapdf/test_writer.rb +11 -2
  168. data/test/hexapdf/test_xref_section.rb +15 -0
  169. data/test/hexapdf/type/test_image.rb +234 -0
  170. data/test/hexapdf/type/test_object_stream.rb +2 -2
  171. data/test/hexapdf/type/test_trailer.rb +4 -0
  172. data/test/hexapdf/utils/test_bit_stream.rb +69 -0
  173. metadata +14 -6
@@ -116,6 +116,9 @@ describe HexaPDF::Serializer do
116
116
  assert_serialized("/Name", HexaPDF::Object.new(:Name, oid: 1))
117
117
  assert_serialized("<</Name 2 0 R>>",
118
118
  HexaPDF::Object.new({Name: HexaPDF::Object.new(5, oid: 2)}, oid: 1))
119
+ obj = HexaPDF::Object.new({Name: HexaPDF::Object.new(5, oid: 2)}, oid: 1)
120
+ obj.value[:Self] = obj
121
+ assert_serialized("<</Name 2 0 R/Self 1 0 R>>", obj)
119
122
  end
120
123
 
121
124
  it "serializes HexaPDF reference objects" do
@@ -40,7 +40,7 @@ startxref
40
40
  219
41
41
  %%EOF
42
42
  3 0 obj
43
- <</Producer(HexaPDF version 0.2.0)>>
43
+ <</Producer(HexaPDF version 0.3.0)>>
44
44
  endobj
45
45
  xref
46
46
  3 1
@@ -72,7 +72,7 @@ startxref
72
72
  141
73
73
  %%EOF
74
74
  6 0 obj
75
- <</Producer(HexaPDF version 0.2.0)>>
75
+ <</Producer(HexaPDF version 0.3.0)>>
76
76
  endobj
77
77
  2 0 obj
78
78
  <</Length 10>>stream
@@ -117,4 +117,13 @@ EOF
117
117
  xref_section.add_compressed_entry(1, 2, 3)
118
118
  assert_raises(HexaPDF::Error) { writer.send(:write_xref_section, xref_section) }
119
119
  end
120
+
121
+ it "removes the /XRefStm entry in a trailer" do
122
+ io = StringIO.new
123
+ doc = HexaPDF::Document.new
124
+ doc.trailer[:XRefStm] = 1234
125
+ doc.write(io)
126
+ doc = HexaPDF::Document.new(io: io)
127
+ refute(doc.trailer.key?(:XRefStm))
128
+ end
120
129
  end
@@ -8,6 +8,21 @@ describe HexaPDF::XRefSection do
8
8
  @xref_section = HexaPDF::XRefSection.new
9
9
  end
10
10
 
11
+ describe "merge" do
12
+ it "adds all entries from the other xref section, potentially overwriting entries" do
13
+ @xref_section.add_in_use_entry(1, 0, 1)
14
+ xref = HexaPDF::XRefSection.new
15
+ xref.add_in_use_entry(1, 0, 2)
16
+ xref.add_in_use_entry(2, 0, 2)
17
+ assert_equal(1, @xref_section[1, 0].pos)
18
+ assert_nil(@xref_section[2, 0])
19
+
20
+ @xref_section.merge!(xref)
21
+ assert_equal(2, @xref_section[1, 0].pos)
22
+ assert_equal(2, @xref_section[2, 0].pos)
23
+ end
24
+ end
25
+
11
26
  describe "each_subsection" do
12
27
  def assert_subsections(result)
13
28
  assert_equal(result, @xref_section.each_subsection.map {|s| s.map(&:oid)})
@@ -0,0 +1,234 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'stringio'
5
+ require 'tempfile'
6
+ require 'hexapdf/document'
7
+
8
+ describe HexaPDF::Type::Image do
9
+ before do
10
+ @jpg = File.join(TEST_DATA_DIR, 'images', 'rgb.jpg')
11
+ @doc = HexaPDF::Document.new
12
+ end
13
+
14
+ describe "info" do
15
+ before do
16
+ @image = @doc.wrap(Subtype: :Image, Width: 10, Height: 5, ColorSpace: :DeviceRGB,
17
+ BitsPerComponent: 4)
18
+ end
19
+
20
+ it "uses the Width, Height and BitsPerComponent values" do
21
+ assert_equal(10, @image.info.width)
22
+ assert_equal(5, @image.info.height)
23
+ assert_equal(4, @image.info.bits_per_component)
24
+ end
25
+
26
+ it "determines the type and extension based on the stream filter" do
27
+ @image.set_filter(:DCTDecode)
28
+ info = @image.info
29
+ assert_equal(:jpeg, info.type)
30
+ assert_equal('jpg', info.extension)
31
+ assert(info.writable)
32
+
33
+ @image.set_filter(:JPXDecode)
34
+ info = @image.info
35
+ assert_equal(:jp2, info.type)
36
+ assert_equal('jpx', info.extension)
37
+ assert(info.writable)
38
+
39
+ @image.set_filter(:JBIG2Decode)
40
+ info = @image.info
41
+ assert_equal(:jbig2, info.type)
42
+ refute(info.writable)
43
+
44
+ @image.set_filter(:CCITTFaxDecode)
45
+ info = @image.info
46
+ assert_equal(:ccitt, info.type)
47
+ refute(info.writable)
48
+
49
+ @image.set_filter(nil)
50
+ info = @image.info
51
+ assert_equal(:png, @image.info.type)
52
+ assert_equal('png', info.extension)
53
+ assert(info.writable)
54
+ end
55
+
56
+ it "determines the color space, indexed and components values using the ColorSpace value" do
57
+ @image[:ColorSpace] = :DeviceGray
58
+ info = @image.info
59
+ assert_equal(:gray, info.color_space)
60
+ assert_equal(1, info.components)
61
+ refute(info.indexed)
62
+ assert(info.writable)
63
+
64
+ @image[:ColorSpace] = [:CalGray, {WhitePoint: [1, 1, 1]}]
65
+ info = @image.info
66
+ assert_equal(:gray, info.color_space)
67
+ assert_equal(1, info.components)
68
+ refute(info.indexed)
69
+ assert(info.writable)
70
+
71
+ @image[:ColorSpace] = :DeviceRGB
72
+ info = @image.info
73
+ assert_equal(:rgb, info.color_space)
74
+ assert_equal(3, info.components)
75
+ refute(info.indexed)
76
+ assert(info.writable)
77
+
78
+ @image[:ColorSpace] = [:CalRGB, {WhitePoint: [1, 1, 1]}]
79
+ info = @image.info
80
+ assert_equal(:rgb, info.color_space)
81
+ assert_equal(3, info.components)
82
+ refute(info.indexed)
83
+ assert(info.writable)
84
+
85
+
86
+ @image[:ColorSpace] = :DeviceCMYK
87
+ @image[:Filter] = :DCTDecode
88
+ info = @image.info
89
+ assert_equal(:cmyk, info.color_space)
90
+ assert_equal(4, info.components)
91
+ refute(info.indexed)
92
+ assert(info.writable)
93
+
94
+ @image[:ColorSpace] = :DeviceCMYK
95
+ @image[:Filter] = :FlateDecode
96
+ info = @image.info
97
+ assert_equal(:cmyk, info.color_space)
98
+ assert_equal(4, info.components)
99
+ refute(info.indexed)
100
+ refute(info.writable)
101
+
102
+
103
+ @image[:ColorSpace] = [:Indexed, :DeviceRGB, 1, "\x80".b * 6]
104
+ info = @image.info
105
+ assert_equal(:rgb, info.color_space)
106
+ assert_equal(3, info.components)
107
+ assert(info.indexed)
108
+ assert(info.writable)
109
+
110
+
111
+ @image[:ColorSpace] = :ICCBased
112
+ info = @image.info
113
+ assert_equal(:other, info.color_space)
114
+ assert_equal(-1, info.components)
115
+ end
116
+ end
117
+
118
+ describe "write" do
119
+ before do
120
+ @file = Tempfile.new(['hexapdf-image-write-test', '.png'])
121
+ end
122
+
123
+ after do
124
+ @file.unlink
125
+ end
126
+
127
+ `pngcheck 2>&1`
128
+ if $?.exitstatus != 0
129
+ warn("Skipping PNG output validity check because pngcheck executable is missing")
130
+ PNG_CHECK_AVAILABLE = false
131
+ else
132
+ PNG_CHECK_AVAILABLE = true
133
+ end
134
+
135
+ def assert_valid_png(filename)
136
+ return unless PNG_CHECK_AVAILABLE
137
+ result = `pngcheck -q #{filename}`
138
+ assert(result.empty?, "pngcheck error: #{result}")
139
+ end
140
+
141
+ it "can write to an IO" do
142
+ io = StringIO.new(''.b)
143
+ image = @doc.images.add(@jpg)
144
+ image.write(io)
145
+ assert_equal(File.binread(@jpg), io.string)
146
+ end
147
+
148
+ it "writes JPEG images to a file with .jpg extension" do
149
+ begin
150
+ file = Tempfile.new(['hexapdf-image-write-test', '.jpg'])
151
+ image = @doc.images.add(@jpg)
152
+ image.write(file.path)
153
+ assert_equal(File.binread(@jpg), File.binread(file.path))
154
+ ensure
155
+ file.unlink
156
+ end
157
+ end
158
+
159
+ it "writes JPEG2000 images to a file with .jpx extension" do
160
+ begin
161
+ file = Tempfile.new(['hexapdf-image-write-test', '.jpx'])
162
+ image = @doc.images.add(@jpg)
163
+ image.set_filter(:JPXDecode) # fake it
164
+ image.write(file.path)
165
+ assert_equal(File.binread(@jpg), File.binread(file.path))
166
+ ensure
167
+ file.unlink
168
+ end
169
+ end
170
+
171
+ Dir.glob(File.join(TEST_DATA_DIR, 'images', '*.png')).each do |png_file|
172
+ it "writes #{File.basename(png_file)} correctly as PNG file" do
173
+ image = @doc.images.add(png_file)
174
+ image.write(@file.path)
175
+
176
+ assert_valid_png(@file.path)
177
+
178
+ new_image = @doc.images.add(@file.path)
179
+
180
+ assert_equal(image[:Width], new_image[:Width], "file: #{png_file}")
181
+ assert_equal(image[:Height], new_image[:Height], "file: #{png_file}")
182
+ assert_equal(image[:BitsPerComponent], new_image[:BitsPerComponent], "file: #{png_file}")
183
+ if image[:Mask]
184
+ assert_equal(image[:Mask], new_image[:Mask], "file: #{png_file}")
185
+ else
186
+ assert_nil(new_image[:Mask], "file: #{png_file}")
187
+ end
188
+ assert_equal(image.stream, new_image.stream, "file: #{png_file}")
189
+
190
+ # ColorSpace is currently not always preserved, e.g. with CalRGB
191
+ if Array(image[:ColorSpace]).first == :Indexed
192
+ assert_equal(image[:ColorSpace][2], new_image[:ColorSpace][2], "file: #{png_file}")
193
+
194
+ img_palette = image[:ColorSpace][3]
195
+ img_palette = img_palette.stream if img_palette.respond_to?(:stream)
196
+ new_img_palette = new_image[:ColorSpace][3]
197
+ new_img_palette = new_img_palette.stream if new_img_palette.respond_to?(:stream)
198
+ assert_equal(img_palette, new_img_palette, "file: #{png_file}")
199
+ end
200
+ end
201
+ end
202
+
203
+ it "works for greyscale indexed images" do
204
+ image = @doc.add(Subtype: :Image, Width: 2, Height: 2, BitsPerComponent: 2,
205
+ ColorSpace: [:Indexed, :DeviceGray, 3, "\x00\x40\x80\xFF".b])
206
+ image.stream = HexaPDF::StreamData.new(filter: :ASCIIHexDecode) { "10 B0".b }
207
+ image.write(@file.path)
208
+ assert_valid_png(@file.path)
209
+
210
+ new_image = @doc.images.add(@file.path)
211
+ assert_equal([:Indexed, :DeviceRGB, 3, "\x00\x00\x00\x40\x40\x40\x80\x80\x80\xFF\xFF\xFF".b],
212
+ new_image[:ColorSpace])
213
+ assert_equal(image.stream, new_image.stream)
214
+ end
215
+
216
+ it "fails if an unsupported stream filter is used" do
217
+ image = @doc.images.add(@jpg)
218
+ image.set_filter([:DCTDecode, :ASCIIHexDecode])
219
+ assert_raises(HexaPDF::Error) { image.write(@file) }
220
+ end
221
+
222
+ it "fails if an unsupported colorspace is used" do
223
+ image = @doc.add(Subtype: :Image, Width: 1, Height: 1, BitsPerComponent: 8,
224
+ ColorSpace: :ICCBased)
225
+ assert_raises(HexaPDF::Error) { image.write(@file) }
226
+ end
227
+
228
+ it "fails if an indexed image with an unsupported colorspace is used" do
229
+ image = @doc.add(Subtype: :Image, Width: 1, Height: 1, BitsPerComponent: 8,
230
+ ColorSpace: [:Indexed, :ICCBased, 0, "0"])
231
+ assert_raises(HexaPDF::Error) { image.write(@file) }
232
+ end
233
+ end
234
+ end
@@ -49,11 +49,11 @@ describe HexaPDF::Type::ObjectStream do
49
49
  @obj.delete_object(5)
50
50
  assert_equal(0, @obj.object_index(9))
51
51
  assert_equal(1, @obj.object_index(7))
52
- assert_equal(nil, @obj.object_index(5))
52
+ assert_nil(@obj.object_index(5))
53
53
 
54
54
  @obj.delete_object(7)
55
55
  @obj.delete_object(9)
56
- assert_equal(nil, @obj.object_index(5))
56
+ assert_nil(@obj.object_index(5))
57
57
  end
58
58
 
59
59
  it "allows writing the objects to the stream" do
@@ -51,6 +51,10 @@ describe HexaPDF::Type::Trailer do
51
51
  @obj.update_id
52
52
  assert_same(@obj[:ID][0], @obj[:ID][1])
53
53
 
54
+ @obj[:ID] = 5
55
+ @obj.update_id
56
+ assert_same(@obj[:ID][0], @obj[:ID][1])
57
+
54
58
  @obj.update_id
55
59
  refute_same(@obj[:ID][0], @obj[:ID][1])
56
60
  end
@@ -0,0 +1,69 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/utils/bit_stream'
5
+
6
+ describe HexaPDF::Utils::BitStreamReader do
7
+ before do
8
+ @reader = HexaPDF::Utils::BitStreamReader.new
9
+ end
10
+
11
+ it "allows appending data" do
12
+ assert_equal(0, @reader.remaining_bits)
13
+ @reader << "data"
14
+ assert_equal(32, @reader.remaining_bits)
15
+ @reader << "some"
16
+ assert_equal(64, @reader.remaining_bits)
17
+ @reader.read(4)
18
+ assert_equal(60, @reader.remaining_bits)
19
+ @reader << "more"
20
+ assert_equal(92, @reader.remaining_bits)
21
+ end
22
+
23
+ it "allows checking whether a certain number of bits can be read" do
24
+ refute(@reader.read?(1))
25
+ @reader << "data"
26
+ assert(@reader.read?(1))
27
+ assert(@reader.read?(32))
28
+ refute(@reader.read?(33))
29
+ end
30
+
31
+ describe "read" do
32
+ it "allows reading any number of bits" do
33
+ @reader << "\xaa" * 8 # 10101010 * 8
34
+ assert_equal(1, @reader.read(1))
35
+ assert_equal(0, @reader.read(1))
36
+ assert_equal(2, @reader.read(2))
37
+ assert_equal(10, @reader.read(4))
38
+ assert_equal(5, @reader.read(3))
39
+ assert_equal((0b01010 << 8) | 0xaa, @reader.read(13))
40
+ assert_equal(5, @reader.read(3))
41
+ assert_equal((0b01010 << 7) | (0xaa >> 1), @reader.read(12))
42
+ assert_equal(2, @reader.read(3))
43
+ end
44
+
45
+ it "allows reading many bits" do
46
+ @reader << "\x80" << "\x00" * 20
47
+ assert_equal(2**127, @reader.read(128))
48
+ end
49
+
50
+ it "returns nil if enough bits are available" do
51
+ assert_nil(@reader.read(1))
52
+ end
53
+ end
54
+ end
55
+
56
+ describe HexaPDF::Utils::BitStreamWriter do
57
+ before do
58
+ @writer = HexaPDF::Utils::BitStreamWriter.new
59
+ end
60
+
61
+ it "allows writing any number of bits" do
62
+ result = @writer.write(1, 1)
63
+ result << @writer.write(0b101, 3)
64
+ result << @writer.write(0xff, 8)
65
+ result << @writer.write(0x5ddd, 15)
66
+ result << @writer.finalize
67
+ assert_equal("\xdf\xfb\xbb\xa0".b, result)
68
+ end
69
+ end
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.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Leitner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-28 00:00:00.000000000 Z
11
+ date: 2017-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmdparse
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '3.0'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 3.0.1
22
+ version: 3.0.3
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: '3.0'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 3.0.1
32
+ version: 3.0.3
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: kramdown
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -98,10 +98,14 @@ files:
98
98
  - examples/truetype.rb
99
99
  - lib/hexapdf.rb
100
100
  - lib/hexapdf/cli.rb
101
- - lib/hexapdf/cli/extract.rb
101
+ - lib/hexapdf/cli/command.rb
102
+ - lib/hexapdf/cli/files.rb
103
+ - lib/hexapdf/cli/images.rb
102
104
  - lib/hexapdf/cli/info.rb
103
105
  - lib/hexapdf/cli/inspect.rb
106
+ - lib/hexapdf/cli/merge.rb
104
107
  - lib/hexapdf/cli/modify.rb
108
+ - lib/hexapdf/cli/optimize.rb
105
109
  - lib/hexapdf/configuration.rb
106
110
  - lib/hexapdf/content.rb
107
111
  - lib/hexapdf/content/canvas.rb
@@ -159,6 +163,7 @@ files:
159
163
  - lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb
160
164
  - lib/hexapdf/font/true_type.rb
161
165
  - lib/hexapdf/font/true_type/font.rb
166
+ - lib/hexapdf/font/true_type/subsetter.rb
162
167
  - lib/hexapdf/font/true_type/table.rb
163
168
  - lib/hexapdf/font/true_type/table/cmap.rb
164
169
  - lib/hexapdf/font/true_type/table/cmap_subtable.rb
@@ -360,6 +365,7 @@ files:
360
365
  - test/hexapdf/font/true_type/table/test_os2.rb
361
366
  - test/hexapdf/font/true_type/table/test_post.rb
362
367
  - test/hexapdf/font/true_type/test_font.rb
368
+ - test/hexapdf/font/true_type/test_subsetter.rb
363
369
  - test/hexapdf/font/true_type/test_table.rb
364
370
  - test/hexapdf/font/type1/test_afm_parser.rb
365
371
  - test/hexapdf/font/type1/test_font.rb
@@ -398,6 +404,7 @@ files:
398
404
  - test/hexapdf/type/test_font_simple.rb
399
405
  - test/hexapdf/type/test_font_type1.rb
400
406
  - test/hexapdf/type/test_form.rb
407
+ - test/hexapdf/type/test_image.rb
401
408
  - test/hexapdf/type/test_info.rb
402
409
  - test/hexapdf/type/test_names.rb
403
410
  - test/hexapdf/type/test_object_stream.rb
@@ -407,6 +414,7 @@ files:
407
414
  - test/hexapdf/type/test_trailer.rb
408
415
  - test/hexapdf/type/test_xref_stream.rb
409
416
  - test/hexapdf/utils/test_bit_field.rb
417
+ - test/hexapdf/utils/test_bit_stream.rb
410
418
  - test/hexapdf/utils/test_lru_cache.rb
411
419
  - test/hexapdf/utils/test_object_hash.rb
412
420
  - test/hexapdf/utils/test_pdf_doc_encoding.rb
@@ -432,7 +440,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
432
440
  version: '0'
433
441
  requirements: []
434
442
  rubyforge_project:
435
- rubygems_version: 2.5.1
443
+ rubygems_version: 2.6.8
436
444
  signing_key:
437
445
  specification_version: 4
438
446
  summary: HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby