xpict 0.4.1 → 1.0.1
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/README.md +272 -17
- package/dist/effects/blur.d.ts +2 -3
- package/dist/effects/blur.js +14 -4
- package/dist/effects/box-blur.d.ts +2 -0
- package/dist/effects/box-blur.js +61 -0
- package/dist/effects/grayscale.d.ts +2 -2
- package/dist/effects/grayscale.js +14 -4
- package/dist/effects/index.d.ts +1 -1
- package/dist/effects/index.js +1 -1
- package/dist/enums/index.d.ts +2 -0
- package/dist/enums/index.js +18 -0
- package/dist/enums/text-align.d.ts +5 -0
- package/dist/enums/text-align.js +9 -0
- package/dist/enums/text-baseline.d.ts +8 -0
- package/dist/enums/text-baseline.js +12 -0
- package/dist/index.d.ts +5 -7
- package/dist/index.js +27 -7
- package/dist/layers/circle-layer.d.ts +1 -1
- package/dist/layers/circle-layer.js +6 -20
- package/dist/layers/group-layer.js +2 -4
- package/dist/layers/image-layer.d.ts +5 -4
- package/dist/layers/image-layer.js +23 -19
- package/dist/layers/line-layer.d.ts +1 -1
- package/dist/layers/line-layer.js +10 -24
- package/dist/layers/rectangle-layer.d.ts +1 -1
- package/dist/layers/rectangle-layer.js +6 -20
- package/dist/layers/repeat-layer.js +2 -4
- package/dist/layers/text-layer.d.ts +7 -15
- package/dist/layers/text-layer.js +8 -42
- package/dist/render-context.d.ts +2 -2
- package/dist/template.d.ts +6 -4
- package/dist/template.js +22 -30
- package/dist/utils/font.d.ts +17 -0
- package/dist/utils/font.js +21 -0
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/resolve-axis.d.ts +3 -5
- package/dist/utils/value-of-enum.d.ts +1 -0
- package/dist/utils/value-of-enum.js +2 -0
- package/package.json +5 -5
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.GroupLayer = void 0;
|
|
4
4
|
const layer_1 = require("./layer");
|
|
5
5
|
const resolve_axis_1 = require("../utils/resolve-axis");
|
|
6
|
-
const commit_frame_1 = require("../utils/commit-frame");
|
|
7
6
|
class GroupLayer extends layer_1.Layer {
|
|
8
7
|
constructor(options) {
|
|
9
8
|
super(options.when);
|
|
@@ -15,13 +14,13 @@ class GroupLayer extends layer_1.Layer {
|
|
|
15
14
|
axis: (_a = this.options.x) !== null && _a !== void 0 ? _a : 0,
|
|
16
15
|
data: data,
|
|
17
16
|
index: index,
|
|
18
|
-
|
|
17
|
+
templateSize: templateConfig,
|
|
19
18
|
});
|
|
20
19
|
const dy = (0, resolve_axis_1.resolveAxis)({
|
|
21
20
|
axis: (_b = this.options.y) !== null && _b !== void 0 ? _b : 0,
|
|
22
21
|
data: data,
|
|
23
22
|
index: index,
|
|
24
|
-
|
|
23
|
+
templateSize: templateConfig,
|
|
25
24
|
});
|
|
26
25
|
const prevX = ctx.offsetX;
|
|
27
26
|
const prevY = ctx.offsetY;
|
|
@@ -36,7 +35,6 @@ class GroupLayer extends layer_1.Layer {
|
|
|
36
35
|
index: index,
|
|
37
36
|
templateConfig: templateConfig,
|
|
38
37
|
});
|
|
39
|
-
ctx.image = await (0, commit_frame_1.commitFrame)(ctx.image);
|
|
40
38
|
}
|
|
41
39
|
ctx.offsetX = prevX;
|
|
42
40
|
ctx.offsetY = prevY;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Canvas, SKRSContext2D } from "@napi-rs/canvas";
|
|
2
2
|
import { Layer, RenderOptions, WhenFunction } from "./layer";
|
|
3
3
|
import { Axis } from "../utils/resolve-axis";
|
|
4
4
|
export type TransformOptions<Data> = {
|
|
5
5
|
data: Data;
|
|
6
6
|
index: number;
|
|
7
|
-
|
|
7
|
+
canvas: Canvas;
|
|
8
|
+
ctx: SKRSContext2D;
|
|
8
9
|
};
|
|
9
|
-
export type ImageTransformFunction<Data> = (options: TransformOptions<Data>) =>
|
|
10
|
+
export type ImageTransformFunction<Data> = (options: TransformOptions<Data>) => void | Promise<void>;
|
|
10
11
|
export type ImageImageSrcOptions<Data> = {
|
|
11
12
|
data: Data;
|
|
12
13
|
index: number;
|
|
@@ -27,5 +28,5 @@ export type ImageLayerOptions<Data> = {
|
|
|
27
28
|
export declare class ImageLayer<Data> extends Layer<Data> {
|
|
28
29
|
private options;
|
|
29
30
|
constructor(options: ImageLayerOptions<Data>);
|
|
30
|
-
render({ context:
|
|
31
|
+
render({ context: renderContext, data, index, templateConfig }: RenderOptions<Data>): Promise<void>;
|
|
31
32
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.ImageLayer = void 0;
|
|
7
|
-
const
|
|
4
|
+
const canvas_1 = require("@napi-rs/canvas");
|
|
8
5
|
const layer_1 = require("./layer");
|
|
9
6
|
const resolve_axis_1 = require("../utils/resolve-axis");
|
|
10
7
|
const error_1 = require("../error");
|
|
@@ -13,47 +10,54 @@ class ImageLayer extends layer_1.Layer {
|
|
|
13
10
|
super(options.when);
|
|
14
11
|
this.options = options;
|
|
15
12
|
}
|
|
16
|
-
async render({ context:
|
|
13
|
+
async render({ context: renderContext, data, index = 0, templateConfig }) {
|
|
17
14
|
const localX = (0, resolve_axis_1.resolveAxis)({
|
|
18
15
|
axis: this.options.x,
|
|
19
16
|
data: data,
|
|
20
17
|
index: index,
|
|
21
|
-
|
|
18
|
+
templateSize: templateConfig,
|
|
22
19
|
});
|
|
23
20
|
const localY = (0, resolve_axis_1.resolveAxis)({
|
|
24
21
|
axis: this.options.y,
|
|
25
22
|
data: data,
|
|
26
23
|
index: index,
|
|
27
|
-
|
|
24
|
+
templateSize: templateConfig,
|
|
28
25
|
});
|
|
29
|
-
const x =
|
|
30
|
-
const y =
|
|
26
|
+
const x = renderContext.offsetX + localX;
|
|
27
|
+
const y = renderContext.offsetY + localY;
|
|
31
28
|
const src = this.options.src;
|
|
32
29
|
const resolvedImageSource = typeof src === "string" ? src : src({ data: data, index: index });
|
|
30
|
+
const image = await (0, canvas_1.loadImage)(resolvedImageSource);
|
|
31
|
+
const localCanvas = (0, canvas_1.createCanvas)(image.width, image.height);
|
|
32
|
+
const localContext = localCanvas.getContext("2d");
|
|
33
33
|
try {
|
|
34
|
-
|
|
34
|
+
localContext.drawImage(image, 0, 0);
|
|
35
35
|
if (this.options.flipX) {
|
|
36
|
-
|
|
36
|
+
localContext.translate(image.width, 0);
|
|
37
|
+
localContext.scale(-1, 1);
|
|
37
38
|
}
|
|
38
39
|
if (this.options.flipY) {
|
|
39
|
-
|
|
40
|
+
localContext.translate(0, image.height);
|
|
41
|
+
localContext.scale(1, -1);
|
|
40
42
|
}
|
|
41
43
|
if (this.options.rotate !== undefined) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
localContext.translate(image.width / 2, image.height / 2);
|
|
45
|
+
localContext.rotate((this.options.rotate * Math.PI) / 180);
|
|
46
|
+
localContext.translate(-image.width / 2, -image.height / 2);
|
|
45
47
|
}
|
|
46
48
|
if (this.options.transform && this.options.transform.length > 0) {
|
|
47
49
|
for (const transform of this.options.transform) {
|
|
48
|
-
|
|
50
|
+
await transform({
|
|
49
51
|
data: data,
|
|
50
52
|
index: index,
|
|
51
|
-
|
|
53
|
+
canvas: localCanvas,
|
|
54
|
+
ctx: localContext,
|
|
52
55
|
});
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
|
-
const buffer =
|
|
56
|
-
|
|
58
|
+
const buffer = localCanvas.toBuffer("image/png");
|
|
59
|
+
const finalImage = await (0, canvas_1.loadImage)(buffer);
|
|
60
|
+
renderContext.ctx.drawImage(finalImage, x, y);
|
|
57
61
|
}
|
|
58
62
|
catch (error) {
|
|
59
63
|
throw new error_1.XpictError(`Failed to render image layer (${resolvedImageSource}): ${error.message}`);
|
|
@@ -16,5 +16,5 @@ export type LineLayerOptions<Data> = {
|
|
|
16
16
|
export declare class LineLayer<Data> extends Layer<Data> {
|
|
17
17
|
private readonly options;
|
|
18
18
|
constructor(options: LineLayerOptions<Data>);
|
|
19
|
-
render({ context:
|
|
19
|
+
render({ context: renderContext, data, index, templateConfig }: RenderOptions<Data>): Promise<void>;
|
|
20
20
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.LineLayer = void 0;
|
|
4
|
-
const canvas_1 = require("canvas");
|
|
5
4
|
const layer_1 = require("./layer");
|
|
6
5
|
const resolve_axis_1 = require("../utils/resolve-axis");
|
|
7
6
|
class LineLayer extends layer_1.Layer {
|
|
@@ -9,41 +8,36 @@ class LineLayer extends layer_1.Layer {
|
|
|
9
8
|
super(options.when);
|
|
10
9
|
this.options = options;
|
|
11
10
|
}
|
|
12
|
-
async render({ context:
|
|
13
|
-
const
|
|
14
|
-
const metadata = await image.metadata();
|
|
15
|
-
const canvasWidth = metadata.width;
|
|
16
|
-
const canvasHeight = metadata.height;
|
|
17
|
-
const x1 = ctx.offsetX +
|
|
11
|
+
async render({ context: renderContext, data, index = 0, templateConfig }) {
|
|
12
|
+
const x1 = renderContext.offsetX +
|
|
18
13
|
(0, resolve_axis_1.resolveAxis)({
|
|
19
14
|
axis: this.options.from.x,
|
|
20
15
|
data: data,
|
|
21
16
|
index: index,
|
|
22
|
-
|
|
17
|
+
templateSize: templateConfig,
|
|
23
18
|
});
|
|
24
|
-
const y1 =
|
|
19
|
+
const y1 = renderContext.offsetY +
|
|
25
20
|
(0, resolve_axis_1.resolveAxis)({
|
|
26
21
|
axis: this.options.from.y,
|
|
27
22
|
data: data,
|
|
28
23
|
index: index,
|
|
29
|
-
|
|
24
|
+
templateSize: templateConfig,
|
|
30
25
|
});
|
|
31
|
-
const x2 =
|
|
26
|
+
const x2 = renderContext.offsetX +
|
|
32
27
|
(0, resolve_axis_1.resolveAxis)({
|
|
33
28
|
axis: this.options.to.x,
|
|
34
29
|
data: data,
|
|
35
30
|
index: index,
|
|
36
|
-
|
|
31
|
+
templateSize: templateConfig,
|
|
37
32
|
});
|
|
38
|
-
const y2 =
|
|
33
|
+
const y2 = renderContext.offsetY +
|
|
39
34
|
(0, resolve_axis_1.resolveAxis)({
|
|
40
35
|
axis: this.options.to.y,
|
|
41
36
|
data: data,
|
|
42
37
|
index: index,
|
|
43
|
-
|
|
38
|
+
templateSize: templateConfig,
|
|
44
39
|
});
|
|
45
|
-
const
|
|
46
|
-
const context = canvas.getContext("2d");
|
|
40
|
+
const context = renderContext.ctx;
|
|
47
41
|
context.strokeStyle = this.options.color;
|
|
48
42
|
context.lineWidth = this.options.width;
|
|
49
43
|
context.lineCap = "round";
|
|
@@ -51,14 +45,6 @@ class LineLayer extends layer_1.Layer {
|
|
|
51
45
|
context.moveTo(x1, y1);
|
|
52
46
|
context.lineTo(x2, y2);
|
|
53
47
|
context.stroke();
|
|
54
|
-
const lineBuffer = canvas.toBuffer();
|
|
55
|
-
ctx.image = image.composite([
|
|
56
|
-
{
|
|
57
|
-
input: lineBuffer,
|
|
58
|
-
top: 0,
|
|
59
|
-
left: 0,
|
|
60
|
-
},
|
|
61
|
-
]);
|
|
62
48
|
}
|
|
63
49
|
}
|
|
64
50
|
exports.LineLayer = LineLayer;
|
|
@@ -12,5 +12,5 @@ export type RectangleLayerOptions<Data> = {
|
|
|
12
12
|
export declare class RectangleLayer<Data> extends Layer<Data> {
|
|
13
13
|
private readonly options;
|
|
14
14
|
constructor(options: RectangleLayerOptions<Data>);
|
|
15
|
-
render({ context:
|
|
15
|
+
render({ context: renderContext, data, index, templateConfig }: RenderOptions<Data>): Promise<void>;
|
|
16
16
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RectangleLayer = void 0;
|
|
4
|
-
const canvas_1 = require("canvas");
|
|
5
4
|
const layer_1 = require("./layer");
|
|
6
5
|
const resolve_axis_1 = require("../utils/resolve-axis");
|
|
7
6
|
class RectangleLayer extends layer_1.Layer {
|
|
@@ -9,28 +8,23 @@ class RectangleLayer extends layer_1.Layer {
|
|
|
9
8
|
super(options.when);
|
|
10
9
|
this.options = options;
|
|
11
10
|
}
|
|
12
|
-
async render({ context:
|
|
13
|
-
const image = ctx.image;
|
|
14
|
-
const metadata = await image.metadata();
|
|
15
|
-
const canvasWidth = metadata.width;
|
|
16
|
-
const canvasHeight = metadata.height;
|
|
11
|
+
async render({ context: renderContext, data, index = 0, templateConfig }) {
|
|
17
12
|
const localX = (0, resolve_axis_1.resolveAxis)({
|
|
18
13
|
axis: this.options.x,
|
|
19
14
|
data: data,
|
|
20
15
|
index: index,
|
|
21
|
-
|
|
16
|
+
templateSize: templateConfig,
|
|
22
17
|
});
|
|
23
18
|
const localY = (0, resolve_axis_1.resolveAxis)({
|
|
24
19
|
axis: this.options.y,
|
|
25
20
|
data: data,
|
|
26
21
|
index: index,
|
|
27
|
-
|
|
22
|
+
templateSize: templateConfig,
|
|
28
23
|
});
|
|
29
|
-
const x =
|
|
30
|
-
const y =
|
|
24
|
+
const x = renderContext.offsetX + localX;
|
|
25
|
+
const y = renderContext.offsetY + localY;
|
|
31
26
|
const { width, height, fill, borderRadius } = this.options;
|
|
32
|
-
const
|
|
33
|
-
const context = canvas.getContext("2d");
|
|
27
|
+
const context = renderContext.ctx;
|
|
34
28
|
context.fillStyle = fill;
|
|
35
29
|
if (borderRadius && borderRadius > 0) {
|
|
36
30
|
const r = Math.min(borderRadius, width / 2, height / 2);
|
|
@@ -50,14 +44,6 @@ class RectangleLayer extends layer_1.Layer {
|
|
|
50
44
|
else {
|
|
51
45
|
context.fillRect(x, y, width, height);
|
|
52
46
|
}
|
|
53
|
-
const rectangleBuffer = canvas.toBuffer();
|
|
54
|
-
ctx.image = image.composite([
|
|
55
|
-
{
|
|
56
|
-
input: rectangleBuffer,
|
|
57
|
-
top: 0,
|
|
58
|
-
left: 0,
|
|
59
|
-
},
|
|
60
|
-
]);
|
|
61
47
|
}
|
|
62
48
|
}
|
|
63
49
|
exports.RectangleLayer = RectangleLayer;
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.RepeatLayer = void 0;
|
|
4
4
|
const layer_1 = require("./layer");
|
|
5
5
|
const resolve_axis_1 = require("../utils/resolve-axis");
|
|
6
|
-
const commit_frame_1 = require("../utils/commit-frame");
|
|
7
6
|
class RepeatLayer extends layer_1.Layer {
|
|
8
7
|
constructor(options) {
|
|
9
8
|
super(options.when);
|
|
@@ -19,13 +18,13 @@ class RepeatLayer extends layer_1.Layer {
|
|
|
19
18
|
axis: this.options.x,
|
|
20
19
|
data: data,
|
|
21
20
|
index: index,
|
|
22
|
-
|
|
21
|
+
templateSize: templateConfig,
|
|
23
22
|
});
|
|
24
23
|
const dy = (0, resolve_axis_1.resolveAxis)({
|
|
25
24
|
axis: this.options.y,
|
|
26
25
|
data: data,
|
|
27
26
|
index: index,
|
|
28
|
-
|
|
27
|
+
templateSize: templateConfig,
|
|
29
28
|
});
|
|
30
29
|
const prevX = ctx.offsetX;
|
|
31
30
|
const prevY = ctx.offsetY;
|
|
@@ -38,7 +37,6 @@ class RepeatLayer extends layer_1.Layer {
|
|
|
38
37
|
index: index,
|
|
39
38
|
templateConfig: templateConfig,
|
|
40
39
|
});
|
|
41
|
-
ctx.image = await (0, commit_frame_1.commitFrame)(ctx.image);
|
|
42
40
|
ctx.offsetX = prevX;
|
|
43
41
|
ctx.offsetY = prevY;
|
|
44
42
|
}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import { Layer, RenderOptions, WhenFunction } from "./layer";
|
|
2
2
|
import { Axis } from "../utils/resolve-axis";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
name?: string;
|
|
7
|
-
filePath?: string;
|
|
8
|
-
};
|
|
9
|
-
export type TextAnchor = "top-left" | "top-center" | "top-right" | "middle-left" | "middle-center" | "middle-right" | "bottom-left" | "bottom-center" | "bottom-right";
|
|
3
|
+
import { ValueOfEnum } from "../utils/value-of-enum";
|
|
4
|
+
import { TextBaseline, TextAlign } from "../enums";
|
|
5
|
+
import { Font } from "../utils/font";
|
|
10
6
|
export type Stroke = {
|
|
11
7
|
fill: string;
|
|
12
8
|
width: number;
|
|
@@ -16,17 +12,13 @@ export type TextFunctionOptions<Data> = {
|
|
|
16
12
|
index: number;
|
|
17
13
|
};
|
|
18
14
|
export type StringFunction<Data> = (options: TextFunctionOptions<Data>) => string;
|
|
19
|
-
export type TextAlign = "left" | "center" | "right";
|
|
20
|
-
export type TextBaseline = "top" | "hanging" | "middle" | "alphabetic" | "ideographic" | "bottom";
|
|
21
15
|
export type TextLayerOptions<Data> = {
|
|
22
16
|
text: StringFunction<Data> | string;
|
|
23
|
-
font:
|
|
17
|
+
font: Font;
|
|
24
18
|
x: Axis<Data>;
|
|
25
19
|
y: Axis<Data>;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
align?: TextAlign;
|
|
29
|
-
baseline?: TextBaseline;
|
|
20
|
+
align?: ValueOfEnum<TextAlign>;
|
|
21
|
+
baseline?: ValueOfEnum<TextBaseline>;
|
|
30
22
|
stroke?: Stroke;
|
|
31
23
|
rotation?: number;
|
|
32
24
|
when?: WhenFunction<Data>;
|
|
@@ -34,5 +26,5 @@ export type TextLayerOptions<Data> = {
|
|
|
34
26
|
export declare class TextLayer<Data> extends Layer<Data> {
|
|
35
27
|
private readonly options;
|
|
36
28
|
constructor(options: TextLayerOptions<Data>);
|
|
37
|
-
render({ context:
|
|
29
|
+
render({ context: renderContext, data, index, templateConfig }: RenderOptions<Data>): Promise<void>;
|
|
38
30
|
}
|
|
@@ -1,43 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TextLayer = void 0;
|
|
4
|
-
const canvas_1 = require("canvas");
|
|
5
4
|
const layer_1 = require("./layer");
|
|
6
5
|
const resolve_axis_1 = require("../utils/resolve-axis");
|
|
7
|
-
const anchorOffsets = {
|
|
8
|
-
"top-left": (w, h) => ({ x: 0, y: 0 }),
|
|
9
|
-
"top-center": (w, h) => ({ x: -w / 2, y: 0 }),
|
|
10
|
-
"top-right": (w, h) => ({ x: -w, y: 0 }),
|
|
11
|
-
"middle-left": (w, h) => ({ x: 0, y: -h / 2 }),
|
|
12
|
-
"middle-center": (w, h) => ({ x: -w / 2, y: -h / 2 }),
|
|
13
|
-
"middle-right": (w, h) => ({ x: -w, y: -h / 2 }),
|
|
14
|
-
"bottom-left": (w, h) => ({ x: 0, y: -h }),
|
|
15
|
-
"bottom-center": (w, h) => ({ x: -w / 2, y: -h }),
|
|
16
|
-
"bottom-right": (w, h) => ({ x: -w, y: -h }),
|
|
17
|
-
};
|
|
18
6
|
class TextLayer extends layer_1.Layer {
|
|
19
7
|
constructor(options) {
|
|
20
8
|
super(options.when);
|
|
21
9
|
this.options = options;
|
|
22
10
|
}
|
|
23
|
-
async render({ context:
|
|
11
|
+
async render({ context: renderContext, data, index = 0, templateConfig }) {
|
|
24
12
|
var _a, _b;
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const height = imageMetadata.height;
|
|
28
|
-
const { text, font, x: initialX, y: initialY, backgroundColor = "transparent", anchor = "top-left", stroke, rotation = 0, align, baseline, } = this.options;
|
|
29
|
-
if (!font.name) {
|
|
30
|
-
throw new Error("Font name is required");
|
|
31
|
-
}
|
|
32
|
-
if (font.filePath) {
|
|
33
|
-
(0, canvas_1.registerFont)(font.filePath, { family: font.name });
|
|
34
|
-
}
|
|
35
|
-
const canvas = (0, canvas_1.createCanvas)(width, height);
|
|
36
|
-
const context = canvas.getContext("2d");
|
|
37
|
-
if (backgroundColor !== "transparent") {
|
|
38
|
-
context.fillStyle = backgroundColor;
|
|
39
|
-
context.fillRect(0, 0, width, height);
|
|
40
|
-
}
|
|
13
|
+
const { text, font, x: initialX, y: initialY, stroke, rotation = 0, align, baseline } = this.options;
|
|
14
|
+
const context = renderContext.ctx;
|
|
41
15
|
if (align) {
|
|
42
16
|
context.textAlign = align;
|
|
43
17
|
}
|
|
@@ -47,28 +21,22 @@ class TextLayer extends layer_1.Layer {
|
|
|
47
21
|
context.font = `${font.size}px ${(_a = font.name) !== null && _a !== void 0 ? _a : "Arial"}`;
|
|
48
22
|
context.fillStyle = (_b = font.color) !== null && _b !== void 0 ? _b : "#000";
|
|
49
23
|
const content = typeof text === "string" ? text : text({ data: data, index: index });
|
|
50
|
-
const metrics = context.measureText(content);
|
|
51
|
-
const textWidth = metrics.width;
|
|
52
|
-
const textHeight = font.size;
|
|
53
|
-
const offset = anchorOffsets[anchor](textWidth, textHeight);
|
|
54
24
|
const localX = (0, resolve_axis_1.resolveAxis)({
|
|
55
25
|
axis: initialX,
|
|
56
26
|
data: data,
|
|
57
27
|
index: index,
|
|
58
|
-
|
|
28
|
+
templateSize: templateConfig,
|
|
59
29
|
});
|
|
60
30
|
const localY = (0, resolve_axis_1.resolveAxis)({
|
|
61
31
|
axis: initialY,
|
|
62
32
|
data: data,
|
|
63
33
|
index: index,
|
|
64
|
-
|
|
34
|
+
templateSize: templateConfig,
|
|
65
35
|
});
|
|
66
|
-
const x =
|
|
67
|
-
const y =
|
|
68
|
-
const adjustedX = x + offset.x;
|
|
69
|
-
const adjustedY = y + offset.y;
|
|
36
|
+
const x = renderContext.offsetX + localX;
|
|
37
|
+
const y = renderContext.offsetY + localY;
|
|
70
38
|
context.save();
|
|
71
|
-
context.translate(
|
|
39
|
+
context.translate(x, y);
|
|
72
40
|
context.rotate((rotation * Math.PI) / 180);
|
|
73
41
|
if (stroke) {
|
|
74
42
|
context.strokeStyle = stroke.fill;
|
|
@@ -78,8 +46,6 @@ class TextLayer extends layer_1.Layer {
|
|
|
78
46
|
}
|
|
79
47
|
context.fillText(content, 0, 0);
|
|
80
48
|
context.restore();
|
|
81
|
-
const buffer = canvas.toBuffer();
|
|
82
|
-
ctx.image = ctx.image.composite([{ input: buffer, top: 0, left: 0 }]);
|
|
83
49
|
}
|
|
84
50
|
}
|
|
85
51
|
exports.TextLayer = TextLayer;
|
package/dist/render-context.d.ts
CHANGED
package/dist/template.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Canvas } from "@napi-rs/canvas";
|
|
2
2
|
import { Layer } from "./layers/layer";
|
|
3
|
-
export type
|
|
3
|
+
export type TemplateSize = {
|
|
4
4
|
width: number;
|
|
5
5
|
height: number;
|
|
6
|
-
|
|
6
|
+
};
|
|
7
|
+
export type TemplateConfig = TemplateSize & {
|
|
8
|
+
fill?: string;
|
|
7
9
|
};
|
|
8
10
|
export type InputTemplateOptions<Data> = {
|
|
9
11
|
imagePath?: undefined;
|
|
@@ -22,5 +24,5 @@ export type TemplateOptions<Data> = {
|
|
|
22
24
|
export declare class Template<Data> {
|
|
23
25
|
readonly options: TemplateOptions<Data>;
|
|
24
26
|
constructor(options: InputTemplateOptions<Data>);
|
|
25
|
-
render(data: Data): Promise<
|
|
27
|
+
render(data: Data): Promise<Canvas>;
|
|
26
28
|
}
|
package/dist/template.js
CHANGED
|
@@ -1,44 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.Template = void 0;
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const transparentFill = {
|
|
10
|
-
r: 0,
|
|
11
|
-
g: 0,
|
|
12
|
-
b: 0,
|
|
13
|
-
alpha: 0,
|
|
14
|
-
};
|
|
4
|
+
const canvas_1 = require("@napi-rs/canvas");
|
|
5
|
+
const error_1 = require("./error");
|
|
15
6
|
class Template {
|
|
16
7
|
constructor(options) {
|
|
17
8
|
this.options = options;
|
|
18
9
|
}
|
|
19
10
|
async render(data) {
|
|
20
|
-
let
|
|
11
|
+
let canvas;
|
|
21
12
|
if (this.options.config) {
|
|
22
13
|
const { width, height, fill } = this.options.config;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
},
|
|
30
|
-
});
|
|
14
|
+
canvas = (0, canvas_1.createCanvas)(width, height);
|
|
15
|
+
if (fill) {
|
|
16
|
+
const ctx = canvas.getContext("2d");
|
|
17
|
+
ctx.fillStyle = fill;
|
|
18
|
+
ctx.fillRect(0, 0, width, height);
|
|
19
|
+
}
|
|
31
20
|
}
|
|
32
|
-
else {
|
|
33
|
-
|
|
34
|
-
|
|
21
|
+
else if (this.options.imagePath) {
|
|
22
|
+
const backgroundImage = await (0, canvas_1.loadImage)(this.options.imagePath);
|
|
23
|
+
canvas = (0, canvas_1.createCanvas)(backgroundImage.width, backgroundImage.height);
|
|
35
24
|
this.options.config = {
|
|
36
|
-
width:
|
|
37
|
-
height:
|
|
25
|
+
width: backgroundImage.width,
|
|
26
|
+
height: backgroundImage.height,
|
|
38
27
|
};
|
|
39
28
|
}
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
else {
|
|
30
|
+
throw new error_1.XpictError("No config or imagePath provided");
|
|
31
|
+
}
|
|
32
|
+
const ctx = canvas.getContext("2d");
|
|
33
|
+
const renderContext = {
|
|
34
|
+
ctx: ctx,
|
|
42
35
|
offsetX: 0,
|
|
43
36
|
offsetY: 0,
|
|
44
37
|
};
|
|
@@ -46,13 +39,12 @@ class Template {
|
|
|
46
39
|
if (!layer.shouldRender(data))
|
|
47
40
|
continue;
|
|
48
41
|
await layer.render({
|
|
49
|
-
context:
|
|
42
|
+
context: renderContext,
|
|
50
43
|
data: data,
|
|
51
44
|
templateConfig: this.options.config,
|
|
52
45
|
});
|
|
53
|
-
ctx.image = await (0, commit_frame_1.commitFrame)(ctx.image);
|
|
54
46
|
}
|
|
55
|
-
return
|
|
47
|
+
return canvas;
|
|
56
48
|
}
|
|
57
49
|
}
|
|
58
50
|
exports.Template = Template;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type FontOptions = {
|
|
2
|
+
size: number;
|
|
3
|
+
color?: string;
|
|
4
|
+
name?: string;
|
|
5
|
+
filePath?: string;
|
|
6
|
+
};
|
|
7
|
+
export type FontConfigOptions = {
|
|
8
|
+
color?: string;
|
|
9
|
+
name: string;
|
|
10
|
+
filePath?: string;
|
|
11
|
+
};
|
|
12
|
+
export type PartialFontOptions = {
|
|
13
|
+
size: number;
|
|
14
|
+
color?: string;
|
|
15
|
+
};
|
|
16
|
+
export type Font = Omit<FontOptions, "filePath">;
|
|
17
|
+
export declare function font(options: FontConfigOptions): (partialOptions: PartialFontOptions) => Font;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.font = font;
|
|
7
|
+
const canvas_1 = require("@napi-rs/canvas");
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
function font(options) {
|
|
10
|
+
if (options.filePath) {
|
|
11
|
+
const buffer = node_fs_1.default.readFileSync(options.filePath);
|
|
12
|
+
canvas_1.GlobalFonts.register(buffer, options.name);
|
|
13
|
+
}
|
|
14
|
+
return (partialOptions) => {
|
|
15
|
+
const { filePath: _, ...rest } = {
|
|
16
|
+
...options,
|
|
17
|
+
...partialOptions,
|
|
18
|
+
};
|
|
19
|
+
return rest;
|
|
20
|
+
};
|
|
21
|
+
}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from "./wrap-text";
|
|
2
|
-
export * from "./font
|
|
2
|
+
export * from "./font";
|
package/dist/utils/index.js
CHANGED
|
@@ -15,4 +15,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./wrap-text"), exports);
|
|
18
|
-
__exportStar(require("./font
|
|
18
|
+
__exportStar(require("./font"), exports);
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TemplateSize } from "../template";
|
|
2
2
|
export type ComputeAxisOptions<Data> = {
|
|
3
3
|
data: Data;
|
|
4
4
|
index: number;
|
|
5
|
+
templateSize: TemplateSize;
|
|
5
6
|
};
|
|
6
7
|
export type ComputeAxis<Data> = (options: ComputeAxisOptions<Data>) => number;
|
|
7
8
|
export type Axis<Data> = ComputeAxis<Data> | number;
|
|
8
|
-
export type ResolveAxisOptions<Data> = {
|
|
9
|
+
export type ResolveAxisOptions<Data> = ComputeAxisOptions<Data> & {
|
|
9
10
|
axis: Axis<Data>;
|
|
10
|
-
data: Data;
|
|
11
|
-
index: number;
|
|
12
|
-
templateConfig: TemplateConfig;
|
|
13
11
|
};
|
|
14
12
|
export declare function resolveAxis<Data>({ axis, ...params }: ResolveAxisOptions<Data>): number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ValueOfEnum<Enum extends string | number> = Enum | `${Enum}`;
|