canvu-react 0.4.67 → 0.4.68
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/dist/{asset-hydration-F6aM5C7x.d.cts → asset-hydration-Dw99FGJB.d.cts} +1 -1
- package/dist/{asset-hydration-BSjiek7Q.d.ts → asset-hydration-aNXfeayg.d.ts} +1 -1
- package/dist/chatbot.d.cts +2 -2
- package/dist/chatbot.d.ts +2 -2
- package/dist/index.cjs +466 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +466 -0
- package/dist/index.js.map +1 -1
- package/dist/{asset-store-35ysK28r.d.cts → raster-image-canvas-BZh73aoc.d.ts} +70 -2
- package/dist/{asset-store-D_FjW_CN.d.ts → raster-image-canvas-zerVYllB.d.cts} +70 -2
- package/dist/react.cjs +475 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +6 -6
- package/dist/react.d.ts +6 -6
- package/dist/react.js +475 -1
- package/dist/react.js.map +1 -1
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/realtime.js.map +1 -1
- package/dist/{types-B-Jdh-n6.d.ts → types-94XpQMy7.d.ts} +12 -1
- package/dist/{types-D5d-3dvz.d.cts → types-BZ9wK9Y3.d.cts} +12 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -2,9 +2,9 @@ import { C as Camera2D } from './shape-builders-DzhCOuzo.cjs';
|
|
|
2
2
|
export { a as Camera2DOptions, D as DEFAULT_STROKE_STYLE, F as FreehandSvgPayload, S as StrokeStyle, b as applyStrokeToItem, c as buildArchitecturalCloudPathD, d as buildArchitecturalCloudSvg, e as buildArrowSvg, f as buildDrawDotSvg, g as buildEllipseSvg, h as buildFreehandPathSvg, i as buildLineSvg, j as buildRectSvg, k as computeFreehandSvgPayload, l as createArchitecturalCloudItem, m as createDrawDotItem, n as createEllipseItem, o as createFreehandStrokeItem, p as createImageFromVectorTrace, q as createImageItem, r as createLineItem, s as createRectangleItem, t as createShapeId, u as createTextItem, v as lineEndpointsToLocal, w as rebuildItemSvg, x as resolveStrokeStyle } from './shape-builders-DzhCOuzo.cjs';
|
|
3
3
|
import { V as VectorSceneItem, A as ArrowEndpointBinding, C as CustomShapeResizeHandles, R as Rect } from './types-fJNwEnHf.cjs';
|
|
4
4
|
export { a as ArrowBindings, b as ResizeHandleId, c as VectorPathPoint, n as normalizeRect, r as rectsIntersect } from './types-fJNwEnHf.cjs';
|
|
5
|
-
export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-
|
|
5
|
+
export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-Dw99FGJB.cjs';
|
|
6
|
+
import { R as RasterImageCanvasRenderingOptions } from './raster-image-canvas-zerVYllB.cjs';
|
|
6
7
|
export { C as CanvuLinkData, D as DEFAULT_LINK_CARD_SIZE, L as LINK_PLUGIN_KEY, b as buildLinkCardSvg, c as createLinkItem, g as getLinkData, i as isLinkItem } from './link-item-BMV3VUCr.cjs';
|
|
7
|
-
import './asset-store-35ysK28r.cjs';
|
|
8
8
|
|
|
9
9
|
type EncodeCanvasToBlobOptions = {
|
|
10
10
|
mimeType?: string;
|
|
@@ -180,6 +180,7 @@ type SvgVectorRendererOptions = {
|
|
|
180
180
|
* (interactive selection / resize / placement).
|
|
181
181
|
*/
|
|
182
182
|
pointerEventsNone?: boolean;
|
|
183
|
+
rasterImageCanvas?: RasterImageCanvasRenderingOptions | null;
|
|
183
184
|
};
|
|
184
185
|
type SvgVectorRendererInteractionState = {
|
|
185
186
|
selectedIds?: readonly string[];
|
|
@@ -204,6 +205,7 @@ declare class SvgVectorRenderer {
|
|
|
204
205
|
private hoveredItemId;
|
|
205
206
|
private liveOverlay;
|
|
206
207
|
private readonly resizeObserver;
|
|
208
|
+
private rasterImageCanvasRendering;
|
|
207
209
|
constructor(options: SvgVectorRendererOptions);
|
|
208
210
|
/**
|
|
209
211
|
* Updates interaction attributes on item groups for CSS hooks.
|
|
@@ -213,6 +215,7 @@ declare class SvgVectorRenderer {
|
|
|
213
215
|
* pointer events.
|
|
214
216
|
*/
|
|
215
217
|
setInteractionState(state: SvgVectorRendererInteractionState): void;
|
|
218
|
+
setRasterImageCanvasRendering(options: RasterImageCanvasRenderingOptions | null | undefined): void;
|
|
216
219
|
/**
|
|
217
220
|
* Reads container size, culls items, and updates the SVG (incrementally when possible).
|
|
218
221
|
*/
|
|
@@ -228,6 +231,13 @@ declare class SvgVectorRenderer {
|
|
|
228
231
|
renderLiveItem(item: VectorSceneItem | null): void;
|
|
229
232
|
private keepLiveOverlayOnTop;
|
|
230
233
|
private syncVisibleItems;
|
|
234
|
+
private syncRasterImageCanvas;
|
|
235
|
+
private ensureRasterImageCanvas;
|
|
236
|
+
private positionRasterImageCanvas;
|
|
237
|
+
private drawRasterImageCanvas;
|
|
238
|
+
private drawQueuedRasterImageCanvasTarget;
|
|
239
|
+
private clearRasterImageCanvasBitmap;
|
|
240
|
+
private releaseRasterImageCanvas;
|
|
231
241
|
private applyInteractionAttributes;
|
|
232
242
|
destroy(): void;
|
|
233
243
|
/** Toggle whether the scene SVG receives pointer events (vs overlay handling them). */
|
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { C as Camera2D } from './shape-builders-xG3A66sv.js';
|
|
|
2
2
|
export { a as Camera2DOptions, D as DEFAULT_STROKE_STYLE, F as FreehandSvgPayload, S as StrokeStyle, b as applyStrokeToItem, c as buildArchitecturalCloudPathD, d as buildArchitecturalCloudSvg, e as buildArrowSvg, f as buildDrawDotSvg, g as buildEllipseSvg, h as buildFreehandPathSvg, i as buildLineSvg, j as buildRectSvg, k as computeFreehandSvgPayload, l as createArchitecturalCloudItem, m as createDrawDotItem, n as createEllipseItem, o as createFreehandStrokeItem, p as createImageFromVectorTrace, q as createImageItem, r as createLineItem, s as createRectangleItem, t as createShapeId, u as createTextItem, v as lineEndpointsToLocal, w as rebuildItemSvg, x as resolveStrokeStyle } from './shape-builders-xG3A66sv.js';
|
|
3
3
|
import { V as VectorSceneItem, A as ArrowEndpointBinding, C as CustomShapeResizeHandles, R as Rect } from './types-fJNwEnHf.js';
|
|
4
4
|
export { a as ArrowBindings, b as ResizeHandleId, c as VectorPathPoint, n as normalizeRect, r as rectsIntersect } from './types-fJNwEnHf.js';
|
|
5
|
-
export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-
|
|
5
|
+
export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-aNXfeayg.js';
|
|
6
|
+
import { R as RasterImageCanvasRenderingOptions } from './raster-image-canvas-BZh73aoc.js';
|
|
6
7
|
export { C as CanvuLinkData, D as DEFAULT_LINK_CARD_SIZE, L as LINK_PLUGIN_KEY, b as buildLinkCardSvg, c as createLinkItem, g as getLinkData, i as isLinkItem } from './link-item-COoNNvCu.js';
|
|
7
|
-
import './asset-store-D_FjW_CN.js';
|
|
8
8
|
|
|
9
9
|
type EncodeCanvasToBlobOptions = {
|
|
10
10
|
mimeType?: string;
|
|
@@ -180,6 +180,7 @@ type SvgVectorRendererOptions = {
|
|
|
180
180
|
* (interactive selection / resize / placement).
|
|
181
181
|
*/
|
|
182
182
|
pointerEventsNone?: boolean;
|
|
183
|
+
rasterImageCanvas?: RasterImageCanvasRenderingOptions | null;
|
|
183
184
|
};
|
|
184
185
|
type SvgVectorRendererInteractionState = {
|
|
185
186
|
selectedIds?: readonly string[];
|
|
@@ -204,6 +205,7 @@ declare class SvgVectorRenderer {
|
|
|
204
205
|
private hoveredItemId;
|
|
205
206
|
private liveOverlay;
|
|
206
207
|
private readonly resizeObserver;
|
|
208
|
+
private rasterImageCanvasRendering;
|
|
207
209
|
constructor(options: SvgVectorRendererOptions);
|
|
208
210
|
/**
|
|
209
211
|
* Updates interaction attributes on item groups for CSS hooks.
|
|
@@ -213,6 +215,7 @@ declare class SvgVectorRenderer {
|
|
|
213
215
|
* pointer events.
|
|
214
216
|
*/
|
|
215
217
|
setInteractionState(state: SvgVectorRendererInteractionState): void;
|
|
218
|
+
setRasterImageCanvasRendering(options: RasterImageCanvasRenderingOptions | null | undefined): void;
|
|
216
219
|
/**
|
|
217
220
|
* Reads container size, culls items, and updates the SVG (incrementally when possible).
|
|
218
221
|
*/
|
|
@@ -228,6 +231,13 @@ declare class SvgVectorRenderer {
|
|
|
228
231
|
renderLiveItem(item: VectorSceneItem | null): void;
|
|
229
232
|
private keepLiveOverlayOnTop;
|
|
230
233
|
private syncVisibleItems;
|
|
234
|
+
private syncRasterImageCanvas;
|
|
235
|
+
private ensureRasterImageCanvas;
|
|
236
|
+
private positionRasterImageCanvas;
|
|
237
|
+
private drawRasterImageCanvas;
|
|
238
|
+
private drawQueuedRasterImageCanvasTarget;
|
|
239
|
+
private clearRasterImageCanvasBitmap;
|
|
240
|
+
private releaseRasterImageCanvas;
|
|
231
241
|
private applyInteractionAttributes;
|
|
232
242
|
destroy(): void;
|
|
233
243
|
/** Toggle whether the scene SVG receives pointer events (vs overlay handling them). */
|
package/dist/index.js
CHANGED
|
@@ -2570,6 +2570,151 @@ function cullItemsByViewport(items, visibleWorld) {
|
|
|
2570
2570
|
return cullItemsByViewportSpatial(items, visibleWorld, SPATIAL_CELL_SIZE);
|
|
2571
2571
|
}
|
|
2572
2572
|
|
|
2573
|
+
// src/renderer/raster-image-canvas.ts
|
|
2574
|
+
var DEFAULT_PIXEL_HEADROOM = 1.5;
|
|
2575
|
+
var DEFAULT_MAX_PIXEL_COUNT = 12e6;
|
|
2576
|
+
var DEFAULT_MAX_DIMENSION = 4096;
|
|
2577
|
+
var DEFAULT_UPSCALE_REDRAW_RATIO = 1.15;
|
|
2578
|
+
function resolveRasterImageCanvasRenderingOptions(options) {
|
|
2579
|
+
if (!options) return null;
|
|
2580
|
+
const fallbackDevicePixelRatio = typeof window === "undefined" ? 1 : window.devicePixelRatio;
|
|
2581
|
+
return {
|
|
2582
|
+
resolveRenderTarget: options.resolveRenderTarget,
|
|
2583
|
+
devicePixelRatio: toPositiveFiniteNumber(
|
|
2584
|
+
options.devicePixelRatio,
|
|
2585
|
+
fallbackDevicePixelRatio
|
|
2586
|
+
),
|
|
2587
|
+
pixelHeadroom: toPositiveFiniteNumber(
|
|
2588
|
+
options.pixelHeadroom,
|
|
2589
|
+
DEFAULT_PIXEL_HEADROOM
|
|
2590
|
+
),
|
|
2591
|
+
maxPixelCount: toPositiveFiniteNumber(
|
|
2592
|
+
options.maxPixelCount,
|
|
2593
|
+
DEFAULT_MAX_PIXEL_COUNT
|
|
2594
|
+
),
|
|
2595
|
+
maxDimension: toPositiveFiniteNumber(
|
|
2596
|
+
options.maxDimension,
|
|
2597
|
+
DEFAULT_MAX_DIMENSION
|
|
2598
|
+
),
|
|
2599
|
+
upscaleRedrawRatio: toPositiveFiniteNumber(
|
|
2600
|
+
options.upscaleRedrawRatio,
|
|
2601
|
+
DEFAULT_UPSCALE_REDRAW_RATIO
|
|
2602
|
+
)
|
|
2603
|
+
};
|
|
2604
|
+
}
|
|
2605
|
+
function getRasterImageContentRect(item) {
|
|
2606
|
+
if (item.toolKind !== "image" || !item.imageIntrinsicSize) return null;
|
|
2607
|
+
const bounds = normalizeRect(item.bounds);
|
|
2608
|
+
const intrinsicWidth = Math.max(1e-6, item.imageIntrinsicSize.width);
|
|
2609
|
+
const intrinsicHeight = Math.max(1e-6, item.imageIntrinsicSize.height);
|
|
2610
|
+
const boundsAspectRatio = bounds.width / Math.max(1e-9, bounds.height);
|
|
2611
|
+
const imageAspectRatio = intrinsicWidth / intrinsicHeight;
|
|
2612
|
+
if (Math.abs(boundsAspectRatio - imageAspectRatio) < 1e-3) {
|
|
2613
|
+
return { x: 0, y: 0, width: bounds.width, height: bounds.height };
|
|
2614
|
+
}
|
|
2615
|
+
if (boundsAspectRatio > imageAspectRatio) {
|
|
2616
|
+
const height2 = bounds.height;
|
|
2617
|
+
const width2 = height2 * imageAspectRatio;
|
|
2618
|
+
return { x: (bounds.width - width2) / 2, y: 0, width: width2, height: height2 };
|
|
2619
|
+
}
|
|
2620
|
+
const width = bounds.width;
|
|
2621
|
+
const height = width / imageAspectRatio;
|
|
2622
|
+
return { x: 0, y: (bounds.height - height) / 2, width, height };
|
|
2623
|
+
}
|
|
2624
|
+
function getRasterImageCanvasTargetSize({
|
|
2625
|
+
intrinsicSize,
|
|
2626
|
+
contentRect,
|
|
2627
|
+
cameraZoom,
|
|
2628
|
+
devicePixelRatio,
|
|
2629
|
+
pixelHeadroom,
|
|
2630
|
+
maxPixelCount,
|
|
2631
|
+
maxDimension
|
|
2632
|
+
}) {
|
|
2633
|
+
const intrinsicWidth = Math.max(1, Math.round(intrinsicSize.width));
|
|
2634
|
+
const intrinsicHeight = Math.max(1, Math.round(intrinsicSize.height));
|
|
2635
|
+
const targetCssWidth = Math.max(1, contentRect.width * cameraZoom);
|
|
2636
|
+
const targetCssHeight = Math.max(1, contentRect.height * cameraZoom);
|
|
2637
|
+
const desiredWidth = targetCssWidth * toPositiveFiniteNumber(devicePixelRatio, 1) * pixelHeadroom;
|
|
2638
|
+
const desiredHeight = targetCssHeight * toPositiveFiniteNumber(devicePixelRatio, 1) * pixelHeadroom;
|
|
2639
|
+
const dimensionScale = Math.min(
|
|
2640
|
+
1,
|
|
2641
|
+
toPositiveFiniteNumber(maxDimension, intrinsicWidth) / Math.max(intrinsicWidth, intrinsicHeight)
|
|
2642
|
+
);
|
|
2643
|
+
const pixelScale = Math.min(
|
|
2644
|
+
1,
|
|
2645
|
+
Math.sqrt(
|
|
2646
|
+
toPositiveFiniteNumber(maxPixelCount, intrinsicWidth * intrinsicHeight) / (intrinsicWidth * intrinsicHeight)
|
|
2647
|
+
)
|
|
2648
|
+
);
|
|
2649
|
+
const viewportScale = Math.min(
|
|
2650
|
+
1,
|
|
2651
|
+
desiredWidth / intrinsicWidth,
|
|
2652
|
+
desiredHeight / intrinsicHeight
|
|
2653
|
+
);
|
|
2654
|
+
const scale = Math.min(dimensionScale, pixelScale, viewportScale);
|
|
2655
|
+
const width = Math.max(1, Math.round(intrinsicWidth * scale));
|
|
2656
|
+
const height = Math.max(1, Math.round(width * (intrinsicHeight / intrinsicWidth)));
|
|
2657
|
+
return { width, height };
|
|
2658
|
+
}
|
|
2659
|
+
function resolveRasterImageCanvasRenderTarget({
|
|
2660
|
+
item,
|
|
2661
|
+
href,
|
|
2662
|
+
intrinsicSize,
|
|
2663
|
+
contentRect,
|
|
2664
|
+
targetSize,
|
|
2665
|
+
viewportSize,
|
|
2666
|
+
cameraZoom,
|
|
2667
|
+
options
|
|
2668
|
+
}) {
|
|
2669
|
+
const request = {
|
|
2670
|
+
item,
|
|
2671
|
+
href,
|
|
2672
|
+
intrinsicSize,
|
|
2673
|
+
contentRect,
|
|
2674
|
+
targetSize,
|
|
2675
|
+
viewportSize,
|
|
2676
|
+
cameraZoom,
|
|
2677
|
+
devicePixelRatio: options.devicePixelRatio
|
|
2678
|
+
};
|
|
2679
|
+
const resolved = options.resolveRenderTarget?.(request);
|
|
2680
|
+
if (typeof resolved === "string") {
|
|
2681
|
+
return { href: resolved, sourceKey: resolved, targetSize, contentRect };
|
|
2682
|
+
}
|
|
2683
|
+
if (resolved?.href) {
|
|
2684
|
+
return {
|
|
2685
|
+
href: resolved.href,
|
|
2686
|
+
sourceKey: resolved.sourceKey ?? resolved.href,
|
|
2687
|
+
targetSize,
|
|
2688
|
+
contentRect
|
|
2689
|
+
};
|
|
2690
|
+
}
|
|
2691
|
+
return { href, sourceKey: href, targetSize, contentRect };
|
|
2692
|
+
}
|
|
2693
|
+
function shouldRedrawRasterImageCanvas({
|
|
2694
|
+
currentSourceKey,
|
|
2695
|
+
currentWidth,
|
|
2696
|
+
currentHeight,
|
|
2697
|
+
nextSourceKey,
|
|
2698
|
+
nextWidth,
|
|
2699
|
+
nextHeight,
|
|
2700
|
+
upscaleRedrawRatio
|
|
2701
|
+
}) {
|
|
2702
|
+
const safeCurrentWidth = Math.max(0, Math.round(currentWidth));
|
|
2703
|
+
const safeCurrentHeight = Math.max(0, Math.round(currentHeight));
|
|
2704
|
+
const safeNextWidth = Math.max(1, Math.round(nextWidth));
|
|
2705
|
+
const safeNextHeight = Math.max(1, Math.round(nextHeight));
|
|
2706
|
+
if (!currentSourceKey || safeCurrentWidth <= 1 || safeCurrentHeight <= 1) {
|
|
2707
|
+
return true;
|
|
2708
|
+
}
|
|
2709
|
+
if (currentSourceKey !== nextSourceKey && safeCurrentWidth === safeNextWidth && safeCurrentHeight === safeNextHeight) {
|
|
2710
|
+
return true;
|
|
2711
|
+
}
|
|
2712
|
+
return safeNextWidth > safeCurrentWidth * upscaleRedrawRatio || safeNextHeight > safeCurrentHeight * upscaleRedrawRatio;
|
|
2713
|
+
}
|
|
2714
|
+
function toPositiveFiniteNumber(value, fallback) {
|
|
2715
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
2716
|
+
}
|
|
2717
|
+
|
|
2573
2718
|
// src/renderer/svg-vector-renderer.ts
|
|
2574
2719
|
function formatCameraTransform(camera) {
|
|
2575
2720
|
const z = camera.zoom;
|
|
@@ -2594,6 +2739,87 @@ function itemClassName(item) {
|
|
|
2594
2739
|
}
|
|
2595
2740
|
return classes.join(" ");
|
|
2596
2741
|
}
|
|
2742
|
+
async function decodeRasterImage(href, width, height, signal) {
|
|
2743
|
+
if (typeof createImageBitmap === "function") {
|
|
2744
|
+
try {
|
|
2745
|
+
const response = await fetch(href, { signal, credentials: "same-origin" });
|
|
2746
|
+
if (!response.ok) {
|
|
2747
|
+
throw new Error(`Failed to fetch raster image: ${response.status}`);
|
|
2748
|
+
}
|
|
2749
|
+
const blob = await response.blob();
|
|
2750
|
+
if (signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
2751
|
+
const bitmap = await createImageBitmap(blob, {
|
|
2752
|
+
resizeWidth: width,
|
|
2753
|
+
resizeHeight: height,
|
|
2754
|
+
resizeQuality: "high"
|
|
2755
|
+
});
|
|
2756
|
+
return {
|
|
2757
|
+
width: bitmap.width,
|
|
2758
|
+
height: bitmap.height,
|
|
2759
|
+
draw: (context) => {
|
|
2760
|
+
context.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height);
|
|
2761
|
+
},
|
|
2762
|
+
close: () => bitmap.close()
|
|
2763
|
+
};
|
|
2764
|
+
} catch (error) {
|
|
2765
|
+
if (signal.aborted) throw error;
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
const image = await loadImageElement(href, signal);
|
|
2769
|
+
return {
|
|
2770
|
+
width,
|
|
2771
|
+
height,
|
|
2772
|
+
draw: (context) => {
|
|
2773
|
+
context.drawImage(image, 0, 0, width, height);
|
|
2774
|
+
},
|
|
2775
|
+
close: () => {
|
|
2776
|
+
}
|
|
2777
|
+
};
|
|
2778
|
+
}
|
|
2779
|
+
function loadImageElement(href, signal) {
|
|
2780
|
+
return new Promise((resolve, reject) => {
|
|
2781
|
+
if (signal.aborted) {
|
|
2782
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
2783
|
+
return;
|
|
2784
|
+
}
|
|
2785
|
+
const image = new Image();
|
|
2786
|
+
const cleanup = () => {
|
|
2787
|
+
signal.removeEventListener("abort", abort);
|
|
2788
|
+
image.onload = null;
|
|
2789
|
+
image.onerror = null;
|
|
2790
|
+
};
|
|
2791
|
+
const abort = () => {
|
|
2792
|
+
cleanup();
|
|
2793
|
+
image.removeAttribute("src");
|
|
2794
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
2795
|
+
};
|
|
2796
|
+
image.decoding = "async";
|
|
2797
|
+
image.onload = () => {
|
|
2798
|
+
const decodePromise = image.decode?.();
|
|
2799
|
+
if (!decodePromise) {
|
|
2800
|
+
cleanup();
|
|
2801
|
+
resolve(image);
|
|
2802
|
+
return;
|
|
2803
|
+
}
|
|
2804
|
+
decodePromise.then(
|
|
2805
|
+
() => {
|
|
2806
|
+
cleanup();
|
|
2807
|
+
resolve(image);
|
|
2808
|
+
},
|
|
2809
|
+
() => {
|
|
2810
|
+
cleanup();
|
|
2811
|
+
resolve(image);
|
|
2812
|
+
}
|
|
2813
|
+
);
|
|
2814
|
+
};
|
|
2815
|
+
image.onerror = () => {
|
|
2816
|
+
cleanup();
|
|
2817
|
+
reject(new Error("Failed to load raster image"));
|
|
2818
|
+
};
|
|
2819
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
2820
|
+
image.src = href;
|
|
2821
|
+
});
|
|
2822
|
+
}
|
|
2597
2823
|
var SvgVectorRenderer = class {
|
|
2598
2824
|
container;
|
|
2599
2825
|
scene;
|
|
@@ -2605,10 +2831,14 @@ var SvgVectorRenderer = class {
|
|
|
2605
2831
|
hoveredItemId = null;
|
|
2606
2832
|
liveOverlay = null;
|
|
2607
2833
|
resizeObserver;
|
|
2834
|
+
rasterImageCanvasRendering;
|
|
2608
2835
|
constructor(options) {
|
|
2609
2836
|
this.container = options.container;
|
|
2610
2837
|
this.scene = options.scene;
|
|
2611
2838
|
this.camera = options.camera;
|
|
2839
|
+
this.rasterImageCanvasRendering = resolveRasterImageCanvasRenderingOptions(
|
|
2840
|
+
options.rasterImageCanvas
|
|
2841
|
+
);
|
|
2612
2842
|
this.svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
2613
2843
|
this.svg.setAttribute("width", "100%");
|
|
2614
2844
|
this.svg.setAttribute("height", "100%");
|
|
@@ -2637,6 +2867,15 @@ var SvgVectorRenderer = class {
|
|
|
2637
2867
|
this.applyInteractionAttributes(cached.g, id);
|
|
2638
2868
|
}
|
|
2639
2869
|
}
|
|
2870
|
+
setRasterImageCanvasRendering(options) {
|
|
2871
|
+
this.rasterImageCanvasRendering = resolveRasterImageCanvasRenderingOptions(options);
|
|
2872
|
+
if (!this.rasterImageCanvasRendering) {
|
|
2873
|
+
for (const cached of this.itemNodeCache.values()) {
|
|
2874
|
+
this.releaseRasterImageCanvas(cached);
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
this.render();
|
|
2878
|
+
}
|
|
2640
2879
|
/**
|
|
2641
2880
|
* Reads container size, culls items, and updates the SVG (incrementally when possible).
|
|
2642
2881
|
*/
|
|
@@ -2710,6 +2949,7 @@ var SvgVectorRenderer = class {
|
|
|
2710
2949
|
}
|
|
2711
2950
|
for (const [id, cached] of this.itemNodeCache) {
|
|
2712
2951
|
if (!visibleIds.has(id)) {
|
|
2952
|
+
this.releaseRasterImageCanvas(cached);
|
|
2713
2953
|
cached.g.remove();
|
|
2714
2954
|
}
|
|
2715
2955
|
}
|
|
@@ -2742,6 +2982,7 @@ var SvgVectorRenderer = class {
|
|
|
2742
2982
|
g.innerHTML = item.childrenSvg;
|
|
2743
2983
|
cached.lastChildrenSvg = item.childrenSvg;
|
|
2744
2984
|
}
|
|
2985
|
+
this.syncRasterImageCanvas(cached, item);
|
|
2745
2986
|
const expectedPosition = previousNode ? previousNode.nextSibling : this.rootG.firstChild;
|
|
2746
2987
|
if (expectedPosition !== g) {
|
|
2747
2988
|
this.rootG.insertBefore(g, expectedPosition);
|
|
@@ -2749,6 +2990,228 @@ var SvgVectorRenderer = class {
|
|
|
2749
2990
|
previousNode = g;
|
|
2750
2991
|
}
|
|
2751
2992
|
}
|
|
2993
|
+
syncRasterImageCanvas(cached, item) {
|
|
2994
|
+
const options = this.rasterImageCanvasRendering;
|
|
2995
|
+
if (!options || item.toolKind !== "image" || !item.imageRasterHref || !item.imageIntrinsicSize) {
|
|
2996
|
+
this.releaseRasterImageCanvas(cached);
|
|
2997
|
+
return;
|
|
2998
|
+
}
|
|
2999
|
+
const contentRect = getRasterImageContentRect(item);
|
|
3000
|
+
const viewportSize = {
|
|
3001
|
+
width: this.container.clientWidth,
|
|
3002
|
+
height: this.container.clientHeight
|
|
3003
|
+
};
|
|
3004
|
+
if (!contentRect || viewportSize.width <= 0 || viewportSize.height <= 0) {
|
|
3005
|
+
this.releaseRasterImageCanvas(cached);
|
|
3006
|
+
return;
|
|
3007
|
+
}
|
|
3008
|
+
const targetSize = getRasterImageCanvasTargetSize({
|
|
3009
|
+
intrinsicSize: item.imageIntrinsicSize,
|
|
3010
|
+
contentRect,
|
|
3011
|
+
cameraZoom: this.camera.zoom,
|
|
3012
|
+
devicePixelRatio: options.devicePixelRatio,
|
|
3013
|
+
pixelHeadroom: options.pixelHeadroom,
|
|
3014
|
+
maxPixelCount: options.maxPixelCount,
|
|
3015
|
+
maxDimension: options.maxDimension
|
|
3016
|
+
});
|
|
3017
|
+
const target = resolveRasterImageCanvasRenderTarget({
|
|
3018
|
+
item,
|
|
3019
|
+
href: item.imageRasterHref,
|
|
3020
|
+
intrinsicSize: item.imageIntrinsicSize,
|
|
3021
|
+
contentRect,
|
|
3022
|
+
targetSize,
|
|
3023
|
+
viewportSize,
|
|
3024
|
+
cameraZoom: this.camera.zoom,
|
|
3025
|
+
options
|
|
3026
|
+
});
|
|
3027
|
+
const rasterCanvas = this.ensureRasterImageCanvas(cached);
|
|
3028
|
+
this.positionRasterImageCanvas(rasterCanvas, target.contentRect);
|
|
3029
|
+
if (rasterCanvas.itemHref !== null && rasterCanvas.itemHref !== item.imageRasterHref) {
|
|
3030
|
+
this.clearRasterImageCanvasBitmap(rasterCanvas);
|
|
3031
|
+
}
|
|
3032
|
+
if (!shouldRedrawRasterImageCanvas({
|
|
3033
|
+
currentSourceKey: rasterCanvas.sourceKey,
|
|
3034
|
+
currentWidth: rasterCanvas.width,
|
|
3035
|
+
currentHeight: rasterCanvas.height,
|
|
3036
|
+
nextSourceKey: target.sourceKey,
|
|
3037
|
+
nextWidth: target.targetSize.width,
|
|
3038
|
+
nextHeight: target.targetSize.height,
|
|
3039
|
+
upscaleRedrawRatio: options.upscaleRedrawRatio
|
|
3040
|
+
})) {
|
|
3041
|
+
return;
|
|
3042
|
+
}
|
|
3043
|
+
const request = {
|
|
3044
|
+
itemHref: item.imageRasterHref,
|
|
3045
|
+
target
|
|
3046
|
+
};
|
|
3047
|
+
if (rasterCanvas.abortController) {
|
|
3048
|
+
if (rasterCanvas.loadingItemHref !== item.imageRasterHref) {
|
|
3049
|
+
rasterCanvas.abortController.abort();
|
|
3050
|
+
rasterCanvas.abortController = null;
|
|
3051
|
+
rasterCanvas.loadingItemHref = null;
|
|
3052
|
+
rasterCanvas.loadingSourceKey = null;
|
|
3053
|
+
rasterCanvas.loadingWidth = 0;
|
|
3054
|
+
rasterCanvas.loadingHeight = 0;
|
|
3055
|
+
rasterCanvas.queuedTarget = null;
|
|
3056
|
+
this.drawRasterImageCanvas(rasterCanvas, request);
|
|
3057
|
+
return;
|
|
3058
|
+
}
|
|
3059
|
+
if (rasterCanvas.loadingSourceKey === target.sourceKey && rasterCanvas.loadingWidth === target.targetSize.width && rasterCanvas.loadingHeight === target.targetSize.height) {
|
|
3060
|
+
return;
|
|
3061
|
+
}
|
|
3062
|
+
if (shouldRedrawRasterImageCanvas({
|
|
3063
|
+
currentSourceKey: rasterCanvas.loadingSourceKey,
|
|
3064
|
+
currentWidth: rasterCanvas.loadingWidth,
|
|
3065
|
+
currentHeight: rasterCanvas.loadingHeight,
|
|
3066
|
+
nextSourceKey: target.sourceKey,
|
|
3067
|
+
nextWidth: target.targetSize.width,
|
|
3068
|
+
nextHeight: target.targetSize.height,
|
|
3069
|
+
upscaleRedrawRatio: options.upscaleRedrawRatio
|
|
3070
|
+
})) {
|
|
3071
|
+
rasterCanvas.queuedTarget = request;
|
|
3072
|
+
}
|
|
3073
|
+
return;
|
|
3074
|
+
}
|
|
3075
|
+
this.drawRasterImageCanvas(rasterCanvas, request);
|
|
3076
|
+
}
|
|
3077
|
+
ensureRasterImageCanvas(cached) {
|
|
3078
|
+
if (cached.rasterCanvas) {
|
|
3079
|
+
if (!cached.rasterCanvas.foreignObject.isConnected) {
|
|
3080
|
+
cached.g.appendChild(cached.rasterCanvas.foreignObject);
|
|
3081
|
+
}
|
|
3082
|
+
return cached.rasterCanvas;
|
|
3083
|
+
}
|
|
3084
|
+
const foreignObject = document.createElementNS(
|
|
3085
|
+
"http://www.w3.org/2000/svg",
|
|
3086
|
+
"foreignObject"
|
|
3087
|
+
);
|
|
3088
|
+
foreignObject.setAttribute("data-canvu-raster-canvas", "true");
|
|
3089
|
+
foreignObject.style.pointerEvents = "none";
|
|
3090
|
+
const canvas = document.createElement("canvas");
|
|
3091
|
+
canvas.width = 1;
|
|
3092
|
+
canvas.height = 1;
|
|
3093
|
+
canvas.style.display = "block";
|
|
3094
|
+
canvas.style.width = "100%";
|
|
3095
|
+
canvas.style.height = "100%";
|
|
3096
|
+
foreignObject.appendChild(canvas);
|
|
3097
|
+
cached.g.appendChild(foreignObject);
|
|
3098
|
+
cached.rasterCanvas = {
|
|
3099
|
+
foreignObject,
|
|
3100
|
+
canvas,
|
|
3101
|
+
itemHref: null,
|
|
3102
|
+
sourceKey: null,
|
|
3103
|
+
width: 0,
|
|
3104
|
+
height: 0,
|
|
3105
|
+
loadSequence: 0,
|
|
3106
|
+
abortController: null,
|
|
3107
|
+
loadingItemHref: null,
|
|
3108
|
+
loadingSourceKey: null,
|
|
3109
|
+
loadingWidth: 0,
|
|
3110
|
+
loadingHeight: 0,
|
|
3111
|
+
queuedTarget: null
|
|
3112
|
+
};
|
|
3113
|
+
return cached.rasterCanvas;
|
|
3114
|
+
}
|
|
3115
|
+
positionRasterImageCanvas(rasterCanvas, contentRect) {
|
|
3116
|
+
rasterCanvas.foreignObject.setAttribute("x", String(contentRect.x));
|
|
3117
|
+
rasterCanvas.foreignObject.setAttribute("y", String(contentRect.y));
|
|
3118
|
+
rasterCanvas.foreignObject.setAttribute("width", String(contentRect.width));
|
|
3119
|
+
rasterCanvas.foreignObject.setAttribute("height", String(contentRect.height));
|
|
3120
|
+
}
|
|
3121
|
+
drawRasterImageCanvas(rasterCanvas, request) {
|
|
3122
|
+
const { target } = request;
|
|
3123
|
+
const width = Math.max(1, Math.round(target.targetSize.width));
|
|
3124
|
+
const height = Math.max(1, Math.round(target.targetSize.height));
|
|
3125
|
+
const sequence = rasterCanvas.loadSequence + 1;
|
|
3126
|
+
rasterCanvas.loadSequence = sequence;
|
|
3127
|
+
rasterCanvas.abortController?.abort();
|
|
3128
|
+
const abortController = new AbortController();
|
|
3129
|
+
rasterCanvas.abortController = abortController;
|
|
3130
|
+
rasterCanvas.loadingItemHref = request.itemHref;
|
|
3131
|
+
rasterCanvas.loadingSourceKey = target.sourceKey;
|
|
3132
|
+
rasterCanvas.loadingWidth = width;
|
|
3133
|
+
rasterCanvas.loadingHeight = height;
|
|
3134
|
+
rasterCanvas.queuedTarget = null;
|
|
3135
|
+
decodeRasterImage(target.href, width, height, abortController.signal).then((decoded) => {
|
|
3136
|
+
if (abortController.signal.aborted || rasterCanvas.loadSequence !== sequence) {
|
|
3137
|
+
decoded.close();
|
|
3138
|
+
return;
|
|
3139
|
+
}
|
|
3140
|
+
const context = rasterCanvas.canvas.getContext("2d");
|
|
3141
|
+
if (!context) {
|
|
3142
|
+
decoded.close();
|
|
3143
|
+
rasterCanvas.abortController = null;
|
|
3144
|
+
rasterCanvas.loadingItemHref = null;
|
|
3145
|
+
rasterCanvas.loadingSourceKey = null;
|
|
3146
|
+
rasterCanvas.loadingWidth = 0;
|
|
3147
|
+
rasterCanvas.loadingHeight = 0;
|
|
3148
|
+
this.drawQueuedRasterImageCanvasTarget(rasterCanvas);
|
|
3149
|
+
return;
|
|
3150
|
+
}
|
|
3151
|
+
rasterCanvas.canvas.width = decoded.width;
|
|
3152
|
+
rasterCanvas.canvas.height = decoded.height;
|
|
3153
|
+
context.clearRect(0, 0, decoded.width, decoded.height);
|
|
3154
|
+
decoded.draw(context);
|
|
3155
|
+
decoded.close();
|
|
3156
|
+
rasterCanvas.itemHref = request.itemHref;
|
|
3157
|
+
rasterCanvas.sourceKey = target.sourceKey;
|
|
3158
|
+
rasterCanvas.width = decoded.width;
|
|
3159
|
+
rasterCanvas.height = decoded.height;
|
|
3160
|
+
rasterCanvas.abortController = null;
|
|
3161
|
+
rasterCanvas.loadingItemHref = null;
|
|
3162
|
+
rasterCanvas.loadingSourceKey = null;
|
|
3163
|
+
rasterCanvas.loadingWidth = 0;
|
|
3164
|
+
rasterCanvas.loadingHeight = 0;
|
|
3165
|
+
this.drawQueuedRasterImageCanvasTarget(rasterCanvas);
|
|
3166
|
+
}).catch((error) => {
|
|
3167
|
+
if (abortController.signal.aborted) return;
|
|
3168
|
+
if (error instanceof Error && error.name === "AbortError") return;
|
|
3169
|
+
if (rasterCanvas.loadSequence === sequence) {
|
|
3170
|
+
rasterCanvas.abortController = null;
|
|
3171
|
+
rasterCanvas.loadingItemHref = null;
|
|
3172
|
+
rasterCanvas.loadingSourceKey = null;
|
|
3173
|
+
rasterCanvas.loadingWidth = 0;
|
|
3174
|
+
rasterCanvas.loadingHeight = 0;
|
|
3175
|
+
this.drawQueuedRasterImageCanvasTarget(rasterCanvas);
|
|
3176
|
+
}
|
|
3177
|
+
});
|
|
3178
|
+
}
|
|
3179
|
+
drawQueuedRasterImageCanvasTarget(rasterCanvas) {
|
|
3180
|
+
const queuedTarget = rasterCanvas.queuedTarget;
|
|
3181
|
+
if (!queuedTarget) return;
|
|
3182
|
+
rasterCanvas.queuedTarget = null;
|
|
3183
|
+
if (!shouldRedrawRasterImageCanvas({
|
|
3184
|
+
currentSourceKey: rasterCanvas.sourceKey,
|
|
3185
|
+
currentWidth: rasterCanvas.width,
|
|
3186
|
+
currentHeight: rasterCanvas.height,
|
|
3187
|
+
nextSourceKey: queuedTarget.target.sourceKey,
|
|
3188
|
+
nextWidth: queuedTarget.target.targetSize.width,
|
|
3189
|
+
nextHeight: queuedTarget.target.targetSize.height,
|
|
3190
|
+
upscaleRedrawRatio: this.rasterImageCanvasRendering?.upscaleRedrawRatio ?? 1
|
|
3191
|
+
})) {
|
|
3192
|
+
return;
|
|
3193
|
+
}
|
|
3194
|
+
this.drawRasterImageCanvas(rasterCanvas, queuedTarget);
|
|
3195
|
+
}
|
|
3196
|
+
clearRasterImageCanvasBitmap(rasterCanvas) {
|
|
3197
|
+
const context = rasterCanvas.canvas.getContext("2d");
|
|
3198
|
+
context?.clearRect(0, 0, rasterCanvas.canvas.width, rasterCanvas.canvas.height);
|
|
3199
|
+
rasterCanvas.canvas.width = 1;
|
|
3200
|
+
rasterCanvas.canvas.height = 1;
|
|
3201
|
+
rasterCanvas.itemHref = null;
|
|
3202
|
+
rasterCanvas.sourceKey = null;
|
|
3203
|
+
rasterCanvas.width = 0;
|
|
3204
|
+
rasterCanvas.height = 0;
|
|
3205
|
+
}
|
|
3206
|
+
releaseRasterImageCanvas(cached) {
|
|
3207
|
+
const rasterCanvas = cached.rasterCanvas;
|
|
3208
|
+
if (!rasterCanvas) return;
|
|
3209
|
+
rasterCanvas.abortController?.abort();
|
|
3210
|
+
rasterCanvas.loadSequence += 1;
|
|
3211
|
+
rasterCanvas.queuedTarget = null;
|
|
3212
|
+
rasterCanvas.foreignObject.remove();
|
|
3213
|
+
cached.rasterCanvas = void 0;
|
|
3214
|
+
}
|
|
2752
3215
|
applyInteractionAttributes(g, itemId) {
|
|
2753
3216
|
g.setAttribute(
|
|
2754
3217
|
"data-canvu-selected",
|
|
@@ -2761,6 +3224,9 @@ var SvgVectorRenderer = class {
|
|
|
2761
3224
|
}
|
|
2762
3225
|
destroy() {
|
|
2763
3226
|
this.resizeObserver.disconnect();
|
|
3227
|
+
for (const cached of this.itemNodeCache.values()) {
|
|
3228
|
+
this.releaseRasterImageCanvas(cached);
|
|
3229
|
+
}
|
|
2764
3230
|
this.itemNodeCache.clear();
|
|
2765
3231
|
this.liveOverlay = null;
|
|
2766
3232
|
this.svg.remove();
|