hexapdf-extras 1.0.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 +7 -0
- data/LICENSE +21 -0
- data/README.rdoc +38 -0
- data/Rakefile +40 -0
- data/lib/hexapdf/extras/graphic_object/qr_code.rb +206 -0
- data/lib/hexapdf/extras/graphic_object.rb +9 -0
- data/lib/hexapdf/extras/layout/qr_code_box.rb +64 -0
- data/lib/hexapdf/extras/layout.rb +9 -0
- data/lib/hexapdf/extras/version.rb +7 -0
- data/lib/hexapdf/extras.rb +16 -0
- data/lib/hexapdf-extras.rb +3 -0
- data/test/hexapdf/extras/graphic_object/test_qr_code.rb +107 -0
- data/test/hexapdf/extras/layout/test_qr_code_box.rb +71 -0
- data/test/test_helper.rb +17 -0
- metadata +83 -0
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,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,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,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
|
data/test/test_helper.rb
ADDED
@@ -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: []
|