qr-generator-styled 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +438 -0
- package/dist/cli/index.d.ts +29 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +126 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/QRGenerator.d.ts +41 -0
- package/dist/lib/QRGenerator.d.ts.map +1 -0
- package/dist/lib/QRGenerator.js +107 -0
- package/dist/lib/QRGenerator.js.map +1 -0
- package/dist/lib/renderers/BackgroundRenderer.d.ts +23 -0
- package/dist/lib/renderers/BackgroundRenderer.d.ts.map +1 -0
- package/dist/lib/renderers/BackgroundRenderer.js +48 -0
- package/dist/lib/renderers/BackgroundRenderer.js.map +1 -0
- package/dist/lib/renderers/GradientRenderer.d.ts +19 -0
- package/dist/lib/renderers/GradientRenderer.d.ts.map +1 -0
- package/dist/lib/renderers/GradientRenderer.js +44 -0
- package/dist/lib/renderers/GradientRenderer.js.map +1 -0
- package/dist/lib/renderers/LogoRenderer.d.ts +23 -0
- package/dist/lib/renderers/LogoRenderer.d.ts.map +1 -0
- package/dist/lib/renderers/LogoRenderer.js +72 -0
- package/dist/lib/renderers/LogoRenderer.js.map +1 -0
- package/dist/lib/renderers/ModuleRenderer.d.ts +41 -0
- package/dist/lib/renderers/ModuleRenderer.d.ts.map +1 -0
- package/dist/lib/renderers/ModuleRenderer.js +133 -0
- package/dist/lib/renderers/ModuleRenderer.js.map +1 -0
- package/dist/lib/utils/types.d.ts +52 -0
- package/dist/lib/utils/types.d.ts.map +1 -0
- package/dist/lib/utils/types.js +29 -0
- package/dist/lib/utils/types.js.map +1 -0
- package/dist/lib/utils/validators.d.ts +11 -0
- package/dist/lib/utils/validators.d.ts.map +1 -0
- package/dist/lib/utils/validators.js +50 -0
- package/dist/lib/utils/validators.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Canvas } from 'canvas';
|
|
2
|
+
import { QROptions } from './utils/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* QR Code Generator with advanced styling options
|
|
5
|
+
*/
|
|
6
|
+
export declare class QRGenerator {
|
|
7
|
+
private options;
|
|
8
|
+
/**
|
|
9
|
+
* Creates a new QR generator instance
|
|
10
|
+
*/
|
|
11
|
+
constructor(options: QROptions);
|
|
12
|
+
/**
|
|
13
|
+
* Generates QR code and returns the canvas
|
|
14
|
+
*/
|
|
15
|
+
generate(): Promise<Canvas>;
|
|
16
|
+
/**
|
|
17
|
+
* Generates QR code and saves to file
|
|
18
|
+
*/
|
|
19
|
+
generateToFile(outputPath: string): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Generates QR code and returns buffer
|
|
22
|
+
*/
|
|
23
|
+
generateToBuffer(format?: 'png' | 'jpeg'): Promise<Buffer>;
|
|
24
|
+
/**
|
|
25
|
+
* Generates QR code and returns data URL
|
|
26
|
+
*/
|
|
27
|
+
generateToDataURL(format?: 'png' | 'jpeg'): Promise<string>;
|
|
28
|
+
/**
|
|
29
|
+
* Updates generator options
|
|
30
|
+
*/
|
|
31
|
+
updateOptions(options: Partial<QROptions>): void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Helper function to quickly generate a QR code
|
|
35
|
+
*/
|
|
36
|
+
export declare function generateQR(options: QROptions): Promise<Canvas>;
|
|
37
|
+
/**
|
|
38
|
+
* Helper function to quickly generate and save a QR code
|
|
39
|
+
*/
|
|
40
|
+
export declare function generateQRToFile(options: QROptions, outputPath: string): Promise<void>;
|
|
41
|
+
//# sourceMappingURL=QRGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QRGenerator.d.ts","sourceRoot":"","sources":["../../src/lib/QRGenerator.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,MAAM,EAAE,MAAM,QAAQ,CAAC;AAM9C,OAAO,EAAE,SAAS,EAAmB,MAAM,kBAAkB,CAAC;AAG9D;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAsB;IAErC;;OAEG;gBACS,OAAO,EAAE,SAAS;IAQ9B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;IA6CjC;;OAEG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvD;;OAEG;IACG,gBAAgB,CAAC,MAAM,GAAE,KAAK,GAAG,MAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAMvE;;OAEG;IACG,iBAAiB,CAAC,MAAM,GAAE,KAAK,GAAG,MAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAQxE;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI;CAOjD;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAGpE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,SAAS,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAGf"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import QRCode from 'qrcode';
|
|
2
|
+
import { createCanvas } from 'canvas';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { BackgroundRenderer } from './renderers/BackgroundRenderer.js';
|
|
5
|
+
import { GradientRenderer } from './renderers/GradientRenderer.js';
|
|
6
|
+
import { ModuleRenderer } from './renderers/ModuleRenderer.js';
|
|
7
|
+
import { LogoRenderer } from './renderers/LogoRenderer.js';
|
|
8
|
+
import { DEFAULT_OPTIONS } from './utils/types.js';
|
|
9
|
+
import { validateOptions, normalizeOptions } from './utils/validators.js';
|
|
10
|
+
/**
|
|
11
|
+
* QR Code Generator with advanced styling options
|
|
12
|
+
*/
|
|
13
|
+
export class QRGenerator {
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new QR generator instance
|
|
16
|
+
*/
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.options = normalizeOptions(options, DEFAULT_OPTIONS);
|
|
19
|
+
validateOptions(this.options);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Generates QR code and returns the canvas
|
|
23
|
+
*/
|
|
24
|
+
async generate() {
|
|
25
|
+
const { url, errorCorrectionLevel, size, padding } = this.options;
|
|
26
|
+
const qrSize = size - padding * 2;
|
|
27
|
+
// Generate QR data
|
|
28
|
+
const qrData = await QRCode.create(url, {
|
|
29
|
+
errorCorrectionLevel
|
|
30
|
+
});
|
|
31
|
+
const modules = qrData.modules;
|
|
32
|
+
const moduleCount = modules.size;
|
|
33
|
+
const moduleSize = qrSize / moduleCount;
|
|
34
|
+
// Create canvas
|
|
35
|
+
const canvas = createCanvas(size, size);
|
|
36
|
+
const ctx = canvas.getContext('2d');
|
|
37
|
+
// Render background
|
|
38
|
+
const backgroundRenderer = new BackgroundRenderer(ctx, this.options);
|
|
39
|
+
backgroundRenderer.render();
|
|
40
|
+
backgroundRenderer.applyClipping();
|
|
41
|
+
// Create fill style (gradient or solid)
|
|
42
|
+
const gradientRenderer = new GradientRenderer(ctx, this.options);
|
|
43
|
+
const fillStyle = gradientRenderer.getFillStyle();
|
|
44
|
+
// Render QR modules
|
|
45
|
+
const moduleRenderer = new ModuleRenderer(ctx, modules, {
|
|
46
|
+
...this.options,
|
|
47
|
+
moduleCount,
|
|
48
|
+
moduleSize
|
|
49
|
+
});
|
|
50
|
+
moduleRenderer.render(fillStyle);
|
|
51
|
+
backgroundRenderer.restoreClipping();
|
|
52
|
+
// Render logo if provided
|
|
53
|
+
if (this.options.logo) {
|
|
54
|
+
const logoRenderer = new LogoRenderer(ctx, this.options);
|
|
55
|
+
await logoRenderer.render(this.options.logo);
|
|
56
|
+
}
|
|
57
|
+
return canvas;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Generates QR code and saves to file
|
|
61
|
+
*/
|
|
62
|
+
async generateToFile(outputPath) {
|
|
63
|
+
const canvas = await this.generate();
|
|
64
|
+
const buffer = canvas.toBuffer('image/png');
|
|
65
|
+
fs.writeFileSync(outputPath, buffer);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Generates QR code and returns buffer
|
|
69
|
+
*/
|
|
70
|
+
async generateToBuffer(format = 'png') {
|
|
71
|
+
const canvas = await this.generate();
|
|
72
|
+
const mimeType = format === 'jpeg' ? 'image/jpeg' : 'image/png';
|
|
73
|
+
return canvas.toBuffer(mimeType);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Generates QR code and returns data URL
|
|
77
|
+
*/
|
|
78
|
+
async generateToDataURL(format = 'png') {
|
|
79
|
+
const canvas = await this.generate();
|
|
80
|
+
if (format === 'jpeg') {
|
|
81
|
+
return canvas.toDataURL('image/jpeg');
|
|
82
|
+
}
|
|
83
|
+
return canvas.toDataURL('image/png');
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Updates generator options
|
|
87
|
+
*/
|
|
88
|
+
updateOptions(options) {
|
|
89
|
+
this.options = normalizeOptions({ ...this.options, ...options }, DEFAULT_OPTIONS);
|
|
90
|
+
validateOptions(this.options);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Helper function to quickly generate a QR code
|
|
95
|
+
*/
|
|
96
|
+
export async function generateQR(options) {
|
|
97
|
+
const generator = new QRGenerator(options);
|
|
98
|
+
return generator.generate();
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Helper function to quickly generate and save a QR code
|
|
102
|
+
*/
|
|
103
|
+
export async function generateQRToFile(options, outputPath) {
|
|
104
|
+
const generator = new QRGenerator(options);
|
|
105
|
+
return generator.generateToFile(outputPath);
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=QRGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QRGenerator.js","sourceRoot":"","sources":["../../src/lib/QRGenerator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { QROptions } from '../utils/types.js';
|
|
2
|
+
import type { CanvasRenderingContext2D } from 'canvas';
|
|
3
|
+
/**
|
|
4
|
+
* Handles background rendering for QR codes
|
|
5
|
+
*/
|
|
6
|
+
export declare class BackgroundRenderer {
|
|
7
|
+
private ctx;
|
|
8
|
+
private options;
|
|
9
|
+
constructor(ctx: CanvasRenderingContext2D, options: Required<QROptions>);
|
|
10
|
+
/**
|
|
11
|
+
* Renders background with rounded corners
|
|
12
|
+
*/
|
|
13
|
+
render(): void;
|
|
14
|
+
/**
|
|
15
|
+
* Applies clipping path for rounded corners
|
|
16
|
+
*/
|
|
17
|
+
applyClipping(): void;
|
|
18
|
+
/**
|
|
19
|
+
* Restores canvas context after clipping
|
|
20
|
+
*/
|
|
21
|
+
restoreClipping(): void;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=BackgroundRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BackgroundRenderer.d.ts","sourceRoot":"","sources":["../../../src/lib/renderers/BackgroundRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,QAAQ,CAAC;AAEvD;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,OAAO,CAAsB;gBAEzB,GAAG,EAAE,wBAAwB,EAAE,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC;IAKvE;;OAEG;IACH,MAAM,IAAI,IAAI;IAed;;OAEG;IACH,aAAa,IAAI,IAAI;IAerB;;OAEG;IACH,eAAe,IAAI,IAAI;CAGxB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles background rendering for QR codes
|
|
3
|
+
*/
|
|
4
|
+
export class BackgroundRenderer {
|
|
5
|
+
constructor(ctx, options) {
|
|
6
|
+
this.ctx = ctx;
|
|
7
|
+
this.options = options;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Renders background with rounded corners
|
|
11
|
+
*/
|
|
12
|
+
render() {
|
|
13
|
+
const { size, cornerRadius, backgroundColor } = this.options;
|
|
14
|
+
const ctx = this.ctx;
|
|
15
|
+
ctx.fillStyle = backgroundColor;
|
|
16
|
+
ctx.beginPath();
|
|
17
|
+
ctx.moveTo(cornerRadius, 0);
|
|
18
|
+
ctx.arcTo(size, 0, size, size, cornerRadius);
|
|
19
|
+
ctx.arcTo(size, size, 0, size, cornerRadius);
|
|
20
|
+
ctx.arcTo(0, size, 0, 0, cornerRadius);
|
|
21
|
+
ctx.arcTo(0, 0, size, 0, cornerRadius);
|
|
22
|
+
ctx.closePath();
|
|
23
|
+
ctx.fill();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Applies clipping path for rounded corners
|
|
27
|
+
*/
|
|
28
|
+
applyClipping() {
|
|
29
|
+
const { size, cornerRadius } = this.options;
|
|
30
|
+
const ctx = this.ctx;
|
|
31
|
+
ctx.save();
|
|
32
|
+
ctx.beginPath();
|
|
33
|
+
ctx.moveTo(cornerRadius, 0);
|
|
34
|
+
ctx.arcTo(size, 0, size, size, cornerRadius);
|
|
35
|
+
ctx.arcTo(size, size, 0, size, cornerRadius);
|
|
36
|
+
ctx.arcTo(0, size, 0, 0, cornerRadius);
|
|
37
|
+
ctx.arcTo(0, 0, size, 0, cornerRadius);
|
|
38
|
+
ctx.closePath();
|
|
39
|
+
ctx.clip();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Restores canvas context after clipping
|
|
43
|
+
*/
|
|
44
|
+
restoreClipping() {
|
|
45
|
+
this.ctx.restore();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=BackgroundRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BackgroundRenderer.js","sourceRoot":"","sources":["../../../src/lib/renderers/BackgroundRenderer.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,OAAO,kBAAkB;IAI7B,YAAY,GAA6B,EAAE,OAA4B;QACrE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QAErB,GAAG,CAAC,SAAS,GAAG,eAAe,CAAC;QAChC,GAAG,CAAC,SAAS,EAAE,CAAC;QAChB,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAC5B,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;QAC7C,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;QAC7C,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;QACvC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;QACvC,GAAG,CAAC,SAAS,EAAE,CAAC;QAChB,GAAG,CAAC,IAAI,EAAE,CAAC;IACb,CAAC;IAED;;OAEG;IACH,aAAa;QACX,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QAErB,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,SAAS,EAAE,CAAC;QAChB,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAC5B,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;QAC7C,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;QAC7C,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;QACvC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;QACvC,GAAG,CAAC,SAAS,EAAE,CAAC;QAChB,GAAG,CAAC,IAAI,EAAE,CAAC;IACb,CAAC;IAED;;OAEG;IACH,eAAe;QACb,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { QROptions } from '../utils/types.js';
|
|
2
|
+
import type { CanvasRenderingContext2D, CanvasGradient } from 'canvas';
|
|
3
|
+
/**
|
|
4
|
+
* Handles gradient creation for QR codes
|
|
5
|
+
*/
|
|
6
|
+
export declare class GradientRenderer {
|
|
7
|
+
private ctx;
|
|
8
|
+
private options;
|
|
9
|
+
constructor(ctx: CanvasRenderingContext2D, options: Required<QROptions>);
|
|
10
|
+
/**
|
|
11
|
+
* Creates a gradient fill style
|
|
12
|
+
*/
|
|
13
|
+
createGradient(): CanvasGradient;
|
|
14
|
+
/**
|
|
15
|
+
* Gets the appropriate fill style (gradient or solid color)
|
|
16
|
+
*/
|
|
17
|
+
getFillStyle(): string | CanvasGradient;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=GradientRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GradientRenderer.d.ts","sourceRoot":"","sources":["../../../src/lib/renderers/GradientRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAEvE;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,OAAO,CAAsB;gBAEzB,GAAG,EAAE,wBAAwB,EAAE,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC;IAKvE;;OAEG;IACH,cAAc,IAAI,cAAc;IAgChC;;OAEG;IACH,YAAY,IAAI,MAAM,GAAG,cAAc;CAIxC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles gradient creation for QR codes
|
|
3
|
+
*/
|
|
4
|
+
export class GradientRenderer {
|
|
5
|
+
constructor(ctx, options) {
|
|
6
|
+
this.ctx = ctx;
|
|
7
|
+
this.options = options;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Creates a gradient fill style
|
|
11
|
+
*/
|
|
12
|
+
createGradient() {
|
|
13
|
+
const { size, gradientColors, gradientAngle } = this.options;
|
|
14
|
+
const ctx = this.ctx;
|
|
15
|
+
// Parse gradient colors
|
|
16
|
+
const colors = gradientColors.split(',').map(c => c.trim());
|
|
17
|
+
// Calculate angle in radians
|
|
18
|
+
const angleRad = (gradientAngle * Math.PI) / 180;
|
|
19
|
+
// Calculate gradient start and end points
|
|
20
|
+
const centerX = size / 2;
|
|
21
|
+
const centerY = size / 2;
|
|
22
|
+
const length = Math.sqrt(size * size + size * size) / 2;
|
|
23
|
+
const x0 = centerX - Math.cos(angleRad) * length;
|
|
24
|
+
const y0 = centerY - Math.sin(angleRad) * length;
|
|
25
|
+
const x1 = centerX + Math.cos(angleRad) * length;
|
|
26
|
+
const y1 = centerY + Math.sin(angleRad) * length;
|
|
27
|
+
// Create linear gradient
|
|
28
|
+
const gradient = ctx.createLinearGradient(x0, y0, x1, y1);
|
|
29
|
+
// Add color stops uniformly distributed
|
|
30
|
+
colors.forEach((color, index) => {
|
|
31
|
+
const stop = index / (colors.length - 1);
|
|
32
|
+
gradient.addColorStop(stop, color);
|
|
33
|
+
});
|
|
34
|
+
return gradient;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Gets the appropriate fill style (gradient or solid color)
|
|
38
|
+
*/
|
|
39
|
+
getFillStyle() {
|
|
40
|
+
const { gradient, color } = this.options;
|
|
41
|
+
return gradient ? this.createGradient() : color;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=GradientRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GradientRenderer.js","sourceRoot":"","sources":["../../../src/lib/renderers/GradientRenderer.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAI3B,YAAY,GAA6B,EAAE,OAA4B;QACrE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QAErB,wBAAwB;QACxB,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAE5D,6BAA6B;QAC7B,MAAM,QAAQ,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;QAEjD,0CAA0C;QAC1C,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QAExD,MAAM,EAAE,GAAG,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;QACjD,MAAM,EAAE,GAAG,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;QACjD,MAAM,EAAE,GAAG,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;QACjD,MAAM,EAAE,GAAG,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;QAEjD,yBAAyB;QACzB,MAAM,QAAQ,GAAG,GAAG,CAAC,oBAAoB,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAE1D,wCAAwC;QACxC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAC9B,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACzC,QAAQ,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,YAAY;QACV,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QACzC,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAClD,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CanvasRenderingContext2D } from 'canvas';
|
|
2
|
+
import { QROptions } from '../utils/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Handles logo rendering on QR codes
|
|
5
|
+
*/
|
|
6
|
+
export declare class LogoRenderer {
|
|
7
|
+
private ctx;
|
|
8
|
+
private options;
|
|
9
|
+
constructor(ctx: CanvasRenderingContext2D, options: Required<QROptions>);
|
|
10
|
+
/**
|
|
11
|
+
* Renders logo with background
|
|
12
|
+
*/
|
|
13
|
+
render(logoPath: string): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Draws logo background (circle or rounded square)
|
|
16
|
+
*/
|
|
17
|
+
private drawLogoBackground;
|
|
18
|
+
/**
|
|
19
|
+
* Draws logo with shadow effect
|
|
20
|
+
*/
|
|
21
|
+
private drawLogoWithShadow;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=LogoRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogoRenderer.d.ts","sourceRoot":"","sources":["../../../src/lib/renderers/LogoRenderer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,OAAO,CAAsB;gBAEzB,GAAG,EAAE,wBAAwB,EAAE,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC;IAKvE;;OAEG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB7C;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA0C1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAuB3B"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { loadImage } from 'canvas';
|
|
2
|
+
/**
|
|
3
|
+
* Handles logo rendering on QR codes
|
|
4
|
+
*/
|
|
5
|
+
export class LogoRenderer {
|
|
6
|
+
constructor(ctx, options) {
|
|
7
|
+
this.ctx = ctx;
|
|
8
|
+
this.options = options;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Renders logo with background
|
|
12
|
+
*/
|
|
13
|
+
async render(logoPath) {
|
|
14
|
+
if (!logoPath)
|
|
15
|
+
return;
|
|
16
|
+
const img = await loadImage(logoPath);
|
|
17
|
+
const { size, logoPadding } = this.options;
|
|
18
|
+
const logoSize = size * 0.25;
|
|
19
|
+
const bgSize = logoSize + logoPadding;
|
|
20
|
+
const centerX = size / 2;
|
|
21
|
+
const centerY = size / 2;
|
|
22
|
+
// Draw logo background
|
|
23
|
+
this.drawLogoBackground(centerX, centerY, bgSize);
|
|
24
|
+
// Draw logo with shadow
|
|
25
|
+
this.drawLogoWithShadow(img, centerX, centerY, logoSize);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Draws logo background (circle or rounded square)
|
|
29
|
+
*/
|
|
30
|
+
drawLogoBackground(centerX, centerY, bgSize) {
|
|
31
|
+
const { logoShape, logoRadius, backgroundColor } = this.options;
|
|
32
|
+
const ctx = this.ctx;
|
|
33
|
+
ctx.fillStyle = backgroundColor;
|
|
34
|
+
if (logoShape === 'circle') {
|
|
35
|
+
ctx.beginPath();
|
|
36
|
+
ctx.arc(centerX, centerY, bgSize / 2, 0, Math.PI * 2);
|
|
37
|
+
ctx.fill();
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// Rounded square
|
|
41
|
+
const squareX = centerX - bgSize / 2;
|
|
42
|
+
const squareY = centerY - bgSize / 2;
|
|
43
|
+
ctx.beginPath();
|
|
44
|
+
ctx.moveTo(squareX + logoRadius, squareY);
|
|
45
|
+
ctx.arcTo(squareX + bgSize, squareY, squareX + bgSize, squareY + bgSize, logoRadius);
|
|
46
|
+
ctx.arcTo(squareX + bgSize, squareY + bgSize, squareX, squareY + bgSize, logoRadius);
|
|
47
|
+
ctx.arcTo(squareX, squareY + bgSize, squareX, squareY, logoRadius);
|
|
48
|
+
ctx.arcTo(squareX, squareY, squareX + bgSize, squareY, logoRadius);
|
|
49
|
+
ctx.closePath();
|
|
50
|
+
ctx.fill();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Draws logo with shadow effect
|
|
55
|
+
*/
|
|
56
|
+
drawLogoWithShadow(img, centerX, centerY, logoSize) {
|
|
57
|
+
const ctx = this.ctx;
|
|
58
|
+
// Apply shadow
|
|
59
|
+
ctx.shadowColor = 'rgba(0, 0, 0, 0.15)';
|
|
60
|
+
ctx.shadowBlur = 12;
|
|
61
|
+
ctx.shadowOffsetX = 0;
|
|
62
|
+
ctx.shadowOffsetY = 2;
|
|
63
|
+
// Draw logo
|
|
64
|
+
const logoX = centerX - logoSize / 2;
|
|
65
|
+
const logoY = centerY - logoSize / 2;
|
|
66
|
+
ctx.drawImage(img, logoX, logoY, logoSize, logoSize);
|
|
67
|
+
// Reset shadow
|
|
68
|
+
ctx.shadowColor = 'transparent';
|
|
69
|
+
ctx.shadowBlur = 0;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=LogoRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogoRenderer.js","sourceRoot":"","sources":["../../../src/lib/renderers/LogoRenderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { QROptions } from '../utils/types.js';
|
|
2
|
+
import type { CanvasRenderingContext2D, CanvasGradient } from 'canvas';
|
|
3
|
+
interface QRModules {
|
|
4
|
+
size: number;
|
|
5
|
+
get(row: number, col: number): number;
|
|
6
|
+
}
|
|
7
|
+
interface RenderOptions extends Required<QROptions> {
|
|
8
|
+
moduleCount: number;
|
|
9
|
+
moduleSize: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Handles QR module rendering with rounded corners
|
|
13
|
+
*/
|
|
14
|
+
export declare class ModuleRenderer {
|
|
15
|
+
private ctx;
|
|
16
|
+
private modules;
|
|
17
|
+
private options;
|
|
18
|
+
constructor(ctx: CanvasRenderingContext2D, modules: QRModules, options: RenderOptions);
|
|
19
|
+
/**
|
|
20
|
+
* Checks if a module exists at given position
|
|
21
|
+
*/
|
|
22
|
+
private hasModule;
|
|
23
|
+
/**
|
|
24
|
+
* Renders all QR modules
|
|
25
|
+
*/
|
|
26
|
+
render(fillStyle: string | CanvasGradient): void;
|
|
27
|
+
/**
|
|
28
|
+
* Renders modules with rounded corners
|
|
29
|
+
*/
|
|
30
|
+
private renderRoundedModules;
|
|
31
|
+
/**
|
|
32
|
+
* Draws a single module with selectively rounded corners
|
|
33
|
+
*/
|
|
34
|
+
private drawRoundedModule;
|
|
35
|
+
/**
|
|
36
|
+
* Renders simple square modules
|
|
37
|
+
*/
|
|
38
|
+
private renderSquareModules;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=ModuleRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModuleRenderer.d.ts","sourceRoot":"","sources":["../../../src/lib/renderers/ModuleRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAEvE,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvC;AAED,UAAU,aAAc,SAAQ,QAAQ,CAAC,SAAS,CAAC;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAgBD;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,OAAO,CAAgB;gBAG7B,GAAG,EAAE,wBAAwB,EAC7B,OAAO,EAAE,SAAS,EAClB,OAAO,EAAE,aAAa;IAOxB;;OAEG;IACH,OAAO,CAAC,SAAS;IAQjB;;OAEG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAWhD;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA2C5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA6EzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAc5B"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles QR module rendering with rounded corners
|
|
3
|
+
*/
|
|
4
|
+
export class ModuleRenderer {
|
|
5
|
+
constructor(ctx, modules, options) {
|
|
6
|
+
this.ctx = ctx;
|
|
7
|
+
this.modules = modules;
|
|
8
|
+
this.options = options;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Checks if a module exists at given position
|
|
12
|
+
*/
|
|
13
|
+
hasModule(row, col) {
|
|
14
|
+
const { moduleCount } = this.options;
|
|
15
|
+
if (row < 0 || row >= moduleCount || col < 0 || col >= moduleCount) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
return this.modules.get(row, col) === 1;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Renders all QR modules
|
|
22
|
+
*/
|
|
23
|
+
render(fillStyle) {
|
|
24
|
+
const { rounded } = this.options;
|
|
25
|
+
this.ctx.fillStyle = fillStyle;
|
|
26
|
+
if (rounded) {
|
|
27
|
+
this.renderRoundedModules();
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
this.renderSquareModules();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Renders modules with rounded corners
|
|
35
|
+
*/
|
|
36
|
+
renderRoundedModules() {
|
|
37
|
+
const { moduleCount, moduleSize, padding, moduleRadius } = this.options;
|
|
38
|
+
const ctx = this.ctx;
|
|
39
|
+
const cornerRadius = moduleSize * moduleRadius;
|
|
40
|
+
for (let row = 0; row < moduleCount; row++) {
|
|
41
|
+
for (let col = 0; col < moduleCount; col++) {
|
|
42
|
+
if (this.modules.get(row, col)) {
|
|
43
|
+
const x = padding + col * moduleSize;
|
|
44
|
+
const y = padding + row * moduleSize;
|
|
45
|
+
// Check adjacent modules
|
|
46
|
+
const top = this.hasModule(row - 1, col);
|
|
47
|
+
const right = this.hasModule(row, col + 1);
|
|
48
|
+
const bottom = this.hasModule(row + 1, col);
|
|
49
|
+
const left = this.hasModule(row, col - 1);
|
|
50
|
+
// Determine which corners to round
|
|
51
|
+
const roundTL = !top && !left;
|
|
52
|
+
const roundTR = !top && !right;
|
|
53
|
+
const roundBR = !bottom && !right;
|
|
54
|
+
const roundBL = !bottom && !left;
|
|
55
|
+
// Small extension to eliminate gaps
|
|
56
|
+
const gap = 0.5;
|
|
57
|
+
const extendTop = top ? gap : 0;
|
|
58
|
+
const extendRight = right ? gap : 0;
|
|
59
|
+
const extendBottom = bottom ? gap : 0;
|
|
60
|
+
const extendLeft = left ? gap : 0;
|
|
61
|
+
this.drawRoundedModule(x, y, moduleSize, cornerRadius, { roundTL, roundTR, roundBR, roundBL }, { extendTop, extendRight, extendBottom, extendLeft });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Draws a single module with selectively rounded corners
|
|
68
|
+
*/
|
|
69
|
+
drawRoundedModule(x, y, size, radius, corners, extensions) {
|
|
70
|
+
const ctx = this.ctx;
|
|
71
|
+
const { roundTL, roundTR, roundBR, roundBL } = corners;
|
|
72
|
+
const { extendTop, extendRight, extendBottom, extendLeft } = extensions;
|
|
73
|
+
ctx.beginPath();
|
|
74
|
+
// Top-left corner
|
|
75
|
+
if (roundTL) {
|
|
76
|
+
ctx.moveTo(x + radius - extendLeft, y - extendTop);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
ctx.moveTo(x - extendLeft, y - extendTop);
|
|
80
|
+
}
|
|
81
|
+
// Top side and top-right corner
|
|
82
|
+
if (roundTR) {
|
|
83
|
+
ctx.lineTo(x + size - radius + extendRight, y - extendTop);
|
|
84
|
+
ctx.quadraticCurveTo(x + size + extendRight, y - extendTop, x + size + extendRight, y + radius - extendTop);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
ctx.lineTo(x + size + extendRight, y - extendTop);
|
|
88
|
+
}
|
|
89
|
+
// Right side and bottom-right corner
|
|
90
|
+
if (roundBR) {
|
|
91
|
+
ctx.lineTo(x + size + extendRight, y + size - radius + extendBottom);
|
|
92
|
+
ctx.quadraticCurveTo(x + size + extendRight, y + size + extendBottom, x + size - radius + extendRight, y + size + extendBottom);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
ctx.lineTo(x + size + extendRight, y + size + extendBottom);
|
|
96
|
+
}
|
|
97
|
+
// Bottom side and bottom-left corner
|
|
98
|
+
if (roundBL) {
|
|
99
|
+
ctx.lineTo(x + radius - extendLeft, y + size + extendBottom);
|
|
100
|
+
ctx.quadraticCurveTo(x - extendLeft, y + size + extendBottom, x - extendLeft, y + size - radius + extendBottom);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
ctx.lineTo(x - extendLeft, y + size + extendBottom);
|
|
104
|
+
}
|
|
105
|
+
// Left side and close path
|
|
106
|
+
if (roundTL) {
|
|
107
|
+
ctx.lineTo(x - extendLeft, y + radius - extendTop);
|
|
108
|
+
ctx.quadraticCurveTo(x - extendLeft, y - extendTop, x + radius - extendLeft, y - extendTop);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
ctx.lineTo(x - extendLeft, y - extendTop);
|
|
112
|
+
}
|
|
113
|
+
ctx.closePath();
|
|
114
|
+
ctx.fill();
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Renders simple square modules
|
|
118
|
+
*/
|
|
119
|
+
renderSquareModules() {
|
|
120
|
+
const { moduleCount, moduleSize, padding } = this.options;
|
|
121
|
+
const ctx = this.ctx;
|
|
122
|
+
for (let row = 0; row < moduleCount; row++) {
|
|
123
|
+
for (let col = 0; col < moduleCount; col++) {
|
|
124
|
+
if (this.modules.get(row, col)) {
|
|
125
|
+
const x = padding + col * moduleSize;
|
|
126
|
+
const y = padding + row * moduleSize;
|
|
127
|
+
ctx.fillRect(x, y, moduleSize, moduleSize);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=ModuleRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModuleRenderer.js","sourceRoot":"","sources":["../../../src/lib/renderers/ModuleRenderer.ts"],"names":[],"mappings":"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"}
|