qrest 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/lib/qrest/base.rb +13 -0
- data/lib/qrest/bch.rb +57 -0
- data/lib/qrest/bitbuffer.rb +85 -0
- data/lib/qrest/bitstream.rb +27 -0
- data/lib/qrest/demerits.rb +118 -0
- data/lib/qrest/foreign/supplement.rb +51 -0
- data/lib/qrest/formats/eps.rb +65 -0
- data/lib/qrest/formats/svg.rb +77 -0
- data/lib/qrest/formats/xpm.rb +48 -0
- data/lib/qrest/modules.rb +300 -0
- data/lib/qrest/polynomial.rb +136 -0
- data/lib/qrest/rsblocks.rb +143 -0
- data/lib/qrest/segment.rb +210 -0
- data/lib/qrest/version.rb +12 -0
- data/lib/qrest.rb +67 -0
- metadata +56 -0
@@ -0,0 +1,210 @@
|
|
1
|
+
#
|
2
|
+
# qrest/segment.rb -- Segments
|
3
|
+
#
|
4
|
+
|
5
|
+
require "qrest/base"
|
6
|
+
|
7
|
+
|
8
|
+
module QRest
|
9
|
+
|
10
|
+
class Segment
|
11
|
+
|
12
|
+
def initialize data
|
13
|
+
@data = data
|
14
|
+
end
|
15
|
+
|
16
|
+
def write buffer, version
|
17
|
+
buffer.put 1<<self.class::ID, 4
|
18
|
+
buffer.put @data.bytesize, (get_length_in_bits version)
|
19
|
+
end
|
20
|
+
|
21
|
+
def size version
|
22
|
+
4 + (get_length_in_bits version) + (
|
23
|
+
chunk_size, bit_length, extra = cbe
|
24
|
+
num, rest = @data.bytesize.divmod chunk_size
|
25
|
+
r = num * bit_length
|
26
|
+
r += extra if rest.nonzero?
|
27
|
+
r
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def get_length_in_bits version
|
34
|
+
macro_version =
|
35
|
+
case version
|
36
|
+
when 1.. 9 then 0
|
37
|
+
when ..26 then 1
|
38
|
+
when ..40 then 2
|
39
|
+
else raise Error, "Unknown version: #{version}"
|
40
|
+
end
|
41
|
+
self.class::BITS_FOR_MODE[macro_version]
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
@sub = []
|
46
|
+
|
47
|
+
class <<self
|
48
|
+
|
49
|
+
def [] *args, **kwargs
|
50
|
+
new *args, **kwargs
|
51
|
+
end
|
52
|
+
|
53
|
+
def inherited cls
|
54
|
+
@sub.push cls
|
55
|
+
end
|
56
|
+
|
57
|
+
def create data, mode = nil
|
58
|
+
case data
|
59
|
+
when String then
|
60
|
+
if mode then
|
61
|
+
type = @sub.find { |t| mode.to_s == t::NAME }
|
62
|
+
type or raise ArgumentError, "Not a valid segment type: #{mode}"
|
63
|
+
type.new data
|
64
|
+
else
|
65
|
+
@sub.each do |t|
|
66
|
+
break t.new data
|
67
|
+
rescue ArgumentError, NotImplementedError
|
68
|
+
end
|
69
|
+
end
|
70
|
+
when Array then
|
71
|
+
Multi.new data
|
72
|
+
when Segment
|
73
|
+
data
|
74
|
+
else
|
75
|
+
raise ArgumentError, "Data must be a String, an Array, or a Segment"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
class Multi
|
85
|
+
|
86
|
+
def initialize data
|
87
|
+
@segs = data.map! { |s|
|
88
|
+
args =
|
89
|
+
case s
|
90
|
+
when String then s
|
91
|
+
when Hash then [ s[ :data], s[ :mode]]
|
92
|
+
end
|
93
|
+
Segment.create *args
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
def write buffer, version
|
98
|
+
@segs.each { |s| s.write buffer, version }
|
99
|
+
end
|
100
|
+
|
101
|
+
def size version
|
102
|
+
@segs.sum { |s| s.size version }
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
class Numeric < Segment
|
109
|
+
|
110
|
+
NAME = "number"
|
111
|
+
ID = 0
|
112
|
+
BITS_FOR_MODE = [10, 12, 14]
|
113
|
+
|
114
|
+
def initialize data
|
115
|
+
data =~ /[^0-9]/ and raise ArgumentError, "Not numeric: #{data}"
|
116
|
+
super
|
117
|
+
end
|
118
|
+
|
119
|
+
NUMBER_LENGTH = { 3 => 10, 2 => 7, 1 => 4 }
|
120
|
+
|
121
|
+
def write buffer, version
|
122
|
+
super
|
123
|
+
@data.scan /\d{1,3}/ do |chars|
|
124
|
+
buffer.put chars.to_i, NUMBER_LENGTH[ chars.length]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def cbe ; [3, NUMBER_LENGTH[3], NUMBER_LENGTH[ @data.size % 3]||0] ; end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
class Alphanumeric < Segment
|
133
|
+
|
134
|
+
NAME = "alphanumeric"
|
135
|
+
ID = 1
|
136
|
+
BITS_FOR_MODE = [ 9, 11, 13]
|
137
|
+
|
138
|
+
ALPHANUMERIC, = [
|
139
|
+
*("0".."9"), *("A".."Z"), " ", "$", "%", "*", "+", "-", ".", "/", ":",
|
140
|
+
].inject [{},0] do |(r,i),e| r[ e] = i ; [r,i+1] end
|
141
|
+
|
142
|
+
def initialize data
|
143
|
+
data.each_char { |c|
|
144
|
+
ALPHANUMERIC[ c] or raise ArgumentError, "Not alphanumeric uppercase: #{data}"
|
145
|
+
}
|
146
|
+
super
|
147
|
+
end
|
148
|
+
|
149
|
+
def write buffer, version
|
150
|
+
super
|
151
|
+
@data.scan /(.)(.)?/ do |c,d|
|
152
|
+
val = ALPHANUMERIC[ c]
|
153
|
+
len = 6
|
154
|
+
if d then
|
155
|
+
val = (val * ALPHANUMERIC.length) + ALPHANUMERIC[ d]
|
156
|
+
len += 5
|
157
|
+
end
|
158
|
+
buffer.put val, len
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def cbe ; [2, 11, 6] ; end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
class Kanji < Segment
|
167
|
+
|
168
|
+
NAME = "kanji"
|
169
|
+
ID = nil # ???
|
170
|
+
BITS_FOR_MODE = [ 8, 10, 12]
|
171
|
+
|
172
|
+
def initialize data
|
173
|
+
super
|
174
|
+
not_implemented
|
175
|
+
end
|
176
|
+
|
177
|
+
def write buffer, version
|
178
|
+
super
|
179
|
+
not_implemented
|
180
|
+
end
|
181
|
+
|
182
|
+
def cbe ; not_implemented ; end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def not_implemented
|
187
|
+
raise NotImplementedError, "Not implemented yet. Please contribute."
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
class Bytes < Segment
|
193
|
+
|
194
|
+
NAME = "8bit"
|
195
|
+
ID = 2
|
196
|
+
BITS_FOR_MODE = [ 8, 16, 16]
|
197
|
+
|
198
|
+
def write buffer, version
|
199
|
+
super
|
200
|
+
@data.each_byte do |b|
|
201
|
+
buffer.put b, 8
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def cbe ; [1, 8, 0] ; end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
210
|
+
|
data/lib/qrest.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#
|
2
|
+
# qrest.rb -- QR code library
|
3
|
+
#
|
4
|
+
|
5
|
+
require "qrest/base"
|
6
|
+
require "qrest/version"
|
7
|
+
require "qrest/segment"
|
8
|
+
require "qrest/rsblocks"
|
9
|
+
require "qrest/modules"
|
10
|
+
|
11
|
+
|
12
|
+
module QRest
|
13
|
+
|
14
|
+
class Code
|
15
|
+
|
16
|
+
class <<self
|
17
|
+
alias [] new
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :modules
|
21
|
+
|
22
|
+
def initialize input, *more, level: nil, max_version: nil, mode: nil, version: nil
|
23
|
+
input = [ input, *more] if not more.empty? or Hash === input
|
24
|
+
input = Segment.create input, mode
|
25
|
+
level ||= :h
|
26
|
+
error_correct_level = level.downcase.to_sym
|
27
|
+
Modules::ERRORCORRECTLEVEL[error_correct_level] or
|
28
|
+
raise ArgumentError, "Unknown error correction level: #{level}"
|
29
|
+
if version then
|
30
|
+
version <= Modules::MAX_VERSION or
|
31
|
+
raise ArgumentError, "Requested version exceeds maximum of #{Modules::MAX_VERSION}"
|
32
|
+
else
|
33
|
+
if max_version then
|
34
|
+
max_version <= Modules::MAX_VERSION or
|
35
|
+
raise ArgumentError, "Maximum posible version is #{Modules::MAX_VERSION}"
|
36
|
+
else
|
37
|
+
max_version = Modules::MAX_VERSION
|
38
|
+
end
|
39
|
+
mb = Modules::MAXBITS[error_correct_level]
|
40
|
+
version = 0
|
41
|
+
begin
|
42
|
+
version += 1
|
43
|
+
version <= max_version or
|
44
|
+
raise Error, "Data length exceeds maximum capacity of version #{max_version}"
|
45
|
+
end until (input.size version) <= mb[version - 1]
|
46
|
+
end
|
47
|
+
|
48
|
+
data = (RSBlocks.get version, error_correct_level).create_data input
|
49
|
+
@modules = Modules.create_best data, version, error_correct_level
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_s dark: nil, light: nil, quiet_size: nil
|
53
|
+
@modules.to_s dark: dark, light: light, quiet_size: quiet_size
|
54
|
+
end
|
55
|
+
|
56
|
+
def method_missing sym, *args, **kwargs, &block
|
57
|
+
if @modules.respond_to? sym then
|
58
|
+
@modules.send sym, *args, **kwargs, &block
|
59
|
+
else
|
60
|
+
super
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
metadata
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: qrest
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bertram Scharpf
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 2025-03-16 00:00:00.000000000 Z
|
11
|
+
dependencies: []
|
12
|
+
description: |
|
13
|
+
A Ruby library that generates QR Codes
|
14
|
+
as XPM, SVG or EPS graphics.
|
15
|
+
email: "<software@bertram-scharpf.de>"
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/qrest.rb
|
21
|
+
- lib/qrest/base.rb
|
22
|
+
- lib/qrest/bch.rb
|
23
|
+
- lib/qrest/bitbuffer.rb
|
24
|
+
- lib/qrest/bitstream.rb
|
25
|
+
- lib/qrest/demerits.rb
|
26
|
+
- lib/qrest/foreign/supplement.rb
|
27
|
+
- lib/qrest/formats/eps.rb
|
28
|
+
- lib/qrest/formats/svg.rb
|
29
|
+
- lib/qrest/formats/xpm.rb
|
30
|
+
- lib/qrest/modules.rb
|
31
|
+
- lib/qrest/polynomial.rb
|
32
|
+
- lib/qrest/rsblocks.rb
|
33
|
+
- lib/qrest/segment.rb
|
34
|
+
- lib/qrest/version.rb
|
35
|
+
homepage: https://github.com/BertramScharpf/ruby-qrest.git
|
36
|
+
licenses:
|
37
|
+
- BSD-2-Clause+
|
38
|
+
metadata: {}
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 3.1.0
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubygems_version: 3.6.4
|
54
|
+
specification_version: 4
|
55
|
+
summary: Generate QR Codes
|
56
|
+
test_files: []
|