hexapdf-extras 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ea614bc7163af0c86933d2861f6c55fbab0e7a95cb799fd28167823db3f5b476
4
+ data.tar.gz: 2ae5cc1c597b8d6040c3a0f0803328692dad49cc011faf2e903e95758ee35260
5
+ SHA512:
6
+ metadata.gz: e8dc9518929b83e6ca2248fce24d1d0123b328af01e92c5f8831c3cf1ecd47655b640529ca8027aa6705c317e6875a54d701dbbbc3be17a9f0478cf3dc7dc0d3
7
+ data.tar.gz: 9266e72303a8c0a13608e24f74c6e5e47528e3875a198e5cdd1d6ded55dd0131978247b8646645e34019e4764396f5a512f4eb3ffd96d1b0f130723c08293eaf
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ hexapdf-extra - Additional functionality for HexaPDF
2
+ Copyright (C) 2022 Thomas Leitner <t_leitner@gmx.at>
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a
5
+ copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included
13
+ in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,38 @@
1
+ == HexaPDF Extras
2
+
3
+ This library contains additional functionality that is not provided by the main
4
+ {HexaPDF}[https://hexapdf.gettalong.org] library.
5
+
6
+ To use it, just <tt>require 'hexapdf-extras'</tt> and it will update the HexaPDF configuration
7
+ settings to make the various extensions available.
8
+
9
+ Note that you need to install the dependencies of the features you use yourself as they are not
10
+ listed in the gem file!
11
+
12
+ === QR code Generator
13
+
14
+ This extension plugs into the graphic objects and boxes system of HexaPDF and allows one to easily
15
+ create a fully-scalable QR code:
16
+
17
+ require 'hexapdf'
18
+ require 'hexapdf-extras'
19
+
20
+ doc = HexaPDF::Document.new
21
+ canvas = doc.pages.add.canvas
22
+ canvas.draw(:qrcode, at: [100, 100], size: 200, data: "https://hexapdf.gettalong.org")
23
+ doc.write('qrcode.pdf')
24
+
25
+ Underneath the +rqrcode_core+ library is used for actually generating the QR code. This means you
26
+ need to install that library for this extension to work.
27
+
28
+ The +data+ argument can be any data that +rqrcode_core+ understands. The other options understood by
29
+ +rqrcode_core+ are also supported.
30
+
31
+ See
32
+ {HexaPDF::Extras::GraphicObject::QRCode}[https://hexapdf-extras.gettalong.org/api/HexaPDF/Extras/GraphicObject/QRCode.html]
33
+ and
34
+ {HexaPDF::Extras::Layout::QRCodeBox}[https://hexapdf-extras.gettalong.org/api/HexaPDF/Extras/Layout/QRCodeBox.html]
35
+ for details.
36
+
37
+ Note: There was a {bug in poppler}[https://gitlab.freedesktop.org/poppler/poppler/-/issues/1281]
38
+ (already fixed) which leads to invalid rendering in Okular (as of 2022-08-06).
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ require 'rake/clean'
2
+ require 'rake/testtask'
3
+ require 'rubygems/package_task'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << 'test'
7
+ t.test_files = FileList['test/**/*.rb']
8
+ t.verbose = false
9
+ t.warning = true
10
+ end
11
+
12
+ CLOBBER << 'webgen-out'
13
+ CLOBBER << 'webgen-tmp'
14
+
15
+ task default: 'test'
16
+
17
+ spec = eval(File.read('hexapdf-extras.gemspec'), binding, 'hexapdf-extras.gemspec')
18
+ Gem::PackageTask.new(spec) do |pkg|
19
+ pkg.need_zip = true
20
+ pkg.need_tar = true
21
+ end
22
+
23
+ desc "Upload the release to Rubygems"
24
+ task publish_files: [:package] do
25
+ sh "gem push pkg/hexapdf-extras-#{HexaPDF::Extras::VERSION}.gem"
26
+ puts 'done'
27
+ end
28
+
29
+ task :test_all do
30
+ versions = `rbenv versions --bare | grep -i 2.[67]\\\\\\|3.`.split("\n")
31
+ versions.each do |version|
32
+ sh "eval \"$(rbenv init -)\"; rbenv shell #{version} && ruby -v && rake test"
33
+ end
34
+ puts "Looks okay? (enter to continue, Ctrl-c to abort)"
35
+ $stdin.gets
36
+ end
37
+
38
+ desc "Release HexaPDF Extras version #{HexaPDF::Extras::VERSION}"
39
+ task release: [:clobber, :test_all, :package, :publish_files]
40
+
@@ -0,0 +1,206 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rqrcode_core'
4
+
5
+ module HexaPDF
6
+ module Extras
7
+ module GraphicObject
8
+
9
+ # Generates a QR code and renders it using simple PDF canvas graphics.
10
+ #
11
+ # It implements the {HexaPDF graphic object
12
+ # interface}[https://hexapdf.gettalong.org/documentation/reference/api/HexaPDF/Content/GraphicObject/index.html]
13
+ # and can therefore easily be used via the +:qrcode+ name:
14
+ #
15
+ # #>pdf-canvas100
16
+ # canvas.draw(:qrcode, data: 'hello', size: 100)
17
+ #
18
+ # This class relies on {rqrcode_core}[https://github.com/whomwah/rqrcode_core/] to generate
19
+ # the QR code from the given data. All options of rqrcode_core are supported, have a look at
20
+ # their documentation to see the allowed values.
21
+ class QRCode
22
+
23
+ # Creates and configures a new QRCode drawing support object.
24
+ #
25
+ # See #configure for the allowed keyword arguments.
26
+ def self.configure(**kwargs)
27
+ new.configure(**kwargs)
28
+ end
29
+
30
+ # The position of the bottom-left corner of the QR code.
31
+ #
32
+ # Default: [0, 0].
33
+ #
34
+ # Examples:
35
+ #
36
+ # #>pdf-canvas100
37
+ # canvas.draw(:qrcode, data: 'test', size: 30)
38
+ # canvas.draw(:qrcode, data: 'test', size: 20, at: [50, 50])
39
+ attr_accessor :at
40
+
41
+ # The size of the whole rendered QR code.
42
+ #
43
+ # Default: none
44
+ #
45
+ # Examples:
46
+ #
47
+ # #>pdf-canvas100
48
+ # canvas.draw(:qrcode, data: 'test', size: 80, at: [10, 10])
49
+ attr_accessor :size
50
+
51
+ # The color for the dark QR code modules ('pixels')
52
+ #
53
+ # Default: 'black'.
54
+ #
55
+ # Examples:
56
+ #
57
+ # #>pdf-canvas100
58
+ # canvas.draw(:qrcode, data: 'test', size: 100, dark_color: 'green')
59
+ attr_accessor :dark_color
60
+
61
+ # The color for the light QR code modules ('pixels').
62
+ #
63
+ # Default: none (i.e. they are not drawn).
64
+ #
65
+ # Examples:
66
+ #
67
+ # #>pdf-canvas100
68
+ # canvas.draw(:qrcode, data: 'test', size: 100, light_color: 'yellow')
69
+ attr_accessor :light_color
70
+
71
+ # The data for which the QR code should be generated.
72
+ #
73
+ # This is directly passed to rqrcode_core as the +data+ argument.
74
+ #
75
+ # Default: none
76
+ attr_accessor :data
77
+
78
+ # The code size of the the QR code (normally called 'version').
79
+ #
80
+ # This is directly passed to rqrcode_core as the +size+ argument.
81
+ #
82
+ # Default: nil (i.e. let rqrcode_core decide)
83
+ #
84
+ # Examples:
85
+ #
86
+ # #>pdf-canvas100
87
+ # canvas.draw(:qrcode, data: 'test', size: 100, code_size: 10)
88
+ attr_accessor :code_size
89
+
90
+ # The maximum code size of the QR code.
91
+ #
92
+ # This is directly passed to rqrcode_core as the +max_size+ argument.
93
+ #
94
+ # Default: nil (i.e. let rqrcode_core decide)
95
+ #
96
+ # Examples:
97
+ #
98
+ # #>pdf-canvas100
99
+ # canvas.draw(:qrcode, data: 't'*100, size: 100, max_code_size: 10)
100
+ attr_accessor :max_code_size
101
+
102
+ # The error correction level of the QR code.
103
+ #
104
+ # This is directly passed to rqrcode_core as the +level+ argument.
105
+ #
106
+ # Default: nil (i.e. let rqrcode_core decide)
107
+ #
108
+ # Examples:
109
+ #
110
+ # #>pdf-canvas100
111
+ # canvas.draw(:qrcode, data: 'test', size: 100, level: :l)
112
+ attr_accessor :level
113
+
114
+ # The mode of the QR code, i.e. which data it holds.
115
+ #
116
+ # This is directly passed to rqrcode_core as the +mode+ argument.
117
+ #
118
+ # Default: nil (i.e. let rqrcode_core decide)
119
+ #
120
+ # Examples:
121
+ #
122
+ # #>pdf-canvas100
123
+ # canvas.draw(:qrcode, data: 'test', size: 100, mode: :kanji)
124
+ attr_accessor :mode
125
+
126
+ # Creates a QRCode object.
127
+ def initialize
128
+ @data = @size = @code_size = @max_code_size = @level = @mode = nil
129
+ @at = [0, 0]
130
+ @dark_color = 'black'
131
+ @light_color = nil
132
+ end
133
+
134
+ # Configures the QRCode object and returns self.
135
+ #
136
+ # The following arguments are allowed:
137
+ #
138
+ # :at:: The position of the bottom-left corner.
139
+ # :size:: The size of the whole rendered QR code.
140
+ # :dark_color:: The color used for the dark QR code modules ('pixels').
141
+ # :light_color:: The color used for the light QR code modules ('pixels').
142
+ # :data:: The data for the QR code.
143
+ # :code_size:: The code size of the QR code.
144
+ # :max_code_size:: The maximum code size of the QR code.
145
+ # :level:: The error correction level of the QR code
146
+ # :mode:: The mode of the of the QR code.
147
+ #
148
+ # Any arguments not specified are not modified and retain their old value, see the attribute
149
+ # methods for the inital default values.
150
+ def configure(at: nil, size: nil, dark_color: nil, light_color: nil,
151
+ data: nil, code_size: nil, max_code_size: nil, level: nil, mode: nil)
152
+ @at = at if at
153
+ @size = size if size
154
+ @dark_color = dark_color if dark_color
155
+ @light_color = light_color if light_color
156
+ @data = data if data
157
+ @code_size = code_size if code_size
158
+ @max_code_size = max_code_size if max_code_size
159
+ @level = level if level
160
+ @mode = mode if mode
161
+ self
162
+ end
163
+
164
+ # Draws the QRCode object onto the given Canvas, with the bottom-left corner at the position
165
+ # specified by #at and the size specified by #size.
166
+ def draw(canvas)
167
+ qrcode = RQRCodeCore::QRCode.new(data, size: code_size, max_size: max_code_size,
168
+ level: level, mode: mode)
169
+
170
+ canvas.save_graphics_state do
171
+ canvas.translate(*at)
172
+ canvas.fill_color(light_color).rectangle(0, 0, size, size).fill if light_color
173
+
174
+ module_count = qrcode.modules.size
175
+ module_size = size.to_f / module_count
176
+ y_start = size - module_size / 2
177
+ canvas.line_cap_style(:butt)
178
+ canvas.line_width(module_size)
179
+ canvas.stroke_color(dark_color)
180
+
181
+ qrcode.modules.each_with_index do |row, row_index|
182
+ pattern = [0]
183
+ last_is_dark = row[0]
184
+ row.each do |col|
185
+ if col == last_is_dark
186
+ pattern[-1] += module_size
187
+ else
188
+ last_is_dark = !last_is_dark
189
+ pattern << module_size
190
+ end
191
+ end
192
+ pattern.unshift(0) unless row[0]
193
+
194
+ canvas.line_dash_pattern(pattern)
195
+ canvas.line(0, y_start - module_size * row_index,
196
+ size, y_start - module_size * row_index).
197
+ stroke
198
+ end
199
+ end
200
+ end
201
+
202
+ end
203
+
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HexaPDF
4
+ module Extras
5
+ module GraphicObject
6
+ autoload(:QRCode, 'hexapdf/extras/graphic_object/qr_code')
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'hexapdf/layout/box'
4
+
5
+ module HexaPDF
6
+ module Extras
7
+ module Layout
8
+
9
+ # A QRCodeBox object is used for displaying a QR code.
10
+ #
11
+ # The size of the QR code is determined by the width and height of the box (to be exact: by
12
+ # the smaller of the two values). The QR code is always placed at the top left corner of the
13
+ # box.
14
+ #
15
+ # Internally, HexaPDF::Extras::GraphicObject::QRCode is used, so any option except +at+ and
16
+ # +size+ supported there can be used here.
17
+ #
18
+ # Example:
19
+ #
20
+ # #>pdf-composer100
21
+ # composer.box(:qrcode, height: 50, data: 'Test', style: {position: :float})
22
+ # composer.box(:qrcode, width: 20, data: 'Test', dark_color: 'red', style: {position: :float})
23
+ # composer.box(:qrcode, width: 30, height: 50, data: 'Test', dark_color: 'green',
24
+ # style: {position: :float})
25
+ # composer.box(:qrcode, data: 'Test', dark_color: 'blue')
26
+ class QRCodeBox < HexaPDF::Layout::Box
27
+
28
+ # The HexaPDF::Extras::GraphicObject::QRCode object that will be drawn.
29
+ attr_reader :qr_code
30
+
31
+ # Creates a new QRCodeBox object with the given arguments (see
32
+ # HexaPDF::Extras::GraphicObject::QRCode for details).
33
+ #
34
+ # At least +data+ needs to be specified.
35
+ def initialize(dark_color: nil, light_color: nil, data: nil, code_size: nil,
36
+ max_code_size: nil, level: nil, mode: nil, **kwargs)
37
+ super(**kwargs)
38
+ @qr_code = HexaPDF::Extras::GraphicObject::QRCode.configure(
39
+ dark_color: dark_color, light_color: light_color, data: data, code_size: code_size,
40
+ max_code_size: max_code_size, level: level, mode: mode
41
+ )
42
+ end
43
+
44
+ # Fits the QRCode into the given area.
45
+ def fit(available_width, available_height, _frame)
46
+ super
47
+ @width = @height = [@width, @height].min
48
+ @qr_code.size = [content_width, content_height].min
49
+ @fit_successful = (@width <= available_width && @height <= available_height)
50
+ end
51
+
52
+ private
53
+
54
+ # Draws the QR code onto the canvas at position [x, y].
55
+ def draw_content(canvas, x, y)
56
+ @qr_code.at = [x, y]
57
+ canvas.draw(@qr_code)
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HexaPDF
4
+ module Extras
5
+ module Layout
6
+ autoload(:QRCodeBox, 'hexapdf/extras/layout/qr_code_box')
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HexaPDF
4
+ module Extras
5
+ VERSION = '1.0.0'
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'hexapdf/configuration'
4
+
5
+ module HexaPDF
6
+ module Extras
7
+ autoload(:GraphicObject, 'hexapdf/extras/graphic_object')
8
+ autoload(:Layout, 'hexapdf/extras/layout')
9
+ end
10
+ end
11
+
12
+ HexaPDF::DefaultDocumentConfiguration['graphic_object.map'][:qrcode] =
13
+ 'HexaPDF::Extras::GraphicObject::QRCode'
14
+
15
+ HexaPDF::DefaultDocumentConfiguration['layout.boxes.map'][:qrcode] =
16
+ 'HexaPDF::Extras::Layout::QRCodeBox'
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'hexapdf/extras'
@@ -0,0 +1,107 @@
1
+ require 'test_helper'
2
+ require 'hexapdf'
3
+ require 'hexapdf/extras/graphic_object/qr_code'
4
+
5
+ describe HexaPDF::Extras::GraphicObject::QRCode do
6
+ before do
7
+ @obj = HexaPDF::Extras::GraphicObject::QRCode.new
8
+ end
9
+
10
+ it "allows creation via the ::configure method" do
11
+ obj = HexaPDF::Extras::GraphicObject::QRCode.configure(data: 'test')
12
+ assert_equal('test', obj.data)
13
+ end
14
+
15
+ it "creates a default Geom2D drawing support object" do
16
+ [:size, :light_color, :data, :code_size, :max_code_size, :level, :mode].each do |method_name|
17
+ assert_nil(@obj.send(method_name))
18
+ end
19
+ assert_equal([0, 0], @obj.at)
20
+ assert_equal('black', @obj.dark_color)
21
+ end
22
+
23
+ it "allows configuration of the object" do
24
+ @obj.configure(data: 'test', size: 30)
25
+ assert_equal('test', @obj.data)
26
+ assert_equal(30, @obj.size)
27
+ end
28
+
29
+ describe "draw" do
30
+ before do
31
+ doc = HexaPDF::Document.new
32
+ @canvas = doc.pages.add.canvas
33
+ end
34
+
35
+ it "draws a QRCode onto the canvas" do
36
+ @obj.configure(data: 'test', size: 210)
37
+ @obj.draw(@canvas)
38
+ assert_operators(@canvas.contents,
39
+ [[:save_graphics_state],
40
+ [:concatenate_matrix, [1, 0, 0, 1, 0, 0]],
41
+ [:set_line_width, [10]],
42
+ [:set_device_rgb_stroking_color, [0, 0, 0]],
43
+ [:set_line_dash_pattern, [[70, 10, 30, 10, 10, 10, 70], 0]],
44
+ [:move_to, [0, 205]], [:line_to, [210, 205]], [:stroke_path],
45
+ [:set_line_dash_pattern,
46
+ [[10, 50, 10, 10, 20, 40, 10, 50, 10], 0]],
47
+ [:move_to, [0, 195]], [:line_to, [210, 195]], [:stroke_path],
48
+ [:set_line_dash_pattern,
49
+ [[10, 10, 30, 10, 10, 30, 20, 20, 10, 10, 30, 10, 10], 0]],
50
+ [:move_to, [0, 185]], [:line_to, [210, 185]], [:stroke_path],
51
+ [:set_line_dash_pattern,
52
+ [[10, 10, 30, 10, 10, 10, 10, 20, 20, 10, 10, 10, 30, 10, 10], 0]],
53
+ [:move_to, [0, 175]], [:line_to, [210, 175]], [:stroke_path],
54
+ [:set_line_dash_pattern,
55
+ [[10, 10, 30, 10, 10, 10, 10, 20, 10, 20, 10, 10, 30, 10, 10], 0]],
56
+ [:move_to, [0, 165]], [:line_to, [210, 165]], [:stroke_path],
57
+ [:set_line_dash_pattern,
58
+ [[10, 50, 10, 10, 20, 40, 10, 50, 10], 0]],
59
+ [:move_to, [0, 155]], [:line_to, [210, 155]], [:stroke_path],
60
+ [:set_line_dash_pattern,
61
+ [[70, 10, 10, 10, 10, 10, 10, 10, 70], 0]],
62
+ [:move_to, [0, 145]], [:line_to, [210, 145]], [:stroke_path],
63
+ [:set_line_dash_pattern, [[0, 90, 20, 10, 10, 80], 0]],
64
+ [:move_to, [0, 135]], [:line_to, [210, 135]], [:stroke_path],
65
+ [:set_line_dash_pattern,
66
+ [[0, 30, 10, 20, 10, 20, 10, 10, 10, 30, 30, 10, 20], 0]],
67
+ [:move_to, [0, 125]], [:line_to, [210, 125]], [:stroke_path],
68
+ [:set_line_dash_pattern,
69
+ [[0, 30, 20, 20, 20, 30, 10, 10, 20, 30, 20], 0]],
70
+ [:move_to, [0, 115]], [:line_to, [210, 115]], [:stroke_path],
71
+ [:set_line_dash_pattern,
72
+ [[10, 10, 20, 20, 30, 10, 10, 10, 10, 10, 50, 10, 10], 0]],
73
+ [:move_to, [0, 105]], [:line_to, [210, 105]], [:stroke_path],
74
+ [:set_line_dash_pattern,
75
+ [[20, 10, 10, 50, 10, 20, 10, 10, 40, 10, 20], 0]],
76
+ [:move_to, [0, 95]], [:line_to, [210, 95]], [:stroke_path],
77
+ [:set_line_dash_pattern,
78
+ [[20, 30, 20, 10, 30, 40, 10, 10, 10, 10, 20], 0]],
79
+ [:move_to, [0, 85]], [:line_to, [210, 85]], [:stroke_path],
80
+ [:set_line_dash_pattern,
81
+ [[0, 80, 10, 20, 30, 20, 20, 10, 20], 0]],
82
+ [:move_to, [0, 75]], [:line_to, [210, 75]], [:stroke_path],
83
+ [:set_line_dash_pattern,
84
+ [[70, 20, 30, 20, 10, 10, 10, 20, 10, 10], 0]],
85
+ [:move_to, [0, 65]], [:line_to, [210, 65]], [:stroke_path],
86
+ [:set_line_dash_pattern,
87
+ [[10, 50, 10, 20, 20, 10, 10, 10, 10, 40, 10, 10], 0]],
88
+ [:move_to, [0, 55]], [:line_to, [210, 55]], [:stroke_path],
89
+ [:set_line_dash_pattern,
90
+ [[10, 10, 30, 10, 10, 40, 10, 10, 20, 20, 10, 20, 10], 0]],
91
+ [:move_to, [0, 45]], [:line_to, [210, 45]], [:stroke_path],
92
+ [:set_line_dash_pattern,
93
+ [[10, 10, 30, 10, 10, 10, 20, 10, 10, 30, 10, 10, 10, 10, 20], 0]],
94
+ [:move_to, [0, 35]], [:line_to, [210, 35]], [:stroke_path],
95
+ [:set_line_dash_pattern,
96
+ [[10, 10, 30, 10, 10, 50, 20, 10, 10, 20, 10, 10, 10], 0]],
97
+ [:move_to, [0, 25]], [:line_to, [210, 25]], [:stroke_path],
98
+ [:set_line_dash_pattern,
99
+ [[10, 50, 10, 20, 10, 10, 10, 20, 20, 10, 10, 30], 0]],
100
+ [:move_to, [0, 15]], [:line_to, [210, 15]], [:stroke_path],
101
+ [:set_line_dash_pattern,
102
+ [[70, 30, 20, 10, 10, 10, 10, 10, 30, 10], 0]],
103
+ [:move_to, [0, 5]], [:line_to, [210, 5]], [:stroke_path],
104
+ [:restore_graphics_state]])
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,71 @@
1
+ require 'test_helper'
2
+ require 'hexapdf'
3
+ require 'hexapdf/extras/layout/qr_code_box'
4
+
5
+ describe HexaPDF::Extras::Layout::QRCodeBox do
6
+ def create_box(**kwargs)
7
+ HexaPDF::Extras::Layout::QRCodeBox.new(**kwargs)
8
+ end
9
+
10
+ describe "initialize" do
11
+ it "can take the common box arguments" do
12
+ box = create_box(width: 10, height: 15)
13
+ assert_equal(10, box.width)
14
+ assert_equal(15, box.height)
15
+ end
16
+
17
+ it "creates the QRCode graphic object" do
18
+ box = create_box(data: 'test', level: :l)
19
+ assert_equal(:l, box.qr_code.level)
20
+ assert_equal('test', box.qr_code.data)
21
+ end
22
+ end
23
+
24
+ describe "fit" do
25
+ it "uses the smaller value of width/height for the dimensions if smaller than available_width/height" do
26
+ [{width: 10}, {width: 10, height: 50}, {height: 10}, {width: 50, height: 10}].each do |args|
27
+ box = create_box(**args)
28
+ assert(box.fit(100, 100, nil))
29
+ assert_equal(10, box.width)
30
+ assert_equal(10, box.height)
31
+ assert_equal(10, box.qr_code.size)
32
+ end
33
+ end
34
+
35
+ it "uses the smaller value of available_width/height for the dimensions" do
36
+ box = create_box
37
+ assert(box.fit(10, 20, nil))
38
+ assert_equal(10, box.width)
39
+ assert_equal(10, box.height)
40
+ assert_equal(10, box.qr_code.size)
41
+
42
+ assert(box.fit(20, 15, nil))
43
+ assert_equal(15, box.width)
44
+ assert_equal(15, box.height)
45
+ assert_equal(15, box.qr_code.size)
46
+ end
47
+
48
+ it "takes the border and padding into account for the QR code size" do
49
+ box = create_box(style: {padding: [1, 2], border: {width: [3, 4]}})
50
+ assert(box.fit(100, 100, nil))
51
+ assert_equal(88, box.qr_code.size)
52
+
53
+ box = create_box(style: {padding: [2, 1], border: {width: [4, 3]}})
54
+ assert(box.fit(100, 100, nil))
55
+ assert_equal(88, box.qr_code.size)
56
+ end
57
+ end
58
+
59
+ describe "draw" do
60
+ it "draws the qrcode" do
61
+ box = create_box(width: 10)
62
+ box.fit(100, 100, nil)
63
+
64
+ canvas = Minitest::Mock.new
65
+ canvas.expect(:draw, nil, [box.qr_code])
66
+ box.draw(canvas, 5, 7)
67
+ assert_equal([5, 7], box.qr_code.at)
68
+ canvas.verify
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ begin
4
+ require 'simplecov'
5
+ SimpleCov.start do
6
+ minimum_coverage line: 100
7
+ add_filter '/test/'
8
+ end
9
+ rescue LoadError
10
+ puts "No code coverage because simplecov is not installed"
11
+ end
12
+
13
+ gem 'minitest'
14
+ require 'minitest/autorun'
15
+ require 'hexapdf/test_utils'
16
+
17
+ Minitest::Test.make_my_diffs_pretty!
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hexapdf-extras
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Thomas Leitner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-08-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: hexapdf
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.24'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.24'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rqrcode_core
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.2'
41
+ description:
42
+ email: t_leitner@gmx.at
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - LICENSE
48
+ - README.rdoc
49
+ - Rakefile
50
+ - lib/hexapdf-extras.rb
51
+ - lib/hexapdf/extras.rb
52
+ - lib/hexapdf/extras/graphic_object.rb
53
+ - lib/hexapdf/extras/graphic_object/qr_code.rb
54
+ - lib/hexapdf/extras/layout.rb
55
+ - lib/hexapdf/extras/layout/qr_code_box.rb
56
+ - lib/hexapdf/extras/version.rb
57
+ - test/hexapdf/extras/graphic_object/test_qr_code.rb
58
+ - test/hexapdf/extras/layout/test_qr_code_box.rb
59
+ - test/test_helper.rb
60
+ homepage: https://hexapdf-extras.gettalong.org
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '2.5'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubygems_version: 3.1.6
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Additional functionality for HexaPDF
83
+ test_files: []