hexapdf 0.32.2 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +104 -1
  3. data/README.md +9 -0
  4. data/examples/002-graphics.rb +15 -17
  5. data/examples/003-arcs.rb +9 -9
  6. data/examples/009-text_layouter_alignment.rb +1 -1
  7. data/examples/010-text_layouter_inline_boxes.rb +2 -2
  8. data/examples/011-text_layouter_line_wrapping.rb +1 -1
  9. data/examples/012-text_layouter_styling.rb +7 -7
  10. data/examples/013-text_layouter_shapes.rb +1 -1
  11. data/examples/014-text_in_polygon.rb +1 -1
  12. data/examples/015-boxes.rb +8 -7
  13. data/examples/016-frame_automatic_box_placement.rb +2 -2
  14. data/examples/017-frame_text_flow.rb +2 -1
  15. data/examples/018-composer.rb +1 -1
  16. data/examples/020-column_box.rb +2 -1
  17. data/examples/025-table_box.rb +46 -0
  18. data/examples/026-optional_content.rb +55 -0
  19. data/examples/027-composer_optional_content.rb +83 -0
  20. data/lib/hexapdf/cli/command.rb +12 -3
  21. data/lib/hexapdf/cli/fonts.rb +1 -1
  22. data/lib/hexapdf/cli/form.rb +5 -5
  23. data/lib/hexapdf/cli/inspect.rb +5 -7
  24. data/lib/hexapdf/composer.rb +106 -53
  25. data/lib/hexapdf/configuration.rb +65 -40
  26. data/lib/hexapdf/content/canvas.rb +445 -267
  27. data/lib/hexapdf/content/color_space.rb +72 -25
  28. data/lib/hexapdf/content/graphic_object/arc.rb +57 -24
  29. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +66 -23
  30. data/lib/hexapdf/content/graphic_object/geom2d.rb +47 -6
  31. data/lib/hexapdf/content/graphic_object/solid_arc.rb +58 -36
  32. data/lib/hexapdf/content/graphic_object.rb +6 -7
  33. data/lib/hexapdf/content/graphics_state.rb +54 -45
  34. data/lib/hexapdf/content/operator.rb +54 -54
  35. data/lib/hexapdf/content/parser.rb +2 -2
  36. data/lib/hexapdf/content/processor.rb +15 -15
  37. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  38. data/lib/hexapdf/content.rb +5 -0
  39. data/lib/hexapdf/dictionary.rb +7 -5
  40. data/lib/hexapdf/dictionary_fields.rb +43 -16
  41. data/lib/hexapdf/digital_signature/cms_handler.rb +2 -2
  42. data/lib/hexapdf/digital_signature/handler.rb +1 -1
  43. data/lib/hexapdf/digital_signature/pkcs1_handler.rb +2 -3
  44. data/lib/hexapdf/digital_signature/signature.rb +6 -6
  45. data/lib/hexapdf/digital_signature/signatures.rb +13 -12
  46. data/lib/hexapdf/digital_signature/signing/default_handler.rb +14 -5
  47. data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -4
  48. data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +4 -4
  49. data/lib/hexapdf/digital_signature/signing.rb +4 -0
  50. data/lib/hexapdf/digital_signature/verification_result.rb +3 -4
  51. data/lib/hexapdf/digital_signature.rb +7 -2
  52. data/lib/hexapdf/document/destinations.rb +12 -11
  53. data/lib/hexapdf/document/files.rb +1 -1
  54. data/lib/hexapdf/document/fonts.rb +1 -1
  55. data/lib/hexapdf/document/layout.rb +170 -39
  56. data/lib/hexapdf/document/pages.rb +4 -3
  57. data/lib/hexapdf/document.rb +96 -55
  58. data/lib/hexapdf/encryption/aes.rb +5 -5
  59. data/lib/hexapdf/encryption/arc4.rb +1 -1
  60. data/lib/hexapdf/encryption/fast_aes.rb +2 -2
  61. data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
  62. data/lib/hexapdf/encryption/identity.rb +1 -1
  63. data/lib/hexapdf/encryption/ruby_aes.rb +11 -21
  64. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  65. data/lib/hexapdf/encryption/security_handler.rb +31 -24
  66. data/lib/hexapdf/encryption/standard_security_handler.rb +45 -36
  67. data/lib/hexapdf/encryption.rb +7 -2
  68. data/lib/hexapdf/error.rb +18 -0
  69. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  70. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  71. data/lib/hexapdf/filter/flate_decode.rb +1 -1
  72. data/lib/hexapdf/filter/lzw_decode.rb +1 -1
  73. data/lib/hexapdf/filter/pass_through.rb +1 -1
  74. data/lib/hexapdf/filter/predictor.rb +1 -1
  75. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  76. data/lib/hexapdf/filter.rb +55 -6
  77. data/lib/hexapdf/font/cmap/parser.rb +2 -2
  78. data/lib/hexapdf/font/cmap.rb +1 -1
  79. data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
  80. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  81. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
  82. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  83. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  84. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +3 -3
  85. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  86. data/lib/hexapdf/font/invalid_glyph.rb +3 -0
  87. data/lib/hexapdf/font/true_type_wrapper.rb +17 -4
  88. data/lib/hexapdf/font/type1_wrapper.rb +19 -4
  89. data/lib/hexapdf/font_loader/from_configuration.rb +5 -2
  90. data/lib/hexapdf/font_loader/from_file.rb +5 -5
  91. data/lib/hexapdf/font_loader/standard14.rb +3 -3
  92. data/lib/hexapdf/font_loader.rb +3 -0
  93. data/lib/hexapdf/image_loader/jpeg.rb +2 -2
  94. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  95. data/lib/hexapdf/image_loader/png.rb +2 -2
  96. data/lib/hexapdf/image_loader.rb +1 -1
  97. data/lib/hexapdf/importer.rb +13 -0
  98. data/lib/hexapdf/layout/box.rb +32 -5
  99. data/lib/hexapdf/layout/box_fitter.rb +2 -2
  100. data/lib/hexapdf/layout/column_box.rb +20 -5
  101. data/lib/hexapdf/layout/frame.rb +53 -18
  102. data/lib/hexapdf/layout/image_box.rb +5 -0
  103. data/lib/hexapdf/layout/inline_box.rb +21 -9
  104. data/lib/hexapdf/layout/list_box.rb +50 -20
  105. data/lib/hexapdf/layout/page_style.rb +6 -5
  106. data/lib/hexapdf/layout/style.rb +64 -9
  107. data/lib/hexapdf/layout/table_box.rb +684 -0
  108. data/lib/hexapdf/layout/text_box.rb +12 -3
  109. data/lib/hexapdf/layout/text_fragment.rb +29 -3
  110. data/lib/hexapdf/layout/text_layouter.rb +32 -8
  111. data/lib/hexapdf/layout.rb +1 -0
  112. data/lib/hexapdf/name_tree_node.rb +1 -1
  113. data/lib/hexapdf/number_tree_node.rb +1 -1
  114. data/lib/hexapdf/object.rb +18 -7
  115. data/lib/hexapdf/parser.rb +7 -7
  116. data/lib/hexapdf/pdf_array.rb +1 -1
  117. data/lib/hexapdf/rectangle.rb +1 -1
  118. data/lib/hexapdf/reference.rb +1 -1
  119. data/lib/hexapdf/revision.rb +1 -1
  120. data/lib/hexapdf/revisions.rb +3 -3
  121. data/lib/hexapdf/serializer.rb +15 -15
  122. data/lib/hexapdf/stream.rb +5 -4
  123. data/lib/hexapdf/tokenizer.rb +14 -14
  124. data/lib/hexapdf/type/acro_form/appearance_generator.rb +22 -22
  125. data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
  126. data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
  127. data/lib/hexapdf/type/acro_form/field.rb +2 -2
  128. data/lib/hexapdf/type/acro_form/form.rb +1 -1
  129. data/lib/hexapdf/type/acro_form/signature_field.rb +4 -4
  130. data/lib/hexapdf/type/acro_form/text_field.rb +1 -1
  131. data/lib/hexapdf/type/acro_form/variable_text_field.rb +1 -1
  132. data/lib/hexapdf/type/acro_form.rb +1 -1
  133. data/lib/hexapdf/type/action.rb +1 -1
  134. data/lib/hexapdf/type/actions/go_to.rb +1 -1
  135. data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
  136. data/lib/hexapdf/type/actions/launch.rb +1 -1
  137. data/lib/hexapdf/type/actions/set_ocg_state.rb +86 -0
  138. data/lib/hexapdf/type/actions/uri.rb +1 -1
  139. data/lib/hexapdf/type/actions.rb +2 -1
  140. data/lib/hexapdf/type/annotation.rb +3 -3
  141. data/lib/hexapdf/type/annotations/link.rb +1 -1
  142. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  143. data/lib/hexapdf/type/annotations/text.rb +2 -3
  144. data/lib/hexapdf/type/annotations/widget.rb +2 -2
  145. data/lib/hexapdf/type/annotations.rb +1 -1
  146. data/lib/hexapdf/type/catalog.rb +11 -2
  147. data/lib/hexapdf/type/cid_font.rb +18 -4
  148. data/lib/hexapdf/type/embedded_file.rb +1 -1
  149. data/lib/hexapdf/type/file_specification.rb +2 -2
  150. data/lib/hexapdf/type/font_descriptor.rb +1 -1
  151. data/lib/hexapdf/type/font_simple.rb +2 -2
  152. data/lib/hexapdf/type/font_type0.rb +3 -3
  153. data/lib/hexapdf/type/font_type3.rb +1 -1
  154. data/lib/hexapdf/type/form.rb +76 -6
  155. data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
  156. data/lib/hexapdf/type/icon_fit.rb +1 -1
  157. data/lib/hexapdf/type/image.rb +1 -1
  158. data/lib/hexapdf/type/info.rb +1 -1
  159. data/lib/hexapdf/type/mark_information.rb +1 -1
  160. data/lib/hexapdf/type/names.rb +2 -2
  161. data/lib/hexapdf/type/object_stream.rb +2 -1
  162. data/lib/hexapdf/type/optional_content_configuration.rb +170 -0
  163. data/lib/hexapdf/type/optional_content_group.rb +370 -0
  164. data/lib/hexapdf/type/optional_content_membership.rb +63 -0
  165. data/lib/hexapdf/type/optional_content_properties.rb +158 -0
  166. data/lib/hexapdf/type/outline.rb +1 -1
  167. data/lib/hexapdf/type/outline_item.rb +1 -1
  168. data/lib/hexapdf/type/page.rb +46 -21
  169. data/lib/hexapdf/type/page_label.rb +5 -9
  170. data/lib/hexapdf/type/page_tree_node.rb +1 -1
  171. data/lib/hexapdf/type/resources.rb +1 -1
  172. data/lib/hexapdf/type/trailer.rb +2 -2
  173. data/lib/hexapdf/type/viewer_preferences.rb +1 -1
  174. data/lib/hexapdf/type/xref_stream.rb +2 -2
  175. data/lib/hexapdf/type.rb +4 -0
  176. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -2
  177. data/lib/hexapdf/version.rb +1 -1
  178. data/lib/hexapdf/writer.rb +4 -4
  179. data/lib/hexapdf/xref_section.rb +2 -2
  180. data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +11 -1
  181. data/test/hexapdf/content/graphic_object/test_geom2d.rb +7 -0
  182. data/test/hexapdf/content/test_canvas.rb +49 -1
  183. data/test/hexapdf/digital_signature/test_signatures.rb +22 -0
  184. data/test/hexapdf/document/test_files.rb +2 -2
  185. data/test/hexapdf/document/test_layout.rb +105 -2
  186. data/test/hexapdf/document/test_pages.rb +6 -6
  187. data/test/hexapdf/encryption/test_security_handler.rb +12 -11
  188. data/test/hexapdf/encryption/test_standard_security_handler.rb +35 -23
  189. data/test/hexapdf/font/test_true_type_wrapper.rb +18 -1
  190. data/test/hexapdf/font/test_type1_wrapper.rb +15 -1
  191. data/test/hexapdf/layout/test_box.rb +14 -5
  192. data/test/hexapdf/layout/test_column_box.rb +65 -21
  193. data/test/hexapdf/layout/test_frame.rb +27 -15
  194. data/test/hexapdf/layout/test_image_box.rb +4 -0
  195. data/test/hexapdf/layout/test_inline_box.rb +17 -3
  196. data/test/hexapdf/layout/test_list_box.rb +84 -33
  197. data/test/hexapdf/layout/test_page_style.rb +3 -2
  198. data/test/hexapdf/layout/test_style.rb +60 -0
  199. data/test/hexapdf/layout/test_table_box.rb +728 -0
  200. data/test/hexapdf/layout/test_text_box.rb +26 -0
  201. data/test/hexapdf/layout/test_text_fragment.rb +33 -0
  202. data/test/hexapdf/layout/test_text_layouter.rb +36 -5
  203. data/test/hexapdf/test_composer.rb +10 -0
  204. data/test/hexapdf/test_dictionary.rb +10 -0
  205. data/test/hexapdf/test_dictionary_fields.rb +4 -1
  206. data/test/hexapdf/test_document.rb +5 -0
  207. data/test/hexapdf/test_filter.rb +8 -0
  208. data/test/hexapdf/test_importer.rb +9 -0
  209. data/test/hexapdf/test_object.rb +16 -5
  210. data/test/hexapdf/test_stream.rb +7 -0
  211. data/test/hexapdf/test_writer.rb +3 -3
  212. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +13 -5
  213. data/test/hexapdf/type/acro_form/test_form.rb +4 -3
  214. data/test/hexapdf/type/actions/test_set_ocg_state.rb +40 -0
  215. data/test/hexapdf/type/test_catalog.rb +11 -0
  216. data/test/hexapdf/type/test_form.rb +119 -0
  217. data/test/hexapdf/type/test_optional_content_configuration.rb +112 -0
  218. data/test/hexapdf/type/test_optional_content_group.rb +158 -0
  219. data/test/hexapdf/type/test_optional_content_properties.rb +109 -0
  220. data/test/hexapdf/type/test_page.rb +20 -6
  221. metadata +28 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f0907362b897b39d61fa8f859510ccfb31ebd5ad88b94a9e36ff62c62fae813a
4
- data.tar.gz: 469465941253bad5e769fc0dd5a57e437c578fdecda52a0fea908370ef8b7169
3
+ metadata.gz: 00aaef323df26b1a17c6e4ee39787c92037e8ae887713b28c3674962fcb6ac26
4
+ data.tar.gz: a46ecda2514bc5c044d115370f66402fc22ad3f8c8dfa1741e057b6849a6b952
5
5
  SHA512:
6
- metadata.gz: 2fc77d33ddc2c6fb377a778b82f92f01fed93d9a4e494cd57c97dc0a00fce4baa7cab185776f8a3303507d68b544e4404ac2f33b72c3b1a7cc7c65ee838c7dd7
7
- data.tar.gz: 21a08984f424b91594a2d8e6fc705a7f9458a990918ee77adef469e758ae2fee976ba905a7a4a696c5c2728831d02f8845dc9b5316c28de4ff5c7f062521a7e3
6
+ metadata.gz: a15e468bdc852fd4c16286ba0e4829fcd3fb3be64aa48c429246216fbfe1c856cb8e155bfefa83c47b99246e7161f20a1de54769aa222dbcdfdb25f8be777643
7
+ data.tar.gz: d75048ff9d77601d93893cceb0c73673410695e3ea381e17d27de8c92d7de3d29d2ed467e44df6362dd28d3ee374a8e5710e5f1323393ee2e4104cdcecef1112
data/CHANGELOG.md CHANGED
@@ -1,3 +1,103 @@
1
+ ## 0.34.0 - 2023-10-22
2
+
3
+ ### Added
4
+
5
+ * Support for optional content groups (layers)
6
+ * Support for reference XObjects
7
+ * Basic support for group XObjects
8
+ * [HexaPDF::Layout::Style#fill_horizontal] for allowing a text fragment to fill
9
+ the remaining space of line
10
+ * [HexaPDF::Layout::TextFragment#text] and [HexaPDF::Layout::TextBox#text] for
11
+ retrieving the text represented by the stored items
12
+ * [HexaPDF::Content::Canvas#pos] for retrieving untransformed positions
13
+ * [HexaPDF::Type::CIDFont::CIDSystemInfo] type class
14
+
15
+ ### Changed
16
+
17
+ * [HexaPDF::Composer#draw_box] to return the last drawn box
18
+ * [HexaPDF::Layout::Style::LinkLayer] to support arbitrary actions
19
+ * [HexaPDF::Layout::Frame::new] (and adapted other layout classes) to accept a
20
+ context argument (a page or Form XObject instance)
21
+ * [HexaPDF::Layout::ListBox] to use its 'fill_color' style property for the item
22
+ marker color
23
+ * [HexaPDF::Layout::Frame::FitResult#draw] to use optional content groups for
24
+ debug output
25
+
26
+ ### Fixed
27
+
28
+ * [HexaPDF::Document::Pages#add_labelling_range] to add a correct entry for
29
+ the default range starting at page 1
30
+ * [HexaPDF::Type::Page#flatten_annotations] to correctly handle scaled
31
+ appearances
32
+ * Using an unknown style name in [HexaPDF:Document::Layout] method by providing
33
+ a useful error message
34
+ * [HexaPDF::Layout::Box::new] to ensure that the properties attribute is always
35
+ a hash
36
+ * [HexaPDF::Layout::ListBox] to work correctly if the marker height is larger
37
+ than the item content height
38
+ * [HexaPDF::Dictionary] setting default values on wrong classes in certain
39
+ situations
40
+
41
+
42
+ ## 0.33.0 - 2023-08-02
43
+
44
+ ### Added
45
+
46
+ * [HexaPDF::Layout::TableBox] for rendering tables
47
+ * [HexaPDF::Document::Layout#table_box] for easier table box creation
48
+ * [HexaPDF::Content::GraphicObject::EndpointArc#max_curves] for setting the
49
+ approximation accuracy
50
+ * [HexaPDF::Importer::copy] for completely copying (including referenced
51
+ indirect objects) a single PDF object (which may be from the same document)
52
+ * [HexaPDF::Layout::Style::Border#draw_on_bounds] for drawing the border on the
53
+ bounds instead of inside
54
+ * [HexaPDF::MissingGlyphError] for better error messages when a font is missing
55
+ a glyph
56
+ * [HexaPDF::Font::Type1Wrapper#custom_glyph] and
57
+ [HexaPDF::Font::TrueTypeWrapper#custom_glyph] for custom glyph creation
58
+ * [HexaPDF::FiberDoubleForString] to avoid creating real `Fiber` instances when
59
+ not necessary
60
+ * Support for drawing `Geom2D::Rectangle` instances via the :geom2d graphic
61
+ object
62
+ * Optional argument `apply_first_text_indent` to
63
+ [HexaPDF::Layout::TextLayouter#fit]
64
+
65
+ ### Changed
66
+
67
+ * [HexaPDF::Layout::Frame] to use more efficient `Geom2D::Rectangle` class
68
+ * Internal constant `HexaPDF::Content::ColorSpace::CSS_COLOR_NAMES` changed to
69
+ [HexaPDF::Content::ColorSpace::COLOR_NAMES]
70
+ * Constructor of [HexaPDF::Layout::PageStyle] to allow setting `next_style`
71
+ attribute
72
+ * The encryption dictionary is now validated before using it for decryption
73
+ * Changed encryption permissions to be compatible to PDF 2.0 by always
74
+ activating the "extract content" permission
75
+ * Digital signature creation in case of signature widgets containing images to
76
+ work around bug in Adobe Acrobat
77
+ * [HexaPDF::Type::Page#each_annotation] and
78
+ [HexaPDF::Type::Page#flatten_annotations] to process certain invalid /Annot
79
+ keys without errors
80
+
81
+ ### Fixed
82
+
83
+ * **Breaking change**: [HexaPDF::Object::make_direct] now needs the document
84
+ instance as second argument to correctly resolve references
85
+ * [HexaPDF::Layout::ColumnBox], [HexaPDF::Layout::ListBox] and
86
+ [HexaPDF::Layout::ImageBox] to correctly respond to `#empty?`
87
+ * [HexaPDF::Layout::ColumnBox] and [HexaPDF::Layout::ListBox] to take different
88
+ final box positions into account
89
+ * [HexaPDF::Content::Canvas#text] to set the leading only when multiple lines
90
+ are drawn
91
+ * [HexaPDF::Layout::TextBox#split] to use float comparison
92
+ * Validation of standard encryption dictionary to auto-correct invalid /U and
93
+ /O fields in case they are padded with zeros
94
+ * [HexaPDF::Document#wrap] handling of sub-type mapping in case of missing type
95
+ * [HexaPDF::Type::AcroForm::AppearanceGenerator] to also take a text field
96
+ widget's width into account when auto-sizing
97
+ * [HexaPDF::Layout::TextBox] to correctly handle text indentation for split
98
+ boxes
99
+
100
+
1
101
  ## 0.32.2 - 2023-05-06
2
102
 
3
103
  ### Changed
@@ -38,7 +138,7 @@
38
138
  ### Added
39
139
 
40
140
  * [HexaPDF::Document::Layout#method_missing] for more convenient box creation
41
- * [HexaPDF::Document::Composer#method_missing] for more convenient box drawing
141
+ * [HexaPDF::Composer#method_missing] for more convenient box drawing
42
142
  * [HexaPDF::Document::Layout#inline_box] for easy creation of inline boxes
43
143
  * [HexaPDF::Type::OutlineItem#open?] for getting the open state of an outline
44
144
  item
@@ -65,6 +165,8 @@
65
165
 
66
166
  * [HexaPDF::Layout::PageStyle] for collecting all styling information for pages
67
167
  * [HexaPDF::Composer#page_style] for configuring different page styles
168
+ * Configuration option 'filter.flate.on_error' for handling potentially
169
+ recoverable flate errors
68
170
 
69
171
  ### Changed
70
172
 
@@ -84,6 +186,7 @@
84
186
  deleted
85
187
  * `HexaPDF::Type::Page#perform_validation` to set a /MediaBox for invalid pages
86
188
  that don't have one
189
+ * Parsing of invalid flate encoded streams that can potentially be recovered
87
190
 
88
191
 
89
192
  ## 0.30.0 - 2023-02-13
data/README.md CHANGED
@@ -13,6 +13,9 @@ In short, it allows
13
13
  * **securing** PDF files by encrypting or signing them and
14
14
  * **optimizing** PDF files for smaller file size or other criteria.
15
15
 
16
+ HexaPDF is available under two license, the AGPL and a commercial license, see the [License
17
+ section](#License) for details.
18
+
16
19
 
17
20
  ## Features
18
21
 
@@ -156,6 +159,12 @@ dependencies as well as make sure that all applications needed for the tests are
156
159
  AGPL - see the LICENSE file for licensing details. Commercial licenses are available at
157
160
  <https://gettalong.at/hexapdf/>.
158
161
 
162
+ A commercial license is needed as soon as HexaPDF is distributed with your software or remotely
163
+ accessed via a network and you don't provide the source code of your application under the AGPL. For
164
+ example, if you serve PDFs on the fly in a web application.
165
+
166
+ Contact <sales@gettalong.at> for more information!
167
+
159
168
  Some included files have a different license:
160
169
 
161
170
  * For the license of the included AFM files in the `data/hexapdf/afm` directory, see the file
@@ -29,8 +29,8 @@ end
29
29
 
30
30
  # Basic transformations: translate, scale, rotate, skew
31
31
  canvas.translate(0, 710) do
32
- normal_color = [0.7, 0.7, 0.3]
33
- transformed_color = [0.3, 0.7, 0.7]
32
+ normal_color = "black"
33
+ transformed_color = "hp-blue"
34
34
 
35
35
  canvas.translate(50, 0) do
36
36
  transformation_shape(canvas, normal_color)
@@ -134,7 +134,7 @@ canvas.translate(0, 320) do
134
134
  canvas.arc(180, 50, a: 40, b: 20, start_angle: -60, end_angle: 115, inclination: 45)
135
135
  canvas.stroke
136
136
 
137
- canvas.fill_color(0.4, 0.3, 0.4)
137
+ canvas.fill_color("hp-blue")
138
138
  canvas.arc(250, 50, a: 10, start_angle: -60, end_angle: 115)
139
139
  canvas.arc(300, 50, a: 40, b: 20, start_angle: -60, end_angle: 115)
140
140
  canvas.arc(380, 50, a: 40, b: 20, start_angle: -60, end_angle: 115, inclination: 45)
@@ -142,13 +142,13 @@ canvas.translate(0, 320) do
142
142
 
143
143
  arc = canvas.graphic_object(:arc, cx: 450, cy: 50, a: 30, b: 30,
144
144
  start_angle: -30, end_angle: 105)
145
- canvas.fill_color(0.4, 0.3, 0.4)
145
+ canvas.fill_color("hp-blue")
146
146
  canvas.move_to(450, 50)
147
147
  canvas.line_to(*arc.start_point)
148
148
  arc.curves.each {|x, y, hash| canvas.curve_to(x, y, **hash)}
149
149
  canvas.fill
150
150
  arc.configure(start_angle: 105, end_angle: -30)
151
- canvas.fill_color(0.3, 0.7, 0.7)
151
+ canvas.fill_color("hp-orange")
152
152
  canvas.move_to(450, 50)
153
153
  canvas.line_to(*arc.start_point)
154
154
  arc.curves.each {|x, y, hash| canvas.curve_to(x, y, **hash)}
@@ -156,13 +156,13 @@ canvas.translate(0, 320) do
156
156
 
157
157
  arc = canvas.graphic_object(:arc, cx: 530, cy: 50, a: 40, b: 20,
158
158
  start_angle: -30, end_angle: 105)
159
- canvas.fill_color(0.4, 0.3, 0.4)
159
+ canvas.fill_color("hp-blue")
160
160
  canvas.move_to(530, 50)
161
161
  canvas.line_to(*arc.start_point)
162
162
  arc.curves.each {|x, y, hash| canvas.curve_to(x, y, **hash)}
163
163
  canvas.fill
164
164
  arc.configure(start_angle: 105, end_angle: -30)
165
- canvas.fill_color(0.7, 0.7, 0.3)
165
+ canvas.fill_color("hp-orange")
166
166
  canvas.move_to(530, 50)
167
167
  canvas.line_to(*arc.start_point)
168
168
  arc.curves.each {|x, y, hash| canvas.curve_to(x, y, **hash)}
@@ -194,7 +194,7 @@ end
194
194
  # fill nonzero and stroke, close fill even-odd and stroke, clip even-odd, clip
195
195
  # nonzero
196
196
  canvas.translate(0, 190) do
197
- canvas.fill_color(0.3, 0.7, 0.7)
197
+ canvas.fill_color("hp-blue")
198
198
 
199
199
  [
200
200
  [:stroke], [:close_stroke], [:fill, :nonzero], [:fill, :even_odd],
@@ -212,8 +212,6 @@ canvas.translate(0, 190) do
212
212
  end
213
213
  end
214
214
 
215
- canvas.fill_color(0.7, 0.7, 0.3)
216
-
217
215
  [:even_odd, :nonzero].each_with_index do |op, index|
218
216
  canvas.translate(370 + 110 * index, 20) do
219
217
  canvas.circle(50, 50, 50)
@@ -228,7 +226,7 @@ end
228
226
 
229
227
  # Some composite shapes, an image and a form XObject
230
228
  canvas.translate(0, 80) do
231
- canvas.fill_color(0.3, 0.7, 0.7)
229
+ canvas.fill_color("hp-blue")
232
230
  canvas.rectangle(50, 0, 80, 80, radius: 80)
233
231
  canvas.fill
234
232
 
@@ -237,14 +235,14 @@ canvas.translate(0, 80) do
237
235
 
238
236
  canvas.line_width(0.5)
239
237
  canvas.opacity(fill_alpha: 0.5, stroke_alpha: 0.2) do
240
- canvas.fill_color('AA8888').draw(solid).fill_stroke
241
- canvas.fill_color('88AA88').draw(solid, start_angle: 130, end_angle: 220).fill_stroke
242
- canvas.fill_color('8888AA').draw(solid, start_angle: 220, end_angle: 10).fill_stroke
238
+ canvas.fill_color("hp-blue").draw(solid).fill_stroke
239
+ canvas.fill_color("hp-orange").draw(solid, start_angle: 130, end_angle: 220).fill_stroke
240
+ canvas.fill_color("hp-teal").draw(solid, start_angle: 220, end_angle: 10).fill_stroke
243
241
 
244
242
  solid.configure(inner_a: 0, inner_b: 0, outer_a: 40, outer_b: 40, cx: 290)
245
- canvas.fill_color('AA8888').draw(solid, start_angle: 10, end_angle: 130).fill_stroke
246
- canvas.fill_color('88AA88').draw(solid, start_angle: 130, end_angle: 220).fill_stroke
247
- canvas.fill_color('8888AA').draw(solid, start_angle: 220, end_angle: 10).fill_stroke
243
+ canvas.fill_color("hp-blue").draw(solid, start_angle: 10, end_angle: 130).fill_stroke
244
+ canvas.fill_color("hp-orange").draw(solid, start_angle: 130, end_angle: 220).fill_stroke
245
+ canvas.fill_color("hp-teal").draw(solid, start_angle: 220, end_angle: 10).fill_stroke
248
246
 
249
247
  canvas.image(File.join(__dir__, 'machupicchu.jpg'), at: [350, 0], height: 80)
250
248
  end
data/examples/003-arcs.rb CHANGED
@@ -19,20 +19,20 @@ radius = 75
19
19
  center = [page.box.width * 0.25, page.box.height * 0.85]
20
20
  pie = canvas.graphic_object(:solid_arc, cx: center[0], cy: center[1],
21
21
  outer_a: radius, outer_b: radius)
22
- canvas.fill_color('ddddff')
22
+ canvas.fill_color("hp-orange-light")
23
23
  canvas.draw(pie, start_angle: 30, end_angle: 110).fill
24
- canvas.fill_color('ffdddd')
24
+ canvas.fill_color("hp-teal-light")
25
25
  canvas.draw(pie, start_angle: 110, end_angle: 130).fill
26
- canvas.fill_color('ddffdd')
26
+ canvas.fill_color("hp-blue-light")
27
27
  canvas.draw(pie, start_angle: 130, end_angle: 30).fill
28
28
 
29
29
  arc = canvas.graphic_object(:arc, cx: center[0], cy: center[1],
30
30
  a: radius, b: radius)
31
- canvas.stroke_color('0000ff')
31
+ canvas.stroke_color("hp-orange")
32
32
  canvas.draw(arc, start_angle: 30, end_angle: 110).stroke
33
- canvas.stroke_color('ff0000')
33
+ canvas.stroke_color("hp-teal")
34
34
  canvas.draw(arc, start_angle: 110, end_angle: 130).stroke
35
- canvas.stroke_color('00ff00')
35
+ canvas.stroke_color("hp-blue-dark")
36
36
  canvas.draw(arc, start_angle: 130, end_angle: 30).stroke
37
37
 
38
38
  # Right pie chart
@@ -40,11 +40,11 @@ center = [page.box.width * 0.75, page.box.height * 0.85]
40
40
  canvas.stroke_color('777777')
41
41
  pie = canvas.graphic_object(:solid_arc, cx: center[0], cy: center[1],
42
42
  outer_a: radius, outer_b: radius)
43
- canvas.fill_color('ddddff')
43
+ canvas.fill_color("hp-orange-light")
44
44
  canvas.draw(pie, start_angle: 30, end_angle: 110).fill_stroke
45
- canvas.fill_color('ffdddd')
45
+ canvas.fill_color("hp-teal-light")
46
46
  canvas.draw(pie, start_angle: 110, end_angle: 130).fill_stroke
47
- canvas.fill_color('ddffdd')
47
+ canvas.fill_color("hp-blue-light")
48
48
  canvas.draw(pie, start_angle: 130, end_angle: 30).fill_stroke
49
49
 
50
50
  doc.write('arcs.pdf', optimize: true)
@@ -40,7 +40,7 @@ tl = HexaPDF::Layout::TextLayouter.new
40
40
 
41
41
  tl.style.align(align).valign(valign)
42
42
  tl.fit([tf], width, height).draw(canvas, x, y)
43
- canvas.stroke_color(128, 0, 0).rectangle(x, y, width, -height).stroke
43
+ canvas.stroke_color("hp-blue-dark").rectangle(x, y, width, -height).stroke
44
44
  end
45
45
  end
46
46
 
@@ -42,13 +42,13 @@ items = sample_text.split(/(:-\)|;-\))/).map do |part|
42
42
  case part
43
43
  when ':-)'
44
44
  InlineBox.create(width: size * 2, height: size * 2, content_box: true,
45
- background_color: [162, 234, 247], padding: 2) do |canvas, box|
45
+ background_color: "hp-blue-light", padding: 2) do |canvas, box|
46
46
  canvas.image(emoji_smile, at: [0, 0], width: box.content_width)
47
47
  end
48
48
  when ';-)'
49
49
  InlineBox.create(width: size, height: size, content_box: true,
50
50
  valign: :top, padding: 5, margin: [0, 10],
51
- border: {width: [1, 2], color: [200, 40]}) do |canvas, box|
51
+ border: {width: [1, 2], color: "hp-blue"}) do |canvas, box|
52
52
  canvas.image(emoji_wink, at: [0, 0], width: box.content_width)
53
53
  end
54
54
  else
@@ -49,7 +49,7 @@ layouter = HexaPDF::Layout::TextLayouter.new
49
49
  [30, 60, 100, 160].each do |width|
50
50
  result = layouter.fit([frag], width, 400)
51
51
  result.draw(canvas, x, y)
52
- canvas.stroke_color(255, 0, 0).line_width(0.2)
52
+ canvas.stroke_color("hp-blue-dark").line_width(0.2)
53
53
  canvas.rectangle(x, y, width, -result.height).stroke
54
54
  y -= result.height + 5
55
55
  end
@@ -44,9 +44,9 @@ base_style = {font: base_font, font_size: 12, text_indent: 20}
44
44
  styles = {
45
45
  "Fonts | Font Sizes | Colors" => [
46
46
  {font: doc.fonts.add("Times", variant: :italic),
47
- font_size: 12, fill_color: [0, 0, 255]},
47
+ font_size: 12, fill_color: "hp-blue-light"},
48
48
  {font: doc.fonts.add("Courier"), font_size: 14,
49
- fill_color: [0, 255, 0]},
49
+ fill_color: "hp-orange"},
50
50
  {font: doc.fonts.add("Helvetica", variant: :bold),
51
51
  font_size: 20, fill_alpha: 0.5},
52
52
  ],
@@ -72,16 +72,16 @@ styles = {
72
72
  {**base_style, text_rendering_mode: :stroke,
73
73
  stroke_width: 0.1},
74
74
  {**base_style, font_size: 20, text_rendering_mode: :fill_stroke,
75
- stroke_color: [0, 255, 0], stroke_width: 0.7,
75
+ stroke_color: "hp-orange-light", stroke_width: 0.7,
76
76
  stroke_dash_pattern: [0.5, 1, 1.5], stroke_cap_style: :round},
77
77
  ],
78
78
  "Underlays | Overlays" => [
79
79
  {**base_style, underlays: [lambda do |canv, box|
80
- canv.fill_color(240, 240, 0).opacity(fill_alpha: 0.5).
80
+ canv.fill_color("hp-orange-light2").opacity(fill_alpha: 0.5).
81
81
  rectangle(0, 0, box.width, box.height).fill
82
82
  end]},
83
83
  {**base_style, overlays: [lambda do |canv, box|
84
- canv.line_width(1).stroke_color([0, 255, 0]).
84
+ canv.line_width(1).stroke_color("hp-teal-light2").
85
85
  line(0, -box.y_min, box.width, box.y_max - box.y_min).stroke
86
86
  end]},
87
87
  ],
@@ -91,7 +91,7 @@ styles = {
91
91
  ]},
92
92
  {**base_style, overlays: [
93
93
  [:link, uri: "https://hexapdf.gettalong.org",
94
- border: [0, 0, 2, [3, 3]], border_color: [89, 150, 220]],
94
+ border: [0, 0, 2, [3, 3]], border_color: "hp-blue"],
95
95
  ]},
96
96
  {**base_style, overlays: [
97
97
  [:link, file: "text_layouter_styling.pdf", border: true],
@@ -115,7 +115,7 @@ styles.each do |desc, variations|
115
115
  fragment(str, base_style)
116
116
  end
117
117
  end
118
- items.unshift(fragment(desc + ": ", fill_color: [255, 0, 0], **base_style))
118
+ items.unshift(fragment(desc + ": ", fill_color: "hp-blue-dark", **base_style))
119
119
  y = draw_text(layouter.fit(items, width, 400), canvas, left, y) - 20
120
120
  end
121
121
 
@@ -31,7 +31,7 @@ doc = HexaPDF::Document.new
31
31
  page = doc.pages.add
32
32
  canvas = page.canvas
33
33
  canvas.font("Times", size: 10, variant: :bold)
34
- canvas.stroke_color(255, 0, 0).line_width(0.2)
34
+ canvas.stroke_color("hp-blue-dark").line_width(0.2)
35
35
  font = doc.fonts.add("Times")
36
36
 
37
37
  sample_text = "Lorem ipsum dolor sit amet, con\u{00AD}sectetur
@@ -53,7 +53,7 @@ width_spec = WidthFromPolygon.new(polygon)
53
53
  result = layouter.fit(items, width_spec, polygon.bbox.height)
54
54
  result.draw(canvas, 150, 550)
55
55
  canvas.translate(150, 100).
56
- stroke_color(255, 0, 0).opacity(stroke_alpha: 0.5).
56
+ stroke_color("hp-blue-dark").
57
57
  line_width(0.5).
58
58
  draw(:geom2d, object: polygon)
59
59
 
@@ -37,13 +37,14 @@ end
37
37
 
38
38
  canvas = doc.pages.add.canvas
39
39
 
40
- [[1, 140], [5, 190], [15, 240]].each_with_index do |(width, red), row|
41
- [[:solid, 140], [:dashed, 177], [:dashed_round, 207],
42
- [:dotted, 240]].each_with_index do |(style, green), column|
40
+ [[1, "hp-blue-light"], [5, "hp-teal-light"],
41
+ [15, "hp-orange-light"]].each_with_index do |(width, color), row|
42
+ color = canvas.color_from_specification([color])
43
+ [:solid, :dashed, :dashed_round, :dotted].each_with_index do |style, column|
43
44
  box = HexaPDF::Layout::Box.create(
44
45
  width: 100, height: 100, content_box: true,
45
46
  border: {width: width, style: style},
46
- background_color: [red, green, 0],
47
+ background_color: color.components.map {|c| c + 0.2 * column },
47
48
  &annotate_box)
48
49
  box.draw(canvas, 20 + 140 * column, 700 - 150 * row)
49
50
  end
@@ -54,9 +55,9 @@ box = HexaPDF::Layout::Box.create(
54
55
  width: 470, height: 200, content_box: true,
55
56
  padding: [20, 5, 10, 15],
56
57
  border: {width: [20, 40, 30, 15],
57
- color: [[46, 185, 206], [206, 199, 46], [188, 46, 206], [59, 206, 46]],
58
+ color: ["hp-blue", "hp-orange", "hp-teal", "hp-blue-light"],
58
59
  style: [:solid, :dashed, :dashed_round, :dotted]},
59
- background_color: [255, 255, 180],
60
+ background_color: "hp-orange-light2",
60
61
  underlays: [
61
62
  lambda do |canv, _|
62
63
  canv.stroke_color([255, 0, 0]).line_width(10).line_cap_style(:butt).
@@ -66,7 +67,7 @@ box = HexaPDF::Layout::Box.create(
66
67
  ],
67
68
  overlays: [
68
69
  lambda do |canv, _|
69
- canv.stroke_color([0, 0, 255]).line_width(5).
70
+ canv.stroke_color("hp-blue-dark").line_width(5).
70
71
  rectangle(10, 10, box.width - 20, box.height - 20).stroke
71
72
  end
72
73
  ],
@@ -28,9 +28,9 @@ frame = Frame.new(page_box.left + 20, page_box.bottom + 20,
28
28
 
29
29
  box_counter = 1
30
30
  draw_box = lambda do |**args|
31
- b = Box.create(**args, border: {width: 1, color: [[255, 0, 0]]}) do |canv, box|
31
+ b = Box.create(**args, border: {width: 1, color: "hp-blue-dark"}) do |canv, box|
32
32
  canv.save_graphics_state do
33
- canv.stroke_color(255, 0, 0)
33
+ canv.stroke_color("hp-blue-dark")
34
34
  canv.line(0, 0, box.content_width, box.content_height).
35
35
  line(0, box.content_height, box.content_width, 0).
36
36
  stroke
@@ -29,7 +29,8 @@ boxes << doc.layout.image_box(File.join(__dir__, 'machupicchu.jpg'),
29
29
  width: 100, margin: [10, 30], position: :float)
30
30
  boxes << Box.create(width: 50, height: 50, margin: 20,
31
31
  position: :float, position_hint: :right,
32
- border: {width: 1, color: [[255, 0, 0]]})
32
+ background_color: "hp-blue-light2",
33
+ border: {width: 1, color: "hp-blue-dark"})
33
34
  boxes << doc.layout.lorem_ipsum_box(count: 3, position: :flow, align: :justify)
34
35
 
35
36
  i = 0
@@ -27,7 +27,7 @@ ullamco laboris nisi ut aliquip ex ea commodo consequat. ".tr("\n", " ")
27
27
  HexaPDF::Composer.create('composer.pdf') do |pdf|
28
28
  pdf.style(:base, line_spacing: 1.5, last_line_gap: true, align: :justify)
29
29
  pdf.style(:image, border: {width: 1}, padding: 5, margin: 10)
30
- pdf.style(:link, fill_color: [6, 158, 224], underline: true)
30
+ pdf.style(:link, fill_color: "hp-blue-dark", underline: true)
31
31
  image = File.join(__dir__, 'machupicchu.jpg')
32
32
 
33
33
  pdf.text(lorem_ipsum * 2)
@@ -29,7 +29,8 @@ columns = doc.layout.column(columns: 2, style: {position: :flow}) do |column|
29
29
  style: {margin: [10, 30], position: :float})
30
30
  column.box(:base, width: 50, height: 50,
31
31
  style: {margin: 20, position: :float, position_hint: :right,
32
- border: {width: 1, color: [[255, 0, 0]]}})
32
+ background_color: "hp-blue-light2",
33
+ border: {width: 1, color: "hp-blue-dark"}})
33
34
  column.lorem_ipsum(count: 2, position: :flow, align: :justify)
34
35
  end
35
36
  end
@@ -0,0 +1,46 @@
1
+ # # Table Box
2
+ #
3
+ # This example shows how [HexaPDF::Layout::TableBox] can be used to
4
+ # create tables.
5
+ #
6
+ # Usage:
7
+ # : `ruby table_box.rb`
8
+ #
9
+
10
+ require 'hexapdf'
11
+
12
+ image = File.join(__dir__, 'machupicchu.jpg')
13
+
14
+ HexaPDF::Composer.create("table_box.pdf") do |composer|
15
+ # We start with the simplest table
16
+ data = [['Hello', 'World'], ['How', 'are you?']]
17
+ composer.table(data)
18
+
19
+ # The width of the columns can be specified
20
+ composer.table(data, column_widths: [100, 50])
21
+
22
+ # Besides text a table cell can contain any other element
23
+ l = composer.document.layout
24
+ data = [['Text', 'Just simple text'],
25
+ ['Image', l.image(image)],
26
+ ['List', l.list {|list| list.text('Hello'); list.text('List')}],
27
+ ['Columns', l.column {|c| c.lorem_ipsum(count: 4) }]]
28
+ composer.table(data, column_widths: [50])
29
+
30
+ # A table can be split if necessary
31
+ composer.table([[l.lorem_ipsum(sentences: 1), l.lorem_ipsum(sentences: 1)],
32
+ [l.lorem_ipsum, l.lorem_ipsum]])
33
+
34
+ # It is possible to specify headers and footers which all split parts
35
+ # will have
36
+ composer.column(height: 200) do |column|
37
+ header = lambda {|table| [[l.text('Header left'), l.text('Header right')]] }
38
+ footer = lambda {|table| [[l.text('Footer left'), l.text('Footer right')]] }
39
+ column.table([[l.lorem_ipsum(sentences: 1), l.lorem_ipsum(sentences: 1)],
40
+ [l.lorem_ipsum(sentences: 1), l.lorem_ipsum(sentences: 1)],
41
+ [l.lorem_ipsum(sentences: 1), l.lorem_ipsum(sentences: 1)],
42
+ [l.lorem_ipsum(sentences: 1), l.lorem_ipsum(sentences: 1)]],
43
+ header: header, footer: footer)
44
+
45
+ end
46
+ end
@@ -0,0 +1,55 @@
1
+ # # Optional Content (a.k.a. Layers)
2
+ #
3
+ # This example shows how to create and assign optional content groups (OCGs) to
4
+ # parts of the content of a page.
5
+ #
6
+ # Four OCGs are created: Squares, Black, Blue, and Orange. The Squares one is
7
+ # applied to everything, the others to the respectively colored squares.
8
+ #
9
+ # When viewed in a compatible viewer, the "Optional Content" or "Layers" panel
10
+ # can be used to switch the layers on and off, resulting in the respective
11
+ # squares appearing or disappearing. Initially, the blue one is not shown, only
12
+ # the black and orange ones.
13
+ #
14
+ # Additionally, if supported by a viewer and if the visibility hasn't been
15
+ # manually changed, the OCGs for the squares are also configured to only be
16
+ # visible at certain zoom levels. For example, the black one is only visible up
17
+ # to a zoom level of 100%.
18
+ #
19
+ # Usage:
20
+ # : `ruby optional_content.rb`
21
+ #
22
+ require 'hexapdf'
23
+
24
+ doc = HexaPDF::Document.new
25
+
26
+ ocg = doc.optional_content.ocg('Squares')
27
+ ocg1 = doc.optional_content.ocg('Black')
28
+ ocg1.zoom(max: 1)
29
+ ocg1.add_to_ui(path: ocg)
30
+ ocg2 = doc.optional_content.ocg('Blue')
31
+ ocg2.zoom(min: 1, max: 2)
32
+ ocg2.add_to_ui(path: ocg)
33
+ ocg2.off!
34
+ ocg3 = doc.optional_content.ocg('Orange')
35
+ ocg3.zoom(min: 2, max: 20)
36
+ ocg3.add_to_ui(path: ocg)
37
+
38
+ canvas = doc.pages.add([0, 0, 200, 200]).canvas
39
+ canvas.optional_content(ocg) do
40
+ canvas.optional_content(ocg1) do
41
+ canvas.fill_color('black').rectangle(20, 80, 100, 100).fill
42
+ end
43
+ canvas.optional_content(ocg2) do
44
+ canvas.fill_color('hp-blue').rectangle(50, 50, 100, 100).fill
45
+ end
46
+ canvas.optional_content(ocg3) do
47
+ canvas.fill_color('hp-orange').rectangle(80, 20, 100, 100).fill
48
+ end
49
+ end
50
+
51
+ doc.optional_content.default_configuration[:AS] = [
52
+ {Event: :View, Category: [:Zoom], OCGs: [ocg1, ocg2, ocg3]}
53
+ ]
54
+
55
+ doc.write('optional_content.pdf')