@sliiu/present-renderer 0.0.0-stage → 0.1.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/COPYRIGHT +5 -0
- package/LICENSE +661 -0
- package/README.md +8 -2
- package/THIRD-PARTY-NOTICES.md +221 -0
- package/dist/cjs/arrow-geom.js +38 -0
- package/dist/cjs/canvas-backend.js +1368 -0
- package/dist/cjs/cell-borders.js +25 -0
- package/dist/cjs/chart-canvas.js +1059 -0
- package/dist/cjs/chart-ex-render.js +275 -0
- package/dist/cjs/chart-geom.js +313 -0
- package/dist/cjs/chart-svg.js +1110 -0
- package/dist/cjs/compose.js +74 -0
- package/dist/cjs/effect-clip.js +652 -0
- package/dist/cjs/entrance-hide.js +63 -0
- package/dist/cjs/font-stack.js +103 -0
- package/dist/cjs/hit-geom.js +50 -0
- package/dist/cjs/hybrid-backend.js +93 -0
- package/dist/cjs/hybrid-segments.js +54 -0
- package/dist/cjs/index.js +70 -0
- package/dist/cjs/linked-src.js +116 -0
- package/dist/cjs/metafile-preview.js +142 -0
- package/dist/cjs/model3d-frame.js +199 -0
- package/dist/cjs/model3d-render.js +78 -0
- package/dist/cjs/morph-transition.js +57 -0
- package/dist/cjs/node-affine.js +79 -0
- package/dist/cjs/ole-render.js +291 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/paint-canvas.js +701 -0
- package/dist/cjs/paint-svg.js +674 -0
- package/dist/cjs/scene-node.js +762 -0
- package/dist/cjs/selection.js +130 -0
- package/dist/cjs/shape-effects.js +66 -0
- package/dist/cjs/shape-front.js +38 -0
- package/dist/cjs/stage-chrome.js +15 -0
- package/dist/cjs/svg-backend.js +2172 -0
- package/dist/cjs/text-autofit.js +48 -0
- package/dist/cjs/text-hit.js +284 -0
- package/dist/cjs/text-layout.js +408 -0
- package/dist/cjs/text-shared.js +238 -0
- package/dist/cjs/text-stacked.js +82 -0
- package/dist/cjs/text-warp.js +377 -0
- package/dist/cjs/text-wordart.js +33 -0
- package/dist/cjs/video-frame.js +113 -0
- package/dist/cjs/webgl-model3d-backend.js +285 -0
- package/dist/cjs/webgl-shape-backend.js +360 -0
- package/dist/esm/arrow-geom.js +33 -0
- package/dist/esm/canvas-backend.js +1363 -0
- package/dist/esm/cell-borders.js +21 -0
- package/dist/esm/chart-canvas.js +1056 -0
- package/dist/esm/chart-ex-render.js +261 -0
- package/dist/esm/chart-geom.js +296 -0
- package/dist/esm/chart-svg.js +1107 -0
- package/dist/esm/compose.js +71 -0
- package/dist/esm/effect-clip.js +648 -0
- package/dist/esm/entrance-hide.js +59 -0
- package/dist/esm/font-stack.js +100 -0
- package/dist/esm/hit-geom.js +45 -0
- package/dist/esm/hybrid-backend.js +89 -0
- package/dist/esm/hybrid-segments.js +51 -0
- package/dist/esm/index.js +24 -0
- package/dist/esm/linked-src.js +109 -0
- package/dist/esm/metafile-preview.js +135 -0
- package/dist/esm/model3d-frame.js +158 -0
- package/dist/esm/model3d-render.js +73 -0
- package/dist/esm/morph-transition.js +54 -0
- package/dist/esm/node-affine.js +71 -0
- package/dist/esm/ole-render.js +286 -0
- package/dist/esm/paint-canvas.js +693 -0
- package/dist/esm/paint-svg.js +670 -0
- package/dist/esm/scene-node.js +750 -0
- package/dist/esm/selection.js +122 -0
- package/dist/esm/shape-effects.js +60 -0
- package/dist/esm/shape-front.js +35 -0
- package/dist/esm/stage-chrome.js +12 -0
- package/dist/esm/svg-backend.js +2168 -0
- package/dist/esm/text-autofit.js +44 -0
- package/dist/esm/text-hit.js +280 -0
- package/dist/esm/text-layout.js +400 -0
- package/dist/esm/text-shared.js +221 -0
- package/dist/esm/text-stacked.js +78 -0
- package/dist/esm/text-warp.js +371 -0
- package/dist/esm/text-wordart.js +30 -0
- package/dist/esm/video-frame.js +109 -0
- package/dist/esm/webgl-model3d-backend.js +248 -0
- package/dist/esm/webgl-shape-backend.js +323 -0
- package/dist/types/arrow-geom.d.ts +10 -0
- package/dist/types/canvas-backend.d.ts +55 -0
- package/dist/types/cell-borders.d.ts +9 -0
- package/dist/types/chart-canvas.d.ts +2 -0
- package/dist/types/chart-ex-render.d.ts +79 -0
- package/dist/types/chart-geom.d.ts +112 -0
- package/dist/types/chart-svg.d.ts +2 -0
- package/dist/types/compose.d.ts +2 -0
- package/dist/types/effect-clip.d.ts +10 -0
- package/dist/types/entrance-hide.d.ts +16 -0
- package/dist/types/font-stack.d.ts +9 -0
- package/dist/types/hit-geom.d.ts +15 -0
- package/dist/types/hybrid-backend.d.ts +21 -0
- package/dist/types/hybrid-segments.d.ts +11 -0
- package/dist/types/index.d.ts +24 -0
- package/dist/types/linked-src.d.ts +13 -0
- package/dist/types/metafile-preview.d.ts +11 -0
- package/dist/types/model3d-frame.d.ts +8 -0
- package/dist/types/model3d-render.d.ts +4 -0
- package/dist/types/morph-transition.d.ts +15 -0
- package/dist/types/node-affine.d.ts +22 -0
- package/dist/types/ole-render.d.ts +7 -0
- package/dist/types/paint-canvas.d.ts +22 -0
- package/dist/types/paint-svg.d.ts +19 -0
- package/dist/types/scene-node.d.ts +128 -0
- package/dist/types/selection.d.ts +22 -0
- package/dist/types/shape-effects.d.ts +13 -0
- package/dist/types/shape-front.d.ts +4 -0
- package/dist/types/stage-chrome.d.ts +8 -0
- package/dist/types/svg-backend.d.ts +88 -0
- package/dist/types/text-autofit.d.ts +7 -0
- package/dist/types/text-hit.d.ts +7 -0
- package/dist/types/text-layout.d.ts +35 -0
- package/dist/types/text-shared.d.ts +86 -0
- package/dist/types/text-stacked.d.ts +11 -0
- package/dist/types/text-warp.d.ts +37 -0
- package/dist/types/text-wordart.d.ts +18 -0
- package/dist/types/video-frame.d.ts +2 -0
- package/dist/types/webgl-model3d-backend.d.ts +25 -0
- package/dist/types/webgl-shape-backend.d.ts +33 -0
- package/package.json +43 -4
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { ChartDef } from "@sliiu/present-core";
|
|
2
|
+
export declare const CHART_EX_PALETTE: string[];
|
|
3
|
+
export interface Plot {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
w: number;
|
|
7
|
+
h: number;
|
|
8
|
+
}
|
|
9
|
+
export interface ChartExSlice {
|
|
10
|
+
label: string;
|
|
11
|
+
value: number;
|
|
12
|
+
color: string;
|
|
13
|
+
}
|
|
14
|
+
export interface TreemapCell extends ChartExSlice {
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
w: number;
|
|
18
|
+
h: number;
|
|
19
|
+
}
|
|
20
|
+
export interface SunburstArc extends ChartExSlice {
|
|
21
|
+
cx: number;
|
|
22
|
+
cy: number;
|
|
23
|
+
r0: number;
|
|
24
|
+
r1: number;
|
|
25
|
+
a0: number;
|
|
26
|
+
a1: number;
|
|
27
|
+
}
|
|
28
|
+
export interface WaterfallBar extends ChartExSlice {
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
w: number;
|
|
32
|
+
h: number;
|
|
33
|
+
kind: "increase" | "decrease" | "total";
|
|
34
|
+
}
|
|
35
|
+
export interface FunnelSeg extends ChartExSlice {
|
|
36
|
+
points: [number, number][];
|
|
37
|
+
}
|
|
38
|
+
export interface ColumnBar extends ChartExSlice {
|
|
39
|
+
x: number;
|
|
40
|
+
y: number;
|
|
41
|
+
w: number;
|
|
42
|
+
h: number;
|
|
43
|
+
}
|
|
44
|
+
export interface ParetoLayout {
|
|
45
|
+
bars: ColumnBar[];
|
|
46
|
+
line: [number, number][];
|
|
47
|
+
}
|
|
48
|
+
export interface BoxWhiskerBar {
|
|
49
|
+
label: string;
|
|
50
|
+
color: string;
|
|
51
|
+
cx: number;
|
|
52
|
+
whiskerLow: number;
|
|
53
|
+
q1: number;
|
|
54
|
+
median: number;
|
|
55
|
+
q3: number;
|
|
56
|
+
whiskerHigh: number;
|
|
57
|
+
boxW: number;
|
|
58
|
+
}
|
|
59
|
+
export interface RegionRow extends ChartExSlice {
|
|
60
|
+
x: number;
|
|
61
|
+
y: number;
|
|
62
|
+
w: number;
|
|
63
|
+
h: number;
|
|
64
|
+
}
|
|
65
|
+
export declare function layoutHistogram(slices: ChartExSlice[], plot: Plot): ColumnBar[];
|
|
66
|
+
export declare function layoutPareto(slices: ChartExSlice[], plot: Plot): ParetoLayout;
|
|
67
|
+
export declare function layoutBoxWhisker(slices: ChartExSlice[], plot: Plot): BoxWhiskerBar[];
|
|
68
|
+
export declare function layoutRegion(slices: ChartExSlice[], plot: Plot): RegionRow[];
|
|
69
|
+
export declare function normalizeChartExSlices(def: ChartDef, opts?: {
|
|
70
|
+
preserveSign?: boolean;
|
|
71
|
+
}): ChartExSlice[];
|
|
72
|
+
/** Slice-and-dice treemap — 足够表达占比结构,编辑预览用。 */
|
|
73
|
+
export declare function layoutTreemap(slices: ChartExSlice[], plot: Plot): TreemapCell[];
|
|
74
|
+
/** 单层 sunburst:内环空心 + 外环扇区(扁平 categories)。 */
|
|
75
|
+
export declare function layoutSunburst(slices: ChartExSlice[], plot: Plot): SunburstArc[];
|
|
76
|
+
export declare function layoutWaterfall(slices: ChartExSlice[], plot: Plot): WaterfallBar[];
|
|
77
|
+
export declare function layoutFunnel(slices: ChartExSlice[], plot: Plot): FunnelSeg[];
|
|
78
|
+
export declare function sunburstArcPath(arc: SunburstArc): string;
|
|
79
|
+
export declare function polygonPath(points: [number, number][]): string;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { BarChartDef, ChartDef, ChartSeries, SurfaceChartDef } from "@sliiu/present-core";
|
|
2
|
+
export interface PlotRect {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
w: number;
|
|
6
|
+
h: number;
|
|
7
|
+
}
|
|
8
|
+
export interface IsoQuad {
|
|
9
|
+
pts: Array<{
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
}>;
|
|
13
|
+
color: string;
|
|
14
|
+
stroke: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** 散点 / 组合图系列的 (x,y) 点:优先 series.points,否则用分类下标 + values。 */
|
|
17
|
+
export declare function seriesXyPoints(def: ChartDef, s: ChartSeries): Array<{
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
z?: number;
|
|
21
|
+
}>;
|
|
22
|
+
export declare function linearFit(xs: number[], ys: number[]): {
|
|
23
|
+
a: number;
|
|
24
|
+
b: number;
|
|
25
|
+
} | null;
|
|
26
|
+
/** Rough advance of `text` at `size` px: CJK glyphs are square, Latin about 0.58em. Legend rows used `length × 6` and overprinted CJK series names. */
|
|
27
|
+
export declare function estimateTextWidth(text: string, size: number): number;
|
|
28
|
+
/**
|
|
29
|
+
* Bottom padding of the plot: room for the category labels (they used to be drawn 14px under
|
|
30
|
+
* the plot into an 8px pad, and the legend was then drawn over them) plus a legend row.
|
|
31
|
+
*/
|
|
32
|
+
export declare function chartPadding(def: ChartDef, textSize: number): {
|
|
33
|
+
bottom: number;
|
|
34
|
+
legend: number;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Geometry shared by the bar renderer and the data-label overlay. Labels used to be placed on
|
|
38
|
+
* the line chart's x positions (i · w/(n−1)), so on a clustered column chart every label sat a
|
|
39
|
+
* bar to the right of its column and clustered labels overprinted each other.
|
|
40
|
+
*/
|
|
41
|
+
export interface BarGeometry {
|
|
42
|
+
isHoriz: boolean;
|
|
43
|
+
stacked: boolean;
|
|
44
|
+
ticks: number[];
|
|
45
|
+
tmin: number;
|
|
46
|
+
tmax: number;
|
|
47
|
+
/** Width (columns) or height (bars) of one category group. */
|
|
48
|
+
groupStep: number;
|
|
49
|
+
/** Width of the cluster inside a group (70 % of the group). */
|
|
50
|
+
inner: number;
|
|
51
|
+
/** Width of one bar in the cluster (the whole cluster when stacked). */
|
|
52
|
+
barW: number;
|
|
53
|
+
/** Per-category totals; used for percent-stacked scaling. */
|
|
54
|
+
totals: number[];
|
|
55
|
+
}
|
|
56
|
+
export declare function barGeometry(def: BarChartDef, plot: PlotRect, sharedTicks?: number[]): BarGeometry;
|
|
57
|
+
export interface BarLabelAnchor {
|
|
58
|
+
x: number;
|
|
59
|
+
y: number;
|
|
60
|
+
anchor: "middle" | "start" | "end";
|
|
61
|
+
/** Where the text sits relative to `y`: above it (bottom baseline), centred on it, or below it (top). */
|
|
62
|
+
baseline: "bottom" | "middle" | "top";
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Where the value label of series `si`, category `ci` goes: just past the free end of a
|
|
66
|
+
* clustered bar (above a column, right of a horizontal bar), or centred in a stacked segment.
|
|
67
|
+
* `stackBefore` is the signed running total of the segments under this one (stacked only).
|
|
68
|
+
*/
|
|
69
|
+
export declare function barLabelAnchor(geo: BarGeometry, plot: PlotRect, si: number, ci: number, v: number, stackBefore?: number): BarLabelAnchor;
|
|
70
|
+
export declare function applyValueAxisScale(yMin: number, yMax: number, def: ChartDef): {
|
|
71
|
+
yMin: number;
|
|
72
|
+
yMax: number;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* 曲面图等距网格:系列 = Y 行,分类 = X 列,values = Z。
|
|
76
|
+
* 单系列时沿 Y 挤一条薄带,避免退化成折线。
|
|
77
|
+
*/
|
|
78
|
+
export declare function surfaceIsoQuads(def: SurfaceChartDef, plot: PlotRect): IsoQuad[];
|
|
79
|
+
export declare function comboXyPlotX(xVal: number, cats: string[], plot: PlotRect, xs: number[]): number;
|
|
80
|
+
export declare function pointLabelText(def: ChartDef, s: ChartSeries, i: number, v: number): string | undefined;
|
|
81
|
+
/** 3D 柱/条预览的挤出偏移(view3D rotX/rotY → 屏幕位移)。 */
|
|
82
|
+
export declare function chart3DOffset(def: ChartDef): {
|
|
83
|
+
dx: number;
|
|
84
|
+
dy: number;
|
|
85
|
+
} | null;
|
|
86
|
+
export interface ChartTextStyle {
|
|
87
|
+
/** Title / data-label colour. */
|
|
88
|
+
text: string;
|
|
89
|
+
/** Axis tick / category / legend label colour. */
|
|
90
|
+
muted: string;
|
|
91
|
+
/** Axis line colour. */
|
|
92
|
+
axis: string;
|
|
93
|
+
/** Gridline colour. */
|
|
94
|
+
grid: string;
|
|
95
|
+
/** Label font size in px (OOXML default 10pt ≈ 13px). */
|
|
96
|
+
size: number;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Chart-wide text and line colours. `def.textColor` / `def.lineColor` (chartSpace txPr, axis spPr)
|
|
100
|
+
* win; otherwise the neutral greys PowerPoint uses on a white chart area. A single text colour
|
|
101
|
+
* gives labels at full strength and ticks / legend at 75% towards the line colour so a dark-theme
|
|
102
|
+
* chart keeps the same hierarchy a light one has.
|
|
103
|
+
*/
|
|
104
|
+
export declare function chartTextStyle(def: Pick<ChartDef, "textColor" | "textSize" | "lineColor">): ChartTextStyle;
|
|
105
|
+
/** Linear mix of two #rrggbb colours; `t` = weight of `b`. */
|
|
106
|
+
export declare function mixHex(a: string, b: string, t: number): string;
|
|
107
|
+
/**
|
|
108
|
+
* "Nice" value-axis ticks: about `count` steps at 1 / 2 / 5 × 10ⁿ. (0..1500 → 0, 500, 1000, 1500;
|
|
109
|
+
* not one line per hundred.)
|
|
110
|
+
*/
|
|
111
|
+
export declare function niceTicks(min: number, max: number, count?: number): number[];
|
|
112
|
+
export declare function shadeHex(color: string, factor: number): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Rect } from "@sliiu/present-core";
|
|
2
|
+
export interface EffectGeom {
|
|
3
|
+
filter: string;
|
|
4
|
+
prLst: string | undefined;
|
|
5
|
+
progress: number;
|
|
6
|
+
bbox: Rect;
|
|
7
|
+
transition?: "in" | "out" | "none";
|
|
8
|
+
}
|
|
9
|
+
export declare function effectClipPathD(geom: EffectGeom): string;
|
|
10
|
+
export declare function effectClipUsesEvenOdd(geom: EffectGeom): boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Slide } from "@sliiu/present-core";
|
|
2
|
+
import type { Scene } from "./scene-node.js";
|
|
3
|
+
/**
|
|
4
|
+
* 放映专用:按当前 timing 把 entrance 目标在 scene 上藏起来(opacity=0 / 段落级 hide)。
|
|
5
|
+
*
|
|
6
|
+
* 编辑器会 `forceVisibleForEdit`,让入场图形在编辑态全部可见;分享 / 导出 / 直播快照
|
|
7
|
+
* 打的是这份数据。播放器必须在这里重算 hidden-until-entrance,不能依赖 shape.opacity。
|
|
8
|
+
*/
|
|
9
|
+
export declare function applyEntranceHideToScene(scene: Scene, slide: Slide): void;
|
|
10
|
+
/**
|
|
11
|
+
* 放映缩略图 / 下一张预览:画出设计稿,而不是「点击前隐藏」的初态。
|
|
12
|
+
*
|
|
13
|
+
* 进入放映时编辑器会把 entrance 目标的 opacity 写回 0。播放舞台要这个初态,
|
|
14
|
+
* 缩略图如果跟着藏,演讲者看到的是空白页。只改 scene,不改 slide 数据。
|
|
15
|
+
*/
|
|
16
|
+
export declare function revealDesignedAppearance(scene: Scene, slide: Slide): void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Font fallback for the browser. OOXML names one typeface per run ("Inter", "Songti SC"); when the
|
|
3
|
+
* machine lacks it PowerPoint substitutes a face of the same class (sans / serif / mono), but a
|
|
4
|
+
* browser given a bare unknown family falls back to its default — usually a serif — so a sans deck
|
|
5
|
+
* comes up in Times. Append the class-matched generic (plus CJK faces so Han glyphs never hit a
|
|
6
|
+
* Latin-only fallback) to every family that is not already a stack.
|
|
7
|
+
*/
|
|
8
|
+
/** `family` as a CSS font-family list with a class-matched generic fallback appended. */
|
|
9
|
+
export declare function withFontFallback(family: string | undefined | null): string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SceneNode } from "./scene-node.js";
|
|
2
|
+
/**
|
|
3
|
+
* 撤销单个 SceneNode 的绘制变换,与 canvas/svg backend 对偶:
|
|
4
|
+
* translate(tx,ty) → rotate around bbox center → scale around center。
|
|
5
|
+
*/
|
|
6
|
+
export declare function inverseSceneNode(n: SceneNode, x: number, y: number): {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
};
|
|
10
|
+
/** 世界坐标 → 该节点未旋转 bbox 空间(含祖先 group 变换)。 */
|
|
11
|
+
export declare function worldToLocal(node: SceneNode, x: number, y: number): {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function hitTestNodeBBox(node: SceneNode, worldX: number, worldY: number): boolean;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Scene } from "./scene-node.js";
|
|
2
|
+
import { SvgBackend } from "./svg-backend.js";
|
|
3
|
+
export interface HybridBackendOptions {
|
|
4
|
+
background?: string;
|
|
5
|
+
interactive?: boolean;
|
|
6
|
+
/** 传给 SVG 段。false 时伸出幻灯片的矢量形状仍画在工作区里。 */
|
|
7
|
+
clipToSlide?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare class HybridBackend {
|
|
10
|
+
readonly host: HTMLElement;
|
|
11
|
+
readonly svg: SvgBackend;
|
|
12
|
+
private wrapper;
|
|
13
|
+
private backends;
|
|
14
|
+
constructor(scene: Scene, container: HTMLElement, opts?: HybridBackendOptions);
|
|
15
|
+
get svgRoot(): SVGSVGElement;
|
|
16
|
+
/** 同步刷新所有子 backend;详见 SvgBackend.flush。 */
|
|
17
|
+
flush(): void;
|
|
18
|
+
/** 等待所有 live 3D(WebGLShapeBackend)首帧就绪——截图 / visual-compare 前调。 */
|
|
19
|
+
waitForReady(): Promise<void>;
|
|
20
|
+
destroy(): void;
|
|
21
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SceneNode } from "./scene-node.js";
|
|
2
|
+
export type HybridSegKind = "canvas" | "svg" | "webgl" | "webglm3d";
|
|
3
|
+
export interface HybridSegment {
|
|
4
|
+
kind: HybridSegKind;
|
|
5
|
+
ids: string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* 按绘制顺序切段。组合不单独成段:非 3D 子形状留在组合被归入的那一类(图片在组合里
|
|
9
|
+
* 仍走 SVG),3D 子形状在它自己的 z 序位置拆成 webgl 段,这样字可以盖在挤出体上面。
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildHybridSegments(children: SceneNode[]): HybridSegment[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export * from "./scene-node.js";
|
|
2
|
+
export { applyEntranceHideToScene, revealDesignedAppearance } from "./entrance-hide.js";
|
|
3
|
+
export * from "./compose.js";
|
|
4
|
+
export * from "./svg-backend.js";
|
|
5
|
+
export * from "./canvas-backend.js";
|
|
6
|
+
export * from "./hybrid-backend.js";
|
|
7
|
+
export { WebGLShapeBackend, type WebGLShapeBackendOptions } from "./webgl-shape-backend.js";
|
|
8
|
+
export { WebGLModel3DBackend, type WebGLModel3DBackendOptions } from "./webgl-model3d-backend.js";
|
|
9
|
+
export { stageChromeBackground } from "./stage-chrome.js";
|
|
10
|
+
export { mountMorphTransitionLayers, type MorphTransitionMount } from "./morph-transition.js";
|
|
11
|
+
export * from "./selection.js";
|
|
12
|
+
export { renderPaint, applyStroke as applySvgStroke } from "./paint-svg.js";
|
|
13
|
+
export { paintToCanvasStyle, applyStroke as applyCanvasStroke, getImage, waitForImagesLoaded } from "./paint-canvas.js";
|
|
14
|
+
export { getVideoPosterFrame, waitForVideoFrames } from "./video-frame.js";
|
|
15
|
+
export { getModel3DPreviewFrame, waitForModel3DFrames } from "./model3d-frame.js";
|
|
16
|
+
export { renderChart } from "./chart-svg.js";
|
|
17
|
+
export { drawChartCanvas } from "./chart-canvas.js";
|
|
18
|
+
export { effectClipPathD, effectClipUsesEvenOdd } from "./effect-clip.js";
|
|
19
|
+
export * from "./text-shared.js";
|
|
20
|
+
export * from "./text-stacked.js";
|
|
21
|
+
export { runLinkAt, hitTestTextRunAt } from "./text-hit.js";
|
|
22
|
+
export { worldToLocal, hitTestNodeBBox, inverseSceneNode } from "./hit-geom.js";
|
|
23
|
+
export { shapeFrontImageSrc } from "./shape-front.js";
|
|
24
|
+
export { warpActive, sampleWarpPath, placeGlyphsOnWarp } from "./text-warp.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** 浏览器无法加载 `file:` 外链图;画带文件名的占位,避免空白碎图。
|
|
2
|
+
* Node 下若本地文件仍在,读成 data URL 仅供预览,**不改 IR 的 src**(否则 round-trip 会丢掉 r:link)。
|
|
3
|
+
*/
|
|
4
|
+
export declare function isFileLinkedSrc(src: string | undefined): boolean;
|
|
5
|
+
export declare function linkedImageLabel(src: string): string;
|
|
6
|
+
export declare function linkedImagePlaceholderDataUri(src: string, w?: number, h?: number): string;
|
|
7
|
+
export declare function displayImageSrc(src: string, w?: number, h?: number): string;
|
|
8
|
+
export declare function drawLinkedImagePlaceholder(ctx: CanvasRenderingContext2D, bbox: {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
w: number;
|
|
12
|
+
h: number;
|
|
13
|
+
}, src: string): void;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const METAFILE_MARKER_SRC: string;
|
|
2
|
+
export declare function isMetafileDataUrl(src: string): boolean;
|
|
3
|
+
/** EMF 签名在偏移 40(" EMF")。可放置 WMF 以 0x9AC6CDD7 开头。 */
|
|
4
|
+
export declare function isMetafileBytes(bytes: Uint8Array, mime?: string): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* 画布该用的地址。
|
|
7
|
+
* 返回空字符串表示图元文件还在转,调用方先留白,完成后再画。
|
|
8
|
+
* 转失败返回虚线占位。普通图片原样返回。
|
|
9
|
+
*/
|
|
10
|
+
export declare function previewImageSrc(src: string, img: HTMLImageElement | undefined, onReady?: () => void): string;
|
|
11
|
+
export declare function waitForMetafilePreviews(): Promise<void>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
import type { Model3DShape } from "@sliiu/present-core";
|
|
3
|
+
export declare function loadGltfScene(src: string): Promise<THREE.Object3D>;
|
|
4
|
+
export declare function applyModel3DCameraPose(cam: THREE.PerspectiveCamera, latDeg: number, lonDeg: number, dist?: number): void;
|
|
5
|
+
export declare function applyModel3DCamera(cam: THREE.PerspectiveCamera, s: Model3DShape): void;
|
|
6
|
+
export declare function applyModel3DTransform(root: THREE.Object3D, s: Model3DShape): void;
|
|
7
|
+
export declare function getModel3DPreviewFrame(s: Model3DShape, onReady?: () => void): HTMLImageElement | null;
|
|
8
|
+
export declare function waitForModel3DFrames(timeoutMs?: number): Promise<void>;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Model3DShape } from "@sliiu/present-core";
|
|
2
|
+
export declare function model3DDisplaySrc(s: Model3DShape, onReady?: () => void): string | undefined;
|
|
3
|
+
export declare function drawModel3DCanvas(ctx: CanvasRenderingContext2D, s: Model3DShape, onReady?: () => void): void;
|
|
4
|
+
export declare function renderModel3DSvg(container: SVGGElement, s: Model3DShape, onReady?: () => void): void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Scene } from "./scene-node.js";
|
|
2
|
+
export interface MorphTransitionMount {
|
|
3
|
+
ghost: HTMLElement;
|
|
4
|
+
target: HTMLElement;
|
|
5
|
+
cleanup(): void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Mount SVG shape layers for morph (FLIP) when the live stage lacks per-shape DOM
|
|
9
|
+
* ids (canvas / hybrid bitmap segments). Pure-SVG stages only need the ghost overlay.
|
|
10
|
+
*/
|
|
11
|
+
export declare function mountMorphTransitionLayers(stageWrap: HTMLElement, stage: HTMLElement, prevScene: Scene, curScene: Scene, opts?: {
|
|
12
|
+
ghostZIndex?: number;
|
|
13
|
+
stageZIndex?: number;
|
|
14
|
+
chromeBg?: string;
|
|
15
|
+
}): MorphTransitionMount;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SceneNode } from "./scene-node.js";
|
|
2
|
+
/** 2D 仿射:x' = a x + c y + e,y' = b x + d y + f。与 SVG / Canvas 的矩阵一致。 */
|
|
3
|
+
export interface Aff {
|
|
4
|
+
a: number;
|
|
5
|
+
b: number;
|
|
6
|
+
c: number;
|
|
7
|
+
d: number;
|
|
8
|
+
e: number;
|
|
9
|
+
f: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function affMul(m: Aff, n: Aff): Aff;
|
|
12
|
+
/** 单个节点的 SVG 变换:先绕 bbox 中心旋转缩放,再平移 tx/ty。 */
|
|
13
|
+
export declare function nodeAffine(node: SceneNode): Aff;
|
|
14
|
+
/** 从最外层祖先乘到自身。幻灯片根是恒等变换,乘进去不改变结果。 */
|
|
15
|
+
export declare function accumulatedAffine(node: SceneNode): Aff;
|
|
16
|
+
/**
|
|
17
|
+
* wrapper 已放在 slide 坐标 (originX, originY)。CSS transform-origin 为 0 0 时,
|
|
18
|
+
* 用这个矩阵才能让视觉位置等于 accumulatedAffine。
|
|
19
|
+
*/
|
|
20
|
+
export declare function cssAffineForBox(m: Aff, originX: number, originY: number): Aff;
|
|
21
|
+
export declare function chainOpacity(node: SceneNode): number;
|
|
22
|
+
export declare function chainHidden(node: SceneNode): boolean;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { OleObjectShape } from "@sliiu/present-core";
|
|
2
|
+
/** Full-bleed package preview (not icon mode). */
|
|
3
|
+
export declare function oleUsesPackagePreview(s: OleObjectShape): boolean;
|
|
4
|
+
/** Canvas / export path: package preview or icon tile + filename. */
|
|
5
|
+
export declare function drawOleCanvas(ctx: CanvasRenderingContext2D, s: OleObjectShape): void;
|
|
6
|
+
/** SVG preview path — package preview via image / PDF embed, else icon placeholder. */
|
|
7
|
+
export declare function renderOleSvg(container: SVGGElement, s: OleObjectShape): void;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Paint, Rect, Stroke } from "@sliiu/present-core";
|
|
2
|
+
export declare function getImage(src: string, onLoad?: () => void): HTMLImageElement;
|
|
3
|
+
/**
|
|
4
|
+
* 等待 imageCache 里所有尚未落定的图片 load/error 完成。
|
|
5
|
+
*
|
|
6
|
+
* 截图 / PDF 导出前必须调用:CanvasBackend(以及 image-paint 填充)只在
|
|
7
|
+
* `img.complete && naturalWidth > 0` 时才 drawImage,否则静默跳过。导出时若不等待图片
|
|
8
|
+
* 解码完成,就会随机丢图——同一份 deck 先后导出 PNG / PDF 结果不一致正是这个原因。
|
|
9
|
+
*
|
|
10
|
+
* 调用前应先让 backend 跑过一次绘制(flush),把所有 src 注册进 imageCache 并开始加载。
|
|
11
|
+
* 每张图带超时兜底,避免坏链 / 慢图把导出永久卡死。
|
|
12
|
+
*/
|
|
13
|
+
export declare function waitForImagesLoaded(timeoutMs?: number): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* shapeHint:承载填充的形状轮廓类别,仅影响 gradFill path="shape"(等值线沿轮廓)
|
|
16
|
+
* 的解释——矩形轮廓走精确的"矩形框带"pattern,其它轮廓退回径向近似。
|
|
17
|
+
*/
|
|
18
|
+
export declare function paintToCanvasStyle(ctx: CanvasRenderingContext2D, paint: Paint | undefined, bbox: Rect, onAsset?: () => void, shapeHint?: "rect" | "ellipse" | "other"): string | CanvasGradient | CanvasPattern;
|
|
19
|
+
export declare function adjustImage(img: HTMLImageElement, adj: import("@sliiu/present-core").ImageColorAdjust): HTMLCanvasElement;
|
|
20
|
+
/** 图片已加载时返回调色后的 data URL,供 SVG `<image href>` 使用。 */
|
|
21
|
+
export declare function rasterizedAdjustHref(src: string, adj: import("@sliiu/present-core").ImageColorAdjust, onLoad?: () => void): string | undefined;
|
|
22
|
+
export declare function applyStroke(ctx: CanvasRenderingContext2D, stroke: Stroke | undefined, bbox: Rect, onAsset?: () => void): boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Paint, Stroke } from "@sliiu/present-core";
|
|
2
|
+
export interface PaintAttrs {
|
|
3
|
+
paint: string;
|
|
4
|
+
opacity?: number;
|
|
5
|
+
defNode?: SVGElement;
|
|
6
|
+
defId?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* shapeHint:承载该填充的形状轮廓类别,仅影响 gradFill path="shape" 的解释
|
|
10
|
+
* (ECMA-376 §20.1.8.30 <a:path path="shape"> = 渐变等值线沿形状轮廓)——
|
|
11
|
+
* 矩形轮廓走精确的"矩形框带"渲染,椭圆等其它轮廓走椭圆 radial 近似。
|
|
12
|
+
*/
|
|
13
|
+
export declare function renderPaint(paint: Paint | undefined, defs: SVGDefsElement, bbox?: {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
w: number;
|
|
17
|
+
h: number;
|
|
18
|
+
}, onAsset?: () => void, shapeHint?: "rect" | "ellipse" | "other"): PaintAttrs;
|
|
19
|
+
export declare function applyStroke(el: SVGGraphicsElement, stroke: Stroke | undefined, defs: SVGDefsElement, idPrefix?: string): void;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { Animatable } from "@sliiu/present-animation";
|
|
2
|
+
import type { ClipState, Paint, Shape, Slide } from "@sliiu/present-core";
|
|
3
|
+
export interface ParaOverride {
|
|
4
|
+
opacity?: number;
|
|
5
|
+
tx?: number;
|
|
6
|
+
ty?: number;
|
|
7
|
+
scale?: number;
|
|
8
|
+
scaleX?: number;
|
|
9
|
+
scaleY?: number;
|
|
10
|
+
rotation?: number;
|
|
11
|
+
visible?: boolean;
|
|
12
|
+
clip?: ClipState;
|
|
13
|
+
fillColor?: string;
|
|
14
|
+
fontColor?: string;
|
|
15
|
+
fontSize?: number;
|
|
16
|
+
fontWeight?: number | string;
|
|
17
|
+
fontStyle?: boolean;
|
|
18
|
+
fontFamily?: string;
|
|
19
|
+
underline?: string;
|
|
20
|
+
}
|
|
21
|
+
/** iterate 子目标上的属性叠在段落动画之上(同名字段以后者为准)。 */
|
|
22
|
+
export declare function mergeParaOverrides(base?: ParaOverride, over?: ParaOverride): ParaOverride | undefined;
|
|
23
|
+
export interface CharRangeOverride extends ParaOverride {
|
|
24
|
+
start: number;
|
|
25
|
+
end: number;
|
|
26
|
+
unit: "char" | "word";
|
|
27
|
+
}
|
|
28
|
+
export type PropertyListener = (key: string, value: unknown, node: SceneNode) => void;
|
|
29
|
+
export declare class SceneNode implements Animatable {
|
|
30
|
+
readonly id: string;
|
|
31
|
+
shape: Shape;
|
|
32
|
+
parent: SceneNode | null;
|
|
33
|
+
children: SceneNode[];
|
|
34
|
+
layerId: string;
|
|
35
|
+
tx: number;
|
|
36
|
+
ty: number;
|
|
37
|
+
scale: number;
|
|
38
|
+
scaleX: number;
|
|
39
|
+
scaleY: number;
|
|
40
|
+
rotation: number;
|
|
41
|
+
/** 动画写入的旋转增量。渲染角 = shape.transform.rotation + animRotation。 */
|
|
42
|
+
animRotation: number;
|
|
43
|
+
opacity: number;
|
|
44
|
+
widthScale: number;
|
|
45
|
+
heightScale: number;
|
|
46
|
+
clip: ClipState | null;
|
|
47
|
+
fillOverride: string | null;
|
|
48
|
+
strokeOverride: string | null;
|
|
49
|
+
strokeWidthOverride: number | null;
|
|
50
|
+
visibleOverride: boolean | null;
|
|
51
|
+
paraOverrides: Map<number, ParaOverride>;
|
|
52
|
+
charOverrides: Map<number, Map<string, CharRangeOverride>>;
|
|
53
|
+
mediaEl: HTMLMediaElement | null;
|
|
54
|
+
private lastMediaAction;
|
|
55
|
+
private listeners;
|
|
56
|
+
constructor(shape: Shape, layerId: string);
|
|
57
|
+
private shapeRotation;
|
|
58
|
+
on(fn: PropertyListener): () => void;
|
|
59
|
+
private fire;
|
|
60
|
+
/**
|
|
61
|
+
* 触发一次 backend redraw 而**不**改变任何节点 / shape 属性。用于离屏光栅 3D 烘焙
|
|
62
|
+
* 把结果写进 shape.meta3D.bakedSrc 副通道后,让 SvgBackend / CanvasBackend 重画读取
|
|
63
|
+
* 新的 bakedSrc(既不污染 shape.src/bbox,也不影响 live WebGL 视图)。
|
|
64
|
+
*/
|
|
65
|
+
markDirty(): void;
|
|
66
|
+
/**
|
|
67
|
+
* 内部用:跳过外部 setProperty 的开关 / 派发逻辑,直接把 opacity 强制设为 v 并
|
|
68
|
+
* 通知 listener。专门给 ParagraphAnimatable / CharRangeAnimatable 在 reveal
|
|
69
|
+
* 文字时同步解除 ancestor group hide 用,避免在每次字符 reveal 都走完整 setProperty
|
|
70
|
+
* switch(性能 + 也避免触发不必要 fire-key 字符串)。
|
|
71
|
+
*/
|
|
72
|
+
forceOpacity(v: number): void;
|
|
73
|
+
setProperty(key: string, value: unknown): void;
|
|
74
|
+
private applyEffectClip;
|
|
75
|
+
getProperty(key: string): unknown;
|
|
76
|
+
walk(fn: (n: SceneNode) => void): void;
|
|
77
|
+
findById(id: string): SceneNode | null;
|
|
78
|
+
resetAnimState(): void;
|
|
79
|
+
setParaProperty(idx: number, key: string, value: unknown): void;
|
|
80
|
+
getParaProperty(idx: number, key: string): unknown;
|
|
81
|
+
setCharRangeProperty(paraIdx: number, unit: "char" | "word", start: number, end: number, key: string, value: unknown): void;
|
|
82
|
+
getCharRangeProperty(paraIdx: number, unit: "char" | "word", start: number, end: number, key: string): unknown;
|
|
83
|
+
}
|
|
84
|
+
export declare function netFlipParity(node: SceneNode): {
|
|
85
|
+
x: number;
|
|
86
|
+
y: number;
|
|
87
|
+
};
|
|
88
|
+
export declare class ParagraphAnimatable implements Animatable {
|
|
89
|
+
readonly node: SceneNode;
|
|
90
|
+
readonly paraIdx: number;
|
|
91
|
+
constructor(node: SceneNode, paraIdx: number);
|
|
92
|
+
setProperty(key: string, value: unknown): void;
|
|
93
|
+
getProperty(key: string): unknown;
|
|
94
|
+
}
|
|
95
|
+
export declare class CharRangeAnimatable implements Animatable {
|
|
96
|
+
readonly node: SceneNode;
|
|
97
|
+
readonly paraIdx: number;
|
|
98
|
+
readonly unit: "char" | "word";
|
|
99
|
+
readonly start: number;
|
|
100
|
+
readonly end: number;
|
|
101
|
+
constructor(node: SceneNode, paraIdx: number, unit: "char" | "word", start: number, end: number);
|
|
102
|
+
setProperty(key: string, value: unknown): void;
|
|
103
|
+
getProperty(key: string): unknown;
|
|
104
|
+
}
|
|
105
|
+
export declare function resolveAnimatable(scene: Scene, id: string): Animatable | null;
|
|
106
|
+
export interface Scene {
|
|
107
|
+
width: number;
|
|
108
|
+
height: number;
|
|
109
|
+
background?: Shape | null;
|
|
110
|
+
slide: Slide;
|
|
111
|
+
layerNodes: Map<string, SceneNode[]>;
|
|
112
|
+
root: SceneNode;
|
|
113
|
+
}
|
|
114
|
+
export interface CreateSceneOptions {
|
|
115
|
+
masters?: import("@sliiu/present-core").SlideMaster[];
|
|
116
|
+
}
|
|
117
|
+
export declare function createScene(slide: Slide, size: {
|
|
118
|
+
width: number;
|
|
119
|
+
height: number;
|
|
120
|
+
}, options?: CreateSceneOptions): Scene;
|
|
121
|
+
/** `useBgFill`:用幻灯片合成背景填形状,坐标系对齐整页而不是 shape bbox。 */
|
|
122
|
+
export declare function shapeRenderFill(s: Shape, scene: Scene, node?: SceneNode): Paint | undefined;
|
|
123
|
+
export declare function shapeRenderFillBBox(s: Shape, scene: Scene, node?: SceneNode): {
|
|
124
|
+
x: number;
|
|
125
|
+
y: number;
|
|
126
|
+
w: number;
|
|
127
|
+
h: number;
|
|
128
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Rect } from "@sliiu/present-core";
|
|
2
|
+
import type { Scene, SceneNode } from "./scene-node.js";
|
|
3
|
+
export interface HitOptions {
|
|
4
|
+
ignoreLocked?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare class Selection {
|
|
7
|
+
private ids;
|
|
8
|
+
private listeners;
|
|
9
|
+
get(): string[];
|
|
10
|
+
has(id: string): boolean;
|
|
11
|
+
set(ids: string[]): void;
|
|
12
|
+
add(id: string): void;
|
|
13
|
+
remove(id: string): void;
|
|
14
|
+
toggle(id: string): void;
|
|
15
|
+
clear(): void;
|
|
16
|
+
on(fn: (ids: Set<string>) => void): () => void;
|
|
17
|
+
private fire;
|
|
18
|
+
}
|
|
19
|
+
export declare function nodeWorldBBox(node: SceneNode): Rect;
|
|
20
|
+
export declare function hitTest(scene: Scene, x: number, y: number, opts?: HitOptions): SceneNode | null;
|
|
21
|
+
export declare function pointInNode(node: SceneNode, x: number, y: number): boolean;
|
|
22
|
+
export declare function attachPointerSelection(hostEl: HTMLElement, scene: Scene, selection: Selection): () => void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { GlowEffect, ReflectionEffect, ShadowEffect, Shape, SoftEdgeEffect } from "@sliiu/present-core";
|
|
2
|
+
export interface CollectedShapeEffects {
|
|
3
|
+
outer: ShadowEffect[];
|
|
4
|
+
glow: GlowEffect[];
|
|
5
|
+
inner?: ShadowEffect;
|
|
6
|
+
softEdge?: SoftEdgeEffect;
|
|
7
|
+
reflection?: ReflectionEffect;
|
|
8
|
+
}
|
|
9
|
+
export declare function collectShapeEffects(s: Shape): CollectedShapeEffects;
|
|
10
|
+
export declare function hasAnyEffect(fx: CollectedShapeEffects): boolean;
|
|
11
|
+
export declare function effectHexWithAlpha(color: string, alpha: number): string;
|
|
12
|
+
/** outer shadow + glow 的 CSS filter 链(SVG style.filter / Canvas ctx.filter 通用)。 */
|
|
13
|
+
export declare function cssFilterForEffects(fx: CollectedShapeEffects): string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Slide } from "@sliiu/present-core";
|
|
2
|
+
/**
|
|
3
|
+
* CSS background for the stage / hybrid wrapper chrome around the scene.
|
|
4
|
+
* When the slide has a painted background, createScene injects a full-slide
|
|
5
|
+
* __bg_* shape — a second opaque underlay would show through image alpha or
|
|
6
|
+
* mask gradient edges. Use white only when the slide has no background paint.
|
|
7
|
+
*/
|
|
8
|
+
export declare function stageChromeBackground(slide?: Slide): string;
|