Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds viewBox option for SVG #112

Merged
merged 1 commit into from May 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions README.md
Expand Up @@ -95,6 +95,9 @@ standalone - whether to make this a full SVG file, or only an svg to embed
use_path - Use <path> to render SVG rather than <rect> to significantly reduce size
and quality. This will become the default in future versions.
(default false)
viewbox - replace the `svg.width` and `svg.height` attribute with `svg.viewBox` to
allow CSS scaling
(default false)
```
Example
```ruby
Expand All @@ -104,11 +107,11 @@ qrcode = RQRCode::QRCode.new("http://github.com/")

# NOTE: showing with default options specified explicitly
svg = qrcode.as_svg(
offset: 0,
color: '000',
shape_rendering: 'crispEdges',
module_size: 11,
standalone: true
standalone: true,
use_path: true
)
```

Expand Down
12 changes: 9 additions & 3 deletions lib/rqrcode/export/svg.rb
Expand Up @@ -143,27 +143,33 @@ def end_y
# use_path - Use <path> to render SVG rather than <rect> to significantly reduce size
# and quality. This will become the default in future versions.
# (default false)
# viewbox - replace `width` and `height` in <svg> with a viewBox, allows CSS scaling
# (default false)
#
def as_svg(options = {})
fill = options[:fill]
use_path = options[:use_path]
offset = options[:offset].to_i || 0
color = options[:color] || "000"
shape_rendering = options[:shape_rendering] || "crispEdges"
module_size = options[:module_size] || 11
standalone = options[:standalone].nil? ? true : options[:standalone]
viewbox = options[:viewbox].nil? ? false : options[:viewbox]

# height and width dependent on offset and QR complexity
dimension = (@qrcode.module_count * module_size) + (2 * offset)
# use dimensions differently if we are using a viewBox
dimensions_attr = viewbox ? %(viewBox="0 0 #{dimension} #{dimension}") : %(width="#{dimension}" height="#{dimension}")

xml_tag = %(<?xml version="1.0" standalone="yes"?>)
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}">)
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" #{dimensions_attr} shape-rendering="#{shape_rendering}">)
close_tag = "</svg>"

output_tag = (use_path ? Path : Rect).new(@qrcode)
output_tag.build(module_size, offset, color)

if options[:fill]
output_tag.result.unshift %(<rect width="#{dimension}" height="#{dimension}" x="0" y="0" style="fill:##{options[:fill]}"/>)
if fill
output_tag.result.unshift %(<rect width="#{dimension}" height="#{dimension}" x="0" y="0" style="fill:##{fill}"/>)
end

if standalone
Expand Down
4 changes: 4 additions & 0 deletions spec/rqrcode/data.rb
Expand Up @@ -18,6 +18,10 @@
<path d="M0 0h7v7h-7zM8 0h7v2h-1v1h1v1h-2v-2h-1v-1h-2v2h-2v-1h1v-1h-1zM17 0h3v2h1v5h-1v-2h-1v2h-1v-3h-2v-1h2v1h1v-2h-1v-1h-1zM22 0h7v7h-7zM1 1v5h5v-5zM23 1v5h5v-5zM2 2h3v3h-3zM11 2h1v1h-1zM24 2h3v3h-3zM8 4h1v1h-1zM10 4h1v1h1v1h-1v1h-1v-1h-1v-1h1zM13 5h1v1h-1zM15 5h2v2h-1v-1h-1zM8 6h1v1h1v1h2v-2h1v1h1v-1h1v1h-1v1h-2v1h-3v-1h-1zM15 7h1v1h1v1h-1v3h1v-1h1v-1h1v1h-1v2h-1v1h1v1h-2v-2h-1v-1h-1v1h-1v-2h1v-1h1v-1h-1v-1h1zM5 8h2v1h-1v1h2v1h-2v1h1v1h-1v1h-2v-1h1v-2h-1v-1h-1v4h-1v-2h-1v1h-1v-3h1v-1h4zM18 8h3v1h1v-1h1v2h1v-2h1v2h1v-2h1v1h1v-1h1v1h-1v1h-1v1h-1v3h-2v-1h1v-1h-1v-1h-1v3h1v1h-2v-2h-1v-1h1v-1h-2v-2h-2zM12 9h1v1h-1zM1 10v1h1v-1zM10 10h2v2h-1v2h1v1h1v-1h1v-1h1v1h-1v1h1v1h1v2h2v-1h1v-2h1v-1h-1v-2h1v1h1v3h-1v1h-1v2h-3v1h2v1h-3v-1h-1v-2h-1v1h-1v-3h-2v1h-1v-1h-1v1h-2v1h3v1h1v1h-1v1h1v1h2v-2h-1v-1h1v1h1v1h1v1h-1v1h1v-1h1v1h1v1h-1v1h-3v-1h-1v-1h-1v2h1v1h2v2h-1v-1h-2v-1h-1v-2h-1v-1h1v-1h-1v-2h-1v-1h-2v-1h-1v-1h1v-2h1v-1h1v-1h1v-2h1v1h1zM27 12h1v1h-1zM9 13v1h1v-1zM28 13h1v1h-1zM0 14h2v1h1v-1h1v2h-1v1h-1v1h1v1h2v1h-2v1h-1v-2h-1v2h-1zM7 14v1h-1v1h1v-1h1v-1zM24 15h3v3h-2v-1h-1zM22 16h1v1h-1zM28 16h1v3h-1zM14 17v1h1v-1zM20 17h1v2h2v-2h1v3h1v-1h1v1h-1v1h1v-1h2v1h-1v1h-2v1h1v1h-1v1h-1v1h1v-1h3v2h-1v-1h-1v1h-1v2h-1v-2h-1v1h-1v-1h-1v1h-2v-1h-1v-1h-3v-1h1v-1h1v-1h2v-1h-1v-1h1v-2h1zM5 20h2v1h-2zM19 21v1h1v-1zM21 21v3h3v-3zM0 22h7v7h-7zM22 22h1v1h-1zM27 22h1v1h-1zM1 23v5h5v-5zM28 23h1v1h-1zM2 24h3v3h-3zM17 24v1h1v-1zM21 25v1h2v-1zM14 26h1v1h1v1h1v1h-3zM9 27h1v1h-1zM26 27h1v1h-1zM28 27h1v1h-1z" style="fill:#000" transform="translate(0,0) scale(11)"/>
SVG

AS_SVG4 = <<~SVG.chomp
<?xml version="1.0" standalone="yes"?><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" viewBox="0 0 319 319" shape-rendering="crispEdges"><path d="M0 0h7v7h-7zM8 0h7v2h-1v1h1v1h-2v-2h-1v-1h-2v2h-2v-1h1v-1h-1zM17 0h3v2h1v5h-1v-2h-1v2h-1v-3h-2v-1h2v1h1v-2h-1v-1h-1zM22 0h7v7h-7zM1 1v5h5v-5zM23 1v5h5v-5zM2 2h3v3h-3zM11 2h1v1h-1zM24 2h3v3h-3zM8 4h1v1h-1zM10 4h1v1h1v1h-1v1h-1v-1h-1v-1h1zM13 5h1v1h-1zM15 5h2v2h-1v-1h-1zM8 6h1v1h1v1h2v-2h1v1h1v-1h1v1h-1v1h-2v1h-3v-1h-1zM15 7h1v1h1v1h-1v3h1v-1h1v-1h1v1h-1v2h-1v1h1v1h-2v-2h-1v-1h-1v1h-1v-2h1v-1h1v-1h-1v-1h1zM5 8h2v1h-1v1h2v1h-2v1h1v1h-1v1h-2v-1h1v-2h-1v-1h-1v4h-1v-2h-1v1h-1v-3h1v-1h4zM18 8h3v1h1v-1h1v2h1v-2h1v2h1v-2h1v1h1v-1h1v1h-1v1h-1v1h-1v3h-2v-1h1v-1h-1v-1h-1v3h1v1h-2v-2h-1v-1h1v-1h-2v-2h-2zM12 9h1v1h-1zM1 10v1h1v-1zM10 10h2v2h-1v2h1v1h1v-1h1v-1h1v1h-1v1h1v1h1v2h2v-1h1v-2h1v-1h-1v-2h1v1h1v3h-1v1h-1v2h-3v1h2v1h-3v-1h-1v-2h-1v1h-1v-3h-2v1h-1v-1h-1v1h-2v1h3v1h1v1h-1v1h1v1h2v-2h-1v-1h1v1h1v1h1v1h-1v1h1v-1h1v1h1v1h-1v1h-3v-1h-1v-1h-1v2h1v1h2v2h-1v-1h-2v-1h-1v-2h-1v-1h1v-1h-1v-2h-1v-1h-2v-1h-1v-1h1v-2h1v-1h1v-1h1v-2h1v1h1zM27 12h1v1h-1zM9 13v1h1v-1zM28 13h1v1h-1zM0 14h2v1h1v-1h1v2h-1v1h-1v1h1v1h2v1h-2v1h-1v-2h-1v2h-1zM7 14v1h-1v1h1v-1h1v-1zM24 15h3v3h-2v-1h-1zM22 16h1v1h-1zM28 16h1v3h-1zM14 17v1h1v-1zM20 17h1v2h2v-2h1v3h1v-1h1v1h-1v1h1v-1h2v1h-1v1h-2v1h1v1h-1v1h-1v1h1v-1h3v2h-1v-1h-1v1h-1v2h-1v-2h-1v1h-1v-1h-1v1h-2v-1h-1v-1h-3v-1h1v-1h1v-1h2v-1h-1v-1h1v-2h1zM5 20h2v1h-2zM19 21v1h1v-1zM21 21v3h3v-3zM0 22h7v7h-7zM22 22h1v1h-1zM27 22h1v1h-1zM1 23v5h5v-5zM28 23h1v1h-1zM2 24h3v3h-3zM17 24v1h1v-1zM21 25v1h2v-1zM14 26h1v1h1v1h1v1h-3zM9 27h1v1h-1zM26 27h1v1h-1zM28 27h1v1h-1z" style="fill:#000" transform="translate(0,0) scale(11)"/></svg>
SVG

AS_BASIC = <<~STR
XXXXXXXOOOXOXOOXXXOOOOXXXXXXX
XOOOOOXOOXXXXXOOXOXOOOXOOOOOX
Expand Down
11 changes: 10 additions & 1 deletion spec/rqrcode/export_svg_spec.rb
Expand Up @@ -33,11 +33,20 @@
end

context "standalone false" do
it "must export to svg" do
it "will not include the <xml>" do
expect(RQRCode::QRCode.new("https://kyan.com").as_svg(
standalone: false,
use_path: true
)).to eq(AS_SVG3)
end
end

context "viewbox true" do
it "will use the viewBox attr" do
expect(RQRCode::QRCode.new("https://kyan.com").as_svg(
viewbox: true,
use_path: true
)).to eq(AS_SVG4)
end
end
end