hexapdf 0.23.0 → 0.24.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -0
- data/LICENSE +1 -1
- data/Rakefile +1 -1
- data/examples/016-frame_automatic_box_placement.rb +7 -2
- data/examples/017-frame_text_flow.rb +10 -18
- data/examples/020-column_box.rb +40 -0
- data/examples/021-list_box.rb +26 -0
- data/lib/hexapdf/cli/batch.rb +1 -1
- data/lib/hexapdf/cli/command.rb +1 -1
- data/lib/hexapdf/cli/files.rb +1 -1
- data/lib/hexapdf/cli/fonts.rb +1 -1
- data/lib/hexapdf/cli/form.rb +2 -2
- data/lib/hexapdf/cli/image2pdf.rb +1 -1
- data/lib/hexapdf/cli/images.rb +1 -1
- data/lib/hexapdf/cli/info.rb +2 -2
- data/lib/hexapdf/cli/inspect.rb +2 -2
- data/lib/hexapdf/cli/merge.rb +1 -1
- 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/cli.rb +1 -1
- data/lib/hexapdf/composer.rb +45 -126
- data/lib/hexapdf/configuration.rb +17 -1
- data/lib/hexapdf/content/canvas.rb +1 -1
- data/lib/hexapdf/content/color_space.rb +1 -1
- data/lib/hexapdf/content/graphic_object/arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object/geom2d.rb +2 -1
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object.rb +1 -1
- data/lib/hexapdf/content/graphics_state.rb +1 -1
- data/lib/hexapdf/content/operator.rb +1 -1
- data/lib/hexapdf/content/parser.rb +1 -1
- data/lib/hexapdf/content/processor.rb +1 -1
- data/lib/hexapdf/content/transformation_matrix.rb +1 -1
- data/lib/hexapdf/content.rb +1 -1
- data/lib/hexapdf/data_dir.rb +1 -1
- data/lib/hexapdf/dictionary.rb +1 -1
- data/lib/hexapdf/dictionary_fields.rb +1 -1
- data/lib/hexapdf/document/files.rb +1 -1
- data/lib/hexapdf/document/fonts.rb +1 -1
- data/lib/hexapdf/document/images.rb +1 -1
- data/lib/hexapdf/document/layout.rb +397 -0
- data/lib/hexapdf/document/pages.rb +17 -1
- data/lib/hexapdf/document/signatures.rb +5 -4
- data/lib/hexapdf/document.rb +8 -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 +30 -21
- 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 +1 -1
- data/lib/hexapdf/encryption/standard_security_handler.rb +1 -1
- data/lib/hexapdf/encryption.rb +1 -1
- data/lib/hexapdf/error.rb +1 -1
- data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
- data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
- data/lib/hexapdf/filter/crypt.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/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 +1 -1
- data/lib/hexapdf/font/cmap/parser.rb +1 -1
- data/lib/hexapdf/font/cmap/writer.rb +1 -1
- data/lib/hexapdf/font/cmap.rb +1 -1
- data/lib/hexapdf/font/encoding/base.rb +1 -1
- data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/glyph_list.rb +2 -2
- 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/encoding.rb +1 -1
- data/lib/hexapdf/font/invalid_glyph.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/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 +1 -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 +1 -1
- data/lib/hexapdf/font/true_type/table/post.rb +1 -1
- data/lib/hexapdf/font/true_type/table.rb +1 -1
- data/lib/hexapdf/font/true_type.rb +1 -1
- data/lib/hexapdf/font/true_type_wrapper.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.rb +1 -1
- data/lib/hexapdf/font/type1_wrapper.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/font_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 +1 -1
- data/lib/hexapdf/image_loader.rb +1 -1
- data/lib/hexapdf/importer.rb +1 -1
- data/lib/hexapdf/layout/box.rb +121 -22
- data/lib/hexapdf/layout/box_fitter.rb +136 -0
- data/lib/hexapdf/layout/column_box.rb +247 -0
- data/lib/hexapdf/layout/frame.rb +155 -139
- data/lib/hexapdf/layout/image_box.rb +19 -4
- data/lib/hexapdf/layout/inline_box.rb +1 -1
- data/lib/hexapdf/layout/line.rb +1 -1
- data/lib/hexapdf/layout/list_box.rb +355 -0
- data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
- data/lib/hexapdf/layout/style.rb +5 -1
- data/lib/hexapdf/layout/text_box.rb +20 -9
- data/lib/hexapdf/layout/text_fragment.rb +3 -2
- data/lib/hexapdf/layout/text_layouter.rb +17 -2
- data/lib/hexapdf/layout/text_shaper.rb +1 -1
- data/lib/hexapdf/layout/width_from_polygon.rb +12 -7
- data/lib/hexapdf/layout.rb +4 -1
- data/lib/hexapdf/name_tree_node.rb +1 -1
- data/lib/hexapdf/number_tree_node.rb +1 -1
- data/lib/hexapdf/object.rb +1 -1
- data/lib/hexapdf/parser.rb +1 -8
- 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 +1 -1
- data/lib/hexapdf/serializer.rb +1 -1
- data/lib/hexapdf/stream.rb +1 -1
- data/lib/hexapdf/task/dereference.rb +1 -1
- data/lib/hexapdf/task/optimize.rb +1 -1
- data/lib/hexapdf/task.rb +1 -1
- data/lib/hexapdf/tokenizer.rb +1 -1
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +1 -1
- 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 +1 -1
- data/lib/hexapdf/type/acro_form/form.rb +1 -1
- data/lib/hexapdf/type/acro_form/signature_field.rb +1 -1
- 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 +1 -1
- 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 +1 -1
- data/lib/hexapdf/type/annotations.rb +1 -1
- data/lib/hexapdf/type/catalog.rb +1 -1
- 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 +1 -1
- data/lib/hexapdf/type/font.rb +1 -1
- data/lib/hexapdf/type/font_descriptor.rb +1 -1
- data/lib/hexapdf/type/font_simple.rb +1 -1
- data/lib/hexapdf/type/font_true_type.rb +1 -1
- data/lib/hexapdf/type/font_type0.rb +1 -1
- data/lib/hexapdf/type/font_type1.rb +1 -1
- 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/names.rb +1 -1
- data/lib/hexapdf/type/object_stream.rb +1 -1
- data/lib/hexapdf/type/page.rb +1 -1
- data/lib/hexapdf/type/page_tree_node.rb +19 -2
- data/lib/hexapdf/type/resources.rb +1 -1
- data/lib/hexapdf/type/signature/adbe_pkcs7_detached.rb +1 -1
- data/lib/hexapdf/type/signature/adbe_x509_rsa_sha1.rb +1 -1
- data/lib/hexapdf/type/signature/handler.rb +1 -1
- data/lib/hexapdf/type/signature/verification_result.rb +1 -1
- data/lib/hexapdf/type/signature.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 +1 -1
- data/lib/hexapdf/type.rb +1 -1
- data/lib/hexapdf/utils/bit_field.rb +1 -1
- 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 +1 -1
- data/lib/hexapdf/version.rb +2 -2
- data/lib/hexapdf/writer.rb +9 -7
- data/lib/hexapdf/xref_section.rb +1 -1
- data/lib/hexapdf.rb +1 -1
- data/test/hexapdf/content/graphic_object/test_geom2d.rb +1 -1
- data/test/hexapdf/document/test_destinations.rb +1 -1
- data/test/hexapdf/document/test_images.rb +1 -1
- data/test/hexapdf/document/test_layout.rb +264 -0
- data/test/hexapdf/document/test_pages.rb +9 -0
- data/test/hexapdf/document/test_signatures.rb +10 -3
- data/test/hexapdf/encryption/test_security_handler.rb +1 -1
- data/test/hexapdf/font/encoding/test_glyph_list.rb +4 -0
- data/test/hexapdf/layout/test_box.rb +53 -3
- data/test/hexapdf/layout/test_box_fitter.rb +62 -0
- data/test/hexapdf/layout/test_column_box.rb +159 -0
- data/test/hexapdf/layout/test_frame.rb +99 -38
- data/test/hexapdf/layout/test_image_box.rb +1 -1
- data/test/hexapdf/layout/test_list_box.rb +249 -0
- data/test/hexapdf/layout/test_text_box.rb +17 -2
- data/test/hexapdf/layout/test_text_fragment.rb +1 -1
- data/test/hexapdf/layout/test_text_layouter.rb +42 -17
- data/test/hexapdf/layout/test_width_from_polygon.rb +13 -0
- data/test/hexapdf/test_composer.rb +11 -0
- data/test/hexapdf/test_dictionary_fields.rb +9 -9
- data/test/hexapdf/test_document.rb +4 -4
- data/test/hexapdf/test_filter.rb +1 -1
- data/test/hexapdf/test_parser.rb +0 -2
- data/test/hexapdf/test_revisions.rb +2 -2
- data/test/hexapdf/test_serializer.rb +1 -5
- data/test/hexapdf/test_writer.rb +58 -3
- data/test/hexapdf/type/test_page_tree_node.rb +21 -1
- data/test/hexapdf/type/test_trailer.rb +3 -3
- data/test/test_helper.rb +5 -1
- metadata +28 -3
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
require_relative '../content/common'
|
|
5
|
+
require 'hexapdf/document'
|
|
6
|
+
require 'hexapdf/layout/list_box'
|
|
7
|
+
|
|
8
|
+
describe HexaPDF::Layout::ListBox do
|
|
9
|
+
before do
|
|
10
|
+
@frame = HexaPDF::Layout::Frame.new(0, 0, 100, 100)
|
|
11
|
+
inline_box = HexaPDF::Layout::InlineBox.create(width: 10, height: 10) {}
|
|
12
|
+
@text_boxes = 5.times.map do
|
|
13
|
+
HexaPDF::Layout::TextBox.new(items: [inline_box] * 15, style: {position: :default})
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def create_box(**kwargs)
|
|
18
|
+
HexaPDF::Layout::ListBox.new(content_indentation: 10, **kwargs)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def check_box(box, width, height, fit_pos = nil)
|
|
22
|
+
assert(box.fit(@frame.available_width, @frame.available_height, @frame), "box fit?")
|
|
23
|
+
assert_equal(width, box.width, "box width")
|
|
24
|
+
assert_equal(height, box.height, "box height")
|
|
25
|
+
if fit_pos
|
|
26
|
+
results = box.instance_variable_get(:@results)
|
|
27
|
+
results.each_with_index do |box_fitter, item_index|
|
|
28
|
+
box_fitter.fit_results.each_with_index do |fit_result, result_index|
|
|
29
|
+
x, y = fit_pos.shift
|
|
30
|
+
assert_equal(x, fit_result.x, "item #{item_index}, result #{result_index}, x")
|
|
31
|
+
assert_equal(y, fit_result.y, "item #{item_index}, result #{result_index}, y")
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
assert(fit_pos.empty?)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe "initialize" do
|
|
39
|
+
it "creates a new instance with the given arguments" do
|
|
40
|
+
box = create_box(children: [:a], item_type: :circle, content_indentation: 15,
|
|
41
|
+
start_number: 4, item_spacing: 20)
|
|
42
|
+
assert_equal([:a], box.children)
|
|
43
|
+
assert_equal(:circle, box.item_type)
|
|
44
|
+
assert_equal(15, box.content_indentation)
|
|
45
|
+
assert_equal(4, box.start_number)
|
|
46
|
+
assert_equal(20, box.item_spacing)
|
|
47
|
+
assert(box.supports_position_flow?)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe "fit" do
|
|
52
|
+
[:default, :flow].each do |position|
|
|
53
|
+
it "respects the set initial width, position #{position}" do
|
|
54
|
+
box = create_box(children: @text_boxes[0, 2], width: 50, style: {position: position})
|
|
55
|
+
check_box(box, 50, 80)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "respects the set initial height, position #{position}" do
|
|
59
|
+
box = create_box(children: @text_boxes[0, 2], height: 50, style: {position: position})
|
|
60
|
+
check_box(box, 100, 40)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "respects the border and padding around all list items, position #{position}" do
|
|
64
|
+
box = create_box(children: @text_boxes[0, 2],
|
|
65
|
+
style: {border: {width: [5, 4, 3, 2]}, padding: [5, 4, 3, 2], position: position})
|
|
66
|
+
check_box(box, 100, 76, [[14, 60], [14, 30]])
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "uses the frame's current cursor position and available width/height when position=:default" do
|
|
71
|
+
@frame.remove_area(Geom2D::Polygon([0, 0], [10, 0], [10, 90], [100, 90], [100, 100], [0, 100]))
|
|
72
|
+
box = create_box(children: @text_boxes[0, 2])
|
|
73
|
+
check_box(box, 90, 40, [[20, 70], [20, 50]])
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "respects the frame's shape when style position=:flow" do
|
|
77
|
+
@frame.remove_area(Geom2D::Polygon([0, 0], [0, 40], [40, 40], [40, 0]))
|
|
78
|
+
box = create_box(children: @text_boxes[0, 4], style: {position: :flow})
|
|
79
|
+
check_box(box, 100, 90, [[10, 80], [10, 60], [10, 40], [50, 10]])
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "respects the content indentation" do
|
|
83
|
+
box = create_box(children: @text_boxes[0, 1], content_indentation: 30)
|
|
84
|
+
check_box(box, 100, 30, [[30, 70]])
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "respects the spacing between list items" do
|
|
88
|
+
box = create_box(children: @text_boxes[0, 2], item_spacing: 30)
|
|
89
|
+
check_box(box, 100, 70, [[10, 80], [10, 30]])
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
describe "split" do
|
|
94
|
+
it "splits before a list item if no part of it will fit" do
|
|
95
|
+
box = create_box(children: @text_boxes[0, 2], height: 20)
|
|
96
|
+
box.fit(100, 100, @frame)
|
|
97
|
+
box_a, box_b = box.split(100, 100, @frame)
|
|
98
|
+
assert_same(box, box_a)
|
|
99
|
+
assert_equal(:show_first_marker, box_b.split_box?)
|
|
100
|
+
assert_equal(1, box_a.instance_variable_get(:@results)[0].fit_results.size)
|
|
101
|
+
assert_equal(1, box_b.children.size)
|
|
102
|
+
assert_equal(2, box_b.start_number)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "splits a list item if some part of it will fit" do
|
|
106
|
+
box = create_box(children: @text_boxes[0, 2], height: 10)
|
|
107
|
+
box.fit(100, 100, @frame)
|
|
108
|
+
box_a, box_b = box.split(100, 100, @frame)
|
|
109
|
+
assert_same(box, box_a)
|
|
110
|
+
assert_equal(:hide_first_marker, box_b.split_box?)
|
|
111
|
+
assert_equal(1, box_a.instance_variable_get(:@results)[0].fit_results.size)
|
|
112
|
+
assert_equal(2, box_b.children.size)
|
|
113
|
+
assert_equal(1, box_b.start_number)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
describe "draw" do
|
|
118
|
+
before do
|
|
119
|
+
@canvas = HexaPDF::Document.new.pages.add.canvas
|
|
120
|
+
draw_block = lambda {|canvas, box| }
|
|
121
|
+
@fixed_size_boxes = 5.times.map { HexaPDF::Layout::Box.new(width: 20, height: 10, &draw_block) }
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "draws the result" do
|
|
125
|
+
box = create_box(children: @fixed_size_boxes[0, 2])
|
|
126
|
+
box.fit(100, 100, @frame)
|
|
127
|
+
box.draw(@canvas, 0, 0)
|
|
128
|
+
operators = [
|
|
129
|
+
[:save_graphics_state],
|
|
130
|
+
[:set_font_and_size, [:F1, 10]],
|
|
131
|
+
[:begin_text],
|
|
132
|
+
[:set_text_matrix, [1, 0, 0, 1, 1.5, 93.17]],
|
|
133
|
+
[:show_text, ["\x95".b]],
|
|
134
|
+
[:end_text],
|
|
135
|
+
[:restore_graphics_state],
|
|
136
|
+
[:save_graphics_state],
|
|
137
|
+
[:concatenate_matrix, [1, 0, 0, 1, 10, 90]],
|
|
138
|
+
[:restore_graphics_state],
|
|
139
|
+
|
|
140
|
+
[:save_graphics_state],
|
|
141
|
+
[:set_font_and_size, [:F1, 10]],
|
|
142
|
+
[:begin_text],
|
|
143
|
+
[:set_text_matrix, [1, 0, 0, 1, 1.5, 83.17]],
|
|
144
|
+
[:show_text, ["\x95".b]],
|
|
145
|
+
[:end_text],
|
|
146
|
+
[:restore_graphics_state],
|
|
147
|
+
[:save_graphics_state],
|
|
148
|
+
[:concatenate_matrix, [1, 0, 0, 1, 10, 80]],
|
|
149
|
+
[:restore_graphics_state],
|
|
150
|
+
]
|
|
151
|
+
assert_operators(@canvas.contents, operators)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it "draws a cicle as marker" do
|
|
155
|
+
box = create_box(children: @fixed_size_boxes[0, 1], item_type: :circle)
|
|
156
|
+
box.fit(100, 100, @frame)
|
|
157
|
+
box.draw(@canvas, 0, 0)
|
|
158
|
+
operators = [
|
|
159
|
+
[:save_graphics_state],
|
|
160
|
+
[:set_font_and_size, [:F1, 5]],
|
|
161
|
+
[:set_text_rise, [-5.555556]],
|
|
162
|
+
[:begin_text],
|
|
163
|
+
[:set_text_matrix, [1, 0, 0, 1, 0.635, 100]],
|
|
164
|
+
[:show_text, ["m".b]],
|
|
165
|
+
[:end_text],
|
|
166
|
+
[:restore_graphics_state],
|
|
167
|
+
[:save_graphics_state],
|
|
168
|
+
[:concatenate_matrix, [1, 0, 0, 1, 10, 90]],
|
|
169
|
+
[:restore_graphics_state],
|
|
170
|
+
]
|
|
171
|
+
assert_operators(@canvas.contents, operators)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it "draws a square as marker" do
|
|
175
|
+
box = create_box(children: @fixed_size_boxes[0, 1], item_type: :square)
|
|
176
|
+
box.fit(100, 100, @frame)
|
|
177
|
+
box.draw(@canvas, 0, 0)
|
|
178
|
+
operators = [
|
|
179
|
+
[:save_graphics_state],
|
|
180
|
+
[:set_font_and_size, [:F1, 5]],
|
|
181
|
+
[:set_text_rise, [-5.555556]],
|
|
182
|
+
[:begin_text],
|
|
183
|
+
[:set_text_matrix, [1, 0, 0, 1, 1.195, 100]],
|
|
184
|
+
[:show_text, ["n".b]],
|
|
185
|
+
[:end_text],
|
|
186
|
+
[:restore_graphics_state],
|
|
187
|
+
[:save_graphics_state],
|
|
188
|
+
[:concatenate_matrix, [1, 0, 0, 1, 10, 90]],
|
|
189
|
+
[:restore_graphics_state],
|
|
190
|
+
]
|
|
191
|
+
assert_operators(@canvas.contents, operators)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it "draws decimal numbers as marker" do
|
|
195
|
+
box = create_box(children: @fixed_size_boxes[0, 2], item_type: :decimal,
|
|
196
|
+
content_indentation: 20)
|
|
197
|
+
box.fit(100, 100, @frame)
|
|
198
|
+
box.draw(@canvas, 0, 0)
|
|
199
|
+
operators = [
|
|
200
|
+
[:save_graphics_state],
|
|
201
|
+
[:set_font_and_size, [:F1, 10]],
|
|
202
|
+
[:begin_text],
|
|
203
|
+
[:set_text_matrix, [1, 0, 0, 1, 7.5, 93.17]],
|
|
204
|
+
[:show_text, ["1.".b]],
|
|
205
|
+
[:end_text],
|
|
206
|
+
[:restore_graphics_state],
|
|
207
|
+
[:save_graphics_state],
|
|
208
|
+
[:concatenate_matrix, [1, 0, 0, 1, 20, 90]],
|
|
209
|
+
[:restore_graphics_state],
|
|
210
|
+
|
|
211
|
+
[:save_graphics_state],
|
|
212
|
+
[:set_font_and_size, [:F1, 10]],
|
|
213
|
+
[:begin_text],
|
|
214
|
+
[:set_text_matrix, [1, 0, 0, 1, 7.5, 83.17]],
|
|
215
|
+
[:show_text, ["2.".b]],
|
|
216
|
+
[:end_text],
|
|
217
|
+
[:restore_graphics_state],
|
|
218
|
+
[:save_graphics_state],
|
|
219
|
+
[:concatenate_matrix, [1, 0, 0, 1, 20, 80]],
|
|
220
|
+
[:restore_graphics_state],
|
|
221
|
+
]
|
|
222
|
+
assert_operators(@canvas.contents, operators)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it "allows drawing custom markers" do
|
|
226
|
+
marker = lambda do |doc, list_box, index|
|
|
227
|
+
HexaPDF::Layout::Box.create(width: 10, height: 10) {}
|
|
228
|
+
end
|
|
229
|
+
box = create_box(children: @fixed_size_boxes[0, 1], item_type: marker)
|
|
230
|
+
box.fit(100, 100, @frame)
|
|
231
|
+
box.draw(@canvas, 0, 0)
|
|
232
|
+
operators = [
|
|
233
|
+
[:save_graphics_state],
|
|
234
|
+
[:concatenate_matrix, [1, 0, 0, 1, 0, 90]],
|
|
235
|
+
[:restore_graphics_state],
|
|
236
|
+
[:save_graphics_state],
|
|
237
|
+
[:concatenate_matrix, [1, 0, 0, 1, 10, 90]],
|
|
238
|
+
[:restore_graphics_state],
|
|
239
|
+
]
|
|
240
|
+
assert_operators(@canvas.contents, operators)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it "fails for unknown item types" do
|
|
244
|
+
box = create_box(children: @fixed_size_boxes[0, 1], item_type: :unknown)
|
|
245
|
+
box.fit(100, 100, @frame)
|
|
246
|
+
assert_raises(HexaPDF::Error) { box.draw(@canvas, 0, 0) }
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
end
|
|
@@ -12,7 +12,7 @@ describe HexaPDF::Layout::TextBox do
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def create_box(items, **kwargs)
|
|
15
|
-
HexaPDF::Layout::TextBox.new(items, **kwargs)
|
|
15
|
+
HexaPDF::Layout::TextBox.new(items: items, **kwargs)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
describe "initialize" do
|
|
@@ -20,6 +20,10 @@ describe HexaPDF::Layout::TextBox do
|
|
|
20
20
|
box = create_box([], width: 100)
|
|
21
21
|
assert_equal(100, box.width)
|
|
22
22
|
end
|
|
23
|
+
|
|
24
|
+
it "supports flowing text around other content" do
|
|
25
|
+
assert(create_box([]).supports_position_flow?)
|
|
26
|
+
end
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
describe "fit" do
|
|
@@ -104,11 +108,22 @@ describe HexaPDF::Layout::TextBox do
|
|
|
104
108
|
assert_equal([nil, box], box.split(100, 100, @frame))
|
|
105
109
|
end
|
|
106
110
|
|
|
107
|
-
it "splits the box if necessary" do
|
|
111
|
+
it "splits the box if necessary when using non-flowing text" do
|
|
108
112
|
box = create_box([@inline_box] * 10)
|
|
109
113
|
boxes = box.split(50, 10, @frame)
|
|
110
114
|
assert_equal(2, boxes.length)
|
|
111
115
|
assert_equal(box, boxes[0])
|
|
116
|
+
refute(boxes[0].split_box?)
|
|
117
|
+
assert(boxes[1].split_box?)
|
|
118
|
+
assert_equal(5, boxes[1].instance_variable_get(:@items).length)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "splits the box if necessary when using flowing text that results in a wider box" do
|
|
122
|
+
@frame.remove_area(Geom2D::Polygon.new([[0, 100], [50, 100], [50, 10], [0, 10]]))
|
|
123
|
+
box = create_box([@inline_box] * 60, style: {position: :flow})
|
|
124
|
+
boxes = box.split(50, 100, @frame)
|
|
125
|
+
assert_equal(2, boxes.length)
|
|
126
|
+
assert_equal(box, boxes[0])
|
|
112
127
|
assert_equal(5, boxes[1].instance_variable_get(:@items).length)
|
|
113
128
|
end
|
|
114
129
|
end
|
|
@@ -57,6 +57,24 @@ module TestTextLayouterHelpers
|
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
describe HexaPDF::Layout::TextLayouter::Box do
|
|
61
|
+
it "can describe itself" do
|
|
62
|
+
assert_equal('Box["test"]', HexaPDF::Layout::TextLayouter::Box.new("test").inspect)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe HexaPDF::Layout::TextLayouter::Glue do
|
|
67
|
+
it "can describe itself" do
|
|
68
|
+
assert_equal('Glue["test"]', HexaPDF::Layout::TextLayouter::Glue.new("test", 5, 5).inspect)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe HexaPDF::Layout::TextLayouter::Penalty do
|
|
73
|
+
it "can describe itself" do
|
|
74
|
+
assert_equal('Penalty[100 10 nil]', HexaPDF::Layout::TextLayouter::Penalty.new(100, 10).inspect)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
60
78
|
describe HexaPDF::Layout::TextLayouter::SimpleTextSegmentation do
|
|
61
79
|
include TestTextLayouterHelpers
|
|
62
80
|
|
|
@@ -556,36 +574,43 @@ describe HexaPDF::Layout::TextLayouter do
|
|
|
556
574
|
end
|
|
557
575
|
end
|
|
558
576
|
|
|
559
|
-
describe "
|
|
577
|
+
describe "breaking into parts of a too wide text fragment" do
|
|
560
578
|
before do
|
|
561
|
-
@str = "
|
|
579
|
+
@str = " Thisisaverylongstring"
|
|
562
580
|
@frag = HexaPDF::Layout::TextFragment.create(@str, font: @font)
|
|
563
581
|
end
|
|
564
582
|
|
|
565
|
-
it "
|
|
583
|
+
it "arranges the parts if single parts fit into the available space" do
|
|
566
584
|
result = @layouter.fit([@frag], 20, 100)
|
|
567
585
|
assert(result.remaining_items.empty?)
|
|
568
586
|
assert_equal(:success, result.status)
|
|
569
|
-
assert_equal(@str.
|
|
570
|
-
assert_equal(
|
|
587
|
+
assert_equal(@str.strip.length, result.lines.sum {|l| l.items.sum {|i| i.items.count } })
|
|
588
|
+
assert_equal(45, result.height)
|
|
589
|
+
end
|
|
571
590
|
|
|
591
|
+
it "works even if a single part doesn't fit" do
|
|
572
592
|
result = @layouter.fit([@frag], 1, 100)
|
|
573
|
-
assert_equal(
|
|
593
|
+
assert_equal(@str.strip.length, result.remaining_items.count)
|
|
574
594
|
assert_equal(:box_too_wide, result.status)
|
|
575
595
|
end
|
|
576
596
|
|
|
577
|
-
it "works
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
else
|
|
583
|
-
10
|
|
584
|
-
end
|
|
585
|
-
end
|
|
586
|
-
result = @layouter.fit([@frag], width_block, 30)
|
|
597
|
+
it "works if the parts of the broken fragment are used in another .fit call" do
|
|
598
|
+
text = "This is a long string to test"
|
|
599
|
+
frag = HexaPDF::Layout::TextFragment.create(text, font: @font)
|
|
600
|
+
result = @layouter.fit([frag], lambda {|h, _| h > 17 ? 0 : 25 }, 20)
|
|
601
|
+
refute(result.remaining_items.empty?)
|
|
587
602
|
assert_equal(:height, result.status)
|
|
588
|
-
assert_equal([
|
|
603
|
+
assert_equal(["This", "is a"],
|
|
604
|
+
result.lines.map {|l| l.items.map {|tf| tf.items.map(&:str).join }.join })
|
|
605
|
+
|
|
606
|
+
# Simulating a split text box where the second part is tried to fit into same remaining
|
|
607
|
+
# space
|
|
608
|
+
result = @layouter.fit(result.remaining_items, 25, 1)
|
|
609
|
+
|
|
610
|
+
# Now fit into next available space
|
|
611
|
+
result = @layouter.fit(result.remaining_items, 25, 100)
|
|
612
|
+
assert_equal(["long", "string", "to test"],
|
|
613
|
+
result.lines.map {|l| l.items.map {|tf| tf.items.map(&:str).join }.join })
|
|
589
614
|
end
|
|
590
615
|
end
|
|
591
616
|
|
|
@@ -32,6 +32,13 @@ describe HexaPDF::Layout::WidthFromPolygon do
|
|
|
32
32
|
assert_equal([2.5, 7.5], ws.call(5, 1))
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
it "works for polygons in counterclockwise order with some segments crossing only top or bottom" do
|
|
36
|
+
ws = create_width_spec(Geom2D::PolygonSet(Geom2D::Polygon([55.0, 65.0], [70, 65], [70.0, 50.0],
|
|
37
|
+
[100.0, 50.0], [100.0, 63.0], [120, 63],
|
|
38
|
+
[120, 70], [55, 70])))
|
|
39
|
+
assert_equal([70, 30], ws.call(0, 10))
|
|
40
|
+
end
|
|
41
|
+
|
|
35
42
|
it "works if some segments only cross the top line" do
|
|
36
43
|
ws = create_width_spec(Geom2D::Polygon([0, 0], [0, 10], [2, 11], [4, 9], [6, 11], [10, 10],
|
|
37
44
|
[10, 0]))
|
|
@@ -60,6 +67,12 @@ describe HexaPDF::Layout::WidthFromPolygon do
|
|
|
60
67
|
assert_equal([5, 5], ws.call(4, 2))
|
|
61
68
|
end
|
|
62
69
|
|
|
70
|
+
it "works in case of small floating point differences" do
|
|
71
|
+
ws = create_width_spec(Geom2D::Polygon([0, 0], [10, 0], [10, 5.99999999999994], [8, 6], [8, 10],
|
|
72
|
+
[6, 10], [6, 5], [0, 5]))
|
|
73
|
+
assert_equal([6, 4], ws.call(4.0, 3.0))
|
|
74
|
+
end
|
|
75
|
+
|
|
63
76
|
describe "multiple polygons" do
|
|
64
77
|
it "rectangle in rectangle" do
|
|
65
78
|
ws = create_width_spec(Geom2D::PolygonSet(Geom2D::Polygon([0, 0], [0, 10], [10, 10], [10, 0]),
|
|
@@ -249,6 +249,17 @@ describe HexaPDF::Composer do
|
|
|
249
249
|
end
|
|
250
250
|
end
|
|
251
251
|
|
|
252
|
+
describe "box" do
|
|
253
|
+
it "creates the named box and draws it on the canvas" do
|
|
254
|
+
box = nil
|
|
255
|
+
@composer.define_singleton_method(:draw_box) {|arg| box = arg }
|
|
256
|
+
image = @composer.document.images.add(File.join(TEST_DATA_DIR, 'images', 'gray.jpg'))
|
|
257
|
+
@composer.box(:list, width: 20) {|list| list.image(image) }
|
|
258
|
+
assert_equal(20, box.width)
|
|
259
|
+
assert_same(image, box.children[0].image)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
252
263
|
describe "draw_box" do
|
|
253
264
|
def create_box(**kwargs)
|
|
254
265
|
HexaPDF::Layout::Box.new(**kwargs) {}
|
|
@@ -37,7 +37,7 @@ describe HexaPDF::DictionaryFields do
|
|
|
37
37
|
describe "convert" do
|
|
38
38
|
it "returns the converted object, using the first usable converter" do
|
|
39
39
|
doc = Minitest::Mock.new
|
|
40
|
-
doc.expect(:wrap, :data, [Hash,
|
|
40
|
+
doc.expect(:wrap, :data, [Hash], type: Integer)
|
|
41
41
|
@field.convert({}, doc)
|
|
42
42
|
doc.verify
|
|
43
43
|
|
|
@@ -67,20 +67,20 @@ describe HexaPDF::DictionaryFields do
|
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
it "allows conversion from a hash" do
|
|
70
|
-
@doc.expect(:wrap, :data, [Hash,
|
|
70
|
+
@doc.expect(:wrap, :data, [Hash], type: Class)
|
|
71
71
|
@field.convert({Test: :value}, @doc)
|
|
72
72
|
@doc.verify
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
it "allows conversion from a Dictionary" do
|
|
76
|
-
@doc.expect(:wrap, :data, [HexaPDF::Dictionary,
|
|
76
|
+
@doc.expect(:wrap, :data, [HexaPDF::Dictionary], type: Class)
|
|
77
77
|
@field.convert(HexaPDF::Dictionary.new({Test: :value}), @doc)
|
|
78
78
|
@doc.verify
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
it "allows conversion from an HexaPDF::Dictionary to a Stream if stream data is set" do
|
|
82
82
|
@field = self.class::Field.new(HexaPDF::Stream)
|
|
83
|
-
@doc.expect(:wrap, :data, [HexaPDF::Dictionary,
|
|
83
|
+
@doc.expect(:wrap, :data, [HexaPDF::Dictionary], type: Class)
|
|
84
84
|
data = HexaPDF::PDFData.new({}, 0, 0, "")
|
|
85
85
|
@field.convert(HexaPDF::Dictionary.new(data), @doc)
|
|
86
86
|
@doc.verify
|
|
@@ -108,7 +108,7 @@ describe HexaPDF::DictionaryFields do
|
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
it "allows conversion from an array" do
|
|
111
|
-
@doc.expect(:wrap, :data, [[1, 2],
|
|
111
|
+
@doc.expect(:wrap, :data, [[1, 2]], type: HexaPDF::PDFArray)
|
|
112
112
|
@field.convert([1, 2], @doc)
|
|
113
113
|
@doc.verify
|
|
114
114
|
end
|
|
@@ -208,14 +208,14 @@ describe HexaPDF::DictionaryFields do
|
|
|
208
208
|
|
|
209
209
|
it "allows conversion from a string" do
|
|
210
210
|
@doc = Minitest::Mock.new
|
|
211
|
-
@doc.expect(:wrap, :data, [{F: 'test'},
|
|
211
|
+
@doc.expect(:wrap, :data, [{F: 'test'}], type: HexaPDF::Type::FileSpecification)
|
|
212
212
|
@field.convert('test', @doc)
|
|
213
213
|
@doc.verify
|
|
214
214
|
end
|
|
215
215
|
|
|
216
216
|
it "allows conversion from a hash/dictionary" do
|
|
217
217
|
@doc = Minitest::Mock.new
|
|
218
|
-
@doc.expect(:wrap, :data, [{F: 'test'},
|
|
218
|
+
@doc.expect(:wrap, :data, [{F: 'test'}], type: HexaPDF::Type::FileSpecification)
|
|
219
219
|
@field.convert({F: 'test'}, @doc)
|
|
220
220
|
@doc.verify
|
|
221
221
|
end
|
|
@@ -232,7 +232,7 @@ describe HexaPDF::DictionaryFields do
|
|
|
232
232
|
|
|
233
233
|
it "allows conversion to a Rectangle from an Array" do
|
|
234
234
|
doc = Minitest::Mock.new
|
|
235
|
-
doc.expect(:wrap, :data, [[0, 1, 2, 3],
|
|
235
|
+
doc.expect(:wrap, :data, [[0, 1, 2, 3]], type: HexaPDF::Rectangle)
|
|
236
236
|
@field.convert([0, 1, 2, 3], doc)
|
|
237
237
|
doc.verify
|
|
238
238
|
end
|
|
@@ -240,7 +240,7 @@ describe HexaPDF::DictionaryFields do
|
|
|
240
240
|
it "allows conversion to a Rectangle from a HexaPDF::PDFArray" do
|
|
241
241
|
data = HexaPDF::PDFArray.new([0, 1, 2, 3])
|
|
242
242
|
doc = Minitest::Mock.new
|
|
243
|
-
doc.expect(:wrap, :data, [data,
|
|
243
|
+
doc.expect(:wrap, :data, [data], type: HexaPDF::Rectangle)
|
|
244
244
|
@field.convert(data, doc)
|
|
245
245
|
doc.verify
|
|
246
246
|
end
|
|
@@ -302,7 +302,7 @@ describe HexaPDF::Document do
|
|
|
302
302
|
|
|
303
303
|
it "defers to @revisions for iterating over all objects" do
|
|
304
304
|
revs = Minitest::Mock.new
|
|
305
|
-
revs.expect(:each_object, :retval,
|
|
305
|
+
revs.expect(:each_object, :retval, only_current: true, only_loaded: true)
|
|
306
306
|
doc = HexaPDF::Document.new
|
|
307
307
|
doc.instance_variable_set(:@revisions, revs)
|
|
308
308
|
doc.each(only_current: true, only_loaded: true)
|
|
@@ -328,7 +328,7 @@ describe HexaPDF::Document do
|
|
|
328
328
|
|
|
329
329
|
it "doesn't decrypt the document if document.auto_encrypt=false" do
|
|
330
330
|
test_file = File.join(TEST_DATA_DIR, 'standard-security-handler', 'nopwd-arc4-40bit-V1.pdf')
|
|
331
|
-
doc = HexaPDF::Document.new(io: StringIO.new(File.
|
|
331
|
+
doc = HexaPDF::Document.new(io: StringIO.new(File.binread(test_file)),
|
|
332
332
|
config: {'document.auto_decrypt' => false})
|
|
333
333
|
assert_kind_of(String, doc.trailer[:Info][:ModDate])
|
|
334
334
|
handler = HexaPDF::Encryption::SecurityHandler.set_up_decryption(doc)
|
|
@@ -510,8 +510,8 @@ describe HexaPDF::Document do
|
|
|
510
510
|
|
|
511
511
|
it "allows to conveniently sign a document" do
|
|
512
512
|
mock = Minitest::Mock.new
|
|
513
|
-
mock.expect(:handler, :handler,
|
|
514
|
-
mock.expect(:add, :added, [:io, :handler,
|
|
513
|
+
mock.expect(:handler, :handler, name: :handler, opt: :key)
|
|
514
|
+
mock.expect(:add, :added, [:io, :handler], signature: :sig, write_options: :write_options)
|
|
515
515
|
@doc.instance_variable_set(:@signatures, mock)
|
|
516
516
|
result = @doc.sign(:io, handler: :handler, write_options: :write_options, signature: :sig, opt: :key)
|
|
517
517
|
assert_equal(:added, result)
|
data/test/hexapdf/test_filter.rb
CHANGED
data/test/hexapdf/test_parser.rb
CHANGED
|
@@ -543,14 +543,12 @@ describe HexaPDF::Parser do
|
|
|
543
543
|
xref_section, trailer = @parser.load_revision(@parser.startxref_offset)
|
|
544
544
|
assert_equal({Test: 'now'}, trailer)
|
|
545
545
|
assert(xref_section[1].in_use?)
|
|
546
|
-
refute(@parser.contains_xref_streams?)
|
|
547
546
|
end
|
|
548
547
|
|
|
549
548
|
it "works for a cross-reference stream" do
|
|
550
549
|
xref_section, trailer = @parser.load_revision(212)
|
|
551
550
|
assert_equal({Size: 2, Type: :XRef}, trailer)
|
|
552
551
|
assert(xref_section[1].in_use?)
|
|
553
|
-
assert(@parser.contains_xref_streams?)
|
|
554
552
|
end
|
|
555
553
|
|
|
556
554
|
it "fails if another object is found instead of a cross-reference stream" do
|
|
@@ -185,8 +185,8 @@ describe HexaPDF::Revisions do
|
|
|
185
185
|
end
|
|
186
186
|
|
|
187
187
|
it "iterates over all objects" do
|
|
188
|
-
assert_equal([
|
|
189
|
-
@revisions.each_object(only_current: false).
|
|
188
|
+
assert_equal([@obj3, 400, 200, @obj3, 10, 20],
|
|
189
|
+
@revisions.each_object(only_current: false).map(&:value))
|
|
190
190
|
end
|
|
191
191
|
|
|
192
192
|
it "iterates over all loaded objects" do
|
|
@@ -101,16 +101,12 @@ describe HexaPDF::Serializer do
|
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
it "serializes time like objects" do
|
|
104
|
-
tz = ENV['TZ']
|
|
105
|
-
ENV['TZ'] = 'Europe/Vienna'
|
|
106
104
|
assert_serialized("(D:20150416094100)", Time.new(2015, 04, 16, 9, 41, 0, 0))
|
|
107
105
|
assert_serialized("(D:20150416094100+01'00')", Time.new(2015, 04, 16, 9, 41, 0, 3600))
|
|
108
106
|
assert_serialized("(D:20150416094100-01'20')", Time.new(2015, 04, 16, 9, 41, 0, -4800))
|
|
109
|
-
assert_serialized("(D:20150416000000
|
|
107
|
+
assert_serialized("(D:20150416000000)", Date.parse("2015-04-16 9:41:00 +02:00"))
|
|
110
108
|
assert_serialized("(D:20150416094100+02'00')",
|
|
111
109
|
Time.parse("2015-04-16 9:41:00 +02:00").to_datetime)
|
|
112
|
-
ensure
|
|
113
|
-
ENV['TZ'] = tz
|
|
114
110
|
end
|
|
115
111
|
|
|
116
112
|
it "serializes HexaPDF objects" do
|