-module(qrkit@render@svg).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/qrkit/render/svg.gleam").
-export([default_options/0, with_dark_color/2, with_light_color/2, with_background/2, to_string/2, with_module_size/2, with_margin/2]).
-export_type([svg_options/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(" SVG renderer for qrkit QR codes.\n").
-opaque svg_options() :: {svg_options,
integer(),
integer(),
binary(),
binary(),
boolean()}.
-file("src/qrkit/render/svg.gleam", 19).
?DOC(" Default SVG rendering options.\n").
-spec default_options() -> svg_options().
default_options() ->
{svg_options, 8, 4, <<"#111111"/utf8>>, <<"#ffffff"/utf8>>, true}.
-file("src/qrkit/render/svg.gleam", 52).
?DOC(" Set the dark module colour.\n").
-spec with_dark_color(svg_options(), binary()) -> svg_options().
with_dark_color(Options, Css_color) ->
{svg_options, Module_size, Margin, _, Light_color, Background} = Options,
{svg_options, Module_size, Margin, Css_color, Light_color, Background}.
-file("src/qrkit/render/svg.gleam", 58).
?DOC(" Set the light/background colour.\n").
-spec with_light_color(svg_options(), binary()) -> svg_options().
with_light_color(Options, Css_color) ->
{svg_options, Module_size, Margin, Dark_color, _, Background} = Options,
{svg_options, Module_size, Margin, Dark_color, Css_color, Background}.
-file("src/qrkit/render/svg.gleam", 64).
?DOC(" Toggle the background rectangle.\n").
-spec with_background(svg_options(), boolean()) -> svg_options().
with_background(Options, Draw) ->
{svg_options, Module_size, Margin, Dark_color, Light_color, _} = Options,
{svg_options, Module_size, Margin, Dark_color, Light_color, Draw}.
-file("src/qrkit/render/svg.gleam", 102).
?DOC(
" Escape an attribute value to prevent breaking out of the surrounding\n"
" `\"...\"` quote pair when callers pass user-controlled CSS strings.\n"
).
-spec escape_attribute(binary()) -> binary().
escape_attribute(Value) ->
_pipe = Value,
_pipe@1 = gleam@string:replace(_pipe, <<"&"/utf8>>, <<"&"/utf8>>),
_pipe@2 = gleam@string:replace(_pipe@1, <<"<"/utf8>>, <<"<"/utf8>>),
_pipe@3 = gleam@string:replace(_pipe@2, <<">"/utf8>>, <<">"/utf8>>),
_pipe@4 = gleam@string:replace(_pipe@3, <<"\""/utf8>>, <<"""/utf8>>),
gleam@string:replace(_pipe@4, <<"'"/utf8>>, <<"'"/utf8>>).
-file("src/qrkit/render/svg.gleam", 169).
-spec dark_run_length(list(boolean()), integer()) -> integer().
dark_run_length(Row, Count) ->
case Row of
[true | Rest] ->
dark_run_length(Rest, Count + 1);
_ ->
Count
end.
-file("src/qrkit/render/svg.gleam", 128).
-spec row_path(
list(boolean()),
integer(),
integer(),
integer(),
integer(),
list(binary())
) -> binary().
row_path(Row, Row_index, Module_size, Margin, Col_index, Acc) ->
case Row of
[] ->
_pipe = Acc,
_pipe@1 = lists:reverse(_pipe),
gleam@string:join(_pipe@1, <<""/utf8>>);
[true | Rest] ->
Run = dark_run_length(Rest, 1),
X = (Col_index + Margin) * Module_size,
Y = (Row_index + Margin) * Module_size,
Width = Run * Module_size,
Path = <<<<<<<<<<<<<<<<<<<<"M"/utf8,
(erlang:integer_to_binary(X))/binary>>/binary,
" "/utf8>>/binary,
(erlang:integer_to_binary(Y))/binary>>/binary,
"h"/utf8>>/binary,
(erlang:integer_to_binary(Width))/binary>>/binary,
"v"/utf8>>/binary,
(erlang:integer_to_binary(Module_size))/binary>>/binary,
"H"/utf8>>/binary,
(erlang:integer_to_binary(X))/binary>>/binary,
"z"/utf8>>,
row_path(
gleam@list:drop(Row, Run),
Row_index,
Module_size,
Margin,
Col_index + Run,
[Path | Acc]
);
[false | Rest@1] ->
row_path(Rest@1, Row_index, Module_size, Margin, Col_index + 1, Acc)
end.
-file("src/qrkit/render/svg.gleam", 111).
-spec path_data(
list(list(boolean())),
integer(),
integer(),
integer(),
list(binary())
) -> binary().
path_data(Rows, Module_size, Margin, Row_index, Acc) ->
case Rows of
[] ->
_pipe = Acc,
_pipe@1 = lists:reverse(_pipe),
gleam@string:join(_pipe@1, <<""/utf8>>);
[Row | Rest] ->
path_data(
Rest,
Module_size,
Margin,
Row_index + 1,
[row_path(Row, Row_index, Module_size, Margin, 0, []) | Acc]
)
end.
-file("src/qrkit/render/svg.gleam", 70).
?DOC(" Render a QR code as an SVG document string.\n").
-spec to_string(qrkit:qr_code(), svg_options()) -> binary().
to_string(Qr, Options) ->
{svg_options, Module_size, Margin, Dark_color, Light_color, Background} = Options,
Total_width = (qrkit:width(Qr) + (Margin * 2)) * Module_size,
Total_height = (qrkit:height(Qr) + (Margin * 2)) * Module_size,
Background_tag = case Background of
true ->
<<<<<<<<<<<<"<rect width=\""/utf8,
(erlang:integer_to_binary(Total_width))/binary>>/binary,
"\" height=\""/utf8>>/binary,
(erlang:integer_to_binary(Total_height))/binary>>/binary,
"\" fill=\""/utf8>>/binary,
(escape_attribute(Light_color))/binary>>/binary,
"\"/>"/utf8>>;
false ->
<<""/utf8>>
end,
Path_data = path_data(qrkit:rows(Qr), Module_size, Margin, 0, []),
<<<<<<<<<<<<<<<<<<<<"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 "/utf8,
(erlang:integer_to_binary(
Total_width
))/binary>>/binary,
" "/utf8>>/binary,
(erlang:integer_to_binary(Total_height))/binary>>/binary,
"\" shape-rendering=\"crispEdges\">"/utf8>>/binary,
Background_tag/binary>>/binary,
"<path fill=\""/utf8>>/binary,
(escape_attribute(Dark_color))/binary>>/binary,
"\" d=\""/utf8>>/binary,
Path_data/binary>>/binary,
"\"/></svg>"/utf8>>.
-file("src/qrkit/render/svg.gleam", 176).
-spec positive_or(integer(), integer()) -> integer().
positive_or(Value, Default) ->
case Value > 0 of
true ->
Value;
false ->
Default
end.
-file("src/qrkit/render/svg.gleam", 26).
?DOC(
" Set the SVG module size.\n"
"\n"
" Values less than 1 are normalised to 1 to keep the rendered output usable.\n"
).
-spec with_module_size(svg_options(), integer()) -> svg_options().
with_module_size(Options, Px) ->
{svg_options, _, Margin, Dark_color, Light_color, Background} = Options,
{svg_options,
positive_or(Px, 1),
Margin,
Dark_color,
Light_color,
Background}.
-file("src/qrkit/render/svg.gleam", 183).
-spec non_negative_or(integer(), integer()) -> integer().
non_negative_or(Value, Default) ->
case Value >= 0 of
true ->
Value;
false ->
Default
end.
-file("src/qrkit/render/svg.gleam", 40).
?DOC(
" Set the quiet-zone margin in modules.\n"
"\n"
" Negative values are normalised to 0.\n"
).
-spec with_margin(svg_options(), integer()) -> svg_options().
with_margin(Options, Modules) ->
{svg_options, Module_size, _, Dark_color, Light_color, Background} = Options,
{svg_options,
Module_size,
non_negative_or(Modules, 0),
Dark_color,
Light_color,
Background}.