@nmmty/lazycanvas 1.0.0-dev.4 → 1.0.0-dev.7
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/dist/core/Scene.d.ts +4 -6
- package/dist/core/Scene.js +6 -22
- package/dist/jsx-runtime.js +1 -1
- package/dist/structures/LazyCanvas.d.ts +2 -0
- package/dist/structures/LazyCanvas.js +2 -0
- package/dist/structures/components/BaseLayer.d.ts +40 -28
- package/dist/structures/components/BaseLayer.js +45 -12
- package/dist/structures/components/BezierLayer.d.ts +10 -2
- package/dist/structures/components/BezierLayer.js +3 -3
- package/dist/structures/components/Div.d.ts +10 -7
- package/dist/structures/components/Div.js +18 -3
- package/dist/structures/components/ImageLayer.js +2 -2
- package/dist/structures/components/LineLayer.d.ts +10 -2
- package/dist/structures/components/LineLayer.js +3 -3
- package/dist/structures/components/MorphLayer.d.ts +1 -1
- package/dist/structures/components/MorphLayer.js +5 -5
- package/dist/structures/components/Path2DLayer.d.ts +4 -4
- package/dist/structures/components/Path2DLayer.js +10 -12
- package/dist/structures/components/PolygonLayer.d.ts +1 -1
- package/dist/structures/components/PolygonLayer.js +5 -5
- package/dist/structures/components/QuadraticLayer.d.ts +10 -2
- package/dist/structures/components/QuadraticLayer.js +3 -3
- package/dist/structures/components/TextLayer.d.ts +1 -1
- package/dist/structures/components/TextLayer.js +33 -12
- package/dist/structures/helpers/readers/JSONReader.js +13 -13
- package/dist/structures/managers/LayoutManager.d.ts +23 -0
- package/dist/structures/managers/LayoutManager.js +409 -0
- package/dist/structures/managers/RenderManager.d.ts +1 -0
- package/dist/structures/managers/RenderManager.js +35 -2
- package/dist/types/types.d.ts +25 -0
- package/dist/utils/utils.js +11 -7
- package/package.json +3 -2
- package/biome.json +0 -41
|
@@ -28,7 +28,7 @@ class Path2DLayer extends BaseLayer_1.BaseLayer {
|
|
|
28
28
|
throw new LazyUtil_1.LazyError("The color of the layer must be provided");
|
|
29
29
|
if (!(0, utils_1.isColor)(color))
|
|
30
30
|
throw new LazyUtil_1.LazyError("The color of the layer must be a valid color");
|
|
31
|
-
this.props.
|
|
31
|
+
this.props.color = color;
|
|
32
32
|
return this;
|
|
33
33
|
}
|
|
34
34
|
setPath(path) {
|
|
@@ -136,6 +136,12 @@ class Path2DLayer extends BaseLayer_1.BaseLayer {
|
|
|
136
136
|
async draw(ctx, canvas, manager, debug) {
|
|
137
137
|
ctx.beginPath();
|
|
138
138
|
ctx.save();
|
|
139
|
+
if (debug)
|
|
140
|
+
LazyUtil_1.LazyLog.log("none", `Drawing Path2D Layer: `, {
|
|
141
|
+
layerId: this.id,
|
|
142
|
+
type: this.type,
|
|
143
|
+
path: this.props.path2D.toSVGString(),
|
|
144
|
+
});
|
|
139
145
|
if (this.props.transform) {
|
|
140
146
|
(0, utils_1.transform)(ctx, this.props.transform, { width: 0, height: 0, x: 0, y: 0, type: this.type });
|
|
141
147
|
}
|
|
@@ -143,8 +149,8 @@ class Path2DLayer extends BaseLayer_1.BaseLayer {
|
|
|
143
149
|
if (this.props.clipPath) {
|
|
144
150
|
ctx.clip(this.props.path2D);
|
|
145
151
|
}
|
|
146
|
-
else if (this.props.
|
|
147
|
-
let fillStyle = await (0, utils_1.parseFillStyle)(ctx, this.props.
|
|
152
|
+
else if (this.props.color) {
|
|
153
|
+
let fillStyle = await (0, utils_1.parseFillStyle)(ctx, this.props.color, { debug, manager });
|
|
148
154
|
if (this.props.globalComposite) {
|
|
149
155
|
ctx.globalCompositeOperation = this.props.globalComposite;
|
|
150
156
|
}
|
|
@@ -182,16 +188,8 @@ class Path2DLayer extends BaseLayer_1.BaseLayer {
|
|
|
182
188
|
validateProps(data) {
|
|
183
189
|
return {
|
|
184
190
|
...super.validateProps(data),
|
|
185
|
-
|
|
191
|
+
color: data.color || "#000000",
|
|
186
192
|
path2D: data.path2D || new canvas_1.Path2D(),
|
|
187
|
-
stroke: {
|
|
188
|
-
width: data.stroke?.width || 1,
|
|
189
|
-
cap: data.stroke?.cap || "butt",
|
|
190
|
-
join: data.stroke?.join || "miter",
|
|
191
|
-
dashOffset: data.stroke?.dashOffset || 0,
|
|
192
|
-
dash: data.stroke?.dash || [],
|
|
193
|
-
miterLimit: data.stroke?.miterLimit || 10,
|
|
194
|
-
},
|
|
195
193
|
loadFromSVG: data.loadFromSVG || false,
|
|
196
194
|
clipPath: data.clipPath || false,
|
|
197
195
|
};
|
|
@@ -40,7 +40,7 @@ class PolygonLayer extends BaseLayer_1.BaseLayer {
|
|
|
40
40
|
throw new LazyUtil_1.LazyError("The color of the layer must be provided");
|
|
41
41
|
if (!(0, utils_1.isColor)(color))
|
|
42
42
|
throw new LazyUtil_1.LazyError("The color of the layer must be a valid color");
|
|
43
|
-
this.props.
|
|
43
|
+
this.props.color = color;
|
|
44
44
|
return this;
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
@@ -74,13 +74,13 @@ class PolygonLayer extends BaseLayer_1.BaseLayer {
|
|
|
74
74
|
async draw(ctx, canvas, manager, debug) {
|
|
75
75
|
const parcer = (0, utils_1.parser)(ctx, canvas, manager);
|
|
76
76
|
const { xs, ys, w } = parcer.parseBatch({
|
|
77
|
-
xs: { v: this.props.position
|
|
78
|
-
ys: { v: this.props.position
|
|
77
|
+
xs: { v: this.props.position?.x || 0 },
|
|
78
|
+
ys: { v: this.props.position?.y || 0, options: LazyUtil_1.defaultArg.vl(true) },
|
|
79
79
|
w: { v: this.props.size.width },
|
|
80
80
|
});
|
|
81
81
|
const h = parcer.parse(this.props.size.height, LazyUtil_1.defaultArg.wh(w), LazyUtil_1.defaultArg.vl(true));
|
|
82
82
|
let { x, y } = (0, utils_1.centring)(this.props.centring, this.type, w, h, xs, ys);
|
|
83
|
-
let fillStyle = await (0, utils_1.parseFillStyle)(ctx, this.props.
|
|
83
|
+
let fillStyle = await (0, utils_1.parseFillStyle)(ctx, this.props.color, {
|
|
84
84
|
debug,
|
|
85
85
|
layer: { width: w, height: h, x: xs, y: ys, align: this.props.centring },
|
|
86
86
|
manager,
|
|
@@ -198,7 +198,7 @@ class PolygonLayer extends BaseLayer_1.BaseLayer {
|
|
|
198
198
|
radius: data.size?.radius || 0,
|
|
199
199
|
count: data.size?.count || 3,
|
|
200
200
|
},
|
|
201
|
-
|
|
201
|
+
color: data.color || "#000000",
|
|
202
202
|
};
|
|
203
203
|
}
|
|
204
204
|
}
|
|
@@ -19,7 +19,15 @@ export interface IQuadraticLayer extends IBaseLayer {
|
|
|
19
19
|
* Interface representing the properties of a Quadratic layer.
|
|
20
20
|
*/
|
|
21
21
|
export interface IQuadraticLayerProps extends IBaseLayerProps {
|
|
22
|
-
position:
|
|
22
|
+
position: {
|
|
23
|
+
/**
|
|
24
|
+
* The x coordinate of the quadratic curve's starting point.
|
|
25
|
+
*/
|
|
26
|
+
x: ScaleType;
|
|
27
|
+
/**
|
|
28
|
+
* The y coordinate of the quadratic curve's starting point.
|
|
29
|
+
*/
|
|
30
|
+
y: ScaleType;
|
|
23
31
|
/**
|
|
24
32
|
* The end x coordinate of the quadratic curve.
|
|
25
33
|
*/
|
|
@@ -40,7 +48,7 @@ export interface IQuadraticLayerProps extends IBaseLayerProps {
|
|
|
40
48
|
/**
|
|
41
49
|
* The fill style (color or pattern) of the layer.
|
|
42
50
|
*/
|
|
43
|
-
|
|
51
|
+
color: ColorType;
|
|
44
52
|
/**
|
|
45
53
|
* The stroke properties of the quadratic curve.
|
|
46
54
|
*/
|
|
@@ -53,7 +53,7 @@ class QuadraticLayer extends BaseLayer_1.BaseLayer {
|
|
|
53
53
|
throw new LazyUtil_1.LazyError("The color of the layer must be provided");
|
|
54
54
|
if (!(0, utils_1.isColor)(color))
|
|
55
55
|
throw new LazyUtil_1.LazyError("The color of the layer must be a valid color");
|
|
56
|
-
this.props.
|
|
56
|
+
this.props.color = color;
|
|
57
57
|
return this;
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
@@ -123,7 +123,7 @@ class QuadraticLayer extends BaseLayer_1.BaseLayer {
|
|
|
123
123
|
{ x: cx, y: cy },
|
|
124
124
|
{ x: xe, y: ye },
|
|
125
125
|
]);
|
|
126
|
-
let fillStyle = await (0, utils_1.parseFillStyle)(ctx, this.props.
|
|
126
|
+
let fillStyle = await (0, utils_1.parseFillStyle)(ctx, this.props.color, {
|
|
127
127
|
debug,
|
|
128
128
|
layer: { width, height, x: min.x, y: min.y, align: "none" },
|
|
129
129
|
manager,
|
|
@@ -200,7 +200,7 @@ class QuadraticLayer extends BaseLayer_1.BaseLayer {
|
|
|
200
200
|
endX: data.position?.endX || 0,
|
|
201
201
|
endY: data.position?.endY || 0,
|
|
202
202
|
},
|
|
203
|
-
|
|
203
|
+
color: data.color || "#000000",
|
|
204
204
|
centring: data.centring || types_1.Centring.None,
|
|
205
205
|
controlPoints: data.controlPoints || [{ x: 0, y: 0 }],
|
|
206
206
|
stroke: {
|
|
@@ -88,7 +88,7 @@ class TextLayer extends BaseLayer_1.BaseLayer {
|
|
|
88
88
|
throw new LazyUtil_1.LazyError("The color of the layer must be provided");
|
|
89
89
|
if (!(0, utils_1.isColor)(color))
|
|
90
90
|
throw new LazyUtil_1.LazyError("The color of the layer must be a valid color");
|
|
91
|
-
this.props.
|
|
91
|
+
this.props.color = color;
|
|
92
92
|
if (sub && sub.length > 0) {
|
|
93
93
|
this.props.subStringColors = sub;
|
|
94
94
|
}
|
|
@@ -167,13 +167,32 @@ class TextLayer extends BaseLayer_1.BaseLayer {
|
|
|
167
167
|
* @returns {Object} The width and height of the text.
|
|
168
168
|
*/
|
|
169
169
|
measureText(ctx, canvas) {
|
|
170
|
+
ctx.font = `${this.props.font.weight} ${this.props.font.size}px ${this.props.font.family}`;
|
|
170
171
|
if (this.props?.multiline?.enabled) {
|
|
171
172
|
const w = (0, utils_1.parseToNormal)(this.props.size?.width || "vw", ctx, canvas);
|
|
172
|
-
|
|
173
|
-
|
|
173
|
+
// Calculate actual height based on text wrapping
|
|
174
|
+
const words = this.props.text.split(" ");
|
|
175
|
+
let line = "";
|
|
176
|
+
let linesCount = 1;
|
|
177
|
+
for (let word of words) {
|
|
178
|
+
let linePlus = line + word + " ";
|
|
179
|
+
if (ctx.measureText(linePlus).width > w) {
|
|
180
|
+
linesCount++;
|
|
181
|
+
line = word + " ";
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
line = linePlus;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const lineHeight = this.props.font.size * (this.props.multiline.spacing || 1.1);
|
|
188
|
+
const calculatedHeight = linesCount * lineHeight;
|
|
189
|
+
// If height is fixed in props, use it, otherwise use calculated height
|
|
190
|
+
const fixedHeight = this.props.size?.height
|
|
191
|
+
? (0, utils_1.parseToNormal)(this.props.size.height, ctx, canvas, { width: w, height: 0 }, { vertical: true })
|
|
192
|
+
: 0;
|
|
193
|
+
return { width: w, height: fixedHeight || calculatedHeight };
|
|
174
194
|
}
|
|
175
195
|
else {
|
|
176
|
-
ctx.font = `${this.props.font.weight} ${this.props.font.size}px ${this.props.font.family}`;
|
|
177
196
|
let data = ctx.measureText(this.props.text);
|
|
178
197
|
return { width: data.width, height: this.props.font.size };
|
|
179
198
|
}
|
|
@@ -188,8 +207,8 @@ class TextLayer extends BaseLayer_1.BaseLayer {
|
|
|
188
207
|
async draw(ctx, canvas, manager, debug) {
|
|
189
208
|
const parcer = (0, utils_1.parser)(ctx, canvas, manager);
|
|
190
209
|
const { x, y, w } = parcer.parseBatch({
|
|
191
|
-
x: { v: this.props.position
|
|
192
|
-
y: { v: this.props.position
|
|
210
|
+
x: { v: this.props.position?.x || 0 },
|
|
211
|
+
y: { v: this.props.position?.y || 0, options: LazyUtil_1.defaultArg.vl(true) },
|
|
193
212
|
w: { v: this.props.size?.width || "vw" },
|
|
194
213
|
});
|
|
195
214
|
const h = parcer.parse(this.props.size?.height || 0, LazyUtil_1.defaultArg.wh(w), LazyUtil_1.defaultArg.vl(true));
|
|
@@ -208,16 +227,18 @@ class TextLayer extends BaseLayer_1.BaseLayer {
|
|
|
208
227
|
DrawUtils_1.DrawUtils.drawShadow(ctx, this.props.shadow);
|
|
209
228
|
DrawUtils_1.DrawUtils.opacity(ctx, this.props.opacity);
|
|
210
229
|
DrawUtils_1.DrawUtils.filters(ctx, this.props.filter);
|
|
211
|
-
|
|
230
|
+
// When layout is managed by Yoga, always use top-left alignment
|
|
231
|
+
// since Yoga calculates position as top-left corner
|
|
232
|
+
const useLayoutAlignment = this.props._computedLayout === true;
|
|
233
|
+
ctx.textAlign = useLayoutAlignment ? "left" : this.props.align;
|
|
212
234
|
if (this.props.letterSpacing)
|
|
213
235
|
ctx.letterSpacing = `${this.props.letterSpacing}px`;
|
|
214
236
|
if (this.props.wordSpacing)
|
|
215
237
|
ctx.wordSpacing = `${this.props.wordSpacing}px`;
|
|
216
|
-
|
|
217
|
-
ctx.textBaseline = this.props.baseline;
|
|
238
|
+
ctx.textBaseline = useLayoutAlignment ? "top" : this.props.baseline || "alphabetic";
|
|
218
239
|
if (this.props.direction)
|
|
219
240
|
ctx.direction = this.props.direction;
|
|
220
|
-
let fillStyle = await (0, utils_1.parseFillStyle)(ctx, this.props.
|
|
241
|
+
let fillStyle = await (0, utils_1.parseFillStyle)(ctx, this.props.color, {
|
|
221
242
|
debug,
|
|
222
243
|
layer: { width: w, height: h, x, y, align: "center" },
|
|
223
244
|
manager,
|
|
@@ -391,7 +412,7 @@ class TextLayer extends BaseLayer_1.BaseLayer {
|
|
|
391
412
|
validateProps(data) {
|
|
392
413
|
return {
|
|
393
414
|
...super.validateProps(data),
|
|
394
|
-
|
|
415
|
+
color: data.color || "#000000",
|
|
395
416
|
text: data.text || "",
|
|
396
417
|
font: {
|
|
397
418
|
family: data.font?.family || "Arial",
|
|
@@ -403,7 +424,7 @@ class TextLayer extends BaseLayer_1.BaseLayer {
|
|
|
403
424
|
spacing: data.multiline?.spacing || 1.1,
|
|
404
425
|
},
|
|
405
426
|
size: {
|
|
406
|
-
width: data.size?.width ||
|
|
427
|
+
width: data.size?.width || 0,
|
|
407
428
|
height: data.size?.height || 0,
|
|
408
429
|
},
|
|
409
430
|
align: data.align || types_1.TextAlign.Left,
|
|
@@ -115,7 +115,7 @@ class JSONReader {
|
|
|
115
115
|
*/
|
|
116
116
|
static layerParse(layer, misc) {
|
|
117
117
|
if (layer instanceof components_1.Div) {
|
|
118
|
-
return new components_1.Div(misc).add(...layer.layers.map((l) => this.layerParse(l)));
|
|
118
|
+
return new components_1.Div({}, misc).add(...layer.layers.map((l) => this.layerParse(l)));
|
|
119
119
|
}
|
|
120
120
|
else {
|
|
121
121
|
switch (layer.type) {
|
|
@@ -136,7 +136,7 @@ class JSONReader {
|
|
|
136
136
|
case types_1.LayerType.Polygon:
|
|
137
137
|
return new components_1.PolygonLayer(layer.props, misc).setColor(this.fillParse(layer));
|
|
138
138
|
case types_1.LayerType.Group:
|
|
139
|
-
return new components_1.Div(misc).add(...layer.layers.map((l) => this.layerParse(l)));
|
|
139
|
+
return new components_1.Div({}, misc).add(...layer.layers.map((l) => this.layerParse(l)));
|
|
140
140
|
default:
|
|
141
141
|
return layer;
|
|
142
142
|
}
|
|
@@ -148,25 +148,25 @@ class JSONReader {
|
|
|
148
148
|
* @returns {string | Gradient | Pattern} The parsed fill style.
|
|
149
149
|
*/
|
|
150
150
|
static fillParse(layer) {
|
|
151
|
-
if ("
|
|
152
|
-
if ((0, Signal_1.isSignal)(layer.props.
|
|
151
|
+
if ("color" in layer.props) {
|
|
152
|
+
if ((0, Signal_1.isSignal)(layer.props.color)) {
|
|
153
153
|
throw new LazyUtil_1.LazyError("Signals are not supported in JSON fill styles");
|
|
154
154
|
}
|
|
155
|
-
if (typeof layer.props.
|
|
156
|
-
switch (layer.props.
|
|
155
|
+
if (typeof layer.props.color === "object") {
|
|
156
|
+
switch (layer.props.color?.fillType) {
|
|
157
157
|
case "gradient":
|
|
158
|
-
return new __1.Gradient({ props: layer.props.
|
|
158
|
+
return new __1.Gradient({ props: layer.props.color });
|
|
159
159
|
case "pattern":
|
|
160
160
|
return new __1.Pattern()
|
|
161
|
-
.setType(layer.props.
|
|
162
|
-
.setSrc(typeof layer.props.
|
|
163
|
-
? layer.props.
|
|
164
|
-
: this.read(layer.props.
|
|
161
|
+
.setType(layer.props.color.type)
|
|
162
|
+
.setSrc(typeof layer.props.color.src === "string"
|
|
163
|
+
? layer.props.color.src
|
|
164
|
+
: this.read(layer.props.color.src));
|
|
165
165
|
default:
|
|
166
|
-
return layer.props.
|
|
166
|
+
return layer.props.color;
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
|
-
return layer.props.
|
|
169
|
+
return layer.props.color || "#000000";
|
|
170
170
|
}
|
|
171
171
|
else {
|
|
172
172
|
return "#000000";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Div } from "../components";
|
|
2
|
+
import { AnyLayer } from "../../types";
|
|
3
|
+
import { SKRSContext2D, Canvas, SvgCanvas } from "@napi-rs/canvas";
|
|
4
|
+
export declare class LayoutManager {
|
|
5
|
+
private yoga;
|
|
6
|
+
private debug;
|
|
7
|
+
ready: Promise<void>;
|
|
8
|
+
constructor(opts?: {
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
});
|
|
11
|
+
private init;
|
|
12
|
+
calculateLayout(root: AnyLayer | Div, width: number, height: number, ctx?: SKRSContext2D, canvas?: Canvas | SvgCanvas): void;
|
|
13
|
+
private createNode;
|
|
14
|
+
private applyLayout;
|
|
15
|
+
private freeNode;
|
|
16
|
+
private getFlexDirection;
|
|
17
|
+
private getJustifyContent;
|
|
18
|
+
private getAlignItems;
|
|
19
|
+
private getPositionType;
|
|
20
|
+
private setDimension;
|
|
21
|
+
private setPadding;
|
|
22
|
+
private setMargin;
|
|
23
|
+
}
|