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
@@ -162,7 +162,7 @@ module HexaPDF
162
162
  if @color_type == INDEXED
163
163
  trns = io.read(length).unpack('C*')
164
164
  elsif @color_type == TRUECOLOR || @color_type == GREYSCALE
165
- dict[:Mask] = io.read(length).unpack('n*').map {|val| [val, val]}.flatten
165
+ dict[:Mask] = io.read(length).unpack('n*').map {|val| [val, val] }.flatten
166
166
  else
167
167
  io.seek(length, IO::SEEK_CUR)
168
168
  end
@@ -179,7 +179,7 @@ module HexaPDF
179
179
  end
180
180
  when 'cHRM' # PNG s11.3.3.1
181
181
  chrm = io.read(length)
182
- @chrm = chrm.unpack('N8').map {|v| v / 100_000.0} unless @intent # sRGB trumps cHRM
182
+ @chrm = chrm.unpack('N8').map {|v| v / 100_000.0 } unless @intent # sRGB trumps cHRM
183
183
  else
184
184
  io.seek(length, IO::SEEK_CUR)
185
185
  end
@@ -320,7 +320,7 @@ module HexaPDF
320
320
  length, type = io.read(8).unpack('Na4') # PNG s5.3
321
321
  break if type != 'IDAT'
322
322
 
323
- chunk_size = @document.config['io.chunk_size'.freeze]
323
+ chunk_size = @document.config['io.chunk_size']
324
324
  while length > 0
325
325
  chunk_size = length if chunk_size > length
326
326
  Fiber.yield(io.read(chunk_size))
@@ -363,7 +363,7 @@ module HexaPDF
363
363
  mask_data << data.byteslice(i, bytes_per_alpha)
364
364
  i += bytes_per_alpha
365
365
  end
366
- data[0, bytes_per_row] = ''.freeze
366
+ data[0, bytes_per_row] = ''
367
367
  end
368
368
  end
369
369
 
@@ -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
@@ -50,16 +50,18 @@ module HexaPDF
50
50
  class Importer
51
51
 
52
52
  class NullableWeakRef < WeakRef #:nodoc:
53
+
53
54
  def __getobj__ #:nodoc:
54
55
  super rescue nil
55
56
  end
57
+
56
58
  end
57
59
 
58
60
  # Returns the Importer object for copying objects from the +source+ to the +destination+
59
61
  # document.
60
62
  def self.for(source:, destination:)
61
63
  @map ||= {}
62
- @map.keep_if {|_, v| v.source.weakref_alive? && v.destination.weakref_alive?}
64
+ @map.keep_if {|_, v| v.source.weakref_alive? && v.destination.weakref_alive? }
63
65
  source = NullableWeakRef.new(source)
64
66
  destination = NullableWeakRef.new(destination)
65
67
  @map[[source.hash, destination.hash]] ||= new(source: source, destination: destination)
@@ -108,7 +110,7 @@ module HexaPDF
108
110
  obj[k] = duplicate(v)
109
111
  end
110
112
  when Array
111
- object.map {|v| duplicate(v)}
113
+ object.map {|v| duplicate(v) }
112
114
  when HexaPDF::Reference
113
115
  import(@source.object(object))
114
116
  when HexaPDF::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
@@ -69,8 +69,8 @@ module HexaPDF
69
69
  attr_reader :style
70
70
 
71
71
  # :call-seq:
72
- # Box.new(content_width: 0, content_height: 0, style: Style.new) {|canvas, box| block} -> box
73
- # Box.new(width: 0, height: 0, style: Style.new) {|canvas, box| block} -> box
72
+ # Box.new(content_width: 0, content_height: 0, style: Style.new) {|canv, box| block} -> box
73
+ # Box.new(width: 0, height: 0, style: Style.new) {|canv, box| block} -> box
74
74
  #
75
75
  # Creates a new Box object with the given width and height for its content that uses the
76
76
  # provided block when it is asked to draw itself on a canvas (see #draw).
@@ -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
@@ -93,7 +93,7 @@ module HexaPDF
93
93
  # Creates a new calculator with the given initial items.
94
94
  def initialize(items = [])
95
95
  reset
96
- items.each {|item| add(item)}
96
+ items.each {|item| add(item) }
97
97
  end
98
98
 
99
99
  # Adds a new item to be considered when calculating the various dimensions.
@@ -117,7 +117,7 @@ module HexaPDF
117
117
  end
118
118
  self
119
119
  end
120
- alias_method :<<, :add
120
+ alias << add
121
121
 
122
122
  # Returns the result of the calculations, the array [y_min, y_max, text_y_min, text_y_max].
123
123
  #
@@ -182,7 +182,7 @@ module HexaPDF
182
182
  # Creates a new Line object, adding all given items to it.
183
183
  def initialize(items = [])
184
184
  @items = []
185
- items.each {|i| add(i)}
185
+ items.each {|i| add(i) }
186
186
  @x_offset = 0
187
187
  @y_offset = 0
188
188
  end
@@ -207,7 +207,7 @@ module HexaPDF
207
207
  end
208
208
  self
209
209
  end
210
- alias :<< :add
210
+ alias << add
211
211
 
212
212
  # :call-seq:
213
213
  # line.each {|item, x, y| block }
@@ -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
@@ -466,7 +466,8 @@ module HexaPDF
466
466
  @border_color = border_color
467
467
  end
468
468
 
469
- # Creates the needed link annotation if possible, i.e. if the context of the canvas is a page.
469
+ # Creates the needed link annotation if possible, i.e. if the context of the canvas is a
470
+ # page.
470
471
  def call(canvas, box)
471
472
  return unless canvas.context.type == :Page
472
473
  page = canvas.context
@@ -493,16 +494,25 @@ module HexaPDF
493
494
 
494
495
  # Creates a new Style object.
495
496
  #
496
- # The +options+ hash may be used to set the initial values of properties by using keys
497
+ # The +properties+ hash may be used to set the initial values of properties by using keys
497
498
  # equivalent to the property names.
498
499
  #
499
500
  # Example:
500
501
  # Style.new(font_size: 15, align: :center, valign: center)
501
- def initialize(**options)
502
- options.each {|key, value| send(key, value)}
502
+ def initialize(**properties)
503
+ update(properties)
503
504
  @scaled_item_widths = {}
504
505
  end
505
506
 
507
+ # :call-seq:
508
+ # style.update(**properties) -> style
509
+ #
510
+ # Updates the style's properties using the key-value pairs specified by the +properties+ hash.
511
+ def update(**properties)
512
+ properties.each {|key, value| send(key, value) }
513
+ self
514
+ end
515
+
506
516
  ##
507
517
  # :method: font
508
518
  # :call-seq:
@@ -799,7 +809,6 @@ module HexaPDF
799
809
  alias_method("#{name}=", name)
800
810
  end
801
811
 
802
-
803
812
  ##
804
813
  # :method: text_segmentation_algorithm
805
814
  # :call-seq:
@@ -945,7 +954,7 @@ module HexaPDF
945
954
 
946
955
  # Returns the default color for an empty PDF page, i.e. black.
947
956
  def default_color
948
- GlobalConfiguration.constantize('color_space.map'.freeze, :DeviceGray).new.default_color
957
+ GlobalConfiguration.constantize('color_space.map', :DeviceGray).new.default_color
949
958
  end
950
959
 
951
960
  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
@@ -58,10 +58,12 @@ module HexaPDF
58
58
 
59
59
  # Creates a new TextFragment object for the given text, shapes it and returns it.
60
60
  #
61
- # The style of the text fragment can be specified using additional options, of which font is
62
- # mandatory.
63
- def self.create(text, font:, **options)
64
- fragment = new(items: font.decode_utf8(text), style: Style.new(font: font, **options))
61
+ # The needed style of the text fragment can either be specified by the +style+ argument or via
62
+ # the +options+ (in which case a new Style object is created). Regardless of the way, the
63
+ # resulting style object needs at least the font set.
64
+ def self.create(text, style = nil, **options)
65
+ style = (style.nil? ? Style.new(options) : style)
66
+ fragment = new(style.font.decode_utf8(text), style)
65
67
  TextShaper.new.shape_text(fragment)
66
68
  end
67
69
 
@@ -99,64 +101,100 @@ module HexaPDF
99
101
  # Creates a new TextFragment object with the given items and style.
100
102
  #
101
103
  # The argument +style+ can either be a Style object or a hash of style options.
102
- def initialize(items:, style: Style.new)
103
- @items = items || []
104
+ def initialize(items, style)
105
+ @items = items
104
106
  @style = (style.kind_of?(Style) ? style : Style.new(style))
105
107
  end
106
108
 
109
+ # The precision used to determine whether two floats represent the same value.
110
+ PRECISION = 0.000001 # :nodoc:
111
+
107
112
  # Draws the text onto the canvas at the given position.
108
113
  #
109
- # Before the text is drawn using HexaPDF::Content;:Canvas#show_glyphs, the text properties
110
- # mentioned in the description of #style are set.
111
- def draw(canvas, x, y)
112
- return if items.empty?
113
-
114
+ # This method is the main styled text drawing facility and therefore some optimizations are
115
+ # done:
116
+ #
117
+ # * The text is drawn using HexaPDF::Content;:Canvas#show_glyphs_only which means that the
118
+ # text matrix is *not* updated. Therefore the caller must *not* rely on it!
119
+ #
120
+ # * All text style properties mentioned in the description of #style are set except if
121
+ # +ignore_text_properties+ is set to +true+. Note that this only applies to style properties
122
+ # that directly affect text drawing, so, for example, underlays/overlays and
123
+ # underlining/strikeout is always done.
124
+ #
125
+ # The caller should set +ignore_text_properties+ to +true+ if the graphics state hasn't been
126
+ # changed. This is the case, for example, if the last thing drawn was a text fragment with
127
+ # the same style.
128
+ #
129
+ # * It is assumed that the text matrix is not rotated, skewed, etc. so that setting the text
130
+ # position can be done using the optimal method.
131
+ def draw(canvas, x, y, ignore_text_properties: false)
114
132
  style.underlays.draw(canvas, x, y + y_min, self)
115
133
 
116
- # Set general font related graphics state
117
- canvas.move_text_cursor(offset: [x, y])
118
- canvas.font(style.font, size: style.calculated_font_size).
119
- horizontal_scaling(style.horizontal_scaling).
120
- character_spacing(style.character_spacing).
121
- word_spacing(style.word_spacing).
122
- text_rise(style.calculated_text_rise).
123
- text_rendering_mode(style.text_rendering_mode)
124
-
125
- # Set fill and/or stroke related graphics state
126
- canvas.opacity(fill_alpha: style.fill_alpha, stroke_alpha: style.stroke_alpha)
127
- trm = canvas.text_rendering_mode
128
- if trm.value.even? # text is filled
129
- canvas.fill_color(style.fill_color)
130
- end
131
- if trm == :stroke || trm == :fill_stroke || trm == :stroke_clip || trm == :fill_stroke_clip
132
- canvas.stroke_color(style.stroke_color).
133
- line_width(style.stroke_width).
134
- line_cap_style(style.stroke_cap_style).
135
- line_join_style(style.stroke_join_style).
136
- miter_limit(style.stroke_miter_limit).
137
- line_dash_pattern(style.stroke_dash_pattern)
134
+ # Set general font related graphics state if necessary
135
+ unless ignore_text_properties
136
+ canvas.font(style.font, size: style.calculated_font_size).
137
+ horizontal_scaling(style.horizontal_scaling).
138
+ character_spacing(style.character_spacing).
139
+ word_spacing(style.word_spacing).
140
+ text_rise(style.calculated_text_rise).
141
+ text_rendering_mode(style.text_rendering_mode)
142
+
143
+ # Set fill and/or stroke related graphics state
144
+ canvas.opacity(fill_alpha: style.fill_alpha, stroke_alpha: style.stroke_alpha)
145
+ trm = canvas.text_rendering_mode
146
+ if trm.value.even? # text is filled
147
+ canvas.fill_color(style.fill_color)
148
+ end
149
+ if trm == :stroke || trm == :fill_stroke || trm == :stroke_clip || trm == :fill_stroke_clip
150
+ canvas.stroke_color(style.stroke_color).
151
+ line_width(style.stroke_width).
152
+ line_cap_style(style.stroke_cap_style).
153
+ line_join_style(style.stroke_join_style).
154
+ miter_limit(style.stroke_miter_limit).
155
+ line_dash_pattern(style.stroke_dash_pattern)
156
+ end
138
157
  end
139
158
 
159
+ canvas.begin_text
160
+ tlm = canvas.graphics_state.tlm
161
+ tx = x - tlm.e
162
+ ty = y - tlm.f
163
+ if tx.abs < PRECISION
164
+ if (ty + canvas.graphics_state.leading).abs < PRECISION
165
+ canvas.move_text_cursor
166
+ else
167
+ canvas.move_text_cursor(offset: [0, ty], absolute: false)
168
+ end
169
+ elsif ty.abs < PRECISION
170
+ canvas.move_text_cursor(offset: [tx, 0], absolute: false)
171
+ else
172
+ canvas.move_text_cursor(offset: [x, y])
173
+ end
140
174
  canvas.show_glyphs_only(items)
141
175
 
142
176
  if style.underline
143
177
  y_offset = style.calculated_underline_position
144
- canvas.stroke_color(style.fill_color).
145
- line_width(style.calculated_underline_thickness).
146
- line_cap_style(:butt).
147
- line_dash_pattern(0).
148
- line(x, y + y_offset, x + width, y + y_offset).
149
- stroke
178
+ canvas.save_graphics_state do
179
+ canvas.stroke_color(style.fill_color).
180
+ line_width(style.calculated_underline_thickness).
181
+ line_cap_style(:butt).
182
+ line_dash_pattern(0).
183
+ line(x, y + y_offset, x + width, y + y_offset).
184
+ stroke
185
+ end
150
186
  end
151
187
 
152
188
  if style.strikeout
153
189
  y_offset = style.calculated_strikeout_position
154
- canvas.stroke_color(style.fill_color).
155
- line_width(style.calculated_strikeout_thickness).
156
- line_cap_style(:butt).
157
- line_dash_pattern(0).
158
- line(x, y + y_offset, x + width, y + y_offset).
159
- stroke
190
+ canvas.save_graphics_state do
191
+ canvas.stroke_color(style.fill_color).
192
+ line_width(style.calculated_strikeout_thickness).
193
+ line_cap_style(:butt).
194
+ line_dash_pattern(0).
195
+ line(x, y + y_offset, x + width, y + y_offset).
196
+ stroke
197
+ end
160
198
  end
161
199
 
162
200
  style.overlays.draw(canvas, x, y + y_min, self)
@@ -200,7 +238,7 @@ module HexaPDF
200
238
  # in PDF1.7 s9.4.4. By using kerning values as the first and/or last items, the text contained
201
239
  # in the fragment may spill over the left and/or right boundary.
202
240
  def width
203
- @width ||= @items.sum {|item| style.scaled_item_width(item)}
241
+ @width ||= @items.sum {|item| style.scaled_item_width(item) }
204
242
  end
205
243
 
206
244
  # The height of the text fragment.