import { defaultProfiler } from "../RenderProfiler.js";

//#region src/preview/rendering/renderToImageNative.ts
/** Track canvases that have been initialized for layoutsubtree (only need to wait once) */
const _layoutInitializedCanvases = /* @__PURE__ */ new WeakSet();
/**
* Wait for next animation frame (allows browser to complete layout)
*/
function waitForFrame() {
	return new Promise((resolve) => requestAnimationFrame(() => resolve()));
}
/**
* Create a canvas element with proper DPR handling.
* Buffer size is based on renderWidth/renderHeight (internal resolution).
* CSS size is based on fullWidth/fullHeight (logical display size).
*/
function createDprCanvas(options) {
	const { renderWidth, renderHeight, scale, fullWidth, fullHeight } = options;
	const dpr = options.dpr ?? window.devicePixelRatio ?? 1;
	const canvas = document.createElement("canvas");
	canvas.width = Math.floor(renderWidth * scale * dpr);
	canvas.height = Math.floor(renderHeight * scale * dpr);
	canvas.style.width = `${Math.floor(fullWidth * scale)}px`;
	canvas.style.height = `${Math.floor(fullHeight * scale)}px`;
	return canvas;
}
/**
* Render HTML content to canvas using native HTML-in-Canvas API (drawElementImage).
* This is much faster than the foreignObject approach and avoids canvas tainting.
*
* Note: The native API renders at device pixel ratio, so we capture at DPR scale
* and then downsample to logical pixels to match the foreignObject path's output.
*
* @param container - The HTML element to render
* @param width - Target width in logical pixels
* @param height - Target height in logical pixels
* @param options - Rendering options (skipWait for batch mode)
*
* @see https://github.com/WICG/html-in-canvas
*/
async function renderToImageNative(container, width, height, options = {}) {
	const t0 = performance.now();
	const { reuseCanvas, skipDprScaling = false } = options;
	const dpr = skipDprScaling ? 1 : window.devicePixelRatio || 1;
	let captureCanvas;
	let shouldCleanup = false;
	if (reuseCanvas) {
		captureCanvas = reuseCanvas;
		const dpr$1 = skipDprScaling ? 1 : window.devicePixelRatio || 1;
		const targetWidth = Math.floor(width * dpr$1);
		const targetHeight = Math.floor(height * dpr$1);
		if (captureCanvas.width !== targetWidth) captureCanvas.width = targetWidth;
		if (captureCanvas.height !== targetHeight) captureCanvas.height = targetHeight;
		captureCanvas.style.cssText = `
      position: fixed;
      left: 0;
      top: 0;
      width: ${width}px;
      height: ${height}px;
      opacity: 0;
      pointer-events: none;
      z-index: -9999;
    `;
		if (!captureCanvas.hasAttribute("layoutsubtree")) {
			captureCanvas.setAttribute("layoutsubtree", "");
			captureCanvas.layoutSubtree = true;
		}
		if (!captureCanvas.parentNode) document.body.appendChild(captureCanvas);
		if (container.parentElement !== captureCanvas) captureCanvas.appendChild(container);
		if (getComputedStyle(container).display === "none") container.style.display = "block";
		if (!_layoutInitializedCanvases.has(captureCanvas)) {
			captureCanvas.offsetHeight;
			container.offsetHeight;
			getComputedStyle(captureCanvas).opacity;
			getComputedStyle(container).opacity;
			_layoutInitializedCanvases.add(captureCanvas);
		}
	} else {
		captureCanvas = document.createElement("canvas");
		captureCanvas.width = Math.floor(width * dpr);
		captureCanvas.height = Math.floor(height * dpr);
		captureCanvas.setAttribute("layoutsubtree", "");
		captureCanvas.layoutSubtree = true;
		captureCanvas.appendChild(container);
		captureCanvas.style.cssText = `
      position: fixed;
      left: 0;
      top: 0;
      width: ${width}px;
      height: ${height}px;
      opacity: 0;
      pointer-events: none;
      z-index: -9999;
    `;
		document.body.appendChild(captureCanvas);
		shouldCleanup = true;
	}
	const t1 = performance.now();
	defaultProfiler.addTime("setup", t1 - t0);
	try {
		getComputedStyle(container).opacity;
		if (reuseCanvas && captureCanvas.layoutSubtree && !_layoutInitializedCanvases.has(captureCanvas)) {
			await waitForFrame();
			_layoutInitializedCanvases.add(captureCanvas);
			if (!captureCanvas.parentNode) return captureCanvas;
		}
		captureCanvas.getContext("2d").drawElementImage(container, 0, 0);
	} finally {
		if (shouldCleanup && captureCanvas.parentNode) captureCanvas.parentNode.removeChild(captureCanvas);
	}
	const t2 = performance.now();
	defaultProfiler.addTime("draw", t2 - t1);
	if (dpr === 1) {
		defaultProfiler.incrementRenderCount();
		return captureCanvas;
	}
	const outputCanvas = document.createElement("canvas");
	outputCanvas.width = width;
	outputCanvas.height = height;
	outputCanvas.getContext("2d").drawImage(captureCanvas, 0, 0, captureCanvas.width, captureCanvas.height, 0, 0, width, height);
	const t3 = performance.now();
	defaultProfiler.addTime("downsample", t3 - t2);
	defaultProfiler.incrementRenderCount();
	return outputCanvas;
}

//#endregion
export { createDprCanvas, renderToImageNative };
//# sourceMappingURL=renderToImageNative.js.map