hexapdf 0.32.2 → 0.33.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 (202) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +63 -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/lib/hexapdf/cli/command.rb +5 -2
  19. data/lib/hexapdf/cli/form.rb +5 -5
  20. data/lib/hexapdf/cli/inspect.rb +3 -3
  21. data/lib/hexapdf/composer.rb +104 -52
  22. data/lib/hexapdf/configuration.rb +44 -39
  23. data/lib/hexapdf/content/canvas.rb +393 -267
  24. data/lib/hexapdf/content/color_space.rb +72 -25
  25. data/lib/hexapdf/content/graphic_object/arc.rb +57 -24
  26. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +66 -23
  27. data/lib/hexapdf/content/graphic_object/geom2d.rb +47 -6
  28. data/lib/hexapdf/content/graphic_object/solid_arc.rb +58 -36
  29. data/lib/hexapdf/content/graphic_object.rb +6 -7
  30. data/lib/hexapdf/content/graphics_state.rb +54 -45
  31. data/lib/hexapdf/content/operator.rb +52 -54
  32. data/lib/hexapdf/content/parser.rb +2 -2
  33. data/lib/hexapdf/content/processor.rb +15 -15
  34. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  35. data/lib/hexapdf/content.rb +5 -0
  36. data/lib/hexapdf/dictionary.rb +6 -5
  37. data/lib/hexapdf/dictionary_fields.rb +42 -14
  38. data/lib/hexapdf/digital_signature/cms_handler.rb +2 -2
  39. data/lib/hexapdf/digital_signature/handler.rb +1 -1
  40. data/lib/hexapdf/digital_signature/pkcs1_handler.rb +2 -3
  41. data/lib/hexapdf/digital_signature/signature.rb +6 -6
  42. data/lib/hexapdf/digital_signature/signatures.rb +13 -12
  43. data/lib/hexapdf/digital_signature/signing/default_handler.rb +14 -5
  44. data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -4
  45. data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +4 -4
  46. data/lib/hexapdf/digital_signature/signing.rb +4 -0
  47. data/lib/hexapdf/digital_signature/verification_result.rb +2 -2
  48. data/lib/hexapdf/digital_signature.rb +7 -2
  49. data/lib/hexapdf/document/destinations.rb +12 -11
  50. data/lib/hexapdf/document/files.rb +1 -1
  51. data/lib/hexapdf/document/fonts.rb +1 -1
  52. data/lib/hexapdf/document/layout.rb +167 -39
  53. data/lib/hexapdf/document/pages.rb +3 -2
  54. data/lib/hexapdf/document.rb +89 -55
  55. data/lib/hexapdf/encryption/aes.rb +5 -5
  56. data/lib/hexapdf/encryption/arc4.rb +1 -1
  57. data/lib/hexapdf/encryption/fast_aes.rb +2 -2
  58. data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
  59. data/lib/hexapdf/encryption/identity.rb +1 -1
  60. data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
  61. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  62. data/lib/hexapdf/encryption/security_handler.rb +31 -24
  63. data/lib/hexapdf/encryption/standard_security_handler.rb +45 -36
  64. data/lib/hexapdf/encryption.rb +7 -2
  65. data/lib/hexapdf/error.rb +18 -0
  66. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  67. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  68. data/lib/hexapdf/filter/flate_decode.rb +1 -1
  69. data/lib/hexapdf/filter/lzw_decode.rb +1 -1
  70. data/lib/hexapdf/filter/pass_through.rb +1 -1
  71. data/lib/hexapdf/filter/predictor.rb +1 -1
  72. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  73. data/lib/hexapdf/filter.rb +55 -6
  74. data/lib/hexapdf/font/cmap/parser.rb +2 -2
  75. data/lib/hexapdf/font/cmap.rb +1 -1
  76. data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
  77. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  78. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
  79. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  80. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  81. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +3 -3
  82. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  83. data/lib/hexapdf/font/invalid_glyph.rb +3 -0
  84. data/lib/hexapdf/font/true_type_wrapper.rb +17 -4
  85. data/lib/hexapdf/font/type1_wrapper.rb +19 -4
  86. data/lib/hexapdf/font_loader/from_configuration.rb +5 -2
  87. data/lib/hexapdf/font_loader/from_file.rb +5 -5
  88. data/lib/hexapdf/font_loader/standard14.rb +3 -3
  89. data/lib/hexapdf/font_loader.rb +3 -0
  90. data/lib/hexapdf/image_loader/jpeg.rb +2 -2
  91. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  92. data/lib/hexapdf/image_loader/png.rb +2 -2
  93. data/lib/hexapdf/image_loader.rb +1 -1
  94. data/lib/hexapdf/importer.rb +13 -0
  95. data/lib/hexapdf/layout/box.rb +9 -2
  96. data/lib/hexapdf/layout/box_fitter.rb +2 -2
  97. data/lib/hexapdf/layout/column_box.rb +18 -4
  98. data/lib/hexapdf/layout/frame.rb +30 -12
  99. data/lib/hexapdf/layout/image_box.rb +5 -0
  100. data/lib/hexapdf/layout/inline_box.rb +1 -0
  101. data/lib/hexapdf/layout/list_box.rb +17 -1
  102. data/lib/hexapdf/layout/page_style.rb +4 -4
  103. data/lib/hexapdf/layout/style.rb +18 -3
  104. data/lib/hexapdf/layout/table_box.rb +682 -0
  105. data/lib/hexapdf/layout/text_box.rb +5 -3
  106. data/lib/hexapdf/layout/text_fragment.rb +1 -1
  107. data/lib/hexapdf/layout/text_layouter.rb +12 -4
  108. data/lib/hexapdf/layout.rb +1 -0
  109. data/lib/hexapdf/name_tree_node.rb +1 -1
  110. data/lib/hexapdf/number_tree_node.rb +1 -1
  111. data/lib/hexapdf/object.rb +18 -7
  112. data/lib/hexapdf/parser.rb +7 -7
  113. data/lib/hexapdf/pdf_array.rb +1 -1
  114. data/lib/hexapdf/rectangle.rb +1 -1
  115. data/lib/hexapdf/reference.rb +1 -1
  116. data/lib/hexapdf/revision.rb +1 -1
  117. data/lib/hexapdf/revisions.rb +3 -3
  118. data/lib/hexapdf/serializer.rb +15 -15
  119. data/lib/hexapdf/stream.rb +4 -2
  120. data/lib/hexapdf/tokenizer.rb +14 -14
  121. data/lib/hexapdf/type/acro_form/appearance_generator.rb +22 -22
  122. data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
  123. data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
  124. data/lib/hexapdf/type/acro_form/field.rb +2 -2
  125. data/lib/hexapdf/type/acro_form/form.rb +1 -1
  126. data/lib/hexapdf/type/acro_form/signature_field.rb +4 -4
  127. data/lib/hexapdf/type/acro_form/text_field.rb +1 -1
  128. data/lib/hexapdf/type/acro_form/variable_text_field.rb +1 -1
  129. data/lib/hexapdf/type/acro_form.rb +1 -1
  130. data/lib/hexapdf/type/action.rb +1 -1
  131. data/lib/hexapdf/type/actions/go_to.rb +1 -1
  132. data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
  133. data/lib/hexapdf/type/actions/launch.rb +1 -1
  134. data/lib/hexapdf/type/actions/uri.rb +1 -1
  135. data/lib/hexapdf/type/actions.rb +1 -1
  136. data/lib/hexapdf/type/annotation.rb +3 -3
  137. data/lib/hexapdf/type/annotations/link.rb +1 -1
  138. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  139. data/lib/hexapdf/type/annotations/text.rb +1 -1
  140. data/lib/hexapdf/type/annotations/widget.rb +2 -2
  141. data/lib/hexapdf/type/annotations.rb +1 -1
  142. data/lib/hexapdf/type/catalog.rb +1 -1
  143. data/lib/hexapdf/type/cid_font.rb +3 -3
  144. data/lib/hexapdf/type/embedded_file.rb +1 -1
  145. data/lib/hexapdf/type/file_specification.rb +2 -2
  146. data/lib/hexapdf/type/font_descriptor.rb +1 -1
  147. data/lib/hexapdf/type/font_simple.rb +2 -2
  148. data/lib/hexapdf/type/font_type0.rb +3 -3
  149. data/lib/hexapdf/type/font_type3.rb +1 -1
  150. data/lib/hexapdf/type/form.rb +1 -1
  151. data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
  152. data/lib/hexapdf/type/icon_fit.rb +1 -1
  153. data/lib/hexapdf/type/image.rb +1 -1
  154. data/lib/hexapdf/type/info.rb +1 -1
  155. data/lib/hexapdf/type/mark_information.rb +1 -1
  156. data/lib/hexapdf/type/names.rb +2 -2
  157. data/lib/hexapdf/type/object_stream.rb +2 -1
  158. data/lib/hexapdf/type/outline.rb +1 -1
  159. data/lib/hexapdf/type/outline_item.rb +1 -1
  160. data/lib/hexapdf/type/page.rb +19 -10
  161. data/lib/hexapdf/type/page_label.rb +1 -1
  162. data/lib/hexapdf/type/page_tree_node.rb +1 -1
  163. data/lib/hexapdf/type/resources.rb +1 -1
  164. data/lib/hexapdf/type/trailer.rb +2 -2
  165. data/lib/hexapdf/type/viewer_preferences.rb +1 -1
  166. data/lib/hexapdf/type/xref_stream.rb +2 -2
  167. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
  168. data/lib/hexapdf/version.rb +1 -1
  169. data/lib/hexapdf/writer.rb +4 -4
  170. data/lib/hexapdf/xref_section.rb +2 -2
  171. data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +11 -1
  172. data/test/hexapdf/content/graphic_object/test_geom2d.rb +7 -0
  173. data/test/hexapdf/content/test_canvas.rb +0 -1
  174. data/test/hexapdf/digital_signature/test_signatures.rb +22 -0
  175. data/test/hexapdf/document/test_files.rb +2 -2
  176. data/test/hexapdf/document/test_layout.rb +98 -0
  177. data/test/hexapdf/encryption/test_security_handler.rb +12 -11
  178. data/test/hexapdf/encryption/test_standard_security_handler.rb +35 -23
  179. data/test/hexapdf/font/test_true_type_wrapper.rb +18 -1
  180. data/test/hexapdf/font/test_type1_wrapper.rb +15 -1
  181. data/test/hexapdf/layout/test_box.rb +1 -1
  182. data/test/hexapdf/layout/test_column_box.rb +65 -21
  183. data/test/hexapdf/layout/test_frame.rb +14 -14
  184. data/test/hexapdf/layout/test_image_box.rb +4 -0
  185. data/test/hexapdf/layout/test_inline_box.rb +5 -0
  186. data/test/hexapdf/layout/test_list_box.rb +40 -6
  187. data/test/hexapdf/layout/test_page_style.rb +3 -2
  188. data/test/hexapdf/layout/test_style.rb +50 -0
  189. data/test/hexapdf/layout/test_table_box.rb +722 -0
  190. data/test/hexapdf/layout/test_text_box.rb +18 -0
  191. data/test/hexapdf/layout/test_text_layouter.rb +4 -0
  192. data/test/hexapdf/test_dictionary_fields.rb +4 -1
  193. data/test/hexapdf/test_document.rb +1 -0
  194. data/test/hexapdf/test_filter.rb +8 -0
  195. data/test/hexapdf/test_importer.rb +9 -0
  196. data/test/hexapdf/test_object.rb +16 -5
  197. data/test/hexapdf/test_stream.rb +7 -0
  198. data/test/hexapdf/test_writer.rb +3 -3
  199. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +13 -5
  200. data/test/hexapdf/type/acro_form/test_form.rb +4 -3
  201. data/test/hexapdf/type/test_page.rb +18 -4
  202. metadata +17 -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: 689e6d8b70951307055c635c744a85bcade50f7065af32b35bd5fd15230cdf4e
4
+ data.tar.gz: a4186126b30e18ad629db5e176be38f81b7367c72c369d8e715a1e952ad49298
5
5
  SHA512:
6
- metadata.gz: 2fc77d33ddc2c6fb377a778b82f92f01fed93d9a4e494cd57c97dc0a00fce4baa7cab185776f8a3303507d68b544e4404ac2f33b72c3b1a7cc7c65ee838c7dd7
7
- data.tar.gz: 21a08984f424b91594a2d8e6fc705a7f9458a990918ee77adef469e758ae2fee976ba905a7a4a696c5c2728831d02f8845dc9b5316c28de4ff5c7f062521a7e3
6
+ metadata.gz: 05ad5c0f6b7819499ef0f013d28c7ee821f94cdb02f3487d27bd91089c5238c3b5b91d25ed8be0dc9b548a1e3daae17dea96171f38522587afe6b0aed47d8585
7
+ data.tar.gz: 51119d2f079f827271378fc9a36310ff3abcda221113096cae0fe4abee42bf2421b6ac73232fe586d9cfcf0045b5f238bd8ff69491d6f6329decc77bba0285ff
data/CHANGELOG.md CHANGED
@@ -1,3 +1,62 @@
1
+ ## 0.33.0 - 2023-08-02
2
+
3
+ ### Added
4
+
5
+ * [HexaPDF::Layout::TableBox] for rendering tables
6
+ * [HexaPDF::Document::Layout#table_box] for easier table box creation
7
+ * [HexaPDF::Content::GraphicObject::EndpointArc#max_curves] for setting the
8
+ approximation accuracy
9
+ * [HexaPDF::Importer::copy] for completely copying (including referenced
10
+ indirect objects) a single PDF object (which may be from the same document)
11
+ * [HexaPDF::Layout::Style::Border#draw_on_bounds] for drawing the border on the
12
+ bounds instead of inside
13
+ * [HexaPDF::MissingGlyphError] for better error messages when a font is missing
14
+ a glyph
15
+ * [HexaPDF::Font::Type1Wrapper#custom_glyph] and
16
+ [HexaPDF::Font::TrueTypeWrapper#custom_glyph] for custom glyph creation
17
+ * [HexaPDF::FiberDoubleForString] to avoid creating real `Fiber` instances when
18
+ not necessary
19
+ * Support for drawing `Geom2D::Rectangle` instances via the :geom2d graphic
20
+ object
21
+ * Optional argument `apply_first_text_indent` to
22
+ [HexaPDF::Layout::TextLayouter#fit]
23
+
24
+ ### Changed
25
+
26
+ * [HexaPDF::Layout::Frame] to use more efficient `Geom2D::Rectangle` class
27
+ * Internal constant `HexaPDF::Content::ColorSpace::CSS_COLOR_NAMES` changed to
28
+ [HexaPDF::Content::ColorSpace::COLOR_NAMES]
29
+ * Constructor of [HexaPDF::Layout::PageStyle] to allow setting `next_style`
30
+ attribute
31
+ * The encryption dictionary is now validated before using it for decryption
32
+ * Changed encryption permissions to be compatible to PDF 2.0 by always
33
+ activating the "extract content" permission
34
+ * Digital signature creation in case of signature widgets containing images to
35
+ work around bug in Adobe Acrobat
36
+ * [HexaPDF::Type::Page#each_annotation] and
37
+ [HexaPDF::Type::Page#flatten_annotations] to process certain invalid /Annot
38
+ keys without errors
39
+
40
+ ### Fixed
41
+
42
+ **Breaking change**: [HexaPDF::Object::make_direct] now needs the document
43
+ instance as second argument to correctly resolve references
44
+ * [HexaPDF::Layout::ColumnBox], [HexaPDF::Layout::ListBox] and
45
+ [HexaPDF::Layout::ImageBox] to correctly respond to `#empty?`
46
+ * [HexaPDF::Layout::ColumnBox] and [HexaPDF::Layout::ListBox] to take different
47
+ final box positions into account
48
+ * [HexaPDF::Content::Canvas#text] to set the leading only when multiple lines
49
+ are drawn
50
+ * [HexaPDF::Layout::TextBox#split] to use float comparison
51
+ * Validation of standard encryption dictionary to auto-correct invalid /U and
52
+ /O fields in case they are padded with zeros
53
+ * [HexaPDF::Document#wrap] handling of sub-type mapping in case of missing type
54
+ * [HexaPDF::Type::AcroForm::AppearanceGenerator] to also take a text field
55
+ widget's width into account when auto-sizing
56
+ * [HexaPDF::Layout::TextBox] to correctly handle text indentation for split
57
+ boxes
58
+
59
+
1
60
  ## 0.32.2 - 2023-05-06
2
61
 
3
62
  ### Changed
@@ -38,7 +97,7 @@
38
97
  ### Added
39
98
 
40
99
  * [HexaPDF::Document::Layout#method_missing] for more convenient box creation
41
- * [HexaPDF::Document::Composer#method_missing] for more convenient box drawing
100
+ * [HexaPDF::Composer#method_missing] for more convenient box drawing
42
101
  * [HexaPDF::Document::Layout#inline_box] for easy creation of inline boxes
43
102
  * [HexaPDF::Type::OutlineItem#open?] for getting the open state of an outline
44
103
  item
@@ -65,6 +124,8 @@
65
124
 
66
125
  * [HexaPDF::Layout::PageStyle] for collecting all styling information for pages
67
126
  * [HexaPDF::Composer#page_style] for configuring different page styles
127
+ * Configuration option 'filter.flate.on_error' for handling potentially
128
+ recoverable flate errors
68
129
 
69
130
  ### Changed
70
131
 
@@ -84,6 +145,7 @@
84
145
  deleted
85
146
  * `HexaPDF::Type::Page#perform_validation` to set a /MediaBox for invalid pages
86
147
  that don't have one
148
+ * Parsing of invalid flate encoded streams that can potentially be recovered
87
149
 
88
150
 
89
151
  ## 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
@@ -43,6 +43,9 @@ require 'hexapdf/font/true_type'
43
43
  module HexaPDF
44
44
  module CLI
45
45
 
46
+ # Raised when problems occur on the CLI side of things.
47
+ class Error < HexaPDF::Error; end
48
+
46
49
  # Base class for all hexapdf commands. It provides utility methods needed by the individual
47
50
  # commands.
48
51
  class Command < CmdParse::Command
@@ -134,7 +137,7 @@ module HexaPDF
134
137
  doc.trailer.update_id
135
138
  doc.validate(auto_correct: true) do |msg, correctable, object|
136
139
  if command_parser.strict && !correctable
137
- raise "Validation error for object (#{object.oid},#{object.gen}): #{msg}"
140
+ raise Error, "Validation error for object (#{object.oid},#{object.gen}): #{msg}"
138
141
  elsif command_parser.verbosity_info?
139
142
  $stderr.puts "#{correctable ? 'Corrected' : 'Ignored'} validation problem " \
140
143
  "for object (#{object.oid},#{object.gen}): #{msg}"
@@ -151,7 +154,7 @@ module HexaPDF
151
154
  # HexaPDF::CLI#force is not set.
152
155
  def maybe_raise_on_existing_file(filename)
153
156
  if !command_parser.force && File.exist?(filename)
154
- raise "Output file '#{filename}' already exists, not overwriting. Use --force to " \
157
+ raise Error, "Output file '#{filename}' already exists, not overwriting. Use --force to " \
155
158
  "force writing"
156
159
  end
157
160
  end
@@ -97,7 +97,7 @@ module HexaPDF
97
97
  def execute(in_file, out_file = nil) #:nodoc:
98
98
  maybe_raise_on_existing_file(out_file) if out_file
99
99
  if (@fill || @flatten) && !out_file
100
- raise "Output file missing"
100
+ raise Error, "Output file missing"
101
101
  end
102
102
  with_document(in_file, password: @password, out_file: out_file,
103
103
  incremental: @incremental) do |doc|
@@ -106,7 +106,7 @@ module HexaPDF
106
106
  end
107
107
 
108
108
  if !doc.acro_form
109
- raise "This PDF doesn't contain an interactive form"
109
+ raise Error, "This PDF doesn't contain an interactive form"
110
110
  elsif out_file
111
111
  doc.acro_form[:NeedAppearances] = @need_appearances unless @need_appearances.nil?
112
112
  if @fill || !@flatten
@@ -220,7 +220,7 @@ module HexaPDF
220
220
  form = doc.acro_form
221
221
  data.each do |name, value|
222
222
  field = form.field_by_name(name)
223
- raise "Field '#{name}' not found in input PDF" unless field
223
+ raise Error, "Field '#{name}' not found in input PDF" unless field
224
224
  apply_field_value(field, value)
225
225
  end
226
226
  end
@@ -268,10 +268,10 @@ module HexaPDF
268
268
  when :radio_button
269
269
  field.field_value = value.to_sym
270
270
  else
271
- raise "Field type #{field.concrete_field_type} not yet supported"
271
+ raise Error, "Field type #{field.concrete_field_type} not yet supported"
272
272
  end
273
273
  rescue StandardError
274
- raise "Error while setting '#{field.full_field_name}': #{$!.message}"
274
+ raise Error, "Error while setting '#{field.full_field_name}': #{$!.message}"
275
275
  end
276
276
 
277
277
  # Iterates over all non-push button fields in page order. If a field appears on multiple
@@ -266,11 +266,11 @@ module HexaPDF
266
266
  # Resolves the PDF object from the given string reference and returns it.
267
267
  def pdf_object_from_string_reference(str)
268
268
  if str.nil?
269
- raise "Error: Missing argument object identifier OID[,GEN]"
269
+ raise Error, "Error: Missing argument object identifier OID[,GEN]"
270
270
  elsif !str.match?(/^\d+(,\d+)?$/)
271
- raise "Error: Invalid argument: Must be of form OID[,GEN], not '#{str}'"
271
+ raise Error, "Error: Invalid argument: Must be of form OID[,GEN], not '#{str}'"
272
272
  elsif !(obj = @doc.object(pdf_reference_from_string(str)))
273
- raise "Error: No object with the given object identifier '#{str}' found"
273
+ raise Error, "Error: No object with the given object identifier '#{str}' found"
274
274
  else
275
275
  obj
276
276
  end