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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 28f37a9b5e5fb20a07f781323ce9f2381ecadd873bec290b5b65811849adb563
4
+ data.tar.gz: 7ba9b8e971a1e76bb5869455a15f0973f29575a82a11d671656070a16ae1cfe0
5
+ SHA512:
6
+ metadata.gz: 5d592804716c69561ceb2cd556c7581302a485c7925c6908d956ebeeb7277011da21cf07867af837942813073d7e0307b7af27e74f7911180b8bbf1a8c11ff23
7
+ data.tar.gz: 72830cd5baadaefc25cade7df5a7a82af010a79ecb78f54e576c90551b09a2e072f943c42306f31e8fd873befaba0d63fdb495b26cb4188f9cbca3234b8c0e30
data/lib/qrest/base.rb ADDED
@@ -0,0 +1,13 @@
1
+ #
2
+ # qrest/base.rb -- Basic definitions
3
+ #
4
+
5
+ require "qrest/foreign/supplement"
6
+
7
+
8
+ module QRest
9
+
10
+ class Error < RuntimeError ; end
11
+
12
+ end
13
+
data/lib/qrest/bch.rb ADDED
@@ -0,0 +1,57 @@
1
+ #
2
+ # qrest/bch.rb -- Bose–Chaudhuri–Hocquenghem codes
3
+ #
4
+
5
+ require "qrest/base"
6
+
7
+
8
+ module QRest
9
+
10
+ module Bch
11
+
12
+ class <<self
13
+
14
+ private
15
+
16
+ def digit data
17
+ n = 0
18
+ while data != 0 do
19
+ data >>= 1
20
+ n += 1
21
+ end
22
+ n
23
+ end
24
+
25
+ end
26
+
27
+ G15 = 0b000010100110111
28
+ G15_MASK = 0b101010000010010
29
+ G18 = 0b001111100100101
30
+
31
+ G15D = digit G15
32
+ G18D = digit G18
33
+
34
+ class <<self
35
+
36
+ def format_info data
37
+ d = data << 10
38
+ until (m = (digit d) - G15D) < 0 do
39
+ d ^= G15 << m
40
+ end
41
+ ((data << 10) | d) ^ G15_MASK
42
+ end
43
+
44
+ def version data
45
+ d = data << 12
46
+ until (m = (digit d) - G18D) < 0 do
47
+ d ^= G18 << m
48
+ end
49
+ (data << 12) | d
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+
@@ -0,0 +1,85 @@
1
+ #
2
+ # qrest/bitbuffer.rb -- Bit buffer
3
+ #
4
+
5
+ require "qrest/base"
6
+
7
+
8
+ module QRest
9
+
10
+ class BitBuffer
11
+
12
+ class <<self
13
+ def build max
14
+ i = new
15
+ yield i
16
+ i.finish max
17
+ i.cont
18
+ end
19
+ end
20
+
21
+ attr_reader :cont
22
+
23
+ def initialize
24
+ @cont, @rem = [], 0
25
+ end
26
+
27
+ # You want to see an example for premature optimization
28
+ # turning into weird code? Okay, here we go.
29
+
30
+ def put num, length
31
+ n = []
32
+ l = length - @rem
33
+ if l > 0 then
34
+ if (r = l % 8).zero? then
35
+ prem = 0
36
+ else
37
+ prem = 8 - r
38
+ n.unshift num << prem
39
+ num >>= r
40
+ length -= r
41
+ end
42
+ while length >= 8 do
43
+ n.unshift num
44
+ num >>= 8
45
+ length -= 8
46
+ end
47
+ else
48
+ prem = -l
49
+ num <<= prem
50
+ end
51
+ @cont.last |= num if length > 0
52
+ @cont.concat n.map { |b| b & 0xff }
53
+ @rem = prem
54
+ nil
55
+ end
56
+
57
+ def put_bit bit
58
+ if @rem.zero? then
59
+ @rem = 7
60
+ @mask = 1 << @rem
61
+ @cont.push 0
62
+ else
63
+ @mask >>= 1
64
+ @rem -= 1
65
+ end
66
+ @cont.last |= @mask if bit
67
+ nil
68
+ end
69
+
70
+ PAD = [ 0xec, 0x11, ]
71
+
72
+ def finish max
73
+ @cont.length <= max or raise Error, "Code length overflow: #{length}>#{max}"
74
+ @cont.push 0 if @rem < 4 and @cont.length < max
75
+ @rem = nil
76
+ pad = max - @cont.length
77
+ ps = PAD * (pad/2+1)
78
+ ps.pop if pad.odd?
79
+ @cont.concat ps
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+
@@ -0,0 +1,27 @@
1
+ #
2
+ # qrest/bitstream.rb -- Bit Stream
3
+ #
4
+
5
+ require "qrest/base"
6
+
7
+
8
+ module QRest
9
+
10
+ class BitStream
11
+
12
+ def initialize data
13
+ @cur, @data = [], data.dup
14
+ end
15
+
16
+ def get
17
+ if @cur.empty? and not @data.empty? then
18
+ n = @data.shift
19
+ 8.times { @cur.push n.odd? ; n >>= 1 }
20
+ end
21
+ @cur.pop
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
@@ -0,0 +1,118 @@
1
+ #
2
+ # qrest/demerits.rb -- Compute demerits
3
+ #
4
+
5
+ require "qrest/base"
6
+
7
+
8
+ module QRest
9
+
10
+ class Demerits
11
+
12
+ def initialize fields
13
+ @fields = fields
14
+ end
15
+
16
+ def total **weigths
17
+ weigths.inject 0 do |sum,(k,v)|
18
+ e = ([*(send k)].zip [*v]).inject 0 do |s,(r,f)| s += r*f end
19
+ sum += e.round
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def same_color
26
+ points, add = 0, 0
27
+ each_pixel do |row,col|
28
+ same = 0
29
+ dark = @fields[row][col]
30
+ each_around row, col do |d|
31
+ same += 1 if dark == d
32
+ end
33
+ a = same - 5
34
+ if a > 0 then
35
+ points += 1
36
+ add += a
37
+ end
38
+ end
39
+ [ points, add]
40
+ end
41
+
42
+ def each_pixel
43
+ @fields.size.times do |row|
44
+ @fields.size.times do |col|
45
+ yield row, col
46
+ end
47
+ end
48
+ end
49
+
50
+ def same_region i
51
+ n = i+1
52
+ (i == 0 ? 0 : -1)..(n >= @fields.size ? 0 : 1)
53
+ end
54
+
55
+ def each_around row, col
56
+ (same_region row).each do |r|
57
+ rn = row + r
58
+ (same_region col).each do |c|
59
+ next if r == 0 && c == 0
60
+ cn = col + c
61
+ yield @fields[rn][cn]
62
+ end
63
+ end
64
+ end
65
+
66
+
67
+ def full_blocks
68
+ points = 0
69
+ each_block do |b|
70
+ b.uniq!
71
+ points += 1 unless b.length > 1
72
+ end
73
+ points
74
+ end
75
+
76
+ def each_block
77
+ sp = @fields.size - 1
78
+ sp.times do |ri|
79
+ rn = ri + 1
80
+ sp.times do |ci|
81
+ cn = ci + 1
82
+ yield [ @fields[ri][ci], @fields[rn][ci], @fields[ri][cn], @fields[rn][cn], ]
83
+ end
84
+ end
85
+ end
86
+
87
+
88
+ def dangerous
89
+ points = 0
90
+ @fields.each do |rs|
91
+ rs.each_cons 7 do |fs|
92
+ points += 1 if is_probe? fs
93
+ end
94
+ end
95
+ @fields.each_cons 7 do |rs|
96
+ @fields.size.times do |c|
97
+ points += 1 if is_probe? rs.map { |r| r[c] }
98
+ end
99
+ end
100
+ points
101
+ end
102
+
103
+ def is_probe? fields
104
+ f0, f1, f2, f3, f4, f5, f6 = fields
105
+ f0 && !f1 && f2 && f3 && f4 && !f5 && f6
106
+ end
107
+
108
+
109
+ def dark_ratio
110
+ dark = @fields.sum do |col| col.count true end
111
+ all = @fields.size*@fields.size
112
+ (dark.to_f / all - 0.5).abs * 100
113
+ end
114
+
115
+ end
116
+
117
+ end
118
+
@@ -0,0 +1,51 @@
1
+ #
2
+ # qrest/foreign/supplement.rb -- Additional useful Ruby functions
3
+ #
4
+
5
+ # The purpose of this is simply to reduce dependencies.
6
+
7
+ begin
8
+ require "supplement"
9
+ rescue LoadError
10
+ class NilClass ; def notempty? ; end ; end
11
+ class String ; def notempty? ; self unless empty? ; end ; end
12
+ class Array ; def notempty? ; self unless empty? ; end ; end
13
+ class Array ; def first= val ; self[ 0] = val ; end ; end
14
+ class Array ; def last= val ; self[-1] = val ;
15
+ rescue IndexError ; a.push val ; end ; end
16
+ class NilClass ; def to_bool ; false ; end ; end
17
+ class FalseClass ; def to_bool ; false ; end ; end
18
+ class Object ; def to_bool ; true ; end ; end
19
+ class <<Struct ; alias [] new ; end
20
+ class Module
21
+ def plain_name
22
+ sep = "::"
23
+ n = name.dup
24
+ i = n.rindex sep
25
+ n.slice! 0, i+sep.length if i
26
+ n
27
+ end
28
+ end
29
+ class String
30
+ def axe n
31
+ if n < length then
32
+ e = "..."
33
+ l = e.length
34
+ if n > l then
35
+ n -= l
36
+ else
37
+ l = 0
38
+ end
39
+ (slice 0, n) << "..."[0,l]
40
+ else
41
+ self
42
+ end
43
+ end
44
+ def starts_with? oth ; o = oth.to_str ; o.length if start_with? o ; end
45
+ def ends_with? oth ; o = oth.to_str ; length - o.length if end_with? o ; end
46
+ alias starts_with starts_with?
47
+ alias ends_with ends_with?
48
+ end
49
+ class Dir ; def entries! ; entries - %w(. ..) ; end ; end
50
+ end
51
+
@@ -0,0 +1,65 @@
1
+ #
2
+ # qrest/formats/xpm.rb -- Build XPM
3
+ #
4
+
5
+ require "qrest/modules"
6
+ require "qrest/version"
7
+
8
+
9
+ module QRest
10
+
11
+ class Modules
12
+
13
+ def eps quiet_size: nil, output: nil
14
+ quiet_size ||= 4
15
+ output ||= ""
16
+
17
+ full = size + 2*quiet_size
18
+ output << <<~EOT
19
+ %!PS
20
+ %%Creator: #{QRest::NAME} #{QRest::VERSION}
21
+ %%BoundingBox: 0 0 #{full} #{full}
22
+ %%EndComments
23
+ /box { newpath moveto 0 -1 rlineto 1 0 rlineto 0 1 rlineto closepath fill } def
24
+ EOT
25
+ LinesOut.open output do |lo|
26
+ each_field_neg quiet_size, full do |ri,ci|
27
+ lo.put "%d %d box" % [ci,ri]
28
+ end
29
+ end
30
+ output << <<~EOT
31
+ showpage
32
+ EOT
33
+ output
34
+ end
35
+
36
+ class LinesOut
37
+ class <<self
38
+ private :new
39
+ def open output
40
+ i = new output
41
+ yield i
42
+ output << "\n"
43
+ end
44
+ end
45
+ MAX = 78
46
+ def initialize output
47
+ @output = output
48
+ @line = 0
49
+ end
50
+ def put str
51
+ @line += str.length
52
+ if @line > MAX then
53
+ @output << "\n"
54
+ @line = 0
55
+ else
56
+ @output << " "
57
+ end
58
+ @output << str
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+
@@ -0,0 +1,77 @@
1
+ #
2
+ # qrest/formats/svg.rb -- Build SVG
3
+ #
4
+
5
+ require "qrest/modules"
6
+ require "qrest/version"
7
+
8
+
9
+ module QRest
10
+
11
+ class Modules
12
+
13
+ def svg header: nil, dimen: nil, quiet_size: nil, title: nil, cls: nil, id: nil, output: nil
14
+ header = true if header.nil?
15
+ dimen ||= "100px"
16
+ quiet_size ||= 4
17
+ title ||= "QR Code"
18
+ cls ||= "qr"
19
+ id ||= self.class.svg_id
20
+ output ||= ""
21
+
22
+ header and output << <<~EOT
23
+ <?xml version="1.0" encoding="UTF-8"?>
24
+ EOT
25
+ full = size + 2*quiet_size
26
+ output << <<~EOT
27
+ <svg xmlns="http://www.w3.org/2000/svg"
28
+ version="1.1" baseProfile="full"
29
+ class="#{cls}" id="#{id}"
30
+ width="#{dimen}" height="#{dimen}" viewBox="0 0 #{full} #{full}">
31
+ <title>#{title}</title>
32
+ <desc>Generated by #{QRest::NAME} #{QRest::VERSION}</desc>
33
+ EOT
34
+ each_field quiet_size do |ri,ci|
35
+ output << <<~EOT % [ci,ri]
36
+ <rect x="%3d" y="%3d" width="1" height="1" fill="black"/>
37
+ EOT
38
+ end
39
+ output << <<~EOT
40
+ </svg>
41
+ EOT
42
+ output
43
+ end
44
+
45
+ def html dimen: nil, quiet_size: nil, title: nil, output: nil
46
+ output ||= ""
47
+ output << <<~EOT
48
+ <!DOCTYPE html>
49
+ <html>
50
+ <head>
51
+ <meta charset="UTF-8">
52
+ <title>Example Page with QR Code</title>
53
+ <style>
54
+ body { background: #ddddee; }
55
+ .qrcode { background: #ffffff; }
56
+ </style>
57
+ </head>
58
+ <body>
59
+ <h1>My self-generated QR Code</h1>
60
+ EOT
61
+ svg header: false, quiet_size: quiet_size, title: title, cls: "qrcode", output: output
62
+ output << <<~EOT
63
+ <hr>
64
+ <pre>#{Time.now}</pre>
65
+ </body>
66
+ </html>
67
+ EOT
68
+ end
69
+
70
+ class <<self
71
+ def svg_id ; @id ||= "qr_000" ; @id.succ! ; end
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+
@@ -0,0 +1,48 @@
1
+ #
2
+ # qrest/formats/xpm.rb -- Build XPM
3
+ #
4
+
5
+ require "qrest/modules"
6
+ require "qrest/version"
7
+
8
+
9
+ module QRest
10
+
11
+ class Modules
12
+
13
+ XPM_D, XPM_L = "X", "."
14
+
15
+ def xpm name: nil, pixels: nil, quiet_size: nil, output: nil
16
+ name ||= QRest::NAME
17
+ name = name[ /[a-z_][a-z_0-9]*/i]
18
+ pixels ||= 3
19
+ quiet_size ||= 4
20
+ output ||= ""
21
+
22
+ output << <<~EOT
23
+ /* XPM */
24
+ static char * #{name}[] = {
25
+ EOT
26
+ dim = (size + 2*quiet_size)*pixels
27
+ output << <<~EOT
28
+ "#{dim} #{dim} 2 1 0 0 XPMEXT",
29
+ EOT
30
+ output << <<~EOT
31
+ "#{XPM_L}\tc #ffffff",
32
+ "#{XPM_D}\tc #000000",
33
+ EOT
34
+ lines dark: XPM_D*pixels, light: XPM_L*pixels, quiet_size: quiet_size do |l|
35
+ pixels.times { output << "\"#{l}\",\n" }
36
+ end
37
+ output << <<~EOT
38
+ "XPMEXT generator #{QRest::NAME} #{QRest::VERSION}",
39
+ "XPMENDEXT"
40
+ };
41
+ EOT
42
+ output
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+