@codehz/draw-call 0.5.0 → 0.5.2
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/browser/index.cjs +176 -103
- package/browser/index.d.cts +9 -4
- package/browser/index.d.ts +9 -4
- package/browser/index.js +175 -103
- package/node/index.cjs +176 -103
- package/node/index.d.cts +9 -4
- package/node/index.d.mts +9 -4
- package/node/index.mjs +175 -103
- package/package.json +2 -2
package/node/index.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
1
2
|
let _napi_rs_canvas = require("@napi-rs/canvas");
|
|
2
3
|
|
|
3
4
|
//#region src/compat/index.ts
|
|
@@ -78,6 +79,19 @@ function normalizeBorderRadius(value) {
|
|
|
78
79
|
|
|
79
80
|
//#endregion
|
|
80
81
|
//#region src/layout/components/box.ts
|
|
82
|
+
/**
|
|
83
|
+
* 安全获取元素的 margin
|
|
84
|
+
* Transform 元素没有 margin,返回默认 spacing
|
|
85
|
+
*/
|
|
86
|
+
function getElementMargin$2(element) {
|
|
87
|
+
if (element.type === "transform") return {
|
|
88
|
+
top: 0,
|
|
89
|
+
right: 0,
|
|
90
|
+
bottom: 0,
|
|
91
|
+
left: 0
|
|
92
|
+
};
|
|
93
|
+
return normalizeSpacing(element.margin);
|
|
94
|
+
}
|
|
81
95
|
function calcEffectiveSize(element, padding, availableWidth) {
|
|
82
96
|
return {
|
|
83
97
|
width: typeof element.width === "number" ? element.width - padding.left - padding.right : availableWidth > 0 ? availableWidth : 0,
|
|
@@ -87,7 +101,7 @@ function calcEffectiveSize(element, padding, availableWidth) {
|
|
|
87
101
|
function collectChildSizes(children, ctx, availableWidth, padding, measureChild) {
|
|
88
102
|
const childSizes = [];
|
|
89
103
|
for (const child of children) {
|
|
90
|
-
const childMargin =
|
|
104
|
+
const childMargin = getElementMargin$2(child);
|
|
91
105
|
const childSize = measureChild(child, ctx, availableWidth - padding.left - padding.right - childMargin.left - childMargin.right);
|
|
92
106
|
childSizes.push({
|
|
93
107
|
width: childSize.width,
|
|
@@ -156,7 +170,7 @@ function measureBoxSize(element, ctx, availableWidth, measureChild) {
|
|
|
156
170
|
contentHeight = wrapped.height;
|
|
157
171
|
} else for (let i = 0; i < children.length; i++) {
|
|
158
172
|
const child = children[i];
|
|
159
|
-
const childMargin =
|
|
173
|
+
const childMargin = getElementMargin$2(child);
|
|
160
174
|
const childSize = measureChild(child, ctx, availableWidth - padding.left - padding.right - childMargin.left - childMargin.right);
|
|
161
175
|
if (isRow) {
|
|
162
176
|
contentWidth += childSize.width + childMargin.left + childMargin.right;
|
|
@@ -390,6 +404,19 @@ function wrapRichText(ctx, spans, maxWidth, lineHeightScale = 1.2, elementStyle
|
|
|
390
404
|
//#endregion
|
|
391
405
|
//#region src/layout/components/stack.ts
|
|
392
406
|
/**
|
|
407
|
+
* 安全获取元素的 margin
|
|
408
|
+
* Transform 元素没有 margin,返回默认 spacing
|
|
409
|
+
*/
|
|
410
|
+
function getElementMargin$1(element) {
|
|
411
|
+
if (element.type === "transform") return {
|
|
412
|
+
top: 0,
|
|
413
|
+
right: 0,
|
|
414
|
+
bottom: 0,
|
|
415
|
+
left: 0
|
|
416
|
+
};
|
|
417
|
+
return normalizeSpacing(element.margin);
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
393
420
|
* 测量 Stack 元素的固有尺寸
|
|
394
421
|
*/
|
|
395
422
|
function measureStackSize(element, ctx, availableWidth, measureChild) {
|
|
@@ -398,7 +425,7 @@ function measureStackSize(element, ctx, availableWidth, measureChild) {
|
|
|
398
425
|
let contentHeight = 0;
|
|
399
426
|
const children = element.children ?? [];
|
|
400
427
|
for (const child of children) {
|
|
401
|
-
const childMargin =
|
|
428
|
+
const childMargin = getElementMargin$1(child);
|
|
402
429
|
const childSize = measureChild(child, ctx, availableWidth - padding.left - padding.right - childMargin.left - childMargin.right);
|
|
403
430
|
contentWidth = Math.max(contentWidth, childSize.width + childMargin.left + childMargin.right);
|
|
404
431
|
contentHeight = Math.max(contentHeight, childSize.height + childMargin.top + childMargin.bottom);
|
|
@@ -637,18 +664,79 @@ function sizeNeedsParent(size) {
|
|
|
637
664
|
|
|
638
665
|
//#endregion
|
|
639
666
|
//#region src/layout/engine.ts
|
|
667
|
+
/**
|
|
668
|
+
* 类型守卫:检查 Element 是否为 LayoutElement(非 Transform)
|
|
669
|
+
* 由于 Transform 元素在 computeLayoutImpl 开始时被处理,
|
|
670
|
+
* 此时只应处理 LayoutElement
|
|
671
|
+
*/
|
|
672
|
+
function assertLayoutElement(element) {
|
|
673
|
+
if (element.type === "transform") throw new Error("Transform elements should be handled at entry point");
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* 安全获取元素的 margin
|
|
677
|
+
* Transform 元素没有 margin,返回默认 spacing
|
|
678
|
+
*/
|
|
679
|
+
function getElementMargin(element) {
|
|
680
|
+
if (element.type === "transform") return {
|
|
681
|
+
top: 0,
|
|
682
|
+
right: 0,
|
|
683
|
+
bottom: 0,
|
|
684
|
+
left: 0
|
|
685
|
+
};
|
|
686
|
+
return normalizeSpacing(element.margin);
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* 安全获取元素的布局属性(width, height, flex等)
|
|
690
|
+
* Transform 元素这些属性为 undefined
|
|
691
|
+
*/
|
|
692
|
+
function getElementLayoutProps(element) {
|
|
693
|
+
if (element.type === "transform") return {
|
|
694
|
+
width: void 0,
|
|
695
|
+
height: void 0,
|
|
696
|
+
flex: void 0,
|
|
697
|
+
minWidth: void 0,
|
|
698
|
+
maxWidth: void 0,
|
|
699
|
+
minHeight: void 0,
|
|
700
|
+
maxHeight: void 0,
|
|
701
|
+
alignSelf: void 0
|
|
702
|
+
};
|
|
703
|
+
const le = element;
|
|
704
|
+
return {
|
|
705
|
+
width: le.width,
|
|
706
|
+
height: le.height,
|
|
707
|
+
flex: le.flex,
|
|
708
|
+
minWidth: le.minWidth,
|
|
709
|
+
maxWidth: le.maxWidth,
|
|
710
|
+
minHeight: le.minHeight,
|
|
711
|
+
maxHeight: le.maxHeight,
|
|
712
|
+
alignSelf: le.alignSelf
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* 布局计算主函数
|
|
717
|
+
* 内部使用 Element 类型以支持 Transform,外部通过 LayoutElement 约束类型
|
|
718
|
+
*/
|
|
640
719
|
function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
641
|
-
|
|
642
|
-
|
|
720
|
+
return computeLayoutImpl(element, ctx, constraints, x, y);
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* 内部实现函数,处理所有元素类型包括 Transform
|
|
724
|
+
*/
|
|
725
|
+
function computeLayoutImpl(element, ctx, constraints, x = 0, y = 0) {
|
|
726
|
+
if (element.type === "transform") return computeLayoutImpl(element.children, ctx, constraints, x, y);
|
|
727
|
+
assertLayoutElement(element);
|
|
728
|
+
const layoutElement = element;
|
|
729
|
+
const margin = normalizeSpacing(layoutElement.margin);
|
|
730
|
+
const padding = normalizeSpacing("padding" in layoutElement ? layoutElement.padding : void 0);
|
|
643
731
|
const availableWidth = constraints.maxWidth - margin.left - margin.right;
|
|
644
732
|
const availableHeight = constraints.maxHeight - margin.top - margin.bottom;
|
|
645
|
-
const intrinsic = measureIntrinsicSize(
|
|
646
|
-
let width = constraints.minWidth === constraints.maxWidth && constraints.minWidth > 0 ? constraints.maxWidth - margin.left - margin.right : resolveSize(
|
|
647
|
-
let height = constraints.minHeight === constraints.maxHeight && constraints.minHeight > 0 ? constraints.maxHeight - margin.top - margin.bottom : resolveSize(
|
|
648
|
-
if (
|
|
649
|
-
if (
|
|
650
|
-
if (
|
|
651
|
-
if (
|
|
733
|
+
const intrinsic = measureIntrinsicSize(layoutElement, ctx, availableWidth);
|
|
734
|
+
let width = constraints.minWidth === constraints.maxWidth && constraints.minWidth > 0 ? constraints.maxWidth - margin.left - margin.right : resolveSize(layoutElement.width, availableWidth, intrinsic.width);
|
|
735
|
+
let height = constraints.minHeight === constraints.maxHeight && constraints.minHeight > 0 ? constraints.maxHeight - margin.top - margin.bottom : resolveSize(layoutElement.height, availableHeight, intrinsic.height);
|
|
736
|
+
if (layoutElement.minWidth !== void 0) width = Math.max(width, layoutElement.minWidth);
|
|
737
|
+
if (layoutElement.maxWidth !== void 0) width = Math.min(width, layoutElement.maxWidth);
|
|
738
|
+
if (layoutElement.minHeight !== void 0) height = Math.max(height, layoutElement.minHeight);
|
|
739
|
+
if (layoutElement.maxHeight !== void 0) height = Math.min(height, layoutElement.maxHeight);
|
|
652
740
|
const actualX = x + margin.left;
|
|
653
741
|
const actualY = y + margin.top;
|
|
654
742
|
const contentX = actualX + padding.left;
|
|
@@ -656,7 +744,7 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
656
744
|
const contentWidth = width - padding.left - padding.right;
|
|
657
745
|
const contentHeight = height - padding.top - padding.bottom;
|
|
658
746
|
const node = {
|
|
659
|
-
element,
|
|
747
|
+
element: layoutElement,
|
|
660
748
|
layout: {
|
|
661
749
|
x: actualX,
|
|
662
750
|
y: actualY,
|
|
@@ -669,14 +757,14 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
669
757
|
},
|
|
670
758
|
children: []
|
|
671
759
|
};
|
|
672
|
-
if (
|
|
673
|
-
const font =
|
|
674
|
-
if (
|
|
675
|
-
let { lines, offsets } = wrapText(ctx,
|
|
676
|
-
if (
|
|
677
|
-
lines = lines.slice(0,
|
|
678
|
-
offsets = offsets.slice(0,
|
|
679
|
-
if (
|
|
760
|
+
if (layoutElement.type === "text") {
|
|
761
|
+
const font = layoutElement.font ?? {};
|
|
762
|
+
if (layoutElement.wrap && contentWidth > 0) {
|
|
763
|
+
let { lines, offsets } = wrapText(ctx, layoutElement.content, contentWidth, font);
|
|
764
|
+
if (layoutElement.maxLines && lines.length > layoutElement.maxLines) {
|
|
765
|
+
lines = lines.slice(0, layoutElement.maxLines);
|
|
766
|
+
offsets = offsets.slice(0, layoutElement.maxLines);
|
|
767
|
+
if (layoutElement.ellipsis && lines.length > 0) {
|
|
680
768
|
const lastIdx = lines.length - 1;
|
|
681
769
|
const truncated = truncateText(ctx, lines[lastIdx], contentWidth, font);
|
|
682
770
|
lines[lastIdx] = truncated.text;
|
|
@@ -686,17 +774,17 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
686
774
|
node.lines = lines;
|
|
687
775
|
node.lineOffsets = offsets;
|
|
688
776
|
} else {
|
|
689
|
-
const { text, offset } = truncateText(ctx,
|
|
777
|
+
const { text, offset } = truncateText(ctx, layoutElement.content, contentWidth > 0 && layoutElement.ellipsis ? contentWidth : Infinity, font);
|
|
690
778
|
node.lines = [text];
|
|
691
779
|
node.lineOffsets = [offset];
|
|
692
780
|
}
|
|
693
781
|
}
|
|
694
|
-
if (
|
|
695
|
-
const lineHeight =
|
|
696
|
-
let lines = wrapRichText(ctx,
|
|
697
|
-
if (
|
|
698
|
-
lines = lines.slice(0,
|
|
699
|
-
if (
|
|
782
|
+
if (layoutElement.type === "richtext") {
|
|
783
|
+
const lineHeight = layoutElement.lineHeight ?? 1.2;
|
|
784
|
+
let lines = wrapRichText(ctx, layoutElement.spans, contentWidth, lineHeight);
|
|
785
|
+
if (layoutElement.maxLines && lines.length > layoutElement.maxLines) {
|
|
786
|
+
lines = lines.slice(0, layoutElement.maxLines);
|
|
787
|
+
if (layoutElement.ellipsis && lines.length > 0) {
|
|
700
788
|
const lastLine = lines[lines.length - 1];
|
|
701
789
|
if (lastLine.segments.length > 0) {
|
|
702
790
|
const lastSeg = lastLine.segments[lastLine.segments.length - 1];
|
|
@@ -708,19 +796,19 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
708
796
|
}
|
|
709
797
|
node.richLines = lines;
|
|
710
798
|
}
|
|
711
|
-
if (
|
|
712
|
-
const children =
|
|
713
|
-
if (
|
|
714
|
-
const stackAlign =
|
|
715
|
-
const stackJustify =
|
|
799
|
+
if (layoutElement.type === "box" || layoutElement.type === "stack") {
|
|
800
|
+
const children = layoutElement.children ?? [];
|
|
801
|
+
if (layoutElement.type === "stack") {
|
|
802
|
+
const stackAlign = layoutElement.align ?? "start";
|
|
803
|
+
const stackJustify = layoutElement.justify ?? "start";
|
|
716
804
|
for (const child of children) {
|
|
717
|
-
const childNode =
|
|
805
|
+
const childNode = computeLayoutImpl(child, ctx, {
|
|
718
806
|
minWidth: 0,
|
|
719
807
|
maxWidth: contentWidth,
|
|
720
808
|
minHeight: 0,
|
|
721
809
|
maxHeight: contentHeight
|
|
722
810
|
}, contentX, contentY);
|
|
723
|
-
const childMargin =
|
|
811
|
+
const childMargin = getElementMargin(child);
|
|
724
812
|
const childOuterWidth = childNode.layout.width + childMargin.left + childMargin.right;
|
|
725
813
|
const childOuterHeight = childNode.layout.height + childMargin.top + childMargin.bottom;
|
|
726
814
|
let offsetX = 0;
|
|
@@ -733,19 +821,21 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
733
821
|
node.children.push(childNode);
|
|
734
822
|
}
|
|
735
823
|
} else {
|
|
736
|
-
const
|
|
737
|
-
const
|
|
738
|
-
const
|
|
739
|
-
const
|
|
740
|
-
const
|
|
824
|
+
const boxElement = layoutElement;
|
|
825
|
+
const direction = boxElement.direction ?? "row";
|
|
826
|
+
const justify = boxElement.justify ?? "start";
|
|
827
|
+
const align = boxElement.align ?? "stretch";
|
|
828
|
+
const gap = boxElement.gap ?? 0;
|
|
829
|
+
const wrap = boxElement.wrap ?? false;
|
|
741
830
|
const isRow = direction === "row" || direction === "row-reverse";
|
|
742
831
|
const isReverse = direction === "row-reverse" || direction === "column-reverse";
|
|
743
832
|
const getContentMainSize = () => isRow ? contentWidth : contentHeight;
|
|
744
833
|
const getContentCrossSize = () => isRow ? contentHeight : contentWidth;
|
|
745
834
|
const childInfos = [];
|
|
746
835
|
for (const child of children) {
|
|
747
|
-
const childMargin =
|
|
748
|
-
const
|
|
836
|
+
const childMargin = getElementMargin(child);
|
|
837
|
+
const childProps = getElementLayoutProps(child);
|
|
838
|
+
const childFlex = childProps.flex ?? 0;
|
|
749
839
|
if (childFlex > 0) childInfos.push({
|
|
750
840
|
element: child,
|
|
751
841
|
width: 0,
|
|
@@ -755,10 +845,10 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
755
845
|
});
|
|
756
846
|
else {
|
|
757
847
|
const size = measureIntrinsicSize(child, ctx, contentWidth - childMargin.left - childMargin.right);
|
|
758
|
-
const shouldStretchWidth = !isRow &&
|
|
759
|
-
const shouldStretchHeight = isRow &&
|
|
760
|
-
let w = sizeNeedsParent(
|
|
761
|
-
let h = sizeNeedsParent(
|
|
848
|
+
const shouldStretchWidth = !isRow && childProps.width === void 0 && align === "stretch";
|
|
849
|
+
const shouldStretchHeight = isRow && childProps.height === void 0 && align === "stretch";
|
|
850
|
+
let w = sizeNeedsParent(childProps.width) ? resolveSize(childProps.width, contentWidth - childMargin.left - childMargin.right, size.width) : resolveSize(childProps.width, 0, size.width);
|
|
851
|
+
let h = sizeNeedsParent(childProps.height) ? resolveSize(childProps.height, contentHeight - childMargin.top - childMargin.bottom, size.height) : resolveSize(childProps.height, 0, size.height);
|
|
762
852
|
if (shouldStretchWidth && !wrap) w = contentWidth - childMargin.left - childMargin.right;
|
|
763
853
|
if (shouldStretchHeight && !wrap) h = contentHeight - childMargin.top - childMargin.bottom;
|
|
764
854
|
childInfos.push({
|
|
@@ -799,14 +889,15 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
799
889
|
const availableForFlex = Math.max(0, mainAxisSize - totalFixed - totalGap);
|
|
800
890
|
for (const info of lineInfos) if (info.flex > 0) {
|
|
801
891
|
const flexSize = totalFlex > 0 ? availableForFlex * info.flex / totalFlex : 0;
|
|
892
|
+
const childProps = getElementLayoutProps(info.element);
|
|
802
893
|
if (isRow) {
|
|
803
894
|
info.width = flexSize;
|
|
804
895
|
const size = measureIntrinsicSize(info.element, ctx, flexSize);
|
|
805
|
-
info.height = sizeNeedsParent(
|
|
896
|
+
info.height = sizeNeedsParent(childProps.height) ? resolveSize(childProps.height, contentHeight - info.margin.top - info.margin.bottom, size.height) : resolveSize(childProps.height, 0, size.height);
|
|
806
897
|
} else {
|
|
807
898
|
info.height = flexSize;
|
|
808
899
|
const size = measureIntrinsicSize(info.element, ctx, contentWidth - info.margin.left - info.margin.right);
|
|
809
|
-
info.width = sizeNeedsParent(
|
|
900
|
+
info.width = sizeNeedsParent(childProps.width) ? resolveSize(childProps.width, contentWidth - info.margin.left - info.margin.right, size.width) : resolveSize(childProps.width, 0, size.width);
|
|
810
901
|
}
|
|
811
902
|
}
|
|
812
903
|
}
|
|
@@ -857,17 +948,18 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
857
948
|
const orderedInfos = isReverse ? [...lineInfos].reverse() : lineInfos;
|
|
858
949
|
for (let i = 0; i < orderedInfos.length; i++) {
|
|
859
950
|
const info = orderedInfos[i];
|
|
951
|
+
const childProps = getElementLayoutProps(info.element);
|
|
860
952
|
const crossAxisSize = wrap ? lineCrossSize : getContentCrossSize();
|
|
861
953
|
const childCrossSize = isRow ? info.height + info.margin.top + info.margin.bottom : info.width + info.margin.left + info.margin.right;
|
|
862
954
|
let itemCrossOffset = 0;
|
|
863
|
-
const effectiveAlign =
|
|
955
|
+
const effectiveAlign = childProps.alignSelf ?? align;
|
|
864
956
|
if (effectiveAlign === "start") itemCrossOffset = 0;
|
|
865
957
|
else if (effectiveAlign === "end") itemCrossOffset = crossAxisSize - childCrossSize;
|
|
866
958
|
else if (effectiveAlign === "center") itemCrossOffset = (crossAxisSize - childCrossSize) / 2;
|
|
867
959
|
else if (effectiveAlign === "stretch") {
|
|
868
960
|
itemCrossOffset = 0;
|
|
869
|
-
if (isRow &&
|
|
870
|
-
else if (!isRow &&
|
|
961
|
+
if (isRow && childProps.height === void 0) info.height = crossAxisSize - info.margin.top - info.margin.bottom;
|
|
962
|
+
else if (!isRow && childProps.width === void 0) info.width = crossAxisSize - info.margin.left - info.margin.right;
|
|
871
963
|
}
|
|
872
964
|
const childX = isRow ? contentX + mainOffset + info.margin.left : contentX + crossOffset + itemCrossOffset + info.margin.left;
|
|
873
965
|
const childY = isRow ? contentY + crossOffset + itemCrossOffset + info.margin.top : contentY + mainOffset + info.margin.top;
|
|
@@ -876,26 +968,29 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
876
968
|
let minHeight = 0;
|
|
877
969
|
let maxHeight = info.height;
|
|
878
970
|
let shouldStretchCross = false;
|
|
879
|
-
if (info.flex > 0)
|
|
880
|
-
|
|
881
|
-
if (
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
971
|
+
if (info.flex > 0) {
|
|
972
|
+
const childProps = getElementLayoutProps(info.element);
|
|
973
|
+
if (isRow) {
|
|
974
|
+
minWidth = maxWidth = info.width;
|
|
975
|
+
if (childProps.height === void 0 && align === "stretch") {
|
|
976
|
+
minHeight = info.height;
|
|
977
|
+
maxHeight = boxElement.height !== void 0 ? info.height : Infinity;
|
|
978
|
+
shouldStretchCross = true;
|
|
979
|
+
}
|
|
980
|
+
} else {
|
|
981
|
+
minHeight = maxHeight = info.height;
|
|
982
|
+
if (childProps.width === void 0 && align === "stretch") {
|
|
983
|
+
minWidth = info.width;
|
|
984
|
+
maxWidth = boxElement.width !== void 0 ? info.width : Infinity;
|
|
985
|
+
shouldStretchCross = true;
|
|
986
|
+
}
|
|
885
987
|
}
|
|
886
988
|
} else {
|
|
887
|
-
|
|
888
|
-
if (
|
|
889
|
-
|
|
890
|
-
maxWidth = element.width !== void 0 ? info.width : Infinity;
|
|
891
|
-
shouldStretchCross = true;
|
|
892
|
-
}
|
|
989
|
+
const childProps = getElementLayoutProps(info.element);
|
|
990
|
+
if (!isRow && childProps.width === void 0 && align === "stretch") minWidth = maxWidth = crossAxisSize - info.margin.left - info.margin.right;
|
|
991
|
+
if (isRow && childProps.height === void 0 && align === "stretch") minHeight = maxHeight = crossAxisSize - info.margin.top - info.margin.bottom;
|
|
893
992
|
}
|
|
894
|
-
|
|
895
|
-
if (!isRow && info.element.width === void 0 && align === "stretch") minWidth = maxWidth = crossAxisSize - info.margin.left - info.margin.right;
|
|
896
|
-
if (isRow && info.element.height === void 0 && align === "stretch") minHeight = maxHeight = crossAxisSize - info.margin.top - info.margin.bottom;
|
|
897
|
-
}
|
|
898
|
-
const childNode = computeLayout(info.element, ctx, {
|
|
993
|
+
const childNode = computeLayoutImpl(info.element, ctx, {
|
|
899
994
|
minWidth,
|
|
900
995
|
maxWidth,
|
|
901
996
|
minHeight,
|
|
@@ -918,12 +1013,12 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
918
1013
|
crossOffset += lineCrossSize;
|
|
919
1014
|
if (lineIndex < lines.length - 1) crossOffset += gap;
|
|
920
1015
|
}
|
|
921
|
-
if (wrap &&
|
|
1016
|
+
if (wrap && boxElement.height === void 0 && isRow) {
|
|
922
1017
|
const actualContentHeight = crossOffset;
|
|
923
1018
|
const actualHeight = actualContentHeight + padding.top + padding.bottom;
|
|
924
1019
|
node.layout.height = actualHeight;
|
|
925
1020
|
node.layout.contentHeight = actualContentHeight;
|
|
926
|
-
} else if (wrap &&
|
|
1021
|
+
} else if (wrap && boxElement.width === void 0 && !isRow) {
|
|
927
1022
|
const actualContentWidth = crossOffset;
|
|
928
1023
|
const actualWidth = actualContentWidth + padding.left + padding.right;
|
|
929
1024
|
node.layout.width = actualWidth;
|
|
@@ -932,7 +1027,7 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
932
1027
|
if (!wrap) {
|
|
933
1028
|
let maxChildCrossSize = 0;
|
|
934
1029
|
for (const childNode of node.children) {
|
|
935
|
-
const childMargin =
|
|
1030
|
+
const childMargin = getElementMargin(childNode.element);
|
|
936
1031
|
if (isRow) {
|
|
937
1032
|
const childOuterHeight = childNode.layout.height + childMargin.top + childMargin.bottom;
|
|
938
1033
|
maxChildCrossSize = Math.max(maxChildCrossSize, childOuterHeight);
|
|
@@ -941,13 +1036,13 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
941
1036
|
maxChildCrossSize = Math.max(maxChildCrossSize, childOuterWidth);
|
|
942
1037
|
}
|
|
943
1038
|
}
|
|
944
|
-
if (isRow &&
|
|
1039
|
+
if (isRow && boxElement.height === void 0) {
|
|
945
1040
|
const actualHeight = maxChildCrossSize + padding.top + padding.bottom;
|
|
946
1041
|
if (actualHeight > node.layout.height) {
|
|
947
1042
|
node.layout.height = actualHeight;
|
|
948
1043
|
node.layout.contentHeight = maxChildCrossSize;
|
|
949
1044
|
}
|
|
950
|
-
} else if (!isRow &&
|
|
1045
|
+
} else if (!isRow && boxElement.width === void 0) {
|
|
951
1046
|
const actualWidth = maxChildCrossSize + padding.left + padding.right;
|
|
952
1047
|
if (actualWidth > node.layout.width) {
|
|
953
1048
|
node.layout.width = actualWidth;
|
|
@@ -957,48 +1052,24 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
957
1052
|
}
|
|
958
1053
|
if (isReverse) node.children.reverse();
|
|
959
1054
|
}
|
|
960
|
-
} else if (
|
|
961
|
-
const child =
|
|
962
|
-
if (child) {
|
|
963
|
-
const childMargin = normalizeSpacing(child.margin);
|
|
964
|
-
const childNode = computeLayout(child, ctx, {
|
|
965
|
-
minWidth: 0,
|
|
966
|
-
maxWidth: contentWidth,
|
|
967
|
-
minHeight: 0,
|
|
968
|
-
maxHeight: contentHeight
|
|
969
|
-
}, contentX, contentY);
|
|
970
|
-
node.children.push(childNode);
|
|
971
|
-
if (element.width === void 0) {
|
|
972
|
-
const childOuterWidth = childNode.layout.width + childMargin.left + childMargin.right;
|
|
973
|
-
const actualWidth = childOuterWidth + padding.left + padding.right;
|
|
974
|
-
node.layout.width = actualWidth;
|
|
975
|
-
node.layout.contentWidth = childOuterWidth;
|
|
976
|
-
}
|
|
977
|
-
if (element.height === void 0) {
|
|
978
|
-
const childOuterHeight = childNode.layout.height + childMargin.top + childMargin.bottom;
|
|
979
|
-
const actualHeight = childOuterHeight + padding.top + padding.bottom;
|
|
980
|
-
node.layout.height = actualHeight;
|
|
981
|
-
node.layout.contentHeight = childOuterHeight;
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
} else if (element.type === "customdraw") {
|
|
985
|
-
const child = element.children;
|
|
1055
|
+
} else if (layoutElement.type === "customdraw") {
|
|
1056
|
+
const child = layoutElement.children;
|
|
986
1057
|
if (child) {
|
|
987
1058
|
const childMargin = normalizeSpacing(child.margin);
|
|
988
|
-
const childNode =
|
|
1059
|
+
const childNode = computeLayoutImpl(child, ctx, {
|
|
989
1060
|
minWidth: 0,
|
|
990
1061
|
maxWidth: contentWidth,
|
|
991
1062
|
minHeight: 0,
|
|
992
1063
|
maxHeight: contentHeight
|
|
993
1064
|
}, contentX, contentY);
|
|
994
1065
|
node.children.push(childNode);
|
|
995
|
-
if (
|
|
1066
|
+
if (layoutElement.width === void 0) {
|
|
996
1067
|
const childOuterWidth = childNode.layout.width + childMargin.left + childMargin.right;
|
|
997
1068
|
const actualWidth = childOuterWidth + padding.left + padding.right;
|
|
998
1069
|
node.layout.width = actualWidth;
|
|
999
1070
|
node.layout.contentWidth = childOuterWidth;
|
|
1000
1071
|
}
|
|
1001
|
-
if (
|
|
1072
|
+
if (layoutElement.height === void 0) {
|
|
1002
1073
|
const childOuterHeight = childNode.layout.height + childMargin.top + childMargin.bottom;
|
|
1003
1074
|
const actualHeight = childOuterHeight + padding.top + padding.bottom;
|
|
1004
1075
|
node.layout.height = actualHeight;
|
|
@@ -2008,10 +2079,12 @@ function getElementType(element) {
|
|
|
2008
2079
|
switch (element.type) {
|
|
2009
2080
|
case "box": return "Box";
|
|
2010
2081
|
case "text": return `Text "${element.content.slice(0, 20)}${element.content.length > 20 ? "..." : ""}"`;
|
|
2082
|
+
case "richtext": return "RichText";
|
|
2011
2083
|
case "stack": return "Stack";
|
|
2012
2084
|
case "image": return "Image";
|
|
2013
2085
|
case "svg": return "Svg";
|
|
2014
|
-
|
|
2086
|
+
case "transform": return "Transform";
|
|
2087
|
+
case "customdraw": return "CustomDraw";
|
|
2015
2088
|
}
|
|
2016
2089
|
}
|
|
2017
2090
|
/**
|
package/node/index.d.cts
CHANGED
|
@@ -363,7 +363,8 @@ interface CustomDrawProps extends LayoutProps {
|
|
|
363
363
|
interface CustomDrawElement extends ElementBase, CustomDrawProps {
|
|
364
364
|
type: "customdraw";
|
|
365
365
|
}
|
|
366
|
-
type
|
|
366
|
+
type LayoutElement = BoxElement | TextElement | RichTextElement | ImageElement | SvgElement | StackElement | CustomDrawElement;
|
|
367
|
+
type Element = LayoutElement | TransformElement;
|
|
367
368
|
//#endregion
|
|
368
369
|
//#region src/canvas.d.ts
|
|
369
370
|
interface CanvasOptions<T extends HTMLCanvasElement | OffscreenCanvas | Canvas = HTMLCanvasElement | OffscreenCanvas | Canvas> {
|
|
@@ -382,7 +383,7 @@ interface DrawCallCanvas<T extends HTMLCanvasElement | OffscreenCanvas | Canvas
|
|
|
382
383
|
readonly height: number;
|
|
383
384
|
readonly pixelRatio: number;
|
|
384
385
|
readonly canvas: T;
|
|
385
|
-
render(element:
|
|
386
|
+
render(element: LayoutElement): LayoutNode;
|
|
386
387
|
clear(): void;
|
|
387
388
|
getContext(): CanvasRenderingContext2D;
|
|
388
389
|
toDataURL(type?: string, quality?: number): string;
|
|
@@ -431,7 +432,11 @@ declare function Text(props: TextProps): TextElement;
|
|
|
431
432
|
declare function Transform(props: TransformProps): TransformElement;
|
|
432
433
|
//#endregion
|
|
433
434
|
//#region src/layout/engine.d.ts
|
|
434
|
-
|
|
435
|
+
/**
|
|
436
|
+
* 布局计算主函数
|
|
437
|
+
* 内部使用 Element 类型以支持 Transform,外部通过 LayoutElement 约束类型
|
|
438
|
+
*/
|
|
439
|
+
declare function computeLayout(element: LayoutElement, ctx: MeasureContext, constraints: LayoutConstraints, x?: number, y?: number): LayoutNode;
|
|
435
440
|
//#endregion
|
|
436
441
|
//#region src/layout/utils/print.d.ts
|
|
437
442
|
/**
|
|
@@ -446,4 +451,4 @@ declare function printLayout(node: LayoutNode): void;
|
|
|
446
451
|
*/
|
|
447
452
|
declare function layoutToString(node: LayoutNode, _indent?: string): string;
|
|
448
453
|
//#endregion
|
|
449
|
-
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 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 };
|
|
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 };
|
package/node/index.d.mts
CHANGED
|
@@ -363,7 +363,8 @@ interface CustomDrawProps extends LayoutProps {
|
|
|
363
363
|
interface CustomDrawElement extends ElementBase, CustomDrawProps {
|
|
364
364
|
type: "customdraw";
|
|
365
365
|
}
|
|
366
|
-
type
|
|
366
|
+
type LayoutElement = BoxElement | TextElement | RichTextElement | ImageElement | SvgElement | StackElement | CustomDrawElement;
|
|
367
|
+
type Element = LayoutElement | TransformElement;
|
|
367
368
|
//#endregion
|
|
368
369
|
//#region src/canvas.d.ts
|
|
369
370
|
interface CanvasOptions<T extends HTMLCanvasElement | OffscreenCanvas | Canvas = HTMLCanvasElement | OffscreenCanvas | Canvas> {
|
|
@@ -382,7 +383,7 @@ interface DrawCallCanvas<T extends HTMLCanvasElement | OffscreenCanvas | Canvas
|
|
|
382
383
|
readonly height: number;
|
|
383
384
|
readonly pixelRatio: number;
|
|
384
385
|
readonly canvas: T;
|
|
385
|
-
render(element:
|
|
386
|
+
render(element: LayoutElement): LayoutNode;
|
|
386
387
|
clear(): void;
|
|
387
388
|
getContext(): CanvasRenderingContext2D;
|
|
388
389
|
toDataURL(type?: string, quality?: number): string;
|
|
@@ -431,7 +432,11 @@ declare function Text(props: TextProps): TextElement;
|
|
|
431
432
|
declare function Transform(props: TransformProps): TransformElement;
|
|
432
433
|
//#endregion
|
|
433
434
|
//#region src/layout/engine.d.ts
|
|
434
|
-
|
|
435
|
+
/**
|
|
436
|
+
* 布局计算主函数
|
|
437
|
+
* 内部使用 Element 类型以支持 Transform,外部通过 LayoutElement 约束类型
|
|
438
|
+
*/
|
|
439
|
+
declare function computeLayout(element: LayoutElement, ctx: MeasureContext, constraints: LayoutConstraints, x?: number, y?: number): LayoutNode;
|
|
435
440
|
//#endregion
|
|
436
441
|
//#region src/layout/utils/print.d.ts
|
|
437
442
|
/**
|
|
@@ -446,4 +451,4 @@ declare function printLayout(node: LayoutNode): void;
|
|
|
446
451
|
*/
|
|
447
452
|
declare function layoutToString(node: LayoutNode, _indent?: string): string;
|
|
448
453
|
//#endregion
|
|
449
|
-
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 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 };
|
|
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 };
|