hexapdf 0.23.0 → 0.24.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 +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
@@ -57,6 +57,14 @@ describe HexaPDF::Layout::Box do
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
+
it "returns false when asking whether it is a split box by default" do
|
61
|
+
refute(create_box.split_box?)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "doesn't support the position :flow" do
|
65
|
+
refute(create_box.supports_position_flow?)
|
66
|
+
end
|
67
|
+
|
60
68
|
describe "fit" do
|
61
69
|
before do
|
62
70
|
@frame = Object.new
|
@@ -89,9 +97,51 @@ describe HexaPDF::Layout::Box do
|
|
89
97
|
end
|
90
98
|
end
|
91
99
|
|
92
|
-
|
93
|
-
|
94
|
-
|
100
|
+
describe "split" do
|
101
|
+
before do
|
102
|
+
@box = create_box(width: 100, height: 100)
|
103
|
+
@box.fit(100, 100, nil)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "doesn't need to be split if it completely fits" do
|
107
|
+
assert_equal([@box, nil], @box.split(100, 100, nil))
|
108
|
+
end
|
109
|
+
|
110
|
+
it "can't be split if it doesn't (completely) fit and its width is greater than the available width" do
|
111
|
+
@box.fit(90, 100, nil)
|
112
|
+
assert_equal([nil, @box], @box.split(50, 150, nil))
|
113
|
+
end
|
114
|
+
|
115
|
+
it "can't be split if it doesn't (completely) fit and its height is greater than the available height" do
|
116
|
+
@box.fit(90, 100, nil)
|
117
|
+
assert_equal([nil, @box], @box.split(150, 50, nil))
|
118
|
+
end
|
119
|
+
|
120
|
+
it "can't be split if it doesn't (completely) fit and its content width is zero" do
|
121
|
+
box = create_box(width: 0, height: 100)
|
122
|
+
assert_equal([nil, box], box.split(150, 150, nil))
|
123
|
+
end
|
124
|
+
|
125
|
+
it "can't be split if it doesn't (completely) fit and its content height is zero" do
|
126
|
+
box = create_box(width: 100, height: 0)
|
127
|
+
assert_equal([nil, box], box.split(150, 150, nil))
|
128
|
+
end
|
129
|
+
|
130
|
+
it "can't be split if it doesn't (completely) fit as the default implementation knows nothing about the content" do
|
131
|
+
@box.style.position = :flow # make sure we would generally be splitable
|
132
|
+
@box.fit(90, 100, nil)
|
133
|
+
assert_equal([nil, @box], @box.split(150, 150, nil))
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
it "can create a cloned box for splitting" do
|
138
|
+
box = create_box
|
139
|
+
box.fit(100, 100, nil)
|
140
|
+
cloned_box = box.send(:create_split_box)
|
141
|
+
assert(cloned_box.split_box?)
|
142
|
+
refute(cloned_box.instance_variable_get(:@fit_successful))
|
143
|
+
assert_equal(0, cloned_box.width)
|
144
|
+
assert_equal(0, cloned_box.height)
|
95
145
|
end
|
96
146
|
|
97
147
|
describe "draw" do
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
require 'geom2d/polygon'
|
5
|
+
require 'hexapdf/layout/box_fitter'
|
6
|
+
require 'hexapdf/layout'
|
7
|
+
|
8
|
+
describe HexaPDF::Layout::BoxFitter do
|
9
|
+
before do
|
10
|
+
shape = Geom2D::Polygon([0, 0], [100, 0], [100, 90], [10, 90], [10, 80], [0, 80])
|
11
|
+
frames = [
|
12
|
+
HexaPDF::Layout::Frame.new(0, 0, 100, 100, shape: shape),
|
13
|
+
HexaPDF::Layout::Frame.new(100, 100, 50, 50),
|
14
|
+
]
|
15
|
+
@box_fitter = HexaPDF::Layout::BoxFitter.new(frames)
|
16
|
+
end
|
17
|
+
|
18
|
+
def fit_box(count, width: 10, height: 10)
|
19
|
+
ibox = HexaPDF::Layout::InlineBox.create(width: width, height: height) {}
|
20
|
+
@box_fitter.fit(HexaPDF::Layout::TextBox.new(items: [ibox] * count))
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_result(*pos, content_heights:, successful: true, boxes_remain: false)
|
24
|
+
pos.each_slice(2).with_index do |(x, y), index|
|
25
|
+
assert_equal(x, @box_fitter.fit_results[index].x, "x #{index}")
|
26
|
+
assert_equal(y, @box_fitter.fit_results[index].y, "y #{index}")
|
27
|
+
end
|
28
|
+
assert_equal(content_heights, @box_fitter.content_heights)
|
29
|
+
successful ? assert(@box_fitter.fit_successful?) : refute(@box_fitter.fit_successful?)
|
30
|
+
rboxes = @box_fitter.remaining_boxes.empty?
|
31
|
+
boxes_remain ? refute(rboxes) : assert(rboxes)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "successfully places boxes only in one frame" do
|
35
|
+
fit_box(20)
|
36
|
+
fit_box(20)
|
37
|
+
check_result(10, 60, 0, 40, content_heights: [50, 0])
|
38
|
+
end
|
39
|
+
|
40
|
+
it "successfully places boxes in multiple frames, without splitting" do
|
41
|
+
fit_box(1, height: 80)
|
42
|
+
fit_box(1, height: 40)
|
43
|
+
check_result(10, 10, 100, 110, content_heights: [80, 40])
|
44
|
+
end
|
45
|
+
|
46
|
+
it "successfully places boxes in multiple framess, with splitting" do
|
47
|
+
fit_box(63)
|
48
|
+
fit_box(30)
|
49
|
+
fit_box(10)
|
50
|
+
check_result(10, 20, 0, 0, 100, 130, 100, 110, content_heights: [90, 40])
|
51
|
+
end
|
52
|
+
|
53
|
+
it "fails when some boxes can't be fitted" do
|
54
|
+
fit_box(9)
|
55
|
+
fit_box(70)
|
56
|
+
fit_box(40)
|
57
|
+
fit_box(20)
|
58
|
+
check_result(10, 80, 0, 10, 0, 0, 100, 100, successful: false, boxes_remain: true,
|
59
|
+
content_heights: [90, 50])
|
60
|
+
assert_equal(2, @box_fitter.remaining_boxes.size)
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
require_relative '../content/common'
|
5
|
+
require 'hexapdf/document'
|
6
|
+
require 'hexapdf/layout/column_box'
|
7
|
+
|
8
|
+
describe HexaPDF::Layout::ColumnBox 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
|
+
draw_block = lambda do |canvas, box|
|
16
|
+
canvas.move_to(0, 0).end_path
|
17
|
+
end
|
18
|
+
@fixed_size_boxes = 15.times.map { HexaPDF::Layout::Box.new(width: 20, height: 10, &draw_block) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_box(**kwargs)
|
22
|
+
HexaPDF::Layout::ColumnBox.new(gaps: 10, **kwargs)
|
23
|
+
end
|
24
|
+
|
25
|
+
def check_box(box, width, height, fit_pos = nil)
|
26
|
+
assert(box.fit(@frame.available_width, @frame.available_height, @frame), "box fit?")
|
27
|
+
assert_equal(width, box.width, "box width")
|
28
|
+
assert_equal(height, box.height, "box height")
|
29
|
+
if fit_pos
|
30
|
+
box_fitter = box.instance_variable_get(:@box_fitter)
|
31
|
+
assert_equal(fit_pos.size, box_fitter.fit_results.size)
|
32
|
+
fit_pos.each_with_index do |(x, y), index|
|
33
|
+
assert_equal(x, box_fitter.fit_results[index].x, "result[#{index}].x")
|
34
|
+
assert_equal(y, box_fitter.fit_results[index].y, "result[#{index}].y")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "initialize" do
|
40
|
+
it "creates a new instance with the given arguments" do
|
41
|
+
box = create_box(children: [:a], columns: 3, gaps: 10, equal_height: false)
|
42
|
+
assert_equal([:a], box.children)
|
43
|
+
assert_equal([-1, -1, -1], box.columns)
|
44
|
+
assert_equal([10], box.gaps)
|
45
|
+
assert_equal(false, box.equal_height)
|
46
|
+
assert(box.supports_position_flow?)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "fit" do
|
51
|
+
[:default, :flow].each do |position|
|
52
|
+
it "respects the set initial width, position #{position}" do
|
53
|
+
box = create_box(children: @text_boxes[0..1], width: 50, style: {position: position})
|
54
|
+
check_box(box, 50, 80)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "respects the set initial height, position #{position}" do
|
58
|
+
box = create_box(children: @text_boxes[0..1], height: 50, equal_height: false,
|
59
|
+
style: {position: position})
|
60
|
+
check_box(box, 100, 50)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "respects the border and padding around all columns, position #{position}" do
|
64
|
+
box = create_box(children: @fixed_size_boxes[0, 3],
|
65
|
+
style: {border: {width: [5, 4, 3, 2]}, padding: [5, 4, 3, 2], position: position})
|
66
|
+
check_box(box, 100, 36, [[4, 80], [4, 70], [53, 80]])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it "uses the frame's current cursor position and available width/height when style 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: @fixed_size_boxes[0, 4])
|
73
|
+
check_box(box, 90, 20, [[10, 80], [10, 70], [60, 80], [60, 70]])
|
74
|
+
end
|
75
|
+
|
76
|
+
it "respects the frame's shape when style position=:flow" do
|
77
|
+
@frame.remove_area(Geom2D::Polygon([30, 65], [70, 65], [70, 35], [30, 35]))
|
78
|
+
box = create_box(children: @text_boxes[0, 3], style: {position: :flow})
|
79
|
+
check_box(box, 100, 70, [[0, 70], [0, 60], [0, 30], [55, 80], [55, 70], [70, 30]])
|
80
|
+
end
|
81
|
+
|
82
|
+
it "allows fitting the contents to fill the columns instead of equalizing the height" do
|
83
|
+
box = create_box(children: @fixed_size_boxes, equal_height: false)
|
84
|
+
check_box(box, 100, 100, [[0, 90], [0, 80], [0, 70], [0, 60], [0, 50], [0, 40], [0, 30],
|
85
|
+
[0, 20], [0, 10], [0, 0], [55, 90], [55, 80], [55, 70],
|
86
|
+
[55, 60], [55, 50]])
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "columns calculations" do
|
90
|
+
it "works for a single column with a specified width" do
|
91
|
+
box = create_box(children: @fixed_size_boxes[0..0], columns: [50])
|
92
|
+
check_box(box, 50, 10, [[0, 90]])
|
93
|
+
end
|
94
|
+
|
95
|
+
it "works for multiple columns with specified widths" do
|
96
|
+
box = create_box(children: @fixed_size_boxes[0..1], columns: [50, 30])
|
97
|
+
check_box(box, 90, 10, [[0, 90], [60, 90]])
|
98
|
+
end
|
99
|
+
|
100
|
+
it "works for a single column with auto-width" do
|
101
|
+
box = create_box(children: @fixed_size_boxes[0..0], columns: [-5])
|
102
|
+
check_box(box, 100, 10, [[0, 90]])
|
103
|
+
end
|
104
|
+
|
105
|
+
it "works for multiple columns with auto-widths" do
|
106
|
+
box = create_box(children: @fixed_size_boxes[0..1], columns: [-2, -1])
|
107
|
+
check_box(box, 100, 10, [[0, 90], [70, 90]])
|
108
|
+
end
|
109
|
+
|
110
|
+
it "works for mixed columns with specified widths and auto-widths" do
|
111
|
+
box = create_box(children: @fixed_size_boxes[0..2], columns: [20, -1, -2])
|
112
|
+
check_box(box, 100, 10, [[0, 90], [30, 90], [60, 90]])
|
113
|
+
end
|
114
|
+
|
115
|
+
it "cycles the gap array" do
|
116
|
+
box = create_box(children: @fixed_size_boxes[0..3], columns: 4, gaps: [5, 10])
|
117
|
+
check_box(box, 100, 10, [[0, 90], [25, 90], [55, 90], [80, 90]])
|
118
|
+
end
|
119
|
+
|
120
|
+
it "fails if the necessary width is larger than the available one" do
|
121
|
+
box = create_box(children: @fixed_size_boxes[0..2], columns: 4, gaps: [40])
|
122
|
+
refute(box.fit(100, 100, @frame))
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
it "splits the children if they are too big to fill the colums" do
|
128
|
+
box = create_box(children: @fixed_size_boxes, width: 50, height: 50)
|
129
|
+
box.fit(100, 100, @frame)
|
130
|
+
box_a, box_b = box.split(100, 100, @frame)
|
131
|
+
assert_same(box, box_a)
|
132
|
+
assert(box_b.split_box?)
|
133
|
+
assert_equal(5, box_b.children.size)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "draws the result onto the canvas" do
|
137
|
+
box = create_box(children: @fixed_size_boxes)
|
138
|
+
box.fit(100, 100, @frame)
|
139
|
+
|
140
|
+
@canvas = HexaPDF::Document.new.pages.add.canvas
|
141
|
+
box.draw(@canvas, 0, 0)
|
142
|
+
operators = 90.step(to: 20, by: -10).map do |y|
|
143
|
+
[[:save_graphics_state],
|
144
|
+
[:concatenate_matrix, [1, 0, 0, 1, 0, y]],
|
145
|
+
[:move_to, [0, 0]],
|
146
|
+
[:end_path],
|
147
|
+
[:restore_graphics_state]]
|
148
|
+
end
|
149
|
+
operators.concat(90.step(to: 30, by: -10).map do |y|
|
150
|
+
[[:save_graphics_state],
|
151
|
+
[:concatenate_matrix, [1, 0, 0, 1, 55, y]],
|
152
|
+
[:move_to, [0, 0]],
|
153
|
+
[:end_path],
|
154
|
+
[:restore_graphics_state]]
|
155
|
+
end)
|
156
|
+
operators.flatten!(1)
|
157
|
+
assert_operators(@canvas.contents, operators)
|
158
|
+
end
|
159
|
+
end
|
@@ -3,6 +3,35 @@
|
|
3
3
|
require 'test_helper'
|
4
4
|
require 'hexapdf/layout/frame'
|
5
5
|
require 'hexapdf/layout/box'
|
6
|
+
require 'hexapdf/document'
|
7
|
+
|
8
|
+
describe HexaPDF::Layout::Frame do
|
9
|
+
it "shows the box's mask area on #draw when using debug output" do
|
10
|
+
doc = HexaPDF::Document.new(config: {'debug' => true})
|
11
|
+
canvas = doc.pages.add.canvas
|
12
|
+
box = HexaPDF::Layout::Box.create(width: 20, height: 20) {}
|
13
|
+
result = HexaPDF::Layout::Frame::FitResult.new(box)
|
14
|
+
result.mask = Geom2D::Polygon([0, 0], [0, 20], [20, 20], [20, 0])
|
15
|
+
result.x = result.y = 0
|
16
|
+
result.draw(canvas)
|
17
|
+
assert_equal(<<~CONTENTS, canvas.contents)
|
18
|
+
q
|
19
|
+
0.0 0.501961 0.0 rg
|
20
|
+
0.0 0.392157 0.0 RG
|
21
|
+
/GS1 gs
|
22
|
+
0 0 m
|
23
|
+
0 20 l
|
24
|
+
20 20 l
|
25
|
+
20 0 l
|
26
|
+
h
|
27
|
+
B
|
28
|
+
Q
|
29
|
+
q
|
30
|
+
1 0 0 1 0 0 cm
|
31
|
+
Q
|
32
|
+
CONTENTS
|
33
|
+
end
|
34
|
+
end
|
6
35
|
|
7
36
|
describe HexaPDF::Layout::Frame do
|
8
37
|
before do
|
@@ -23,16 +52,14 @@ describe HexaPDF::Layout::Frame do
|
|
23
52
|
assert_equal(150, @frame.available_height)
|
24
53
|
end
|
25
54
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
assert_same(contour_line, frame.contour_line)
|
35
|
-
end
|
55
|
+
it "allows setting the shape of the frame on initialization" do
|
56
|
+
shape = Geom2D::Polygon([50, 10], [55, 100], [105, 100], [105, 10])
|
57
|
+
frame = HexaPDF::Layout::Frame.new(5, 10, 100, 150, shape: shape)
|
58
|
+
assert_equal(shape, frame.shape)
|
59
|
+
assert_equal(55, frame.x)
|
60
|
+
assert_equal(100, frame.y)
|
61
|
+
assert_equal(50, frame.available_width)
|
62
|
+
assert_equal(90, frame.available_height)
|
36
63
|
end
|
37
64
|
|
38
65
|
it "returns an appropriate width specification object" do
|
@@ -44,15 +71,25 @@ describe HexaPDF::Layout::Frame do
|
|
44
71
|
before do
|
45
72
|
@frame = HexaPDF::Layout::Frame.new(10, 10, 100, 100)
|
46
73
|
@canvas = Minitest::Mock.new
|
74
|
+
def @canvas.context
|
75
|
+
Object.new.tap do |ctx|
|
76
|
+
def ctx.document; Object.new.tap {|doc| def doc.config; Hash.new(false); end } end
|
77
|
+
end
|
78
|
+
end
|
47
79
|
end
|
48
80
|
|
49
81
|
# Creates a box with the given option, storing it in @box, and draws it inside @frame. It is
|
50
82
|
# checked whether the box coordinates are pos and whether the frame has the shape given by
|
51
83
|
# points.
|
52
|
-
def check_box(box_opts, pos, points)
|
84
|
+
def check_box(box_opts, pos, mask, points)
|
85
|
+
flow_supported = !box_opts.delete(:doesnt_support_position_flow)
|
53
86
|
@box = HexaPDF::Layout::Box.create(**box_opts) {}
|
87
|
+
@box.define_singleton_method(:supports_position_flow?) { true } if flow_supported
|
54
88
|
@canvas.expect(:translate, nil, pos)
|
55
|
-
|
89
|
+
fit_result = @frame.fit(@box)
|
90
|
+
refute_nil(fit_result)
|
91
|
+
@frame.draw(@canvas, fit_result)
|
92
|
+
assert_equal(mask, fit_result.mask.bbox.to_a)
|
56
93
|
assert_equal(points, @frame.shape.polygons.map(&:to_a))
|
57
94
|
@canvas.verify
|
58
95
|
end
|
@@ -75,6 +112,7 @@ describe HexaPDF::Layout::Frame do
|
|
75
112
|
check_box(
|
76
113
|
{width: 50, height: 50, position: :absolute, position_hint: [10, 10]},
|
77
114
|
[20, 20],
|
115
|
+
[20, 20, 70, 70],
|
78
116
|
[[[10, 10], [110, 10], [110, 110], [10, 110]],
|
79
117
|
[[20, 20], [70, 20], [70, 70], [20, 70]]]
|
80
118
|
)
|
@@ -84,6 +122,7 @@ describe HexaPDF::Layout::Frame do
|
|
84
122
|
check_box(
|
85
123
|
{position: :absolute, position_hint: [10, 10]},
|
86
124
|
[20, 20],
|
125
|
+
[20, 20, 110, 110],
|
87
126
|
[[[10, 10], [110, 10], [110, 20], [20, 20], [20, 110], [10, 110]]]
|
88
127
|
)
|
89
128
|
end
|
@@ -93,6 +132,7 @@ describe HexaPDF::Layout::Frame do
|
|
93
132
|
{width: 50, height: 50, position: :absolute, position_hint: [10, 10],
|
94
133
|
margin: [10, 20, 30, 40]},
|
95
134
|
[20, 20],
|
135
|
+
[-20, -10, 90, 80],
|
96
136
|
[[[10, 80], [90, 80], [90, 10], [110, 10], [110, 110], [10, 110]]]
|
97
137
|
)
|
98
138
|
end
|
@@ -102,18 +142,21 @@ describe HexaPDF::Layout::Frame do
|
|
102
142
|
it "draws the box on the left side" do
|
103
143
|
check_box({width: 50, height: 50},
|
104
144
|
[10, 60],
|
145
|
+
[10, 60, 110, 110],
|
105
146
|
[[[10, 10], [110, 10], [110, 60], [10, 60]]])
|
106
147
|
end
|
107
148
|
|
108
149
|
it "draws the box on the right side" do
|
109
150
|
check_box({width: 50, height: 50, position_hint: :right},
|
110
151
|
[60, 60],
|
152
|
+
[10, 60, 110, 110],
|
111
153
|
[[[10, 10], [110, 10], [110, 60], [10, 60]]])
|
112
154
|
end
|
113
155
|
|
114
156
|
it "draws the box in the center" do
|
115
157
|
check_box({width: 50, height: 50, position_hint: :center},
|
116
158
|
[35, 60],
|
159
|
+
[10, 60, 110, 110],
|
117
160
|
[[[10, 10], [110, 10], [110, 60], [10, 60]]])
|
118
161
|
end
|
119
162
|
|
@@ -121,7 +164,7 @@ describe HexaPDF::Layout::Frame do
|
|
121
164
|
[:left, :center, :right].each do |hint|
|
122
165
|
it "ignores all margins if the box fills the whole frame, with position hint #{hint}" do
|
123
166
|
check_box({margin: 10, position_hint: hint},
|
124
|
-
[10, 10], [])
|
167
|
+
[10, 10], [10, 10, 110, 110], [])
|
125
168
|
assert_equal(100, @box.width)
|
126
169
|
assert_equal(100, @box.height)
|
127
170
|
end
|
@@ -130,6 +173,7 @@ describe HexaPDF::Layout::Frame do
|
|
130
173
|
"frame's, with position hint #{hint}" do
|
131
174
|
check_box({height: 50, margin: 10, position_hint: hint},
|
132
175
|
[10, 60],
|
176
|
+
[10, 50, 110, 110],
|
133
177
|
[[[10, 10], [110, 10], [110, 50], [10, 50]]])
|
134
178
|
end
|
135
179
|
|
@@ -138,6 +182,7 @@ describe HexaPDF::Layout::Frame do
|
|
138
182
|
remove_area(:top)
|
139
183
|
check_box({height: 50, margin: 10, position_hint: hint},
|
140
184
|
[10, 40],
|
185
|
+
[10, 30, 110, 100],
|
141
186
|
[[[10, 10], [110, 10], [110, 30], [10, 30]]])
|
142
187
|
assert_equal(100, @box.width)
|
143
188
|
end
|
@@ -147,6 +192,7 @@ describe HexaPDF::Layout::Frame do
|
|
147
192
|
remove_area(:left)
|
148
193
|
check_box({height: 50, margin: 10, position_hint: hint},
|
149
194
|
[30, 60],
|
195
|
+
[10, 50, 110, 110],
|
150
196
|
[[[20, 10], [110, 10], [110, 50], [20, 50]]])
|
151
197
|
assert_equal(80, @box.width)
|
152
198
|
end
|
@@ -156,6 +202,7 @@ describe HexaPDF::Layout::Frame do
|
|
156
202
|
remove_area(:right)
|
157
203
|
check_box({height: 50, margin: 10, position_hint: hint},
|
158
204
|
[10, 60],
|
205
|
+
[10, 50, 110, 110],
|
159
206
|
[[[10, 10], [100, 10], [100, 50], [10, 50]]])
|
160
207
|
assert_equal(80, @box.width)
|
161
208
|
end
|
@@ -164,6 +211,7 @@ describe HexaPDF::Layout::Frame do
|
|
164
211
|
it "perfectly centers a box if possible, margins ignored" do
|
165
212
|
check_box({width: 50, height: 10, margin: [10, 10, 10, 20], position_hint: :center},
|
166
213
|
[35, 100],
|
214
|
+
[10, 90, 110, 110],
|
167
215
|
[[[10, 10], [110, 10], [110, 90], [10, 90]]])
|
168
216
|
end
|
169
217
|
|
@@ -171,6 +219,7 @@ describe HexaPDF::Layout::Frame do
|
|
171
219
|
remove_area(:left, :right)
|
172
220
|
check_box({width: 40, height: 10, margin: [10, 10, 10, 20], position_hint: :center},
|
173
221
|
[40, 100],
|
222
|
+
[10, 90, 110, 110],
|
174
223
|
[[[20, 10], [100, 10], [100, 90], [20, 90]]])
|
175
224
|
end
|
176
225
|
|
@@ -178,6 +227,7 @@ describe HexaPDF::Layout::Frame do
|
|
178
227
|
remove_area(:left, :right)
|
179
228
|
check_box({width: 20, height: 10, margin: [10, 10, 10, 40], position_hint: :center},
|
180
229
|
[65, 100],
|
230
|
+
[10, 90, 110, 110],
|
181
231
|
[[[20, 10], [100, 10], [100, 90], [20, 90]]])
|
182
232
|
end
|
183
233
|
end
|
@@ -187,18 +237,21 @@ describe HexaPDF::Layout::Frame do
|
|
187
237
|
it "draws the box on the left side" do
|
188
238
|
check_box({width: 50, height: 50, position: :float},
|
189
239
|
[10, 60],
|
240
|
+
[10, 60, 60, 110],
|
190
241
|
[[[10, 10], [110, 10], [110, 110], [60, 110], [60, 60], [10, 60]]])
|
191
242
|
end
|
192
243
|
|
193
244
|
it "draws the box on the right side" do
|
194
245
|
check_box({width: 50, height: 50, position: :float, position_hint: :right},
|
195
246
|
[60, 60],
|
247
|
+
[60, 60, 110, 110],
|
196
248
|
[[[10, 10], [110, 10], [110, 60], [60, 60], [60, 110], [10, 110]]])
|
197
249
|
end
|
198
250
|
|
199
251
|
it "draws the box in the center" do
|
200
252
|
check_box({width: 50, height: 50, position: :float, position_hint: :center},
|
201
253
|
[35, 60],
|
254
|
+
[35, 60, 85, 110],
|
202
255
|
[[[10, 10], [110, 10], [110, 110], [85, 110], [85, 60], [35, 60],
|
203
256
|
[35, 110], [10, 110]]])
|
204
257
|
end
|
@@ -207,7 +260,7 @@ describe HexaPDF::Layout::Frame do
|
|
207
260
|
[:left, :center, :right].each do |hint|
|
208
261
|
it "ignores all margins if the box fills the whole frame, with position hint #{hint}" do
|
209
262
|
check_box({margin: 10, position: :float, position_hint: hint},
|
210
|
-
[10, 10], [])
|
263
|
+
[10, 10], [10, 10, 110, 110], [])
|
211
264
|
assert_equal(100, @box.width)
|
212
265
|
assert_equal(100, @box.height)
|
213
266
|
end
|
@@ -216,6 +269,7 @@ describe HexaPDF::Layout::Frame do
|
|
216
269
|
it "ignores the left, but not the right margin if aligned left to the frame border" do
|
217
270
|
check_box({width: 50, height: 50, margin: 10, position: :float, position_hint: :left},
|
218
271
|
[10, 60],
|
272
|
+
[10, 50, 70, 110],
|
219
273
|
[[[10, 10], [110, 10], [110, 110], [70, 110], [70, 50], [10, 50]]])
|
220
274
|
end
|
221
275
|
|
@@ -223,12 +277,14 @@ describe HexaPDF::Layout::Frame do
|
|
223
277
|
remove_area(:left)
|
224
278
|
check_box({width: 50, height: 50, margin: 10, position: :float, position_hint: :left},
|
225
279
|
[30, 60],
|
280
|
+
[20, 50, 90, 110],
|
226
281
|
[[[20, 10], [110, 10], [110, 110], [90, 110], [90, 50], [20, 50]]])
|
227
282
|
end
|
228
283
|
|
229
284
|
it "uses the left and the right margin if aligned center" do
|
230
285
|
check_box({width: 50, height: 50, margin: 10, position: :float, position_hint: :center},
|
231
286
|
[35, 60],
|
287
|
+
[25, 50, 95, 110],
|
232
288
|
[[[10, 10], [110, 10], [110, 110], [95, 110], [95, 50], [25, 50],
|
233
289
|
[25, 110], [10, 110]]])
|
234
290
|
end
|
@@ -236,6 +292,7 @@ describe HexaPDF::Layout::Frame do
|
|
236
292
|
it "ignores the right, but not the left margin if aligned right to the frame border" do
|
237
293
|
check_box({width: 50, height: 50, margin: 10, position: :float, position_hint: :right},
|
238
294
|
[60, 60],
|
295
|
+
[50, 50, 110, 110],
|
239
296
|
[[[10, 10], [110, 10], [110, 50], [50, 50], [50, 110], [10, 110]]])
|
240
297
|
end
|
241
298
|
|
@@ -243,6 +300,7 @@ describe HexaPDF::Layout::Frame do
|
|
243
300
|
remove_area(:right)
|
244
301
|
check_box({width: 50, height: 50, margin: 10, position: :float, position_hint: :right},
|
245
302
|
[40, 60],
|
303
|
+
[30, 50, 100, 110],
|
246
304
|
[[[10, 10], [100, 10], [100, 50], [30, 50], [30, 110], [10, 110]]])
|
247
305
|
end
|
248
306
|
end
|
@@ -250,35 +308,48 @@ describe HexaPDF::Layout::Frame do
|
|
250
308
|
|
251
309
|
describe "flowing boxes" do
|
252
310
|
it "flows inside the frame's outline" do
|
253
|
-
check_box({width: 10, height: 20, position: :flow},
|
311
|
+
check_box({width: 10, height: 20, margin: 10, position: :flow},
|
254
312
|
[0, 90],
|
255
|
-
[
|
313
|
+
[10, 80, 110, 110],
|
314
|
+
[[[10, 10], [110, 10], [110, 80], [10, 80]]])
|
256
315
|
end
|
257
|
-
end
|
258
316
|
|
259
|
-
|
260
|
-
|
261
|
-
|
317
|
+
it "uses position=default if the box indicates it doesn't support flowing contents" do
|
318
|
+
check_box({width: 10, height: 20, margin: 10, position: :flow, doesnt_support_position_flow: true},
|
319
|
+
[10, 90],
|
320
|
+
[10, 80, 110, 110],
|
321
|
+
[[[10, 10], [110, 10], [110, 80], [10, 80]]])
|
322
|
+
end
|
262
323
|
end
|
263
324
|
|
264
325
|
it "can't fit the box if there is no available space" do
|
265
326
|
@frame.remove_area(Geom2D::Polygon([0, 0], [110, 0], [110, 110], [0, 110]))
|
266
327
|
box = HexaPDF::Layout::Box.create
|
267
|
-
refute(@frame.fit(box))
|
328
|
+
refute(@frame.fit(box).success?)
|
268
329
|
end
|
269
330
|
|
270
|
-
it "
|
271
|
-
|
272
|
-
box
|
273
|
-
|
331
|
+
it "handles (but doesn't draw) the box if the its height or width is zero" do
|
332
|
+
result = Minitest::Mock.new
|
333
|
+
box = Minitest::Mock.new
|
334
|
+
|
335
|
+
result.expect(:box, box)
|
336
|
+
box.expect(:height, 0)
|
337
|
+
@frame.draw(@canvas, result)
|
338
|
+
|
339
|
+
result.expect(:box, box)
|
340
|
+
box.expect(:height, 5)
|
341
|
+
result.expect(:box, box)
|
342
|
+
box.expect(:width, 0)
|
343
|
+
@frame.draw(@canvas, result)
|
344
|
+
|
345
|
+
result.verify
|
274
346
|
end
|
275
347
|
end
|
276
348
|
|
277
349
|
describe "split" do
|
278
350
|
it "splits the box if necessary" do
|
279
351
|
box = HexaPDF::Layout::Box.create(width: 10, height: 10)
|
280
|
-
assert_equal([
|
281
|
-
assert_nil(@frame.instance_variable_get(:@fit_data).box)
|
352
|
+
assert_equal([box, nil], @frame.split(@frame.fit(box)))
|
282
353
|
end
|
283
354
|
end
|
284
355
|
|
@@ -348,17 +419,7 @@ describe HexaPDF::Layout::Frame do
|
|
348
419
|
frame.remove_area(Geom2D::PolygonSet(top_cut, left_cut))
|
349
420
|
|
350
421
|
check_regions(frame, [[0, 100, 20, 60], [0, 90, 20, 50], [0, 80, 100, 40],
|
351
|
-
[30,
|
352
|
-
end
|
353
|
-
end
|
354
|
-
|
355
|
-
describe "remove_area" do
|
356
|
-
it "recalculates the contour line only if necessary" do
|
357
|
-
contour = Geom2D::Polygon([10, 10], [10, 90], [90, 90], [90, 10])
|
358
|
-
frame = HexaPDF::Layout::Frame.new(0, 0, 100, 100, contour_line: contour)
|
359
|
-
frame.remove_area(Geom2D::Polygon([0, 0], [20, 0], [20, 100], [0, 100]))
|
360
|
-
assert_equal([[[20, 10], [90, 10], [90, 90], [20, 90]]],
|
361
|
-
frame.contour_line.polygons.map(&:to_a))
|
422
|
+
[30, 80, 70, 80], [0, 20, 100, 20]])
|
362
423
|
end
|
363
424
|
end
|
364
425
|
end
|