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

Take improvement from Stijn-van-Nieulande/qr-code-styling repo #23

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
830 changes: 584 additions & 246 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"lib"
],
"dependencies": {
"qrcode-generator": "^1.4.3"
"qrcode-generator-ts": "0.0.4"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^2.4.0",
Expand Down
4 changes: 3 additions & 1 deletion src/common.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ interface UnknownObject {
[key: string]: any;
}

type DotType = "dots" | "rounded" | "square";
type DotType = "dots" | "small-dots" | "rounded" | "square";
type EyeFrameType = 0 | 1 | 2;
type EyeBallType = 0;
type Extension = "png" | "jpeg" | "webp";

interface DotTypes {
Expand Down
19 changes: 0 additions & 19 deletions src/constants/errorCorrectionLevels.test.js

This file was deleted.

10 changes: 0 additions & 10 deletions src/constants/errorCorrectionLevels.ts

This file was deleted.

11 changes: 0 additions & 11 deletions src/constants/modes.test.js

This file was deleted.

10 changes: 0 additions & 10 deletions src/constants/modes.ts

This file was deleted.

19 changes: 0 additions & 19 deletions src/constants/qrTypes.test.js

This file was deleted.

20 changes: 0 additions & 20 deletions src/constants/qrTypes.ts

This file was deleted.

84 changes: 84 additions & 0 deletions src/core/QRCanvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import calculateImageSize from "../tools/calculateImageSize";
import errorCorrectionPercents from "../constants/errorCorrectionPercents";
import QRDot from "./QRDot";
import { Options } from "./QROptions";
import { QRCode } from "qrcode-generator-ts";
import QREye from "./QREye";

type FilterFunction = (i: number, j: number) => boolean;

Expand All @@ -10,6 +12,7 @@ export default class QRCanvas {
_options: Options;
_qr?: QRCode;
_image?: HTMLImageElement;
private _positionProbeModules: any = {};

//TODO don't pass all options to this class
constructor(options: Options) {
Expand Down Expand Up @@ -48,6 +51,11 @@ export default class QRCanvas {
this.drawBackground();
this._qr = qr;

this.setupPositionProbeModules(0, 0);
this.setupPositionProbeModules(this._qr.getModuleCount() - 7, 0);
this.setupPositionProbeModules(0, this._qr.getModuleCount() - 7);
this.drawEyes();

if (this._options.image) {
return this.drawImageAndDots();
} else {
Expand Down Expand Up @@ -98,6 +106,10 @@ export default class QRCanvas {
if (!this._qr.isDark(i, j)) {
continue;
}
if (i in this._positionProbeModules && j in this._positionProbeModules[i]) {
continue;
}

canvasContext.fillStyle = options.dotsOptions.color;
dot.draw(
xBeginning + i * dotSize,
Expand Down Expand Up @@ -179,4 +191,76 @@ export default class QRCanvas {
image.src = options.image;
});
}

drawEyes(): void {
if (!this._qr) {
throw "QR code is not defined";
}

const canvas = this._canvas;
const canvasContext = this.context;
const options = this._options;
const count = this._qr.getModuleCount();

if (!canvasContext) {
throw "QR code is not defined";
}
if (count > options.width || count > options.height) {
throw "The canvas is too small.";
}

const minSize = Math.min(options.width, options.height);
const dotSize = Math.floor(minSize / count);
const xBeginning = Math.floor((options.width - count * dotSize) / 2);
const yBeginning = Math.floor((options.height - count * dotSize) / 2);

const qrEye = new QREye({
context: canvasContext,
options: options
});

qrEye.draw(xBeginning, yBeginning, dotSize);

canvasContext.save();
canvasContext.translate(canvas.width, 0);
canvasContext.scale(-1, 1);
qrEye.draw(xBeginning, yBeginning, dotSize);
canvasContext.restore();

canvasContext.save();
canvasContext.translate(0, canvas.height);
canvasContext.scale(1, -1);
qrEye.draw(xBeginning, yBeginning, dotSize);
canvasContext.restore();
}

private setupPositionProbeModules(row: number, col: number): void {
if (!this._qr) {
throw "QR code is not defined";
}

for (let r = -1; r <= 7; r += 1) {
for (let c = -1; c <= 7; c += 1) {
if (
row + r <= -1 ||
this._qr.getModuleCount() <= row + r ||
col + c <= -1 ||
this._qr.getModuleCount() <= col + c
) {
continue;
}

if (
(0 <= r && r <= 6 && (c == 0 || c == 6)) ||
(0 <= c && c <= 6 && (r == 0 || r == 6)) ||
(2 <= r && r <= 4 && 2 <= c && c <= 4)
) {
if (!(row + r in this._positionProbeModules)) {
this._positionProbeModules[row + r] = {};
}
this._positionProbeModules[row + r][col + c] = true;
}
}
}
}
}
13 changes: 9 additions & 4 deletions src/core/QRCodeStyling.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import getMode from "../tools/getMode";
import mergeDeep from "../tools/merge";
import downloadURI from "../tools/downloadURI";
import QRCanvas from "./QRCanvas";
import defaultOptions, { Options } from "./QROptions";
import qrcode from "qrcode-generator";
import { QRCode } from "qrcode-generator-ts";

type DownloadOptions = {
name?: string;
Expand Down Expand Up @@ -36,8 +35,10 @@ export default class QRCodeStyling {
return;
}

this._qr = qrcode(this._options.qrOptions.typeNumber, this._options.qrOptions.errorCorrectionLevel);
this._qr.addData(this._options.data, this._options.qrOptions.mode || getMode(this._options.data));
this._qr = new QRCode();
this._qr.setTypeNumber(this._options.qrOptions.typeNumber);
this._qr.setErrorCorrectLevel(this._options.qrOptions.errorCorrectionLevel);
this._qr.addData(this._options.data);
this._qr.make();
this._canvas = new QRCanvas(this._options);
this._drawingPromise = this._canvas.drawQR(this._qr);
Expand Down Expand Up @@ -88,4 +89,8 @@ export default class QRCodeStyling {
downloadURI(data, `${name}.${extension}`);
});
}

getQRCanvas(): QRCanvas | undefined {
return this._canvas;
}
}
35 changes: 11 additions & 24 deletions src/core/QRDot.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { drawCircle, DrawFunctionArgs, drawSquare } from "../tools/drawUtils";

type GetNeighbor = (x: number, y: number) => boolean;
type DrawFunctionArgs = {
x: number;
y: number;
size: number;
context: CanvasRenderingContext2D;
getNeighbor: GetNeighbor;
};

export default class QRDot {
_context: CanvasRenderingContext2D;
Expand All @@ -19,34 +14,26 @@ export default class QRDot {
draw(x: number, y: number, size: number, getNeighbor: GetNeighbor): void {
const context = this._context;
const type = this._type;
let drawFunction;
const drawFunctionArgs = { x, y, size, context, getNeighbor };

switch (type) {
case "dots":
drawFunction = this._drawDots;
drawCircle(drawFunctionArgs);
break;
case "small-dots":
drawCircle(drawFunctionArgs, 3);
break;
case "rounded":
drawFunction = this._drawRounded;
this._drawRounded(drawFunctionArgs, getNeighbor);
break;
case "square":
default:
drawFunction = this._drawSquare;
drawSquare(drawFunctionArgs);
break;
}

drawFunction({ x, y, size, context, getNeighbor });
}

_drawDots({ x, y, size, context }: DrawFunctionArgs): void {
context.beginPath();
context.arc(x + size / 2, y + size / 2, size / 2, 0, Math.PI * 2);
context.fill();
}

_drawSquare({ x, y, size, context }: DrawFunctionArgs): void {
context.fillRect(x, y, size, size);
}

_drawRounded({ x, y, size, context, getNeighbor }: DrawFunctionArgs): void {
_drawRounded({ x, y, size, context }: DrawFunctionArgs, getNeighbor: GetNeighbor): void {
context.beginPath();
context.moveTo(x, y + size / 2);

Expand Down
Loading