{"version":3,"file":"CanvasTextGenerator.mjs","sources":["../../../../src/scene/text/canvas/CanvasTextGenerator.ts"],"sourcesContent":["import { Color } from '../../../color/Color';\nimport { Rectangle } from '../../../maths/shapes/Rectangle';\nimport { type CanvasAndContext, CanvasPool } from '../../../rendering/renderers/shared/texture/CanvasPool';\nimport { getCanvasBoundingBox } from '../../../utils/canvas/getCanvasBoundingBox';\nimport { type TextStyle } from '../TextStyle';\nimport { CanvasTextMetrics } from './CanvasTextMetrics';\nimport { fontStringFromTextStyle } from './utils/fontStringFromTextStyle';\nimport { getCanvasFillStyle } from './utils/getCanvasFillStyle';\n\n/**\n * Temporary rectangle for getting the bounding box of the text.\n * @internal\n */\nconst tempRect = new Rectangle();\n\nfunction countSpaces(text: string): number\n{\n    let count = 0;\n\n    for (let i = 0; i < text.length; i++)\n    {\n        if (text.charCodeAt(i) === 32) count++;\n    }\n\n    return count;\n}\n\n/**\n * Utility for generating and managing canvas-based text rendering.\n *\n * This class is responsible for rendering text to canvas elements based on provided styles,\n * measuring the resulting text dimensions, and managing the lifecycle of canvas resources.\n *\n * CanvasTextGenerator supports:\n * - Text rendering with various styles (fill, stroke, gradient, etc.)\n * - Drop shadows and letter spacing\n * - Automatic trimming of transparent pixels\n * - Canvas resource pooling\n *\n * As a singleton, it's accessed via the exported `CanvasTextGenerator` constant.\n * @example\n * ```typescript\n * // Basic usage - render text to a canvas\n * import { CanvasTextGenerator } from 'pixi.js';\n * import { TextStyle } from 'pixi.js';\n *\n * // Create a text style\n * const style = new TextStyle({\n *   fontFamily: 'Arial',\n *   fontSize: 24,\n *   fill: 0xff1010,\n *   align: 'center',\n * });\n *\n * // Get a canvas with the text rendered to it\n * const { canvasAndContext, frame } = CanvasTextGenerator.getCanvasAndContext({\n *   text: 'Hello Pixi!',\n *   style,\n *   resolution: 1\n * });\n *\n * @internal\n */\nclass CanvasTextGeneratorClass\n{\n    /**\n     * Creates a canvas with the specified text rendered to it.\n     *\n     * Generates a canvas of appropriate size, renders the text with the provided style,\n     * and returns both the canvas/context and a Rectangle representing the text bounds.\n     *\n     * When trim is enabled in the style, the frame will represent the bounds of the\n     * non-transparent pixels, which can be smaller than the full canvas.\n     * @param options - The options for generating the text canvas\n     * @param options.text - The text to render\n     * @param options.style - The style to apply to the text\n     * @param options.resolution - The resolution of the canvas (defaults to 1)\n     * @param options.padding\n     * @returns An object containing the canvas/context and the frame (bounds) of the text\n     */\n    public getCanvasAndContext(options: {text: string, style: TextStyle, resolution?: number, padding?: number})\n    {\n        const { text, style, resolution = 1 } = options;\n\n        const padding = (style as TextStyle)._getFinalPadding();\n\n        // create a canvas with the word hello on it\n        const measured = CanvasTextMetrics.measureText(text || ' ', style);\n\n        const width = Math.ceil(Math.ceil((Math.max(1, measured.width) + (padding * 2))) * resolution);\n        const height = Math.ceil(Math.ceil((Math.max(1, measured.height) + (padding * 2))) * resolution);\n\n        const canvasAndContext = CanvasPool.getOptimalCanvasAndContext(width, height);\n\n        this._renderTextToCanvas(style, padding, resolution, canvasAndContext, measured);\n\n        const frame = style.trim\n            ? getCanvasBoundingBox({ canvas: canvasAndContext.canvas, width, height, resolution: 1, output: tempRect })\n            : tempRect.set(0, 0, width, height);\n\n        return {\n            canvasAndContext,\n            frame\n        };\n    }\n\n    /**\n     * Returns a canvas and context to the pool.\n     *\n     * This should be called when you're done with the canvas to allow reuse\n     * and prevent memory leaks.\n     * @param canvasAndContext - The canvas and context to return to the pool\n     */\n    public returnCanvasAndContext(canvasAndContext: CanvasAndContext): void\n    {\n        CanvasPool.returnCanvasAndContext(canvasAndContext);\n    }\n\n    /**\n     * Renders text to its canvas, and updates its texture.\n     * @param style - The style of the text\n     * @param padding - The padding of the text\n     * @param resolution - The resolution of the text\n     * @param canvasAndContext - The canvas and context to render the text to\n     * @param measured - Pre-measured text metrics to avoid duplicate measurement\n     */\n    private _renderTextToCanvas(\n        style: TextStyle,\n        padding: number,\n        resolution: number,\n        canvasAndContext: CanvasAndContext,\n        measured: CanvasTextMetrics\n    ): void\n    {\n        // Check if we have tagged text data\n        if (measured.runsByLine && measured.runsByLine.length > 0)\n        {\n            this._renderTaggedTextToCanvas(measured, style, padding, resolution, canvasAndContext);\n\n            return;\n        }\n\n        const { canvas, context } = canvasAndContext as { canvas: HTMLCanvasElement, context: CanvasRenderingContext2D };\n\n        const font = fontStringFromTextStyle(style);\n\n        const lines = measured.lines;\n        const lineHeight = measured.lineHeight;\n        const lineWidths = measured.lineWidths;\n        const maxLineWidth = measured.maxLineWidth;\n        const fontProperties = measured.fontProperties;\n\n        const height = canvas.height;\n\n        context.resetTransform();\n        context.scale(resolution, resolution);\n        context.textBaseline = style.textBaseline;\n\n        // set stroke styles..\n\n        if (style._stroke?.width)\n        {\n            const strokeStyle = style._stroke;\n\n            context.lineWidth = strokeStyle.width;\n\n            context.miterLimit = strokeStyle.miterLimit;\n            context.lineJoin = strokeStyle.join;\n            context.lineCap = strokeStyle.cap;\n        }\n\n        // return;\n        context.font = font;\n\n        let linePositionX: number;\n        let linePositionY: number;\n\n        // require 2 passes if a shadow; the first to draw the drop shadow, the second to draw the text\n        const passesCount = style.dropShadow ? 2 : 1;\n\n        // For v4, we drew text at the colours of the drop shadow underneath the normal text. This gave the correct zIndex,\n        // but features such as alpha and shadowblur did not look right at all, since we were using actual text as a shadow.\n        //\n        // For v5.0.0, we moved over to just use the canvas API for drop shadows, which made them look much nicer and more\n        // visually please, but now because the stroke is drawn and then the fill, drop shadows would appear on both the fill\n        // and the stroke; and fill drop shadows would appear over the top of the stroke.\n        //\n        // For v5.1.1, the new route is to revert to v4 style of drawing text first to get the drop shadows underneath normal\n        // text, but instead drawing text in the correct location, we'll draw it off screen (-paddingY), and then adjust the\n        // drop shadow so only that appears on screen (+paddingY). Now we'll have the correct draw order of the shadow\n        // beneath the text, whilst also having the proper text shadow styling.\n        // Calculate alignment width - use the larger of wordWrapWidth and maxLineWidth\n        // when wrapping, so lines wider than wordWrapWidth still center correctly\n        const alignWidth = style.wordWrap ? Math.max(style.wordWrapWidth, maxLineWidth) : maxLineWidth;\n        const strokeWidth = style._stroke?.width ?? 0;\n        const halfStroke = strokeWidth / 2;\n\n        let linePositionYShift = (lineHeight - fontProperties.fontSize) / 2;\n\n        if (lineHeight - fontProperties.fontSize < 0)\n        {\n            linePositionYShift = 0;\n        }\n\n        for (let i = 0; i < passesCount; ++i)\n        {\n            const isShadowPass = style.dropShadow && i === 0;\n            // we only want the drop shadow, so put text way off-screen\n            const dsOffsetText = isShadowPass ? Math.ceil(Math.max(1, height) + (padding * 2)) : 0;\n            const dsOffsetShadow = dsOffsetText * resolution;\n\n            if (isShadowPass)\n            {\n                this._setupDropShadow(context, style, resolution, dsOffsetShadow);\n            }\n            else\n            {\n                // When gradient bounds are set (e.g., from SplitText), use them for gradient calculation\n                const gradientBounds = style._gradientBounds;\n                const gradientOffset = style._gradientOffset;\n\n                if (gradientBounds)\n                {\n                    const gradientMetrics = {\n                        width: gradientBounds.width,\n                        height: gradientBounds.height,\n                        lineHeight: gradientBounds.height,\n                        lines: measured.lines,\n                    } as CanvasTextMetrics;\n\n                    this._setFillAndStrokeStyles(\n                        context, style, gradientMetrics, padding, halfStroke,\n                        gradientOffset?.x ?? 0, gradientOffset?.y ?? 0\n                    );\n                }\n                else if (gradientOffset)\n                {\n                    this._setFillAndStrokeStyles(\n                        context, style, measured, padding, halfStroke,\n                        gradientOffset.x, gradientOffset.y\n                    );\n                }\n                else\n                {\n                    this._setFillAndStrokeStyles(context, style, measured, padding, halfStroke);\n                }\n\n                context.shadowColor = 'rgba(0,0,0,0)';\n            }\n\n            // draw lines line by line\n            for (let j = 0; j < lines.length; j++)\n            {\n                linePositionX = halfStroke;\n                linePositionY = (halfStroke + (j * lineHeight)) + fontProperties.ascent + linePositionYShift;\n\n                linePositionX += this._getAlignmentOffset(lineWidths[j], alignWidth, style.align);\n\n                let wordSpacing = 0;\n\n                if (style.align === 'justify' && style.wordWrap && j < lines.length - 1)\n                {\n                    const spaces = countSpaces(lines[j]);\n\n                    if (spaces > 0)\n                    {\n                        wordSpacing = (alignWidth - lineWidths[j]) / spaces;\n                    }\n                }\n\n                if (style._stroke?.width)\n                {\n                    this._drawLetterSpacing(\n                        lines[j],\n                        style,\n                        canvasAndContext,\n                        linePositionX + padding,\n                        linePositionY + padding - dsOffsetText,\n                        true,\n                        wordSpacing\n                    );\n                }\n\n                if (style._fill !== undefined)\n                {\n                    this._drawLetterSpacing(\n                        lines[j],\n                        style,\n                        canvasAndContext,\n                        linePositionX + padding,\n                        linePositionY + padding - dsOffsetText,\n                        false,\n                        wordSpacing\n                    );\n                }\n            }\n        }\n    }\n\n    /**\n     * Renders tagged text (with per-run styles) to canvas.\n     * @param measured - The measured text metrics containing runsByLine\n     * @param style - The base text style\n     * @param padding - The padding of the text\n     * @param resolution - The resolution of the text\n     * @param canvasAndContext - The canvas and context to render to\n     */\n    private _renderTaggedTextToCanvas(\n        measured: CanvasTextMetrics,\n        style: TextStyle,\n        padding: number,\n        resolution: number,\n        canvasAndContext: CanvasAndContext\n    ): void\n    {\n        const { canvas, context } = canvasAndContext;\n        const { runsByLine, lineWidths, maxLineWidth, lineAscents, lineHeights, hasDropShadow } = measured;\n\n        const height = canvas.height;\n\n        context.resetTransform();\n        context.scale(resolution, resolution);\n        context.textBaseline = style.textBaseline;\n\n        // require 2 passes if a shadow; the first to draw the drop shadow, the second to draw the text\n        const passesCount = hasDropShadow ? 2 : 1;\n\n        // Calculate alignment width - use the larger of wordWrapWidth and maxLineWidth\n        // when wrapping, so lines wider than wordWrapWidth still center correctly\n        const alignWidth = style.wordWrap ? Math.max(style.wordWrapWidth, maxLineWidth) : maxLineWidth;\n        let maxStrokeWidth = style._stroke?.width ?? 0;\n\n        for (const lineRuns of runsByLine)\n        {\n            for (const run of lineRuns)\n            {\n                const w = run.style._stroke?.width ?? 0;\n\n                if (w > maxStrokeWidth) maxStrokeWidth = w;\n            }\n        }\n        const halfStroke = maxStrokeWidth / 2;\n\n        // Pre-calculate run widths and font strings to avoid redundant computation per pass\n        const runDataByLine: Array<Array<{ width: number; font: string }>> = [];\n\n        for (let lineIndex = 0; lineIndex < runsByLine.length; lineIndex++)\n        {\n            const lineRuns = runsByLine[lineIndex];\n            const runData: Array<{ width: number; font: string }> = [];\n\n            for (const run of lineRuns)\n            {\n                const font = fontStringFromTextStyle(run.style);\n\n                context.font = font;\n                runData.push({\n                    width: CanvasTextMetrics._measureText(run.text, run.style.letterSpacing, context),\n                    font,\n                });\n            }\n            runDataByLine.push(runData);\n        }\n\n        for (let pass = 0; pass < passesCount; ++pass)\n        {\n            const isShadowPass = hasDropShadow && pass === 0;\n            const dsOffsetText = isShadowPass ? Math.ceil(Math.max(1, height) + (padding * 2)) : 0;\n            const dsOffsetShadow = dsOffsetText * resolution;\n\n            if (!isShadowPass)\n            {\n                context.shadowColor = 'rgba(0,0,0,0)';\n            }\n\n            let currentY = halfStroke;\n\n            // Draw lines\n            for (let lineIndex = 0; lineIndex < runsByLine.length; lineIndex++)\n            {\n                const lineRuns = runsByLine[lineIndex];\n                const lineWidth = lineWidths[lineIndex];\n                const lineAscent = lineAscents[lineIndex];\n                const currentLineHeight = lineHeights[lineIndex];\n                const lineRunData = runDataByLine[lineIndex];\n\n                // Calculate line X position based on alignment\n                let linePositionX = halfStroke;\n\n                linePositionX += this._getAlignmentOffset(lineWidth, alignWidth, style.align);\n\n                let wordSpacing = 0;\n\n                if (style.align === 'justify' && style.wordWrap && lineIndex < runsByLine.length - 1)\n                {\n                    let totalSpaces = 0;\n\n                    for (const run of lineRuns)\n                    {\n                        totalSpaces += countSpaces(run.text);\n                    }\n\n                    if (totalSpaces > 0)\n                    {\n                        wordSpacing = (alignWidth - lineWidth) / totalSpaces;\n                    }\n                }\n\n                // Calculate Y position - use line ascent for proper baseline\n                const linePositionY = currentY + lineAscent;\n\n                // Track X position for runs\n                let runX = linePositionX + padding;\n\n                // First pass: draw strokes for all runs\n                for (let runIndex = 0; runIndex < lineRuns.length; runIndex++)\n                {\n                    const run = lineRuns[runIndex];\n                    const { width: runWidth, font: runFont } = lineRunData[runIndex];\n\n                    context.font = runFont;\n                    context.textBaseline = run.style.textBaseline;\n\n                    // Set stroke style for this run\n                    if (run.style._stroke?.width)\n                    {\n                        const runStroke = run.style._stroke;\n\n                        // Always set stroke properties (both passes need correct lineWidth)\n                        context.lineWidth = runStroke.width;\n                        context.miterLimit = runStroke.miterLimit;\n                        context.lineJoin = runStroke.join;\n                        context.lineCap = runStroke.cap;\n\n                        if (isShadowPass)\n                        {\n                            // Set up drop shadow for this specific run\n                            if (run.style.dropShadow)\n                            {\n                                this._setupDropShadow(\n                                    context as CanvasRenderingContext2D,\n                                    run.style,\n                                    resolution,\n                                    dsOffsetShadow\n                                );\n                            }\n                            else\n                            {\n                                // No shadow for this run, skip drawing\n                                const spacesSkipped = countSpaces(run.text);\n\n                                runX += runWidth + (spacesSkipped * wordSpacing);\n                                continue;\n                            }\n                        }\n                        else\n                        {\n                            // Create per-run metrics for gradient calculation\n                            // Use run's font metrics for height to match non-tagged text behavior\n                            const runFontProps = CanvasTextMetrics.measureFont(runFont);\n                            const runHeight = run.style.lineHeight || runFontProps.fontSize;\n\n                            const runMetrics = {\n                                width: runWidth,\n                                height: runHeight,\n                                lineHeight: runHeight,\n                                lines: [run.text],\n                            } as CanvasTextMetrics;\n\n                            // Pass position offsets so gradient aligns with where the run is drawn\n                            // Subtract padding from runX because runX already includes padding,\n                            // but regular text rendering has gradient at origin with text at +padding\n                            context.strokeStyle = getCanvasFillStyle(\n                                runStroke, context, runMetrics, padding * 2, runX - padding, currentY\n                            );\n                        }\n\n                        this._drawLetterSpacing(\n                            run.text,\n                            run.style,\n                            canvasAndContext,\n                            runX,\n                            linePositionY + padding - dsOffsetText,\n                            true,\n                            wordSpacing\n                        );\n                    }\n\n                    const spacesInRun = countSpaces(run.text);\n\n                    runX += runWidth + (spacesInRun * wordSpacing);\n                }\n\n                // Reset X position for fill pass\n                runX = linePositionX + padding;\n\n                // Second pass: draw fills for all runs\n                for (let runIndex = 0; runIndex < lineRuns.length; runIndex++)\n                {\n                    const run = lineRuns[runIndex];\n                    const { width: runWidth, font: runFont } = lineRunData[runIndex];\n\n                    context.font = runFont;\n                    context.textBaseline = run.style.textBaseline;\n\n                    // Set fill style for this run if not shadow pass\n                    if (run.style._fill !== undefined)\n                    {\n                        if (isShadowPass)\n                        {\n                            // Set up drop shadow for this specific run\n                            if (run.style.dropShadow)\n                            {\n                                this._setupDropShadow(\n                                    context as CanvasRenderingContext2D,\n                                    run.style,\n                                    resolution,\n                                    dsOffsetShadow\n                                );\n                            }\n                            else\n                            {\n                                // No shadow for this run, skip drawing\n                                const spacesSkipped = countSpaces(run.text);\n\n                                runX += runWidth + (spacesSkipped * wordSpacing);\n                                continue;\n                            }\n                        }\n                        else\n                        {\n                            // Create per-run metrics for gradient calculation\n                            // Use run's font metrics for height to match non-tagged text behavior\n                            const runFontProps = CanvasTextMetrics.measureFont(runFont);\n                            const runHeight = run.style.lineHeight || runFontProps.fontSize;\n\n                            const runMetrics = {\n                                width: runWidth,\n                                height: runHeight,\n                                lineHeight: runHeight,\n                                lines: [run.text],\n                            } as CanvasTextMetrics;\n\n                            // Pass position offsets so gradient aligns with where the run is drawn\n                            // Subtract padding from runX because runX already includes padding,\n                            // but regular text rendering has gradient at origin with text at +padding\n                            context.fillStyle = getCanvasFillStyle(\n                                run.style._fill, context, runMetrics, padding * 2, runX - padding, currentY\n                            );\n                        }\n\n                        this._drawLetterSpacing(\n                            run.text,\n                            run.style,\n                            canvasAndContext,\n                            runX,\n                            linePositionY + padding - dsOffsetText,\n                            false,\n                            wordSpacing\n                        );\n                    }\n\n                    const spacesInFillRun = countSpaces(run.text);\n\n                    runX += runWidth + (spacesInFillRun * wordSpacing);\n                }\n\n                currentY += currentLineHeight;\n            }\n        }\n    }\n\n    /**\n     * Sets fill and stroke styles on the canvas context for text rendering.\n     * @param context - The canvas context\n     * @param style - The text style\n     * @param metrics - The text metrics for gradient calculation\n     * @param padding - The padding value\n     * @param halfStroke - Half the stroke width\n     * @param offsetX - X offset for gradient positioning\n     * @param offsetY - Y offset for gradient positioning\n     */\n    private _setFillAndStrokeStyles(\n        context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n        style: TextStyle,\n        metrics: CanvasTextMetrics,\n        padding: number,\n        halfStroke: number,\n        offsetX: number = 0,\n        offsetY: number = 0\n    ): void\n    {\n        context.fillStyle = style._fill\n            ? getCanvasFillStyle(style._fill, context, metrics, padding * 2, offsetX, offsetY)\n            : null;\n\n        if (style._stroke?.width)\n        {\n            const strokePadding = halfStroke + (padding * 2);\n\n            context.strokeStyle = getCanvasFillStyle(\n                style._stroke, context, metrics, strokePadding, offsetX, offsetY\n            );\n        }\n    }\n\n    /**\n     * Sets up the canvas context for drop shadow rendering.\n     * @param context - The canvas context\n     * @param style - The text style containing drop shadow options\n     * @param resolution - The resolution multiplier\n     * @param dsOffsetShadow - The shadow Y offset\n     */\n    private _setupDropShadow(\n        context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n        style: TextStyle,\n        resolution: number,\n        dsOffsetShadow: number\n    ): void\n    {\n        // On Safari, text with gradient and drop shadows together do not position correctly\n        // if the scale of the canvas is not 1: https://bugs.webkit.org/show_bug.cgi?id=197689\n        // Therefore we'll set the styles to be a plain black whilst generating this drop shadow\n        context.fillStyle = 'black';\n        context.strokeStyle = 'black';\n\n        const shadowOptions = style.dropShadow;\n        const dropShadowColor = shadowOptions.color;\n        const dropShadowAlpha = shadowOptions.alpha;\n\n        context.shadowColor = Color.shared\n            .setValue(dropShadowColor)\n            .setAlpha(dropShadowAlpha)\n            .toRgbaString();\n\n        const dropShadowBlur = shadowOptions.blur * resolution;\n        const dropShadowDistance = shadowOptions.distance * resolution;\n\n        context.shadowBlur = dropShadowBlur;\n        context.shadowOffsetX = Math.cos(shadowOptions.angle) * dropShadowDistance;\n        context.shadowOffsetY = (Math.sin(shadowOptions.angle) * dropShadowDistance) + dsOffsetShadow;\n    }\n\n    /**\n     * Calculates the X offset for text alignment.\n     * @param lineWidth - The width of the current line\n     * @param alignWidth - The width to align against (maxLineWidth or wordWrapWidth)\n     * @param align - The text alignment\n     * @returns The X offset for this line\n     */\n    private _getAlignmentOffset(lineWidth: number, alignWidth: number, align: string): number\n    {\n        if (align === 'right')\n        {\n            return alignWidth - lineWidth;\n        }\n        else if (align === 'center')\n        {\n            return (alignWidth - lineWidth) / 2;\n        }\n\n        return 0;\n    }\n\n    /**\n     * Render the text with letter-spacing.\n     *\n     * This method handles rendering text with the correct letter spacing, using either:\n     * 1. Native letter spacing if supported by the browser\n     * 2. Manual letter spacing calculation if not natively supported\n     *\n     * For manual letter spacing, it calculates the position of each character\n     * based on its width and the desired spacing.\n     * @param text - The text to draw\n     * @param style - The text style to apply\n     * @param canvasAndContext - The canvas and context to draw to\n     * @param x - Horizontal position to draw the text\n     * @param y - Vertical position to draw the text\n     * @param isStroke - Whether to render the stroke (true) or fill (false)\n     * @param wordSpacing - Extra spacing to add between words (for justify alignment)\n     * @private\n     */\n    private _drawLetterSpacing(\n        text: string,\n        style: TextStyle,\n        canvasAndContext: CanvasAndContext,\n        x: number, y: number,\n        isStroke = false,\n        wordSpacing = 0\n    ): void\n    {\n        const { context } = canvasAndContext;\n\n        // letterSpacing of 0 means normal\n        const letterSpacing = style.letterSpacing;\n\n        let useExperimentalLetterSpacing = false;\n\n        if (CanvasTextMetrics.experimentalLetterSpacingSupported)\n        {\n            if (CanvasTextMetrics.experimentalLetterSpacing)\n            {\n                context.letterSpacing = `${letterSpacing}px`;\n                context.textLetterSpacing = `${letterSpacing}px`;\n                useExperimentalLetterSpacing = true;\n            }\n            else\n            {\n                context.letterSpacing = '0px';\n                context.textLetterSpacing = '0px';\n            }\n        }\n\n        if ((letterSpacing === 0 || useExperimentalLetterSpacing) && wordSpacing === 0)\n        {\n            if (isStroke)\n            {\n                context.strokeText(text, x, y);\n            }\n            else\n            {\n                context.fillText(text, x, y);\n            }\n\n            return;\n        }\n\n        if (wordSpacing !== 0 && (letterSpacing === 0 || useExperimentalLetterSpacing))\n        {\n            const words = text.split(' ');\n            let currentPosition = x;\n            const spaceWidth = context.measureText(' ').width;\n\n            for (let i = 0; i < words.length; i++)\n            {\n                if (isStroke)\n                {\n                    context.strokeText(words[i], currentPosition, y);\n                }\n                else\n                {\n                    context.fillText(words[i], currentPosition, y);\n                }\n\n                currentPosition += context.measureText(words[i]).width + spaceWidth + wordSpacing;\n            }\n\n            return;\n        }\n\n        let currentPosition = x;\n\n        const stringArray = CanvasTextMetrics.graphemeSegmenter(text);\n        let previousWidth = context.measureText(text).width;\n        let currentWidth = 0;\n\n        for (let i = 0; i < stringArray.length; ++i)\n        {\n            const currentChar = stringArray[i];\n\n            if (isStroke)\n            {\n                context.strokeText(currentChar, currentPosition, y);\n            }\n            else\n            {\n                context.fillText(currentChar, currentPosition, y);\n            }\n            let textStr = '';\n\n            for (let j = i + 1; j < stringArray.length; ++j)\n            {\n                textStr += stringArray[j];\n            }\n            currentWidth = context.measureText(textStr).width;\n            currentPosition += previousWidth - currentWidth + letterSpacing;\n            if (currentChar === ' ') currentPosition += wordSpacing;\n            previousWidth = currentWidth;\n        }\n    }\n}\n\n/** @internal */\nexport const CanvasTextGenerator = new CanvasTextGeneratorClass();\n"],"names":["currentPosition"],"mappings":"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"}