hexapdf 0.11.9 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (270) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +157 -0
  3. data/LICENSE +1 -1
  4. data/examples/001-hello_world.rb +1 -1
  5. data/examples/002-graphics.rb +1 -1
  6. data/examples/003-arcs.rb +1 -1
  7. data/examples/004-optimizing.rb +1 -1
  8. data/examples/005-merging.rb +1 -1
  9. data/examples/006-standard_pdf_fonts.rb +1 -1
  10. data/examples/007-truetype.rb +1 -1
  11. data/examples/008-show_char_bboxes.rb +1 -1
  12. data/examples/009-text_layouter_alignment.rb +1 -1
  13. data/examples/010-text_layouter_inline_boxes.rb +1 -1
  14. data/examples/011-text_layouter_line_wrapping.rb +1 -1
  15. data/examples/012-text_layouter_styling.rb +1 -1
  16. data/examples/013-text_layouter_shapes.rb +1 -1
  17. data/examples/014-text_in_polygon.rb +1 -1
  18. data/examples/015-boxes.rb +1 -1
  19. data/examples/016-frame_automatic_box_placement.rb +1 -1
  20. data/examples/017-frame_text_flow.rb +1 -1
  21. data/examples/018-composer.rb +1 -1
  22. data/examples/019-acro_form.rb +51 -0
  23. data/lib/hexapdf.rb +1 -1
  24. data/lib/hexapdf/cli.rb +3 -1
  25. data/lib/hexapdf/cli/batch.rb +1 -1
  26. data/lib/hexapdf/cli/command.rb +22 -11
  27. data/lib/hexapdf/cli/files.rb +1 -1
  28. data/lib/hexapdf/cli/form.rb +240 -0
  29. data/lib/hexapdf/cli/image2pdf.rb +3 -2
  30. data/lib/hexapdf/cli/images.rb +1 -1
  31. data/lib/hexapdf/cli/info.rb +52 -3
  32. data/lib/hexapdf/cli/inspect.rb +31 -9
  33. data/lib/hexapdf/cli/merge.rb +2 -2
  34. data/lib/hexapdf/cli/modify.rb +1 -1
  35. data/lib/hexapdf/cli/optimize.rb +1 -1
  36. data/lib/hexapdf/cli/split.rb +1 -1
  37. data/lib/hexapdf/cli/watermark.rb +1 -1
  38. data/lib/hexapdf/composer.rb +2 -2
  39. data/lib/hexapdf/configuration.rb +81 -11
  40. data/lib/hexapdf/content.rb +3 -1
  41. data/lib/hexapdf/content/canvas.rb +5 -18
  42. data/lib/hexapdf/content/color_space.rb +111 -32
  43. data/lib/hexapdf/content/graphic_object.rb +1 -1
  44. data/lib/hexapdf/content/graphic_object/arc.rb +4 -4
  45. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
  46. data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
  47. data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
  48. data/lib/hexapdf/content/graphics_state.rb +1 -1
  49. data/lib/hexapdf/content/operator.rb +9 -9
  50. data/lib/hexapdf/content/parser.rb +18 -5
  51. data/lib/hexapdf/content/processor.rb +1 -1
  52. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  53. data/lib/hexapdf/data_dir.rb +1 -1
  54. data/lib/hexapdf/dictionary.rb +5 -5
  55. data/lib/hexapdf/dictionary_fields.rb +2 -10
  56. data/lib/hexapdf/document.rb +45 -17
  57. data/lib/hexapdf/document/files.rb +1 -2
  58. data/lib/hexapdf/document/fonts.rb +1 -1
  59. data/lib/hexapdf/document/images.rb +1 -1
  60. data/lib/hexapdf/document/pages.rb +3 -14
  61. data/lib/hexapdf/encryption.rb +1 -1
  62. data/lib/hexapdf/encryption/aes.rb +1 -1
  63. data/lib/hexapdf/encryption/arc4.rb +1 -1
  64. data/lib/hexapdf/encryption/fast_aes.rb +1 -1
  65. data/lib/hexapdf/encryption/fast_arc4.rb +2 -2
  66. data/lib/hexapdf/encryption/identity.rb +1 -1
  67. data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
  68. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  69. data/lib/hexapdf/encryption/security_handler.rb +2 -1
  70. data/lib/hexapdf/encryption/standard_security_handler.rb +2 -1
  71. data/lib/hexapdf/error.rb +1 -1
  72. data/lib/hexapdf/filter.rb +3 -3
  73. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  74. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  75. data/lib/hexapdf/filter/encryption.rb +1 -1
  76. data/lib/hexapdf/filter/flate_decode.rb +1 -1
  77. data/lib/hexapdf/filter/lzw_decode.rb +1 -1
  78. data/lib/hexapdf/filter/{jpx_decode.rb → pass_through.rb} +5 -5
  79. data/lib/hexapdf/filter/predictor.rb +1 -1
  80. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  81. data/lib/hexapdf/font/cmap.rb +2 -5
  82. data/lib/hexapdf/font/cmap/parser.rb +1 -1
  83. data/lib/hexapdf/font/cmap/writer.rb +1 -1
  84. data/lib/hexapdf/font/encoding.rb +1 -1
  85. data/lib/hexapdf/font/encoding/base.rb +9 -1
  86. data/lib/hexapdf/font/encoding/difference_encoding.rb +7 -1
  87. data/lib/hexapdf/font/encoding/glyph_list.rb +1 -1
  88. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  89. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +1 -1
  90. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  91. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  92. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +1 -1
  93. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  94. data/lib/hexapdf/font/invalid_glyph.rb +1 -1
  95. data/lib/hexapdf/font/true_type.rb +1 -1
  96. data/lib/hexapdf/font/true_type/builder.rb +1 -1
  97. data/lib/hexapdf/font/true_type/font.rb +1 -1
  98. data/lib/hexapdf/font/true_type/optimizer.rb +1 -1
  99. data/lib/hexapdf/font/true_type/subsetter.rb +1 -1
  100. data/lib/hexapdf/font/true_type/table.rb +1 -1
  101. data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
  102. data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +1 -1
  103. data/lib/hexapdf/font/true_type/table/directory.rb +1 -1
  104. data/lib/hexapdf/font/true_type/table/glyf.rb +1 -1
  105. data/lib/hexapdf/font/true_type/table/head.rb +2 -1
  106. data/lib/hexapdf/font/true_type/table/hhea.rb +1 -1
  107. data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -1
  108. data/lib/hexapdf/font/true_type/table/kern.rb +1 -1
  109. data/lib/hexapdf/font/true_type/table/loca.rb +1 -1
  110. data/lib/hexapdf/font/true_type/table/maxp.rb +1 -1
  111. data/lib/hexapdf/font/true_type/table/name.rb +1 -1
  112. data/lib/hexapdf/font/true_type/table/os2.rb +3 -1
  113. data/lib/hexapdf/font/true_type/table/post.rb +1 -1
  114. data/lib/hexapdf/font/true_type_wrapper.rb +54 -51
  115. data/lib/hexapdf/font/type1.rb +1 -1
  116. data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
  117. data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
  118. data/lib/hexapdf/font/type1/font.rb +1 -1
  119. data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
  120. data/lib/hexapdf/font/type1/pfb_parser.rb +1 -1
  121. data/lib/hexapdf/font/type1_wrapper.rb +68 -52
  122. data/lib/hexapdf/font_loader.rb +1 -1
  123. data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
  124. data/lib/hexapdf/font_loader/from_file.rb +1 -1
  125. data/lib/hexapdf/font_loader/standard14.rb +1 -1
  126. data/lib/hexapdf/image_loader.rb +1 -1
  127. data/lib/hexapdf/image_loader/jpeg.rb +1 -1
  128. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  129. data/lib/hexapdf/image_loader/png.rb +4 -3
  130. data/lib/hexapdf/importer.rb +2 -4
  131. data/lib/hexapdf/layout.rb +1 -1
  132. data/lib/hexapdf/layout/box.rb +1 -1
  133. data/lib/hexapdf/layout/frame.rb +1 -1
  134. data/lib/hexapdf/layout/image_box.rb +1 -1
  135. data/lib/hexapdf/layout/inline_box.rb +1 -1
  136. data/lib/hexapdf/layout/line.rb +2 -2
  137. data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
  138. data/lib/hexapdf/layout/style.rb +24 -24
  139. data/lib/hexapdf/layout/text_box.rb +1 -1
  140. data/lib/hexapdf/layout/text_fragment.rb +1 -1
  141. data/lib/hexapdf/layout/text_layouter.rb +1 -1
  142. data/lib/hexapdf/layout/text_shaper.rb +4 -3
  143. data/lib/hexapdf/layout/width_from_polygon.rb +1 -1
  144. data/lib/hexapdf/name_tree_node.rb +1 -1
  145. data/lib/hexapdf/number_tree_node.rb +1 -1
  146. data/lib/hexapdf/object.rb +32 -27
  147. data/lib/hexapdf/parser.rb +69 -6
  148. data/lib/hexapdf/pdf_array.rb +10 -3
  149. data/lib/hexapdf/rectangle.rb +31 -1
  150. data/lib/hexapdf/reference.rb +1 -1
  151. data/lib/hexapdf/revision.rb +2 -1
  152. data/lib/hexapdf/revisions.rb +30 -22
  153. data/lib/hexapdf/serializer.rb +2 -2
  154. data/lib/hexapdf/stream.rb +1 -1
  155. data/lib/hexapdf/task.rb +1 -1
  156. data/lib/hexapdf/task/dereference.rb +1 -1
  157. data/lib/hexapdf/task/optimize.rb +7 -5
  158. data/lib/hexapdf/tokenizer.rb +5 -4
  159. data/lib/hexapdf/type.rb +1 -1
  160. data/lib/hexapdf/type/acro_form.rb +7 -1
  161. data/lib/hexapdf/type/acro_form/appearance_generator.rb +405 -0
  162. data/lib/hexapdf/type/acro_form/button_field.rb +305 -0
  163. data/lib/hexapdf/type/acro_form/choice_field.rb +220 -0
  164. data/lib/hexapdf/type/acro_form/field.rb +250 -17
  165. data/lib/hexapdf/type/acro_form/form.rb +159 -7
  166. data/lib/hexapdf/type/acro_form/text_field.rb +187 -0
  167. data/lib/hexapdf/type/acro_form/variable_text_field.rb +122 -0
  168. data/lib/hexapdf/type/action.rb +1 -1
  169. data/lib/hexapdf/type/actions.rb +1 -1
  170. data/lib/hexapdf/type/actions/go_to.rb +1 -1
  171. data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
  172. data/lib/hexapdf/type/actions/launch.rb +1 -1
  173. data/lib/hexapdf/type/actions/uri.rb +4 -3
  174. data/lib/hexapdf/type/annotation.rb +73 -3
  175. data/lib/hexapdf/type/annotations.rb +1 -1
  176. data/lib/hexapdf/type/annotations/link.rb +2 -2
  177. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  178. data/lib/hexapdf/type/annotations/text.rb +1 -1
  179. data/lib/hexapdf/type/annotations/widget.rb +238 -2
  180. data/lib/hexapdf/type/catalog.rb +23 -3
  181. data/lib/hexapdf/type/cid_font.rb +1 -1
  182. data/lib/hexapdf/type/embedded_file.rb +1 -1
  183. data/lib/hexapdf/type/file_specification.rb +2 -2
  184. data/lib/hexapdf/type/font.rb +18 -1
  185. data/lib/hexapdf/type/font_descriptor.rb +2 -2
  186. data/lib/hexapdf/type/font_simple.rb +4 -2
  187. data/lib/hexapdf/type/font_true_type.rb +7 -3
  188. data/lib/hexapdf/type/font_type0.rb +2 -2
  189. data/lib/hexapdf/type/font_type1.rb +16 -1
  190. data/lib/hexapdf/type/font_type3.rb +1 -1
  191. data/lib/hexapdf/type/form.rb +12 -2
  192. data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
  193. data/lib/hexapdf/type/icon_fit.rb +1 -1
  194. data/lib/hexapdf/type/image.rb +5 -3
  195. data/lib/hexapdf/type/info.rb +1 -1
  196. data/lib/hexapdf/type/names.rb +1 -1
  197. data/lib/hexapdf/type/object_stream.rb +1 -1
  198. data/lib/hexapdf/type/page.rb +36 -12
  199. data/lib/hexapdf/type/page_tree_node.rb +37 -16
  200. data/lib/hexapdf/type/resources.rb +17 -3
  201. data/lib/hexapdf/type/trailer.rb +4 -6
  202. data/lib/hexapdf/type/viewer_preferences.rb +1 -1
  203. data/lib/hexapdf/type/xref_stream.rb +1 -1
  204. data/lib/hexapdf/utils/bit_field.rb +38 -24
  205. data/lib/hexapdf/utils/bit_stream.rb +1 -1
  206. data/lib/hexapdf/utils/graphics_helpers.rb +1 -1
  207. data/lib/hexapdf/utils/lru_cache.rb +1 -1
  208. data/lib/hexapdf/utils/math_helpers.rb +1 -1
  209. data/lib/hexapdf/utils/object_hash.rb +1 -1
  210. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
  211. data/lib/hexapdf/utils/sorted_tree_node.rb +19 -16
  212. data/lib/hexapdf/version.rb +2 -2
  213. data/lib/hexapdf/writer.rb +1 -1
  214. data/lib/hexapdf/xref_section.rb +1 -1
  215. data/test/hexapdf/common_tokenizer_tests.rb +6 -1
  216. data/test/hexapdf/content/common.rb +2 -2
  217. data/test/hexapdf/content/graphic_object/test_arc.rb +4 -4
  218. data/test/hexapdf/content/test_canvas.rb +3 -3
  219. data/test/hexapdf/content/test_color_space.rb +71 -8
  220. data/test/hexapdf/content/test_operator.rb +22 -22
  221. data/test/hexapdf/content/test_parser.rb +14 -0
  222. data/test/hexapdf/document/test_fonts.rb +1 -1
  223. data/test/hexapdf/document/test_pages.rb +6 -6
  224. data/test/hexapdf/encryption/test_aes.rb +4 -4
  225. data/test/hexapdf/encryption/test_standard_security_handler.rb +11 -11
  226. data/test/hexapdf/filter/test_ascii85_decode.rb +1 -1
  227. data/test/hexapdf/filter/test_ascii_hex_decode.rb +1 -1
  228. data/test/hexapdf/font/encoding/test_base.rb +10 -0
  229. data/test/hexapdf/font/encoding/test_difference_encoding.rb +8 -0
  230. data/test/hexapdf/font/test_true_type_wrapper.rb +10 -7
  231. data/test/hexapdf/font/test_type1_wrapper.rb +33 -8
  232. data/test/hexapdf/layout/test_style.rb +1 -1
  233. data/test/hexapdf/layout/test_text_layouter.rb +3 -4
  234. data/test/hexapdf/test_configuration.rb +2 -2
  235. data/test/hexapdf/test_dictionary.rb +3 -1
  236. data/test/hexapdf/test_dictionary_fields.rb +2 -2
  237. data/test/hexapdf/test_document.rb +16 -4
  238. data/test/hexapdf/test_object.rb +44 -26
  239. data/test/hexapdf/test_parser.rb +125 -55
  240. data/test/hexapdf/test_pdf_array.rb +7 -0
  241. data/test/hexapdf/test_rectangle.rb +14 -0
  242. data/test/hexapdf/test_revision.rb +3 -0
  243. data/test/hexapdf/test_revisions.rb +35 -0
  244. data/test/hexapdf/test_writer.rb +2 -2
  245. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +521 -0
  246. data/test/hexapdf/type/acro_form/test_button_field.rb +281 -0
  247. data/test/hexapdf/type/acro_form/test_choice_field.rb +137 -0
  248. data/test/hexapdf/type/acro_form/test_field.rb +163 -6
  249. data/test/hexapdf/type/acro_form/test_form.rb +189 -22
  250. data/test/hexapdf/type/acro_form/test_text_field.rb +121 -0
  251. data/test/hexapdf/type/acro_form/test_variable_text_field.rb +77 -0
  252. data/test/hexapdf/type/annotations/test_text.rb +1 -1
  253. data/test/hexapdf/type/annotations/test_widget.rb +199 -0
  254. data/test/hexapdf/type/test_annotation.rb +45 -0
  255. data/test/hexapdf/type/test_catalog.rb +18 -0
  256. data/test/hexapdf/type/test_font.rb +5 -0
  257. data/test/hexapdf/type/test_font_simple.rb +2 -1
  258. data/test/hexapdf/type/test_font_true_type.rb +6 -0
  259. data/test/hexapdf/type/test_font_type1.rb +8 -0
  260. data/test/hexapdf/type/test_form.rb +19 -1
  261. data/test/hexapdf/type/test_image.rb +7 -0
  262. data/test/hexapdf/type/test_page.rb +45 -7
  263. data/test/hexapdf/type/test_page_tree_node.rb +62 -12
  264. data/test/hexapdf/type/test_resources.rb +20 -0
  265. data/test/hexapdf/type/test_trailer.rb +4 -0
  266. data/test/hexapdf/utils/test_bit_field.rb +15 -1
  267. data/test/hexapdf/utils/test_sorted_tree_node.rb +10 -9
  268. data/test/test_helper.rb +1 -1
  269. metadata +34 -21
  270. data/lib/hexapdf/filter/dct_decode.rb +0 -60
@@ -4,7 +4,7 @@
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-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 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
@@ -4,7 +4,7 @@
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-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 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
@@ -53,7 +53,7 @@ module HexaPDF
53
53
  version: '1.2'
54
54
  define_field :PA, type: Dictionary, version: '1.3'
55
55
  define_field :QuadPoints, type: PDFArray, version: '1.6'
56
- define_field :BS, type: Dictionary, version: '1.6'
56
+ define_field :BS, type: :Border, version: '1.6'
57
57
 
58
58
  end
59
59
 
@@ -4,7 +4,7 @@
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-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 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
@@ -4,7 +4,7 @@
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-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 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
@@ -4,7 +4,7 @@
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-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 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
@@ -35,6 +35,8 @@
35
35
  #++
36
36
 
37
37
  require 'hexapdf/type/annotation'
38
+ require 'hexapdf/content'
39
+ require 'hexapdf/serializer'
38
40
 
39
41
  module HexaPDF
40
42
  module Type
@@ -80,9 +82,243 @@ module HexaPDF
80
82
  define_field :MK, type: :XXAppearanceCharacteristics
81
83
  define_field :A, type: Dictionary, version: '1.1'
82
84
  define_field :AA, type: Dictionary, version: '1.2'
83
- define_field :BS, type: Dictionary, version: '1.2'
85
+ define_field :BS, type: :Border, version: '1.2'
84
86
  define_field :Parent, type: Dictionary
85
87
 
88
+ # Returs the AcroForm field object to which this widget annotation belongs.
89
+ #
90
+ # Since a widget and a field can share the same dictionary object, the returned object is
91
+ # often just the widget re-wrapped in the correct field class.
92
+ def form_field
93
+ field = if key?(:Parent) &&
94
+ (tmp = document.wrap(self[:Parent], type: :XXAcroFormField)).terminal_field?
95
+ tmp
96
+ else
97
+ document.wrap(self, type: :XXAcroFormField)
98
+ end
99
+ document.wrap(field, type: :XXAcroFormField, subtype: field[:FT])
100
+ end
101
+
102
+ # :call-seq:
103
+ # widget.background_color => background_color or nil
104
+ # widget.background_color(*color) => widget
105
+ #
106
+ # Returns the current background color as device color object, or +nil+ if no background
107
+ # color is set, when no argument is given. Otherwise sets the background color using the
108
+ # +color+ argument and returns self.
109
+ #
110
+ # See HexaPDF::Content::ColorSpace.device_color_from_specification for information on the
111
+ # allowed arguments.
112
+ def background_color(*color)
113
+ if color.empty?
114
+ components = self[:MK]&.[](:BG)
115
+ components.nil? ? nil : Content::ColorSpace.prenormalized_device_color(components)
116
+ else
117
+ color = Content::ColorSpace.device_color_from_specification(color)
118
+ (self[:MK] ||= {})[:BG] = color.components
119
+ self
120
+ end
121
+ end
122
+
123
+ # Describes the border of an annotation.
124
+ #
125
+ # The +color+ property is either +nil+ if the border is transparent or else a device color
126
+ # object - see HexaPDF::Content::ColorSpace.
127
+ #
128
+ # The +style+ property can be one of the following:
129
+ #
130
+ # :solid:: Solid line.
131
+ # :beveled:: Embossed rectangle seemingly raised above the surface of the page.
132
+ # :inset:: Engraved rectangle receeding into the page.
133
+ # :underlined:: Underlined, i.e. only the bottom border is draw.
134
+ # Array: Dash array describing how to dash the line.
135
+ BorderStyle = Struct.new(:width, :color, :style, :horizontal_corner_radius,
136
+ :vertical_corner_radius)
137
+
138
+ # :call-seq:
139
+ # widget.border_style => border_style
140
+ # widget.border_style(color: 0, width: 1, style: :solid) => widget
141
+ #
142
+ # Returns a BorderStyle instance representing the border style of the widget when no
143
+ # argument is given. Otherwise sets the border style of the widget and returns self.
144
+ #
145
+ # When setting a border style, arguments that are not provided will use the default: a
146
+ # border with a solid, black, 1pt wide line. This also means that multiple invocations will
147
+ # reset *all* prior values.
148
+ #
149
+ # +color+:: The color of the border. See
150
+ # HexaPDF::Content::ColorSpace.device_color_from_specification for information on
151
+ # the allowed arguments.
152
+ #
153
+ # If the special value +:transparent+ is used when setting the color, a
154
+ # transparent is used. A transparent border will return a +nil+ value when getting
155
+ # the border color.
156
+ #
157
+ # +width+:: The width of the border. If set to 0, no border is shown.
158
+ #
159
+ # +style+:: Defines how the border is drawn. can be one of the following:
160
+ #
161
+ # +:solid+:: Draws a solid border.
162
+ # +:beveled+:: Draws a beveled border.
163
+ # +:inset+:: Draws an inset border.
164
+ # +:underlined+:: Draws only the bottom border.
165
+ # Array:: An array specifying a line dash pattern (see
166
+ # HexaPDF::Content::LineDashPattern)
167
+ def border_style(color: nil, width: nil, style: nil)
168
+ if color || width || style
169
+ color = if color == :transparent
170
+ []
171
+ else
172
+ Content::ColorSpace.device_color_from_specification(color || 0).components
173
+ end
174
+ width ||= 1
175
+ style ||= :solid
176
+
177
+ (self[:MK] ||= {})[:BC] = color
178
+ bs = self[:BS] = {W: width}
179
+ case style
180
+ when :solid then bs[:S] = :S
181
+ when :beveled then bs[:S] = :B
182
+ when :inset then bs[:S] = :I
183
+ when :underlined then bs[:S] = :U
184
+ when Array
185
+ bs[:S] = :D
186
+ bs[:D] = style
187
+ else
188
+ raise ArgumentError, "Unknown value #{style} for style argument"
189
+ end
190
+ self
191
+ else
192
+ result = BorderStyle.new(1, nil, :solid, 0, 0)
193
+ if (ac = self[:MK]) && (bc = ac[:BC]) && !bc.empty?
194
+ result.color = Content::ColorSpace.prenormalized_device_color(bc.value)
195
+ end
196
+
197
+ if (bs = self[:BS])
198
+ result.width = bs[:W] if bs.key?(:W)
199
+ result.style = case bs[:S]
200
+ when :S then :solid
201
+ when :B then :beveled
202
+ when :I then :inset
203
+ when :U then :underlined
204
+ when :D then bs[:D].value
205
+ else :solid
206
+ end
207
+ elsif key?(:Border)
208
+ border = self[:Border]
209
+ result.horizontal_corner_radius = border[0]
210
+ result.vertical_corner_radius = border[1]
211
+ result.width = border[2]
212
+ result.style = border[3] if border[3]
213
+ end
214
+
215
+ result
216
+ end
217
+ end
218
+
219
+ # Describes the marker style of a check box or radio button widget.
220
+ class MarkerStyle
221
+
222
+ # The kind of marker that is shown inside the widget. Can either be one of the symbols
223
+ # +:check+, +:circle+, +:cross+, +:diamond+, +:square+ or +:star+, or a one character
224
+ # string. The latter is interpreted using the ZapfDingbats font.
225
+ attr_reader :style
226
+
227
+ # The size of the marker in PDF points that is shown inside the widget. The special value
228
+ # 0 means that the marker should be auto-sized based on the widget's rectangle.
229
+ attr_reader :size
230
+
231
+ # A device color object representing the color of the marker - see
232
+ # HexaPDF::Content::ColorSpace.
233
+ attr_reader :color
234
+
235
+ # Creates a new instance with the given values.
236
+ def initialize(style, size, color)
237
+ @style = style
238
+ @size = size
239
+ @color = color
240
+ end
241
+
242
+ end
243
+
244
+ # :call-seq:
245
+ # widget.marker_style => marker_style
246
+ # widget.marker_style(style: nil, size: nil, color: nil) => widget
247
+ #
248
+ # Returns a MarkerStyle instance representing the marker style of the widget when no
249
+ # argument is given. Otherwise sets the button marker style of the widget and returns self.
250
+ #
251
+ # This method returns valid information only for check boxes and radio buttons!
252
+ #
253
+ # When setting a marker style, arguments that are not provided will use the default: a black
254
+ # auto-sized checkmark (i.e. :check for for check boxes) or circle (:circle for radio
255
+ # buttons). This also means that multiple invocations will reset *all* prior values.
256
+ #
257
+ # Note: The marker is called "normal caption" in the PDF 1.7 spec and the /CA entry of the
258
+ # associated appearance characteristics dictionary. The marker size and color are set using
259
+ # the /DA key on the widget (although /DA is not defined for widget, this is how Acrobat
260
+ # does it).
261
+ #
262
+ # See: PDF1.7 s12.5.6.19 and s17.7.3.3
263
+ def marker_style(style: nil, size: nil, color: nil)
264
+ field = form_field
265
+ if style || size || color
266
+ style ||= (field.check_box? ? :check : :cicrle)
267
+ size ||= 0
268
+ color = Content::ColorSpace.device_color_from_specification(color || 0)
269
+
270
+ self[:MK] ||= {}
271
+ self[:MK][:CA] = case style
272
+ when :check then '4'
273
+ when :circle then 'l'
274
+ when :cross then '8'
275
+ when :diamond then 'u'
276
+ when :square then 'n'
277
+ when :star then 'H'
278
+ when String then style
279
+ else
280
+ raise ArgumentError, "Unknown value #{style} for argument 'style'"
281
+ end
282
+ operator = case color.color_space.family
283
+ when :DeviceRGB then :rg
284
+ when :DeviceGray then :g
285
+ when :DeviceCMYK then :k
286
+ end
287
+ serialized_color = Content::Operator::DEFAULT_OPERATORS[operator].
288
+ serialize(HexaPDF::Serializer.new, *color.components)
289
+ self[:DA] = "/ZaDb #{size} Tf #{serialized_color}".strip
290
+ else
291
+ style = case self[:MK]&.[](:CA)
292
+ when '4' then :check
293
+ when 'l' then :circle
294
+ when '8' then :cross
295
+ when 'u' then :diamond
296
+ when 'n' then :square
297
+ when 'H' then :star
298
+ when String then self[:MK][:CA]
299
+ else
300
+ if field.check_box?
301
+ :check
302
+ else
303
+ :circle
304
+ end
305
+ end
306
+ size = 0
307
+ color = [0]
308
+ if (da = self[:DA] || field[:DA])
309
+ HexaPDF::Content::Parser.parse(da) do |obj, params|
310
+ case obj
311
+ when :rg, :g, :k then color = params.dup
312
+ when :Tf then size = params[1]
313
+ end
314
+ end
315
+ end
316
+ color = HexaPDF::Content::ColorSpace.prenormalized_device_color(color)
317
+
318
+ MarkerStyle.new(style, size, color)
319
+ end
320
+ end
321
+
86
322
  end
87
323
 
88
324
  end
@@ -4,7 +4,7 @@
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-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 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
@@ -97,15 +97,35 @@ module HexaPDF
97
97
  self[:Pages] ||= document.add({Type: :Pages})
98
98
  end
99
99
 
100
+ # Returns the main AcroForm object.
101
+ #
102
+ # * If an AcroForm object exists, the +create+ argument is not used.
103
+ #
104
+ # * If no AcroForm object exists and +create+ is +true+, a new AcroForm object with default
105
+ # settings will be created and returned.
106
+ #
107
+ # * If no AcroForm object exists and +create+ is +false+, +nil+ is returned.
108
+ #
109
+ # See: AcroForm::Form
110
+ def acro_form(create: false)
111
+ if (form = self[:AcroForm])
112
+ form
113
+ elsif create
114
+ form = self[:AcroForm] = document.add({}, type: :XXAcroForm)
115
+ form.set_default_appearance_string
116
+ form
117
+ end
118
+ end
119
+
100
120
  private
101
121
 
102
122
  # Ensures that there is a valid page tree.
103
- def perform_validation
123
+ def perform_validation(&block)
104
124
  super
105
125
  unless key?(:Pages)
106
126
  yield("A PDF document needs a page tree", true)
107
127
  value[:Pages] = document.add({Type: :Pages})
108
- value[:Pages].validate {|msg, correctable| yield(msg, correctable) }
128
+ value[:Pages].validate(&block)
109
129
  end
110
130
  end
111
131
 
@@ -4,7 +4,7 @@
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-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 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
@@ -4,7 +4,7 @@
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-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 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
@@ -4,7 +4,7 @@
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-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 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
@@ -220,7 +220,7 @@ module HexaPDF
220
220
 
221
221
  if document.catalog.key?(:Names) && document.catalog[:Names].key?(:EmbeddedFiles)
222
222
  tree = document.catalog[:Names][:EmbeddedFiles]
223
- tree.each_entry.find_all {|_, spec| document.deref(spec) == self }.each do |(name, _)|
223
+ tree.each_entry.find_all {|_, spec| spec == self }.each do |(name, _)|
224
224
  tree.delete_entry(name)
225
225
  end
226
226
  end
@@ -4,7 +4,7 @@
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-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 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,6 +50,23 @@ module HexaPDF
50
50
  define_field :Type, type: Symbol, required: true, default: type
51
51
  define_field :ToUnicode, type: Stream, version: '1.2'
52
52
 
53
+ # Retrieves the font wrapper that is needed when this font is used for text output. Returns
54
+ # +nil+ if this font can't be used for text output.
55
+ #
56
+ # Note: For internal use only!
57
+ #
58
+ # See: HexaPDF::Font
59
+ def font_wrapper
60
+ @font_wrapper ||= nil
61
+ end
62
+
63
+ # Sets the font wrapper.
64
+ #
65
+ # See: #font_wrapper
66
+ def font_wrapper=(font)
67
+ @font_wrapper = font
68
+ end
69
+
53
70
  # Font objects must always be indirect.
54
71
  def must_be_indirect?
55
72
  true
@@ -4,7 +4,7 @@
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-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 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
@@ -84,7 +84,7 @@ module HexaPDF
84
84
 
85
85
  bit_field(:raw_flags, {fixed_pitch: 0, serif: 1, symbolic: 2, script: 3, nonsymbolic: 5,
86
86
  italic: 6, all_cap: 16, small_cap: 17, force_bold: 18},
87
- lister: "flags", getter: "flagged?", setter: "flag")
87
+ lister: "flags", getter: "flagged?", setter: "flag", unsetter: 'unflag')
88
88
 
89
89
  private
90
90
 
@@ -4,7 +4,7 @@
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-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 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
@@ -170,7 +170,9 @@ module HexaPDF
170
170
  [:FirstChar, :LastChar, :Widths].each do |field|
171
171
  yield("Required field #{field} is not set", false) if self[field].nil?
172
172
  end
173
- if self[:Widths].length != (self[:LastChar] - self[:FirstChar] + 1)
173
+
174
+ if key?(:Widths) && key?(:LastChar) && key?(:FirstChar) &&
175
+ self[:Widths].length != (self[:LastChar] - self[:FirstChar] + 1)
174
176
  yield("Invalid number of entries in field Widths", false)
175
177
  end
176
178
  end