hexapdf 0.32.2 → 0.34.0

Sign up to get free protection for your applications and to get access to all the features.
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')