Skip to content

Commit

Permalink
Allow flatten render for the svg
Browse files Browse the repository at this point in the history
Added a new option `flatten` to the `%SvgSettings{}`.
This will allow `<path d="<data>" />` to be rendered.

Benefits:

1. Smaller files / markup;
2. Prevent "spacing" glitch that appear between
the `rects` due to pixel density.
  • Loading branch information
cmnstmntmn authored and s-m-i-t-a committed Oct 2, 2024
1 parent 3cc83d6 commit b55346a
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ tags
.projections.json

.elixir_ls/
.DS_Store
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ There are several options to change the appearance of svg or png:
| background_opacity | nil or 0.0 <= x <= 1.0 | nil | sets background opacity of svg |
| background_color | string or {r, g, b} | "#ffffff" | sets background color of svg |
| qrcode_color | string or {r, g, b} | "#000000" | sets color of QR |
| flatten | boolean | false | renders path data instead of rects | |
| image | {string, size} or nil | nil | puts the image to the center of svg |
| structure | :minify or :readable | :minify | minifies or makes readable svg file |
```
Expand Down
21 changes: 16 additions & 5 deletions lib/qr_code/render/svg.ex
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ defmodule QRCode.Render.Svg do
|> construct_svg(settings)
end

defp construct_body(matrix, svg, %SvgSettings{scale: scale}) do
defp construct_body(matrix, svg, %SvgSettings{scale: scale, flatten: flatten}) do
{rank_matrix, _} = Matrix.size(matrix)

%{
svg
| body:
matrix
|> find_nonzero_element()
|> Enum.map(&create_rect(&1, scale)),
|> Enum.map(&create_body(&1, scale, flatten)),
rank_matrix: rank_matrix
}
end
Expand All @@ -69,6 +69,7 @@ defmodule QRCode.Render.Svg do
background_color: bg,
image: image,
qrcode_color: qc,
flatten: flatten,
scale: scale,
structure: structure
}
Expand All @@ -79,12 +80,11 @@ defmodule QRCode.Render.Svg do
xlink: xlink,
width: rank_matrix * scale,
height: rank_matrix * scale
}, [background_rect(bg, bg_tr), to_group(body, qc), put_image(image)]}
}, [background_rect(bg, bg_tr), body_type(body, qc, flatten), put_image(image)]}
|> XmlBuilder.generate(format: format(structure))
end

# Helpers

defp background_settings(color) do
%{
width: "100%",
Expand All @@ -93,10 +93,17 @@ defmodule QRCode.Render.Svg do
}
end

defp create_rect({x_pos, y_pos}, scale) do
defp body_type(body, qc, false), do: to_group(body, qc)
defp body_type(body, qc, true), do: to_path(body, qc)

defp create_body({x_pos, y_pos}, scale, false) do
{:rect, %{width: scale, height: scale, x: scale * x_pos, y: scale * y_pos}, nil}
end

defp create_body({x_pos, y_pos}, scale, true) do
~s(M#{scale * x_pos} #{scale * y_pos}h#{scale}v#{scale}H#{scale * x_pos}z)
end

defp background_rect(color, nil) do
{:rect, background_settings(color), nil}
end
Expand All @@ -115,6 +122,10 @@ defmodule QRCode.Render.Svg do
{:g, %{fill: to_hex(color)}, body}
end

defp to_path(body, color) do
{:path, %{fill: to_hex(color), d: body}, nil}
end

defp put_image(nil), do: ""

defp put_image({path_to_image, size}) when is_binary(path_to_image) and 0 < size do
Expand Down
3 changes: 3 additions & 0 deletions lib/qr_code/render/svg_settings.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ defmodule QRCode.Render.SvgSettings do
@type background_opacity :: ExMaybe.t(float())
@type background_color :: String.t() | tuple
@type qrcode_color :: String.t() | tuple
@type flatten :: boolean()
@type structure :: :minify | :readable

@type t :: %__MODULE__{
Expand All @@ -25,6 +26,7 @@ defmodule QRCode.Render.SvgSettings do
background_opacity: background_opacity,
background_color: background_color,
qrcode_color: qrcode_color,
flatten: flatten,
structure: structure
}

Expand All @@ -33,5 +35,6 @@ defmodule QRCode.Render.SvgSettings do
background_opacity: nil,
background_color: "#ffffff",
qrcode_color: "#000000",
flatten: false,
structure: :minify
end

0 comments on commit b55346a

Please sign in to comment.