@codehz/draw-call 0.5.1 → 0.5.3

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.
@@ -0,0 +1,454 @@
1
+ import { Canvas } from "@napi-rs/canvas";
2
+
3
+ //#region src/types/base.d.ts
4
+ type Size = number | `${number}%` | "auto" | "fill";
5
+ interface ColorStop {
6
+ offset: number;
7
+ color: string;
8
+ }
9
+ interface LinearGradientDescriptor {
10
+ type: "linear-gradient";
11
+ angle: number;
12
+ stops: ColorStop[];
13
+ }
14
+ interface RadialGradientDescriptor {
15
+ type: "radial-gradient";
16
+ startX?: number;
17
+ startY?: number;
18
+ startRadius?: number;
19
+ endX?: number;
20
+ endY?: number;
21
+ endRadius?: number;
22
+ stops: ColorStop[];
23
+ }
24
+ type GradientDescriptor = LinearGradientDescriptor | RadialGradientDescriptor;
25
+ type Color = string | CanvasGradient | CanvasPattern | GradientDescriptor;
26
+ declare function linearGradient(angle: number, ...stops: (string | [number, string])[]): LinearGradientDescriptor;
27
+ declare function radialGradient(options: {
28
+ startX?: number;
29
+ startY?: number;
30
+ startRadius?: number;
31
+ endX?: number;
32
+ endY?: number;
33
+ endRadius?: number;
34
+ }, ...stops: (string | [number, string])[]): RadialGradientDescriptor;
35
+ interface Spacing {
36
+ top?: number;
37
+ right?: number;
38
+ bottom?: number;
39
+ left?: number;
40
+ }
41
+ interface Border {
42
+ width?: number;
43
+ color?: Color;
44
+ radius?: number | [number, number, number, number];
45
+ }
46
+ interface Shadow {
47
+ offsetX?: number;
48
+ offsetY?: number;
49
+ blur?: number;
50
+ color?: Color;
51
+ }
52
+ interface FontProps {
53
+ family?: string;
54
+ size?: number;
55
+ weight?: number | "normal" | "bold";
56
+ style?: "normal" | "italic";
57
+ }
58
+ interface StrokeProps {
59
+ color: Color;
60
+ width: number;
61
+ dash?: number[];
62
+ cap?: "butt" | "round" | "square";
63
+ join?: "miter" | "round" | "bevel";
64
+ }
65
+ interface Bounds {
66
+ x: number;
67
+ y: number;
68
+ width: number;
69
+ height: number;
70
+ }
71
+ //#endregion
72
+ //#region src/layout/utils/measure.d.ts
73
+ interface MeasureTextResult {
74
+ width: number;
75
+ height: number;
76
+ offset: number;
77
+ ascent: number;
78
+ descent: number;
79
+ }
80
+ interface MeasureContext {
81
+ measureText(text: string, font: FontProps): MeasureTextResult;
82
+ }
83
+ declare function createCanvasMeasureContext(ctx: CanvasRenderingContext2D): MeasureContext;
84
+ //#endregion
85
+ //#region src/types/layout.d.ts
86
+ type FlexDirection = "row" | "column" | "row-reverse" | "column-reverse";
87
+ type JustifyContent = "start" | "end" | "center" | "space-between" | "space-around" | "space-evenly";
88
+ type AlignItems = "start" | "end" | "center" | "stretch" | "baseline";
89
+ type AlignSelf = "auto" | AlignItems;
90
+ interface LayoutProps {
91
+ width?: Size;
92
+ height?: Size;
93
+ minWidth?: number;
94
+ maxWidth?: number;
95
+ minHeight?: number;
96
+ maxHeight?: number;
97
+ margin?: number | Spacing;
98
+ padding?: number | Spacing;
99
+ flex?: number;
100
+ alignSelf?: AlignSelf;
101
+ }
102
+ interface ContainerLayoutProps extends LayoutProps {
103
+ direction?: FlexDirection;
104
+ justify?: JustifyContent;
105
+ align?: AlignItems;
106
+ gap?: number;
107
+ wrap?: boolean;
108
+ }
109
+ interface ComputedLayout {
110
+ x: number;
111
+ y: number;
112
+ width: number;
113
+ height: number;
114
+ contentX: number;
115
+ contentY: number;
116
+ contentWidth: number;
117
+ contentHeight: number;
118
+ }
119
+ interface RichTextSpanSegment {
120
+ text: string;
121
+ font: FontProps;
122
+ color: Color;
123
+ background: Color;
124
+ underline: boolean;
125
+ strikethrough: boolean;
126
+ width: number;
127
+ height: number;
128
+ ascent: number;
129
+ descent: number;
130
+ offset: number;
131
+ }
132
+ interface RichTextLine {
133
+ segments: RichTextSpanSegment[];
134
+ width: number;
135
+ height: number;
136
+ baseline: number;
137
+ }
138
+ interface LayoutNode {
139
+ element: Element;
140
+ layout: ComputedLayout;
141
+ children: LayoutNode[];
142
+ lines?: string[];
143
+ lineOffsets?: number[];
144
+ richLines?: RichTextLine[];
145
+ }
146
+ interface LayoutConstraints {
147
+ minWidth: number;
148
+ maxWidth: number;
149
+ minHeight: number;
150
+ maxHeight: number;
151
+ }
152
+ //#endregion
153
+ //#region src/types/components.d.ts
154
+ type ElementType = "box" | "text" | "richtext" | "image" | "svg" | "stack" | "transform" | "customdraw";
155
+ interface ProxiedCanvasContextOptions {
156
+ inner?: () => void;
157
+ width: number;
158
+ height: number;
159
+ }
160
+ interface ElementBase {
161
+ type: ElementType;
162
+ }
163
+ interface BoxProps extends ContainerLayoutProps {
164
+ background?: Color;
165
+ border?: Border;
166
+ shadow?: Shadow;
167
+ opacity?: number;
168
+ clip?: boolean;
169
+ children?: Element[];
170
+ }
171
+ interface BoxElement extends ElementBase, BoxProps {
172
+ type: "box";
173
+ }
174
+ interface TextProps extends LayoutProps {
175
+ content: string;
176
+ font?: FontProps;
177
+ color?: Color;
178
+ align?: "left" | "center" | "right";
179
+ verticalAlign?: "top" | "middle" | "bottom";
180
+ lineHeight?: number;
181
+ maxLines?: number;
182
+ ellipsis?: boolean;
183
+ wrap?: boolean;
184
+ shadow?: Shadow;
185
+ stroke?: StrokeProps;
186
+ }
187
+ interface TextElement extends ElementBase, TextProps {
188
+ type: "text";
189
+ }
190
+ interface RichTextStyleProps {
191
+ font?: FontProps;
192
+ color?: Color;
193
+ background?: Color;
194
+ underline?: boolean;
195
+ strikethrough?: boolean;
196
+ }
197
+ interface RichTextSpan extends RichTextStyleProps {
198
+ text: string;
199
+ }
200
+ interface RichTextProps extends LayoutProps, RichTextStyleProps {
201
+ spans: RichTextSpan[];
202
+ lineHeight?: number;
203
+ align?: "left" | "center" | "right";
204
+ verticalAlign?: "top" | "middle" | "bottom";
205
+ maxLines?: number;
206
+ ellipsis?: boolean;
207
+ }
208
+ interface RichTextElement extends ElementBase, RichTextProps {
209
+ type: "richtext";
210
+ }
211
+ interface ImageProps extends LayoutProps {
212
+ src: ImageBitmap | CanvasImageSource;
213
+ fit?: "contain" | "cover" | "fill" | "none" | "scale-down";
214
+ position?: {
215
+ x?: "left" | "center" | "right" | number;
216
+ y?: "top" | "center" | "bottom" | number;
217
+ };
218
+ border?: Border;
219
+ shadow?: Shadow;
220
+ opacity?: number;
221
+ }
222
+ interface ImageElement extends ElementBase, ImageProps {
223
+ type: "image";
224
+ }
225
+ interface SvgStyleProps {
226
+ fill?: Color | "none";
227
+ stroke?: StrokeProps;
228
+ opacity?: number;
229
+ }
230
+ interface SvgTransformProps {
231
+ transform?: {
232
+ translate?: [number, number]; /** 旋转角度(弧度)或 [angle(弧度), cx, cy](绕点旋转) */
233
+ rotate?: number | [number, number, number];
234
+ scale?: number | [number, number]; /** 水平偏移角度(弧度) */
235
+ skewX?: number; /** 垂直偏移角度(弧度) */
236
+ skewY?: number;
237
+ matrix?: [number, number, number, number, number, number];
238
+ };
239
+ }
240
+ interface SvgRectChild extends SvgStyleProps, SvgTransformProps {
241
+ type: "rect";
242
+ x?: number;
243
+ y?: number;
244
+ width: number;
245
+ height: number;
246
+ rx?: number;
247
+ ry?: number;
248
+ }
249
+ interface SvgCircleChild extends SvgStyleProps, SvgTransformProps {
250
+ type: "circle";
251
+ cx: number;
252
+ cy: number;
253
+ r: number;
254
+ }
255
+ interface SvgEllipseChild extends SvgStyleProps, SvgTransformProps {
256
+ type: "ellipse";
257
+ cx: number;
258
+ cy: number;
259
+ rx: number;
260
+ ry: number;
261
+ }
262
+ interface SvgLineChild extends SvgStyleProps, SvgTransformProps {
263
+ type: "line";
264
+ x1: number;
265
+ y1: number;
266
+ x2: number;
267
+ y2: number;
268
+ }
269
+ interface SvgPolylineChild extends SvgStyleProps, SvgTransformProps {
270
+ type: "polyline";
271
+ points: [number, number][];
272
+ }
273
+ interface SvgPolygonChild extends SvgStyleProps, SvgTransformProps {
274
+ type: "polygon";
275
+ points: [number, number][];
276
+ }
277
+ interface SvgPathChild extends SvgStyleProps, SvgTransformProps {
278
+ type: "path";
279
+ d: string;
280
+ }
281
+ interface SvgTextChild extends SvgStyleProps, SvgTransformProps {
282
+ type: "text";
283
+ x?: number;
284
+ y?: number;
285
+ content: string;
286
+ font?: FontProps;
287
+ textAnchor?: "start" | "middle" | "end";
288
+ dominantBaseline?: "auto" | "middle" | "hanging";
289
+ }
290
+ interface SvgGroupChild extends SvgStyleProps, SvgTransformProps {
291
+ type: "g";
292
+ children: SvgChild[];
293
+ }
294
+ type SvgChild = SvgRectChild | SvgCircleChild | SvgEllipseChild | SvgLineChild | SvgPolylineChild | SvgPolygonChild | SvgPathChild | SvgTextChild | SvgGroupChild;
295
+ type SvgAlign = "none" | "xMinYMin" | "xMidYMin" | "xMaxYMin" | "xMinYMid" | "xMidYMid" | "xMaxYMid" | "xMinYMax" | "xMidYMax" | "xMaxYMax";
296
+ interface SvgProps extends LayoutProps {
297
+ viewBox?: {
298
+ x?: number;
299
+ y?: number;
300
+ width: number;
301
+ height: number;
302
+ };
303
+ preserveAspectRatio?: {
304
+ align?: SvgAlign;
305
+ meetOrSlice?: "meet" | "slice";
306
+ };
307
+ children: SvgChild[];
308
+ background?: Color;
309
+ shadow?: Shadow;
310
+ }
311
+ interface SvgElement extends ElementBase, SvgProps {
312
+ type: "svg";
313
+ }
314
+ type StackAlign = "start" | "end" | "center";
315
+ interface StackProps extends LayoutProps {
316
+ children: Element[];
317
+ background?: Color;
318
+ border?: Border;
319
+ shadow?: Shadow;
320
+ opacity?: number;
321
+ clip?: boolean;
322
+ /** 水平对齐方式(默认 start) */
323
+ align?: StackAlign;
324
+ /** 垂直对齐方式(默认 start) */
325
+ justify?: StackAlign;
326
+ }
327
+ interface StackElement extends ElementBase, StackProps {
328
+ type: "stack";
329
+ }
330
+ interface TransformSimpleObject {
331
+ translate?: [number, number];
332
+ /** 旋转角度(弧度)或 [angle(弧度), cx, cy](绕点旋转) */
333
+ rotate?: number | [number, number, number];
334
+ scale?: number | [number, number];
335
+ /** 水平偏移角度(弧度) */
336
+ skewX?: number;
337
+ /** 垂直偏移角度(弧度) */
338
+ skewY?: number;
339
+ }
340
+ interface DOMMatrix2DInit {
341
+ a?: number;
342
+ b?: number;
343
+ c?: number;
344
+ d?: number;
345
+ e?: number;
346
+ f?: number;
347
+ }
348
+ type TransformValue = TransformSimpleObject | DOMMatrix2DInit | [number, number, number, number, number, number];
349
+ interface TransformProps {
350
+ children: Element;
351
+ /** 变换值(rotate/skew 使用弧度) */
352
+ transform?: TransformValue;
353
+ /** 变换原点,默认为 [0, 0](左上角) */
354
+ transformOrigin?: [number | string, number | string];
355
+ }
356
+ interface TransformElement extends ElementBase, TransformProps {
357
+ type: "transform";
358
+ }
359
+ interface CustomDrawProps extends LayoutProps {
360
+ draw: (ctx: CanvasRenderingContext2D, options: ProxiedCanvasContextOptions) => void;
361
+ children?: Element;
362
+ }
363
+ interface CustomDrawElement extends ElementBase, CustomDrawProps {
364
+ type: "customdraw";
365
+ }
366
+ type LayoutElement = BoxElement | TextElement | RichTextElement | ImageElement | SvgElement | StackElement | CustomDrawElement;
367
+ type Element = LayoutElement | TransformElement;
368
+ //#endregion
369
+ //#region src/canvas.d.ts
370
+ interface CanvasOptions<T extends HTMLCanvasElement | OffscreenCanvas | Canvas = HTMLCanvasElement | OffscreenCanvas | Canvas> {
371
+ width: number;
372
+ height: number;
373
+ pixelRatio?: number;
374
+ /** 根据内容调整画布大小 */
375
+ fitContent?: boolean;
376
+ updateStyles?: boolean;
377
+ imageSmoothingEnabled?: boolean;
378
+ imageSmoothingQuality?: "low" | "medium" | "high";
379
+ canvas?: T;
380
+ }
381
+ interface DrawCallCanvas<T extends HTMLCanvasElement | OffscreenCanvas | Canvas = HTMLCanvasElement> {
382
+ readonly width: number;
383
+ readonly height: number;
384
+ readonly pixelRatio: number;
385
+ readonly canvas: T;
386
+ render(element: LayoutElement): LayoutNode;
387
+ clear(): void;
388
+ getContext(): CanvasRenderingContext2D;
389
+ toDataURL(type?: string, quality?: number): string;
390
+ toBuffer(type?: "image/png" | "image/jpeg"): Buffer;
391
+ }
392
+ /**
393
+ * 创建适用于浏览器环境的 Canvas
394
+ *
395
+ * 在浏览器环境中使用,支持传入已有的 canvas 实例
396
+ */
397
+ declare function createCanvas<T extends HTMLCanvasElement | OffscreenCanvas | Canvas = HTMLCanvasElement>(options: CanvasOptions<T>): DrawCallCanvas<T>;
398
+ //#endregion
399
+ //#region src/components/Box.d.ts
400
+ declare function Box(props: BoxProps): BoxElement;
401
+ //#endregion
402
+ //#region src/components/CustomDraw.d.ts
403
+ declare function CustomDraw(props: CustomDrawProps): CustomDrawElement;
404
+ //#endregion
405
+ //#region src/components/Image.d.ts
406
+ declare function Image(props: ImageProps): ImageElement;
407
+ //#endregion
408
+ //#region src/components/RichText.d.ts
409
+ declare function RichText(props: RichTextProps): RichTextElement;
410
+ //#endregion
411
+ //#region src/components/Stack.d.ts
412
+ declare function Stack(props: StackProps): StackElement;
413
+ //#endregion
414
+ //#region src/components/Svg.d.ts
415
+ declare function Svg(props: SvgProps): SvgElement;
416
+ declare const svg: {
417
+ rect: (props: Omit<SvgRectChild, "type">) => SvgRectChild;
418
+ circle: (props: Omit<SvgCircleChild, "type">) => SvgCircleChild;
419
+ ellipse: (props: Omit<SvgEllipseChild, "type">) => SvgEllipseChild;
420
+ line: (props: Omit<SvgLineChild, "type">) => SvgLineChild;
421
+ polyline: (props: Omit<SvgPolylineChild, "type">) => SvgPolylineChild;
422
+ polygon: (props: Omit<SvgPolygonChild, "type">) => SvgPolygonChild;
423
+ path: (props: Omit<SvgPathChild, "type">) => SvgPathChild;
424
+ text: (props: Omit<SvgTextChild, "type">) => SvgTextChild;
425
+ g: (props: Omit<SvgGroupChild, "type">) => SvgGroupChild;
426
+ };
427
+ //#endregion
428
+ //#region src/components/Text.d.ts
429
+ declare function Text(props: TextProps): TextElement;
430
+ //#endregion
431
+ //#region src/components/Transform.d.ts
432
+ declare function Transform(props: TransformProps): TransformElement;
433
+ //#endregion
434
+ //#region src/layout/engine.d.ts
435
+ /**
436
+ * 布局计算主函数
437
+ * 内部使用 Element 类型以支持 Transform,外部通过 LayoutElement 约束类型
438
+ */
439
+ declare function computeLayout(element: LayoutElement, ctx: MeasureContext, constraints: LayoutConstraints, x?: number, y?: number): LayoutNode;
440
+ //#endregion
441
+ //#region src/layout/utils/print.d.ts
442
+ /**
443
+ * 打印 LayoutNode 树结构到控制台
444
+ */
445
+ declare function printLayout(node: LayoutNode): void;
446
+ /**
447
+ * 将 LayoutNode 转换为美观的字符串
448
+ * @param node LayoutNode 根节点
449
+ * @param indent 缩进字符串,默认为两个空格
450
+ * @returns 格式化的字符串
451
+ */
452
+ declare function layoutToString(node: LayoutNode, _indent?: string): string;
453
+ //#endregion
454
+ export { type AlignItems, type AlignSelf, type Border, type Bounds, Box, type BoxElement, type BoxProps, type CanvasOptions, type Color, type ColorStop, type ContainerLayoutProps, CustomDraw, type CustomDrawElement, type CustomDrawProps, type DrawCallCanvas, type Element, type FlexDirection, type FontProps, type GradientDescriptor, Image, type JustifyContent, type LayoutElement, type LayoutNode, type LayoutProps, type LinearGradientDescriptor, type MeasureContext, type ProxiedCanvasContextOptions, type RadialGradientDescriptor, RichText, type RichTextElement, type RichTextProps, type RichTextSpan, type Shadow, type Size, type Spacing, Stack, type StackAlign, type StackElement, type StackProps, type StrokeProps, Svg, type SvgAlign, type SvgChild, type SvgCircleChild, type SvgElement, type SvgEllipseChild, type SvgGroupChild, type SvgLineChild, type SvgPathChild, type SvgPolygonChild, type SvgPolylineChild, type SvgProps, type SvgRectChild, type SvgStyleProps, type SvgTextChild, type SvgTransformProps, Text, type TextElement, type TextProps, Transform, type TransformElement, type TransformProps, computeLayout, createCanvas, createCanvasMeasureContext, layoutToString, linearGradient, printLayout, radialGradient, svg };