hexapdf 0.11.7 → 0.12.2

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 (255) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +121 -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 +18 -9
  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 +1 -1
  30. data/lib/hexapdf/cli/images.rb +1 -1
  31. data/lib/hexapdf/cli/info.rb +1 -1
  32. data/lib/hexapdf/cli/inspect.rb +1 -1
  33. data/lib/hexapdf/cli/merge.rb +1 -1
  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 +66 -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 +1 -1
  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 +1 -1
  55. data/lib/hexapdf/dictionary_fields.rb +1 -1
  56. data/lib/hexapdf/document.rb +14 -5
  57. data/lib/hexapdf/document/files.rb +1 -1
  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 +1 -1
  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 +7 -1
  70. data/lib/hexapdf/encryption/standard_security_handler.rb +1 -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 +1 -1
  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 +1 -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 +1 -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 +1 -1
  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 +1 -1
  137. data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
  138. data/lib/hexapdf/layout/style.rb +1 -1
  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 +1 -1
  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 +2 -2
  147. data/lib/hexapdf/parser.rb +4 -3
  148. data/lib/hexapdf/pdf_array.rb +1 -1
  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 +1 -1
  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 +1 -1
  158. data/lib/hexapdf/tokenizer.rb +1 -1
  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 +401 -0
  162. data/lib/hexapdf/type/acro_form/button_field.rb +300 -0
  163. data/lib/hexapdf/type/acro_form/choice_field.rb +220 -0
  164. data/lib/hexapdf/type/acro_form/field.rb +220 -17
  165. data/lib/hexapdf/type/acro_form/form.rb +157 -7
  166. data/lib/hexapdf/type/acro_form/text_field.rb +186 -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 +1 -1
  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 +239 -2
  180. data/lib/hexapdf/type/catalog.rb +21 -1
  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 +1 -1
  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 +1 -1
  187. data/lib/hexapdf/type/font_true_type.rb +1 -1
  188. data/lib/hexapdf/type/font_type0.rb +1 -1
  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 +10 -1
  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 +3 -1
  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 +20 -5
  199. data/lib/hexapdf/type/page_tree_node.rb +8 -11
  200. data/lib/hexapdf/type/resources.rb +16 -3
  201. data/lib/hexapdf/type/trailer.rb +2 -3
  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 +1 -1
  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/content/common.rb +2 -2
  216. data/test/hexapdf/content/test_color_space.rb +71 -8
  217. data/test/hexapdf/content/test_operator.rb +22 -22
  218. data/test/hexapdf/content/test_parser.rb +14 -0
  219. data/test/hexapdf/document/test_fonts.rb +1 -1
  220. data/test/hexapdf/document/test_pages.rb +6 -6
  221. data/test/hexapdf/encryption/test_security_handler.rb +4 -0
  222. data/test/hexapdf/font/encoding/test_base.rb +10 -0
  223. data/test/hexapdf/font/encoding/test_difference_encoding.rb +8 -0
  224. data/test/hexapdf/font/test_true_type_wrapper.rb +10 -7
  225. data/test/hexapdf/font/test_type1_wrapper.rb +33 -8
  226. data/test/hexapdf/layout/test_style.rb +1 -1
  227. data/test/hexapdf/test_document.rb +12 -0
  228. data/test/hexapdf/test_parser.rb +10 -0
  229. data/test/hexapdf/test_rectangle.rb +14 -0
  230. data/test/hexapdf/test_revision.rb +3 -0
  231. data/test/hexapdf/test_serializer.rb +3 -3
  232. data/test/hexapdf/test_writer.rb +2 -2
  233. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +515 -0
  234. data/test/hexapdf/type/acro_form/test_button_field.rb +276 -0
  235. data/test/hexapdf/type/acro_form/test_choice_field.rb +137 -0
  236. data/test/hexapdf/type/acro_form/test_field.rb +124 -6
  237. data/test/hexapdf/type/acro_form/test_form.rb +189 -22
  238. data/test/hexapdf/type/acro_form/test_text_field.rb +119 -0
  239. data/test/hexapdf/type/acro_form/test_variable_text_field.rb +77 -0
  240. data/test/hexapdf/type/annotations/test_text.rb +1 -1
  241. data/test/hexapdf/type/annotations/test_widget.rb +199 -0
  242. data/test/hexapdf/type/test_annotation.rb +45 -0
  243. data/test/hexapdf/type/test_catalog.rb +18 -0
  244. data/test/hexapdf/type/test_font.rb +5 -0
  245. data/test/hexapdf/type/test_font_type1.rb +8 -0
  246. data/test/hexapdf/type/test_form.rb +18 -0
  247. data/test/hexapdf/type/test_image.rb +7 -0
  248. data/test/hexapdf/type/test_page.rb +37 -6
  249. data/test/hexapdf/type/test_page_tree_node.rb +20 -12
  250. data/test/hexapdf/type/test_resources.rb +20 -0
  251. data/test/hexapdf/type/test_trailer.rb +4 -0
  252. data/test/hexapdf/utils/test_bit_field.rb +13 -1
  253. data/test/test_helper.rb +1 -1
  254. metadata +38 -18
  255. 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,244 @@ 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
+ if obj == :rg || obj == :g || obj == :k
311
+ color = params.dup
312
+ elsif obj == :Tf
313
+ size = params[1]
314
+ end
315
+ end
316
+ end
317
+ color = HexaPDF::Content::ColorSpace.prenormalized_device_color(color)
318
+
319
+ MarkerStyle.new(style, size, color)
320
+ end
321
+ end
322
+
86
323
  end
87
324
 
88
325
  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,6 +97,26 @@ 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.
@@ -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
@@ -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
@@ -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