hexapdf 0.11.9 → 0.13.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 +157 -0
- data/LICENSE +1 -1
- data/examples/001-hello_world.rb +1 -1
- data/examples/002-graphics.rb +1 -1
- data/examples/003-arcs.rb +1 -1
- data/examples/004-optimizing.rb +1 -1
- data/examples/005-merging.rb +1 -1
- data/examples/006-standard_pdf_fonts.rb +1 -1
- data/examples/007-truetype.rb +1 -1
- data/examples/008-show_char_bboxes.rb +1 -1
- data/examples/009-text_layouter_alignment.rb +1 -1
- data/examples/010-text_layouter_inline_boxes.rb +1 -1
- data/examples/011-text_layouter_line_wrapping.rb +1 -1
- data/examples/012-text_layouter_styling.rb +1 -1
- data/examples/013-text_layouter_shapes.rb +1 -1
- data/examples/014-text_in_polygon.rb +1 -1
- data/examples/015-boxes.rb +1 -1
- data/examples/016-frame_automatic_box_placement.rb +1 -1
- data/examples/017-frame_text_flow.rb +1 -1
- data/examples/018-composer.rb +1 -1
- data/examples/019-acro_form.rb +51 -0
- data/lib/hexapdf.rb +1 -1
- data/lib/hexapdf/cli.rb +3 -1
- data/lib/hexapdf/cli/batch.rb +1 -1
- data/lib/hexapdf/cli/command.rb +22 -11
- data/lib/hexapdf/cli/files.rb +1 -1
- data/lib/hexapdf/cli/form.rb +240 -0
- data/lib/hexapdf/cli/image2pdf.rb +3 -2
- data/lib/hexapdf/cli/images.rb +1 -1
- data/lib/hexapdf/cli/info.rb +52 -3
- data/lib/hexapdf/cli/inspect.rb +31 -9
- data/lib/hexapdf/cli/merge.rb +2 -2
- data/lib/hexapdf/cli/modify.rb +1 -1
- data/lib/hexapdf/cli/optimize.rb +1 -1
- data/lib/hexapdf/cli/split.rb +1 -1
- data/lib/hexapdf/cli/watermark.rb +1 -1
- data/lib/hexapdf/composer.rb +2 -2
- data/lib/hexapdf/configuration.rb +81 -11
- data/lib/hexapdf/content.rb +3 -1
- data/lib/hexapdf/content/canvas.rb +5 -18
- data/lib/hexapdf/content/color_space.rb +111 -32
- data/lib/hexapdf/content/graphic_object.rb +1 -1
- data/lib/hexapdf/content/graphic_object/arc.rb +4 -4
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
- data/lib/hexapdf/content/graphics_state.rb +1 -1
- data/lib/hexapdf/content/operator.rb +9 -9
- data/lib/hexapdf/content/parser.rb +18 -5
- data/lib/hexapdf/content/processor.rb +1 -1
- data/lib/hexapdf/content/transformation_matrix.rb +1 -1
- data/lib/hexapdf/data_dir.rb +1 -1
- data/lib/hexapdf/dictionary.rb +5 -5
- data/lib/hexapdf/dictionary_fields.rb +2 -10
- data/lib/hexapdf/document.rb +45 -17
- data/lib/hexapdf/document/files.rb +1 -2
- data/lib/hexapdf/document/fonts.rb +1 -1
- data/lib/hexapdf/document/images.rb +1 -1
- data/lib/hexapdf/document/pages.rb +3 -14
- data/lib/hexapdf/encryption.rb +1 -1
- data/lib/hexapdf/encryption/aes.rb +1 -1
- data/lib/hexapdf/encryption/arc4.rb +1 -1
- data/lib/hexapdf/encryption/fast_aes.rb +1 -1
- data/lib/hexapdf/encryption/fast_arc4.rb +2 -2
- 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 +2 -1
- data/lib/hexapdf/encryption/standard_security_handler.rb +2 -1
- data/lib/hexapdf/error.rb +1 -1
- data/lib/hexapdf/filter.rb +3 -3
- data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
- data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
- data/lib/hexapdf/filter/encryption.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/{jpx_decode.rb → pass_through.rb} +5 -5
- data/lib/hexapdf/filter/predictor.rb +1 -1
- data/lib/hexapdf/filter/run_length_decode.rb +1 -1
- data/lib/hexapdf/font/cmap.rb +2 -5
- data/lib/hexapdf/font/cmap/parser.rb +1 -1
- data/lib/hexapdf/font/cmap/writer.rb +1 -1
- data/lib/hexapdf/font/encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/base.rb +9 -1
- data/lib/hexapdf/font/encoding/difference_encoding.rb +7 -1
- data/lib/hexapdf/font/encoding/glyph_list.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +1 -1
- 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 +1 -1
- data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
- data/lib/hexapdf/font/invalid_glyph.rb +1 -1
- data/lib/hexapdf/font/true_type.rb +1 -1
- data/lib/hexapdf/font/true_type/builder.rb +1 -1
- data/lib/hexapdf/font/true_type/font.rb +1 -1
- data/lib/hexapdf/font/true_type/optimizer.rb +1 -1
- data/lib/hexapdf/font/true_type/subsetter.rb +1 -1
- data/lib/hexapdf/font/true_type/table.rb +1 -1
- data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
- data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +1 -1
- data/lib/hexapdf/font/true_type/table/directory.rb +1 -1
- data/lib/hexapdf/font/true_type/table/glyf.rb +1 -1
- data/lib/hexapdf/font/true_type/table/head.rb +2 -1
- data/lib/hexapdf/font/true_type/table/hhea.rb +1 -1
- data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -1
- data/lib/hexapdf/font/true_type/table/kern.rb +1 -1
- data/lib/hexapdf/font/true_type/table/loca.rb +1 -1
- data/lib/hexapdf/font/true_type/table/maxp.rb +1 -1
- data/lib/hexapdf/font/true_type/table/name.rb +1 -1
- data/lib/hexapdf/font/true_type/table/os2.rb +3 -1
- data/lib/hexapdf/font/true_type/table/post.rb +1 -1
- data/lib/hexapdf/font/true_type_wrapper.rb +54 -51
- data/lib/hexapdf/font/type1.rb +1 -1
- data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
- data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
- data/lib/hexapdf/font/type1/font.rb +1 -1
- data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
- data/lib/hexapdf/font/type1/pfb_parser.rb +1 -1
- data/lib/hexapdf/font/type1_wrapper.rb +68 -52
- data/lib/hexapdf/font_loader.rb +1 -1
- data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
- data/lib/hexapdf/font_loader/from_file.rb +1 -1
- data/lib/hexapdf/font_loader/standard14.rb +1 -1
- data/lib/hexapdf/image_loader.rb +1 -1
- data/lib/hexapdf/image_loader/jpeg.rb +1 -1
- data/lib/hexapdf/image_loader/pdf.rb +1 -1
- data/lib/hexapdf/image_loader/png.rb +4 -3
- data/lib/hexapdf/importer.rb +2 -4
- data/lib/hexapdf/layout.rb +1 -1
- data/lib/hexapdf/layout/box.rb +1 -1
- data/lib/hexapdf/layout/frame.rb +1 -1
- data/lib/hexapdf/layout/image_box.rb +1 -1
- data/lib/hexapdf/layout/inline_box.rb +1 -1
- data/lib/hexapdf/layout/line.rb +2 -2
- data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
- data/lib/hexapdf/layout/style.rb +24 -24
- data/lib/hexapdf/layout/text_box.rb +1 -1
- data/lib/hexapdf/layout/text_fragment.rb +1 -1
- data/lib/hexapdf/layout/text_layouter.rb +1 -1
- data/lib/hexapdf/layout/text_shaper.rb +4 -3
- data/lib/hexapdf/layout/width_from_polygon.rb +1 -1
- data/lib/hexapdf/name_tree_node.rb +1 -1
- data/lib/hexapdf/number_tree_node.rb +1 -1
- data/lib/hexapdf/object.rb +32 -27
- data/lib/hexapdf/parser.rb +69 -6
- data/lib/hexapdf/pdf_array.rb +10 -3
- data/lib/hexapdf/rectangle.rb +31 -1
- data/lib/hexapdf/reference.rb +1 -1
- data/lib/hexapdf/revision.rb +2 -1
- data/lib/hexapdf/revisions.rb +30 -22
- data/lib/hexapdf/serializer.rb +2 -2
- data/lib/hexapdf/stream.rb +1 -1
- data/lib/hexapdf/task.rb +1 -1
- data/lib/hexapdf/task/dereference.rb +1 -1
- data/lib/hexapdf/task/optimize.rb +7 -5
- data/lib/hexapdf/tokenizer.rb +5 -4
- data/lib/hexapdf/type.rb +1 -1
- data/lib/hexapdf/type/acro_form.rb +7 -1
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +405 -0
- data/lib/hexapdf/type/acro_form/button_field.rb +305 -0
- data/lib/hexapdf/type/acro_form/choice_field.rb +220 -0
- data/lib/hexapdf/type/acro_form/field.rb +250 -17
- data/lib/hexapdf/type/acro_form/form.rb +159 -7
- data/lib/hexapdf/type/acro_form/text_field.rb +187 -0
- data/lib/hexapdf/type/acro_form/variable_text_field.rb +122 -0
- data/lib/hexapdf/type/action.rb +1 -1
- data/lib/hexapdf/type/actions.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 +4 -3
- data/lib/hexapdf/type/annotation.rb +73 -3
- data/lib/hexapdf/type/annotations.rb +1 -1
- data/lib/hexapdf/type/annotations/link.rb +2 -2
- 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 +238 -2
- data/lib/hexapdf/type/catalog.rb +23 -3
- data/lib/hexapdf/type/cid_font.rb +1 -1
- data/lib/hexapdf/type/embedded_file.rb +1 -1
- data/lib/hexapdf/type/file_specification.rb +2 -2
- data/lib/hexapdf/type/font.rb +18 -1
- data/lib/hexapdf/type/font_descriptor.rb +2 -2
- data/lib/hexapdf/type/font_simple.rb +4 -2
- data/lib/hexapdf/type/font_true_type.rb +7 -3
- data/lib/hexapdf/type/font_type0.rb +2 -2
- data/lib/hexapdf/type/font_type1.rb +16 -1
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +12 -2
- 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 +5 -3
- data/lib/hexapdf/type/info.rb +1 -1
- data/lib/hexapdf/type/names.rb +1 -1
- data/lib/hexapdf/type/object_stream.rb +1 -1
- data/lib/hexapdf/type/page.rb +36 -12
- data/lib/hexapdf/type/page_tree_node.rb +37 -16
- data/lib/hexapdf/type/resources.rb +17 -3
- data/lib/hexapdf/type/trailer.rb +4 -6
- data/lib/hexapdf/type/viewer_preferences.rb +1 -1
- data/lib/hexapdf/type/xref_stream.rb +1 -1
- data/lib/hexapdf/utils/bit_field.rb +38 -24
- data/lib/hexapdf/utils/bit_stream.rb +1 -1
- data/lib/hexapdf/utils/graphics_helpers.rb +1 -1
- data/lib/hexapdf/utils/lru_cache.rb +1 -1
- data/lib/hexapdf/utils/math_helpers.rb +1 -1
- data/lib/hexapdf/utils/object_hash.rb +1 -1
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
- data/lib/hexapdf/utils/sorted_tree_node.rb +19 -16
- data/lib/hexapdf/version.rb +2 -2
- data/lib/hexapdf/writer.rb +1 -1
- data/lib/hexapdf/xref_section.rb +1 -1
- data/test/hexapdf/common_tokenizer_tests.rb +6 -1
- data/test/hexapdf/content/common.rb +2 -2
- data/test/hexapdf/content/graphic_object/test_arc.rb +4 -4
- data/test/hexapdf/content/test_canvas.rb +3 -3
- data/test/hexapdf/content/test_color_space.rb +71 -8
- data/test/hexapdf/content/test_operator.rb +22 -22
- data/test/hexapdf/content/test_parser.rb +14 -0
- data/test/hexapdf/document/test_fonts.rb +1 -1
- data/test/hexapdf/document/test_pages.rb +6 -6
- data/test/hexapdf/encryption/test_aes.rb +4 -4
- data/test/hexapdf/encryption/test_standard_security_handler.rb +11 -11
- data/test/hexapdf/filter/test_ascii85_decode.rb +1 -1
- data/test/hexapdf/filter/test_ascii_hex_decode.rb +1 -1
- data/test/hexapdf/font/encoding/test_base.rb +10 -0
- data/test/hexapdf/font/encoding/test_difference_encoding.rb +8 -0
- data/test/hexapdf/font/test_true_type_wrapper.rb +10 -7
- data/test/hexapdf/font/test_type1_wrapper.rb +33 -8
- data/test/hexapdf/layout/test_style.rb +1 -1
- data/test/hexapdf/layout/test_text_layouter.rb +3 -4
- data/test/hexapdf/test_configuration.rb +2 -2
- data/test/hexapdf/test_dictionary.rb +3 -1
- data/test/hexapdf/test_dictionary_fields.rb +2 -2
- data/test/hexapdf/test_document.rb +16 -4
- data/test/hexapdf/test_object.rb +44 -26
- data/test/hexapdf/test_parser.rb +125 -55
- data/test/hexapdf/test_pdf_array.rb +7 -0
- data/test/hexapdf/test_rectangle.rb +14 -0
- data/test/hexapdf/test_revision.rb +3 -0
- data/test/hexapdf/test_revisions.rb +35 -0
- data/test/hexapdf/test_writer.rb +2 -2
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +521 -0
- data/test/hexapdf/type/acro_form/test_button_field.rb +281 -0
- data/test/hexapdf/type/acro_form/test_choice_field.rb +137 -0
- data/test/hexapdf/type/acro_form/test_field.rb +163 -6
- data/test/hexapdf/type/acro_form/test_form.rb +189 -22
- data/test/hexapdf/type/acro_form/test_text_field.rb +121 -0
- data/test/hexapdf/type/acro_form/test_variable_text_field.rb +77 -0
- data/test/hexapdf/type/annotations/test_text.rb +1 -1
- data/test/hexapdf/type/annotations/test_widget.rb +199 -0
- data/test/hexapdf/type/test_annotation.rb +45 -0
- data/test/hexapdf/type/test_catalog.rb +18 -0
- data/test/hexapdf/type/test_font.rb +5 -0
- data/test/hexapdf/type/test_font_simple.rb +2 -1
- data/test/hexapdf/type/test_font_true_type.rb +6 -0
- data/test/hexapdf/type/test_font_type1.rb +8 -0
- data/test/hexapdf/type/test_form.rb +19 -1
- data/test/hexapdf/type/test_image.rb +7 -0
- data/test/hexapdf/type/test_page.rb +45 -7
- data/test/hexapdf/type/test_page_tree_node.rb +62 -12
- data/test/hexapdf/type/test_resources.rb +20 -0
- data/test/hexapdf/type/test_trailer.rb +4 -0
- data/test/hexapdf/utils/test_bit_field.rb +15 -1
- data/test/hexapdf/utils/test_sorted_tree_node.rb +10 -9
- data/test/test_helper.rb +1 -1
- metadata +34 -21
- data/lib/hexapdf/filter/dct_decode.rb +0 -60
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -48,8 +48,12 @@ module HexaPDF
|
|
48
48
|
private
|
49
49
|
|
50
50
|
def perform_validation
|
51
|
-
|
52
|
-
|
51
|
+
std_font = FontType1::StandardFonts.standard_font?(self[:BaseFont])
|
52
|
+
super(ignore_missing_font_fields: std_font)
|
53
|
+
|
54
|
+
if self[:FontDescriptor].nil? && !std_font
|
55
|
+
yield("Required field FontDescriptor is not set", false)
|
56
|
+
end
|
53
57
|
end
|
54
58
|
|
55
59
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -59,7 +59,7 @@ module HexaPDF
|
|
59
59
|
# Returns the CID font of this type 0 font.
|
60
60
|
def descendant_font
|
61
61
|
document.cache(@data, :descendant_font) do
|
62
|
-
document.wrap(
|
62
|
+
document.wrap(self[:DescendantFonts][0])
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -37,6 +37,7 @@
|
|
37
37
|
require 'hexapdf/data_dir'
|
38
38
|
require 'hexapdf/type/font_simple'
|
39
39
|
require 'hexapdf/font/type1'
|
40
|
+
require 'hexapdf/font/type1_wrapper'
|
40
41
|
|
41
42
|
module HexaPDF
|
42
43
|
module Type
|
@@ -105,6 +106,20 @@ module HexaPDF
|
|
105
106
|
define_field :Subtype, type: Symbol, required: true, default: :Type1
|
106
107
|
define_field :BaseFont, type: Symbol, required: true
|
107
108
|
|
109
|
+
# Overrides the default to provide a font wrapper in case none is set and the font is one of
|
110
|
+
# the standard fonts.
|
111
|
+
#
|
112
|
+
# See: Font#font_wrapper
|
113
|
+
def font_wrapper
|
114
|
+
if (tmp = super)
|
115
|
+
tmp
|
116
|
+
elsif StandardFonts.standard_font?(self[:BaseFont])
|
117
|
+
self.font_wrapper = HexaPDF::Font::Type1Wrapper.new(document,
|
118
|
+
StandardFonts.font(self[:BaseFont]),
|
119
|
+
pdf_object: self)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
108
123
|
# Returns the unscaled width of the given code point in glyph units, or 0 if the width for the
|
109
124
|
# code point is missing.
|
110
125
|
def width(code)
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
data/lib/hexapdf/type/form.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -101,7 +101,8 @@ module HexaPDF
|
|
101
101
|
|
102
102
|
# Returns the resource dictionary which is automatically created if it doesn't exist.
|
103
103
|
def resources
|
104
|
-
self[:Resources] ||= document.wrap({
|
104
|
+
self[:Resources] ||= document.wrap({ProcSet: [:PDF, :Text, :ImageB, :ImageC, :ImageI]},
|
105
|
+
type: :XXResources)
|
105
106
|
end
|
106
107
|
|
107
108
|
# Processes the content stream of the form XObject with the given processor object.
|
@@ -126,13 +127,22 @@ module HexaPDF
|
|
126
127
|
# The canvas object is cached once it is created so that its graphics state is correctly
|
127
128
|
# retained without the need for parsing its contents.
|
128
129
|
#
|
130
|
+
# If the bounding box of the form XObject doesn't have its origin at (0, 0), the canvas origin
|
131
|
+
# is translated into the bottom left corner so that this detail doesn't matter when using the
|
132
|
+
# canvas. This means that the canvas' origin is always at the bottom left corner of the
|
133
|
+
# bounding box.
|
134
|
+
#
|
129
135
|
# *Note* that a canvas can only be retrieved for initially empty form XObjects!
|
130
136
|
def canvas
|
131
137
|
document.cache(@data, :canvas) do
|
132
138
|
unless stream.empty?
|
133
139
|
raise HexaPDF::Error, "Cannot create a canvas for a form XObjects with contents"
|
134
140
|
end
|
141
|
+
|
135
142
|
canvas = Content::Canvas.new(self)
|
143
|
+
if box.left != 0 || box.bottom != 0
|
144
|
+
canvas.save_graphics_state.translate(box.left, box.bottom)
|
145
|
+
end
|
136
146
|
self.stream = canvas.stream_data
|
137
147
|
set_filter(:FlateDecode)
|
138
148
|
canvas
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
data/lib/hexapdf/type/image.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -150,7 +150,7 @@ module HexaPDF
|
|
150
150
|
color_space, = *self[:ColorSpace]
|
151
151
|
if color_space == :Indexed
|
152
152
|
result.indexed = true
|
153
|
-
color_space, = *
|
153
|
+
color_space, = *self[:ColorSpace][1]
|
154
154
|
end
|
155
155
|
case color_space
|
156
156
|
when :DeviceRGB, :CalRGB
|
@@ -169,6 +169,8 @@ module HexaPDF
|
|
169
169
|
result.writable = false if result.type == :png
|
170
170
|
end
|
171
171
|
|
172
|
+
result.writable = false if self[:SMask]
|
173
|
+
|
172
174
|
result
|
173
175
|
end
|
174
176
|
|
@@ -238,7 +240,7 @@ module HexaPDF
|
|
238
240
|
end
|
239
241
|
|
240
242
|
if color_type == ImageLoader::PNG::INDEXED
|
241
|
-
palette_data =
|
243
|
+
palette_data = self[:ColorSpace][3]
|
242
244
|
palette_data = palette_data.stream unless palette_data.kind_of?(String)
|
243
245
|
palette = ''.b
|
244
246
|
if info.color_space == :rgb
|
data/lib/hexapdf/type/info.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
data/lib/hexapdf/type/names.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
data/lib/hexapdf/type/page.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -304,7 +304,7 @@ module HexaPDF
|
|
304
304
|
def contents
|
305
305
|
Array(self[:Contents]).each_with_object("".b) do |content_stream, content|
|
306
306
|
content << " " unless content.empty?
|
307
|
-
content <<
|
307
|
+
content << content_stream.stream
|
308
308
|
end
|
309
309
|
end
|
310
310
|
|
@@ -323,10 +323,11 @@ module HexaPDF
|
|
323
323
|
end
|
324
324
|
end
|
325
325
|
|
326
|
-
# Returns the possibly inherited resource dictionary which is automatically created if it
|
326
|
+
# Returns the, possibly inherited, resource dictionary which is automatically created if it
|
327
327
|
# doesn't exist.
|
328
328
|
def resources
|
329
|
-
self[:Resources] ||= document.wrap({
|
329
|
+
self[:Resources] ||= document.wrap({ProcSet: [:PDF, :Text, :ImageB, :ImageC, :ImageI]},
|
330
|
+
type: :XXResources)
|
330
331
|
end
|
331
332
|
|
332
333
|
# Processes the content streams associated with the page with the given processor object.
|
@@ -344,8 +345,7 @@ module HexaPDF
|
|
344
345
|
node = self
|
345
346
|
while (parent_node = node[:Parent])
|
346
347
|
parent_node[:Kids].each do |kid|
|
347
|
-
kid
|
348
|
-
break if kid.data == node.data
|
348
|
+
break if kid == node
|
349
349
|
idx += (kid.type == :Page ? 1 : kid[:Count])
|
350
350
|
end
|
351
351
|
node = parent_node
|
@@ -353,11 +353,26 @@ module HexaPDF
|
|
353
353
|
idx
|
354
354
|
end
|
355
355
|
|
356
|
+
# Returns all parent nodes of the page up to the root of the page tree.
|
357
|
+
#
|
358
|
+
# The direct parent is the first node in the array and the root node the last.
|
359
|
+
def ancestor_nodes
|
360
|
+
parent = self[:Parent]
|
361
|
+
result = [parent]
|
362
|
+
result << parent while (parent = parent[:Parent])
|
363
|
+
result
|
364
|
+
end
|
365
|
+
|
356
366
|
# Returns the requested type of canvas for the page.
|
357
367
|
#
|
358
368
|
# The canvas object is cached once it is created so that its graphics state is correctly
|
359
369
|
# retained without the need for parsing its contents.
|
360
370
|
#
|
371
|
+
# If the media box of the page doesn't have its origin at (0, 0), the canvas origin is
|
372
|
+
# translated into the bottom left corner so that this detail doesn't matter when using the
|
373
|
+
# canvas. This means that the canvas' origin is always at the bottom left corner of the media
|
374
|
+
# box.
|
375
|
+
#
|
361
376
|
# type::
|
362
377
|
# Can either be
|
363
378
|
# * :page for getting the canvas for the page itself (only valid for initially empty pages)
|
@@ -374,16 +389,25 @@ module HexaPDF
|
|
374
389
|
raise HexaPDF::Error, "Cannot get the canvas for a page with contents"
|
375
390
|
end
|
376
391
|
|
392
|
+
create_canvas = lambda do
|
393
|
+
Content::Canvas.new(self).tap do |canvas|
|
394
|
+
media_box = box(:media)
|
395
|
+
if media_box.left != 0 || media_box.bottom != 0
|
396
|
+
canvas.translate(media_box.left, media_box.bottom)
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
377
401
|
contents = self[:Contents]
|
378
402
|
if contents.nil?
|
379
|
-
page_canvas = document.cache(@data, :page_canvas,
|
403
|
+
page_canvas = document.cache(@data, :page_canvas, create_canvas.call)
|
380
404
|
self[:Contents] = document.add({Filter: :FlateDecode},
|
381
405
|
stream: page_canvas.stream_data)
|
382
406
|
end
|
383
407
|
|
384
408
|
if type == :overlay || type == :underlay
|
385
|
-
underlay_canvas = document.cache(@data, :underlay_canvas,
|
386
|
-
overlay_canvas = document.cache(@data, :overlay_canvas,
|
409
|
+
underlay_canvas = document.cache(@data, :underlay_canvas, create_canvas.call)
|
410
|
+
overlay_canvas = document.cache(@data, :overlay_canvas, create_canvas.call)
|
387
411
|
|
388
412
|
stream = HexaPDF::StreamData.new do
|
389
413
|
Fiber.yield(" q ")
|
@@ -396,11 +420,12 @@ module HexaPDF
|
|
396
420
|
underlay = document.add({Filter: :FlateDecode}, stream: stream)
|
397
421
|
|
398
422
|
stream = HexaPDF::StreamData.new do
|
399
|
-
Fiber.yield(" Q ")
|
423
|
+
Fiber.yield(" Q q ")
|
400
424
|
fiber = overlay_canvas.stream_data.fiber
|
401
425
|
while fiber.alive? && (data = fiber.resume)
|
402
426
|
Fiber.yield(data)
|
403
427
|
end
|
428
|
+
" Q "
|
404
429
|
end
|
405
430
|
overlay = document.add({Filter: :FlateDecode}, stream: stream)
|
406
431
|
|
@@ -448,8 +473,7 @@ module HexaPDF
|
|
448
473
|
REQUIRED_INHERITABLE_FIELDS.each do |name|
|
449
474
|
next if self[name]
|
450
475
|
yield("Inheritable page field #{name} not set", name == :Resources)
|
451
|
-
|
452
|
-
self[:Resources].validate(&block)
|
476
|
+
resources.validate(&block) if name == :Ressources
|
453
477
|
end
|
454
478
|
end
|
455
479
|
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -35,6 +35,7 @@
|
|
35
35
|
#++
|
36
36
|
|
37
37
|
require 'hexapdf/dictionary'
|
38
|
+
require 'hexapdf/error'
|
38
39
|
|
39
40
|
module HexaPDF
|
40
41
|
module Type
|
@@ -159,38 +160,58 @@ module HexaPDF
|
|
159
160
|
end
|
160
161
|
|
161
162
|
# :call-seq:
|
162
|
-
# pages.delete_page(page)
|
163
|
-
# pages.delete_page(index)
|
163
|
+
# pages.delete_page(page)
|
164
|
+
# pages.delete_page(index)
|
164
165
|
#
|
165
166
|
# Deletes the given page or the page at the position specified by the zero-based index from
|
166
|
-
# the page tree and
|
167
|
-
# returned.
|
168
|
-
#
|
169
|
-
# Note that the page is *not* deleted from the document itself, only from the page tree! This
|
170
|
-
# also means that the /Parent entry of the page is set to +nil+ if deleted.
|
167
|
+
# the page tree and the document.
|
171
168
|
#
|
172
169
|
# Negative indices count backwards from the end, i.e. -1 is the last page.
|
173
170
|
def delete_page(page)
|
174
171
|
page = self.page(page) if page.kind_of?(Integer)
|
175
|
-
return
|
172
|
+
return unless page && !page.null? && page[:Parent]
|
176
173
|
|
177
174
|
parent = page[:Parent]
|
178
|
-
index = parent[:Kids].index
|
175
|
+
index = parent[:Kids].index(page)
|
179
176
|
|
180
177
|
if index
|
181
|
-
ancestors =
|
182
|
-
ancestors << parent while (parent = parent[:Parent])
|
178
|
+
ancestors = page.ancestor_nodes
|
183
179
|
return nil unless ancestors.include?(self)
|
184
180
|
|
185
181
|
page[:Parent][:Kids].delete_at(index)
|
186
182
|
page.delete(:Parent)
|
183
|
+
document.delete(page)
|
187
184
|
ancestors.each {|node| node[:Count] -= 1 }
|
188
|
-
page
|
189
185
|
else
|
190
|
-
|
186
|
+
raise HexaPDF::Error, "Given page not found in page tree"
|
191
187
|
end
|
192
188
|
end
|
193
189
|
|
190
|
+
# :call-seq:
|
191
|
+
# pages.move_page(page, to_index)
|
192
|
+
# pages.move_page(index, to_index)
|
193
|
+
#
|
194
|
+
# Moves the given page or the page at the position specified by the zero-based index to the
|
195
|
+
# +to_index+ position.
|
196
|
+
#
|
197
|
+
# If the page that should be moved, doesn't exist or is invalid, an error is raised.
|
198
|
+
#
|
199
|
+
# Negative indices count backwards from the end, i.e. -1 is the last page. When using a
|
200
|
+
# negative index, the page will be moved after that element. So using an index of -1 will
|
201
|
+
# move the page after the last page.
|
202
|
+
def move_page(page, to_index)
|
203
|
+
page = self.page(page) if page.kind_of?(Integer)
|
204
|
+
if page.nil? || page.null? || !page[:Parent] ||
|
205
|
+
!(ancestors = page.ancestor_nodes).include?(self)
|
206
|
+
raise HexaPDF::Error, "The page to be moved doesn't exist in this page tree"
|
207
|
+
end
|
208
|
+
|
209
|
+
parent = page[:Parent]
|
210
|
+
insert_page(to_index, page)
|
211
|
+
ancestors.each {|node| node[:Count] -= 1 }
|
212
|
+
parent[:Kids].delete(page)
|
213
|
+
end
|
214
|
+
|
194
215
|
# :call-seq:
|
195
216
|
# pages.each_page {|page| block } -> pages
|
196
217
|
# pages.each_page -> Enumerator
|
@@ -225,7 +246,7 @@ module HexaPDF
|
|
225
246
|
# Ensures that the /Count and /Parent fields of the whole page tree are set up correctly and
|
226
247
|
# that there is at least one page node. This is therefore only done for the root node of the
|
227
248
|
# page tree!
|
228
|
-
def perform_validation
|
249
|
+
def perform_validation(&block)
|
229
250
|
super
|
230
251
|
return if key?(:Parent)
|
231
252
|
|
@@ -258,7 +279,7 @@ module HexaPDF
|
|
258
279
|
|
259
280
|
if self[:Count] == 0
|
260
281
|
yield("A PDF document needs at least one page", true)
|
261
|
-
add_page.validate
|
282
|
+
add_page.validate(&block)
|
262
283
|
end
|
263
284
|
end
|
264
285
|
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -69,11 +69,10 @@ module HexaPDF
|
|
69
69
|
when :DeviceRGB, :DeviceGray, :DeviceCMYK
|
70
70
|
GlobalConfiguration.constantize('color_space.map', name).new
|
71
71
|
else
|
72
|
-
space_definition =
|
72
|
+
space_definition = (name == :Pattern ? name : self[:ColorSpace]&.[](name))
|
73
73
|
if space_definition.nil?
|
74
74
|
raise HexaPDF::Error, "Color space '#{name}' not found in the resources"
|
75
75
|
elsif space_definition.kind_of?(Array)
|
76
|
-
space_definition.map! {|item| document.deref(item) }
|
77
76
|
space_family = space_definition[0]
|
78
77
|
else
|
79
78
|
space_family = space_definition
|
@@ -168,6 +167,20 @@ module HexaPDF
|
|
168
167
|
object_setter(:Properties, 'P', dict)
|
169
168
|
end
|
170
169
|
|
170
|
+
# Returns the pattern dictionary stored under the given name.
|
171
|
+
#
|
172
|
+
# If the dictionary is not found, an error is raised.
|
173
|
+
def pattern(name)
|
174
|
+
object_getter(:Pattern, name)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Adds the pattern dictionary to the resources and returns the name under which it is stored.
|
178
|
+
#
|
179
|
+
# If there already exists a name for the given dictionary, it is just returned.
|
180
|
+
def add_pattern(object)
|
181
|
+
object_setter(:Pattern, 'P', object)
|
182
|
+
end
|
183
|
+
|
171
184
|
private
|
172
185
|
|
173
186
|
# Helper method for returning an entry of a subdictionary.
|
@@ -206,6 +219,7 @@ module HexaPDF
|
|
206
219
|
super
|
207
220
|
val = self[:ProcSet]
|
208
221
|
if !val
|
222
|
+
yield("No procedure set specified", true)
|
209
223
|
self[:ProcSet] = [:PDF, :Text, :ImageB, :ImageC, :ImageI]
|
210
224
|
else
|
211
225
|
val.reject! do |name|
|