@vvfx/svg2ir 0.0.0-stage → 0.0.1-beta.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.
- package/LICENSE +22 -0
- package/README.md +179 -2
- package/dist/common/errors.d.ts +33 -0
- package/dist/common/types.d.ts +89 -0
- package/dist/convert.d.ts +19 -0
- package/dist/debug.d.ts +8 -0
- package/dist/helper.d.ts +5 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +16013 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +16008 -0
- package/dist/index.mjs.map +1 -0
- package/dist/node.d.ts +1 -0
- package/dist/node.js +16030 -0
- package/dist/node.js.map +1 -0
- package/dist/node.mjs +16025 -0
- package/dist/node.mjs.map +1 -0
- package/dist/parse-svg/bridge.d.ts +10 -0
- package/dist/parse-svg/node.d.ts +3 -0
- package/dist/parse-svg/read-presentation-attribute.d.ts +5 -0
- package/dist/parse-svg/svg-parser.d.ts +46 -0
- package/dist/svg-preserved-data.d.ts +78 -0
- package/dist/svg2ge-adapter/assemble.d.ts +5 -0
- package/dist/svg2ge-adapter/convert.d.ts +5 -0
- package/dist/svg2ge-adapter/converter/animation.d.ts +10 -0
- package/dist/svg2ge-adapter/converter/data-path.d.ts +6 -0
- package/dist/svg2ge-adapter/normalize-shape-animation.d.ts +2 -0
- package/dist/svg2ge-adapter/post-process/apply-fonts.d.ts +6 -0
- package/dist/svg2ge-adapter/post-process/apply-shape-geometry-animation.d.ts +4 -0
- package/dist/svg2ge-adapter/post-process/apply-shape-paint-animation.d.ts +4 -0
- package/dist/svg2ge-adapter/post-process/paint-animation-sampling.d.ts +13 -0
- package/dist/svg2ge-adapter/post-process/restore-gradient-uv.d.ts +3 -0
- package/dist/svg2ge-adapter/post-process/rewrite-text-components.d.ts +13 -0
- package/dist/svg2ge-adapter/pre-process.d.ts +7 -0
- package/dist/svg2ge-adapter/types.d.ts +11 -0
- package/dist/svg2ir/assemble.d.ts +9 -0
- package/dist/svg2ir/convert-arc.d.ts +10 -0
- package/dist/svg2ir/convert.d.ts +21 -0
- package/dist/svg2ir/converter/clip/apply-mask.d.ts +4 -0
- package/dist/svg2ir/converter/clip/build-clip-mask.d.ts +35 -0
- package/dist/svg2ir/converter/clip/collect-geometry.d.ts +32 -0
- package/dist/svg2ir/converter/clip/warn-unsupported.d.ts +7 -0
- package/dist/svg2ir/converter/diagnostics/collect-warnings.d.ts +6 -0
- package/dist/svg2ir/converter/diagnostics/inspect-filter.d.ts +4 -0
- package/dist/svg2ir/converter/diagnostics/warn-unsupported.d.ts +8 -0
- package/dist/svg2ir/converter/image/parse-image.d.ts +14 -0
- package/dist/svg2ir/converter/layers/build-layers.d.ts +8 -0
- package/dist/svg2ir/converter/layers/conversion-session.d.ts +161 -0
- package/dist/svg2ir/converter/layers/convert-group-element.d.ts +3 -0
- package/dist/svg2ir/converter/layers/convert-image-element.d.ts +3 -0
- package/dist/svg2ir/converter/layers/convert-shape-element.d.ts +3 -0
- package/dist/svg2ir/converter/layers/convert-text-element.d.ts +3 -0
- package/dist/svg2ir/converter/layers/convert-use-element.d.ts +3 -0
- package/dist/svg2ir/converter/layers/element-categories.d.ts +2 -0
- package/dist/svg2ir/converter/layers/registry.d.ts +4 -0
- package/dist/svg2ir/converter/paint/resolve-gradient.d.ts +29 -0
- package/dist/svg2ir/converter/shape/convert-annulus.d.ts +10 -0
- package/dist/svg2ir/converter/shape/parse-dash.d.ts +23 -0
- package/dist/svg2ir/converter/shape/parse-shape-element.d.ts +4 -0
- package/dist/svg2ir/converter/shape/parse-shape-primitives.d.ts +15 -0
- package/dist/svg2ir/converter/smil/apply-opacity-composition.d.ts +6 -0
- package/dist/svg2ir/converter/smil/apply-transform-animation.d.ts +14 -0
- package/dist/svg2ir/converter/smil/apply-transform-composition.d.ts +4 -0
- package/dist/svg2ir/converter/smil/build-keyframes.d.ts +10 -0
- package/dist/svg2ir/converter/smil/collect-geometry-animation.d.ts +7 -0
- package/dist/svg2ir/converter/smil/inspect-animation.d.ts +6 -0
- package/dist/svg2ir/converter/smil/parse-motion.d.ts +4 -0
- package/dist/svg2ir/converter/smil/parse-paint-animation.d.ts +13 -0
- package/dist/svg2ir/converter/smil/parse-shape-animation.d.ts +4 -0
- package/dist/svg2ir/converter/smil/parse-timeline.d.ts +4 -0
- package/dist/svg2ir/converter/smil/resolve-animation-target.d.ts +4 -0
- package/dist/svg2ir/converter/smil/sample-composition-frames.d.ts +42 -0
- package/dist/svg2ir/converter/smil/scan-duration.d.ts +4 -0
- package/dist/svg2ir/converter/smil/timeline-schedule.d.ts +17 -0
- package/dist/svg2ir/converter/smil/timeline-values.d.ts +20 -0
- package/dist/svg2ir/converter/smil/types.d.ts +129 -0
- package/dist/svg2ir/converter/switch-branch.d.ts +3 -0
- package/dist/svg2ir/converter/text/build-per-line-text-layers.d.ts +11 -0
- package/dist/svg2ir/converter/text/build-single-text-layer.d.ts +11 -0
- package/dist/svg2ir/converter/text/build-split-text-layers.d.ts +11 -0
- package/dist/svg2ir/converter/text/build-vertical-text-layers.d.ts +10 -0
- package/dist/svg2ir/converter/text/font-metrics.d.ts +53 -0
- package/dist/svg2ir/converter/text/inspect-content.d.ts +42 -0
- package/dist/svg2ir/converter/text/parse.d.ts +10 -0
- package/dist/svg2ir/converter/text/text-layout.d.ts +29 -0
- package/dist/svg2ir/converter/transform/build-transform.d.ts +15 -0
- package/dist/svg2ir/converter/use/collect-group-use-instances.d.ts +16 -0
- package/dist/svg2ir/converter/use/expand-use.d.ts +31 -0
- package/dist/svg2ir/css-named-colors.d.ts +1 -0
- package/dist/svg2ir/index.d.ts +2 -0
- package/dist/svg2ir/map-color.d.ts +3 -0
- package/dist/svg2ir/matrix.d.ts +67 -0
- package/dist/svg2ir/normalize-path.d.ts +52 -0
- package/dist/svg2ir/read-attributes.d.ts +12 -0
- package/dist/svg2layers-adapter/assemble.d.ts +8 -0
- package/dist/svg2layers-adapter/convert.d.ts +4 -0
- package/dist/svg2layers-adapter/converter/diagnostics/collect-warnings.d.ts +10 -0
- package/dist/svg2layers-adapter/converter/image/convert-image-layer.d.ts +5 -0
- package/dist/svg2layers-adapter/converter/layers/build-layers.d.ts +3 -0
- package/dist/svg2layers-adapter/converter/layers/conversion-session.d.ts +14 -0
- package/dist/svg2layers-adapter/converter/layers/registry.d.ts +9 -0
- package/dist/svg2layers-adapter/converter/layers/resolve-visual-state.d.ts +4 -0
- package/dist/svg2layers-adapter/converter/text/convert-text-layer.d.ts +5 -0
- package/dist/svg2layers-adapter/converter/text/parse-text-runs.d.ts +11 -0
- package/dist/svg2layers-adapter/converter/text/text-layout.d.ts +9 -0
- package/dist/svg2layers-adapter/converter/transform/build-transform.d.ts +8 -0
- package/dist/svg2layers-adapter/matrix.d.ts +16 -0
- package/dist/svg2layers-adapter/post-process/inline-image-resources.d.ts +3 -0
- package/dist/svg2layers-adapter/types.d.ts +61 -0
- package/package.json +61 -3
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
2
|
+
import { type SVGConversionSession } from './conversion-session';
|
|
3
|
+
export type SVGElementConverter = (element: Element) => void;
|
|
4
|
+
export declare function createSVGElementConverterRegistry(session: SVGConversionSession): ReadonlyMap<string, SVGElementConverter>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG 渐变 paint 解析 → IRGradientPaint。
|
|
3
|
+
*
|
|
4
|
+
* 支持 linearGradient 的 userSpaceOnUse/objectBoundingBox。radialGradient 因 IR 仅有
|
|
5
|
+
* gradientStart/End,使用水平直径近似;gradientTransform 只处理可稳定映射的子集。
|
|
6
|
+
*
|
|
7
|
+
* 坐标(IR gradient 使用归一化 UV 空间):效果运行时 shape 片元着色器用 uv0(顶点位置按 shape bbox
|
|
8
|
+
* 归一化到 0-1)比对 _StartPoint/_EndPoint。故渐变起止点必须是相对 shape bbox 的 0-1 UV,
|
|
9
|
+
* 不是 world-local 单位。这里把 userSpaceOnUse / objectBoundingBox 坐标统一转成 UV 存进 IR;
|
|
10
|
+
* GE 适配阶段再将这些 UV 坐标映射到运行时渐变参数。
|
|
11
|
+
*/
|
|
12
|
+
import type EditableSVG from '../../../parse-svg/svg-parser';
|
|
13
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
14
|
+
import type { IRColor, IRGradientPaint } from '@vvfx/animation-ir';
|
|
15
|
+
export interface ShapeBBox {
|
|
16
|
+
minX: number;
|
|
17
|
+
minY: number;
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
}
|
|
21
|
+
/** 从渐变取 t=0.5 的颜色,作为文本 fill=url(#渐变) 的降级纯色。
|
|
22
|
+
* 返回归一化 [r,g,b,a] 或 null(目标不是渐变/未找到)。
|
|
23
|
+
*/
|
|
24
|
+
export declare function getGradientMidpointColor(es: EditableSVG, raw: string | number | null | undefined, opacity?: number): IRColor | null;
|
|
25
|
+
/** 尝试把 fill/stroke 属性值解析为渐变 paint;非 url(#id) 返回 null。 */
|
|
26
|
+
export declare function resolveGradientPaint(es: EditableSVG, raw: string | number | null | undefined, opacity: number, bbox: ShapeBBox): IRGradientPaint | null;
|
|
27
|
+
/** IR 当前仅表达 pad 渐变语义;repeat 和 reflect 没有对应的 shader 参数,因此保持未映射并报告 warning。 */
|
|
28
|
+
/** 读取渐变 stop 的 alpha 值。 */
|
|
29
|
+
export declare function gradientStopColorAlpha(el: Element, rawPaint: string): number[];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type EditableSVG from '../../../parse-svg/svg-parser';
|
|
2
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
3
|
+
import type { IRShape, IREllipseShape } from '@vvfx/animation-ir';
|
|
4
|
+
/**
|
|
5
|
+
* 将精确的 SVG 环形结构 `outer-circle + inner-circle` 转换为椭圆中心线和描边。
|
|
6
|
+
*
|
|
7
|
+
* 该判断比通用嵌套轮廓转换更严格:渐变填充、paint 动画、非圆形路径和任意圆角图形
|
|
8
|
+
* 继续使用 custom path,避免改变这些 SVG 的填充语义。
|
|
9
|
+
*/
|
|
10
|
+
export declare function convertCircularAnnulusToEllipseStroke(es: EditableSVG, el: Element, shape: IRShape): IREllipseShape | null;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG stroke-dasharray 到 IR open subpath 的转换。
|
|
3
|
+
*
|
|
4
|
+
* 该模块只处理虚线判断和几何切分,不负责普通 shape 的解析或样式组装。
|
|
5
|
+
*/
|
|
6
|
+
import type EditableSVG from '../../../parse-svg/svg-parser';
|
|
7
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
8
|
+
import type { IRBezierPath, IRShapeStroke, IRShapeStyle } from '@vvfx/animation-ir';
|
|
9
|
+
type IRShapePaint = NonNullable<IRShapeStyle['fills']>[number];
|
|
10
|
+
/** 解析 stroke-dasharray / stroke-dashoffset → { dash(偶数长), offset∈[0,patternLen), patternLen }。null=无有效虚线。
|
|
11
|
+
* SVG spec:dash 奇数个时复制一遍(e.g. "7" → "7 7");偶索引是 on(实)、奇索引是 off(虚)。 */
|
|
12
|
+
export declare function parseDashArray(es: EditableSVG, el: Element): {
|
|
13
|
+
dash: number[];
|
|
14
|
+
offset: number;
|
|
15
|
+
patternLen: number;
|
|
16
|
+
} | null;
|
|
17
|
+
/** 共享虚线合成判断,并决定是否生成对应 warning。
|
|
18
|
+
* 合成 ROI:有虚线描边、无 fill、无 0 长度 on-dash、所有 subpath 全直线(切线恒 {0,0})且 open。任一不满足返 false。 */
|
|
19
|
+
export declare function canSynthesizeDash(es: EditableSVG, el: Element, fills: IRShapePaint[], strokes: IRShapeStroke[], strokeWidth: number | undefined, customPaths: IRBezierPath[] | undefined): boolean;
|
|
20
|
+
/** 把直线 open subpath 按虚线 on-区间切成多条 open 子路径(绝对 SVG 坐标,之后照常 -cx/-cy 转相对)。
|
|
21
|
+
* SVG dash 跨顶点连续:一个跨顶点的 on-dash 是一条横跨该顶点的段(join 在此渲,只在 dash 自身端点渲 cap)。 */
|
|
22
|
+
export declare function synthesizeDashSubpaths(paths: IRBezierPath[], dash: number[], offset: number, patternLen: number): IRBezierPath[];
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 将 SVG 基本形状元素解析为 IRShape。
|
|
3
|
+
*
|
|
4
|
+
* 支持 rect、circle、ellipse、line、polygon、polyline 和 path;坐标使用 SVG 设计像素。
|
|
5
|
+
*/
|
|
6
|
+
import type EditableSVG from '../../../parse-svg/svg-parser';
|
|
7
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
8
|
+
import type { IRCustomShape, IREllipseShape, IRRectangleShape } from '@vvfx/animation-ir';
|
|
9
|
+
/** 读 borderRadius 风格字段:返 number 或 undefined(解析底座数值属性返 number)。 */
|
|
10
|
+
/** SVG <rect x y width height rx ry> → IRRectangleShape。 */
|
|
11
|
+
export declare function parseRect(es: EditableSVG, el: Element): IRRectangleShape;
|
|
12
|
+
/** SVG <circle cx cy r> / <ellipse cx cy rx ry> → IREllipseShape。 */
|
|
13
|
+
export declare function parseEllipse(es: EditableSVG, el: Element, isCircle: boolean): IREllipseShape;
|
|
14
|
+
/** SVG <path d> / <polygon points> / <polyline points> / <line x1 y1 x2 y2> → IRCustomShape。 */
|
|
15
|
+
export declare function parseCustomPath(es: EditableSVG, el: Element, kind: 'path' | 'polygon' | 'polyline' | 'line'): IRCustomShape | null;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { IRTransform } from '@vvfx/animation-ir';
|
|
2
|
+
import { type BeginTimeCache, type SMILAnimation, type TransformStage } from './types';
|
|
3
|
+
export declare function readStaticOpacity(node: globalThis.Element): number;
|
|
4
|
+
export declare function readStaticVisibility(node: globalThis.Element): number;
|
|
5
|
+
export declare function collectOpacityAnimations(stage: TransformStage, root: globalThis.Element, beginCache: BeginTimeCache, comparisonDuration?: number): SMILAnimation[];
|
|
6
|
+
export declare function applySampledOpacityComposition(stages: TransformStage[], animationsByStage: SMILAnimation[][], transform: IRTransform, frameRate: number): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { IRTransform } from '@vvfx/animation-ir';
|
|
2
|
+
import { type TransformContext } from './types';
|
|
3
|
+
export declare function applySMILToTransform(el: {
|
|
4
|
+
node?: globalThis.Element | null;
|
|
5
|
+
}, transform: IRTransform, outDuration: {
|
|
6
|
+
value: number;
|
|
7
|
+
}, frameRate: number, context: TransformContext): void;
|
|
8
|
+
export declare function applySMILToTransformWithOuter(innerEl: {
|
|
9
|
+
node?: globalThis.Element | null;
|
|
10
|
+
}, outerEl: {
|
|
11
|
+
node?: globalThis.Element | null;
|
|
12
|
+
}, transform: IRTransform, outDuration: {
|
|
13
|
+
value: number;
|
|
14
|
+
}, frameRate: number, innerContext: TransformContext, outerContext: TransformContext): void;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IRTransform } from '@vvfx/animation-ir';
|
|
2
|
+
import { type SVGMatrix } from '../../matrix';
|
|
3
|
+
import { type TransformContext, type TransformStage } from './types';
|
|
4
|
+
export declare function applySampledTransformComposition(stages: TransformStage[], baseMatrix: SVGMatrix, transform: IRTransform, frameRate: number, context: TransformContext): void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IRAnimatedProperty, IRKeyframe, IRPropertyValue, IRVec3 } from '@vvfx/animation-ir';
|
|
2
|
+
import { type SVGMatrix } from '../../matrix';
|
|
3
|
+
import { type SMILAnimation } from './types';
|
|
4
|
+
export declare function makeKeyframes<T extends IRPropertyValue>(animation: SMILAnimation, frameRate: number, mapValue: (value: number[], index: number) => T, baseValue?: T): IRKeyframe<T>[];
|
|
5
|
+
export declare function matrixForTransformValue(type: string, value: number[]): SVGMatrix;
|
|
6
|
+
export declare function applyRotateSpatialTangents(animation: SMILAnimation, keyframes: IRKeyframe<IRVec3>[], baseMatrix: SVGMatrix, localCenter: [number, number]): void;
|
|
7
|
+
export declare function staticValue<T extends number | IRVec3>(property: IRAnimatedProperty<T> | undefined, fallback: T): T;
|
|
8
|
+
export declare function subdivideFullTurn(animation: SMILAnimation): SMILAnimation;
|
|
9
|
+
export declare function unwrapRotationValues(animation: SMILAnimation, matrices: SVGMatrix[]): number[];
|
|
10
|
+
export declare function sampleAnimationValue(animation: SMILAnimation, time: number): number[] | null;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type BeginTimeCache, type GeometryAnimation, type TransformContext, type TransformStage } from './types';
|
|
2
|
+
declare const LINE_ATTRIBUTES: readonly ["x1", "y1", "x2", "y2"];
|
|
3
|
+
type LineAttribute = typeof LINE_ATTRIBUTES[number];
|
|
4
|
+
export declare function isLineGeometryAttribute(attributeName: string): attributeName is LineAttribute;
|
|
5
|
+
export declare function canConvertLineGeometryAnimations(target: globalThis.Element, root: globalThis.Element): boolean;
|
|
6
|
+
export declare function collectGeometryAnimation(stage: TransformStage, root: globalThis.Element, beginCache: BeginTimeCache, context: TransformContext): GeometryAnimation | null;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
2
|
+
export declare function isMappedSMILAnimationElement(el: Element, tag: string): boolean;
|
|
3
|
+
/** 判断元素或祖先是否存在 opacity 动画。 */
|
|
4
|
+
export declare function hasDirectOpacityAnimation(node: globalThis.Element | null | undefined): boolean;
|
|
5
|
+
export declare function hasAnimatedVisibility(el: Element): boolean;
|
|
6
|
+
export declare function hasAnimatedAncestorOpacity(el: Element): boolean;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SVGMatrix } from '../../matrix';
|
|
2
|
+
import { type BeginTimeCache, type MotionAnimation } from './types';
|
|
3
|
+
export declare function parseMotionAnimation(tag: globalThis.Element, root: globalThis.Element, beginCache: BeginTimeCache, comparisonDuration?: number): MotionAnimation | null;
|
|
4
|
+
export declare function motionMatrixAtTime(animation: MotionAnimation, time: number): SVGMatrix | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SVGPreservedPaintAnimation } from '../../../svg-preserved-data';
|
|
2
|
+
export declare function parseSMILPaintAnimations(el: {
|
|
3
|
+
node?: globalThis.Element | null;
|
|
4
|
+
}, frameRate: number, comparisonDuration: number, baseOpacity: {
|
|
5
|
+
fill: number;
|
|
6
|
+
stroke: number;
|
|
7
|
+
}, alphaBase: {
|
|
8
|
+
fill: number;
|
|
9
|
+
stroke: number;
|
|
10
|
+
}, paintSources: {
|
|
11
|
+
fill?: string;
|
|
12
|
+
stroke?: string;
|
|
13
|
+
}, baseStrokeWidth?: number): SVGPreservedPaintAnimation[];
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IRShape } from '@vvfx/animation-ir';
|
|
2
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
3
|
+
import type { SVGPreservedShapeAnimation } from '../../../svg-preserved-data';
|
|
4
|
+
export declare function parseShapeGeometryAnimation(el: Element, shape: IRShape, comparisonDuration: number): SVGPreservedShapeAnimation | undefined;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { BeginTimeCache, SMILAnimation, SMILValueParser } from './types';
|
|
2
|
+
export { cubicBezierRatio, interpolateValues, parseColorValue, parseNumberList, parsePointValue, parseKeySplines, parseValue, sampleExpandedValue, splitCubicAtRatio, valuesEqual, } from './timeline-values';
|
|
3
|
+
export { activeDuration, comparisonEnd, findAnimationById, parseClockValue, resolveBegin, resolveBeginTimes, } from './timeline-schedule';
|
|
4
|
+
export declare function parseSMILTag(tag: globalThis.Element, root: globalThis.Element, beginCache: BeginTimeCache, comparisonDuration?: number, valueParser?: SMILValueParser, underlyingValue?: number[]): SMILAnimation | null;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Resolve the element animated by a direct or href-targeted SMIL element. */
|
|
2
|
+
export declare function resolveSMILAnimationTarget(animation: globalThis.Element, root: globalThis.Element): globalThis.Element | null;
|
|
3
|
+
/** Collect direct and href-targeted SMIL elements for one SVG element in document order. */
|
|
4
|
+
export declare function collectSMILAnimationElements(target: globalThis.Element, root: globalThis.Element, tags?: ReadonlySet<string>): globalThis.Element[];
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 单个图层烘焙组合变换时的采样点上限。
|
|
3
|
+
*
|
|
4
|
+
* 组合变换只能栅格化,采样密度直接决定 IR 与 GE 的体积:长时间线会转出上百 MB
|
|
5
|
+
* 场景数据,Effects 解析时锁死主线程。与 COMPOSITION_SAMPLE_STEP 共同决定切换点,
|
|
6
|
+
* 1024 点约合 256 帧(30fps 下 8.5 秒)之后转入误差驱动细分。
|
|
7
|
+
*/
|
|
8
|
+
export declare const MAX_COMPOSITION_SAMPLES = 1024;
|
|
9
|
+
/** 烘焙组合变换的基准采样间隔(帧)。 */
|
|
10
|
+
export declare const COMPOSITION_SAMPLE_STEP = 0.25;
|
|
11
|
+
export interface CompositionFrameSample<T> {
|
|
12
|
+
frame: number;
|
|
13
|
+
value: T;
|
|
14
|
+
}
|
|
15
|
+
export interface CompositionFrameSamplingOptions<T> {
|
|
16
|
+
/** 时间线末帧。 */
|
|
17
|
+
endFrame: number;
|
|
18
|
+
/** 承载语义、必须保留的时刻:源关键帧、区间边界、动画起止。 */
|
|
19
|
+
anchorFrames: number[];
|
|
20
|
+
/** 瞬时跳变时刻。跨越它的区间不参与细分,否则误差必然超限并耗尽预算。 */
|
|
21
|
+
jumpFrames?: number[];
|
|
22
|
+
/** 求指定帧的组合值。 */
|
|
23
|
+
evaluate: (frame: number) => T;
|
|
24
|
+
/** 把值对齐到左邻所在分支,例如角度跨过 ±180° 时补整圈。 */
|
|
25
|
+
unwrapForMeasure?: (value: T, left: T) => T;
|
|
26
|
+
/** 相对线性插值的误差,1 表示刚好达到容忍度;t 为区间内的归一化位置。 */
|
|
27
|
+
normalizeError: (value: T, left: T, right: T, t: number) => number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 组合变换的采样入口。
|
|
31
|
+
*
|
|
32
|
+
* 均匀网格装得进预算时照常铺网;超出预算时按误差细分,保留全部锚点,只加密
|
|
33
|
+
* 线性插值误差超限的区间。
|
|
34
|
+
*/
|
|
35
|
+
export declare function sampleCompositionFrames<T>(options: CompositionFrameSamplingOptions<T>): CompositionFrameSample<T>[];
|
|
36
|
+
/**
|
|
37
|
+
* 在锚点之间按误差细分。
|
|
38
|
+
*
|
|
39
|
+
* 锚点全部保留;只有相对两端线性插值的误差超限时才继续二分,因此线性区间不会
|
|
40
|
+
* 增加采样点,而曲线路径(如绕远端支点旋转的圆心轨迹)会被检测到。
|
|
41
|
+
*/
|
|
42
|
+
export declare function refineCompositionFrames<T>(options: CompositionFrameSamplingOptions<T>): CompositionFrameSample<T>[];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMIL begin/end、repeat 和 syncbase 时间调度。
|
|
3
|
+
*
|
|
4
|
+
* 本模块不负责动画值插值,只负责确定动画何时开始、结束以及哪些 interval 需要展开。
|
|
5
|
+
*/
|
|
6
|
+
import { type BeginTimeCache } from './types';
|
|
7
|
+
export declare function parseClockValue(raw: string): number | null;
|
|
8
|
+
export declare function activeDuration(tag: globalThis.Element): number;
|
|
9
|
+
export declare function findAnimationById(root: globalThis.Element, id: string): globalThis.Element | null;
|
|
10
|
+
export declare function getBeginTimeCache(root: globalThis.Element, comparisonDuration?: number): BeginTimeCache;
|
|
11
|
+
export declare function resolveBeginTimes(tag: globalThis.Element, root: globalThis.Element, cache: BeginTimeCache, comparisonDuration?: number): number[];
|
|
12
|
+
export declare function resolveBegin(tag: globalThis.Element, root: globalThis.Element, cache: BeginTimeCache): number | null;
|
|
13
|
+
export declare function comparisonEnd(tag: globalThis.Element, begin: number): number;
|
|
14
|
+
export declare function buildAnimationWindows(tag: globalThis.Element, beginTimes: number[], totalDuration: number, comparisonDuration?: number): Array<{
|
|
15
|
+
begin: number;
|
|
16
|
+
end: number;
|
|
17
|
+
}>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { IRBezierHandle } from '@vvfx/animation-ir';
|
|
2
|
+
import { type SMILAnimation, type SMILSample, type SMILValueParser } from './types';
|
|
3
|
+
export declare function parseNumberList(value: string): number[];
|
|
4
|
+
export declare function parseValue(value: string, type: string): number[];
|
|
5
|
+
export declare function parseColorValue(value: string): number[] | null;
|
|
6
|
+
export declare function parsePointValue(value: string): [number, number];
|
|
7
|
+
export declare function parseKeySplines(tag: globalThis.Element, segmentCount: number): IRBezierHandle[][];
|
|
8
|
+
/** 根据相邻值的数值距离计算 paced 动画的时间节点,忽略 authored keyTimes。 */
|
|
9
|
+
export declare function parsePacedKeyTimes(values: number[][]): number[];
|
|
10
|
+
export declare function parseValues(tag: globalThis.Element, type: string, valueParser?: SMILValueParser, underlyingValue?: number[]): number[][];
|
|
11
|
+
export declare function valuesEqual(a: number[], b: number[]): boolean;
|
|
12
|
+
export declare function interpolateValues(from: number[], to: number[], ratio: number): number[];
|
|
13
|
+
export declare function cubicBezierRatio(ratio: number, handles: IRBezierHandle[]): number;
|
|
14
|
+
export declare function splitCubicAtRatio(ratio: number, handles: IRBezierHandle[]): {
|
|
15
|
+
out: IRBezierHandle;
|
|
16
|
+
in: IRBezierHandle;
|
|
17
|
+
};
|
|
18
|
+
export declare function sampleExpandedValue(samples: SMILSample[], time: number, calcMode: SMILAnimation['calcMode'], keySplines: IRBezierHandle[][]): SMILSample | null;
|
|
19
|
+
export declare function clipSamplesToComparisonWindow(samples: SMILSample[], end: number, calcMode: SMILAnimation['calcMode'], keySplines: IRBezierHandle[][], fill: SMILAnimation['fill']): SMILSample[];
|
|
20
|
+
export declare function expandSamples(values: number[][], keyTimes: number[], begin: number, duration: number, totalDuration: number, accumulate: boolean, calcMode?: SMILAnimation['calcMode'], keySplines?: IRBezierHandle[][]): SMILSample[];
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { IRAnimatedProperty, IRBezierHandle, IRVec3 } from '@vvfx/animation-ir';
|
|
2
|
+
import type { SVGMatrix } from '../../matrix';
|
|
3
|
+
export interface SMILSample {
|
|
4
|
+
time: number;
|
|
5
|
+
value: number[];
|
|
6
|
+
cycle: number;
|
|
7
|
+
sourceIndex: number;
|
|
8
|
+
/**
|
|
9
|
+
* fractional active interval 结束位置的合成样本 metadata。
|
|
10
|
+
* 该值已经按 authored simple-time 计算,不能作为普通 keyframe 再次应用 spline 缓动。
|
|
11
|
+
*/
|
|
12
|
+
activeEndSegment?: {
|
|
13
|
+
cycleStartTime: number;
|
|
14
|
+
segmentIndex: number;
|
|
15
|
+
startTime: number;
|
|
16
|
+
endTime: number;
|
|
17
|
+
startValue: number[];
|
|
18
|
+
endValue: number[];
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export interface SMILInterval {
|
|
22
|
+
begin: number;
|
|
23
|
+
end: number;
|
|
24
|
+
sampleStart: number;
|
|
25
|
+
sampleEnd: number;
|
|
26
|
+
}
|
|
27
|
+
/** 解析后的 active SMIL interval,已展开有限 repeat。 */
|
|
28
|
+
export interface SMILAnimation {
|
|
29
|
+
attributeName: string;
|
|
30
|
+
type: string;
|
|
31
|
+
begin: number;
|
|
32
|
+
end: number;
|
|
33
|
+
fill: 'remove' | 'freeze';
|
|
34
|
+
additive: 'replace' | 'sum';
|
|
35
|
+
byOnly: boolean;
|
|
36
|
+
indefinite: boolean;
|
|
37
|
+
calcMode: 'linear' | 'discrete' | 'spline' | 'paced';
|
|
38
|
+
keySplines: IRBezierHandle[][];
|
|
39
|
+
samples: SMILSample[];
|
|
40
|
+
intervals: SMILInterval[];
|
|
41
|
+
}
|
|
42
|
+
export interface TransformContext {
|
|
43
|
+
ancestorMatrix: SVGMatrix;
|
|
44
|
+
selfMatrix: SVGMatrix;
|
|
45
|
+
localCenter: [number, number];
|
|
46
|
+
ancestorStopNode?: globalThis.Element | null;
|
|
47
|
+
preserveAncestorTransforms?: boolean;
|
|
48
|
+
geometry?: GeometryContext;
|
|
49
|
+
geometryScaleSink?: {
|
|
50
|
+
value?: IRAnimatedProperty<IRVec3>;
|
|
51
|
+
};
|
|
52
|
+
comparisonDuration?: number;
|
|
53
|
+
/** 将文本 paint alpha 与图层 opacity 分离,并在图层轨道上合成各级 authored opacity。 */
|
|
54
|
+
composeOpacityAcrossStages?: boolean;
|
|
55
|
+
}
|
|
56
|
+
export interface GeometryContext {
|
|
57
|
+
kind: 'rect' | 'circle' | 'ellipse' | 'line' | 'use';
|
|
58
|
+
base: Record<string, number>;
|
|
59
|
+
referenceWidth: number;
|
|
60
|
+
referenceHeight: number;
|
|
61
|
+
}
|
|
62
|
+
export interface GeometryAnimation {
|
|
63
|
+
animations: SMILAnimation[];
|
|
64
|
+
matrixAtTime: (time: number) => SVGMatrix;
|
|
65
|
+
scaleAtTime: (time: number) => {
|
|
66
|
+
x: number;
|
|
67
|
+
y: number;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export interface GeometrySample {
|
|
71
|
+
centerX: number;
|
|
72
|
+
centerY: number;
|
|
73
|
+
scaleX: number;
|
|
74
|
+
scaleY: number;
|
|
75
|
+
}
|
|
76
|
+
export interface TransformStage {
|
|
77
|
+
node: globalThis.Element;
|
|
78
|
+
staticMatrix: SVGMatrix;
|
|
79
|
+
animations: SMILAnimation[];
|
|
80
|
+
motions: MotionAnimation[];
|
|
81
|
+
geometry?: GeometryAnimation;
|
|
82
|
+
ignoreOpacity?: boolean;
|
|
83
|
+
}
|
|
84
|
+
export interface MotionPathSegment {
|
|
85
|
+
p0: [number, number];
|
|
86
|
+
p1: [number, number];
|
|
87
|
+
p2: [number, number];
|
|
88
|
+
p3: [number, number];
|
|
89
|
+
length: number;
|
|
90
|
+
samples: Array<{
|
|
91
|
+
t: number;
|
|
92
|
+
length: number;
|
|
93
|
+
}>;
|
|
94
|
+
}
|
|
95
|
+
export interface MotionPath {
|
|
96
|
+
segments: MotionPathSegment[];
|
|
97
|
+
totalLength: number;
|
|
98
|
+
vertexProgress: number[];
|
|
99
|
+
}
|
|
100
|
+
export interface MotionAnimation {
|
|
101
|
+
begin: number;
|
|
102
|
+
end: number;
|
|
103
|
+
simpleDuration: number;
|
|
104
|
+
activeDuration: number;
|
|
105
|
+
fill: 'remove' | 'freeze';
|
|
106
|
+
additive: 'replace' | 'sum';
|
|
107
|
+
indefinite: boolean;
|
|
108
|
+
calcMode: SMILAnimation['calcMode'];
|
|
109
|
+
keySplines: IRBezierHandle[][];
|
|
110
|
+
keyTimes: number[];
|
|
111
|
+
keyPoints: number[];
|
|
112
|
+
usesKeyPoints: boolean;
|
|
113
|
+
path: MotionPath;
|
|
114
|
+
pointValues?: Array<[number, number]>;
|
|
115
|
+
rotate: 'auto' | 'auto-reverse' | number;
|
|
116
|
+
}
|
|
117
|
+
export declare const EPSILON = 1e-9;
|
|
118
|
+
export declare const BEGIN_TIME_EPSILON = 1e-7;
|
|
119
|
+
export declare const LINEAR_OUT_TANGENT: IRBezierHandle;
|
|
120
|
+
export declare const LINEAR_IN_TANGENT: IRBezierHandle;
|
|
121
|
+
export declare const MAX_SYNCBASE_EVENTS = 10000;
|
|
122
|
+
export type BeginTimeCache = Map<globalThis.Element, number[]>;
|
|
123
|
+
export interface SyncbaseDependency {
|
|
124
|
+
source: globalThis.Element;
|
|
125
|
+
target: globalThis.Element;
|
|
126
|
+
event: 'begin' | 'end';
|
|
127
|
+
offset: number;
|
|
128
|
+
}
|
|
129
|
+
export type SMILValueParser = (value: string, type: string) => number[] | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** 将各行具有独立水平锚点的多行文本拆分为多个 IR 文本图层。 */
|
|
2
|
+
import type EditableSVG from '../../../parse-svg/svg-parser';
|
|
3
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
4
|
+
import type { IRTextLayer } from '@vvfx/animation-ir';
|
|
5
|
+
import { type TextMeasure } from './font-metrics';
|
|
6
|
+
import type { TextContentResult } from './inspect-content';
|
|
7
|
+
import type { SVGPreservedTextData } from '../../../svg-preserved-data';
|
|
8
|
+
export declare function buildPerLineTextLayers(es: EditableSVG, el: Element, textContent: TextContentResult, measureText?: TextMeasure): {
|
|
9
|
+
layers: Array<Omit<IRTextLayer, 'id' | 'name' | 'time'>>;
|
|
10
|
+
infos: SVGPreservedTextData[];
|
|
11
|
+
} | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** 构造普通文本图层。 */
|
|
2
|
+
import type EditableSVG from '../../../parse-svg/svg-parser';
|
|
3
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
4
|
+
import type { IRTextLayer } from '@vvfx/animation-ir';
|
|
5
|
+
import { type TextMeasure } from './font-metrics';
|
|
6
|
+
import type { TextContentResult } from './inspect-content';
|
|
7
|
+
import type { SVGPreservedTextData } from '../../../svg-preserved-data';
|
|
8
|
+
export declare function buildSingleTextLayer(es: EditableSVG, el: Element, textContent: TextContentResult, measureText?: TextMeasure): {
|
|
9
|
+
layer: Omit<IRTextLayer, 'id' | 'name' | 'time'> | null;
|
|
10
|
+
info: SVGPreservedTextData | null;
|
|
11
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** 构造需要独立定位的单行文本图层。 */
|
|
2
|
+
import type EditableSVG from '../../../parse-svg/svg-parser';
|
|
3
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
4
|
+
import type { IRTextLayer } from '@vvfx/animation-ir';
|
|
5
|
+
import { type TextMeasure } from './font-metrics';
|
|
6
|
+
import type { TextContentResult } from './inspect-content';
|
|
7
|
+
import type { SVGPreservedTextData } from '../../../svg-preserved-data';
|
|
8
|
+
export declare function buildSplitTextLayers(es: EditableSVG, el: Element, textContent: TextContentResult, measureText: TextMeasure): {
|
|
9
|
+
layers: Array<Omit<IRTextLayer, 'id' | 'name' | 'time'>>;
|
|
10
|
+
infos: SVGPreservedTextData[];
|
|
11
|
+
} | null;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** 将竖排文本按字符拆分为独立 IR 文本图层。 */
|
|
2
|
+
import type EditableSVG from '../../../parse-svg/svg-parser';
|
|
3
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
4
|
+
import type { IRTextLayer } from '@vvfx/animation-ir';
|
|
5
|
+
import { type TextMeasure } from './font-metrics';
|
|
6
|
+
import type { SVGPreservedTextData } from '../../../svg-preserved-data';
|
|
7
|
+
export declare function buildVerticalTextLayers(es: EditableSVG, el: Element, measureText?: TextMeasure): {
|
|
8
|
+
layers: Array<Omit<IRTextLayer, 'id' | 'name' | 'time'>>;
|
|
9
|
+
infos: SVGPreservedTextData[];
|
|
10
|
+
} | null;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG 文本到 Effects 文本组件共用的字体、度量和宽度估算逻辑。
|
|
3
|
+
*
|
|
4
|
+
* 这些函数不读取 SVG DOM,只根据字体属性和可选的 measureText 回调计算文本布局数据。
|
|
5
|
+
*/
|
|
6
|
+
type IRFontWeight = 'normal' | 'bold' | 'lighter';
|
|
7
|
+
interface TextMeasureResult {
|
|
8
|
+
width: number;
|
|
9
|
+
fontBoundingBoxAscent?: number;
|
|
10
|
+
fontBoundingBoxDescent?: number;
|
|
11
|
+
actualBoundingBoxAscent?: number;
|
|
12
|
+
hangingBaseline?: number;
|
|
13
|
+
}
|
|
14
|
+
export type TextMeasure = (fontDesc: string, text: string) => TextMeasureResult;
|
|
15
|
+
export declare function mapFontWeight(raw: string, fontFamily?: string): IRFontWeight;
|
|
16
|
+
/** 从字体族名中推断数值字重(100-950)。
|
|
17
|
+
* 优先级:关键词 > Linotype 数字代码 > 裸 100-900 数字 > AlibabaPuHuiTi 单字母后缀。 */
|
|
18
|
+
export declare function inferNumericWeightFromFamily(family: string): number | null;
|
|
19
|
+
/** 解析 Effects RichText strategies 所需的字体 asc/desc 与 x-height。
|
|
20
|
+
* 有 measureText 回调时使用当前字体指标;没有回调时使用字族比例估算。
|
|
21
|
+
* SVG 的 precise baseline 指标按实际字号读取,Effects layout metric 按字号比例缩放。 */
|
|
22
|
+
export declare function resolveFontMetrics(measureText: TextMeasure | undefined, fontFamily: string, fontWeight: IRFontWeight, fontStyle: string, fontSize: number): {
|
|
23
|
+
asc: number;
|
|
24
|
+
desc: number;
|
|
25
|
+
xHeight: number;
|
|
26
|
+
hanging?: number;
|
|
27
|
+
svgAsc?: number;
|
|
28
|
+
svgDesc?: number;
|
|
29
|
+
};
|
|
30
|
+
/** 将 SVG dominant-baseline 转换为 Effects alphabetic baseline 的 y 偏移。
|
|
31
|
+
* Effects 没有独立的 dominant-baseline 字段,因此复用字体 asc/desc、x-height 和可用的 hangingBaseline。 */
|
|
32
|
+
export declare function dominantBaselineDelta(baseline: string | undefined, asc: number, desc: number, xHeight: number, precise?: {
|
|
33
|
+
hanging?: number;
|
|
34
|
+
svgAsc?: number;
|
|
35
|
+
svgDesc?: number;
|
|
36
|
+
}): number;
|
|
37
|
+
/** 读取各空格字符在目标字体下的 advance,返回去重后的候选表。 */
|
|
38
|
+
export declare function buildSpaceCharTable(measureText: TextMeasure, fd: string): Array<{
|
|
39
|
+
ch: string;
|
|
40
|
+
w: number;
|
|
41
|
+
}>;
|
|
42
|
+
/** 选择 advance 最接近目标值的单个空格字符。 */
|
|
43
|
+
export declare function greedySpaceForDx(target: number, table: Array<{
|
|
44
|
+
ch: string;
|
|
45
|
+
w: number;
|
|
46
|
+
}>): string;
|
|
47
|
+
/** 构造与 Effects Runtime getFontDesc 一致的 CSS font 简写字符串,用于 Canvas measureText。 */
|
|
48
|
+
export declare function buildCanvasFontDesc(fontSize: number, fontFamily: string, fontWeight: IRFontWeight, fontStyle: string): string;
|
|
49
|
+
/** 文本宽度估算。优先使用调用方提供的 Canvas measureText,否则使用字符级启发式系数。 */
|
|
50
|
+
export declare function estimateTextWidth(content: string, fontSize: number, letterSpacing: number, measureText: ((fontDesc: string, text: string) => {
|
|
51
|
+
width: number;
|
|
52
|
+
}) | undefined, fontFamily: string, fontWeight: IRFontWeight, fontStyle: string): number;
|
|
53
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG text/tspan 内容读取与偏移、拆段结构判定。
|
|
3
|
+
*
|
|
4
|
+
* 该模块只解释 SVG 文本 DOM,不负责创建 IR layer 或计算 Effects 文本布局。
|
|
5
|
+
* 拆段结构判定结果供文本布局模块使用。
|
|
6
|
+
*/
|
|
7
|
+
import type EditableSVG from '../../../parse-svg/svg-parser';
|
|
8
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
9
|
+
import type { SVGPreservedTextSpan } from '../../../svg-preserved-data';
|
|
10
|
+
/** SVG tspan dx 属性原串是否为 svg2ir 可处理形态。
|
|
11
|
+
* - 'unsupported':列表(含空格多值,逐字偏移)/百分比(含 %)/非 px 单位(em/ex/pt 等)。parseFloat 会静默
|
|
12
|
+
* 只取首数或剥离单位当成 px(如 '50%'→50),与 SVG 语义不符 → 走 ge-capability 旁路,不拆不烘焙。
|
|
13
|
+
* - 'ok':单数值 px(含负值,拆段 leftEdge 累加负值表达段叠,多 comp z-order=文档序与 SVG 一致)。
|
|
14
|
+
* 空串(无 dx)不算 unsupported,调用方先判空。 */
|
|
15
|
+
export declare function isUnsupportedTextOffset(dxRaw: string): boolean;
|
|
16
|
+
/** 是否存在非首段 tspan 显式 x(绝对锚点重置,与 leftEdge 累加矛盾→不拆)。首段 x 已由 blockLeft 处理。 */
|
|
17
|
+
export declare function hasNonFirstTspanExplicitX(el: Element): boolean;
|
|
18
|
+
/** 是否竖排(writing-mode=vertical-rl/lr/tb-rl/tb-lr 等)。Effects 富文本无竖排原生布局,需逐字拆层;拆段路径不重复处理。
|
|
19
|
+
* 用 es.getAttr 读取以保留解析底座的继承语义,不切换到 raw getAttribute(会丢继承值)。 */
|
|
20
|
+
export declare function hasWritingMode(es: EditableSVG, el: Element): boolean;
|
|
21
|
+
/** 是否有直接子 tspan 带 transform 或 rotate 属性(markup 无旋转/矩阵,拆段各 comp 用 <text> 矩阵会丢→不拆)。 */
|
|
22
|
+
export declare function hasTspanTransformOrRotate(el: Element): boolean;
|
|
23
|
+
/** 是否存在嵌套 tspan(tspan 含元素子节点)。readTextContent 不递归,嵌套文字会错并进父段→不拆。 */
|
|
24
|
+
export declare function hasNestedTspan(el: Element): boolean;
|
|
25
|
+
/** 读 <text> 直接子文本 + 子 <tspan>。单 <text> 多 <tspan y=不同> 是 SVG 多行:
|
|
26
|
+
* 按 tspan 的 y(绝对,相对 <text>)分行,\n 连接给 Effects TextComponent 多行渲染(lineCount/lineHeight)。
|
|
27
|
+
* 无 y 的 tspan 连排(同行)。返回 {content(\n 连接),lineHeight(首两行 y 差,0=单行),lineCount,lineTexts}。
|
|
28
|
+
* per-span 样式需要富文本表达;无法表达的样式差异由 warning 报告。
|
|
29
|
+
*/
|
|
30
|
+
export interface TextContentResult {
|
|
31
|
+
content: string;
|
|
32
|
+
lineHeight: number;
|
|
33
|
+
lineCount: number;
|
|
34
|
+
lineTexts: string[];
|
|
35
|
+
firstTspanX: number | null;
|
|
36
|
+
firstTspanY: number | null;
|
|
37
|
+
spans: SVGPreservedTextSpan[];
|
|
38
|
+
isPathText: boolean;
|
|
39
|
+
lineXs: Array<number | null>;
|
|
40
|
+
lineYs: number[];
|
|
41
|
+
}
|
|
42
|
+
export declare function readTextContent(el: Element): TextContentResult;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** 选择文本布局并构造 IR 文本图层。 */
|
|
2
|
+
import type EditableSVG from '../../../parse-svg/svg-parser';
|
|
3
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
4
|
+
import type { IRTextLayer } from '@vvfx/animation-ir';
|
|
5
|
+
import type { SVGPreservedTextData } from '../../../svg-preserved-data';
|
|
6
|
+
import type { TextMeasure } from './font-metrics';
|
|
7
|
+
export declare function parseTextLayers(es: EditableSVG, el: Element, measureText?: TextMeasure): {
|
|
8
|
+
layers: Array<Omit<IRTextLayer, 'id' | 'name' | 'time'>>;
|
|
9
|
+
infos: SVGPreservedTextData[];
|
|
10
|
+
} | null;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type EditableSVG from '../../../parse-svg/svg-parser';
|
|
2
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
3
|
+
import type { IRColor } from '@vvfx/animation-ir';
|
|
4
|
+
import type { SVGPreservedTextData, SVGPreservedTextSpan } from '../../../svg-preserved-data';
|
|
5
|
+
export declare const TEXT_ANCHOR_MAP: Record<string, 'left' | 'center' | 'right'>;
|
|
6
|
+
export declare const FONT_STYLE_MAP: Record<string, 'normal' | 'italic' | 'oblique'>;
|
|
7
|
+
export type TextFontWeight = 'normal' | 'bold' | 'lighter';
|
|
8
|
+
/** 构造 SVG 文本的保留数据。 */
|
|
9
|
+
export declare function buildSVGPreservedTextData(spans: SVGPreservedTextSpan[], isPathText: boolean, fontFamily: string, fontWeight: TextFontWeight, fontStyle: SVGPreservedTextData['fontStyle']): SVGPreservedTextData;
|
|
10
|
+
/** 根据 direction=rtl 调整 text-anchor 的水平对齐。 */
|
|
11
|
+
export declare function resolveEffectiveTextAlign(es: EditableSVG, el: Element, textAlign: 'left' | 'center' | 'right'): 'left' | 'center' | 'right';
|
|
12
|
+
/** 合并文本元素及祖先变换,并分解出 IR 支持的缩放和旋转。 */
|
|
13
|
+
export declare function buildTextWorldMatrix(el: Element): {
|
|
14
|
+
sx: number;
|
|
15
|
+
sy: number;
|
|
16
|
+
rotation: number;
|
|
17
|
+
m: import("../../matrix").SVGMatrix;
|
|
18
|
+
};
|
|
19
|
+
/** 解析 text 级 fill 颜色;渐变使用中点色,缺省或 none 使用黑色。 */
|
|
20
|
+
export declare function resolveTextFillColor(es: EditableSVG, fillRaw: string | number | null | undefined, fillOpacity: number): IRColor;
|
|
21
|
+
/** 读取 text 自身和祖先组的 opacity,以及 fill-opacity。 */
|
|
22
|
+
export declare function readTextOpacity(es: EditableSVG, el: Element): {
|
|
23
|
+
totalOpacity: number;
|
|
24
|
+
fillOpacity: number;
|
|
25
|
+
};
|
|
26
|
+
/** 将 IR 颜色编码为十六进制字符串。 */
|
|
27
|
+
export declare function irColorToHex(c: IRColor): string;
|
|
28
|
+
/** 读取 letter-spacing,并转换为像素值。 */
|
|
29
|
+
export declare function readLetterSpacing(es: EditableSVG, el: Element, fontSize: number): number;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type EditableSVG from '../../../parse-svg/svg-parser';
|
|
2
|
+
import type { Element } from '@svgdotjs/svg.js';
|
|
3
|
+
import type { IRAnimatedProperty, IRShape, IRTransform, IRVec3 } from '@vvfx/animation-ir';
|
|
4
|
+
import type { GeometryContext } from '../smil/types';
|
|
5
|
+
export declare function readRawNumberAttribute(el: Element, name: string, fallback?: number): number;
|
|
6
|
+
export declare function prepareSMILShapeGeometry(el: Element, shape: IRShape): void;
|
|
7
|
+
export declare function buildTransformGeometry(el: Element, shape: IRShape): GeometryContext | undefined;
|
|
8
|
+
export declare function buildTransform(es: EditableSVG, el: Element, shape: IRShape, smilDurationSink: {
|
|
9
|
+
value: number;
|
|
10
|
+
}, frameRate: number, geometryScaleSink?: {
|
|
11
|
+
value?: IRAnimatedProperty<IRVec3>;
|
|
12
|
+
}): IRTransform;
|
|
13
|
+
export declare function applySMILToParsedTransform(el: Element, transform: IRTransform | undefined, smilDurationSink: {
|
|
14
|
+
value: number;
|
|
15
|
+
}, frameRate: number, composeOpacityAcrossStages?: boolean): void;
|