rqrcode 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5aa4c4868eb5c584254a66743407f0461a05be74aece89350d41ea79671bc7d0
4
- data.tar.gz: eb6bbae7b8449b5a3a60ed5faa4d80a99c9bff2ff09b081a38fcac3bed55046c
3
+ metadata.gz: 9dad1e83dc97d564e2ec828cb8ba389c222fa4ae7662d6feaaed36fbfea194ba
4
+ data.tar.gz: e3d901e23ba8dfb7cc6b300ae47bc11dcbc6913d2fce1a66824bffa670ca5cf5
5
5
  SHA512:
6
- metadata.gz: f5c67b502684055b820a1c4d6aa7be65370c493a5431fcb87c9b859486cf9d584806ceffedbeeff50b41c3d524cf8aa02dda535674c33838bbd0943292f26666
7
- data.tar.gz: 1f5295a6b53acea72b83b869666ec004d4bbec494603ee59f7b6ab46401af0bf669c06f9957737c7558e1837c335b3b8da231e28fa18fc167ce6747cc2e1d7d5
6
+ metadata.gz: 317ff35bc49042e5a7a0d9390c82051b9552bd5d2a4c7a56e99e2ea75e7d2d4cf9071516f1fb800e5fd1af3c964976c6354db675c33928a0fee99f54cf588a7c
7
+ data.tar.gz: 167fc518c536b3bf32699dc09952fc5068db81d44040b0b768a4a220186438076992a8a3deb5eb85537c651d1d47ddabe7d4b2a29fbc490027a157b8265e3f77
@@ -1,20 +1,28 @@
1
1
  name: rqrcode
2
2
 
3
- on: [push]
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+ branches:
9
+ - master
4
10
 
5
11
  jobs:
6
- build:
7
-
8
- runs-on: ubuntu-latest
9
-
12
+ Build:
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ os: [ubuntu-latest, macos-latest]
17
+ ruby: [2.5, 2.6, 2.7, 3.0]
18
+ runs-on: ${{ matrix.os }}
10
19
  steps:
11
20
  - uses: actions/checkout@v1
12
- - name: Set up Ruby 2.6
13
- uses: actions/setup-ruby@v1
21
+ - uses: ruby/setup-ruby@v1
14
22
  with:
15
- ruby-version: 2.6.x
16
- - name: Build and test with Rake
17
- run: |
18
- gem install bundler
19
- bundle install --jobs 4 --retry 3
20
- bundle exec rake test
23
+ ruby-version: ${{ matrix.ruby }}
24
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
25
+ - name: Run Tests for Ruby ${{ matrix.ruby }} on ${{ matrix.os }}
26
+ run: bundle exec rake spec
27
+ - name: StandardRB check for Ruby ${{ matrix.ruby }} on ${{ matrix.os }}
28
+ run: bundle exec standardrb --format progress
data/.gitignore CHANGED
@@ -10,4 +10,4 @@
10
10
  .rvmrc
11
11
  *.sublime-project
12
12
  *.sublime-workspace
13
- Gemfile.lock
13
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/CHANGELOG.md ADDED
@@ -0,0 +1,39 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [2.0.0] - 2021-05-06
11
+
12
+ ### Added
13
+
14
+ - A new `use_path:` option on `.to_svg`. This uses a `<path>` node to greatly reduce the final SVG size. [#108]
15
+ - A new `viewbox:` option on `.to_svg`. Replaces the `svg.width` and `svg.height` attribute with `svg.viewBox` to allow CSS scaling. [#112]
16
+ - A new `svg_attributes:` option on `.to_svg`. Allows you to pass in custom SVG attributes to be used in the `<svg>` tag. [#113]
17
+
18
+ ### Changed
19
+
20
+ - README updated
21
+ - Rakefile cleaned up. You can now just run `rake` which will run specs and fix linting using `standardrb`
22
+ - Small documentation clarification [@smnscp](https://github.com/smnscp)
23
+ - Bump `rqrcode_core` to `~> 1.0`
24
+
25
+ ### Breaking Change
26
+
27
+ - The dependency `rqrcode_core-1.0.0` has a tiny breaking change to the `to_s` public method. https://github.com/whomwah/rqrcode_core/blob/master/CHANGELOG.md#breaking-changes
28
+
29
+ ## [1.2.0] - 2020-12-26
30
+
31
+ ### Changed
32
+
33
+ - README updated
34
+ - bump dependencies
35
+ - fix `required_ruby_version` for Ruby 3 support
36
+
37
+ [unreleased]: https://github.com/whomwah/rqrcode/compare/v2.0.0...HEAD
38
+ [2.0.0]: https://github.com/whomwah/rqrcode/compare/v1.2.0...v2.0.0
39
+ [1.2.0]: https://github.com/whomwah/rqrcode/compare/v1.1.1...v1.2.0
data/Gemfile.lock ADDED
@@ -0,0 +1,68 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rqrcode (2.0.0)
5
+ chunky_png (~> 1.0)
6
+ rqrcode_core (~> 1.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ ast (2.4.2)
12
+ chunky_png (1.4.0)
13
+ diff-lcs (1.4.4)
14
+ parallel (1.20.1)
15
+ parser (3.0.1.0)
16
+ ast (~> 2.4.1)
17
+ rainbow (3.0.0)
18
+ rake (13.0.3)
19
+ regexp_parser (2.1.1)
20
+ rexml (3.2.5)
21
+ rqrcode_core (1.0.0)
22
+ rspec (3.10.0)
23
+ rspec-core (~> 3.10.0)
24
+ rspec-expectations (~> 3.10.0)
25
+ rspec-mocks (~> 3.10.0)
26
+ rspec-core (3.10.1)
27
+ rspec-support (~> 3.10.0)
28
+ rspec-expectations (3.10.1)
29
+ diff-lcs (>= 1.2.0, < 2.0)
30
+ rspec-support (~> 3.10.0)
31
+ rspec-mocks (3.10.2)
32
+ diff-lcs (>= 1.2.0, < 2.0)
33
+ rspec-support (~> 3.10.0)
34
+ rspec-support (3.10.2)
35
+ rubocop (1.12.1)
36
+ parallel (~> 1.10)
37
+ parser (>= 3.0.0.0)
38
+ rainbow (>= 2.2.2, < 4.0)
39
+ regexp_parser (>= 1.8, < 3.0)
40
+ rexml
41
+ rubocop-ast (>= 1.2.0, < 2.0)
42
+ ruby-progressbar (~> 1.7)
43
+ unicode-display_width (>= 1.4.0, < 3.0)
44
+ rubocop-ast (1.4.1)
45
+ parser (>= 2.7.1.5)
46
+ rubocop-performance (1.10.1)
47
+ rubocop (>= 0.90.0, < 2.0)
48
+ rubocop-ast (>= 0.4.0)
49
+ ruby-progressbar (1.11.0)
50
+ standard (1.0.5)
51
+ rubocop (= 1.12.1)
52
+ rubocop-performance (= 1.10.1)
53
+ standardrb (1.0.0)
54
+ standard
55
+ unicode-display_width (2.0.0)
56
+
57
+ PLATFORMS
58
+ ruby
59
+
60
+ DEPENDENCIES
61
+ bundler (~> 2.0)
62
+ rake (~> 13.0)
63
+ rqrcode!
64
+ rspec (~> 3.5)
65
+ standardrb (~> 1.0)
66
+
67
+ BUNDLED WITH
68
+ 2.2.15
data/README.md CHANGED
@@ -1,20 +1,21 @@
1
1
  # RQRCode
2
2
 
3
- ![](https://github.com/whomwah/rqrcode/workflows/rqrcode/badge.svg)
3
+ ![](https://github.com/whomwah/rqrcode/actions/workflows/ruby.yml/badge.svg)
4
4
 
5
5
 
6
6
  [RQRCode](https://github.com/whomwah/rqrcode) is a library for creating and rendering QR codes into various formats. It has a simple interface with all the standard QR code options. It was adapted from the Javascript library by Kazuhiko Arase.
7
7
 
8
8
  * QR code is trademarked by Denso Wave inc
9
- * Minimum Ruby version is `~> 2.3`
10
- * For `rqrcode` releases `< 1.0.0` please use [this README](https://github.com/whomwah/rqrcode/blob/cd2732a68434e6197c219e6c8cbdadfce0c4c4f3/README.md)
9
+ * Minimum Ruby version is `>= 2.3`
10
+ * For `rqrcode` releases `< 2.0.0` please use [this README](https://github.com/whomwah/rqrcode/blob/v1.2.0/README.md)
11
+ * For `rqrcode` releases `< 1.0.0` please use [this README](https://github.com/whomwah/rqrcode/blob/v0.9.0/README.md)
11
12
 
12
13
  ## Installing
13
14
 
14
15
  Add this line to your application's `Gemfile`:
15
16
 
16
17
  ```ruby
17
- gem 'rqrcode'
18
+ gem "rqrcode", "~> 2.0"
18
19
  ```
19
20
 
20
21
  or install manually:
@@ -26,20 +27,19 @@ gem install rqrcode
26
27
  ## Basic usage example
27
28
 
28
29
  ```ruby
29
- require 'rqrcode'
30
+ require "rqrcode"
30
31
 
31
- qr = RQRCode::QRCode.new('http://github.com')
32
- result = ''
32
+ qr = RQRCode::QRCode.new("https://kyan.com")
33
33
 
34
- qr.qrcode.modules.each do |row|
35
- row.each do |col|
36
- result << (col ? 'X' : 'O')
37
- end
38
-
39
- result << "\n"
40
- end
34
+ puts qr.to_s
41
35
 
42
- puts result
36
+ xxxxxxx xxxxxxx xxx xxxxxxx
37
+ x x x xxx xx x x
38
+ x xxx x xx x x xx x xxx x
39
+ x xxx x xx xx xx x xxx x
40
+ x xxx x x x xxx x xxx x
41
+ x x xxx x xx x x x x
42
+ ...
43
43
  ```
44
44
 
45
45
  ### Advanced Options
@@ -49,7 +49,7 @@ These are the various QR Code generation options provided by [rqrqcode_core](htt
49
49
  ```
50
50
  string - the string you wish to encode
51
51
 
52
- size - the size of the qrcode (default 4)
52
+ size - the size (Integer) of the qrcode (defaults to smallest size needed to encode the string)
53
53
 
54
54
  level - the error correction level, can be:
55
55
  * Level :l 7% of code can be restored
@@ -72,104 +72,207 @@ qrcode = RQRCodeCore::QRCode.new('hello world', size: 1, level: :m, mode: :alpha
72
72
 
73
73
  ## Render types
74
74
 
75
- You can output your QR code in various forms. These are detailed below:
75
+ You probably want to output your QR code in a specific format. We make this easy by providing a bunch of formats to choose from below, each with their own set of options:
76
76
 
77
- ### as SVG
77
+ ### `as_svg`
78
78
 
79
79
  The SVG renderer will produce a stand-alone SVG as a `String`
80
80
 
81
+ ```
82
+ Options:
83
+
84
+ offset - Padding around the QR Code in pixels
85
+ (default 0)
86
+ fill - Background color e.g "ffffff" or :white
87
+ (default none)
88
+ color - Foreground color e.g "000" or :black
89
+ (default "000")
90
+ module_size - The Pixel size of each module
91
+ (defaults 11)
92
+ shape_rendering - SVG Attribute: auto | optimizeSpeed | crispEdges | geometricPrecision
93
+ (defaults crispEdges)
94
+ standalone - Whether to make this a full SVG file, or only an svg to embed in other svg
95
+ (default true)
96
+ use_path - Use <path> to render SVG rather than <rect> to significantly reduce size
97
+ and quality. This will become the default in future versions.
98
+ (default false)
99
+ viewbox - Replace the `svg.width` and `svg.height` attribute with `svg.viewBox` to
100
+ allow CSS scaling
101
+ (default false)
102
+ svg_attributes - A optional hash of custom <svg> attributes. Existing attributes will remain.
103
+ (default {})
104
+ ```
105
+ Example
81
106
  ```ruby
82
- require 'rqrcode'
107
+ require "rqrcode"
83
108
 
84
109
  qrcode = RQRCode::QRCode.new("http://github.com/")
85
110
 
86
111
  # NOTE: showing with default options specified explicitly
87
112
  svg = qrcode.as_svg(
88
- offset: 0,
89
- color: '000',
90
- shape_rendering: 'crispEdges',
91
- module_size: 6,
92
- standalone: true
113
+ color: "000",
114
+ shape_rendering: "crispEdges",
115
+ module_size: 11,
116
+ standalone: true,
117
+ use_path: true,
118
+ svg_attributes: {
119
+ id: "myUniqueId"
120
+ }
93
121
  )
94
122
  ```
95
123
 
96
124
  ![QR code with github url](./images/github-qrcode.svg)
97
125
 
98
- ### as ANSI
126
+ ### `as_png`
99
127
 
100
- The ANSI renderer will produce as a string with ANSI color codes.
128
+ The will produce a PNG using the [ChunkyPNG gem](https://github.com/wvanbergen/chunky_png). The result will be a `ChunkyPNG::Image` instance.
101
129
 
102
- ```ruby
103
- require 'rqrcode'
130
+ ```
131
+ Options:
104
132
 
105
- qrcode = RQRCode::QRCode.new("http://github.com/")
133
+ fill - Background ChunkyPNG::Color, defaults to 'white'
134
+ color - Foreground ChunkyPNG::Color, defaults to 'black'
106
135
 
107
- # NOTE: showing with default options specified explicitly
108
- svg = qrcode.as_ansi(
109
- light: "\033[47m", dark: "\033[40m",
110
- fill_character: ' ',
111
- quiet_zone_size: 4
112
- )
113
- ```
136
+ When option :file is supplied you can use the following ChunkyPNG constraints:
114
137
 
115
- ![QR code with github url](./images/ansi-screen-shot.png)
138
+ color_mode - The color mode to use. Use one of the ChunkyPNG::COLOR_* constants.
139
+ (defaults to 'ChunkyPNG::COLOR_GRAYSCALE')
140
+ bit_depth - The bit depth to use. This option is only used for indexed images.
141
+ (defaults to 1 bit)
142
+ interlace - Whether to use interlacing (true or false).
143
+ (defaults to ChunkyPNG default)
144
+ compression - The compression level for Zlib. This can be a value between 0 and 9, or a
145
+ Zlib constant like Zlib::BEST_COMPRESSION
146
+ (defaults to ChunkyPNG default)
116
147
 
117
- ### as PNG
148
+ There are two sizing algorithms.
118
149
 
119
- The library can produce a PNG. Result will be a `ChunkyPNG::Image` instance.
150
+ * Original that can result in blurry and hard to scan images
151
+ * Google's Chart API inspired sizing that resizes the module size to fit within the given image size.
152
+
153
+ The Google one will be used when no options are given or when the new size option is used.
154
+
155
+ *Google Sizing*
156
+
157
+ size - Total size of PNG in pixels. The module size is calculated so it fits.
158
+ (defaults to 120)
159
+ border_modules - Width of white border around the modules.
160
+ (defaults to 4).
161
+
162
+ -- DONT USE border_modules OPTION UNLESS YOU KNOW ABOUT THE QUIET ZONE NEEDS OF QR CODES --
163
+
164
+ *Original Sizing*
165
+
166
+ module_px_size - Image size, in pixels.
167
+ border - Border thickness, in pixels
168
+
169
+ It first creates an image where 1px = 1 module, then resizes.
170
+ Defaults to 120x120 pixels, customizable by option.
171
+ ```
172
+
173
+ Example
120
174
 
121
175
  ```ruby
122
- require 'rqrcode'
176
+ require "rqrcode"
123
177
 
124
178
  qrcode = RQRCode::QRCode.new("http://github.com/")
125
179
 
126
180
  # NOTE: showing with default options specified explicitly
127
181
  png = qrcode.as_png(
128
- resize_gte_to: false,
129
- resize_exactly_to: false,
130
- fill: 'white',
131
- color: 'black',
132
- size: 120,
182
+ bit_depth: 1,
133
183
  border_modules: 4,
184
+ color_mode: ChunkyPNG::COLOR_GRAYSCALE,
185
+ color: "black",
186
+ file: nil,
187
+ fill: "white",
134
188
  module_px_size: 6,
135
- file: nil # path to write
189
+ resize_exactly_to: false,
190
+ resize_gte_to: false,
191
+ size: 120
136
192
  )
137
193
 
138
- IO.write("/tmp/github-qrcode.png", png.to_s)
194
+ IO.binwrite("/tmp/github-qrcode.png", png.to_s)
139
195
  ```
140
196
 
141
197
  ![QR code with github url](./images/github-qrcode.png)
142
198
 
143
- ### On the console ( just because you can )
144
199
 
145
- ```ruby
146
- require 'rqrcode'
200
+ ### `as_ansi`
147
201
 
148
- qr = RQRCode::QRCode.new('http://kyan.com', size: 4, level: :h)
202
+ The ANSI renderer will produce as a string with ANSI color codes.
149
203
 
150
- puts qr.to_s
151
204
  ```
205
+ Options:
206
+
207
+ light - Foreground ANSI code
208
+ (default "\033[47m")
209
+ dark - Background ANSI code
210
+ (default "\033[40m")
211
+ fill_character - The written character
212
+ (default ' ')
213
+ quiet_zone_size - Padding around the edge
214
+ (default 4)
215
+ ```
216
+ Example
217
+ ```ruby
218
+ require "rqrcode"
152
219
 
153
- Output:
220
+ qrcode = RQRCode::QRCode.new("http://github.com/")
154
221
 
222
+ # NOTE: showing with default options specified explicitly
223
+ svg = qrcode.as_ansi(
224
+ light: "\033[47m", dark: "\033[40m",
225
+ fill_character: " ",
226
+ quiet_zone_size: 4
227
+ )
155
228
  ```
156
- xxxxxxx x x xxx xxxxxxx
157
- x x xxxxx x x x x
158
- x xxx x x x x x xxx x
159
- x xxx x xxx x xxx x xxx x
160
- x xxx x xxx x x x x xxx x
161
- ... etc
162
- ```
229
+
230
+ ![QR code with github url](./images/ansi-screen-shot.png)
163
231
 
164
232
  ## API Documentation
165
233
 
166
234
  [http://www.rubydoc.info/gems/rqrcode](http://www.rubydoc.info/gems/rqrcode)
167
235
 
236
+ ## Tests
237
+
238
+ You can run the test suite using:
239
+
240
+ ```
241
+ $ ./bin/setup
242
+ $ rake # runs specs and standard:fix
243
+ $ rake spec # just runs the specs
244
+ ```
245
+
246
+ or try the lib from the console with:
247
+
248
+ ```
249
+ $ ./bin/console
250
+ ```
251
+
252
+ ## Linting
253
+
254
+ The project uses [standardrb](https://github.com/testdouble/standard) and can be used with:
255
+
256
+ ```
257
+ $ ./bin/setup
258
+ $ rake standard # checks
259
+ $ rake standard:fix # fixes
260
+ ```
261
+
168
262
  ## Contributing
263
+
264
+ I am not currently accepting any new renderers as the current `as_png`, `as_svg` and `as_ansi` work for most cases. If you need something different from what's available, the [`rqrcode_core`](https://github.com/whomwah/rqrcode_core) gem gives you access to all the QR Code information you will need so makes it simple to generate your own.
265
+
266
+ The motivation for the above is because the rendering side of this gem takes up the most time. It seems that many people want a slightly different version of a QR Code so supporting all the variations would be hard. The easiest way is to empower people to create their own versions which they can manage and share. This is what `rqrcode_core` does.
267
+
268
+ Any contribution PR's will be greatly accepted. It's important that they are well tested and backwards compatible.
269
+
169
270
  * Fork the project
170
271
  * Send a pull request
171
272
  * Don't touch the .gemspec, I'll do that when I release a new version
172
273
 
274
+ Thanks D.
275
+
173
276
  ## Authors
174
277
 
175
278
  Original RQRCode author: Duncan Robertson
data/Rakefile CHANGED
@@ -1,10 +1,10 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
1
+ begin
2
+ require "standard/rake"
3
+ require "rspec/core/rake_task"
3
4
 
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
8
- end
5
+ RSpec::Core::RakeTask.new(:spec)
9
6
 
10
- task :default => :test
7
+ task default: [:spec, "standard:fix"]
8
+ rescue LoadError
9
+ # no standard/rspec available
10
+ end
data/lib/rqrcode.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RQRCode
4
- require 'rqrcode_core'
5
- require 'rqrcode/qrcode'
6
- require 'rqrcode/export'
7
- require 'rqrcode/version'
4
+ require "rqrcode_core"
5
+ require "rqrcode/qrcode"
6
+ require "rqrcode/export"
7
+ require "rqrcode/version"
8
8
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rqrcode/export/ansi'
4
- require 'rqrcode/export/html'
5
- require 'rqrcode/export/png'
6
- require 'rqrcode/export/svg'
3
+ require "rqrcode/export/ansi"
4
+ require "rqrcode/export/html"
5
+ require "rqrcode/export/png"
6
+ require "rqrcode/export/svg"
@@ -9,15 +9,15 @@ module RQRCode
9
9
  #
10
10
  # Options:
11
11
  # light: Foreground ("\033[47m")
12
- # dark: Background ANSI code. ("\033[47m")
12
+ # dark: Background ANSI code. ("\033[40m")
13
13
  # fill_character: The written character. (' ')
14
14
  # quiet_zone_size: (4)
15
15
  #
16
- def as_ansi(options={})
16
+ def as_ansi(options = {})
17
17
  options = {
18
18
  light: "\033[47m",
19
19
  dark: "\033[40m",
20
- fill_character: ' ',
20
+ fill_character: " ",
21
21
  quiet_zone_size: 4
22
22
  }.merge(options)
23
23
 
@@ -39,15 +39,13 @@ module RQRCode
39
39
  row << dark
40
40
  previous_dark = true
41
41
  end
42
- row << fill_character
43
- else
42
+ elsif previous_dark != false
44
43
  # light
45
- if previous_dark != false
46
- row << light
47
- previous_dark = false
48
- end
49
- row << fill_character
44
+ row << light
45
+ previous_dark = false
50
46
  end
47
+
48
+ row << fill_character
51
49
  end
52
50
 
53
51
  # add quiet zone
@@ -68,7 +66,7 @@ module RQRCode
68
66
  quiet_row = light + fill_character * width + normal
69
67
  quiet_rows = quiet_row * quiet_zone_size
70
68
 
71
- return quiet_rows + output.join + quiet_rows
69
+ quiet_rows + output.join + quiet_rows
72
70
  end
73
71
  end
74
72
  end
@@ -6,7 +6,7 @@ module RQRCode
6
6
  #
7
7
  # Use this module to HTML-ify the QR code if you just want the default HTML
8
8
  def as_html
9
- ['<table>', rows.as_html, '</table>'].join
9
+ ["<table>", rows.as_html, "</table>"].join
10
10
  end
11
11
 
12
12
  private
@@ -27,7 +27,7 @@ module RQRCode
27
27
 
28
28
  class Row < Struct.new(:qr, :qr_module, :row_index)
29
29
  def as_html
30
- ['<tr>', cells.map(&:as_html).join, '</tr>'].join
30
+ ["<tr>", cells.map(&:as_html).join, "</tr>"].join
31
31
  end
32
32
 
33
33
  def cells
@@ -41,7 +41,7 @@ module RQRCode
41
41
  end
42
42
 
43
43
  def html_class
44
- qr.checked?(row_index, col_index) ? 'black' : 'white'
44
+ qr.checked?(row_index, col_index) ? "black" : "white"
45
45
  end
46
46
  end
47
47
  end
@@ -1,58 +1,70 @@
1
1
  # frozen_string_literal: true
2
- require 'chunky_png'
2
+
3
+ require "chunky_png"
3
4
 
4
5
  # This class creates PNG files.
5
6
  # Code from: https://github.com/DCarper/rqrcode
6
7
  module RQRCode
7
8
  module Export
8
9
  module PNG
10
+ # Render the PNG from the QR Code.
9
11
  #
10
- # Render the PNG from the Qrcode.
12
+ # Options:
13
+ # fill - Background ChunkyPNG::Color, defaults to 'white'
14
+ # color - Foreground ChunkyPNG::Color, defaults to 'black'
11
15
  #
12
- # There are two sizing algoritams.
16
+ # When option :file is supplied you can use the following ChunkyPNG constraints
17
+ # color_mode - The color mode to use. Use one of the ChunkyPNG::COLOR_* constants.
18
+ # (defaults to 'ChunkyPNG::COLOR_GRAYSCALE')
19
+ # bit_depth - The bit depth to use. This option is only used for indexed images.
20
+ # (defaults to 1 bit)
21
+ # interlace - Whether to use interlacing (true or false).
22
+ # (defaults to ChunkyPNG default)
23
+ # compression - The compression level for Zlib. This can be a value between 0 and 9, or a
24
+ # Zlib constant like Zlib::BEST_COMPRESSION
25
+ # (defaults to ChunkyPNG default)
26
+ #
27
+ # There are two sizing algorithms.
13
28
  #
14
29
  # - Original that can result in blurry and hard to scan images
15
30
  # - Google's Chart API inspired sizing that resizes the module size to fit within the given image size.
16
31
  #
17
32
  # The Googleis one will be used when no options are given or when the new size option is used.
18
33
  #
19
- # Options:
20
- # fill - Background ChunkyPNG::Color, defaults to 'white'
21
- # color - Foreground ChunkyPNG::Color, defaults to 'black'
22
- #
23
- # *Googleis*
24
- # size - Total size of PNG in pixels. The module size is calculated so it fits. (defaults to 90)
25
- # border_modules - Width of white border around in modules. (defaults to 4).
34
+ # *Google*
35
+ # size - Total size of PNG in pixels. The module size is calculated so it fits.
36
+ # (defaults to 120)
37
+ # border_modules - Width of white border around in modules.
38
+ # (defaults to 4).
26
39
  #
27
40
  # -- DONT USE border_modules OPTION UNLESS YOU KNOW ABOUT THE QUIET ZONE NEEDS OF QR CODES --
28
41
  #
29
42
  # *Original*
30
43
  # module_px_size - Image size, in pixels.
31
- # border - Border thickness, in pixels
44
+ # border - Border thickness, in pixels
32
45
  #
33
46
  # It first creates an image where 1px = 1 module, then resizes.
34
- # Defaults to 90x90 pixels, customizable by option.
47
+ # Defaults to 120x120 pixels, customizable by option.
35
48
  #
36
49
  def as_png(options = {})
37
50
  default_img_options = {
38
- :resize_gte_to => false,
39
- :resize_exactly_to => false,
40
- :fill => 'white',
41
- :color => 'black',
42
- :size => 120,
43
- :border_modules => 4,
44
- :file => false,
45
- :module_px_size => 6
51
+ bit_depth: 1,
52
+ border_modules: 4,
53
+ color_mode: ChunkyPNG::COLOR_GRAYSCALE,
54
+ color: "black",
55
+ file: false,
56
+ fill: "white",
57
+ module_px_size: 6,
58
+ resize_exactly_to: false,
59
+ resize_gte_to: false,
60
+ size: 120
46
61
  }
47
62
 
48
- googleis = options.length == 0 || (options[:size] != nil)
49
-
63
+ googleis = options.length == 0 || !options[:size].nil?
50
64
  options = default_img_options.merge(options) # reverse_merge
51
-
52
- fill = ChunkyPNG::Color(options[:fill])
53
- color = ChunkyPNG::Color(options[:color])
65
+ fill = ChunkyPNG::Color(options[:fill])
66
+ color = ChunkyPNG::Color(options[:color])
54
67
  output_file = options[:file]
55
-
56
68
  module_px_size = nil
57
69
  border_px = nil
58
70
  png = nil
@@ -77,7 +89,7 @@ module RQRCode
77
89
  else
78
90
  options[:module_px_size]
79
91
  end
80
- border_px = border * module_px_size
92
+ border_px = border * module_px_size
81
93
  total_border_px = border_px * 2
82
94
  resize_to = options[:resize_exactly_to]
83
95
 
@@ -92,7 +104,7 @@ module RQRCode
92
104
  if @qrcode.checked?(x, y)
93
105
  (0...module_px_size).each do |i|
94
106
  (0...module_px_size).each do |j|
95
- png[(y * module_px_size) + border_px + j , (x * module_px_size) + border_px + i] = color
107
+ png[(y * module_px_size) + border_px + j, (x * module_px_size) + border_px + i] = color
96
108
  end
97
109
  end
98
110
  end
@@ -103,10 +115,16 @@ module RQRCode
103
115
  png = png.resize(resize_to, resize_to)
104
116
  end
105
117
 
106
-
107
118
  if output_file
108
- png.save(output_file,{ :color_mode => ChunkyPNG::COLOR_GRAYSCALE, :bit_depth =>1})
119
+ constraints = {
120
+ color_mode: options[:color_mode],
121
+ bit_depth: options[:bit_depth]
122
+ }
123
+ constraints[:interlace] = options[:interlace] if options.has_key?(:interlace)
124
+ constraints[:compression] = options[:compression] if options.has_key?(:compression)
125
+ png.save(output_file, constraints)
109
126
  end
127
+
110
128
  png
111
129
  end
112
130
  end
@@ -1,59 +1,198 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This class creates a SVG files.
4
- # Code from: https://github.com/samvincent/rqrcode-rails3
4
+ # Initial code from: https://github.com/samvincent/rqrcode-rails3
5
5
  module RQRCode
6
6
  module Export
7
7
  module SVG
8
+ class BaseOutputSVG
9
+ attr_reader :result
10
+
11
+ def initialize(qrcode)
12
+ @qrcode = qrcode
13
+ @result = []
14
+ end
15
+ end
16
+
17
+ class Path < BaseOutputSVG
18
+ def build(module_size, offset, color)
19
+ modules_array = @qrcode.modules
20
+ matrix_width = matrix_height = modules_array.length + 1
21
+ empty_row = [Array.new(matrix_width - 1, false)]
22
+ edge_matrix = Array.new(matrix_height) { Array.new(matrix_width) }
23
+
24
+ (empty_row + modules_array + empty_row).each_cons(2).with_index do |row_pair, row_index|
25
+ first_row, second_row = row_pair
26
+
27
+ # horizontal edges
28
+ first_row.zip(second_row).each_with_index do |cell_pair, column_index|
29
+ edge = case cell_pair
30
+ when [true, false] then Edge.new column_index + 1, row_index, :left
31
+ when [false, true] then Edge.new column_index, row_index, :right
32
+ end
33
+
34
+ (edge_matrix[edge.start_y][edge.start_x] ||= []) << edge if edge
35
+ end
36
+
37
+ # vertical edges
38
+ ([false] + second_row + [false]).each_cons(2).each_with_index do |cell_pair, column_index|
39
+ edge = case cell_pair
40
+ when [true, false] then Edge.new column_index, row_index, :down
41
+ when [false, true] then Edge.new column_index, row_index + 1, :up
42
+ end
43
+
44
+ (edge_matrix[edge.start_y][edge.start_x] ||= []) << edge if edge
45
+ end
46
+ end
47
+
48
+ edge_count = edge_matrix.flatten.compact.count
49
+ path = []
50
+
51
+ while edge_count > 0
52
+ edge_loop = []
53
+ next_matrix_cell = edge_matrix.find(&:any?).find { |cell| cell&.any? }
54
+ edge = next_matrix_cell.first
55
+
56
+ while edge
57
+ edge_loop << edge
58
+ matrix_cell = edge_matrix[edge.start_y][edge.start_x]
59
+ matrix_cell.delete edge
60
+ edge_matrix[edge.start_y][edge.start_x] = nil if matrix_cell.empty?
61
+ edge_count -= 1
62
+
63
+ # try to find an edge continuing the current edge
64
+ edge = edge_matrix[edge.end_y][edge.end_x]&.first
65
+ end
66
+
67
+ first_edge = edge_loop.first
68
+ edge_loop_string = SVG_PATH_COMMANDS[:move]
69
+ edge_loop_string += "#{first_edge.start_x} #{first_edge.start_y}"
70
+
71
+ edge_loop.chunk(&:direction).to_a[0...-1].each do |direction, edges|
72
+ edge_loop_string << "#{SVG_PATH_COMMANDS[direction]}#{edges.length}"
73
+ end
74
+ edge_loop_string << SVG_PATH_COMMANDS[:close]
75
+
76
+ path << edge_loop_string
77
+ end
78
+
79
+ @result << %{<path d="#{path.join}" style="fill:##{color}" transform="translate(#{offset},#{offset}) scale(#{module_size})"/>}
80
+ end
81
+ end
82
+
83
+ class Rect < BaseOutputSVG
84
+ def build(module_size, offset, color)
85
+ @qrcode.modules.each_index do |c|
86
+ tmp = []
87
+ @qrcode.modules.each_index do |r|
88
+ y = c * module_size + offset
89
+ x = r * module_size + offset
90
+
91
+ next unless @qrcode.checked?(c, r)
92
+ tmp << %(<rect width="#{module_size}" height="#{module_size}" x="#{x}" y="#{y}" style="fill:##{color}"/>)
93
+ end
94
+
95
+ @result << tmp.join
96
+ end
97
+ end
98
+ end
99
+
100
+ class Edge < Struct.new(:start_x, :start_y, :direction)
101
+ def end_x
102
+ case direction
103
+ when :right then start_x + 1
104
+ when :left then start_x - 1
105
+ else start_x
106
+ end
107
+ end
108
+
109
+ def end_y
110
+ case direction
111
+ when :down then start_y + 1
112
+ when :up then start_y - 1
113
+ else start_y
114
+ end
115
+ end
116
+ end
117
+
118
+ DEFAULT_SVG_ATTRIBUTES = [
119
+ %(version="1.1"),
120
+ %(xmlns="http://www.w3.org/2000/svg"),
121
+ %(xmlns:xlink="http://www.w3.org/1999/xlink"),
122
+ %(xmlns:ev="http://www.w3.org/2001/xml-events")
123
+ ]
124
+
125
+ SVG_PATH_COMMANDS = {
126
+ move: "M",
127
+ up: "v-",
128
+ down: "v",
129
+ left: "h-",
130
+ right: "h",
131
+ close: "z"
132
+ }
133
+
8
134
  #
9
135
  # Render the SVG from the Qrcode.
10
136
  #
11
137
  # Options:
12
- # offset - Padding around the QR Code (e.g. 10)
13
- # fill - Background color (e.g "ffffff" or :white)
14
- # color - Foreground color for the code (e.g. "000000" or :black)
15
- # module_size - The Pixel size of each module (e.g. 11)
16
- # shape_rendering - Defaults to crispEdges
17
- # standalone - wether to make this a full SVG file, or only svg to embed
18
- # in other svg.
138
+ # offset - Padding around the QR Code in pixels
139
+ # (default 0)
140
+ # fill - Background color e.g "ffffff"
141
+ # (default none)
142
+ # color - Foreground color e.g "000"
143
+ # (default "000")
144
+ # module_size - The Pixel size of each module
145
+ # (defaults 11)
146
+ # shape_rendering - SVG Attribute: auto | optimizeSpeed | crispEdges | geometricPrecision
147
+ # (defaults crispEdges)
148
+ # standalone - Whether to make this a full SVG file, or only an svg to embed in other svg
149
+ # (default true)
150
+ # use_path - Use <path> to render SVG rather than <rect> to significantly reduce size
151
+ # and quality. This will become the default in future versions.
152
+ # (default false)
153
+ # viewbox - replace `width` and `height` in <svg> with a viewBox, allows CSS scaling
154
+ # (default false)
155
+ # svg_attributes - A optional hash of custom <svg> attributes. Existing attributes will remain.
156
+ # (default {})
19
157
  #
20
- def as_svg(options={})
158
+ def as_svg(options = {})
159
+ fill = options[:fill]
160
+ use_path = options[:use_path]
21
161
  offset = options[:offset].to_i || 0
22
162
  color = options[:color] || "000"
23
163
  shape_rendering = options[:shape_rendering] || "crispEdges"
24
164
  module_size = options[:module_size] || 11
25
165
  standalone = options[:standalone].nil? ? true : options[:standalone]
166
+ viewbox = options[:viewbox].nil? ? false : options[:viewbox]
167
+ svg_attributes = options[:svg_attributes] || {}
26
168
 
27
169
  # height and width dependent on offset and QR complexity
28
- dimension = (@qrcode.module_count*module_size) + (2*offset)
170
+ dimension = (@qrcode.module_count * module_size) + (2 * offset)
171
+ # use dimensions differently if we are using a viewBox
172
+ dimensions_attr = viewbox ? %(viewBox="0 0 #{dimension} #{dimension}") : %(width="#{dimension}" height="#{dimension}")
29
173
 
30
- xml_tag = %{<?xml version="1.0" standalone="yes"?>}
31
- open_tag = %{<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" width="#{dimension}" height="#{dimension}" shape-rendering="#{shape_rendering}">}
32
- close_tag = "</svg>"
174
+ svg_tag_attributes = (DEFAULT_SVG_ATTRIBUTES + [
175
+ dimensions_attr,
176
+ %(shape-rendering="#{shape_rendering}")
177
+ ] + svg_attributes.map { |k, v| %(#{k}="#{v}") }).join(" ")
33
178
 
34
- result = []
35
- @qrcode.modules.each_index do |c|
36
- tmp = []
37
- @qrcode.modules.each_index do |r|
38
- y = c*module_size + offset
39
- x = r*module_size + offset
179
+ xml_tag = %(<?xml version="1.0" standalone="yes"?>)
180
+ open_tag = %(<svg #{svg_tag_attributes}>)
181
+ close_tag = "</svg>"
40
182
 
41
- next unless @qrcode.checked?(c, r)
42
- tmp << %{<rect width="#{module_size}" height="#{module_size}" x="#{x}" y="#{y}" style="fill:##{color}"/>}
43
- end
44
- result << tmp.join
45
- end
183
+ output_tag = (use_path ? Path : Rect).new(@qrcode)
184
+ output_tag.build(module_size, offset, color)
46
185
 
47
- if options[:fill]
48
- result.unshift %{<rect width="#{dimension}" height="#{dimension}" x="0" y="0" style="fill:##{options[:fill]}"/>}
186
+ if fill
187
+ output_tag.result.unshift %(<rect width="#{dimension}" height="#{dimension}" x="0" y="0" style="fill:##{fill}"/>)
49
188
  end
50
189
 
51
190
  if standalone
52
- result.unshift(xml_tag, open_tag)
53
- result << close_tag
191
+ output_tag.result.unshift(xml_tag, open_tag)
192
+ output_tag.result << close_tag
54
193
  end
55
194
 
56
- result.join("\n")
195
+ output_tag.result.join
57
196
  end
58
197
  end
59
198
  end
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rqrcode/qrcode/qrcode'
3
+ require "rqrcode/qrcode/qrcode"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
3
+ require "forwardable"
4
4
 
5
5
  module RQRCode #:nodoc:
6
6
  class QRCode
@@ -11,7 +11,7 @@ module RQRCode #:nodoc:
11
11
  attr_reader :qrcode
12
12
 
13
13
  def initialize(string, *args)
14
- @qrcode = RQRCodeCore::QRCode.new(string, args)
14
+ @qrcode = RQRCodeCore::QRCode.new(string, *args)
15
15
  end
16
16
  end
17
17
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RQRCode
4
- VERSION = "1.0.0"
4
+ VERSION = "2.0.0"
5
5
  end
data/rqrcode.gemspec CHANGED
@@ -1,36 +1,35 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
1
  lib = File.expand_path("../lib", __FILE__)
4
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
3
  require "rqrcode/version"
6
4
 
7
5
  Gem::Specification.new do |spec|
8
- spec.name = "rqrcode"
9
- spec.version = RQRCode::VERSION
10
- spec.platform = Gem::Platform::RUBY
11
- spec.authors = ["Duncan Robertson"]
12
- spec.email = ["duncan@whomwah.com"]
6
+ spec.name = "rqrcode"
7
+ spec.version = RQRCode::VERSION
8
+ spec.platform = Gem::Platform::RUBY
9
+ spec.authors = ["Duncan Robertson"]
10
+ spec.email = ["duncan@whomwah.com"]
13
11
 
14
- spec.summary = %q{A library to encode QR Codes}
15
- spec.description = <<EOF
16
- rqrcode is a library for encoding QR Codes. The simple
17
- interface allows you to create QR Code data structures
18
- and then render them in the way you choose.
19
- EOF
20
- spec.homepage = "https://github.com/whomwah/rqrcode"
21
- spec.license = "MIT"
12
+ spec.summary = "A library to encode QR Codes"
13
+ spec.description = <<~EOF
14
+ rqrcode is a library for encoding QR Codes. The simple
15
+ interface allows you to create QR Code data structures
16
+ and then render them in the way you choose.
17
+ EOF
18
+ spec.homepage = "https://github.com/whomwah/rqrcode"
19
+ spec.license = "MIT"
22
20
 
23
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
21
+ spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
24
22
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
23
  end
26
- spec.bindir = "exe"
27
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.bindir = "exe"
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
26
  spec.require_paths = ["lib"]
29
27
 
30
- spec.required_ruby_version = '~> 2.3'
31
- spec.add_dependency 'rqrcode_core', '~> 0.1.0'
32
- spec.add_dependency 'chunky_png', "~> 1.0"
28
+ spec.required_ruby_version = ">= 2.3"
29
+ spec.add_dependency "rqrcode_core", "~> 1.0"
30
+ spec.add_dependency "chunky_png", "~> 1.0"
33
31
  spec.add_development_dependency "bundler", "~> 2.0"
34
- spec.add_development_dependency "rake", "~> 12.0"
35
- spec.add_development_dependency "minitest", "~> 5.0"
32
+ spec.add_development_dependency "rake", "~> 13.0"
33
+ spec.add_development_dependency "rspec", "~> 3.5"
34
+ spec.add_development_dependency "standardrb", "~> 1.0"
36
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rqrcode
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Duncan Robertson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-16 00:00:00.000000000 Z
11
+ date: 2021-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rqrcode_core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.0
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.0
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: chunky_png
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -58,28 +58,42 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '12.0'
61
+ version: '13.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '13.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.5'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '12.0'
82
+ version: '3.5'
69
83
  - !ruby/object:Gem::Dependency
70
- name: minitest
84
+ name: standardrb
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: '5.0'
89
+ version: '1.0'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '5.0'
96
+ version: '1.0'
83
97
  description: |
84
98
  rqrcode is a library for encoding QR Codes. The simple
85
99
  interface allows you to create QR Code data structures
@@ -92,7 +106,10 @@ extra_rdoc_files: []
92
106
  files:
93
107
  - ".github/workflows/ruby.yml"
94
108
  - ".gitignore"
109
+ - ".rspec"
110
+ - CHANGELOG.md
95
111
  - Gemfile
112
+ - Gemfile.lock
96
113
  - LICENSE.txt
97
114
  - README.md
98
115
  - Rakefile
@@ -122,7 +139,7 @@ require_paths:
122
139
  - lib
123
140
  required_ruby_version: !ruby/object:Gem::Requirement
124
141
  requirements:
125
- - - "~>"
142
+ - - ">="
126
143
  - !ruby/object:Gem::Version
127
144
  version: '2.3'
128
145
  required_rubygems_version: !ruby/object:Gem::Requirement
@@ -131,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
148
  - !ruby/object:Gem::Version
132
149
  version: '0'
133
150
  requirements: []
134
- rubygems_version: 3.0.1
151
+ rubygems_version: 3.2.15
135
152
  signing_key:
136
153
  specification_version: 4
137
154
  summary: A library to encode QR Codes