hexapdf 0.6.0 → 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.
Files changed (257) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +33 -0
  3. data/CONTRIBUTERS +1 -1
  4. data/LICENSE +1 -1
  5. data/Rakefile +1 -1
  6. data/VERSION +1 -1
  7. data/bin/hexapdf +1 -1
  8. data/examples/text_layouter_styling.rb +1 -2
  9. data/lib/hexapdf.rb +2 -2
  10. data/lib/hexapdf/cli.rb +3 -3
  11. data/lib/hexapdf/cli/batch.rb +5 -5
  12. data/lib/hexapdf/cli/command.rb +15 -17
  13. data/lib/hexapdf/cli/files.rb +3 -3
  14. data/lib/hexapdf/cli/images.rb +3 -4
  15. data/lib/hexapdf/cli/info.rb +5 -5
  16. data/lib/hexapdf/cli/inspect.rb +6 -6
  17. data/lib/hexapdf/cli/merge.rb +6 -6
  18. data/lib/hexapdf/cli/modify.rb +4 -4
  19. data/lib/hexapdf/cli/optimize.rb +3 -3
  20. data/lib/hexapdf/configuration.rb +4 -5
  21. data/lib/hexapdf/content.rb +2 -2
  22. data/lib/hexapdf/content/canvas.rb +35 -36
  23. data/lib/hexapdf/content/color_space.rb +9 -14
  24. data/lib/hexapdf/content/graphic_object.rb +2 -2
  25. data/lib/hexapdf/content/graphic_object/arc.rb +3 -3
  26. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +2 -2
  27. data/lib/hexapdf/content/graphic_object/solid_arc.rb +4 -8
  28. data/lib/hexapdf/content/graphics_state.rb +4 -13
  29. data/lib/hexapdf/content/operator.rb +33 -35
  30. data/lib/hexapdf/content/parser.rb +28 -18
  31. data/lib/hexapdf/content/processor.rb +4 -5
  32. data/lib/hexapdf/content/transformation_matrix.rb +2 -2
  33. data/lib/hexapdf/data_dir.rb +2 -2
  34. data/lib/hexapdf/dictionary.rb +8 -9
  35. data/lib/hexapdf/dictionary_fields.rb +7 -10
  36. data/lib/hexapdf/document.rb +18 -18
  37. data/lib/hexapdf/document/files.rb +12 -10
  38. data/lib/hexapdf/document/fonts.rb +2 -2
  39. data/lib/hexapdf/document/images.rb +3 -3
  40. data/lib/hexapdf/document/pages.rb +4 -4
  41. data/lib/hexapdf/encryption.rb +2 -2
  42. data/lib/hexapdf/encryption/aes.rb +2 -2
  43. data/lib/hexapdf/encryption/arc4.rb +4 -4
  44. data/lib/hexapdf/encryption/fast_aes.rb +2 -2
  45. data/lib/hexapdf/encryption/fast_arc4.rb +4 -4
  46. data/lib/hexapdf/encryption/identity.rb +5 -4
  47. data/lib/hexapdf/encryption/ruby_aes.rb +147 -139
  48. data/lib/hexapdf/encryption/ruby_arc4.rb +4 -4
  49. data/lib/hexapdf/encryption/security_handler.rb +11 -12
  50. data/lib/hexapdf/encryption/standard_security_handler.rb +6 -9
  51. data/lib/hexapdf/error.rb +7 -9
  52. data/lib/hexapdf/filter.rb +2 -3
  53. data/lib/hexapdf/filter/ascii85_decode.rb +3 -3
  54. data/lib/hexapdf/filter/ascii_hex_decode.rb +2 -2
  55. data/lib/hexapdf/filter/dct_decode.rb +2 -2
  56. data/lib/hexapdf/filter/encryption.rb +2 -2
  57. data/lib/hexapdf/filter/flate_decode.rb +16 -33
  58. data/lib/hexapdf/filter/jpx_decode.rb +2 -2
  59. data/lib/hexapdf/filter/lzw_decode.rb +4 -4
  60. data/lib/hexapdf/filter/predictor.rb +2 -6
  61. data/lib/hexapdf/filter/run_length_decode.rb +2 -2
  62. data/lib/hexapdf/font/cmap.rb +2 -3
  63. data/lib/hexapdf/font/cmap/parser.rb +11 -11
  64. data/lib/hexapdf/font/cmap/writer.rb +25 -25
  65. data/lib/hexapdf/font/encoding.rb +2 -2
  66. data/lib/hexapdf/font/encoding/base.rb +2 -2
  67. data/lib/hexapdf/font/encoding/difference_encoding.rb +2 -2
  68. data/lib/hexapdf/font/encoding/glyph_list.rb +6 -6
  69. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +2 -2
  70. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
  71. data/lib/hexapdf/font/encoding/standard_encoding.rb +2 -2
  72. data/lib/hexapdf/font/encoding/symbol_encoding.rb +2 -2
  73. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +2 -2
  74. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +2 -2
  75. data/lib/hexapdf/font/invalid_glyph.rb +7 -7
  76. data/lib/hexapdf/font/true_type.rb +2 -2
  77. data/lib/hexapdf/font/true_type/builder.rb +13 -7
  78. data/lib/hexapdf/font/true_type/font.rb +2 -3
  79. data/lib/hexapdf/font/true_type/optimizer.rb +2 -2
  80. data/lib/hexapdf/font/true_type/subsetter.rb +4 -4
  81. data/lib/hexapdf/font/true_type/table.rb +3 -5
  82. data/lib/hexapdf/font/true_type/table/cmap.rb +2 -2
  83. data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +9 -16
  84. data/lib/hexapdf/font/true_type/table/directory.rb +4 -4
  85. data/lib/hexapdf/font/true_type/table/glyf.rb +2 -2
  86. data/lib/hexapdf/font/true_type/table/head.rb +3 -2
  87. data/lib/hexapdf/font/true_type/table/hhea.rb +2 -2
  88. data/lib/hexapdf/font/true_type/table/hmtx.rb +2 -2
  89. data/lib/hexapdf/font/true_type/table/kern.rb +3 -3
  90. data/lib/hexapdf/font/true_type/table/loca.rb +3 -3
  91. data/lib/hexapdf/font/true_type/table/maxp.rb +2 -2
  92. data/lib/hexapdf/font/true_type/table/name.rb +3 -5
  93. data/lib/hexapdf/font/true_type/table/os2.rb +4 -3
  94. data/lib/hexapdf/font/true_type/table/post.rb +3 -7
  95. data/lib/hexapdf/font/true_type_wrapper.rb +20 -22
  96. data/lib/hexapdf/font/type1.rb +2 -2
  97. data/lib/hexapdf/font/type1/afm_parser.rb +7 -7
  98. data/lib/hexapdf/font/type1/character_metrics.rb +2 -2
  99. data/lib/hexapdf/font/type1/font.rb +3 -3
  100. data/lib/hexapdf/font/type1/font_metrics.rb +2 -4
  101. data/lib/hexapdf/font/type1/pfb_parser.rb +2 -2
  102. data/lib/hexapdf/font/type1_wrapper.rb +8 -9
  103. data/lib/hexapdf/font_loader.rb +2 -2
  104. data/lib/hexapdf/font_loader/from_configuration.rb +2 -2
  105. data/lib/hexapdf/font_loader/from_file.rb +2 -2
  106. data/lib/hexapdf/font_loader/standard14.rb +2 -2
  107. data/lib/hexapdf/image_loader.rb +2 -2
  108. data/lib/hexapdf/image_loader/jpeg.rb +6 -4
  109. data/lib/hexapdf/image_loader/pdf.rb +2 -2
  110. data/lib/hexapdf/image_loader/png.rb +6 -6
  111. data/lib/hexapdf/importer.rb +6 -4
  112. data/lib/hexapdf/layout.rb +2 -2
  113. data/lib/hexapdf/layout/box.rb +4 -4
  114. data/lib/hexapdf/layout/inline_box.rb +2 -2
  115. data/lib/hexapdf/layout/line.rb +6 -6
  116. data/lib/hexapdf/layout/numeric_refinements.rb +2 -2
  117. data/lib/hexapdf/layout/style.rb +17 -8
  118. data/lib/hexapdf/layout/text_fragment.rb +86 -48
  119. data/lib/hexapdf/layout/text_layouter.rb +40 -21
  120. data/lib/hexapdf/layout/text_shaper.rb +2 -2
  121. data/lib/hexapdf/name_tree_node.rb +2 -2
  122. data/lib/hexapdf/number_tree_node.rb +2 -2
  123. data/lib/hexapdf/object.rb +6 -8
  124. data/lib/hexapdf/parser.rb +10 -10
  125. data/lib/hexapdf/rectangle.rb +4 -4
  126. data/lib/hexapdf/reference.rb +2 -2
  127. data/lib/hexapdf/revision.rb +4 -4
  128. data/lib/hexapdf/revisions.rb +5 -5
  129. data/lib/hexapdf/serializer.rb +27 -24
  130. data/lib/hexapdf/stream.rb +4 -4
  131. data/lib/hexapdf/task.rb +2 -2
  132. data/lib/hexapdf/task/dereference.rb +4 -4
  133. data/lib/hexapdf/task/optimize.rb +5 -4
  134. data/lib/hexapdf/tokenizer.rb +12 -14
  135. data/lib/hexapdf/type.rb +2 -2
  136. data/lib/hexapdf/type/action.rb +3 -3
  137. data/lib/hexapdf/type/actions.rb +2 -2
  138. data/lib/hexapdf/type/actions/go_to.rb +2 -2
  139. data/lib/hexapdf/type/actions/go_to_r.rb +2 -2
  140. data/lib/hexapdf/type/actions/launch.rb +2 -2
  141. data/lib/hexapdf/type/actions/uri.rb +3 -3
  142. data/lib/hexapdf/type/annotation.rb +3 -3
  143. data/lib/hexapdf/type/annotations.rb +2 -2
  144. data/lib/hexapdf/type/annotations/link.rb +2 -2
  145. data/lib/hexapdf/type/annotations/markup_annotation.rb +2 -2
  146. data/lib/hexapdf/type/annotations/text.rb +2 -2
  147. data/lib/hexapdf/type/catalog.rb +4 -4
  148. data/lib/hexapdf/type/cid_font.rb +4 -5
  149. data/lib/hexapdf/type/embedded_file.rb +3 -3
  150. data/lib/hexapdf/type/file_specification.rb +6 -7
  151. data/lib/hexapdf/type/font.rb +4 -4
  152. data/lib/hexapdf/type/font_descriptor.rb +3 -4
  153. data/lib/hexapdf/type/font_simple.rb +12 -16
  154. data/lib/hexapdf/type/font_true_type.rb +2 -2
  155. data/lib/hexapdf/type/font_type0.rb +5 -5
  156. data/lib/hexapdf/type/font_type1.rb +4 -4
  157. data/lib/hexapdf/type/form.rb +3 -3
  158. data/lib/hexapdf/type/graphics_state_parameter.rb +3 -3
  159. data/lib/hexapdf/type/image.rb +13 -14
  160. data/lib/hexapdf/type/info.rb +2 -2
  161. data/lib/hexapdf/type/names.rb +2 -2
  162. data/lib/hexapdf/type/object_stream.rb +5 -5
  163. data/lib/hexapdf/type/page.rb +9 -10
  164. data/lib/hexapdf/type/page_tree_node.rb +5 -6
  165. data/lib/hexapdf/type/resources.rb +11 -11
  166. data/lib/hexapdf/type/trailer.rb +3 -3
  167. data/lib/hexapdf/type/viewer_preferences.rb +2 -2
  168. data/lib/hexapdf/type/xref_stream.rb +8 -4
  169. data/lib/hexapdf/utils/bit_field.rb +4 -4
  170. data/lib/hexapdf/utils/bit_stream.rb +4 -4
  171. data/lib/hexapdf/utils/graphics_helpers.rb +2 -2
  172. data/lib/hexapdf/utils/lru_cache.rb +2 -2
  173. data/lib/hexapdf/utils/math_helpers.rb +2 -2
  174. data/lib/hexapdf/utils/object_hash.rb +3 -3
  175. data/lib/hexapdf/utils/pdf_doc_encoding.rb +3 -3
  176. data/lib/hexapdf/utils/sorted_tree_node.rb +12 -11
  177. data/lib/hexapdf/version.rb +3 -3
  178. data/lib/hexapdf/writer.rb +8 -8
  179. data/lib/hexapdf/xref_section.rb +3 -3
  180. data/test/hexapdf/common_tokenizer_tests.rb +6 -7
  181. data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +0 -1
  182. data/test/hexapdf/content/test_canvas.rb +28 -36
  183. data/test/hexapdf/content/test_color_space.rb +4 -0
  184. data/test/hexapdf/content/test_graphics_state.rb +2 -0
  185. data/test/hexapdf/content/test_operator.rb +6 -7
  186. data/test/hexapdf/content/test_parser.rb +2 -2
  187. data/test/hexapdf/content/test_processor.rb +1 -1
  188. data/test/hexapdf/document/test_files.rb +1 -0
  189. data/test/hexapdf/document/test_images.rb +1 -1
  190. data/test/hexapdf/encryption/common.rb +3 -3
  191. data/test/hexapdf/encryption/test_aes.rb +10 -4
  192. data/test/hexapdf/encryption/test_identity.rb +1 -1
  193. data/test/hexapdf/encryption/test_security_handler.rb +13 -17
  194. data/test/hexapdf/encryption/test_standard_security_handler.rb +12 -12
  195. data/test/hexapdf/filter/test_ascii85_decode.rb +2 -3
  196. data/test/hexapdf/filter/test_ascii_hex_decode.rb +6 -1
  197. data/test/hexapdf/filter/test_flate_decode.rb +2 -2
  198. data/test/hexapdf/filter/test_lzw_decode.rb +10 -10
  199. data/test/hexapdf/filter/test_predictor.rb +10 -2
  200. data/test/hexapdf/filter/test_run_length_decode.rb +1 -1
  201. data/test/hexapdf/font/cmap/test_parser.rb +40 -40
  202. data/test/hexapdf/font/cmap/test_writer.rb +29 -29
  203. data/test/hexapdf/font/test_true_type_wrapper.rb +3 -2
  204. data/test/hexapdf/font/true_type/common.rb +2 -0
  205. data/test/hexapdf/font/true_type/table/test_cmap.rb +1 -1
  206. data/test/hexapdf/font/true_type/table/test_cmap_subtable.rb +5 -4
  207. data/test/hexapdf/font/true_type/table/test_glyf.rb +2 -2
  208. data/test/hexapdf/font/true_type/table/test_head.rb +2 -2
  209. data/test/hexapdf/font/true_type/table/test_name.rb +9 -6
  210. data/test/hexapdf/font/true_type/test_builder.rb +8 -3
  211. data/test/hexapdf/font/true_type/test_optimizer.rb +1 -2
  212. data/test/hexapdf/font/type1/test_afm_parser.rb +2 -2
  213. data/test/hexapdf/image_loader/test_jpeg.rb +1 -1
  214. data/test/hexapdf/image_loader/test_pdf.rb +1 -1
  215. data/test/hexapdf/image_loader/test_png.rb +3 -3
  216. data/test/hexapdf/layout/test_inline_box.rb +10 -1
  217. data/test/hexapdf/layout/test_line.rb +4 -4
  218. data/test/hexapdf/layout/test_style.rb +19 -7
  219. data/test/hexapdf/layout/test_text_fragment.rb +73 -27
  220. data/test/hexapdf/layout/test_text_layouter.rb +84 -68
  221. data/test/hexapdf/layout/test_text_shaper.rb +4 -6
  222. data/test/hexapdf/task/test_dereference.rb +2 -2
  223. data/test/hexapdf/task/test_optimize.rb +16 -7
  224. data/test/hexapdf/test_configuration.rb +1 -1
  225. data/test/hexapdf/test_data_dir.rb +2 -2
  226. data/test/hexapdf/test_dictionary.rb +6 -3
  227. data/test/hexapdf/test_dictionary_fields.rb +15 -14
  228. data/test/hexapdf/test_document.rb +47 -48
  229. data/test/hexapdf/test_filter.rb +30 -26
  230. data/test/hexapdf/test_importer.rb +14 -0
  231. data/test/hexapdf/test_object.rb +16 -4
  232. data/test/hexapdf/test_parser.rb +36 -36
  233. data/test/hexapdf/test_reference.rb +7 -5
  234. data/test/hexapdf/test_revision.rb +1 -1
  235. data/test/hexapdf/test_revisions.rb +90 -90
  236. data/test/hexapdf/test_serializer.rb +3 -2
  237. data/test/hexapdf/test_stream.rb +2 -4
  238. data/test/hexapdf/test_tokenizer.rb +2 -2
  239. data/test/hexapdf/test_writer.rb +80 -80
  240. data/test/hexapdf/test_xref_section.rb +1 -1
  241. data/test/hexapdf/type/annotations/test_link.rb +1 -1
  242. data/test/hexapdf/type/annotations/test_text.rb +3 -3
  243. data/test/hexapdf/type/test_font_descriptor.rb +1 -1
  244. data/test/hexapdf/type/test_font_simple.rb +2 -2
  245. data/test/hexapdf/type/test_font_type0.rb +0 -1
  246. data/test/hexapdf/type/test_image.rb +0 -3
  247. data/test/hexapdf/type/test_object_stream.rb +2 -1
  248. data/test/hexapdf/type/test_page.rb +5 -1
  249. data/test/hexapdf/type/test_page_tree_node.rb +4 -4
  250. data/test/hexapdf/type/test_trailer.rb +1 -1
  251. data/test/hexapdf/type/test_xref_stream.rb +4 -0
  252. data/test/hexapdf/utils/test_bit_field.rb +2 -0
  253. data/test/hexapdf/utils/test_bit_stream.rb +1 -1
  254. data/test/hexapdf/utils/test_lru_cache.rb +1 -1
  255. data/test/hexapdf/utils/test_sorted_tree_node.rb +10 -4
  256. data/test/test_helper.rb +3 -6
  257. metadata +3 -3
@@ -1,10 +1,10 @@
1
- # -*- encoding: utf-8 -*-
1
+ # -*- encoding: utf-8; frozen_string_literal: true -*-
2
2
  #
3
3
  #--
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2017 Thomas Leitner
7
+ # Copyright (C) 2014-2018 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -41,7 +41,14 @@ module HexaPDF
41
41
  # More efficient tokenizer for content streams. This tokenizer class works directly on a
42
42
  # string and not on an IO.
43
43
  #
44
- # Note: Indirect object references are *not* supported by this tokenizer!
44
+ # Changes:
45
+ #
46
+ # * Since a content stream is normally parsed front to back, a StopIteration error can be raised
47
+ # instead of returning +NO_MORE_TOKENS+ once the end of the string is reached to avoid costly
48
+ # checks in each iteration. If this behaviour is wanted, pass "raise_on_eos: true" in the
49
+ # constructor.
50
+ #
51
+ # * Indirect object references are *not* supported by this tokenizer!
45
52
  #
46
53
  # See: PDF1.7 s7.2
47
54
  class Tokenizer < HexaPDF::Tokenizer #:nodoc:
@@ -50,9 +57,10 @@ module HexaPDF
50
57
  attr_reader :string
51
58
 
52
59
  # Creates a new tokenizer.
53
- def initialize(string)
60
+ def initialize(string, raise_on_eos: false)
54
61
  @ss = StringScanner.new(string)
55
62
  @string = string
63
+ @raise_on_eos = raise_on_eos
56
64
  end
57
65
 
58
66
  # See: HexaPDF::Tokenizer#pos
@@ -104,10 +112,12 @@ module HexaPDF
104
112
  elsif byte == 123 || byte == 125 # { }
105
113
  Token.new(@ss.get_byte)
106
114
  elsif byte == 37 # %
107
- return NO_MORE_TOKENS unless @ss.skip_until(/(?=[\r\n])/)
115
+ unless @ss.skip_until(/(?=[\r\n])/)
116
+ (@raise_on_eos ? (raise StopIteration) : (return NO_MORE_TOKENS))
117
+ end
108
118
  next_token
109
119
  elsif byte == -1
110
- NO_MORE_TOKENS
120
+ @raise_on_eos ? raise(StopIteration) : NO_MORE_TOKENS
111
121
  else
112
122
  parse_keyword
113
123
  end
@@ -117,11 +127,11 @@ module HexaPDF
117
127
 
118
128
  # See: HexaPDF::Tokenizer#parse_number
119
129
  def parse_number
120
- if (val = @ss.scan(/[+-]?\d++(?!\.)/))
121
- val.to_i
122
- elsif (val = @ss.scan(/[+-]?(?:\d+\.\d*|\.\d+)/))
123
- val << '0'.freeze if val.getbyte(-1) == 46 # dot '.'
130
+ if (val = @ss.scan(/[+-]?(?:\d+\.\d*|\.\d+)/))
131
+ val << '0' if val.getbyte(-1) == 46 # dot '.'
124
132
  Float(val)
133
+ elsif (val = @ss.scan(/[+-]?\d++/))
134
+ val.to_i
125
135
  else
126
136
  parse_keyword
127
137
  end
@@ -133,7 +143,6 @@ module HexaPDF
133
143
 
134
144
  end
135
145
 
136
-
137
146
  # This class knows how to correctly parse a content stream.
138
147
  #
139
148
  # == Overview
@@ -156,11 +165,12 @@ module HexaPDF
156
165
 
157
166
  # Parses the contents and calls the processor object for each parsed operator.
158
167
  def parse(contents, processor)
159
- tokenizer = Tokenizer.new(contents)
168
+ tokenizer = Tokenizer.new(contents, raise_on_eos: true)
160
169
  params = []
161
- while (obj = tokenizer.next_object(allow_keyword: true)) != Tokenizer::NO_MORE_TOKENS
170
+ loop do
171
+ obj = tokenizer.next_object(allow_keyword: true)
162
172
  if obj.kind_of?(Tokenizer::Token)
163
- if obj == 'BI'.freeze
173
+ if obj == 'BI'
164
174
  params = parse_inline_image(tokenizer)
165
175
  end
166
176
  processor.process(obj.to_sym, params)
@@ -179,15 +189,15 @@ module HexaPDF
179
189
  def parse_inline_image(tokenizer)
180
190
  # BI has already been read, so read the image dictionary
181
191
  dict = {}
182
- while (key = tokenizer.next_object(allow_keyword: true))
183
- if key == 'ID'.freeze
192
+ while (key = tokenizer.next_object(allow_keyword: true) rescue Tokenizer::NO_MORE_TOKENS)
193
+ if key == 'ID'
184
194
  break
185
195
  elsif key == Tokenizer::NO_MORE_TOKENS
186
196
  raise HexaPDF::Error, "EOS while trying to read dictionary key for inline image"
187
197
  elsif !key.kind_of?(Symbol)
188
198
  raise HexaPDF::Error, "Inline image dictionary keys must be PDF name objects"
189
199
  end
190
- value = tokenizer.next_object
200
+ value = tokenizer.next_object rescue Tokenizer::NO_MORE_TOKENS
191
201
  if value == Tokenizer::NO_MORE_TOKENS
192
202
  raise HexaPDF::Error, "EOS while trying to read dictionary value for inline image"
193
203
  end
@@ -213,7 +223,7 @@ module HexaPDF
213
223
  # Check if we found EI inside of the image data
214
224
  count = 0
215
225
  while count < MAX_TOKEN_CHECK
216
- token = tokenizer.next_object(allow_keyword: true) rescue break
226
+ token = tokenizer.next_object(allow_keyword: true) rescue Tokenizer::NO_MORE_TOKENS
217
227
  if token == Tokenizer::NO_MORE_TOKENS
218
228
  count += MAX_TOKEN_CHECK
219
229
  elsif token.kind_of?(Tokenizer::Token) &&
@@ -1,10 +1,10 @@
1
- # -*- encoding: utf-8 -*-
1
+ # -*- encoding: utf-8; frozen_string_literal: true -*-
2
2
  #
3
3
  #--
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2017 Thomas Leitner
7
+ # Copyright (C) 2014-2018 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -145,7 +145,6 @@ module HexaPDF
145
145
 
146
146
  end
147
147
 
148
-
149
148
  # Represents a box composed of GlyphBox objects.
150
149
  #
151
150
  # The bounding box methods #lower_left, #lower_right, #upper_left, #upper_right are computed
@@ -387,10 +386,10 @@ module HexaPDF
387
386
  # text strings together with positioning information (+TJ+ operator).
388
387
  def decode_text(data)
389
388
  if data.kind_of?(Array)
390
- data = data.each_with_object(''.b) {|obj, result| result << obj if obj.kind_of?(String)}
389
+ data = data.each_with_object(''.b) {|obj, result| result << obj if obj.kind_of?(String) }
391
390
  end
392
391
  font = graphics_state.font
393
- font.decode(data).map {|code_point| font.to_utf8(code_point)}.join('')
392
+ font.decode(data).map {|code_point| font.to_utf8(code_point) }.join('')
394
393
  end
395
394
 
396
395
  # Decodes the given text object and returns it as a CompositeBox object.
@@ -1,10 +1,10 @@
1
- # -*- encoding: utf-8 -*-
1
+ # -*- encoding: utf-8; frozen_string_literal: true -*-
2
2
  #
3
3
  #--
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2017 Thomas Leitner
7
+ # Copyright (C) 2014-2018 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -1,10 +1,10 @@
1
- # -*- encoding: utf-8 -*-
1
+ # -*- encoding: utf-8; frozen_string_literal: true -*-
2
2
  #
3
3
  #--
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2017 Thomas Leitner
7
+ # Copyright (C) 2014-2018 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -1,10 +1,10 @@
1
- # -*- encoding: utf-8 -*-
1
+ # -*- encoding: utf-8; frozen_string_literal: true -*-
2
2
  #
3
3
  #--
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2017 Thomas Leitner
7
+ # Copyright (C) 2014-2018 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -130,7 +130,6 @@ module HexaPDF
130
130
  defined?(@type) && @type
131
131
  end
132
132
 
133
-
134
133
  # Returns the value for the given dictionary entry.
135
134
  #
136
135
  # This method should be used instead of direct access to the value because it provides
@@ -150,14 +149,14 @@ module HexaPDF
150
149
  field = self.class.field(name)
151
150
  data = if key?(name)
152
151
  value[name]
153
- elsif field && field.default?
152
+ elsif field&.default?
154
153
  value[name] = field.default
155
154
  end
156
155
  value[name] = data = document.deref(data) if data.kind_of?(HexaPDF::Reference)
157
156
  if data.class == HexaPDF::Object || (data.kind_of?(HexaPDF::Object) && data.value.nil?)
158
157
  data = data.value
159
158
  end
160
- self[name] = data = field.convert(data, document) if field && field.convert?(data)
159
+ self[name] = data = field.convert(data, document) if field&.convert?(data)
161
160
  data
162
161
  end
163
162
 
@@ -199,7 +198,7 @@ module HexaPDF
199
198
  # Note that the yielded value is already preprocessed like in #[].
200
199
  def each
201
200
  return to_enum(__method__) unless block_given?
202
- value.each_key {|name| yield(name, self[name])}
201
+ value.each_key {|name| yield(name, self[name]) }
203
202
  self
204
203
  end
205
204
 
@@ -244,7 +243,7 @@ module HexaPDF
244
243
 
245
244
  # Iterates over all currently set fields and those that are required.
246
245
  def each_set_key_or_required_field #:yields: name, field
247
- value.each_key {|name| yield(name, self.class.field(name))}
246
+ value.each_key {|name| yield(name, self.class.field(name)) }
248
247
  self.class.each_field do |name, field|
249
248
  yield(name, field) if field.required? && !value.key?(name)
250
249
  end
@@ -287,11 +286,11 @@ module HexaPDF
287
286
  obj = value[name] # we need the unwrapped object!
288
287
  if field.indirect && (!obj.kind_of?(HexaPDF::Object) || !obj.indirect?)
289
288
  yield("Field #{name} needs to be an indirect object", true)
290
- value[name] = obj = document.add(obj)
289
+ value[name] = document.add(obj)
291
290
  elsif !field.indirect && obj.kind_of?(HexaPDF::Object) && obj.indirect?
292
291
  yield("Field #{name} needs to be a direct object", true)
293
292
  document.delete(obj)
294
- value[name] = obj = obj.value
293
+ value[name] = obj.value
295
294
  end
296
295
  end
297
296
  end
@@ -1,10 +1,10 @@
1
- # -*- encoding: utf-8 -*-
1
+ # -*- encoding: utf-8; frozen_string_literal: true -*-
2
2
  #
3
3
  #--
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2017 Thomas Leitner
7
+ # Copyright (C) 2014-2018 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -94,10 +94,9 @@ module HexaPDF
94
94
  # two converters could potentially be used for the same type, the one that appears earlier
95
95
  # is used.
96
96
  def self.converter_for(type)
97
- @converters.find {|converter| converter.usable_for?(type)}
97
+ @converters.find {|converter| converter.usable_for?(type) }
98
98
  end
99
99
 
100
-
101
100
  # Returns +true+ if the value for this field needs to be an indirect object, +false+ if it
102
101
  # needs to be a direct object or +nil+ if it can be either.
103
102
  attr_reader :indirect
@@ -123,7 +122,7 @@ module HexaPDF
123
122
  @type.concat(Array(@converter.additional_types))
124
123
  @type.map! do |type|
125
124
  if type.kind_of?(Symbol)
126
- HexaPDF::GlobalConfiguration.constantize('object.type_map'.freeze, type)
125
+ HexaPDF::GlobalConfiguration.constantize('object.type_map', type)
127
126
  else
128
127
  type
129
128
  end
@@ -158,8 +157,8 @@ module HexaPDF
158
157
 
159
158
  # Returns +true+ if the given object is valid for this field.
160
159
  def valid_object?(obj)
161
- type.any? {|t| obj.kind_of?(t)} ||
162
- (obj.kind_of?(HexaPDF::Object) && type.any? {|t| obj.value.kind_of?(t)})
160
+ type.any? {|t| obj.kind_of?(t) } ||
161
+ (obj.kind_of?(HexaPDF::Object) && type.any? {|t| obj.value.kind_of?(t) })
163
162
  end
164
163
 
165
164
  # If a converter was defined, it is used. Otherwise +false+ is returned.
@@ -307,7 +306,7 @@ module HexaPDF
307
306
 
308
307
  # Returns +true+ if the given data should be converted to a Time object.
309
308
  def self.convert?(data, _type)
310
- data.kind_of?(String) && data =~ DATE_RE
309
+ data.kind_of?(String) && data.match?(DATE_RE)
311
310
  end
312
311
 
313
312
  # Converts the string into a Time object.
@@ -320,7 +319,6 @@ module HexaPDF
320
319
 
321
320
  end
322
321
 
323
-
324
322
  # Converter module for file specification fields. A file specification in string format is
325
323
  # converted to the corresponding file specification dictionary.
326
324
  module FileSpecificationConverter
@@ -349,7 +347,6 @@ module HexaPDF
349
347
 
350
348
  end
351
349
 
352
-
353
350
  # Converter module for fields of type Rectangle.
354
351
  module RectangleConverter
355
352
 
@@ -1,10 +1,10 @@
1
- # -*- encoding: utf-8 -*-
1
+ # -*- encoding: utf-8; frozen_string_literal: true -*-
2
2
  #
3
3
  #--
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2017 Thomas Leitner
7
+ # Copyright (C) 2014-2018 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -129,11 +129,11 @@ module HexaPDF
129
129
  @version = '1.2'
130
130
 
131
131
  @revisions = Revisions.from_io(self, io)
132
- if encrypted? && @config['document.auto_decrypt']
133
- @security_handler = Encryption::SecurityHandler.set_up_decryption(self, decryption_opts)
134
- else
135
- @security_handler = nil
136
- end
132
+ @security_handler = if encrypted? && @config['document.auto_decrypt']
133
+ Encryption::SecurityHandler.set_up_decryption(self, decryption_opts)
134
+ else
135
+ nil
136
+ end
137
137
 
138
138
  @listeners = {}
139
139
  @cache = Hash.new {|h, k| h[k] = {} }
@@ -178,7 +178,7 @@ module HexaPDF
178
178
  # because this method takes *all* revisions into account. Also see the discussion on #each for
179
179
  # more information.
180
180
  def object?(ref)
181
- @revisions.any? {|rev| rev.object?(ref)}
181
+ @revisions.any? {|rev| rev.object?(ref) }
182
182
  end
183
183
 
184
184
  # :call-seq:
@@ -241,7 +241,7 @@ module HexaPDF
241
241
  when :current
242
242
  @revisions.current.delete(ref, mark_as_free: mark_as_free)
243
243
  when :all
244
- @revisions.each {|rev| rev.delete(ref, mark_as_free: mark_as_free)}
244
+ @revisions.each {|rev| rev.delete(ref, mark_as_free: mark_as_free) }
245
245
  else
246
246
  raise ArgumentError, "Unsupported option revision: #{revision}"
247
247
  end
@@ -318,14 +318,14 @@ module HexaPDF
318
318
  type = (klass <= HexaPDF::Dictionary ? klass.type : nil)
319
319
  else
320
320
  type ||= deref(data.value[:Type]) if data.value.kind_of?(Hash)
321
- klass = GlobalConfiguration.constantize('object.type_map'.freeze, type) { nil } if type
321
+ klass = GlobalConfiguration.constantize('object.type_map', type) { nil } if type
322
322
  end
323
323
 
324
324
  if data.value.kind_of?(Hash)
325
325
  subtype ||= deref(data.value[:Subtype]) || deref(data.value[:S])
326
326
  end
327
327
  if subtype
328
- klass = GlobalConfiguration.constantize('object.subtype_map'.freeze, type, subtype) { klass }
328
+ klass = GlobalConfiguration.constantize('object.subtype_map', type, subtype) { klass }
329
329
  end
330
330
 
331
331
  klass ||= if data.stream
@@ -354,10 +354,10 @@ module HexaPDF
354
354
  case object
355
355
  when Hash
356
356
  seen[object] = true
357
- object.each_with_object({}) {|(key, val), memo| memo[key] = unwrap(val, seen.dup)}
357
+ object.each_with_object({}) {|(key, val), memo| memo[key] = unwrap(val, seen.dup) }
358
358
  when Array
359
359
  seen[object] = true
360
- object.map {|inner_o| unwrap(inner_o, seen.dup)}
360
+ object.map {|inner_o| unwrap(inner_o, seen.dup) }
361
361
  when HexaPDF::PDFData
362
362
  seen[object] = true
363
363
  unwrap(object.value, seen.dup)
@@ -415,7 +415,7 @@ module HexaPDF
415
415
 
416
416
  # Dispatches the message +name+ with the given arguments to all registered listeners.
417
417
  def dispatch_message(name, *args)
418
- @listeners[name] && @listeners[name].each {|obj| obj.call(*args)}
418
+ @listeners[name]&.each {|obj| obj.call(*args) }
419
419
  end
420
420
 
421
421
  # Caches the value or the return value of the given block using the given Object::PDFData and
@@ -477,7 +477,7 @@ module HexaPDF
477
477
  #
478
478
  # See Task for more information.
479
479
  def task(name, **opts, &block)
480
- task = config.constantize('task.map'.freeze, name) do
480
+ task = config.constantize('task.map', name) do
481
481
  raise HexaPDF::Error, "No task named '#{name}' is available"
482
482
  end
483
483
  task.call(self, **opts, &block)
@@ -501,14 +501,14 @@ module HexaPDF
501
501
  #
502
502
  # See: PDF1.7 s7.2.2
503
503
  def version
504
- catalog_version = (catalog[:Version] || '1.0'.freeze).to_s
504
+ catalog_version = (catalog[:Version] || '1.0').to_s
505
505
  (@version < catalog_version ? catalog_version : @version)
506
506
  end
507
507
 
508
508
  # Sets the version of the PDF document. The argument must be a string in the format 'M.N'
509
509
  # where M is the major version and N the minor version (e.g. '1.4' or '2.0').
510
510
  def version=(value)
511
- raise ArgumentError, "PDF version must follow format M.N" unless value.to_s =~ /\A\d\.\d\z/
511
+ raise ArgumentError, "PDF version must follow format M.N" unless value.to_s.match?(/\A\d\.\d\z/)
512
512
  @version = value.to_s
513
513
  end
514
514
 
@@ -615,7 +615,7 @@ module HexaPDF
615
615
  dispatch_message(:before_write)
616
616
 
617
617
  if file_or_io.kind_of?(String)
618
- File.open(file_or_io, 'w+') {|file| Writer.write(self, file)}
618
+ File.open(file_or_io, 'w+') {|file| Writer.write(self, file) }
619
619
  else
620
620
  Writer.write(self, file_or_io)
621
621
  end
@@ -1,10 +1,10 @@
1
- # -*- encoding: utf-8 -*-
1
+ # -*- encoding: utf-8; frozen_string_literal: true -*-
2
2
  #
3
3
  #--
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2017 Thomas Leitner
7
+ # Copyright (C) 2014-2018 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -49,8 +49,8 @@ module HexaPDF
49
49
  end
50
50
 
51
51
  # :call-seq:
52
- # files.add(filename, name: File.basename(filename), description: nil, embed: true) -> file_spec
53
- # files.add(io, name:, description: nil) -> file_spec
52
+ # files.add(filename, name: nil, description: nil, embed: true) -> file_spec
53
+ # files.add(io, name:, description: nil) -> file_spec
54
54
  #
55
55
  # Adds the file or IO to the PDF document and returns the corresponding file specification
56
56
  # object.
@@ -58,8 +58,11 @@ module HexaPDF
58
58
  # Options:
59
59
  #
60
60
  # name::
61
- # The name that should be used for the file path. This name is also for registering the
62
- # file in the EmbeddedFiles name tree.
61
+ # The name that should be used for the file path. This name is also used for registering
62
+ # the file in the EmbeddedFiles name tree.
63
+ #
64
+ # When a filename is given, the basename of the file is used by default for +name+ if it
65
+ # is not specified.
63
66
  #
64
67
  # description::
65
68
  # A description of the file.
@@ -104,14 +107,13 @@ module HexaPDF
104
107
  else
105
108
  seen = {}
106
109
  tree = @document.catalog[:Names] && @document.catalog[:Names][:EmbeddedFiles]
107
- tree.each_entry do |_, spec|
110
+ tree&.each_entry do |_, spec|
108
111
  seen[spec] = true
109
112
  yield(spec)
110
- end if tree
113
+ end
111
114
 
112
115
  @document.pages.each do |page|
113
- next unless page[:Annots]
114
- page[:Annots].each do |annot|
116
+ page[:Annots]&.each do |annot|
115
117
  annot = @document.deref(annot)
116
118
  next unless annot[:Subtype] == :FileAttachment
117
119
  spec = @document.deref(annot[:FS])