main
Kyle Zheng 2024-09-13 03:52:47 -04:00
rodzic a463c790b7
commit ce6461085a
43 zmienionych plików z 392 dodań i 945 usunięć

Wyświetl plik

@ -122,14 +122,16 @@ A preset must export `paramsSchema` and either `renderSVG` or `renderCanvas`
This schema defines the UI components whose values are passed into `renderSVG` or `renderCanvas` via the `params` object.
All properties besides `type` are optional, except
- type `select` must have a nonempty options array
- type `array` must have a valid `props` value.
In this example, `default` is set explicitly to the implicit default value.
```js
export const paramsSchema = {
Example1: {
type: "number"
type: "number",
min: 0,
max: 10,
step: 0.1,
@ -141,29 +143,29 @@ export const paramsSchema = {
},
Example3: {
type: "color",
default: "#000000"
default: "#000000", // css color string (hex/rgba/hsla)
},
Example4: {
type: "select",
options: ["I'm feeling", 22]
default: "I'm feeling",
options: ["I'm feeling", 22],
default: "I'm feeling", // first option
},
Example5: {
type: "file",
accept: ".jpeg, .jpg, .png"
accept: ".jpeg, .jpg, .png",
default: null,
},
Example6: {
type: "array",
props: {
type: "number" // any type except "array"
type: "number", // any type except "array"
// corresponding props
},
resizable: true,
defaultLength: 5, // overridden by default
default: [], // overrides defaultLength
}
}
},
};
```
## `renderSVG` and `renderCanvas`
@ -180,27 +182,24 @@ type renderCanvas = (qr: Qr, params: Params, canvas: OffscreenCanvas) => void;
```ts
type Qr = {
matrix: Module[] // see below
matrix: Uint8Array; // see below
version: number; // 1- 40
mask: number; // 0 - 8,
mask: number; // 0 - 7,
ecl: number; // 0 - 3, Low, Medium, Quartile, High
mode: number; // 0 - 2, Numeric, Alphanumeric, Byte
};
enum Module {
DataOFF = 0,
DataON = 1,
FinderOFF = 2,
FinderON = 3,
AlignmentOFF = 4,
AlignmentON = 5,
TimingOFF = 6,
TimingON = 7,
FormatOFF = 8,
FormatON = 9,
VersionOFF = 10,
VersionON = 11,
SeparatorOFF = 12,
}
// bit flags for each u8 in matrix
const Module = {
ON: 1 << 0,
DATA: 1 << 1,
FINDER: 1 << 2,
ALIGNMENT: 1 << 3,
TIMING: 1 << 4,
FORMAT: 1 << 5,
VERSION: 1 << 6,
MODIFIER: 1 << 7,
};
```
`MODIFIER` is set for Finder and Alignment centers, Format and Version copy.

Wyświetl plik

@ -2,7 +2,7 @@
"name": "qrframe",
"type": "module",
"scripts": {
"dev": "vinxi dev",
"dev": "nr presets dev && vinxi dev",
"build": "vinxi build",
"start": "vinxi start",
"presets": "node updatePresets"
@ -22,7 +22,7 @@
"@thisbeyond/solid-dnd": "^0.7.5",
"@unocss/reset": "^0.59.4",
"codemirror": "^6.0.1",
"fuqr": "^0.0.6",
"fuqr": "^0.0.7",
"lucide-solid": "^0.378.0",
"solid-js": "^1.8.17",
"unocss": "^0.59.4",

Wyświetl plik

@ -55,8 +55,8 @@ importers:
specifier: ^6.0.1
version: 6.0.1(@lezer/common@1.2.1)
fuqr:
specifier: ^0.0.6
version: 0.0.6
specifier: ^0.0.7
version: 0.0.7
lucide-solid:
specifier: ^0.378.0
version: 0.378.0(solid-js@1.8.17)
@ -1790,8 +1790,8 @@ packages:
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
fuqr@0.0.6:
resolution: {integrity: sha512-pYq22vaBSzVEJJ9lkh11kFMdDtv++saB09I/dGSB5gL3GUTVrV0M1l5FDiSIjLisylrUOKsBXuSfH70a3desjg==}
fuqr@0.0.7:
resolution: {integrity: sha512-5+s5Lr0DaizSQwSsA+grIMK5DrVg45KOHIHe4oHCLvlfmIHba1iZSVvLchYLDZq/BbKyZUdPk6jeZa4QegD+Xw==}
gauge@3.0.2:
resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==}
@ -4801,7 +4801,7 @@ snapshots:
function-bind@1.1.2: {}
fuqr@0.0.6: {}
fuqr@0.0.7: {}
gauge@3.0.2:
dependencies:

Wyświetl plik

@ -1,5 +1,7 @@
// Based on QRBTF's Line style
// https://github.com/CPunisher/react-qrbtf/blob/master/src/components/QRLine.tsx
import { Module, getSeededRand } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -28,36 +30,8 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const rangeStr = (min, max) => (rand() * (max - min) + min).toFixed(2);
const matrixWidth = qr.version * 4 + 17;
@ -117,9 +91,9 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = matrix(x, y);
if ((module | 1) === Module.FinderON) continue;
if (module & Module.FINDER) continue;
if (!(module & 1)) continue;
if (!(module & Module.ON)) continue;
dotsLayer += `<circle cx="${x + 0.5}" cy="${y + 0.5}" r="${rangeStr(0.2, 0.4)}"/>`;
if (!visited1(x, y)) {
@ -128,7 +102,7 @@ export function renderSVG(qr, params) {
while (
nx < matrixWidth &&
ny < matrixWidth &&
matrix(nx, ny) & 1 &&
matrix(nx, ny) & Module.ON &&
!visited1(nx, ny)
) {
setVisited1(nx, ny);
@ -146,7 +120,7 @@ export function renderSVG(qr, params) {
while (
nx >= 0 &&
ny < matrixWidth &&
matrix(nx, ny) & 1 &&
matrix(nx, ny) & Module.ON &&
!visited2(nx, ny)
) {
setVisited2(nx, ny);

Wyświetl plik

@ -1,3 +1,5 @@
import { Module } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -52,22 +54,6 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
export async function renderSVG(qr, params) {
const matrixWidth = qr.version * 4 + 17;
const margin = params["Margin"];
@ -142,8 +128,8 @@ export async function renderSVG(qr, params) {
continue;
}
const module = qr.matrix[y * matrixWidth + x];
if (!(module & 1)) continue;
if (module === Module.FinderON) continue;
if (!(module & Module.ON)) continue;
if (module & Module.FINDER) continue;
if (defaultShape) {
if (roundness) {

Wyświetl plik

@ -1,5 +1,7 @@
// Based on QRBTF's DSJ style
// https://github.com/CPunisher/react-qrbtf/blob/master/src/components/QRDsj.tsx
import { Module } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -51,22 +53,6 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
export function renderSVG(qr, params) {
const matrixWidth = qr.version * 4 + 17;
const margin = params["Margin"];
@ -122,8 +108,8 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = matrix(x, y);
if ((module | 1) === Module.FinderON) continue;
if (!(module & 1)) continue;
if (module & Module.FINDER) continue;
if (!(module & Module.ON)) continue;
if (visited(x, y)) continue;
setVisited(x, y);
@ -157,9 +143,13 @@ export function renderSVG(qr, params) {
if (
y < matrixWidth - 1 &&
x < matrixWidth - 1 &&
matrix(x + 1, y) & matrix(x, y + 1) & matrix(x + 1, y + 1) & 1
matrix(x + 1, y) & matrix(x, y + 1) & matrix(x + 1, y + 1) & Module.ON
) {
if (!visited(x + 1, y) && !visited(x + 1, y + 1) && !visited(x, y + 1)) {
if (
!visited(x + 1, y) &&
!visited(x + 1, y + 1) &&
!visited(x, y + 1)
) {
crossLayer += `<g>`;
crossLayer += `<line x1="${x + co}" y1="${y + co}" x2="${x + 2 - co}" y2="${y + 2 - co}"/>`;
crossLayer += `<line x1="${x + 2 - co}" y1="${y + co}" x2="${x + co}" y2="${y + 2 - co}"/>`;
@ -173,7 +163,7 @@ export function renderSVG(qr, params) {
}
let ny = y + 1;
while (ny < matrixWidth && matrix(x, ny) & 1 && !visited(x, ny)) {
while (ny < matrixWidth && matrix(x, ny) & Module.ON && !visited(x, ny)) {
ny++;
}
if (ny - y > 2) {
@ -186,7 +176,7 @@ export function renderSVG(qr, params) {
}
let nx = x + 1;
while (nx < matrixWidth && matrix(nx, y) & 1 && !visited(nx, y)) {
while (nx < matrixWidth && matrix(nx, y) & Module.ON && !visited(nx, y)) {
setVisited(nx, y);
nx++;
}

Wyświetl plik

@ -1,5 +1,7 @@
// Based on QRBTF's Bubble style
// https://github.com/CPunisher/react-qrbtf/blob/master/src/components/QRBubble.tsx
import { Module, getSeededRand } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -43,36 +45,8 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const rangeStr = params["Randomize circle size"]
? (min, max) => (rand() * (max - min) + min).toFixed(2)
@ -116,7 +90,7 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = matrix(x, y);
if ((module | 1) === Module.FinderON) continue;
if (module & Module.FINDER) continue;
if (visited(x, y)) continue;
if (
@ -140,13 +114,16 @@ export function renderSVG(qr, params) {
setVisited(x + 1, y + 2);
continue;
}
if (!(module & 1)) continue;
if (!(module & Module.ON)) continue;
setVisited(x, y);
if (
y < matrixWidth - 1 &&
x < matrixWidth - 1 &&
matrix(x + 1, y) & matrix(x, y + 1) & matrix(x + 1, y + 1) & 1 &&
matrix(x + 1, y) &
matrix(x, y + 1) &
matrix(x + 1, y + 1) &
Module.ON &&
!visited(x + 1, y) &&
!visited(x + 1, y + 1)
) {
@ -156,12 +133,20 @@ export function renderSVG(qr, params) {
setVisited(x + 1, y + 1);
continue;
}
if (x < matrixWidth - 1 && matrix(x + 1, y) & 1 && !visited(x + 1, y)) {
if (
x < matrixWidth - 1 &&
matrix(x + 1, y) & Module.ON &&
!visited(x + 1, y)
) {
layer3 += `<circle cx="${x + 1}" cy="${y + 0.5}" r="${rangeStr(0.4, 0.6)}"/>`;
setVisited(x + 1, y);
continue;
}
if (y < matrixWidth - 1 && matrix(x, y + 1) & 1 && !visited(x, y + 1)) {
if (
y < matrixWidth - 1 &&
matrix(x, y + 1) & Module.ON &&
!visited(x, y + 1)
) {
layer3 += `<circle cx="${x + 0.5}" cy="${y + 1}" r="${rangeStr(0.3, 0.5)}"/>`;
setVisited(x, y + 1);
continue;

Wyświetl plik

@ -1,3 +1,5 @@
import { Module, getSeededRand } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Foreground: {
type: "color",
@ -30,36 +32,8 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const margin = params["Margin"];
const quietZone = params["Quiet zone"];
const fg = params["Foreground"];
@ -68,18 +42,18 @@ export function renderSVG(qr, params) {
const qrWidth = qr.version * 4 + 17;
const matrixWidth = qrWidth + 2 * margin;
const newMatrix = Array(matrixWidth * matrixWidth).fill(Module.DataOFF);
const newMatrix = Array(matrixWidth * matrixWidth).fill(0);
const visited = new Uint16Array(matrixWidth * matrixWidth);
// Copy qr to matrix with margin and randomly set pixels in margin
for (let y = 0; y < margin - quietZone; y++) {
for (let x = 0; x < matrixWidth; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
}
for (let y = margin - quietZone; y < margin + qrWidth + quietZone; y++) {
for (let x = 0; x < margin - quietZone; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
if (y >= margin && y < margin + qrWidth) {
for (let x = margin; x < matrixWidth - margin; x++) {
@ -88,12 +62,28 @@ export function renderSVG(qr, params) {
}
}
for (let x = margin + qrWidth + quietZone; x < matrixWidth; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
}
for (let y = margin + qrWidth + quietZone; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
}
if (quietZone === 0 && margin > 0) {
for (let x = margin; x < margin + 7; x++) {
newMatrix[(margin - 1) * matrixWidth + x] = 0;
newMatrix[(margin - 1) * matrixWidth + x + qrWidth - 7] = 0;
}
for (let y = margin; y < margin + 7; y++) {
newMatrix[y * matrixWidth + margin - 1] = 0;
newMatrix[y * matrixWidth + matrixWidth - margin] = 0;
}
for (let y = margin + qrWidth - 7; y < margin + qrWidth; y++) {
newMatrix[y * matrixWidth + margin - 1] = 0;
}
for (let x = margin; x < margin + 7; x++) {
newMatrix[(matrixWidth - margin) * matrixWidth + x] = 0;
}
}
@ -108,8 +98,8 @@ export function renderSVG(qr, params) {
let baseY;
const on = params["Invert"]
? (x, y) => (newMatrix[y * matrixWidth + x] & 1) === 0
: (x, y) => (newMatrix[y * matrixWidth + x] & 1) === 1;
? (x, y) => (newMatrix[y * matrixWidth + x] & Module.ON) === 0
: (x, y) => (newMatrix[y * matrixWidth + x] & Module.ON) !== 0;
function goRight(x, y, path, cw) {
let sx = x;

Wyświetl plik

@ -1,3 +1,5 @@
import { Module, getSeededRand } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -60,34 +62,6 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
const fmt = (n) => n.toFixed(2).replace(/.00$/, "");
export async function renderSVG(qr, params) {
@ -99,7 +73,7 @@ export async function renderSVG(qr, params) {
const file = params["Logo"];
const logoRatio = params["Logo size"];
const showLogoData = params["Show data behind logo"];
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const range = (min, max) => rand() * (max - min) + min;
const size = matrixWidth + 2 * margin;
@ -183,26 +157,16 @@ export async function renderSVG(qr, params) {
if (x >= 0 && x < matrixWidth && y >= 0 && y < matrixWidth) {
const module = qr.matrix[y * matrixWidth + x];
if (!(module & 1)) continue;
if (!(module & Module.ON)) continue;
if (
params["Finder pattern"] !== "Default" &&
(module | 1) === Module.FinderON
) {
if (params["Finder pattern"] !== "Default" && module & Module.FINDER) {
continue;
}
if (
params["Alignment pattern"] !== "Default" &&
module === Module.AlignmentON
module & Module.ALIGNMENT
) {
if (
!(
(qr.matrix[(y - 1) * matrixWidth + x] |
qr.matrix[y * matrixWidth + x + 1] |
qr.matrix[(y + 1) * matrixWidth + x]) &
1
)
) {
if (module & Module.MODIFIER) {
if (params["Alignment pattern"] === "Circle") {
svg += `M${x + 0.5},${y - 2}a2.5,2.5 0,0,0 0,5a2.5,2.5 0,0,0 0,-5`;
svg += `M${x + 0.5},${y - 1}a1.5,1.5 0,0,1 0,3a1.5,1.5 0,0,1 0,-3`;

Wyświetl plik

@ -1,3 +1,5 @@
import { Module, getSeededRand } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -64,38 +66,10 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const unit = params["Density"];
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const rangeStr = (min, max) => (rand() * (max - min) + min).toFixed(2);
const matrixWidth = qr.version * 4 + 17;
const margin = params["Margin"] * unit;
@ -119,9 +93,9 @@ export function renderSVG(qr, params) {
const qx = Math.floor((x + center) / unit);
const qy = Math.floor((y + center) / unit);
if (qx >= 0 && qx < matrixWidth && qy >= 0 && qy < matrixWidth) {
if (qr.matrix[qy * matrixWidth + qx] & 1) {
if (qr.matrix[qy * matrixWidth + qx] & Module.ON) {
const rad =
qr.matrix[qy * matrixWidth + qx] === Module.FinderON
qr.matrix[qy * matrixWidth + qx] & Module.FINDER
? params["Finder clarity"]
: dotRadius;
svg += `<circle cx="${(center + x).toFixed(2)}" cy="${(center + y).toFixed(2)}" r="${rad}" />`;

Wyświetl plik

@ -1,3 +1,4 @@
import { Module, getSeededRand } from "REPLACE_URL/utils.js";
import rough from "https://esm.sh/roughjs";
export const paramsSchema = {
@ -74,34 +75,6 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
const domMock = {
ownerDocument: {
createElementNS: (_ns, tagName) => {
@ -148,7 +121,7 @@ export function renderSVG(qr, params) {
x === matrixWidth - 1 ||
y === matrixWidth - 1
) {
matrix.push(Module.DataOFF);
matrix.push(0);
} else {
matrix.push(qr.matrix[(y - 1) * (matrixWidth - 2) + x - 1]);
}
@ -172,8 +145,8 @@ export function renderSVG(qr, params) {
let baseY;
const on = params["Invert"]
? (x, y) => (matrix[y * matrixWidth + x] & 1) === 0
: (x, y) => (matrix[y * matrixWidth + x] & 1) === 1;
? (x, y) => (matrix[y * matrixWidth + x] & Module.ON) === 0
: (x, y) => (matrix[y * matrixWidth + x] & Module.ON) !== 0;
function goRight(x, y, shape, cw) {
let sx = x;

Wyświetl plik

@ -1,3 +1,5 @@
import { Module, getSeededRand } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -51,20 +53,8 @@ export const paramsSchema = {
},
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const margin = params["Margin"];
const unit = 4;
@ -245,7 +235,7 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
if (matrix[y * matrixWidth + x] & 1) {
if (matrix[y * matrixWidth + x] & Module.ON) {
qrLayer += `M${x * unit},${y * unit}h${unit}v${unit}h-${unit}z`;
}

Wyświetl plik

@ -1,4 +1,5 @@
// Halftone is a misnomer, but that's what this type of QR code is known as
import { Module } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Image: {
type: "file",
@ -43,22 +44,6 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
export async function renderCanvas(qr, params, canvas) {
const unit = 3;
const pixel = 1;
@ -90,7 +75,7 @@ export async function renderCanvas(qr, params, canvas) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = qr.matrix[y * matrixWidth + x];
if (module & 1) {
if (module & Module.ON) {
const px = x + margin;
const py = y + margin;
ctx.fillRect(px * unit, py * unit, unit, unit);
@ -149,7 +134,7 @@ export async function renderCanvas(qr, params, canvas) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = qr.matrix[y * matrixWidth + x];
if (module & 1) {
if (module & Module.ON) {
ctx.fillStyle = fg;
} else {
ctx.fillStyle = bg;
@ -158,11 +143,10 @@ export async function renderCanvas(qr, params, canvas) {
const px = x + margin;
const py = y + margin;
const type = module | 1;
if (
type === Module.FinderON ||
(alignment && type === Module.AlignmentON) ||
(timing && type === Module.TimingON)
module & Module.FINDER ||
(alignment && module & Module.ALIGNMENT) ||
(timing && module & Module.TIMING)
) {
ctx.fillRect(px * unit, py * unit, unit, unit);
} else {

Wyświetl plik

@ -1,3 +1,5 @@
import { Module } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -85,7 +87,7 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = qr.matrix[y * matrixWidth + x];
if (module & 1) {
if (module & Module.ON) {
svg += `M${x},${y}h1v1h-1z`;
}
}

Wyświetl plik

@ -1,3 +1,5 @@
import { Module } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -16,22 +18,6 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
export function renderSVG(qr, params) {
const matrixWidth = qr.version * 4 + 17;
const unit = 10;
@ -66,11 +52,11 @@ export function renderSVG(qr, params) {
for (let x = 0; x < matrixWidth; x++) {
const module = qr.matrix[y * matrixWidth + x];
if ((module | 1) === Module.FinderON) {
if (module & Module.FINDER) {
continue;
}
if (module & 1) {
if (module & Module.ON) {
const sx = x * unit + offset;
const sy = y * unit + offset;
svg += `M${sx},${sy}h${dataSize}v${dataSize}h-${dataSize}z`;

Wyświetl plik

@ -1,3 +1,5 @@
import { Module, getSeededRand } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -35,20 +37,8 @@ export const paramsSchema = {
},
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const margin = params["Margin"];
const unit = 20;
@ -90,7 +80,7 @@ export function renderSVG(qr, params) {
if (visited[y * matrixWidth + x]) continue;
let layer = "";
const on = module & 1;
const on = module & Module.ON;
visited[y * matrixWidth + x] = true;
let width = 1;
@ -98,7 +88,7 @@ export function renderSVG(qr, params) {
while (
x + width < matrixWidth &&
(matrix[y * matrixWidth + x + width] & 1) === on &&
(matrix[y * matrixWidth + x + width] & Module.ON) === on &&
!visited[y * matrixWidth + x + width]
) {
visited[y * matrixWidth + x + width] = true;
@ -107,7 +97,7 @@ export function renderSVG(qr, params) {
outer: while (y + height < matrixWidth) {
for (let i = 0; i < width; i++) {
if ((matrix[(y + height) * matrixWidth + x + i] & 1) !== on) {
if ((matrix[(y + height) * matrixWidth + x + i] & Module.ON) !== on) {
break outer;
}
}

Wyświetl plik

@ -1,3 +1,5 @@
import { Module, getSeededRand } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Foreground: {
type: "array",
@ -51,36 +53,8 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const margin = params["Margin"];
const colors = params["Foreground"];
const bg = params["Background"];
@ -88,18 +62,18 @@ export function renderSVG(qr, params) {
const qrWidth = qr.version * 4 + 17;
const matrixWidth = qrWidth + 2 * margin;
const newMatrix = Array(matrixWidth * matrixWidth).fill(Module.DataOFF);
const newMatrix = Array(matrixWidth * matrixWidth).fill(0);
const visited = new Uint16Array(matrixWidth * matrixWidth);
// Copy qr to matrix with margin and randomly set pixels in margin
for (let y = 0; y < margin - 1; y++) {
for (let x = 0; x < matrixWidth; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
}
for (let y = margin - 1; y < margin + qrWidth + 1; y++) {
for (let x = 0; x < margin - 1; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
if (y >= margin && y < margin + qrWidth) {
for (let x = margin; x < matrixWidth - margin; x++) {
@ -108,30 +82,28 @@ export function renderSVG(qr, params) {
}
}
for (let x = margin + qrWidth + 1; x < matrixWidth; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
}
for (let y = margin + qrWidth + 1; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
}
if (params["Quiet zone"] === "Minimal") {
for (let x = margin + 8; x < matrixWidth - margin - 8; x++) {
if (rand() > 0.5)
newMatrix[(margin - 1) * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[(margin - 1) * matrixWidth + x] = Module.ON;
}
for (let y = margin + 8; y < matrixWidth - margin; y++) {
if (y < matrixWidth - margin - 8) {
if (rand() > 0.5)
newMatrix[y * matrixWidth + margin - 1] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + margin - 1] = Module.ON;
}
if (rand() > 0.5)
newMatrix[y * matrixWidth + matrixWidth - margin] = Module.DataON;
newMatrix[y * matrixWidth + matrixWidth - margin] = Module.ON;
}
for (let x = margin + 8; x < matrixWidth - margin + 1; x++) {
if (rand() > 0.5)
newMatrix[(matrixWidth - margin) * matrixWidth + x] = Module.DataON;
newMatrix[(matrixWidth - margin) * matrixWidth + x] = Module.ON;
}
}
@ -156,8 +128,8 @@ export function renderSVG(qr, params) {
let baseY;
const on = params["Invert"]
? (x, y) => (newMatrix[y * matrixWidth + x] & 1) === 0
: (x, y) => (newMatrix[y * matrixWidth + x] & 1) === 1;
? (x, y) => (newMatrix[y * matrixWidth + x] & Module.ON) === 0
: (x, y) => (newMatrix[y * matrixWidth + x] & Module.ON) !== 0;
function goRight(x, y, shape, cw) {
let sx = x;
@ -303,7 +275,7 @@ export function renderSVG(qr, params) {
for (let x = 0; x < matrixWidth; x++) {
if (visited[y * matrixWidth + x]) continue;
if ((newMatrix[y * matrixWidth + x] | 1) === Module.FinderON) {
if (newMatrix[y * matrixWidth + x] & Module.FINDER) {
thin = params["Finder thickness"];
offset = (unit - thin) / 2;
} else {

Wyświetl plik

@ -1,5 +1,7 @@
// Based on QRBTF's A1P style
// https://github.com/CPunisher/react-qrbtf/blob/master/src/components/QRNormal.tsx
import { Module, getSeededRand } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -32,36 +34,8 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const range = (min, max) =>
Math.trunc(100 * (rand() * (max - min) + min)) / 100;
@ -112,7 +86,7 @@ export function renderSVG(qr, params) {
let dotsLayer = `<g fill="${fg}">`;
function on(x, y) {
return (qr.matrix[y * matrixWidth + x] & 1) === 1;
return (qr.matrix[y * matrixWidth + x] & Module.ON) !== 0;
}
const visitArray = Array.from({ length: matrixWidth * matrixWidth }).fill(
@ -134,7 +108,7 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = qr.matrix[y * matrixWidth + x];
if ((module | 1) === Module.FinderON) continue;
if (module & Module.FINDER) continue;
if (params["Particles"] && y < matrixWidth - 2 && x < matrixWidth - 2) {
let xCross = false;

Wyświetl plik

@ -1,3 +1,5 @@
import { Module } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -31,22 +33,6 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
export function renderSVG(qr, params) {
const unit = 16;
const gap = 2;
@ -60,9 +46,7 @@ export function renderSVG(qr, params) {
const bg = params["Background"];
const grout = params["Grout"];
const newMatrix = Array.from({ length: matrixWidth * matrixWidth }).fill(
Module.DataOFF
);
const newMatrix = Array.from({ length: matrixWidth * matrixWidth }).fill(0);
const start = margin;
const end = matrixWidth - 1 - margin;
@ -72,29 +56,29 @@ export function renderSVG(qr, params) {
for (let x = 0; x < matrixWidth; x++) {
// outer square
if (y === start - outer && x >= start - outer && x <= end + outer) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
} else if (
(x === start - outer || x === end + outer) &&
y >= start - outer + 1 &&
y <= end + outer - 1
) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
newMatrix[y * matrixWidth + x] = Module.ON;
} else if (y === end + outer && x >= start - outer && x <= end + outer) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
}
// inner square
else if (y === start - inner && x >= start - inner && x <= end + inner) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
} else if (
(x === start - inner || x === end + inner) &&
y >= start - inner + 1 &&
y <= end + inner - 1
) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
newMatrix[y * matrixWidth + x] = Module.ON;
} else if (y === end + inner && x >= start - inner && x <= end + inner) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
}
// qr code w/ quiet zone
else if (
@ -121,16 +105,16 @@ export function renderSVG(qr, params) {
x < end + outer
) {
if ((x + y) & 1) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
}
// outside squares
} else {
if (x % 4 && y % 4) {
if ((x % 8 < 4 && y % 8 < 4) || (x % 8 > 4 && y % 8 > 4)) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
}
} else {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
}
}
}
@ -146,8 +130,8 @@ export function renderSVG(qr, params) {
for (let x = 0; x < matrixWidth; x++) {
const module = newMatrix[y * matrixWidth + x];
let tiles;
if (module & 1) {
if (module === Module.FinderON) {
if (module & Module.ON) {
if (module & Module.FINDER) {
svg += `M${x * unit},${y * unit}h${unit}v${unit}h-${unit}z`;
continue;
}
@ -161,7 +145,7 @@ export function renderSVG(qr, params) {
const ny = y * unit + offset + dy * (tile + gap);
for (let dx = 0; dx < tiles; dx++) {
const nx = x * unit + offset + dx * (tile + gap);
if (module & 1) {
if (module & Module.ON) {
svg += `M${nx},${ny}h${tile}v${tile}h-${tile}z`;
} else {
layer += `M${nx},${ny}h${tile}v${tile}h-${tile}z`;

Wyświetl plik

@ -1,3 +1,4 @@
import { Module } from "REPLACE_URL/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -30,7 +31,7 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = qr.matrix[y * matrixWidth + x];
if (module & 1) {
if (module & Module.ON) {
svg += `M${x},${y}h1v1h-1z`;
}
}
@ -58,7 +59,7 @@ export function renderSVG(qr, params) {
// for (let y = 0; y < matrixWidth; y++) {
// for (let x = 0; x < matrixWidth; x++) {
// const module = qr.matrix[y * matrixWidth + x];
// if (module & 1) {
// if (module & Module.ON) {
// ctx.fillRect((x + margin) * unit, (y + margin) * unit, unit, unit)
// }
// }

Wyświetl plik

@ -1,31 +1,31 @@
// pre-generated thumbnail qrcode
// pre-generated unscannable thumbnail qrcode
const PREVIEW_OUTPUTQR = {
text: "https://qrfra.me",
text: "thumbnail",
// prettier-ignore
matrix: [3,3,3,3,3,3,3,12,8,1,1,0,0,12,3,3,3,3,3,3,3,3,2,2,2,2,2,3,12,9,1,0,1,1,12,3,2,2,2,2,2,3,3,2,3,3,3,2,3,12,9,0,0,0,0,12,3,2,3,3,3,2,3,3,2,3,3,3,2,3,12,8,0,0,1,1,12,3,2,3,3,3,2,3,3,2,3,3,3,2,3,12,8,0,0,1,0,12,3,2,3,3,3,2,3,3,2,2,2,2,2,3,12,8,0,1,1,0,12,3,2,2,2,2,2,3,3,3,3,3,3,3,3,12,7,6,7,6,7,12,3,3,3,3,3,3,3,12,12,12,12,12,12,12,12,8,1,1,0,0,12,12,12,12,12,12,12,12,8,9,9,9,8,9,7,8,8,0,0,1,1,8,8,8,8,8,9,9,8,1,1,0,1,0,0,6,0,1,1,1,1,1,0,1,1,1,0,0,0,1,1,1,1,1,1,1,7,1,0,0,1,0,0,1,1,1,0,1,0,1,1,1,0,1,0,1,0,6,1,0,1,1,0,1,0,0,1,1,1,0,1,0,1,0,1,0,0,0,7,0,1,0,1,1,0,0,1,1,0,1,0,1,0,12,12,12,12,12,12,12,12,9,0,1,0,1,1,0,0,1,0,0,1,0,3,3,3,3,3,3,3,12,8,1,1,1,0,1,0,1,1,1,0,0,0,3,2,2,2,2,2,3,12,9,1,1,0,1,0,0,1,1,1,1,1,0,3,2,3,3,3,2,3,12,8,0,0,1,1,0,1,1,1,1,1,0,0,3,2,3,3,3,2,3,12,9,1,1,1,0,0,1,0,0,1,1,1,0,3,2,3,3,3,2,3,12,9,1,0,0,1,0,1,0,0,1,1,0,0,3,2,2,2,2,2,3,12,9,1,0,0,0,1,0,0,1,0,0,0,1,3,3,3,3,3,3,3,12,8,1,1,0,0,1,0,0,1,0,1,0,0],
matrix: [ 5,5,5,5,5,5,5,0,33,2,3,2,3,0,5,5,5,5,5,5,5,5,4,4,4,4,4,5,0,33,3,2,2,3,0,5,4,4,4,4,4,5,5,4,133,133,133,4,5,0,33,2,3,2,2,0,5,4,133,133,133,4,5,5,4,133,133,133,4,5,0,33,3,2,3,2,0,5,4,133,133,133,4,5,5,4,133,133,133,4,5,0,33,2,2,2,2,0,5,4,133,133,133,4,5,5,4,4,4,4,4,5,0,32,2,2,3,2,0,5,4,4,4,4,4,5,5,5,5,5,5,5,5,0,17,16,17,16,17,0,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,33,3,3,3,2,0,0,0,0,0,0,0,0,32,33,33,32,33,32,17,33,32,2,3,3,3,160,161,160,161,161,161,161,161,2,3,2,2,2,2,16,2,3,2,3,3,2,2,3,2,3,2,3,2,3,3,3,2,3,3,2,17,3,3,2,3,3,2,3,2,3,2,2,2,3,2,3,3,3,2,2,2,16,2,2,3,2,2,3,3,2,3,2,3,2,2,2,2,2,3,3,2,2,17,2,3,3,3,3,3,2,3,2,2,3,3,3,2,0,0,0,0,0,0,0,0,161,2,3,3,3,3,3,2,3,3,2,3,3,5,5,5,5,5,5,5,0,161,3,2,3,2,2,2,3,2,3,2,3,2,5,4,4,4,4,4,5,0,160,2,3,2,2,2,2,2,3,3,2,3,2,5,4,133,133,133,4,5,0,161,2,2,2,3,2,2,3,3,2,3,2,3,5,4,133,133,133,4,5,0,160,3,2,3,2,3,3,2,3,3,3,2,2,5,4,133,133,133,4,5,0,161,2,2,2,2,2,3,3,2,3,2,2,2,5,4,4,4,4,4,5,0,161,3,2,3,2,3,3,2,3,3,2,2,2,5,5,5,5,5,5,5,0,160,3,2,2,2,2,2,2,2,2,3,3,2],
version: 1,
ecl: 2, //ECL.Quartile
mode: 2, // Mode.Byte
mask: 3, // Mask.M3
mask: 4, // Mask.M4
};
onmessage = async ({ data: { type, url, params, timeoutId } }) => {
onmessage = async ({ data: { type,url,params,timeoutId } }) => {
try {
switch (type) {
case "svg": {
const { renderSVG } = await import(url);
const svg = await renderSVG(PREVIEW_OUTPUTQR, params);
const svg = await renderSVG(PREVIEW_OUTPUTQR,params);
postMessage({ type, svg, timeoutId });
postMessage({ type,svg,timeoutId });
break;
}
case "canvas": {
const { renderCanvas } = await import(url);
const canvas = new OffscreenCanvas(0, 0);
await renderCanvas(PREVIEW_OUTPUTQR, params, canvas);
const canvas = new OffscreenCanvas(0,0);
await renderCanvas(PREVIEW_OUTPUTQR,params,canvas);
const bitmap = canvas.transferToImageBitmap();
postMessage({ type, bitmap, timeoutId }, [bitmap]);
postMessage({ type,bitmap,timeoutId },[bitmap]);
break;
}
}

23
public/utils.js 100644
Wyświetl plik

@ -0,0 +1,23 @@
export const Module = Object.freeze({
ON: 1 << 0,
DATA: 1 << 1,
FINDER: 1 << 2,
ALIGNMENT: 1 << 3,
TIMING: 1 << 4,
FORMAT: 1 << 5,
VERSION: 1 << 6,
MODIFIER: 1 << 7,
});
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export { splitmix32 as getSeededRand }

Wyświetl plik

@ -26,7 +26,7 @@ type Props = {
const FUNC_KEYS = "funcKeys";
const VERSION = 1;
const VERSION = 2;
const PRESETS_VERSION = "presetsVersion";
const LOADING_THUMB = `data:image/svg+xml,<svg viewBox="-12 -12 48 48" xmlns="http://www.w3.org/2000/svg"><path d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"><animateTransform attributeName="transform" type="rotate" dur="0.75s" values="0 12 12;360 12 12" repeatCount="indefinite"/></path></svg>`;

Wyświetl plik

@ -11,7 +11,7 @@ import {
} from "~/lib/options";
import type { Params } from "~/lib/params";
import { FlatButton } from "../Button";
import { clearToasts, toastError } from "../ErrorToasts";
import { toastError } from "../ErrorToasts";
import { unwrap } from "solid-js/store";
import { SplitButton } from "../SplitButton";
@ -36,7 +36,7 @@ export default function QrPreview(props: Props) {
<Show
when={typeof outputQr() !== "number"}
fallback={
<div class="aspect-[1/1] border rounded-md flex justify-center items-center">
<div class="aspect-[1/1] border rounded-md p-2">
<Switch>
<Match when={outputQr() === QrError.ExceedsMaxCapacity}>
Data exceeds max capacity
@ -170,10 +170,7 @@ function RenderedQrCode() {
return (
<>
<div class="checkboard aspect-[1/1] border rounded-md relative overflow-hidden">
<Show when={error()}>
<div class="absolute w-full h-full bg-back-base/50 p-2">{error()}</div>
</Show>
<div class="checkboard aspect-[1/1] border rounded-md grid [&>*]:[grid-area:1/1] overflow-hidden">
<Switch>
<Match when={render()?.type === "svg"}>
<div ref={svgParent!}></div>
@ -185,6 +182,9 @@ function RenderedQrCode() {
></canvas>
</Match>
</Switch>
<Show when={error()}>
<div class="bg-back-base/50 p-2">{error()}</div>
</Show>
</div>
<Show when={render()?.type === "canvas"}>
<div class="text-center">

Wyświetl plik

@ -7,16 +7,7 @@ import {
type JSX,
type Setter,
} from "solid-js";
import {
ECL,
Mode,
Mask,
QrError,
Module,
QrOptions,
Version,
get_matrix,
} from "fuqr";
import { ECL, Mode, Mask, QrError, QrOptions, Version, generate } from "fuqr";
import { createStore, type SetStoreFunction } from "solid-js/store";
import { type Params, type ParamsSchema } from "./params";
import { clearToasts, toastError } from "~/components/ErrorToasts";
@ -37,7 +28,7 @@ export type OutputQr = Readonly<{
ecl: ECL;
mode: Mode;
mask: Mask;
matrix: ReadonlyArray<Module>;
matrix: Uint8Array;
}>;
export const QrContext = createContext<{
@ -102,10 +93,10 @@ export function QrContextProvider(props: { children: JSX.Element }) {
const outputQr = createMemo(() => {
// can't skip first render, b/c need to track deps
try {
// NOTE: WASM ptrs (QrOptions, Version, Matrix) become null after leaving scope
// NOTE: WASM ptrs (QrOptions, Version) become null after leaving scope
// They can't be reused or stored
let qrOptions = new QrOptions()
const qrOptions = new QrOptions()
.min_version(new Version(inputQr.minVersion))
.strict_version(inputQr.strictVersion)
.min_ecl(inputQr.minEcl)
@ -113,18 +104,10 @@ export function QrContextProvider(props: { children: JSX.Element }) {
.mask(inputQr.mask!) // null instead of undefined (wasm-pack type)
.mode(inputQr.mode!); // null instead of undefined (wasm-pack type)
let m = get_matrix(inputQr.text, qrOptions);
// outputQr is passed as param to renderFunc
// must either freeze or pass new copy for each render
return Object.freeze({
return {
text: inputQr.text,
matrix: Object.freeze(m.value),
version: m.version["0"],
ecl: m.ecl,
mode: m.mode,
mask: m.mask,
});
...generate(inputQr.text, qrOptions),
};
} catch (e) {
return e as QrError;
}

Wyświetl plik

@ -1,5 +1,7 @@
export const Alien = `// Based on QRBTF's Line style
// https://github.com/CPunisher/react-qrbtf/blob/master/src/components/QRLine.tsx
import { Module, getSeededRand } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -28,36 +30,8 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const rangeStr = (min, max) => (rand() * (max - min) + min).toFixed(2);
const matrixWidth = qr.version * 4 + 17;
@ -117,9 +91,9 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = matrix(x, y);
if ((module | 1) === Module.FinderON) continue;
if (module & Module.FINDER) continue;
if (!(module & 1)) continue;
if (!(module & Module.ON)) continue;
dotsLayer += \`<circle cx="\${x + 0.5}" cy="\${y + 0.5}" r="\${rangeStr(0.2, 0.4)}"/>\`;
if (!visited1(x, y)) {
@ -128,7 +102,7 @@ export function renderSVG(qr, params) {
while (
nx < matrixWidth &&
ny < matrixWidth &&
matrix(nx, ny) & 1 &&
matrix(nx, ny) & Module.ON &&
!visited1(nx, ny)
) {
setVisited1(nx, ny);
@ -146,7 +120,7 @@ export function renderSVG(qr, params) {
while (
nx >= 0 &&
ny < matrixWidth &&
matrix(nx, ny) & 1 &&
matrix(nx, ny) & Module.ON &&
!visited2(nx, ny)
) {
setVisited2(nx, ny);

Wyświetl plik

@ -1,4 +1,6 @@
export const Basic = `export const paramsSchema = {
export const Basic = `import { Module } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
min: 0,
@ -52,22 +54,6 @@ export const Basic = `export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
export async function renderSVG(qr, params) {
const matrixWidth = qr.version * 4 + 17;
const margin = params["Margin"];
@ -142,8 +128,8 @@ export async function renderSVG(qr, params) {
continue;
}
const module = qr.matrix[y * matrixWidth + x];
if (!(module & 1)) continue;
if (module === Module.FinderON) continue;
if (!(module & Module.ON)) continue;
if (module & Module.FINDER) continue;
if (defaultShape) {
if (roundness) {

Wyświetl plik

@ -1,5 +1,7 @@
export const Blocks = `// Based on QRBTF's DSJ style
// https://github.com/CPunisher/react-qrbtf/blob/master/src/components/QRDsj.tsx
import { Module } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -51,22 +53,6 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
export function renderSVG(qr, params) {
const matrixWidth = qr.version * 4 + 17;
const margin = params["Margin"];
@ -122,8 +108,8 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = matrix(x, y);
if ((module | 1) === Module.FinderON) continue;
if (!(module & 1)) continue;
if (module & Module.FINDER) continue;
if (!(module & Module.ON)) continue;
if (visited(x, y)) continue;
setVisited(x, y);
@ -157,9 +143,13 @@ export function renderSVG(qr, params) {
if (
y < matrixWidth - 1 &&
x < matrixWidth - 1 &&
matrix(x + 1, y) & matrix(x, y + 1) & matrix(x + 1, y + 1) & 1
matrix(x + 1, y) & matrix(x, y + 1) & matrix(x + 1, y + 1) & Module.ON
) {
if (!visited(x + 1, y) && !visited(x + 1, y + 1) && !visited(x, y + 1)) {
if (
!visited(x + 1, y) &&
!visited(x + 1, y + 1) &&
!visited(x, y + 1)
) {
crossLayer += \`<g>\`;
crossLayer += \`<line x1="\${x + co}" y1="\${y + co}" x2="\${x + 2 - co}" y2="\${y + 2 - co}"/>\`;
crossLayer += \`<line x1="\${x + 2 - co}" y1="\${y + co}" x2="\${x + co}" y2="\${y + 2 - co}"/>\`;
@ -173,7 +163,7 @@ export function renderSVG(qr, params) {
}
let ny = y + 1;
while (ny < matrixWidth && matrix(x, ny) & 1 && !visited(x, ny)) {
while (ny < matrixWidth && matrix(x, ny) & Module.ON && !visited(x, ny)) {
ny++;
}
if (ny - y > 2) {
@ -186,7 +176,7 @@ export function renderSVG(qr, params) {
}
let nx = x + 1;
while (nx < matrixWidth && matrix(nx, y) & 1 && !visited(nx, y)) {
while (nx < matrixWidth && matrix(nx, y) & Module.ON && !visited(nx, y)) {
setVisited(nx, y);
nx++;
}

Wyświetl plik

@ -1,5 +1,7 @@
export const Bubbles = `// Based on QRBTF's Bubble style
// https://github.com/CPunisher/react-qrbtf/blob/master/src/components/QRBubble.tsx
import { Module, getSeededRand } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -43,36 +45,8 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const rangeStr = params["Randomize circle size"]
? (min, max) => (rand() * (max - min) + min).toFixed(2)
@ -116,7 +90,7 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = matrix(x, y);
if ((module | 1) === Module.FinderON) continue;
if (module & Module.FINDER) continue;
if (visited(x, y)) continue;
if (
@ -140,13 +114,16 @@ export function renderSVG(qr, params) {
setVisited(x + 1, y + 2);
continue;
}
if (!(module & 1)) continue;
if (!(module & Module.ON)) continue;
setVisited(x, y);
if (
y < matrixWidth - 1 &&
x < matrixWidth - 1 &&
matrix(x + 1, y) & matrix(x, y + 1) & matrix(x + 1, y + 1) & 1 &&
matrix(x + 1, y) &
matrix(x, y + 1) &
matrix(x + 1, y + 1) &
Module.ON &&
!visited(x + 1, y) &&
!visited(x + 1, y + 1)
) {
@ -156,12 +133,20 @@ export function renderSVG(qr, params) {
setVisited(x + 1, y + 1);
continue;
}
if (x < matrixWidth - 1 && matrix(x + 1, y) & 1 && !visited(x + 1, y)) {
if (
x < matrixWidth - 1 &&
matrix(x + 1, y) & Module.ON &&
!visited(x + 1, y)
) {
layer3 += \`<circle cx="\${x + 1}" cy="\${y + 0.5}" r="\${rangeStr(0.4, 0.6)}"/>\`;
setVisited(x + 1, y);
continue;
}
if (y < matrixWidth - 1 && matrix(x, y + 1) & 1 && !visited(x, y + 1)) {
if (
y < matrixWidth - 1 &&
matrix(x, y + 1) & Module.ON &&
!visited(x, y + 1)
) {
layer3 += \`<circle cx="\${x + 0.5}" cy="\${y + 1}" r="\${rangeStr(0.3, 0.5)}"/>\`;
setVisited(x, y + 1);
continue;

Wyświetl plik

@ -1,4 +1,6 @@
export const Camo = `export const paramsSchema = {
export const Camo = `import { Module, getSeededRand } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Foreground: {
type: "color",
default: "#1c4a1a",
@ -30,36 +32,8 @@ export const Camo = `export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const margin = params["Margin"];
const quietZone = params["Quiet zone"];
const fg = params["Foreground"];
@ -68,18 +42,18 @@ export function renderSVG(qr, params) {
const qrWidth = qr.version * 4 + 17;
const matrixWidth = qrWidth + 2 * margin;
const newMatrix = Array(matrixWidth * matrixWidth).fill(Module.DataOFF);
const newMatrix = Array(matrixWidth * matrixWidth).fill(0);
const visited = new Uint16Array(matrixWidth * matrixWidth);
// Copy qr to matrix with margin and randomly set pixels in margin
for (let y = 0; y < margin - quietZone; y++) {
for (let x = 0; x < matrixWidth; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
}
for (let y = margin - quietZone; y < margin + qrWidth + quietZone; y++) {
for (let x = 0; x < margin - quietZone; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
if (y >= margin && y < margin + qrWidth) {
for (let x = margin; x < matrixWidth - margin; x++) {
@ -88,12 +62,28 @@ export function renderSVG(qr, params) {
}
}
for (let x = margin + qrWidth + quietZone; x < matrixWidth; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
}
for (let y = margin + qrWidth + quietZone; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
}
if (quietZone === 0 && margin > 0) {
for (let x = margin; x < margin + 7; x++) {
newMatrix[(margin - 1) * matrixWidth + x] = 0;
newMatrix[(margin - 1) * matrixWidth + x + qrWidth - 7] = 0;
}
for (let y = margin; y < margin + 7; y++) {
newMatrix[y * matrixWidth + margin - 1] = 0;
newMatrix[y * matrixWidth + matrixWidth - margin] = 0;
}
for (let y = margin + qrWidth - 7; y < margin + qrWidth; y++) {
newMatrix[y * matrixWidth + margin - 1] = 0;
}
for (let x = margin; x < margin + 7; x++) {
newMatrix[(matrixWidth - margin) * matrixWidth + x] = 0;
}
}
@ -108,8 +98,8 @@ export function renderSVG(qr, params) {
let baseY;
const on = params["Invert"]
? (x, y) => (newMatrix[y * matrixWidth + x] & 1) === 0
: (x, y) => (newMatrix[y * matrixWidth + x] & 1) === 1;
? (x, y) => (newMatrix[y * matrixWidth + x] & Module.ON) === 0
: (x, y) => (newMatrix[y * matrixWidth + x] & Module.ON) !== 0;
function goRight(x, y, path, cw) {
let sx = x;

Wyświetl plik

@ -1,4 +1,6 @@
export const Circle = `export const paramsSchema = {
export const Circle = `import { Module, getSeededRand } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
min: 0,
@ -60,34 +62,6 @@ export const Circle = `export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
const fmt = (n) => n.toFixed(2).replace(/.00$/, "");
export async function renderSVG(qr, params) {
@ -99,7 +73,7 @@ export async function renderSVG(qr, params) {
const file = params["Logo"];
const logoRatio = params["Logo size"];
const showLogoData = params["Show data behind logo"];
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const range = (min, max) => rand() * (max - min) + min;
const size = matrixWidth + 2 * margin;
@ -183,26 +157,16 @@ export async function renderSVG(qr, params) {
if (x >= 0 && x < matrixWidth && y >= 0 && y < matrixWidth) {
const module = qr.matrix[y * matrixWidth + x];
if (!(module & 1)) continue;
if (!(module & Module.ON)) continue;
if (
params["Finder pattern"] !== "Default" &&
(module | 1) === Module.FinderON
) {
if (params["Finder pattern"] !== "Default" && module & Module.FINDER) {
continue;
}
if (
params["Alignment pattern"] !== "Default" &&
module === Module.AlignmentON
module & Module.ALIGNMENT
) {
if (
!(
(qr.matrix[(y - 1) * matrixWidth + x] |
qr.matrix[y * matrixWidth + x + 1] |
qr.matrix[(y + 1) * matrixWidth + x]) &
1
)
) {
if (module & Module.MODIFIER) {
if (params["Alignment pattern"] === "Circle") {
svg += \`M\${x + 0.5},\${y - 2}a2.5,2.5 0,0,0 0,5a2.5,2.5 0,0,0 0,-5\`;
svg += \`M\${x + 0.5},\${y - 1}a1.5,1.5 0,0,1 0,3a1.5,1.5 0,0,1 0,-3\`;

Wyświetl plik

@ -1,4 +1,6 @@
export const Dots = `export const paramsSchema = {
export const Dots = `import { Module, getSeededRand } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
min: 0,
@ -64,38 +66,10 @@ export const Dots = `export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const unit = params["Density"];
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const rangeStr = (min, max) => (rand() * (max - min) + min).toFixed(2);
const matrixWidth = qr.version * 4 + 17;
const margin = params["Margin"] * unit;
@ -119,9 +93,9 @@ export function renderSVG(qr, params) {
const qx = Math.floor((x + center) / unit);
const qy = Math.floor((y + center) / unit);
if (qx >= 0 && qx < matrixWidth && qy >= 0 && qy < matrixWidth) {
if (qr.matrix[qy * matrixWidth + qx] & 1) {
if (qr.matrix[qy * matrixWidth + qx] & Module.ON) {
const rad =
qr.matrix[qy * matrixWidth + qx] === Module.FinderON
qr.matrix[qy * matrixWidth + qx] & Module.FINDER
? params["Finder clarity"]
: dotRadius;
svg += \`<circle cx="\${(center + x).toFixed(2)}" cy="\${(center + y).toFixed(2)}" r="\${rad}" />\`;

Wyświetl plik

@ -1,4 +1,5 @@
export const Drawing = `import rough from "https://esm.sh/roughjs";
export const Drawing = `import { Module, getSeededRand } from "https://qrframe.kylezhe.ng/utils.js";
import rough from "https://esm.sh/roughjs";
export const paramsSchema = {
Margin: {
@ -74,34 +75,6 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
const domMock = {
ownerDocument: {
createElementNS: (_ns, tagName) => {
@ -148,7 +121,7 @@ export function renderSVG(qr, params) {
x === matrixWidth - 1 ||
y === matrixWidth - 1
) {
matrix.push(Module.DataOFF);
matrix.push(0);
} else {
matrix.push(qr.matrix[(y - 1) * (matrixWidth - 2) + x - 1]);
}
@ -172,8 +145,8 @@ export function renderSVG(qr, params) {
let baseY;
const on = params["Invert"]
? (x, y) => (matrix[y * matrixWidth + x] & 1) === 0
: (x, y) => (matrix[y * matrixWidth + x] & 1) === 1;
? (x, y) => (matrix[y * matrixWidth + x] & Module.ON) === 0
: (x, y) => (matrix[y * matrixWidth + x] & Module.ON) !== 0;
function goRight(x, y, shape, cw) {
let sx = x;

Wyświetl plik

@ -1,4 +1,6 @@
export const Glass = `export const paramsSchema = {
export const Glass = `import { Module, getSeededRand } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
min: 0,
@ -51,20 +53,8 @@ export const Glass = `export const paramsSchema = {
},
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const margin = params["Margin"];
const unit = 4;
@ -245,7 +235,7 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
if (matrix[y * matrixWidth + x] & 1) {
if (matrix[y * matrixWidth + x] & Module.ON) {
qrLayer += \`M\${x * unit},\${y * unit}h\${unit}v\${unit}h-\${unit}z\`;
}

Wyświetl plik

@ -1,4 +1,5 @@
export const Halftone = `// Halftone is a misnomer, but that's what this type of QR code is known as
export const Halftone = `import { Module } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Image: {
type: "file",
@ -43,22 +44,6 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
export async function renderCanvas(qr, params, canvas) {
const unit = 3;
const pixel = 1;
@ -90,7 +75,7 @@ export async function renderCanvas(qr, params, canvas) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = qr.matrix[y * matrixWidth + x];
if (module & 1) {
if (module & Module.ON) {
const px = x + margin;
const py = y + margin;
ctx.fillRect(px * unit, py * unit, unit, unit);
@ -149,7 +134,7 @@ export async function renderCanvas(qr, params, canvas) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = qr.matrix[y * matrixWidth + x];
if (module & 1) {
if (module & Module.ON) {
ctx.fillStyle = fg;
} else {
ctx.fillStyle = bg;
@ -158,11 +143,10 @@ export async function renderCanvas(qr, params, canvas) {
const px = x + margin;
const py = y + margin;
const type = module | 1;
if (
type === Module.FinderON ||
(alignment && type === Module.AlignmentON) ||
(timing && type === Module.TimingON)
module & Module.FINDER ||
(alignment && module & Module.ALIGNMENT) ||
(timing && module & Module.TIMING)
) {
ctx.fillRect(px * unit, py * unit, unit, unit);
} else {

Wyświetl plik

@ -1,4 +1,6 @@
export const Layers = `export const paramsSchema = {
export const Layers = `import { Module } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
min: 0,
@ -85,7 +87,7 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = qr.matrix[y * matrixWidth + x];
if (module & 1) {
if (module & Module.ON) {
svg += \`M\${x},\${y}h1v1h-1z\`;
}
}

Wyświetl plik

@ -1,4 +1,6 @@
export const Minimal = `export const paramsSchema = {
export const Minimal = `import { Module } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
min: 0,
@ -16,22 +18,6 @@ export const Minimal = `export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
export function renderSVG(qr, params) {
const matrixWidth = qr.version * 4 + 17;
const unit = 10;
@ -66,11 +52,11 @@ export function renderSVG(qr, params) {
for (let x = 0; x < matrixWidth; x++) {
const module = qr.matrix[y * matrixWidth + x];
if ((module | 1) === Module.FinderON) {
if (module & Module.FINDER) {
continue;
}
if (module & 1) {
if (module & Module.ON) {
const sx = x * unit + offset;
const sy = y * unit + offset;
svg += \`M\${sx},\${sy}h\${dataSize}v\${dataSize}h-\${dataSize}z\`;

Wyświetl plik

@ -1,4 +1,6 @@
export const Mondrian = `export const paramsSchema = {
export const Mondrian = `import { Module, getSeededRand } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
min: 0,
@ -35,20 +37,8 @@ export const Mondrian = `export const paramsSchema = {
},
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const margin = params["Margin"];
const unit = 20;
@ -90,7 +80,7 @@ export function renderSVG(qr, params) {
if (visited[y * matrixWidth + x]) continue;
let layer = "";
const on = module & 1;
const on = module & Module.ON;
visited[y * matrixWidth + x] = true;
let width = 1;
@ -98,7 +88,7 @@ export function renderSVG(qr, params) {
while (
x + width < matrixWidth &&
(matrix[y * matrixWidth + x + width] & 1) === on &&
(matrix[y * matrixWidth + x + width] & Module.ON) === on &&
!visited[y * matrixWidth + x + width]
) {
visited[y * matrixWidth + x + width] = true;
@ -107,7 +97,7 @@ export function renderSVG(qr, params) {
outer: while (y + height < matrixWidth) {
for (let i = 0; i < width; i++) {
if ((matrix[(y + height) * matrixWidth + x + i] & 1) !== on) {
if ((matrix[(y + height) * matrixWidth + x + i] & Module.ON) !== on) {
break outer;
}
}

Wyświetl plik

@ -1,4 +1,6 @@
export const Neon = `export const paramsSchema = {
export const Neon = `import { Module, getSeededRand } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Foreground: {
type: "array",
props: {
@ -51,36 +53,8 @@ export const Neon = `export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const margin = params["Margin"];
const colors = params["Foreground"];
const bg = params["Background"];
@ -88,18 +62,18 @@ export function renderSVG(qr, params) {
const qrWidth = qr.version * 4 + 17;
const matrixWidth = qrWidth + 2 * margin;
const newMatrix = Array(matrixWidth * matrixWidth).fill(Module.DataOFF);
const newMatrix = Array(matrixWidth * matrixWidth).fill(0);
const visited = new Uint16Array(matrixWidth * matrixWidth);
// Copy qr to matrix with margin and randomly set pixels in margin
for (let y = 0; y < margin - 1; y++) {
for (let x = 0; x < matrixWidth; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
}
for (let y = margin - 1; y < margin + qrWidth + 1; y++) {
for (let x = 0; x < margin - 1; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
if (y >= margin && y < margin + qrWidth) {
for (let x = margin; x < matrixWidth - margin; x++) {
@ -108,30 +82,28 @@ export function renderSVG(qr, params) {
}
}
for (let x = margin + qrWidth + 1; x < matrixWidth; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
}
for (let y = margin + qrWidth + 1; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + x] = Module.ON;
}
}
if (params["Quiet zone"] === "Minimal") {
for (let x = margin + 8; x < matrixWidth - margin - 8; x++) {
if (rand() > 0.5)
newMatrix[(margin - 1) * matrixWidth + x] = Module.DataON;
if (rand() > 0.5) newMatrix[(margin - 1) * matrixWidth + x] = Module.ON;
}
for (let y = margin + 8; y < matrixWidth - margin; y++) {
if (y < matrixWidth - margin - 8) {
if (rand() > 0.5)
newMatrix[y * matrixWidth + margin - 1] = Module.DataON;
if (rand() > 0.5) newMatrix[y * matrixWidth + margin - 1] = Module.ON;
}
if (rand() > 0.5)
newMatrix[y * matrixWidth + matrixWidth - margin] = Module.DataON;
newMatrix[y * matrixWidth + matrixWidth - margin] = Module.ON;
}
for (let x = margin + 8; x < matrixWidth - margin + 1; x++) {
if (rand() > 0.5)
newMatrix[(matrixWidth - margin) * matrixWidth + x] = Module.DataON;
newMatrix[(matrixWidth - margin) * matrixWidth + x] = Module.ON;
}
}
@ -156,8 +128,8 @@ export function renderSVG(qr, params) {
let baseY;
const on = params["Invert"]
? (x, y) => (newMatrix[y * matrixWidth + x] & 1) === 0
: (x, y) => (newMatrix[y * matrixWidth + x] & 1) === 1;
? (x, y) => (newMatrix[y * matrixWidth + x] & Module.ON) === 0
: (x, y) => (newMatrix[y * matrixWidth + x] & Module.ON) !== 0;
function goRight(x, y, shape, cw) {
let sx = x;
@ -303,7 +275,7 @@ export function renderSVG(qr, params) {
for (let x = 0; x < matrixWidth; x++) {
if (visited[y * matrixWidth + x]) continue;
if ((newMatrix[y * matrixWidth + x] | 1) === Module.FinderON) {
if (newMatrix[y * matrixWidth + x] & Module.FINDER) {
thin = params["Finder thickness"];
offset = (unit - thin) / 2;
} else {

Wyświetl plik

@ -1,5 +1,7 @@
export const Quantum = `// Based on QRBTF's A1P style
// https://github.com/CPunisher/react-qrbtf/blob/master/src/components/QRNormal.tsx
import { Module, getSeededRand } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
@ -32,36 +34,8 @@ export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
function splitmix32(a) {
return function () {
a |= 0;
a = (a + 0x9e3779b9) | 0;
let t = a ^ (a >>> 16);
t = Math.imul(t, 0x21f0aaad);
t = t ^ (t >>> 15);
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
};
}
export function renderSVG(qr, params) {
const rand = splitmix32(params["Seed"]);
const rand = getSeededRand(params["Seed"]);
const range = (min, max) =>
Math.trunc(100 * (rand() * (max - min) + min)) / 100;
@ -112,7 +86,7 @@ export function renderSVG(qr, params) {
let dotsLayer = \`<g fill="\${fg}">\`;
function on(x, y) {
return (qr.matrix[y * matrixWidth + x] & 1) === 1;
return (qr.matrix[y * matrixWidth + x] & Module.ON) !== 0;
}
const visitArray = Array.from({ length: matrixWidth * matrixWidth }).fill(
@ -134,7 +108,7 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = qr.matrix[y * matrixWidth + x];
if ((module | 1) === Module.FinderON) continue;
if (module & Module.FINDER) continue;
if (params["Particles"] && y < matrixWidth - 2 && x < matrixWidth - 2) {
let xCross = false;

Wyświetl plik

@ -1,4 +1,6 @@
export const Tile = `export const paramsSchema = {
export const Tile = `import { Module } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
min: 0,
@ -31,22 +33,6 @@ export const Tile = `export const paramsSchema = {
},
};
const Module = {
DataOFF: 0,
DataON: 1,
FinderOFF: 2,
FinderON: 3,
AlignmentOFF: 4,
AlignmentON: 5,
TimingOFF: 6,
TimingON: 7,
FormatOFF: 8,
FormatON: 9,
VersionOFF: 10,
VersionON: 11,
SeparatorOFF: 12,
};
export function renderSVG(qr, params) {
const unit = 16;
const gap = 2;
@ -60,9 +46,7 @@ export function renderSVG(qr, params) {
const bg = params["Background"];
const grout = params["Grout"];
const newMatrix = Array.from({ length: matrixWidth * matrixWidth }).fill(
Module.DataOFF
);
const newMatrix = Array.from({ length: matrixWidth * matrixWidth }).fill(0);
const start = margin;
const end = matrixWidth - 1 - margin;
@ -72,29 +56,29 @@ export function renderSVG(qr, params) {
for (let x = 0; x < matrixWidth; x++) {
// outer square
if (y === start - outer && x >= start - outer && x <= end + outer) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
} else if (
(x === start - outer || x === end + outer) &&
y >= start - outer + 1 &&
y <= end + outer - 1
) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
newMatrix[y * matrixWidth + x] = Module.ON;
} else if (y === end + outer && x >= start - outer && x <= end + outer) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
}
// inner square
else if (y === start - inner && x >= start - inner && x <= end + inner) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
} else if (
(x === start - inner || x === end + inner) &&
y >= start - inner + 1 &&
y <= end + inner - 1
) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
newMatrix[y * matrixWidth + x] = Module.ON;
} else if (y === end + inner && x >= start - inner && x <= end + inner) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
}
// qr code w/ quiet zone
else if (
@ -121,16 +105,16 @@ export function renderSVG(qr, params) {
x < end + outer
) {
if ((x + y) & 1) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
}
// outside squares
} else {
if (x % 4 && y % 4) {
if ((x % 8 < 4 && y % 8 < 4) || (x % 8 > 4 && y % 8 > 4)) {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
}
} else {
newMatrix[y * matrixWidth + x] = Module.DataON;
newMatrix[y * matrixWidth + x] = Module.ON;
}
}
}
@ -146,8 +130,8 @@ export function renderSVG(qr, params) {
for (let x = 0; x < matrixWidth; x++) {
const module = newMatrix[y * matrixWidth + x];
let tiles;
if (module & 1) {
if (module === Module.FinderON) {
if (module & Module.ON) {
if (module & Module.FINDER) {
svg += \`M\${x * unit},\${y * unit}h\${unit}v\${unit}h-\${unit}z\`;
continue;
}
@ -161,7 +145,7 @@ export function renderSVG(qr, params) {
const ny = y * unit + offset + dy * (tile + gap);
for (let dx = 0; dx < tiles; dx++) {
const nx = x * unit + offset + dx * (tile + gap);
if (module & 1) {
if (module & Module.ON) {
svg += \`M\${nx},\${ny}h\${tile}v\${tile}h-\${tile}z\`;
} else {
layer += \`M\${nx},\${ny}h\${tile}v\${tile}h-\${tile}z\`;

Wyświetl plik

@ -1,4 +1,5 @@
export const Tutorial = `export const paramsSchema = {
export const Tutorial = `import { Module } from "https://qrframe.kylezhe.ng/utils.js";
export const paramsSchema = {
Margin: {
type: "number",
min: 0,
@ -30,7 +31,7 @@ export function renderSVG(qr, params) {
for (let y = 0; y < matrixWidth; y++) {
for (let x = 0; x < matrixWidth; x++) {
const module = qr.matrix[y * matrixWidth + x];
if (module & 1) {
if (module & Module.ON) {
svg += \`M\${x},\${y}h1v1h-1z\`;
}
}
@ -58,7 +59,7 @@ export function renderSVG(qr, params) {
// for (let y = 0; y < matrixWidth; y++) {
// for (let x = 0; x < matrixWidth; x++) {
// const module = qr.matrix[y * matrixWidth + x];
// if (module & 1) {
// if (module & Module.ON) {
// ctx.fillRect((x + margin) * unit, (y + margin) * unit, unit, unit)
// }
// }

Wyświetl plik

@ -1,6 +1,9 @@
import { promises as fs } from "fs";
import path from "path";
const dev = process.argv[2] === "dev";
const url = dev ? "http://localhost:3000" : "https://qrframe.kylezhe.ng";
async function convertTsToJs(inputDir, outputDir) {
try {
// Ensure output directory exists
@ -15,6 +18,7 @@ async function convertTsToJs(inputDir, outputDir) {
let code = await fs.readFile(inputPath, "utf-8");
code = code.replace("REPLACE_URL", url);
code = code.replaceAll("`", "\\`");
code = code.replaceAll("${", "\\${");
@ -23,10 +27,10 @@ async function convertTsToJs(inputDir, outputDir) {
`export const ${file.slice(0, -3)} = \`${code.slice(0, -1)}\n\`\n`,
"utf-8"
);
console.log(`Converted and formatted: ${inputPath} -> ${outputPath}`);
if (!dev) console.log(`Converted and formatted: ${inputPath} -> ${outputPath}`);
}
console.log("Conversion and formatting completed successfully.");
if (!dev) console.log("Conversion and formatting completed successfully.");
} catch (error) {
console.error("An error occurred:", error);
}