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/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-F6aM5C7x.cjs';
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-BSjiek7Q.js';
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();