@remotion/web-renderer 4.0.391 → 4.0.393

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 (38) hide show
  1. package/dist/can-use-webfs-target.d.ts +1 -0
  2. package/dist/can-use-webfs-target.js +19 -0
  3. package/dist/compose.d.ts +6 -1
  4. package/dist/compose.js +31 -23
  5. package/dist/drawing/calculate-transforms.js +27 -8
  6. package/dist/drawing/draw-dom-element.d.ts +2 -0
  7. package/dist/drawing/draw-dom-element.js +17 -0
  8. package/dist/drawing/draw-element-to-canvas.d.ts +7 -3
  9. package/dist/drawing/draw-element-to-canvas.js +40 -48
  10. package/dist/drawing/draw-element.d.ts +9 -0
  11. package/dist/drawing/draw-element.js +50 -0
  12. package/dist/drawing/drawn-fn.d.ts +5 -0
  13. package/dist/drawing/drawn-fn.js +1 -0
  14. package/dist/drawing/text/apply-text-transform.d.ts +1 -0
  15. package/dist/drawing/text/apply-text-transform.js +12 -0
  16. package/dist/drawing/text/draw-text.d.ts +2 -0
  17. package/dist/drawing/text/draw-text.js +44 -0
  18. package/dist/drawing/text/handle-text-node.d.ts +7 -1
  19. package/dist/drawing/text/handle-text-node.js +7 -66
  20. package/dist/drawing/transform-in-3d.d.ts +8 -0
  21. package/dist/drawing/transform-in-3d.js +142 -0
  22. package/dist/esm/index.mjs +677 -8534
  23. package/dist/index.d.ts +2 -1
  24. package/dist/mediabunny-mappings.d.ts +1 -0
  25. package/dist/mediabunny-mappings.js +10 -0
  26. package/dist/output-target.d.ts +1 -0
  27. package/dist/output-target.js +1 -0
  28. package/dist/render-media-on-web.d.ts +6 -1
  29. package/dist/render-media-on-web.js +64 -24
  30. package/dist/render-operations-queue.d.ts +3 -0
  31. package/dist/render-operations-queue.js +3 -0
  32. package/dist/render-still-on-web.js +15 -9
  33. package/dist/take-screenshot.js +1 -1
  34. package/dist/walk-tree.d.ts +1 -0
  35. package/dist/walk-tree.js +14 -0
  36. package/dist/web-fs-target.d.ts +7 -0
  37. package/dist/web-fs-target.js +41 -0
  38. package/package.json +6 -6
@@ -0,0 +1 @@
1
+ export declare const canUseWebFsWriter: () => Promise<boolean>;
@@ -0,0 +1,19 @@
1
+ export const canUseWebFsWriter = async () => {
2
+ if (!('storage' in navigator)) {
3
+ return false;
4
+ }
5
+ if (!('getDirectory' in navigator.storage)) {
6
+ return false;
7
+ }
8
+ try {
9
+ const directoryHandle = await navigator.storage.getDirectory();
10
+ const fileHandle = await directoryHandle.getFileHandle('remotion-probe-web-fs-support', {
11
+ create: true,
12
+ });
13
+ const canUse = fileHandle.createWritable !== undefined;
14
+ return canUse;
15
+ }
16
+ catch (_a) {
17
+ return false;
18
+ }
19
+ };
package/dist/compose.d.ts CHANGED
@@ -1 +1,6 @@
1
- export declare const compose: (element: HTMLDivElement, context: OffscreenCanvasRenderingContext2D) => Promise<void>;
1
+ export declare const compose: ({ element, context, offsetLeft, offsetTop, }: {
2
+ element: HTMLElement | SVGElement;
3
+ context: OffscreenCanvasRenderingContext2D;
4
+ offsetLeft: number;
5
+ offsetTop: number;
6
+ }) => Promise<void>;
package/dist/compose.js CHANGED
@@ -1,7 +1,23 @@
1
+ import { drawDomElement } from './drawing/draw-dom-element';
1
2
  import { drawElementToCanvas } from './drawing/draw-element-to-canvas';
2
3
  import { handleTextNode } from './drawing/text/handle-text-node';
3
- import { turnSvgIntoDrawable } from './drawing/turn-svg-into-drawable';
4
- export const compose = async (element, context) => {
4
+ import { skipToNextNonDescendant } from './walk-tree';
5
+ const walkOverNode = ({ node, context, offsetLeft, offsetTop, }) => {
6
+ if (node instanceof HTMLElement || node instanceof SVGElement) {
7
+ return drawElementToCanvas({
8
+ element: node,
9
+ context,
10
+ draw: drawDomElement(node),
11
+ offsetLeft,
12
+ offsetTop,
13
+ });
14
+ }
15
+ if (node instanceof Text) {
16
+ return handleTextNode({ node, context, offsetLeft, offsetTop });
17
+ }
18
+ throw new Error('Unknown node type');
19
+ };
20
+ export const compose = async ({ element, context, offsetLeft, offsetTop, }) => {
5
21
  const treeWalker = document.createTreeWalker(element, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, (node) => {
6
22
  if (node instanceof Element) {
7
23
  // SVG does have children, but we process SVG elements in its
@@ -16,28 +32,20 @@ export const compose = async (element, context) => {
16
32
  }
17
33
  return NodeFilter.FILTER_ACCEPT;
18
34
  });
19
- while (treeWalker.nextNode()) {
20
- const node = treeWalker.currentNode;
21
- if (node instanceof HTMLElement || node instanceof SVGElement) {
22
- await drawElementToCanvas({
23
- element: node,
24
- context,
25
- draw: async (dimensions) => {
26
- const drawable = await (node instanceof SVGSVGElement
27
- ? turnSvgIntoDrawable(node)
28
- : node instanceof HTMLImageElement
29
- ? node
30
- : node instanceof HTMLCanvasElement
31
- ? node
32
- : null);
33
- if (drawable) {
34
- context.drawImage(drawable, dimensions.left, dimensions.top, dimensions.width, dimensions.height);
35
- }
36
- },
37
- });
35
+ while (true) {
36
+ const val = await walkOverNode({
37
+ node: treeWalker.currentNode,
38
+ context,
39
+ offsetLeft,
40
+ offsetTop,
41
+ });
42
+ if (val === 'skip-children') {
43
+ if (!skipToNextNonDescendant(treeWalker)) {
44
+ break;
45
+ }
38
46
  }
39
- else if (node instanceof Text) {
40
- await handleTextNode(node, context);
47
+ else if (!treeWalker.nextNode()) {
48
+ break;
41
49
  }
42
50
  }
43
51
  };
@@ -39,17 +39,34 @@ export const calculateTransforms = (element) => {
39
39
  ? undefined
40
40
  : computedStyle.transform;
41
41
  const matrix = new DOMMatrix(toParse);
42
- const { transform } = parent.style;
42
+ const { transform, scale, rotate } = parent.style;
43
+ const additionalMatrices = [];
44
+ // The order of transformations is:
45
+ // 1. Translate --> We do not have to consider it since it changes getClientBoundingRect()
46
+ // 2. Rotate
47
+ // 3. Scale
48
+ // 4. CSS "transform"
49
+ if (rotate !== '' && rotate !== 'none') {
50
+ additionalMatrices.push(new DOMMatrix(`rotate(${rotate})`));
51
+ }
52
+ if (scale !== '' && scale !== 'none') {
53
+ additionalMatrices.push(new DOMMatrix(`scale(${scale})`));
54
+ }
55
+ additionalMatrices.push(matrix);
43
56
  parent.style.transform = 'none';
57
+ parent.style.scale = 'none';
58
+ parent.style.rotate = 'none';
44
59
  transforms.push({
45
- matrix,
46
60
  rect: parent,
47
61
  transformOrigin: computedStyle.transformOrigin,
48
62
  boundingClientRect: null,
63
+ matrices: additionalMatrices,
49
64
  });
50
65
  const parentRef = parent;
51
66
  toReset.push(() => {
52
67
  parentRef.style.transform = transform;
68
+ parentRef.style.scale = scale;
69
+ parentRef.style.rotate = rotate;
53
70
  });
54
71
  }
55
72
  parent = parent.parentElement;
@@ -64,12 +81,14 @@ export const calculateTransforms = (element) => {
64
81
  if (!transform.boundingClientRect) {
65
82
  throw new Error('Bounding client rect not found');
66
83
  }
67
- const globalTransformOrigin = getGlobalTransformOrigin(transform);
68
- const transformMatrix = new DOMMatrix()
69
- .translate(globalTransformOrigin.x, globalTransformOrigin.y)
70
- .multiply(transform.matrix)
71
- .translate(-globalTransformOrigin.x, -globalTransformOrigin.y);
72
- totalMatrix.multiplySelf(transformMatrix);
84
+ for (const matrix of transform.matrices) {
85
+ const globalTransformOrigin = getGlobalTransformOrigin(transform);
86
+ const transformMatrix = new DOMMatrix()
87
+ .translate(globalTransformOrigin.x, globalTransformOrigin.y)
88
+ .multiply(matrix)
89
+ .translate(-globalTransformOrigin.x, -globalTransformOrigin.y);
90
+ totalMatrix.multiplySelf(transformMatrix);
91
+ }
73
92
  }
74
93
  if (!elementComputedStyle) {
75
94
  throw new Error('Element computed style not found');
@@ -0,0 +1,2 @@
1
+ import type { DrawFn } from './drawn-fn';
2
+ export declare const drawDomElement: (node: HTMLElement | SVGElement) => DrawFn;
@@ -0,0 +1,17 @@
1
+ import { turnSvgIntoDrawable } from './turn-svg-into-drawable';
2
+ export const drawDomElement = (node) => {
3
+ const domDrawFn = async ({ dimensions, contextToDraw }) => {
4
+ const drawable = await (node instanceof SVGSVGElement
5
+ ? turnSvgIntoDrawable(node)
6
+ : node instanceof HTMLImageElement
7
+ ? node
8
+ : node instanceof HTMLCanvasElement
9
+ ? node
10
+ : null);
11
+ if (!drawable) {
12
+ return;
13
+ }
14
+ contextToDraw.drawImage(drawable, dimensions.left, dimensions.top, dimensions.width, dimensions.height);
15
+ };
16
+ return domDrawFn;
17
+ };
@@ -1,5 +1,9 @@
1
- export declare const drawElementToCanvas: ({ element, context, draw, }: {
1
+ import type { DrawFn } from './drawn-fn';
2
+ export type DrawElementToCanvasReturnValue = 'continue' | 'skip-children';
3
+ export declare const drawElementToCanvas: ({ element, context, draw, offsetLeft, offsetTop, }: {
2
4
  element: HTMLElement | SVGElement;
3
5
  context: OffscreenCanvasRenderingContext2D;
4
- draw: (dimensions: DOMRect, computedStyle: CSSStyleDeclaration) => Promise<void> | void;
5
- }) => Promise<void>;
6
+ draw: DrawFn;
7
+ offsetLeft: number;
8
+ offsetTop: number;
9
+ }) => Promise<DrawElementToCanvasReturnValue>;
@@ -1,61 +1,53 @@
1
- import { parseBorderRadius, setBorderRadius } from './border-radius';
1
+ import { compose } from '../compose';
2
2
  import { calculateTransforms } from './calculate-transforms';
3
- import { drawBorder } from './draw-border';
4
- import { setOpacity } from './opacity';
5
- import { setTransform } from './transform';
6
- export const drawElementToCanvas = async ({ element, context, draw, }) => {
3
+ import { drawElement } from './draw-element';
4
+ import { transformIn3d } from './transform-in-3d';
5
+ export const drawElementToCanvas = async ({ element, context, draw, offsetLeft, offsetTop, }) => {
7
6
  const { totalMatrix, reset, dimensions, opacity, computedStyle } = calculateTransforms(element);
8
7
  if (opacity === 0) {
9
8
  reset();
10
- return;
9
+ return 'continue';
11
10
  }
12
11
  if (dimensions.width <= 0 || dimensions.height <= 0) {
13
12
  reset();
14
- return;
13
+ return 'continue';
15
14
  }
16
- const background = computedStyle.backgroundColor;
17
- const borderRadius = parseBorderRadius({
18
- borderRadius: computedStyle.borderRadius,
19
- width: dimensions.width,
20
- height: dimensions.height,
21
- });
22
- const finishTransform = setTransform({
23
- ctx: context,
24
- transform: totalMatrix,
25
- });
26
- const finishBorderRadius = setBorderRadius({
27
- ctx: context,
28
- x: dimensions.left,
29
- y: dimensions.top,
30
- width: dimensions.width,
31
- height: dimensions.height,
32
- borderRadius,
33
- });
34
- const finishOpacity = setOpacity({
35
- ctx: context,
36
- opacity,
37
- });
38
- if (background &&
39
- background !== 'transparent' &&
40
- !(background.startsWith('rgba') &&
41
- (background.endsWith(', 0)') || background.endsWith(',0')))) {
42
- const originalFillStyle = context.fillStyle;
43
- context.fillStyle = background;
44
- context.fillRect(dimensions.left, dimensions.top, dimensions.width, dimensions.height);
45
- context.fillStyle = originalFillStyle;
15
+ if (!totalMatrix.is2D) {
16
+ const canvasOffsetLeft = Math.min(dimensions.left, 0);
17
+ const canvasOffsetTop = Math.min(dimensions.top, 0);
18
+ const tempCanvasWidth = Math.max(dimensions.width, dimensions.right);
19
+ const tempCanvasHeight = Math.max(dimensions.height, dimensions.bottom);
20
+ const tempCanvas = new OffscreenCanvas(tempCanvasWidth, tempCanvasHeight);
21
+ const context2 = tempCanvas.getContext('2d');
22
+ if (!context2) {
23
+ throw new Error('Could not get context');
24
+ }
25
+ await compose({
26
+ element,
27
+ context: context2,
28
+ offsetLeft: canvasOffsetLeft,
29
+ offsetTop: canvasOffsetTop,
30
+ });
31
+ const transformed = transformIn3d({
32
+ canvasWidth: tempCanvasWidth,
33
+ canvasHeight: tempCanvasHeight,
34
+ matrix: totalMatrix,
35
+ sourceCanvas: tempCanvas,
36
+ offsetLeft: canvasOffsetLeft,
37
+ offsetTop: canvasOffsetTop,
38
+ });
39
+ context.drawImage(transformed, 0, 0);
40
+ reset();
41
+ return 'skip-children';
46
42
  }
47
- await draw(dimensions, computedStyle);
48
- drawBorder({
49
- ctx: context,
50
- x: dimensions.left,
51
- y: dimensions.top,
52
- width: dimensions.width,
53
- height: dimensions.height,
54
- borderRadius,
43
+ await drawElement({
44
+ dimensions: new DOMRect(dimensions.left - offsetLeft, dimensions.top - offsetTop, dimensions.width, dimensions.height),
55
45
  computedStyle,
46
+ context,
47
+ draw,
48
+ opacity,
49
+ totalMatrix,
56
50
  });
57
- finishOpacity();
58
- finishBorderRadius();
59
- finishTransform();
60
51
  reset();
52
+ return 'continue';
61
53
  };
@@ -0,0 +1,9 @@
1
+ import type { DrawFn } from './drawn-fn';
2
+ export declare const drawElement: ({ dimensions, computedStyle, context, draw, opacity, totalMatrix, }: {
3
+ dimensions: DOMRect;
4
+ computedStyle: CSSStyleDeclaration;
5
+ context: OffscreenCanvasRenderingContext2D;
6
+ opacity: number;
7
+ totalMatrix: DOMMatrix;
8
+ draw: DrawFn;
9
+ }) => Promise<void>;
@@ -0,0 +1,50 @@
1
+ import { parseBorderRadius, setBorderRadius } from './border-radius';
2
+ import { drawBorder } from './draw-border';
3
+ import { setOpacity } from './opacity';
4
+ import { setTransform } from './transform';
5
+ export const drawElement = async ({ dimensions, computedStyle, context, draw, opacity, totalMatrix, }) => {
6
+ const background = computedStyle.backgroundColor;
7
+ const borderRadius = parseBorderRadius({
8
+ borderRadius: computedStyle.borderRadius,
9
+ width: dimensions.width,
10
+ height: dimensions.height,
11
+ });
12
+ const finishTransform = setTransform({
13
+ ctx: context,
14
+ transform: totalMatrix,
15
+ });
16
+ const finishBorderRadius = setBorderRadius({
17
+ ctx: context,
18
+ x: dimensions.left,
19
+ y: dimensions.top,
20
+ width: dimensions.width,
21
+ height: dimensions.height,
22
+ borderRadius,
23
+ });
24
+ const finishOpacity = setOpacity({
25
+ ctx: context,
26
+ opacity,
27
+ });
28
+ if (background &&
29
+ background !== 'transparent' &&
30
+ !(background.startsWith('rgba') &&
31
+ (background.endsWith(', 0)') || background.endsWith(',0')))) {
32
+ const originalFillStyle = context.fillStyle;
33
+ context.fillStyle = background;
34
+ context.fillRect(dimensions.left, dimensions.top, dimensions.width, dimensions.height);
35
+ context.fillStyle = originalFillStyle;
36
+ }
37
+ await draw({ dimensions, computedStyle, contextToDraw: context });
38
+ drawBorder({
39
+ ctx: context,
40
+ x: dimensions.left,
41
+ y: dimensions.top,
42
+ width: dimensions.width,
43
+ height: dimensions.height,
44
+ borderRadius,
45
+ computedStyle,
46
+ });
47
+ finishOpacity();
48
+ finishBorderRadius();
49
+ finishTransform();
50
+ };
@@ -0,0 +1,5 @@
1
+ export type DrawFn = ({ computedStyle, contextToDraw, dimensions, }: {
2
+ dimensions: DOMRect;
3
+ computedStyle: CSSStyleDeclaration;
4
+ contextToDraw: OffscreenCanvasRenderingContext2D;
5
+ }) => Promise<void> | void;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export declare const applyTextTransform: (text: string, transform: string) => string;
@@ -0,0 +1,12 @@
1
+ export const applyTextTransform = (text, transform) => {
2
+ if (transform === 'uppercase') {
3
+ return text.toUpperCase();
4
+ }
5
+ if (transform === 'lowercase') {
6
+ return text.toLowerCase();
7
+ }
8
+ if (transform === 'capitalize') {
9
+ return text.replace(/\b\w/g, (char) => char.toUpperCase());
10
+ }
11
+ return text;
12
+ };
@@ -0,0 +1,2 @@
1
+ import type { DrawFn } from '../drawn-fn';
2
+ export declare const drawText: (span: HTMLSpanElement) => DrawFn;
@@ -0,0 +1,44 @@
1
+ import { Internals } from 'remotion';
2
+ import { applyTextTransform } from './apply-text-transform';
3
+ import { findLineBreaks } from './find-line-breaks.text';
4
+ import { getCollapsedText } from './get-collapsed-text';
5
+ export const drawText = (span) => {
6
+ const drawFn = ({ dimensions: rect, computedStyle, contextToDraw }) => {
7
+ const { fontFamily, fontSize, fontWeight, color, lineHeight, direction, writingMode, letterSpacing, textTransform, } = computedStyle;
8
+ const isVertical = writingMode !== 'horizontal-tb';
9
+ if (isVertical) {
10
+ // TODO: Only warn once per render.
11
+ Internals.Log.warn({
12
+ logLevel: 'warn',
13
+ tag: '@remotion/web-renderer',
14
+ }, 'Detected "writing-mode" CSS property. Vertical text is not yet supported in @remotion/web-renderer');
15
+ return;
16
+ }
17
+ contextToDraw.save();
18
+ contextToDraw.font = `${fontWeight} ${fontSize} ${fontFamily}`;
19
+ contextToDraw.fillStyle = color;
20
+ contextToDraw.letterSpacing = letterSpacing;
21
+ const fontSizePx = parseFloat(fontSize);
22
+ // TODO: This is not necessarily correct, need to create text and measure to know for sure
23
+ const lineHeightPx = lineHeight === 'normal' ? 1.2 * fontSizePx : parseFloat(lineHeight);
24
+ const baselineOffset = (lineHeightPx - fontSizePx) / 2;
25
+ const isRTL = direction === 'rtl';
26
+ contextToDraw.textAlign = isRTL ? 'right' : 'left';
27
+ contextToDraw.textBaseline = 'top';
28
+ const originalText = span.textContent;
29
+ const collapsedText = getCollapsedText(span);
30
+ const transformedText = applyTextTransform(collapsedText, textTransform);
31
+ span.textContent = transformedText;
32
+ // For RTL text, fill from the right edge instead of left
33
+ const xPosition = isRTL ? rect.right : rect.left;
34
+ const lines = findLineBreaks(span, isRTL);
35
+ let offsetTop = 0;
36
+ for (const line of lines) {
37
+ contextToDraw.fillText(line.text, xPosition + line.offsetHorizontal, rect.top + baselineOffset + offsetTop);
38
+ offsetTop += line.offsetTop;
39
+ }
40
+ span.textContent = originalText;
41
+ contextToDraw.restore();
42
+ };
43
+ return drawFn;
44
+ };
@@ -1 +1,7 @@
1
- export declare const handleTextNode: (node: Text, context: OffscreenCanvasRenderingContext2D) => Promise<void>;
1
+ import type { DrawElementToCanvasReturnValue } from '../draw-element-to-canvas';
2
+ export declare const handleTextNode: ({ node, context, offsetLeft, offsetTop, }: {
3
+ node: Text;
4
+ context: OffscreenCanvasRenderingContext2D;
5
+ offsetLeft: number;
6
+ offsetTop: number;
7
+ }) => Promise<DrawElementToCanvasReturnValue>;
@@ -1,32 +1,6 @@
1
- // Supported:
2
- // - fontFamily
3
- // - fontSize
4
- // - fontWeight
5
- // - color
6
- // - lineHeight
7
- // - direction
8
- // - letterSpacing
9
- // - textTransform
10
- // Not supported:
11
- // - writingMode
12
- // - textDecoration
13
- import { Internals } from 'remotion';
14
1
  import { drawElementToCanvas } from '../draw-element-to-canvas';
15
- import { findLineBreaks } from './find-line-breaks.text';
16
- import { getCollapsedText } from './get-collapsed-text';
17
- const applyTextTransform = (text, transform) => {
18
- if (transform === 'uppercase') {
19
- return text.toUpperCase();
20
- }
21
- if (transform === 'lowercase') {
22
- return text.toLowerCase();
23
- }
24
- if (transform === 'capitalize') {
25
- return text.replace(/\b\w/g, (char) => char.toUpperCase());
26
- }
27
- return text;
28
- };
29
- export const handleTextNode = async (node, context) => {
2
+ import { drawText } from './draw-text';
3
+ export const handleTextNode = async ({ node, context, offsetLeft, offsetTop, }) => {
30
4
  const span = document.createElement('span');
31
5
  const parent = node.parentNode;
32
6
  if (!parent) {
@@ -34,48 +8,15 @@ export const handleTextNode = async (node, context) => {
34
8
  }
35
9
  parent.insertBefore(span, node);
36
10
  span.appendChild(node);
37
- await drawElementToCanvas({
11
+ const value = await drawElementToCanvas({
38
12
  context,
39
13
  element: span,
40
- draw(rect, style) {
41
- const { fontFamily, fontSize, fontWeight, color, lineHeight, direction, writingMode, letterSpacing, textTransform, } = style;
42
- const isVertical = writingMode !== 'horizontal-tb';
43
- if (isVertical) {
44
- // TODO: Only warn once per render.
45
- Internals.Log.warn({
46
- logLevel: 'warn',
47
- tag: '@remotion/web-renderer',
48
- }, 'Detected "writing-mode" CSS property. Vertical text is not yet supported in @remotion/web-renderer');
49
- return;
50
- }
51
- context.save();
52
- context.font = `${fontWeight} ${fontSize} ${fontFamily}`;
53
- context.fillStyle = color;
54
- context.letterSpacing = letterSpacing;
55
- const fontSizePx = parseFloat(fontSize);
56
- // TODO: This is not necessarily correct, need to create text and measure to know for sure
57
- const lineHeightPx = lineHeight === 'normal' ? 1.2 * fontSizePx : parseFloat(lineHeight);
58
- const baselineOffset = (lineHeightPx - fontSizePx) / 2;
59
- const isRTL = direction === 'rtl';
60
- context.textAlign = isRTL ? 'right' : 'left';
61
- context.textBaseline = 'top';
62
- const originalText = span.textContent;
63
- const collapsedText = getCollapsedText(span);
64
- const transformedText = applyTextTransform(collapsedText, textTransform);
65
- span.textContent = transformedText;
66
- // For RTL text, fill from the right edge instead of left
67
- const xPosition = isRTL ? rect.right : rect.left;
68
- const lines = findLineBreaks(span, isRTL);
69
- let offsetTop = 0;
70
- for (const line of lines) {
71
- context.fillText(line.text, xPosition + line.offsetHorizontal, rect.top + baselineOffset + offsetTop);
72
- offsetTop += line.offsetTop;
73
- }
74
- span.textContent = originalText;
75
- context.restore();
76
- },
14
+ draw: drawText(span),
15
+ offsetLeft,
16
+ offsetTop,
77
17
  });
78
18
  // Undo the layout manipulation
79
19
  parent.insertBefore(node, span);
80
20
  parent.removeChild(span);
21
+ return value;
81
22
  };
@@ -0,0 +1,8 @@
1
+ export declare const transformIn3d: ({ canvasWidth, canvasHeight, matrix, sourceCanvas, offsetLeft, offsetTop, }: {
2
+ canvasWidth: number;
3
+ canvasHeight: number;
4
+ offsetLeft: number;
5
+ offsetTop: number;
6
+ matrix: DOMMatrix;
7
+ sourceCanvas: HTMLCanvasElement | OffscreenCanvas;
8
+ }) => OffscreenCanvas;