hexapdf 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/CONTRIBUTERS +1 -1
  4. data/Rakefile +35 -50
  5. data/VERSION +1 -1
  6. data/lib/hexapdf/cli.rb +4 -0
  7. data/lib/hexapdf/cli/command.rb +6 -2
  8. data/lib/hexapdf/cli/image2pdf.rb +141 -0
  9. data/lib/hexapdf/cli/info.rb +1 -1
  10. data/lib/hexapdf/cli/inspect.rb +32 -2
  11. data/lib/hexapdf/cli/modify.rb +1 -1
  12. data/lib/hexapdf/cli/optimize.rb +1 -1
  13. data/lib/hexapdf/cli/watermark.rb +130 -0
  14. data/lib/hexapdf/composer.rb +2 -2
  15. data/lib/hexapdf/configuration.rb +7 -1
  16. data/lib/hexapdf/content/canvas.rb +2 -2
  17. data/lib/hexapdf/content/graphic_object/arc.rb +2 -2
  18. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +2 -2
  19. data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
  20. data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
  21. data/lib/hexapdf/dictionary.rb +11 -3
  22. data/lib/hexapdf/dictionary_fields.rb +32 -3
  23. data/lib/hexapdf/document.rb +7 -3
  24. data/lib/hexapdf/document/files.rb +1 -1
  25. data/lib/hexapdf/document/fonts.rb +21 -1
  26. data/lib/hexapdf/document/pages.rb +2 -2
  27. data/lib/hexapdf/encryption/standard_security_handler.rb +2 -2
  28. data/lib/hexapdf/font/cmap/parser.rb +1 -1
  29. data/lib/hexapdf/font/true_type/table/head.rb +2 -2
  30. data/lib/hexapdf/font/true_type/table/os2.rb +4 -4
  31. data/lib/hexapdf/font/true_type_wrapper.rb +16 -16
  32. data/lib/hexapdf/font/type1_wrapper.rb +16 -16
  33. data/lib/hexapdf/font_loader.rb +2 -0
  34. data/lib/hexapdf/font_loader/from_configuration.rb +5 -0
  35. data/lib/hexapdf/font_loader/standard14.rb +5 -0
  36. data/lib/hexapdf/image_loader/png.rb +1 -1
  37. data/lib/hexapdf/layout/box.rb +2 -2
  38. data/lib/hexapdf/layout/image_box.rb +1 -1
  39. data/lib/hexapdf/layout/style.rb +50 -24
  40. data/lib/hexapdf/layout/text_box.rb +1 -1
  41. data/lib/hexapdf/layout/text_fragment.rb +2 -2
  42. data/lib/hexapdf/layout/text_layouter.rb +14 -10
  43. data/lib/hexapdf/name_tree_node.rb +3 -3
  44. data/lib/hexapdf/number_tree_node.rb +3 -3
  45. data/lib/hexapdf/pdf_array.rb +207 -0
  46. data/lib/hexapdf/rectangle.rb +12 -12
  47. data/lib/hexapdf/serializer.rb +1 -1
  48. data/lib/hexapdf/stream.rb +6 -4
  49. data/lib/hexapdf/task/optimize.rb +3 -3
  50. data/lib/hexapdf/type.rb +2 -0
  51. data/lib/hexapdf/type/acro_form.rb +51 -0
  52. data/lib/hexapdf/type/acro_form/field.rb +129 -0
  53. data/lib/hexapdf/type/acro_form/form.rb +124 -0
  54. data/lib/hexapdf/type/action.rb +1 -1
  55. data/lib/hexapdf/type/actions/go_to.rb +1 -1
  56. data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
  57. data/lib/hexapdf/type/actions/launch.rb +1 -1
  58. data/lib/hexapdf/type/annotation.rb +2 -2
  59. data/lib/hexapdf/type/annotations.rb +1 -0
  60. data/lib/hexapdf/type/annotations/link.rb +4 -15
  61. data/lib/hexapdf/type/annotations/markup_annotation.rb +2 -1
  62. data/lib/hexapdf/type/annotations/text.rb +3 -6
  63. data/lib/hexapdf/type/annotations/widget.rb +90 -0
  64. data/lib/hexapdf/type/catalog.rb +12 -9
  65. data/lib/hexapdf/type/cid_font.rb +3 -3
  66. data/lib/hexapdf/type/file_specification.rb +2 -2
  67. data/lib/hexapdf/type/font_descriptor.rb +5 -2
  68. data/lib/hexapdf/type/font_simple.rb +1 -1
  69. data/lib/hexapdf/type/font_type0.rb +1 -1
  70. data/lib/hexapdf/type/font_type3.rb +1 -1
  71. data/lib/hexapdf/type/form.rb +2 -2
  72. data/lib/hexapdf/type/graphics_state_parameter.rb +11 -6
  73. data/lib/hexapdf/type/icon_fit.rb +58 -0
  74. data/lib/hexapdf/type/image.rb +14 -8
  75. data/lib/hexapdf/type/info.rb +2 -1
  76. data/lib/hexapdf/type/page.rb +4 -4
  77. data/lib/hexapdf/type/page_tree_node.rb +3 -7
  78. data/lib/hexapdf/type/resources.rb +1 -1
  79. data/lib/hexapdf/type/trailer.rb +4 -4
  80. data/lib/hexapdf/type/viewer_preferences.rb +7 -4
  81. data/lib/hexapdf/type/xref_stream.rb +2 -2
  82. data/lib/hexapdf/utils/sorted_tree_node.rb +1 -1
  83. data/lib/hexapdf/version.rb +1 -1
  84. data/man/man1/hexapdf.1 +77 -8
  85. data/test/hexapdf/content/test_canvas.rb +2 -2
  86. data/test/hexapdf/content/test_processor.rb +3 -3
  87. data/test/hexapdf/document/test_files.rb +4 -4
  88. data/test/hexapdf/document/test_fonts.rb +13 -1
  89. data/test/hexapdf/document/test_images.rb +6 -6
  90. data/test/hexapdf/document/test_pages.rb +8 -8
  91. data/test/hexapdf/encryption/test_security_handler.rb +7 -7
  92. data/test/hexapdf/encryption/test_standard_security_handler.rb +5 -5
  93. data/test/hexapdf/font/test_true_type_wrapper.rb +2 -2
  94. data/test/hexapdf/font_loader/test_from_configuration.rb +4 -0
  95. data/test/hexapdf/font_loader/test_standard14.rb +10 -0
  96. data/test/hexapdf/image_loader/test_jpeg.rb +1 -1
  97. data/test/hexapdf/image_loader/test_png.rb +3 -3
  98. data/test/hexapdf/layout/test_box.rb +2 -2
  99. data/test/hexapdf/layout/test_frame.rb +1 -1
  100. data/test/hexapdf/layout/test_image_box.rb +1 -1
  101. data/test/hexapdf/layout/test_style.rb +18 -13
  102. data/test/hexapdf/layout/test_text_box.rb +1 -1
  103. data/test/hexapdf/layout/test_text_layouter.rb +11 -6
  104. data/test/hexapdf/task/test_dereference.rb +2 -2
  105. data/test/hexapdf/task/test_optimize.rb +11 -11
  106. data/test/hexapdf/test_composer.rb +1 -1
  107. data/test/hexapdf/test_dictionary.rb +10 -2
  108. data/test/hexapdf/test_dictionary_fields.rb +27 -3
  109. data/test/hexapdf/test_document.rb +16 -15
  110. data/test/hexapdf/test_importer.rb +4 -4
  111. data/test/hexapdf/test_object.rb +1 -1
  112. data/test/hexapdf/test_pdf_array.rb +162 -0
  113. data/test/hexapdf/test_rectangle.rb +3 -5
  114. data/test/hexapdf/test_serializer.rb +1 -1
  115. data/test/hexapdf/test_stream.rb +1 -0
  116. data/test/hexapdf/test_writer.rb +3 -3
  117. data/test/hexapdf/type/acro_form/test_field.rb +85 -0
  118. data/test/hexapdf/type/acro_form/test_form.rb +69 -0
  119. data/test/hexapdf/type/annotations/test_text.rb +2 -6
  120. data/test/hexapdf/type/annotations/test_widget.rb +24 -0
  121. data/test/hexapdf/type/test_annotation.rb +1 -1
  122. data/test/hexapdf/type/test_catalog.rb +1 -1
  123. data/test/hexapdf/type/test_cid_font.rb +3 -3
  124. data/test/hexapdf/type/test_font.rb +2 -2
  125. data/test/hexapdf/type/test_font_descriptor.rb +2 -1
  126. data/test/hexapdf/type/test_font_simple.rb +3 -3
  127. data/test/hexapdf/type/test_font_true_type.rb +6 -6
  128. data/test/hexapdf/type/test_font_type0.rb +5 -5
  129. data/test/hexapdf/type/test_font_type1.rb +8 -8
  130. data/test/hexapdf/type/test_font_type3.rb +4 -4
  131. data/test/hexapdf/type/test_image.rb +16 -12
  132. data/test/hexapdf/type/test_page.rb +11 -11
  133. data/test/hexapdf/type/test_page_tree_node.rb +20 -20
  134. data/test/hexapdf/type/test_resources.rb +6 -6
  135. data/test/hexapdf/type/test_trailer.rb +5 -2
  136. data/test/hexapdf/type/test_xref_stream.rb +1 -0
  137. data/test/hexapdf/utils/test_sorted_tree_node.rb +35 -35
  138. metadata +23 -7
  139. data/test/hexapdf/type/annotations/test_link.rb +0 -19
@@ -54,7 +54,7 @@ module HexaPDF
54
54
  define_field :Subtype, type: Symbol, required: true, default: :Type0
55
55
  define_field :BaseFont, type: Symbol, required: true
56
56
  define_field :Encoding, type: [Stream, Symbol], required: true
57
- define_field :DescendantFonts, type: Array, required: true
57
+ define_field :DescendantFonts, type: PDFArray, required: true
58
58
 
59
59
  # Returns the CID font of this type 0 font.
60
60
  def descendant_font
@@ -47,7 +47,7 @@ module HexaPDF
47
47
  define_field :Subtype, type: Symbol, required: true, default: :Type3
48
48
  define_field :Name, type: Symbol
49
49
  define_field :FontBBox, type: Rectangle, required: true
50
- define_field :FontMatrix, type: Array, required: true
50
+ define_field :FontMatrix, type: PDFArray, required: true
51
51
  define_field :CharProcs, type: Dictionary, required: true
52
52
  define_field :Resources, type: Dictionary, version: '1.2'
53
53
 
@@ -49,9 +49,9 @@ module HexaPDF
49
49
 
50
50
  define_field :Type, type: Symbol, default: type
51
51
  define_field :Subtype, type: Symbol, required: true, default: :Form
52
- define_field :FormType, type: Integer, default: 1
52
+ define_field :FormType, type: Integer, default: 1, allowed_values: 1
53
53
  define_field :BBox, type: Rectangle, required: true
54
- define_field :Matrix, type: Array
54
+ define_field :Matrix, type: PDFArray, default: [1, 0, 0, 1, 0, 0]
55
55
  define_field :Resources, type: :XXResources, version: '1.2'
56
56
  define_field :Group, type: Dictionary, version: '1.4'
57
57
  define_field :Ref, type: Dictionary, version: '1.4'
@@ -35,6 +35,7 @@
35
35
  #++
36
36
 
37
37
  require 'hexapdf/dictionary'
38
+ require 'hexapdf/content/graphics_state'
38
39
 
39
40
  module HexaPDF
40
41
  module Type
@@ -55,23 +56,27 @@ module HexaPDF
55
56
  define_field :LC, type: Integer, version: "1.3"
56
57
  define_field :LJ, type: Integer, version: "1.3"
57
58
  define_field :ML, type: Numeric, version: "1.3"
58
- define_field :D, type: Array, version: "1.3"
59
- define_field :RI, type: Symbol, version: "1.3"
59
+ define_field :D, type: PDFArray, version: "1.3"
60
+ define_field :RI, type: Symbol, version: "1.3",
61
+ allowed_values: [HexaPDF::Content::RenderingIntent::ABSOLUTE_COLORIMETRIC,
62
+ HexaPDF::Content::RenderingIntent::RELATIVE_COLORIMETRIC,
63
+ HexaPDF::Content::RenderingIntent::SATURATION,
64
+ HexaPDF::Content::RenderingIntent::PERCEPTUAL]
60
65
  define_field :OP, type: Boolean
61
66
  define_field :op, type: Boolean, version: "1.3"
62
67
  define_field :OPM, type: Integer, version: "1.3"
63
- define_field :Font, type: Array, version: "1.3"
68
+ define_field :Font, type: PDFArray, version: "1.3"
64
69
  define_field :BG, type: [Dictionary, Stream]
65
70
  define_field :BG2, type: [Dictionary, Stream, Symbol], version: "1.3"
66
71
  define_field :UCR, type: [Dictionary, Stream]
67
72
  define_field :UCR2, type: [Dictionary, Stream, Symbol], version: "1.3"
68
- define_field :TR, type: [Dictionary, Stream, Array, Symbol]
69
- define_field :TR2, type: [Dictionary, Stream, Array, Symbol], version: "1.3"
73
+ define_field :TR, type: [Dictionary, Stream, PDFArray, Symbol]
74
+ define_field :TR2, type: [Dictionary, Stream, PDFArray, Symbol], version: "1.3"
70
75
  define_field :HT, type: [Dictionary, Stream, Symbol]
71
76
  define_field :FL, type: Numeric, version: "1.3"
72
77
  define_field :SM, type: Numeric, version: "1.3"
73
78
  define_field :SA, type: Boolean
74
- define_field :BM, type: [Symbol, Array], version: "1.4"
79
+ define_field :BM, type: [Symbol, PDFArray], version: "1.4"
75
80
  define_field :SMask, type: [Dictionary, Symbol], version: "1.4"
76
81
  define_field :CA, type: Numeric, version: "1.4"
77
82
  define_field :ca, type: Numeric, version: "1.4"
@@ -0,0 +1,58 @@
1
+ # -*- encoding: utf-8; frozen_string_literal: true -*-
2
+ #
3
+ #--
4
+ # This file is part of HexaPDF.
5
+ #
6
+ # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
+ # Copyright (C) 2014-2019 Thomas Leitner
8
+ #
9
+ # HexaPDF is free software: you can redistribute it and/or modify it
10
+ # under the terms of the GNU Affero General Public License version 3 as
11
+ # published by the Free Software Foundation with the addition of the
12
+ # following permission added to Section 15 as permitted in Section 7(a):
13
+ # FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
14
+ # THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
15
+ # INFRINGEMENT OF THIRD PARTY RIGHTS.
16
+ #
17
+ # HexaPDF is distributed in the hope that it will be useful, but WITHOUT
18
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
20
+ # License for more details.
21
+ #
22
+ # You should have received a copy of the GNU Affero General Public License
23
+ # along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
24
+ #
25
+ # The interactive user interfaces in modified source and object code
26
+ # versions of HexaPDF must display Appropriate Legal Notices, as required
27
+ # under Section 5 of the GNU Affero General Public License version 3.
28
+ #
29
+ # In accordance with Section 7(b) of the GNU Affero General Public
30
+ # License, a covered work must retain the producer line in every PDF that
31
+ # is created or manipulated using HexaPDF.
32
+ #
33
+ # If the GNU Affero General Public License doesn't fit your need,
34
+ # commercial licenses are available at <https://gettalong.at/hexapdf/>.
35
+ #++
36
+
37
+ require 'hexapdf/type/annotation'
38
+
39
+ module HexaPDF
40
+ module Type
41
+
42
+ # An IconFit dictionary specifies how an icon should be displayed inside an annotation
43
+ # rectangle.
44
+ #
45
+ # See: PDF1.7 s12.7.7.3.2
46
+ class IconFit < Annotation
47
+
48
+ define_type :XXIconFit
49
+
50
+ define_field :SW, type: Symbol, default: :A, allowed_values: [:A, :B, :S, :N]
51
+ define_field :S, type: Symbol, default: :P, allowed_values: [:A, :P]
52
+ define_field :A, type: PDFArray, default: [0.5, 0.5]
53
+ define_field :FB, type: Boolean, default: false, version: '1.5'
54
+
55
+ end
56
+
57
+ end
58
+ end
@@ -38,6 +38,7 @@ require 'zlib'
38
38
  require 'hexapdf/error'
39
39
  require 'hexapdf/stream'
40
40
  require 'hexapdf/image_loader'
41
+ require 'hexapdf/content/graphics_state'
41
42
 
42
43
  module HexaPDF
43
44
  module Type
@@ -57,16 +58,20 @@ module HexaPDF
57
58
  define_field :Subtype, type: Symbol, required: true, default: :Image
58
59
  define_field :Width, type: Integer, required: true
59
60
  define_field :Height, type: Integer, required: true
60
- define_field :ColorSpace, type: [Symbol, Array]
61
+ define_field :ColorSpace, type: [Symbol, PDFArray]
61
62
  define_field :BitsPerComponent, type: Integer
62
- define_field :Intent, type: Symbol, version: '1.1'
63
+ define_field :Intent, type: Symbol, version: '1.1',
64
+ allowed_values: [HexaPDF::Content::RenderingIntent::ABSOLUTE_COLORIMETRIC,
65
+ HexaPDF::Content::RenderingIntent::RELATIVE_COLORIMETRIC,
66
+ HexaPDF::Content::RenderingIntent::SATURATION,
67
+ HexaPDF::Content::RenderingIntent::PERCEPTUAL]
63
68
  define_field :ImageMask, type: Boolean, default: false
64
- define_field :Mask, type: [Stream, Array], version: '1.3'
65
- define_field :Decode, type: Array
69
+ define_field :Mask, type: [Stream, PDFArray], version: '1.3'
70
+ define_field :Decode, type: PDFArray
66
71
  define_field :Interpolate, type: Boolean, default: false
67
- define_field :Alternates, type: Array, version: '1.3'
72
+ define_field :Alternates, type: PDFArray, version: '1.3'
68
73
  define_field :SMask, type: Stream, version: '1.4'
69
- define_field :SMaskInData, type: Integer, version: '1.5'
74
+ define_field :SMaskInData, type: Integer, version: '1.5', allowed_values: [0, 1, 2]
70
75
  define_field :StructParent, type: Integer, version: '1.3'
71
76
  define_field :ID, type: PDFByteString, version: '1.3'
72
77
  define_field :OPI, type: Dictionary, version: '1.2'
@@ -244,13 +249,14 @@ module HexaPDF
244
249
  io << png_chunk('PLTE', palette)
245
250
  end
246
251
 
247
- if self[:Mask].kind_of?(Array) && self[:Mask].each_slice(2).all? {|a, b| a == b } &&
252
+ if self[:Mask].kind_of?(PDFArray) && self[:Mask].each_slice(2).all? {|a, b| a == b } &&
248
253
  (color_type == ImageLoader::PNG::TRUECOLOR || color_type == ImageLoader::PNG::GREYSCALE)
249
254
  io << png_chunk('tRNS', self[:Mask].each_slice(2).map {|a, _| a }.pack('n*'))
250
255
  end
251
256
 
252
257
  filter, = *self[:Filter]
253
- if filter == :FlateDecode && self[:DecodeParms] && self[:DecodeParms][:Predictor].to_i >= 10
258
+ decode_parms, = *self[:DecodeParms]
259
+ if filter == :FlateDecode && decode_parms && decode_parms[:Predictor].to_i >= 10
254
260
  data = stream_source
255
261
  else
256
262
  colors = (color_type == ImageLoader::PNG::INDEXED ? 1 : info.components)
@@ -57,7 +57,8 @@ module HexaPDF
57
57
  define_field :Producer, type: String
58
58
  define_field :CreationDate, type: PDFDate
59
59
  define_field :ModDate, type: PDFDate
60
- define_field :Trapped, type: Symbol, version: '1.3'
60
+ define_field :Trapped, type: Symbol, version: '1.3',
61
+ allowed_values: [:True, :False, :Unknown]
61
62
 
62
63
  # Info dictionaries must always be indirect.
63
64
  def must_be_indirect?
@@ -133,14 +133,14 @@ module HexaPDF
133
133
  define_field :TrimBox, type: Rectangle, version: '1.3'
134
134
  define_field :ArtBox, type: Rectangle, version: '1.3'
135
135
  define_field :BoxColorInfo, type: Dictionary, version: '1.4'
136
- define_field :Contents, type: [Stream, Array]
136
+ define_field :Contents, type: [Stream, PDFArray]
137
137
  define_field :Rotate, type: Integer, default: 0
138
138
  define_field :Group, type: Dictionary, version: '1.4'
139
139
  define_field :Thumb, type: Stream
140
- define_field :B, type: Array, version: '1.1'
140
+ define_field :B, type: PDFArray, version: '1.1'
141
141
  define_field :Dur, type: Numeric, version: '1.1'
142
142
  define_field :Trans, type: Dictionary, version: '1.1'
143
- define_field :Annots, type: Array
143
+ define_field :Annots, type: PDFArray
144
144
  define_field :AA, type: Dictionary, version: '1.2'
145
145
  define_field :Metadata, type: Stream, version: '1.4'
146
146
  define_field :PieceInfo, type: Dictionary, version: '1.3'
@@ -152,7 +152,7 @@ module HexaPDF
152
152
  define_field :TemplateInstantiated, type: Symbol, version: '1.5'
153
153
  define_field :PresSteps, type: Dictionary, version: '1.5'
154
154
  define_field :UserUnit, type: Numeric, version: '1.6'
155
- define_field :VP, type: Array, version: '1.6'
155
+ define_field :VP, type: PDFArray, version: '1.6'
156
156
 
157
157
  # Returns +true+ since page objects must always be indirect.
158
158
  def must_be_indirect?
@@ -66,7 +66,7 @@ module HexaPDF
66
66
 
67
67
  define_field :Type, type: Symbol, required: true, default: type
68
68
  define_field :Parent, type: Dictionary, indirect: true
69
- define_field :Kids, type: Array, required: true, default: []
69
+ define_field :Kids, type: PDFArray, required: true, default: []
70
70
  define_field :Count, type: Integer, required: true, default: 0
71
71
 
72
72
  # Inheritable page fields
@@ -96,7 +96,6 @@ module HexaPDF
96
96
  return nil if index < 0 || index >= self[:Count]
97
97
 
98
98
  self[:Kids].each do |kid|
99
- kid = document.deref(kid)
100
99
  if kid.type == :Page
101
100
  if index == 0
102
101
  return kid
@@ -132,7 +131,6 @@ module HexaPDF
132
131
  page[:Resources] ||= {}
133
132
  else
134
133
  self[:Kids].each_with_index do |kid, kid_index|
135
- kid = document.deref(kid)
136
134
  if index == 0
137
135
  self[:Kids].insert(kid_index, page)
138
136
  page[:Parent] = self
@@ -177,7 +175,7 @@ module HexaPDF
177
175
  return nil unless page && page[:Parent]
178
176
 
179
177
  parent = page[:Parent]
180
- index = parent[:Kids].index {|kid| document.deref(kid).data == page.data }
178
+ index = parent[:Kids].index {|kid| kid.data == page.data }
181
179
 
182
180
  if index
183
181
  ancestors = [parent]
@@ -203,7 +201,6 @@ module HexaPDF
203
201
  return to_enum(__method__) unless block_given?
204
202
 
205
203
  self[:Kids].each do |kid|
206
- kid = document.deref(kid)
207
204
  if kid.type == :Page
208
205
  yield(kid)
209
206
  else
@@ -222,7 +219,7 @@ module HexaPDF
222
219
  if box.kind_of?(Symbol)
223
220
  box = Page.media_box(box, orientation: config['page.default_media_orientation'])
224
221
  end
225
- document.add(Type: :Page, MediaBox: box)
222
+ document.add({Type: :Page, MediaBox: box})
226
223
  end
227
224
 
228
225
  # Ensures that the /Count and /Parent fields of the whole page tree are set up correctly and
@@ -235,7 +232,6 @@ module HexaPDF
235
232
  validate_node = lambda do |node|
236
233
  count = 0
237
234
  node[:Kids].reject! do |kid|
238
- kid = document.deref(kid)
239
235
  if !kid.kind_of?(HexaPDF::Object) || kid.null? ||
240
236
  (kid.type != :Page && kid.type != :Pages)
241
237
  yield("Invalid object in page tree node", true)
@@ -55,7 +55,7 @@ module HexaPDF
55
55
  define_field :Shading, type: Dictionary, version: '1.3'
56
56
  define_field :XObject, type: Dictionary
57
57
  define_field :Font, type: Dictionary
58
- define_field :ProcSet, type: Array
58
+ define_field :ProcSet, type: PDFArray
59
59
  define_field :Properties, type: Dictionary, version: '1.2'
60
60
 
61
61
  # Returns the color space stored under the given name.
@@ -65,12 +65,12 @@ module HexaPDF
65
65
  define_field :Root, type: :Catalog, indirect: true
66
66
  define_field :Encrypt, type: Dictionary
67
67
  define_field :Info, type: :XXInfo, indirect: true
68
- define_field :ID, type: Array
68
+ define_field :ID, type: PDFArray
69
69
  define_field :XRefStm, type: Integer, version: '1.5'
70
70
 
71
71
  # Returns the document's Catalog (see Type::Catalog), creating it if needed.
72
72
  def catalog
73
- self[:Root] ||= document.add(Type: :Catalog)
73
+ self[:Root] ||= document.add({Type: :Catalog})
74
74
  end
75
75
 
76
76
  # Returns the document's information dictionary (see Type::Info), creating it if needed.
@@ -88,7 +88,7 @@ module HexaPDF
88
88
  # Updates the second part of the /ID field (the first part should always be the same for a
89
89
  # PDF file, the second part should change with each write).
90
90
  def update_id
91
- if !value[:ID].kind_of?(Array)
91
+ if !self[:ID].kind_of?(PDFArray)
92
92
  set_random_id
93
93
  else
94
94
  value[:ID][1] = Digest::MD5.digest(rand.to_s)
@@ -112,7 +112,7 @@ module HexaPDF
112
112
 
113
113
  unless value[:Root]
114
114
  yield("A PDF document must have a Catalog dictionary", true)
115
- value[:Root] = document.add(Type: :Catalog)
115
+ value[:Root] = document.add({Type: :Catalog})
116
116
  value[:Root].validate {|message, correctable| yield(message, correctable) }
117
117
  end
118
118
 
@@ -55,16 +55,19 @@ module HexaPDF
55
55
  define_field :FitWindow, type: Boolean, default: false
56
56
  define_field :CenterWindow, type: Boolean, default: false
57
57
  define_field :DisplayDocTitle, type: Boolean, default: false, version: '1.4'
58
- define_field :NonFullScreenPageMode, type: Symbol, default: :UseNone
59
- define_field :Direction, type: Symbol, default: :L2R, version: '1.3'
58
+ define_field :NonFullScreenPageMode, type: Symbol, default: :UseNone,
59
+ allowed_values: [:UseNone, :UseOutlines, :UseThumbs, :UseOC]
60
+ define_field :Direction, type: Symbol, default: :L2R, version: '1.3',
61
+ allowed_values: [:L2R, :R2L]
60
62
  define_field :ViewArea, type: Symbol, default: :CropBox, version: '1.4'
61
63
  define_field :ViewClip, type: Symbol, default: :CropBox, version: '1.4'
62
64
  define_field :PrintArea, type: Symbol, default: :CropBox, version: '1.4'
63
65
  define_field :PrintClip, type: Symbol, default: :CropBox, version: '1.4'
64
66
  define_field :PrintScaling, type: Symbol, default: :AppDefault, version: '1.6'
65
- define_field :Duplex, type: Symbol, version: '1.7'
67
+ define_field :Duplex, type: Symbol, version: '1.7',
68
+ allowed_values: [:Simplex, :DuplexFlipShortEdge, :DuplexFlipLongEdge]
66
69
  define_field :PickTrayByPDFSize, type: Boolean, version: '1.7'
67
- define_field :PrintPageRange, type: Array, version: '1.7'
70
+ define_field :PrintPageRange, type: PDFArray, version: '1.7'
68
71
  define_field :NumCopies, type: Integer, version: '1.7'
69
72
 
70
73
  end
@@ -74,10 +74,10 @@ module HexaPDF
74
74
  version: '1.5'
75
75
  # Size is not required because it will be auto-filled before the object is written
76
76
  define_field :Size, type: Integer, indirect: false
77
- define_field :Index, type: Array, indirect: false
77
+ define_field :Index, type: PDFArray, indirect: false
78
78
  define_field :Prev, type: Integer, indirect: false
79
79
  # W is not required because it will be auto-filled on #update_with_xref_section_and_trailer
80
- define_field :W, type: Array, indirect: false
80
+ define_field :W, type: PDFArray, indirect: false
81
81
 
82
82
  # Returns an XRefSection that represents the content of this cross-reference stream.
83
83
  #
@@ -201,7 +201,7 @@ module HexaPDF
201
201
  index += 2
202
202
  end
203
203
  elsif node.key?(:Kids)
204
- stack.concat(node[:Kids].reverse)
204
+ stack.concat(node[:Kids].reverse_each.to_a)
205
205
  end
206
206
  end
207
207
 
@@ -37,6 +37,6 @@
37
37
  module HexaPDF
38
38
 
39
39
  # The version of HexaPDF.
40
- VERSION = '0.10.0'
40
+ VERSION = '0.11.0'
41
41
 
42
42
  end
@@ -15,23 +15,27 @@ Using the hexapdf application the following tasks can be performed with PDF file
15
15
  .sp
16
16
  .PD 0
17
17
  .IP \(bu 4
18
- Extracting embedded files (see the \fBfiles\fP command)
18
+ Modifying an existing PDF file (see the \fBmodify\fP command)
19
19
  .IP \(bu 4
20
- Extracting images (see the \fBimages\fP command)
20
+ Merging multiple PDF files into one (see the \fBmerge\fP command)
21
21
  .IP \(bu 4
22
- Showing general information of a PDF file (see the \fBinfo\fP command)
22
+ Splitting a PDF file into individual pages (see the \fBsplit\fP command)
23
23
  .IP \(bu 4
24
- Inspecting the internal structure of a PDF file (see the \fBinspect\fP command)
24
+ Optimizing the file size of a PDF file (see the \fBoptimize\fP command)
25
25
  .IP \(bu 4
26
- Merging multiple PDF files into one (see the \fBmerge\fP command)
26
+ Watermarking/Stamping a PDF onto another one (see the \fBwatermark\fP command)
27
27
  .IP \(bu 4
28
- Modifying an existing PDF file (see the \fBmodify\fP command)
28
+ Extracting embedded files (see the \fBfiles\fP command)
29
29
  .IP \(bu 4
30
- Optimizing the file size of a PDF file (see the \fBoptimize\fP command)
30
+ Extracting images (see the \fBimages\fP command)
31
31
  .IP \(bu 4
32
- Splitting a PDF file into individual pages (see the \fBsplit\fP command)
32
+ Converting images to PDF (see the \fBimage2pdf\fP command)
33
+ .IP \(bu 4
34
+ Showing general information of a PDF file (see the \fBinfo\fP command)
33
35
  .IP \(bu 4
34
36
  Batch execution of a command on multiple PDF files (see the \fBbatch\fP command)
37
+ .IP \(bu 4
38
+ Inspecting the internal structure of a PDF file (see the \fBinspect\fP command)
35
39
  .PD
36
40
  .P
37
41
  The application contains a built\-in \fBhelp\fP command that can be used to provide a quick reminder of a command\[u2019]s purpose and its options\.
@@ -247,6 +251,34 @@ The image type\. Either jpg (JPEG), jp2 (JPEG2000), ccitt (CCITT Group 3 or 4 Fa
247
251
  \fBwritable\fP
248
252
  Either true or false depending on whether hexapdf supports the image format\.
249
253
  .RE
254
+ .SS "image2pdf"
255
+ Synopsis: \fBiamge2pdf\fP [\fBOPTIONS\fP] \fIOUTPUT\fP [\fIIMAGES\fP\.\.\.]
256
+ .P
257
+ This command converts one or more images into a single PDF file, one image per page\. The various options allow setting a page size, scaling the images and defining margins\. Images are always centered on the pages\.
258
+ .P
259
+ Supported image formats are JPEG, PNG and PDF\. Images in PNG format may take longer to process due to the way they are stored inside a PDF\.
260
+ .TP
261
+ \fB\-p\fP \fIPAGE_SIZE\fP, \fB\-\-page\-size\fP \fIPAGE_SIZE\fP
262
+ The PDF page size\. The default value of \fIauto\fP chooses the page size based on the image dimensions\. Either \fIauto\fP which chooses a size based on the image size or a valid page size like \fIA4\fP, \fIA4\-landscape\fP or \fI595x842\fP\&\. The \fI\-landscape\fP suffix can be added to any predefined page size\.
263
+ .RS
264
+ .P
265
+ Common page sizes are \fIA4\fP, \fIA5\fP, \fIA3\fP, \fILetter\fP and \fILegal\fP\&\.
266
+ .RE
267
+ .TP
268
+ \fB\-\-[no\-]auto\-rotate\fP
269
+ If enabled (the default) pages are automatically rotated so that the pages and images always have the same orientation\. I\.e\. landscape\-oriented images go on landscape page, portrait\-oriented images on portrait pages\.
270
+ .RS
271
+ .P
272
+ Note that pages won\[u2019]t be rotated if scaling is used and the image would fit into the requested page size\.
273
+ .RE
274
+ .TP
275
+ \fB\-s\fP \fISCALE\fP, \fB\-\-scale\fP \fISCALE\fP
276
+ Defines how the images should be scaled\. The default value of \fIfit\fP scales the images so that they optimally fit the pages\. Otherwise \fISCALE\fP is interpreted as the minimum number of pixels per inch (PPI) that the images should have\.
277
+ .TP
278
+ \fB\-m\fP \fIMARGINS\fP, \fB\-\-margins\fP \fIMARGINS\fP
279
+ Defines the margins around the images\. The argument \fIMARGINS\fP can either be a single number specifying the margin on all four sides, or four numbers separated by commas (like \fB10,20,30,40\fP) specifying the top, right, bottom and left margins\. Default: \fI0\fP\&\.
280
+ .P
281
+ Additionally, the \fBOptimization Options\fP and \fBEncryption Options\fP can be used\.
250
282
  .SS "info"
251
283
  Synopsis: \fBinfo\fP [\fBOPTIONS\fP] \fIFILE\fP
252
284
  .P
@@ -395,6 +427,31 @@ If no \fIOUTPUT_SPEC\fP is given, files of the form \fIINPUT_0001\.pdf\fP, \fIIN
395
427
  The password to decrypt the \fIINPUT\fP\&\. Use \fB\-\fP for \fIPASSWORD\fP for reading it from standard input\.
396
428
  .P
397
429
  Additionally, the \fBOptimization Options\fP and \fBEncryption Options\fP can be used\.
430
+ .SS "watermark"
431
+ Synopsis: \fBwatermark\fP [\fBOPTIONS\fP] \fIINPUT\fP \fIOUTPUT\fP
432
+ .P
433
+ This command uses one ore more pages from a PDF file and applies them as background or stamp (depending on the \fB\-\-type\fP option) on another PDF file\. If multiple pages are selected from the watermark PDF, the \fB\-\-repeat\fP option can be used to specify how they should be applied\.
434
+ .TP
435
+ \fB\-w\fP \fIWATERMARK\fP, \fB\-\-watermark\-file\fP \fIWATERMARK\fP
436
+ The PDF file that should be used for watermarking\.
437
+ .TP
438
+ \fB\-i\fP \fIPAGES\fP, \fB\-\-pages\fP \fIPAGES\fP
439
+ The pages from the \fIWATERMARK\fP PDF that should be used\. The first \fIWATERMARK\fP page is applied to the first \fIINPUT\fP page, the second \fIWATERMARK\fP page to the second \fIINPUT\fP page and so on\. If there are fewer \fIWATERMARK\fP pages than \fIINPUT\fP pages, the \fB\-\-repeat\fP option comes into play\.
440
+ .RS
441
+ .P
442
+ See the \fBPAGES SPECIFICATION\fP below for details on the allowed format of \fIPAGES\fP\&\. Default: \fI1\fP\&\.
443
+ .RE
444
+ .TP
445
+ \fB\-r\fP \fIREPEAT_MODE\fP, \fB\-\-repeat\fP \fIREPEAT_MODE\fP
446
+ Specifies how the \fIWATERMARK\fP pages should be repeated: \fBlast\fP (the default) will only repeat the last \fIWATERMARK\fP page whereas \fBall\fP will cyclically repeat all \fIWATERMARK\fP pages\.
447
+ .TP
448
+ \fB\-t\fP \fIWATERMARK_TYPE\fP, \fB\-\-type\fP \fIWATERMARK_TYPE\fP
449
+ Specifies how the \fIWATERMARK\fP pages are applied to the \fIINPUT\fP pages: \fBbackground\fP (the default) applies them below the page contents and \fBstamp\fP applies them above the page contents\.
450
+ .TP
451
+ \fB\-p\fP \fIPASSWORD\fP, \fB\-\-password\fP \fIPASSWORD\fP
452
+ The password to decrypt the \fIINPUT\fP\&\. Use \fB\-\fP for \fIPASSWORD\fP for reading it from standard input\.
453
+ .P
454
+ Additionally, the \fBOptimization Options\fP and \fBEncryption Options\fP can be used\.
398
455
  .SS "version"
399
456
  This command shows the version of the hexapdf application\. It is an alternative to using the global \fB\-\-version\fP option\.
400
457
  .SH "PAGES SPECIFICATION"
@@ -475,6 +532,14 @@ Optimization: Compress the \fBinput\.pdf\fP to get a smaller file size\.
475
532
  \fBhexapdf split input\.pdf out_%02d\.pdf\fP
476
533
  .P
477
534
  Split the \fBinput\.pdf\fP into individual pages, naming the output files \fBout_01\.pdf\fP, \fBout_02\.pdf\fP, and so on\.
535
+ .SS "watermark"
536
+ \fBhexapdf watermark \-w watermark\.pdf \-t stamp input\.pdf output\.pdf\fP
537
+ .P
538
+ Applies the first page of the \fBwatermark\.pdf\fP as stamp on \fBinput\.pdf\fP\&\.
539
+ .P
540
+ \fBhexapdf watermark \-w watermark\.pdf \-i 2\-5 \-r all input\.pdf output\.pdf\fP
541
+ .P
542
+ Cyclically applies the pages 2 to 5 of the \fBwatermark\.pdf\fP as background on \fBinput\.pdf\fP\&\.
478
543
  .SS "files"
479
544
  \fBhexapdf files input\.pdf\fP
480
545
  .br
@@ -487,6 +552,10 @@ Embedded files: The first command lists the embedded files in the \fBinput\.pdf\
487
552
  \fBhexapdf images input\.pdf \-e \-\-prefix images/image\fP
488
553
  .P
489
554
  Image info and extraction: The first command lists the images of the \fBinput\.pdf\fP, the second one then extracts the images into the subdirectory \fBimages\fP with the prefix \fBimage\fP\&\.
555
+ .SS "image2pdf"
556
+ \fBhexapdf image2pdf output\.pdf image1\.jpg image2\.pdf image3\.png\fP
557
+ .P
558
+ Create a PDF file \fBoutput\.pdf\fP containing three pages with one image per page and the image fitted to the page\.
490
559
  .SS "info"
491
560
  \fBhexapdf info input\.pdf\fP
492
561
  .P