(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.clearSpriteRasterizationCache = exports.rasterizeSvgToTexture = void 0;
    const DEFAULT_SIZE = 128;
    const DEFAULT_RESOLUTION = 1;
    const SVG_SPRITE_CACHE = new Map();
    const resolveSize = (size, fallback) => {
        const normalized = Math.floor(size ?? fallback);
        if (!Number.isFinite(normalized) || normalized <= 0) {
            return fallback;
        }
        return normalized;
    };
    const resolveResolution = (resolution) => {
        const normalized = Math.floor(resolution ?? DEFAULT_RESOLUTION);
        if (!Number.isFinite(normalized) || normalized <= 0) {
            return DEFAULT_RESOLUTION;
        }
        return normalized;
    };
    const toErrorMessage = (error) => {
        if (error instanceof Error) {
            return error.message;
        }
        if (typeof error === 'string') {
            return error;
        }
        return 'unknown error';
    };
    const buildSpriteCacheKey = (input) => `${input.url}|${input.width}x${input.height}@${input.resolution}`;
    const loadImage = async (imageUrl) => {
        const image = new Image();
        return new Promise((resolve, reject) => {
            image.onload = () => {
                resolve(image);
            };
            image.onerror = (event) => {
                const reason = toErrorMessage(event);
                reject(new Error(`Failed to load SVG sprite '${imageUrl}'. ${reason}`));
            };
            image.src = imageUrl;
        });
    };
    /**
     * Cache by URL + target dimensions + DPR so each unique rasterization request is
     * performed once and then reused.
     */
    const getOrCreateCache = (key, create) => {
        const existing = SVG_SPRITE_CACHE.get(key);
        if (existing) {
            return existing;
        }
        const rasterized = create().catch((error) => {
            const message = toErrorMessage(error);
            SVG_SPRITE_CACHE.delete(key);
            throw new Error(`Failed to rasterize SVG sprite. ${message}`);
        });
        SVG_SPRITE_CACHE.set(key, rasterized);
        return rasterized;
    };
    /**
     * @remarks
     * "RGBA" means red-green-blue-alpha channels, one byte each.
     */
    const rasterizeSvgToTexture = async (url, options = {}) => {
        const width = resolveSize(options.width, DEFAULT_SIZE);
        const height = resolveSize(options.height, DEFAULT_SIZE);
        const resolution = resolveResolution(options.resolution);
        const payload = {
            url,
            width,
            height,
            resolution,
        };
        const key = buildSpriteCacheKey(payload);
        return getOrCreateCache(key, async () => {
            const response = await fetch(url);
            if (!response.ok) {
                throw new Error(`Failed to fetch SVG sprite '${url}'. Status: ${response.status} ${response.statusText}`);
            }
            const svgText = await response.text();
            const blob = new Blob([svgText], {
                type: 'image/svg+xml;charset=utf-8',
            });
            const blobUrl = URL.createObjectURL(blob);
            try {
                const image = await loadImage(blobUrl);
                const textureWidth = width * resolution;
                const textureHeight = height * resolution;
                const sourceWidth = Math.max(1, image.naturalWidth);
                const sourceHeight = Math.max(1, image.naturalHeight);
                const xScale = textureWidth / sourceWidth;
                const yScale = textureHeight / sourceHeight;
                const scale = Math.min(xScale, yScale);
                const scaledWidth = Math.max(1, Math.floor(sourceWidth * scale));
                const scaledHeight = Math.max(1, Math.floor(sourceHeight * scale));
                const canvas = document.createElement('canvas');
                canvas.width = textureWidth;
                canvas.height = textureHeight;
                const context = canvas.getContext('2d');
                if (!context) {
                    throw new Error(`Unable to create 2d context for rasterizing '${url}'.`);
                }
                context.clearRect(0, 0, textureWidth, textureHeight);
                context.imageSmoothingEnabled = true;
                const drawX = (textureWidth - scaledWidth) / 2;
                const drawY = (textureHeight - scaledHeight) / 2;
                context.drawImage(image, drawX, drawY, scaledWidth, scaledHeight);
                const pixelData = context.getImageData(0, 0, textureWidth, textureHeight).data;
                return {
                    width: textureWidth,
                    height: textureHeight,
                    pixels: new Uint8Array(pixelData),
                };
            }
            finally {
                URL.revokeObjectURL(blobUrl);
            }
        });
    };
    exports.rasterizeSvgToTexture = rasterizeSvgToTexture;
    const clearSpriteRasterizationCache = () => {
        SVG_SPRITE_CACHE.clear();
    };
    exports.clearSpriteRasterizationCache = clearSpriteRasterizationCache;
});
