@sliiu/present-renderer 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/COPYRIGHT +5 -0
  2. package/LICENSE +661 -0
  3. package/THIRD-PARTY-NOTICES.md +221 -0
  4. package/dist/cjs/arrow-geom.js +38 -0
  5. package/dist/cjs/canvas-backend.js +1368 -0
  6. package/dist/cjs/cell-borders.js +25 -0
  7. package/dist/cjs/chart-canvas.js +1059 -0
  8. package/dist/cjs/chart-ex-render.js +275 -0
  9. package/dist/cjs/chart-geom.js +313 -0
  10. package/dist/cjs/chart-svg.js +1110 -0
  11. package/dist/cjs/compose.js +74 -0
  12. package/dist/cjs/effect-clip.js +652 -0
  13. package/dist/cjs/entrance-hide.js +63 -0
  14. package/dist/cjs/font-stack.js +103 -0
  15. package/dist/cjs/hit-geom.js +50 -0
  16. package/dist/cjs/hybrid-backend.js +93 -0
  17. package/dist/cjs/hybrid-segments.js +54 -0
  18. package/dist/cjs/index.js +70 -0
  19. package/dist/cjs/linked-src.js +116 -0
  20. package/dist/cjs/metafile-preview.js +142 -0
  21. package/dist/cjs/model3d-frame.js +199 -0
  22. package/dist/cjs/model3d-render.js +78 -0
  23. package/dist/cjs/morph-transition.js +57 -0
  24. package/dist/cjs/node-affine.js +79 -0
  25. package/dist/cjs/ole-render.js +291 -0
  26. package/dist/cjs/package.json +1 -0
  27. package/dist/cjs/paint-canvas.js +701 -0
  28. package/dist/cjs/paint-svg.js +674 -0
  29. package/dist/cjs/scene-node.js +762 -0
  30. package/dist/cjs/selection.js +130 -0
  31. package/dist/cjs/shape-effects.js +66 -0
  32. package/dist/cjs/shape-front.js +38 -0
  33. package/dist/cjs/stage-chrome.js +15 -0
  34. package/dist/cjs/svg-backend.js +2172 -0
  35. package/dist/cjs/text-autofit.js +48 -0
  36. package/dist/cjs/text-hit.js +284 -0
  37. package/dist/cjs/text-layout.js +408 -0
  38. package/dist/cjs/text-shared.js +238 -0
  39. package/dist/cjs/text-stacked.js +82 -0
  40. package/dist/cjs/text-warp.js +377 -0
  41. package/dist/cjs/text-wordart.js +33 -0
  42. package/dist/cjs/video-frame.js +113 -0
  43. package/dist/cjs/webgl-model3d-backend.js +285 -0
  44. package/dist/cjs/webgl-shape-backend.js +360 -0
  45. package/dist/esm/arrow-geom.js +33 -0
  46. package/dist/esm/canvas-backend.js +1363 -0
  47. package/dist/esm/cell-borders.js +21 -0
  48. package/dist/esm/chart-canvas.js +1056 -0
  49. package/dist/esm/chart-ex-render.js +261 -0
  50. package/dist/esm/chart-geom.js +296 -0
  51. package/dist/esm/chart-svg.js +1107 -0
  52. package/dist/esm/compose.js +71 -0
  53. package/dist/esm/effect-clip.js +648 -0
  54. package/dist/esm/entrance-hide.js +59 -0
  55. package/dist/esm/font-stack.js +100 -0
  56. package/dist/esm/hit-geom.js +45 -0
  57. package/dist/esm/hybrid-backend.js +89 -0
  58. package/dist/esm/hybrid-segments.js +51 -0
  59. package/dist/esm/index.js +24 -0
  60. package/dist/esm/linked-src.js +109 -0
  61. package/dist/esm/metafile-preview.js +135 -0
  62. package/dist/esm/model3d-frame.js +158 -0
  63. package/dist/esm/model3d-render.js +73 -0
  64. package/dist/esm/morph-transition.js +54 -0
  65. package/dist/esm/node-affine.js +71 -0
  66. package/dist/esm/ole-render.js +286 -0
  67. package/dist/esm/paint-canvas.js +693 -0
  68. package/dist/esm/paint-svg.js +670 -0
  69. package/dist/esm/scene-node.js +750 -0
  70. package/dist/esm/selection.js +122 -0
  71. package/dist/esm/shape-effects.js +60 -0
  72. package/dist/esm/shape-front.js +35 -0
  73. package/dist/esm/stage-chrome.js +12 -0
  74. package/dist/esm/svg-backend.js +2168 -0
  75. package/dist/esm/text-autofit.js +44 -0
  76. package/dist/esm/text-hit.js +280 -0
  77. package/dist/esm/text-layout.js +400 -0
  78. package/dist/esm/text-shared.js +221 -0
  79. package/dist/esm/text-stacked.js +78 -0
  80. package/dist/esm/text-warp.js +371 -0
  81. package/dist/esm/text-wordart.js +30 -0
  82. package/dist/esm/video-frame.js +109 -0
  83. package/dist/esm/webgl-model3d-backend.js +248 -0
  84. package/dist/esm/webgl-shape-backend.js +323 -0
  85. package/dist/types/arrow-geom.d.ts +10 -0
  86. package/dist/types/canvas-backend.d.ts +55 -0
  87. package/dist/types/cell-borders.d.ts +9 -0
  88. package/dist/types/chart-canvas.d.ts +2 -0
  89. package/dist/types/chart-ex-render.d.ts +79 -0
  90. package/dist/types/chart-geom.d.ts +112 -0
  91. package/dist/types/chart-svg.d.ts +2 -0
  92. package/dist/types/compose.d.ts +2 -0
  93. package/dist/types/effect-clip.d.ts +10 -0
  94. package/dist/types/entrance-hide.d.ts +16 -0
  95. package/dist/types/font-stack.d.ts +9 -0
  96. package/dist/types/hit-geom.d.ts +15 -0
  97. package/dist/types/hybrid-backend.d.ts +21 -0
  98. package/dist/types/hybrid-segments.d.ts +11 -0
  99. package/dist/types/index.d.ts +24 -0
  100. package/dist/types/linked-src.d.ts +13 -0
  101. package/dist/types/metafile-preview.d.ts +11 -0
  102. package/dist/types/model3d-frame.d.ts +8 -0
  103. package/dist/types/model3d-render.d.ts +4 -0
  104. package/dist/types/morph-transition.d.ts +15 -0
  105. package/dist/types/node-affine.d.ts +22 -0
  106. package/dist/types/ole-render.d.ts +7 -0
  107. package/dist/types/paint-canvas.d.ts +22 -0
  108. package/dist/types/paint-svg.d.ts +19 -0
  109. package/dist/types/scene-node.d.ts +128 -0
  110. package/dist/types/selection.d.ts +22 -0
  111. package/dist/types/shape-effects.d.ts +13 -0
  112. package/dist/types/shape-front.d.ts +4 -0
  113. package/dist/types/stage-chrome.d.ts +8 -0
  114. package/dist/types/svg-backend.d.ts +88 -0
  115. package/dist/types/text-autofit.d.ts +7 -0
  116. package/dist/types/text-hit.d.ts +7 -0
  117. package/dist/types/text-layout.d.ts +35 -0
  118. package/dist/types/text-shared.d.ts +86 -0
  119. package/dist/types/text-stacked.d.ts +11 -0
  120. package/dist/types/text-warp.d.ts +37 -0
  121. package/dist/types/text-wordart.d.ts +18 -0
  122. package/dist/types/video-frame.d.ts +2 -0
  123. package/dist/types/webgl-model3d-backend.d.ts +25 -0
  124. package/dist/types/webgl-shape-backend.d.ts +33 -0
  125. package/package.json +33 -4
  126. package/README.md +0 -3
@@ -0,0 +1,122 @@
1
+ export class Selection {
2
+ ids = new Set();
3
+ listeners = new Set();
4
+ get() {
5
+ return [...this.ids];
6
+ }
7
+ has(id) {
8
+ return this.ids.has(id);
9
+ }
10
+ set(ids) {
11
+ this.ids = new Set(ids);
12
+ this.fire();
13
+ }
14
+ add(id) {
15
+ this.ids.add(id);
16
+ this.fire();
17
+ }
18
+ remove(id) {
19
+ this.ids.delete(id);
20
+ this.fire();
21
+ }
22
+ toggle(id) {
23
+ if (this.ids.has(id))
24
+ this.ids.delete(id);
25
+ else
26
+ this.ids.add(id);
27
+ this.fire();
28
+ }
29
+ clear() {
30
+ if (this.ids.size === 0)
31
+ return;
32
+ this.ids.clear();
33
+ this.fire();
34
+ }
35
+ on(fn) {
36
+ this.listeners.add(fn);
37
+ return () => this.listeners.delete(fn);
38
+ }
39
+ fire() {
40
+ for (const l of this.listeners)
41
+ l(this.ids);
42
+ }
43
+ }
44
+ export function nodeWorldBBox(node) {
45
+ const b = node.shape.bbox;
46
+ const cx = b.x + b.w / 2;
47
+ const cy = b.y + b.h / 2;
48
+ const flipX = node.shape.transform?.scaleX ?? 1;
49
+ const flipY = node.shape.transform?.scaleY ?? 1;
50
+ const sx = node.scale * node.scaleX * node.widthScale * (flipX < 0 ? -1 : 1);
51
+ const sy = node.scale * node.scaleY * node.heightScale * (flipY < 0 ? -1 : 1);
52
+ return {
53
+ x: b.x + node.tx + (1 - sx) * (cx - b.x),
54
+ y: b.y + node.ty + (1 - sy) * (cy - b.y),
55
+ w: b.w * sx,
56
+ h: b.h * sy,
57
+ };
58
+ }
59
+ export function hitTest(scene, x, y, opts = {}) {
60
+ let result = null;
61
+ const visit = (node) => {
62
+ if (node.shape.kind !== "group") {
63
+ if (opts.ignoreLocked && node.shape.locked)
64
+ return;
65
+ if (pointInNode(node, x, y))
66
+ result = node;
67
+ }
68
+ for (const c of node.children)
69
+ visit(c);
70
+ };
71
+ visit(scene.root);
72
+ return result;
73
+ }
74
+ export function pointInNode(node, x, y) {
75
+ const b = node.shape.bbox;
76
+ const cx = b.x + b.w / 2;
77
+ const cy = b.y + b.h / 2;
78
+ let lx = x - node.tx;
79
+ let ly = y - node.ty;
80
+ const flipX = node.shape.transform?.scaleX ?? 1;
81
+ const flipY = node.shape.transform?.scaleY ?? 1;
82
+ const sx = node.scale * node.scaleX * node.widthScale * (flipX < 0 ? -1 : 1);
83
+ const sy = node.scale * node.scaleY * node.heightScale * (flipY < 0 ? -1 : 1);
84
+ if (sx !== 1)
85
+ lx = (lx - cx) / sx + cx;
86
+ if (sy !== 1)
87
+ ly = (ly - cy) / sy + cy;
88
+ if (node.rotation !== 0) {
89
+ const a = (-node.rotation * Math.PI) / 180;
90
+ const dx = lx - cx;
91
+ const dy = ly - cy;
92
+ lx = cx + dx * Math.cos(a) - dy * Math.sin(a);
93
+ ly = cy + dx * Math.sin(a) + dy * Math.cos(a);
94
+ }
95
+ if (node.shape.kind === "ellipse") {
96
+ const rx = b.w / 2;
97
+ const ry = b.h / 2;
98
+ const dx = (lx - cx) / rx;
99
+ const dy = (ly - cy) / ry;
100
+ return dx * dx + dy * dy <= 1;
101
+ }
102
+ return lx >= b.x && lx <= b.x + b.w && ly >= b.y && ly <= b.y + b.h;
103
+ }
104
+ export function attachPointerSelection(hostEl, scene, selection) {
105
+ const onClick = (e) => {
106
+ const rect = hostEl.getBoundingClientRect();
107
+ const sx = (e.clientX - rect.left) * (scene.width / rect.width);
108
+ const sy = (e.clientY - rect.top) * (scene.height / rect.height);
109
+ const hit = hitTest(scene, sx, sy);
110
+ if (!hit) {
111
+ if (!e.shiftKey)
112
+ selection.clear();
113
+ return;
114
+ }
115
+ if (e.shiftKey)
116
+ selection.toggle(hit.id);
117
+ else
118
+ selection.set([hit.id]);
119
+ };
120
+ hostEl.addEventListener("pointerdown", onClick);
121
+ return () => hostEl.removeEventListener("pointerdown", onClick);
122
+ }
@@ -0,0 +1,60 @@
1
+ const EMPTY = { outer: [], glow: [] };
2
+ export function collectShapeEffects(s) {
3
+ const list = s.effects && s.effects.length ? s.effects : s.shadow ? [s.shadow] : undefined;
4
+ if (!list)
5
+ return EMPTY;
6
+ const out = { outer: [], glow: [] };
7
+ for (const fx of list) {
8
+ switch (fx.kind) {
9
+ case "outer":
10
+ out.outer.push(fx);
11
+ break;
12
+ case "inner":
13
+ if (!out.inner)
14
+ out.inner = fx;
15
+ break;
16
+ case "glow":
17
+ out.glow.push(fx);
18
+ break;
19
+ case "softEdge":
20
+ if (!out.softEdge)
21
+ out.softEdge = fx;
22
+ break;
23
+ case "reflection":
24
+ if (!out.reflection)
25
+ out.reflection = fx;
26
+ break;
27
+ default:
28
+ // blur/duotone/alphaMod 等位图效果由 paint-canvas 的图像通道处理,不在此列。
29
+ break;
30
+ }
31
+ }
32
+ return out;
33
+ }
34
+ export function hasAnyEffect(fx) {
35
+ return fx.outer.length > 0 || fx.glow.length > 0 || !!fx.inner || !!fx.softEdge || !!fx.reflection;
36
+ }
37
+ export function effectHexWithAlpha(color, alpha) {
38
+ if (alpha >= 1)
39
+ return color;
40
+ if (/^#([0-9a-f]{6})$/i.test(color)) {
41
+ const a = Math.round(Math.max(0, Math.min(1, alpha)) * 255)
42
+ .toString(16)
43
+ .padStart(2, "0");
44
+ return color + a;
45
+ }
46
+ return color;
47
+ }
48
+ /** outer shadow + glow 的 CSS filter 链(SVG style.filter / Canvas ctx.filter 通用)。 */
49
+ export function cssFilterForEffects(fx) {
50
+ const parts = [];
51
+ for (const sh of fx.outer) {
52
+ parts.push(`drop-shadow(${sh.dx}px ${sh.dy}px ${sh.blur}px ${effectHexWithAlpha(sh.color, sh.alpha)})`);
53
+ }
54
+ for (const g of fx.glow) {
55
+ const c = effectHexWithAlpha(g.color, g.alpha);
56
+ parts.push(`drop-shadow(0 0 ${g.radius}px ${c})`);
57
+ parts.push(`drop-shadow(0 0 ${g.radius}px ${c})`);
58
+ }
59
+ return parts.join(" ");
60
+ }
@@ -0,0 +1,35 @@
1
+ import { rasterizeShapeFront } from "./canvas-backend.js";
2
+ const cache = new Map();
3
+ /** 文字 3D 的正面:字形画进 PNG,再贴到挤出体上。非文字返回 undefined。 */
4
+ export function shapeFrontImageSrc(scene, shape) {
5
+ if (shape.kind !== "text" || typeof document === "undefined")
6
+ return undefined;
7
+ const key = JSON.stringify({
8
+ id: shape.id,
9
+ w: Math.round(shape.bbox.w),
10
+ h: Math.round(shape.bbox.h),
11
+ p: shape.paragraphs,
12
+ f: shape.fill ?? null,
13
+ i: shape.insets ?? null,
14
+ });
15
+ const hit = cache.get(key);
16
+ if (hit)
17
+ return hit;
18
+ const canvas = rasterizeShapeFront(scene, shape.id);
19
+ if (!canvas)
20
+ return undefined;
21
+ let url;
22
+ try {
23
+ url = canvas.toDataURL("image/png");
24
+ }
25
+ catch {
26
+ return undefined;
27
+ }
28
+ cache.set(key, url);
29
+ if (cache.size > 40) {
30
+ const oldest = cache.keys().next().value;
31
+ if (oldest)
32
+ cache.delete(oldest);
33
+ }
34
+ return url;
35
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * CSS background for the stage / hybrid wrapper chrome around the scene.
3
+ * When the slide has a painted background, createScene injects a full-slide
4
+ * __bg_* shape — a second opaque underlay would show through image alpha or
5
+ * mask gradient edges. Use white only when the slide has no background paint.
6
+ */
7
+ export function stageChromeBackground(slide) {
8
+ const bg = slide?.background;
9
+ if (!bg || bg.kind === "none")
10
+ return "#ffffff";
11
+ return "transparent";
12
+ }