hexapdf 0.32.2 → 0.33.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +63 -1
- data/README.md +9 -0
- data/examples/002-graphics.rb +15 -17
- data/examples/003-arcs.rb +9 -9
- data/examples/009-text_layouter_alignment.rb +1 -1
- data/examples/010-text_layouter_inline_boxes.rb +2 -2
- data/examples/011-text_layouter_line_wrapping.rb +1 -1
- data/examples/012-text_layouter_styling.rb +7 -7
- data/examples/013-text_layouter_shapes.rb +1 -1
- data/examples/014-text_in_polygon.rb +1 -1
- data/examples/015-boxes.rb +8 -7
- data/examples/016-frame_automatic_box_placement.rb +2 -2
- data/examples/017-frame_text_flow.rb +2 -1
- data/examples/018-composer.rb +1 -1
- data/examples/020-column_box.rb +2 -1
- data/examples/025-table_box.rb +46 -0
- data/lib/hexapdf/cli/command.rb +5 -2
- data/lib/hexapdf/cli/form.rb +5 -5
- data/lib/hexapdf/cli/inspect.rb +3 -3
- data/lib/hexapdf/composer.rb +104 -52
- data/lib/hexapdf/configuration.rb +44 -39
- data/lib/hexapdf/content/canvas.rb +393 -267
- data/lib/hexapdf/content/color_space.rb +72 -25
- data/lib/hexapdf/content/graphic_object/arc.rb +57 -24
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +66 -23
- data/lib/hexapdf/content/graphic_object/geom2d.rb +47 -6
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +58 -36
- data/lib/hexapdf/content/graphic_object.rb +6 -7
- data/lib/hexapdf/content/graphics_state.rb +54 -45
- data/lib/hexapdf/content/operator.rb +52 -54
- data/lib/hexapdf/content/parser.rb +2 -2
- data/lib/hexapdf/content/processor.rb +15 -15
- data/lib/hexapdf/content/transformation_matrix.rb +1 -1
- data/lib/hexapdf/content.rb +5 -0
- data/lib/hexapdf/dictionary.rb +6 -5
- data/lib/hexapdf/dictionary_fields.rb +42 -14
- data/lib/hexapdf/digital_signature/cms_handler.rb +2 -2
- data/lib/hexapdf/digital_signature/handler.rb +1 -1
- data/lib/hexapdf/digital_signature/pkcs1_handler.rb +2 -3
- data/lib/hexapdf/digital_signature/signature.rb +6 -6
- data/lib/hexapdf/digital_signature/signatures.rb +13 -12
- data/lib/hexapdf/digital_signature/signing/default_handler.rb +14 -5
- data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -4
- data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +4 -4
- data/lib/hexapdf/digital_signature/signing.rb +4 -0
- data/lib/hexapdf/digital_signature/verification_result.rb +2 -2
- data/lib/hexapdf/digital_signature.rb +7 -2
- data/lib/hexapdf/document/destinations.rb +12 -11
- data/lib/hexapdf/document/files.rb +1 -1
- data/lib/hexapdf/document/fonts.rb +1 -1
- data/lib/hexapdf/document/layout.rb +167 -39
- data/lib/hexapdf/document/pages.rb +3 -2
- data/lib/hexapdf/document.rb +89 -55
- data/lib/hexapdf/encryption/aes.rb +5 -5
- data/lib/hexapdf/encryption/arc4.rb +1 -1
- data/lib/hexapdf/encryption/fast_aes.rb +2 -2
- data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
- data/lib/hexapdf/encryption/identity.rb +1 -1
- data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
- data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
- data/lib/hexapdf/encryption/security_handler.rb +31 -24
- data/lib/hexapdf/encryption/standard_security_handler.rb +45 -36
- data/lib/hexapdf/encryption.rb +7 -2
- data/lib/hexapdf/error.rb +18 -0
- data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
- data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
- data/lib/hexapdf/filter/flate_decode.rb +1 -1
- data/lib/hexapdf/filter/lzw_decode.rb +1 -1
- data/lib/hexapdf/filter/pass_through.rb +1 -1
- data/lib/hexapdf/filter/predictor.rb +1 -1
- data/lib/hexapdf/filter/run_length_decode.rb +1 -1
- data/lib/hexapdf/filter.rb +55 -6
- data/lib/hexapdf/font/cmap/parser.rb +2 -2
- data/lib/hexapdf/font/cmap.rb +1 -1
- data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
- data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +3 -3
- data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
- data/lib/hexapdf/font/invalid_glyph.rb +3 -0
- data/lib/hexapdf/font/true_type_wrapper.rb +17 -4
- data/lib/hexapdf/font/type1_wrapper.rb +19 -4
- data/lib/hexapdf/font_loader/from_configuration.rb +5 -2
- data/lib/hexapdf/font_loader/from_file.rb +5 -5
- data/lib/hexapdf/font_loader/standard14.rb +3 -3
- data/lib/hexapdf/font_loader.rb +3 -0
- data/lib/hexapdf/image_loader/jpeg.rb +2 -2
- data/lib/hexapdf/image_loader/pdf.rb +1 -1
- data/lib/hexapdf/image_loader/png.rb +2 -2
- data/lib/hexapdf/image_loader.rb +1 -1
- data/lib/hexapdf/importer.rb +13 -0
- data/lib/hexapdf/layout/box.rb +9 -2
- data/lib/hexapdf/layout/box_fitter.rb +2 -2
- data/lib/hexapdf/layout/column_box.rb +18 -4
- data/lib/hexapdf/layout/frame.rb +30 -12
- data/lib/hexapdf/layout/image_box.rb +5 -0
- data/lib/hexapdf/layout/inline_box.rb +1 -0
- data/lib/hexapdf/layout/list_box.rb +17 -1
- data/lib/hexapdf/layout/page_style.rb +4 -4
- data/lib/hexapdf/layout/style.rb +18 -3
- data/lib/hexapdf/layout/table_box.rb +682 -0
- data/lib/hexapdf/layout/text_box.rb +5 -3
- data/lib/hexapdf/layout/text_fragment.rb +1 -1
- data/lib/hexapdf/layout/text_layouter.rb +12 -4
- data/lib/hexapdf/layout.rb +1 -0
- data/lib/hexapdf/name_tree_node.rb +1 -1
- data/lib/hexapdf/number_tree_node.rb +1 -1
- data/lib/hexapdf/object.rb +18 -7
- data/lib/hexapdf/parser.rb +7 -7
- data/lib/hexapdf/pdf_array.rb +1 -1
- data/lib/hexapdf/rectangle.rb +1 -1
- data/lib/hexapdf/reference.rb +1 -1
- data/lib/hexapdf/revision.rb +1 -1
- data/lib/hexapdf/revisions.rb +3 -3
- data/lib/hexapdf/serializer.rb +15 -15
- data/lib/hexapdf/stream.rb +4 -2
- data/lib/hexapdf/tokenizer.rb +14 -14
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +22 -22
- data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/field.rb +2 -2
- data/lib/hexapdf/type/acro_form/form.rb +1 -1
- data/lib/hexapdf/type/acro_form/signature_field.rb +4 -4
- data/lib/hexapdf/type/acro_form/text_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/variable_text_field.rb +1 -1
- data/lib/hexapdf/type/acro_form.rb +1 -1
- data/lib/hexapdf/type/action.rb +1 -1
- data/lib/hexapdf/type/actions/go_to.rb +1 -1
- data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
- data/lib/hexapdf/type/actions/launch.rb +1 -1
- data/lib/hexapdf/type/actions/uri.rb +1 -1
- data/lib/hexapdf/type/actions.rb +1 -1
- data/lib/hexapdf/type/annotation.rb +3 -3
- data/lib/hexapdf/type/annotations/link.rb +1 -1
- data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
- data/lib/hexapdf/type/annotations/text.rb +1 -1
- data/lib/hexapdf/type/annotations/widget.rb +2 -2
- data/lib/hexapdf/type/annotations.rb +1 -1
- data/lib/hexapdf/type/catalog.rb +1 -1
- data/lib/hexapdf/type/cid_font.rb +3 -3
- data/lib/hexapdf/type/embedded_file.rb +1 -1
- data/lib/hexapdf/type/file_specification.rb +2 -2
- data/lib/hexapdf/type/font_descriptor.rb +1 -1
- data/lib/hexapdf/type/font_simple.rb +2 -2
- data/lib/hexapdf/type/font_type0.rb +3 -3
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +1 -1
- data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
- data/lib/hexapdf/type/icon_fit.rb +1 -1
- data/lib/hexapdf/type/image.rb +1 -1
- data/lib/hexapdf/type/info.rb +1 -1
- data/lib/hexapdf/type/mark_information.rb +1 -1
- data/lib/hexapdf/type/names.rb +2 -2
- data/lib/hexapdf/type/object_stream.rb +2 -1
- data/lib/hexapdf/type/outline.rb +1 -1
- data/lib/hexapdf/type/outline_item.rb +1 -1
- data/lib/hexapdf/type/page.rb +19 -10
- data/lib/hexapdf/type/page_label.rb +1 -1
- data/lib/hexapdf/type/page_tree_node.rb +1 -1
- data/lib/hexapdf/type/resources.rb +1 -1
- data/lib/hexapdf/type/trailer.rb +2 -2
- data/lib/hexapdf/type/viewer_preferences.rb +1 -1
- data/lib/hexapdf/type/xref_stream.rb +2 -2
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
- data/lib/hexapdf/version.rb +1 -1
- data/lib/hexapdf/writer.rb +4 -4
- data/lib/hexapdf/xref_section.rb +2 -2
- data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +11 -1
- data/test/hexapdf/content/graphic_object/test_geom2d.rb +7 -0
- data/test/hexapdf/content/test_canvas.rb +0 -1
- data/test/hexapdf/digital_signature/test_signatures.rb +22 -0
- data/test/hexapdf/document/test_files.rb +2 -2
- data/test/hexapdf/document/test_layout.rb +98 -0
- data/test/hexapdf/encryption/test_security_handler.rb +12 -11
- data/test/hexapdf/encryption/test_standard_security_handler.rb +35 -23
- data/test/hexapdf/font/test_true_type_wrapper.rb +18 -1
- data/test/hexapdf/font/test_type1_wrapper.rb +15 -1
- data/test/hexapdf/layout/test_box.rb +1 -1
- data/test/hexapdf/layout/test_column_box.rb +65 -21
- data/test/hexapdf/layout/test_frame.rb +14 -14
- data/test/hexapdf/layout/test_image_box.rb +4 -0
- data/test/hexapdf/layout/test_inline_box.rb +5 -0
- data/test/hexapdf/layout/test_list_box.rb +40 -6
- data/test/hexapdf/layout/test_page_style.rb +3 -2
- data/test/hexapdf/layout/test_style.rb +50 -0
- data/test/hexapdf/layout/test_table_box.rb +722 -0
- data/test/hexapdf/layout/test_text_box.rb +18 -0
- data/test/hexapdf/layout/test_text_layouter.rb +4 -0
- data/test/hexapdf/test_dictionary_fields.rb +4 -1
- data/test/hexapdf/test_document.rb +1 -0
- data/test/hexapdf/test_filter.rb +8 -0
- data/test/hexapdf/test_importer.rb +9 -0
- data/test/hexapdf/test_object.rb +16 -5
- data/test/hexapdf/test_stream.rb +7 -0
- data/test/hexapdf/test_writer.rb +3 -3
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +13 -5
- data/test/hexapdf/type/acro_form/test_form.rb +4 -3
- data/test/hexapdf/type/test_page.rb +18 -4
- metadata +17 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 689e6d8b70951307055c635c744a85bcade50f7065af32b35bd5fd15230cdf4e
|
4
|
+
data.tar.gz: a4186126b30e18ad629db5e176be38f81b7367c72c369d8e715a1e952ad49298
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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::
|
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
|
data/examples/002-graphics.rb
CHANGED
@@ -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 =
|
33
|
-
transformed_color =
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
241
|
-
canvas.fill_color(
|
242
|
-
canvas.fill_color(
|
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(
|
246
|
-
canvas.fill_color(
|
247
|
-
canvas.fill_color(
|
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(
|
22
|
+
canvas.fill_color("hp-orange-light")
|
23
23
|
canvas.draw(pie, start_angle: 30, end_angle: 110).fill
|
24
|
-
canvas.fill_color(
|
24
|
+
canvas.fill_color("hp-teal-light")
|
25
25
|
canvas.draw(pie, start_angle: 110, end_angle: 130).fill
|
26
|
-
canvas.fill_color(
|
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(
|
31
|
+
canvas.stroke_color("hp-orange")
|
32
32
|
canvas.draw(arc, start_angle: 30, end_angle: 110).stroke
|
33
|
-
canvas.stroke_color(
|
33
|
+
canvas.stroke_color("hp-teal")
|
34
34
|
canvas.draw(arc, start_angle: 110, end_angle: 130).stroke
|
35
|
-
canvas.stroke_color(
|
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(
|
43
|
+
canvas.fill_color("hp-orange-light")
|
44
44
|
canvas.draw(pie, start_angle: 30, end_angle: 110).fill_stroke
|
45
|
-
canvas.fill_color(
|
45
|
+
canvas.fill_color("hp-teal-light")
|
46
46
|
canvas.draw(pie, start_angle: 110, end_angle: 130).fill_stroke
|
47
|
-
canvas.fill_color(
|
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(
|
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:
|
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:
|
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(
|
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:
|
47
|
+
font_size: 12, fill_color: "hp-blue-light"},
|
48
48
|
{font: doc.fonts.add("Courier"), font_size: 14,
|
49
|
-
fill_color:
|
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:
|
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(
|
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(
|
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:
|
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:
|
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(
|
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(
|
56
|
+
stroke_color("hp-blue-dark").
|
57
57
|
line_width(0.5).
|
58
58
|
draw(:geom2d, object: polygon)
|
59
59
|
|
data/examples/015-boxes.rb
CHANGED
@@ -37,13 +37,14 @@ end
|
|
37
37
|
|
38
38
|
canvas = doc.pages.add.canvas
|
39
39
|
|
40
|
-
[[1,
|
41
|
-
|
42
|
-
|
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:
|
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: [
|
58
|
+
color: ["hp-blue", "hp-orange", "hp-teal", "hp-blue-light"],
|
58
59
|
style: [:solid, :dashed, :dashed_round, :dotted]},
|
59
|
-
background_color:
|
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(
|
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:
|
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(
|
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
|
-
|
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
|
data/examples/018-composer.rb
CHANGED
@@ -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:
|
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)
|
data/examples/020-column_box.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/hexapdf/cli/command.rb
CHANGED
@@ -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
|
data/lib/hexapdf/cli/form.rb
CHANGED
@@ -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
|
data/lib/hexapdf/cli/inspect.rb
CHANGED
@@ -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
|