hexapdf 0.35.0 → 0.36.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.
@@ -62,41 +62,41 @@ module HexaPDF
62
62
  # * ISO sizes: A0x4, A0x2, A0-A10, B0-B10, C0-C10
63
63
  # * Letter, Legal, Ledger, Tabloid, Executive
64
64
  PAPER_SIZE = {
65
- A0x4: [0, 0, 4768, 6741].freeze,
66
- A0x2: [0, 0, 3370, 4768].freeze,
67
- A0: [0, 0, 2384, 3370].freeze,
68
- A1: [0, 0, 1684, 2384].freeze,
69
- A2: [0, 0, 1191, 1684].freeze,
70
- A3: [0, 0, 842, 1191].freeze,
71
- A4: [0, 0, 595, 842].freeze,
72
- A5: [0, 0, 420, 595].freeze,
73
- A6: [0, 0, 298, 420].freeze,
74
- A7: [0, 0, 210, 298].freeze,
75
- A8: [0, 0, 147, 210].freeze,
76
- A9: [0, 0, 105, 147].freeze,
77
- A10: [0, 0, 74, 105].freeze,
78
- B0: [0, 0, 2835, 4008].freeze,
79
- B1: [0, 0, 2004, 2835].freeze,
80
- B2: [0, 0, 1417, 2004].freeze,
81
- B3: [0, 0, 1001, 1417].freeze,
82
- B4: [0, 0, 709, 1001].freeze,
83
- B5: [0, 0, 499, 709].freeze,
84
- B6: [0, 0, 354, 499].freeze,
85
- B7: [0, 0, 249, 354].freeze,
86
- B8: [0, 0, 176, 249].freeze,
87
- B9: [0, 0, 125, 176].freeze,
88
- B10: [0, 0, 88, 125].freeze,
89
- C0: [0, 0, 2599, 3677].freeze,
90
- C1: [0, 0, 1837, 2599].freeze,
91
- C2: [0, 0, 1298, 1837].freeze,
92
- C3: [0, 0, 918, 1298].freeze,
93
- C4: [0, 0, 649, 918].freeze,
94
- C5: [0, 0, 459, 649].freeze,
95
- C6: [0, 0, 323, 459].freeze,
96
- C7: [0, 0, 230, 323].freeze,
97
- C8: [0, 0, 162, 230].freeze,
98
- C9: [0, 0, 113, 162].freeze,
99
- C10: [0, 0, 79, 113].freeze,
65
+ A0x4: [0, 0, 4767.874016, 6740.787402].freeze,
66
+ A0x2: [0, 0, 3370.393701, 4767.874016].freeze,
67
+ A0: [0, 0, 2383.937008, 3370.393701].freeze,
68
+ A1: [0, 0, 1683.779528, 2383.937008].freeze,
69
+ A2: [0, 0, 1190.551181, 1683.779528].freeze,
70
+ A3: [0, 0, 841.889764, 1190.551181].freeze,
71
+ A4: [0, 0, 595.275591, 841.889764].freeze,
72
+ A5: [0, 0, 419.527559, 595.275591].freeze,
73
+ A6: [0, 0, 297.637795, 419.527559].freeze,
74
+ A7: [0, 0, 209.76378, 297.637795].freeze,
75
+ A8: [0, 0, 147.401575, 209.76378].freeze,
76
+ A9: [0, 0, 104.88189, 147.401575].freeze,
77
+ A10: [0, 0, 73.700787, 104.88189].freeze,
78
+ B0: [0, 0, 2834.645669, 4008.188976].freeze,
79
+ B1: [0, 0, 2004.094488, 2834.645669].freeze,
80
+ B2: [0, 0, 1417.322835, 2004.094488].freeze,
81
+ B3: [0, 0, 1000.629921, 1417.322835].freeze,
82
+ B4: [0, 0, 708.661417, 1000.629921].freeze,
83
+ B5: [0, 0, 498.897638, 708.661417].freeze,
84
+ B6: [0, 0, 354.330709, 498.897638].freeze,
85
+ B7: [0, 0, 249.448819, 354.330709].freeze,
86
+ B8: [0, 0, 175.748031, 249.448819].freeze,
87
+ B9: [0, 0, 124.724409, 175.748031].freeze,
88
+ B10: [0, 0, 87.874016, 124.724409].freeze,
89
+ C0: [0, 0, 2599.370079, 3676.535433].freeze,
90
+ C1: [0, 0, 1836.850394, 2599.370079].freeze,
91
+ C2: [0, 0, 1298.267717, 1836.850394].freeze,
92
+ C3: [0, 0, 918.425197, 1298.267717].freeze,
93
+ C4: [0, 0, 649.133858, 918.425197].freeze,
94
+ C5: [0, 0, 459.212598, 649.133858].freeze,
95
+ C6: [0, 0, 323.149606, 459.212598].freeze,
96
+ C7: [0, 0, 229.606299, 323.149606].freeze,
97
+ C8: [0, 0, 161.574803, 229.606299].freeze,
98
+ C9: [0, 0, 113.385827, 161.574803].freeze,
99
+ C10: [0, 0, 79.370079, 113.385827].freeze,
100
100
  Letter: [0, 0, 612, 792].freeze,
101
101
  Legal: [0, 0, 612, 1008].freeze,
102
102
  Ledger: [0, 0, 792, 1224].freeze,
@@ -0,0 +1,66 @@
1
+ # -*- encoding: utf-8; frozen_string_literal: true -*-
2
+ #
3
+ #--
4
+ # This file is part of HexaPDF.
5
+ #
6
+ # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
+ #
9
+ # HexaPDF is free software: you can redistribute it and/or modify it
10
+ # under the terms of the GNU Affero General Public License version 3 as
11
+ # published by the Free Software Foundation with the addition of the
12
+ # following permission added to Section 15 as permitted in Section 7(a):
13
+ # FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
14
+ # THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
15
+ # INFRINGEMENT OF THIRD PARTY RIGHTS.
16
+ #
17
+ # HexaPDF is distributed in the hope that it will be useful, but WITHOUT
18
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
20
+ # License for more details.
21
+ #
22
+ # You should have received a copy of the GNU Affero General Public License
23
+ # along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
24
+ #
25
+ # The interactive user interfaces in modified source and object code
26
+ # versions of HexaPDF must display Appropriate Legal Notices, as required
27
+ # under Section 5 of the GNU Affero General Public License version 3.
28
+ #
29
+ # In accordance with Section 7(b) of the GNU Affero General Public
30
+ # License, a covered work must retain the producer line in every PDF that
31
+ # is created or manipulated using HexaPDF.
32
+ #
33
+ # If the GNU Affero General Public License doesn't fit your need,
34
+ # commercial licenses are available at <https://gettalong.at/hexapdf/>.
35
+ #++
36
+
37
+ require 'geom2d/utils'
38
+
39
+ module HexaPDF
40
+ module Utils
41
+
42
+ # The precision with which to compare floating point numbers.
43
+ #
44
+ # This is chosen with respect to precision that is used for serializing floating point numbers.
45
+ EPSILON = 1e-6
46
+
47
+ # Best effort of setting Geom2D's precision to the one used by HexaPDF.
48
+ ::Geom2D::Utils.precision = EPSILON
49
+
50
+ module_function
51
+
52
+ private
53
+
54
+ # Compares two floats whether they are equal using the FLOAT_EPSILON precision.
55
+ def float_equal(a, b)
56
+ (a - b).abs < EPSILON
57
+ end
58
+
59
+ # Compares two floats like the <=> operator but using the FLOAT_EPSILON precision for detecting
60
+ # whether they are equal.
61
+ def float_compare(a, b)
62
+ (a - b).abs < EPSILON ? 0 : a <=> b
63
+ end
64
+
65
+ end
66
+ end
@@ -37,6 +37,6 @@
37
37
  module HexaPDF
38
38
 
39
39
  # The version of HexaPDF.
40
- VERSION = '0.35.0'
40
+ VERSION = '0.36.0'
41
41
 
42
42
  end
@@ -39,7 +39,7 @@ describe HexaPDF::Content::CanvasComposer do
39
39
  @composer.draw_box(create_box)
40
40
  assert_operators(@composer.canvas.contents,
41
41
  [[:save_graphics_state],
42
- [:concatenate_matrix, [1, 0, 0, 1, 0, 742]],
42
+ [:concatenate_matrix, [1, 0, 0, 1, 0, 741.889764]],
43
43
  [:restore_graphics_state],
44
44
  [:save_graphics_state],
45
45
  [:concatenate_matrix, [1, 0, 0, 1, 0, 0]],
@@ -58,10 +58,10 @@ describe HexaPDF::Content::CanvasComposer do
58
58
  [:concatenate_matrix, [1, 0, 0, 1, 0, 0]],
59
59
  [:restore_graphics_state],
60
60
  [:save_graphics_state],
61
- [:concatenate_matrix, [1, 0, 0, 1, 400, 742]],
61
+ [:concatenate_matrix, [1, 0, 0, 1, 400, 741.889764]],
62
62
  [:restore_graphics_state],
63
63
  [:save_graphics_state],
64
- [:concatenate_matrix, [1, 0, 0, 1, 400, 642]],
64
+ [:concatenate_matrix, [1, 0, 0, 1, 400, 641.889764]],
65
65
  [:restore_graphics_state]])
66
66
  end
67
67
 
@@ -70,10 +70,10 @@ describe HexaPDF::Content::CanvasComposer do
70
70
  @composer.draw_box(create_box(width: 400, height: 100))
71
71
  assert_operators(@composer.canvas.contents,
72
72
  [[:save_graphics_state],
73
- [:concatenate_matrix, [1, 0, 0, 1, 0, 742]],
73
+ [:concatenate_matrix, [1, 0, 0, 1, 0, 741.889764]],
74
74
  [:restore_graphics_state],
75
75
  [:save_graphics_state],
76
- [:concatenate_matrix, [1, 0, 0, 1, 0, 642]],
76
+ [:concatenate_matrix, [1, 0, 0, 1, 0, 641.889764]],
77
77
  [:restore_graphics_state]])
78
78
  end
79
79
 
@@ -175,6 +175,12 @@ describe HexaPDF::Document::Layout do
175
175
  assert_equal(2, box.children.size)
176
176
  end
177
177
 
178
+ it "uses the provided block as drawing block for the base box class if name=:base" do
179
+ block = proc {}
180
+ box = @layout.box(width: 100, &block)
181
+ assert_equal(block, box.instance_variable_get(:@draw_block))
182
+ end
183
+
178
184
  it "fails if the name is not registered" do
179
185
  assert_raises(HexaPDF::Error) { @layout.box(:unknown) }
180
186
  end
@@ -17,20 +17,20 @@ describe HexaPDF::Document::Pages do
17
17
  describe "create" do
18
18
  it "uses the defaults from the configuration for missing arguments" do
19
19
  page = @doc.pages.create
20
- assert_equal([0, 0, 595, 842], page.box(:media).value)
20
+ assert_equal([0, 0, 595.275591, 841.889764], page.box(:media).value)
21
21
  end
22
22
 
23
23
  it "allows specifying a reference to a predefined page size" do
24
24
  page = @doc.pages.create(media_box: :A3)
25
- assert_equal([0, 0, 842, 1191], page.box(:media).value)
25
+ assert_equal([0, 0, 841.889764, 1190.551181], page.box(:media).value)
26
26
  end
27
27
 
28
28
  it "allows specifying the orientation for a predefined page size" do
29
29
  page = @doc.pages.create(media_box: :A4, orientation: :landscape)
30
- assert_equal([0, 0, 842, 595], page.box(:media).value)
30
+ assert_equal([0, 0, 841.889764, 595.275591], page.box(:media).value)
31
31
 
32
32
  page = @doc.pages.create(orientation: :landscape)
33
- assert_equal([0, 0, 842, 595], page.box(:media).value)
33
+ assert_equal([0, 0, 841.889764, 595.275591], page.box(:media).value)
34
34
  end
35
35
 
36
36
  it "allows using a media box array" do
@@ -54,7 +54,7 @@ describe HexaPDF::Document::Pages do
54
54
  it "adds a new empty page with the given page format" do
55
55
  page = @doc.pages.add(:A4, orientation: :landscape)
56
56
  assert_same(page, @doc.pages[0])
57
- assert_equal([0, 0, 842, 595], @doc.pages[0].box(:media).value)
57
+ assert_equal([0, 0, 841.889764, 595.275591], @doc.pages[0].box(:media).value)
58
58
  end
59
59
 
60
60
  it "adds the given page to the end" do
@@ -5,6 +5,12 @@ require 'hexapdf/document'
5
5
  require 'hexapdf/layout/box'
6
6
 
7
7
  describe HexaPDF::Layout::Box do
8
+ before do
9
+ @frame = Object.new
10
+ def @frame.x; 0; end
11
+ def @frame.y; 100; end
12
+ end
13
+
8
14
  def create_box(**args, &block)
9
15
  HexaPDF::Layout::Box.new(**args, &block)
10
16
  end
@@ -70,15 +76,13 @@ describe HexaPDF::Layout::Box do
70
76
  end
71
77
 
72
78
  describe "fit" do
73
- before do
74
- @frame = Object.new
75
- end
76
-
77
79
  it "fits a fixed sized box" do
78
- box = create_box(width: 50, height: 50)
80
+ box = create_box(width: 50, height: 50, style: {padding: 5})
79
81
  assert(box.fit(100, 100, @frame))
80
82
  assert_equal(50, box.width)
81
83
  assert_equal(50, box.height)
84
+ assert_equal(5, box.instance_variable_get(:@fit_x))
85
+ assert_equal(55, box.instance_variable_get(:@fit_y))
82
86
  end
83
87
 
84
88
  it "uses the maximum available width" do
@@ -95,53 +99,82 @@ describe HexaPDF::Layout::Box do
95
99
  assert_equal(100, box.height)
96
100
  end
97
101
 
102
+ it "uses float comparison" do
103
+ box = create_box(width: 50.0000002, height: 49.9999996)
104
+ assert(box.fit(50, 50, @frame))
105
+ assert_equal(50.0000002, box.width)
106
+ assert_equal(49.9999996, box.height)
107
+ end
108
+
98
109
  it "returns false if the box doesn't fit" do
99
110
  box = create_box(width: 101)
100
111
  refute(box.fit(100, 100, @frame))
101
112
  end
113
+
114
+ it "can use the #content_width/#content_height helper methods" do
115
+ box = create_box
116
+ box.define_singleton_method(:fit_content) do |aw, ah, frame|
117
+ update_content_width { 10 }
118
+ update_content_height { 20 }
119
+ true
120
+ end
121
+ assert(box.fit(100, 100, @frame))
122
+ assert_equal(10, box.width)
123
+ assert_equal(20, box.height)
124
+
125
+ box = create_box(width: 30, height: 50)
126
+ box.define_singleton_method(:fit_content) do |aw, ah, frame|
127
+ update_content_width { 10 }
128
+ update_content_height { 20 }
129
+ true
130
+ end
131
+ assert(box.fit(100, 100, @frame))
132
+ assert_equal(30, box.width)
133
+ assert_equal(50, box.height)
134
+ end
102
135
  end
103
136
 
104
137
  describe "split" do
105
138
  before do
106
139
  @box = create_box(width: 100, height: 100)
107
- @box.fit(100, 100, nil)
140
+ @box.fit(100, 100, @frame)
108
141
  end
109
142
 
110
143
  it "doesn't need to be split if it completely fits" do
111
- assert_equal([@box, nil], @box.split(100, 100, nil))
144
+ assert_equal([@box, nil], @box.split(100, 100, @frame))
112
145
  end
113
146
 
114
147
  it "can't be split if it doesn't (completely) fit and its width is greater than the available width" do
115
148
  @box.fit(90, 100, nil)
116
- assert_equal([nil, @box], @box.split(50, 150, nil))
149
+ assert_equal([nil, @box], @box.split(50, 150, @frame))
117
150
  end
118
151
 
119
152
  it "can't be split if it doesn't (completely) fit and its height is greater than the available height" do
120
153
  @box.fit(90, 100, nil)
121
- assert_equal([nil, @box], @box.split(150, 50, nil))
154
+ assert_equal([nil, @box], @box.split(150, 50, @frame))
122
155
  end
123
156
 
124
157
  it "can't be split if it doesn't (completely) fit and its content width is zero" do
125
158
  box = create_box(width: 0, height: 100)
126
- assert_equal([nil, box], box.split(150, 150, nil))
159
+ assert_equal([nil, box], box.split(150, 150, @frame))
127
160
  end
128
161
 
129
162
  it "can't be split if it doesn't (completely) fit and its content height is zero" do
130
163
  box = create_box(width: 100, height: 0)
131
- assert_equal([nil, box], box.split(150, 150, nil))
164
+ assert_equal([nil, box], box.split(150, 150, @frame))
132
165
  end
133
166
 
134
167
  it "can't be split if it doesn't (completely) fit as the default implementation " \
135
168
  "knows nothing about the content" do
136
169
  @box.style.position = :flow # make sure we would generally be splitable
137
170
  @box.fit(90, 100, nil)
138
- assert_equal([nil, @box], @box.split(150, 150, nil))
171
+ assert_equal([nil, @box], @box.split(150, 150, @frame))
139
172
  end
140
173
  end
141
174
 
142
175
  it "can create a cloned box for splitting" do
143
176
  box = create_box
144
- box.fit(100, 100, nil)
177
+ box.fit(100, 100, @frame)
145
178
  cloned_box = box.send(:create_split_box)
146
179
  assert(cloned_box.split_box?)
147
180
  refute(cloned_box.instance_variable_get(:@fit_successful))
@@ -192,19 +192,19 @@ describe HexaPDF::Layout::ColumnBox do
192
192
  end
193
193
 
194
194
  it "takes a different final location into account" do
195
- box = create_box(children: @fixed_size_boxes[0, 2])
195
+ box = create_box(children: @fixed_size_boxes[0, 2], style: {padding: [2, 4, 6, 8]})
196
196
  box.fit(100, 100, @frame)
197
197
  box.draw(@canvas, 20, 10)
198
198
  operators = [
199
199
  [:save_graphics_state],
200
- [:concatenate_matrix, [1, 0, 0, 1, 20, -80]],
200
+ [:concatenate_matrix, [1, 0, 0, 1, 20, -72]],
201
201
  [:save_graphics_state],
202
- [:concatenate_matrix, [1, 0, 0, 1, 0, 90]],
202
+ [:concatenate_matrix, [1, 0, 0, 1, 8, 88]],
203
203
  [:move_to, [0, 0]],
204
204
  [:end_path],
205
205
  [:restore_graphics_state],
206
206
  [:save_graphics_state],
207
- [:concatenate_matrix, [1, 0, 0, 1, 55, 90]],
207
+ [:concatenate_matrix, [1, 0, 0, 1, 57, 88]],
208
208
  [:move_to, [0, 0]],
209
209
  [:end_path],
210
210
  [:restore_graphics_state],
@@ -0,0 +1,84 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/document'
5
+ require 'hexapdf/layout/container_box'
6
+
7
+ describe HexaPDF::Layout::ContainerBox do
8
+ before do
9
+ @doc = HexaPDF::Document.new
10
+ @frame = HexaPDF::Layout::Frame.new(0, 0, 100, 100)
11
+ end
12
+
13
+ def create_box(children, **kwargs)
14
+ HexaPDF::Layout::ContainerBox.new(children: Array(children), **kwargs)
15
+ end
16
+
17
+ def check_box(box, width, height, fit_pos = nil)
18
+ assert(box.fit(@frame.available_width, @frame.available_height, @frame), "box didn't fit")
19
+ assert_equal(width, box.width, "box width")
20
+ assert_equal(height, box.height, "box height")
21
+ if fit_pos
22
+ box_fitter = box.instance_variable_get(:@box_fitter)
23
+ assert_equal(fit_pos.size, box_fitter.fit_results.size)
24
+ fit_pos.each_with_index do |(x, y), index|
25
+ assert_equal(x, box_fitter.fit_results[index].x, "result[#{index}].x")
26
+ assert_equal(y, box_fitter.fit_results[index].y, "result[#{index}].y")
27
+ end
28
+ end
29
+ end
30
+
31
+ describe "empty?" do
32
+ it "is empty if nothing is fit yet" do
33
+ assert(create_box([]).empty?)
34
+ end
35
+
36
+ it "is empty if no box fits" do
37
+ box = create_box(@doc.layout.box(width: 110))
38
+ box.fit(@frame.available_width, @frame.available_height, @frame)
39
+ assert(box.empty?)
40
+ end
41
+
42
+ it "is not empty if at least one box fits" do
43
+ box = create_box(@doc.layout.box(width: 50, height: 20))
44
+ check_box(box, 100, 20)
45
+ refute(box.empty?)
46
+ end
47
+ end
48
+
49
+ describe "fit_content" do
50
+ it "fits the children according to their mask_mode, valign, and align style properties" do
51
+ box = create_box([@doc.layout.box(height: 20),
52
+ @doc.layout.box(height: 20, style: {valign: :bottom, mask_mode: :fill_horizontal}),
53
+ @doc.layout.box(width: 20, style: {align: :right, mask_mode: :fill_vertical})])
54
+ check_box(box, 100, 100, [[0, 80], [0, 0], [80, 20]])
55
+ end
56
+
57
+ it "respects the initially set width/height as well as border/padding" do
58
+ box = create_box(@doc.layout.box(height: 20), height: 50, width: 40,
59
+ style: {padding: 2, border: {width: 3}})
60
+ check_box(box, 40, 50, [[5, 75]])
61
+ end
62
+ end
63
+
64
+ describe "draw_content" do
65
+ before do
66
+ @canvas = @doc.pages.add.canvas
67
+ end
68
+
69
+ it "draws the result onto the canvas" do
70
+ child_box = @doc.layout.box(height: 20) do |canvas, b|
71
+ canvas.line(0, 0, b.content_width, b.content_height).end_path
72
+ end
73
+ box = create_box(child_box)
74
+ box.fit(100, 100, @frame)
75
+ box.draw(@canvas, 0, 50)
76
+ assert_operators(@canvas.contents, [[:save_graphics_state],
77
+ [:concatenate_matrix, [1, 0, 0, 1, 0, 50]],
78
+ [:move_to, [0, 0]],
79
+ [:line_to, [100, 20]],
80
+ [:end_path],
81
+ [:restore_graphics_state]])
82
+ end
83
+ end
84
+ end
@@ -13,10 +13,11 @@ describe HexaPDF::Layout::Frame::FitResult do
13
13
  result = HexaPDF::Layout::Frame::FitResult.new(box)
14
14
  result.mask = Geom2D::Rectangle(0, 0, 20, 20)
15
15
  result.x = result.y = 0
16
- result.draw(canvas)
16
+ result.draw(canvas, dx: 10, dy: 15)
17
17
  assert_equal(<<~CONTENTS, canvas.contents)
18
18
  /OC /P1 BDC
19
19
  q
20
+ 1 0 0 1 10 15 cm
20
21
  0.0 0.501961 0.0 rg
21
22
  0.0 0.392157 0.0 RG
22
23
  /GS1 gs
@@ -25,7 +26,7 @@ describe HexaPDF::Layout::Frame::FitResult do
25
26
  Q
26
27
  EMC
27
28
  q
28
- 1 0 0 1 0 0 cm
29
+ 1 0 0 1 10 15 cm
29
30
  Q
30
31
  CONTENTS
31
32
  ocg = doc.optional_content.ocgs.first
@@ -35,7 +35,7 @@ describe HexaPDF::Layout::PageStyle do
35
35
  istyle.next_style = :other
36
36
  end
37
37
  page = style.create_page(@doc)
38
- assert_equal([0, 0, 595, 842], page.box(:media))
38
+ assert_equal([0, 0, 595.275591, 841.889764], page.box(:media))
39
39
  assert_equal("0 0 10 10 re\nS\n", page.contents)
40
40
  assert_equal(:frame, style.frame)
41
41
  assert_equal(:other, style.next_style)
@@ -54,8 +54,8 @@ describe HexaPDF::Layout::PageStyle do
54
54
  assert_kind_of(HexaPDF::Layout::Frame, style.frame)
55
55
  assert_equal(36, style.frame.left)
56
56
  assert_equal(36, style.frame.bottom)
57
- assert_equal(523, style.frame.width)
58
- assert_equal(770, style.frame.height)
57
+ assert_equal(523.275591, style.frame.width)
58
+ assert_equal(769.889764, style.frame.height)
59
59
  end
60
60
  end
61
61
 
@@ -65,7 +65,7 @@ describe HexaPDF::Layout::PageStyle do
65
65
  frame = style.create_frame(style.create_page(doc), [15, 10])
66
66
  assert_equal(10, frame.left)
67
67
  assert_equal(15, frame.bottom)
68
- assert_equal(575, frame.width)
69
- assert_equal(812, frame.height)
68
+ assert_equal(575.275591, frame.width)
69
+ assert_equal(811.889764, frame.height)
70
70
  end
71
71
  end
@@ -16,8 +16,8 @@ describe HexaPDF::Composer do
16
16
  assert_kind_of(HexaPDF::Type::Page, @composer.page)
17
17
  assert_equal(36, @composer.frame.left)
18
18
  assert_equal(36, @composer.frame.bottom)
19
- assert_equal(523, @composer.frame.width)
20
- assert_equal(770, @composer.frame.height)
19
+ assert_equal(523.275591, @composer.frame.width)
20
+ assert_equal(769.889764, @composer.frame.height)
21
21
  assert_kind_of(HexaPDF::Layout::Style, @composer.style(:base))
22
22
  end
23
23
 
@@ -28,15 +28,15 @@ describe HexaPDF::Composer do
28
28
 
29
29
  it "allows the customization of the page orientation" do
30
30
  composer = HexaPDF::Composer.new(page_orientation: :landscape)
31
- assert_equal([0, 0, 842, 595], composer.page.box.value)
31
+ assert_equal([0, 0, 841.889764, 595.275591], composer.page.box.value)
32
32
  end
33
33
 
34
34
  it "allows the customization of the margin" do
35
35
  composer = HexaPDF::Composer.new(margin: [100, 80, 60, 40])
36
36
  assert_equal(40, composer.frame.left)
37
37
  assert_equal(60, composer.frame.bottom)
38
- assert_equal(475, composer.frame.width)
39
- assert_equal(682, composer.frame.height)
38
+ assert_in_delta(475.275591, composer.frame.width)
39
+ assert_equal(681.889764, composer.frame.height)
40
40
  end
41
41
 
42
42
  it "allows skipping the initial page creation" do
@@ -107,7 +107,7 @@ describe HexaPDF::Composer do
107
107
  end
108
108
 
109
109
  it "returns the current y-position" do
110
- assert_equal(806, @composer.y)
110
+ assert_equal(805.889764, @composer.y)
111
111
  end
112
112
 
113
113
  describe "style" do
@@ -203,7 +203,7 @@ describe HexaPDF::Composer do
203
203
  @composer.draw_box(create_box)
204
204
  assert_operators(@composer.canvas.contents,
205
205
  [[:save_graphics_state],
206
- [:concatenate_matrix, [1, 0, 0, 1, 36, 706]],
206
+ [:concatenate_matrix, [1, 0, 0, 1, 36, 705.889764]],
207
207
  [:restore_graphics_state],
208
208
  [:save_graphics_state],
209
209
  [:concatenate_matrix, [1, 0, 0, 1, 36, 36]],
@@ -232,14 +232,14 @@ describe HexaPDF::Composer do
232
232
  @composer.draw_box(box)
233
233
  assert_operators(first_page_contents,
234
234
  [[:save_graphics_state],
235
- [:concatenate_matrix, [1, 0, 0, 1, 36, 406]],
235
+ [:concatenate_matrix, [1, 0, 0, 1, 36, 405.889764]],
236
236
  [:restore_graphics_state],
237
237
  [:save_graphics_state],
238
- [:concatenate_matrix, [1, 0, 0, 1, 36, 6]],
238
+ [:concatenate_matrix, [1, 0, 0, 1, 36, 5.889764]],
239
239
  [:restore_graphics_state]])
240
240
  assert_operators(@composer.canvas.contents,
241
241
  [[:save_graphics_state],
242
- [:concatenate_matrix, [1, 0, 0, 1, 36, 706]],
242
+ [:concatenate_matrix, [1, 0, 0, 1, 36, 705.889764]],
243
243
  [:restore_graphics_state]])
244
244
  end
245
245
 
@@ -252,14 +252,14 @@ describe HexaPDF::Composer do
252
252
  @composer.draw_box(box)
253
253
  assert_operators(first_page_contents,
254
254
  [[:save_graphics_state],
255
- [:concatenate_matrix, [1, 0, 0, 1, 36, 406]],
255
+ [:concatenate_matrix, [1, 0, 0, 1, 36, 405.889764]],
256
256
  [:restore_graphics_state],
257
257
  [:save_graphics_state],
258
- [:concatenate_matrix, [1, 0, 0, 1, 36, 306]],
258
+ [:concatenate_matrix, [1, 0, 0, 1, 36, 305.889764]],
259
259
  [:restore_graphics_state]])
260
260
  assert_operators(@composer.canvas.contents,
261
261
  [[:save_graphics_state],
262
- [:concatenate_matrix, [1, 0, 0, 1, 36, 406]],
262
+ [:concatenate_matrix, [1, 0, 0, 1, 36, 405.889764]],
263
263
  [:restore_graphics_state]])
264
264
  end
265
265
 
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/utils.rb'
5
+
6
+ describe HexaPDF::Utils do
7
+ include HexaPDF::Utils
8
+
9
+ it "checks floats for equality with a certain precision" do
10
+ assert(float_equal(1.0, 1))
11
+ assert(float_equal(1.0, 1.0000003))
12
+ end
13
+
14
+ it "compares floats like the <=> operator" do
15
+ assert_equal(0, float_compare(1.0, 1))
16
+ assert_equal(0, float_compare(1.0, 1.0000003))
17
+ assert_equal(-1, float_compare(1.0, 1.03))
18
+ assert_equal(1, float_compare(1.0, 0.9997))
19
+ end
20
+ end
@@ -40,7 +40,7 @@ describe HexaPDF::Writer do
40
40
  219
41
41
  %%EOF
42
42
  3 0 obj
43
- <</Producer(HexaPDF version 0.35.0)>>
43
+ <</Producer(HexaPDF version 0.36.0)>>
44
44
  endobj
45
45
  xref
46
46
  3 1
@@ -72,7 +72,7 @@ describe HexaPDF::Writer do
72
72
  141
73
73
  %%EOF
74
74
  6 0 obj
75
- <</Producer(HexaPDF version 0.35.0)>>
75
+ <</Producer(HexaPDF version 0.36.0)>>
76
76
  endobj
77
77
  2 0 obj
78
78
  <</Length 10>>stream
@@ -214,7 +214,7 @@ describe HexaPDF::Writer do
214
214
  <</Type/Page/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<<>>>>
215
215
  endobj
216
216
  5 0 obj
217
- <</Producer(HexaPDF version 0.35.0)>>
217
+ <</Producer(HexaPDF version 0.35.1)>>
218
218
  endobj
219
219
  4 0 obj
220
220
  <</Root 1 0 R/Info 5 0 R/Size 6/Type/XRef/W[1 1 2]/Index[0 6]/Filter/FlateDecode/DecodeParms<</Columns 4/Predictor 12>>/Length 33>>stream