{"version":3,"file":"loadSVG.mjs","sources":["../../../../../src/assets/loader/parsers/textures/loadSVG.ts"],"sourcesContent":["import { DOMAdapter } from '../../../../environment/adapter';\nimport { type ImageLike } from '../../../../environment/ImageLike';\nimport { ExtensionType } from '../../../../extensions/Extensions';\nimport { ImageSource } from '../../../../rendering/renderers/shared/texture/sources/ImageSource';\nimport { GraphicsContext } from '../../../../scene/graphics/shared/GraphicsContext';\nimport { getResolutionOfUrl } from '../../../../utils/network/getResolutionOfUrl';\nimport { checkDataUrl } from '../../../utils/checkDataUrl';\nimport { checkExtension } from '../../../utils/checkExtension';\nimport { type LoaderParser, LoaderParserPriority } from '../LoaderParser';\nimport { createTexture } from './utils/createTexture';\n\nimport type { TextureSourceOptions } from '../../../../rendering/renderers/shared/texture/sources/TextureSource';\nimport type { Texture } from '../../../../rendering/renderers/shared/texture/Texture';\nimport type { ResolvedAsset } from '../../../types';\nimport type { Loader } from '../../Loader';\n\n/**\n * Configuration for the {@link loadSvg} plugin.\n * @see loadSvg\n * @category assets\n * @advanced\n */\nexport interface LoadSVGConfig\n{\n    /**\n     * The crossOrigin value to use for loading the SVG as an image.\n     * @default 'anonymous'\n     */\n    crossOrigin: ImageLike['crossOrigin'];\n    /**\n     * When set to `true`, loading and decoding images will happen with `new Image()`,\n     * @default false\n     */\n    parseAsGraphicsContext: boolean;\n}\n\n/**\n * Regular expression for SVG XML document.\n * @example &lt;?xml version=\"1.0\" encoding=\"utf-8\" ?&gt;&lt;!-- image/svg --&gt;&lt;svg\n * @readonly\n */\nconst validSVGExtension = '.svg';\nconst validSVGMIME = 'image/svg+xml';\n\n/**\n * A simple loader plugin for loading json data\n * @category assets\n * @advanced\n */\nexport const loadSvg: LoaderParser<Texture | GraphicsContext, TextureSourceOptions & LoadSVGConfig, LoadSVGConfig> = {\n    extension: {\n        type: ExtensionType.LoadParser,\n        priority: LoaderParserPriority.Low,\n        name: 'loadSVG',\n    },\n\n    /** used for deprecation purposes */\n    name: 'loadSVG',\n    id: 'svg',\n\n    config: {\n        crossOrigin: 'anonymous',\n        parseAsGraphicsContext: false,\n    },\n\n    test(url: string): boolean\n    {\n        return checkDataUrl(url, validSVGMIME) || checkExtension(url, validSVGExtension);\n    },\n\n    async load(\n        url: string,\n        asset: ResolvedAsset<TextureSourceOptions & LoadSVGConfig>,\n        loader: Loader\n    ): Promise<Texture | GraphicsContext>\n    {\n        if (asset.data?.parseAsGraphicsContext ?? this.config.parseAsGraphicsContext)\n        {\n            return loadAsGraphics(url);\n        }\n\n        return loadAsTexture(url, asset, loader, this.config.crossOrigin);\n    },\n\n    unload(asset: Texture | GraphicsContext): void\n    {\n        asset.destroy(true);\n    }\n\n};\n\nasync function loadAsTexture(\n    url: string,\n    asset: ResolvedAsset<TextureSourceOptions & LoadSVGConfig>,\n    loader: Loader,\n    crossOrigin: ImageLike['crossOrigin']\n): Promise<Texture>\n{\n    const response = await DOMAdapter.get().fetch(url);\n\n    const image = DOMAdapter.get().createImage();\n\n    image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(await response.text())}`;\n    image.crossOrigin = crossOrigin;\n    await image.decode();\n\n    // convert to canvas...\n    const width = asset.data?.width ?? image.width;\n    const height = asset.data?.height ?? image.height;\n    const resolution = asset.data?.resolution || getResolutionOfUrl(url);\n\n    // Ensure canvas dimensions are integers to prevent edge trimming\n    const canvasWidth = Math.ceil(width * resolution);\n    const canvasHeight = Math.ceil(height * resolution);\n\n    const canvas = DOMAdapter.get().createCanvas(canvasWidth, canvasHeight);\n    const context = canvas.getContext('2d');\n\n    // Improve rendering quality for decimal resolutions\n    context.imageSmoothingEnabled = true;\n    context.imageSmoothingQuality = 'high';\n\n    // Draw image with exact scaled dimensions to prevent trimming\n    context.drawImage(image as CanvasImageSource, 0, 0, width * resolution, height * resolution);\n\n    const { parseAsGraphicsContext: _p, ...rest } = asset.data ?? {};\n    const base = new ImageSource({\n        resource: canvas,\n        alphaMode: 'premultiply-alpha-on-upload',\n        resolution,\n        ...rest,\n    });\n\n    return createTexture(base, loader, url);\n}\n\nasync function loadAsGraphics(url: string): Promise<GraphicsContext>\n{\n    const response = await DOMAdapter.get().fetch(url);\n    const svgSource = await response.text();\n\n    const context = new GraphicsContext();\n\n    context.svg(svgSource);\n\n    return context;\n}\n"],"names":[],"mappings":"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"}