{"version":3,"file":"Text.mjs","sources":["../src/Text.ts"],"sourcesContent":["/* eslint max-depth: [2, 8] */\nimport { Color, Rectangle, settings, Texture, utils } from '@pixi/core';\nimport { Sprite } from '@pixi/sprite';\nimport { TEXT_GRADIENT } from './const';\nimport { TextMetrics } from './TextMetrics';\nimport { TextStyle } from './TextStyle';\n\nimport type { ICanvas, ICanvasRenderingContext2D, Renderer } from '@pixi/core';\nimport type { IDestroyOptions } from '@pixi/display';\nimport type { ITextStyle } from './TextStyle';\n\nconst defaultDestroyOptions: IDestroyOptions = {\n    texture: true,\n    children: false,\n    baseTexture: true,\n};\n\n/**\n * A Text Object will create a line or multiple lines of text.\n *\n * The text is created using the [Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API).\n *\n * The primary advantage of this class over BitmapText is that you have great control over the style of the text,\n * which you can change at runtime.\n *\n * The primary disadvantages is that each piece of text has it's own texture, which can use more memory.\n * When text changes, this texture has to be re-generated and re-uploaded to the GPU, taking up time.\n *\n * To split a line you can use '\\n' in your text string, or, on the `style` object,\n * change its `wordWrap` property to true and and give the `wordWrapWidth` property a value.\n *\n * A Text can be created directly from a string and a style object,\n * which can be generated [here](https://pixijs.io/pixi-text-style).\n * @example\n * import { Text } from 'pixi.js';\n *\n * const text = new Text('This is a PixiJS text', {\n *     fontFamily: 'Arial',\n *     fontSize: 24,\n *     fill: 0xff1010,\n *     align: 'center',\n * });\n * @memberof PIXI\n */\nexport class Text extends Sprite\n{\n    /**\n     * Override whether or not the resolution of the text is automatically adjusted to match the resolution of the renderer.\n     * Setting this to false can allow you to get crisper text at lower render resolutions.\n     * @example\n     * // renderer has a resolution of 1\n     * const app = new Application();\n     *\n     * Text.defaultResolution = 2;\n     * Text.defaultAutoResolution = false;\n     * // text has a resolution of 2\n     * const text = new Text('This is a PixiJS text');\n     */\n    public static defaultAutoResolution = true;\n\n    /**\n     * If {@link PIXI.Text.defaultAutoResolution} is false, this will be the default resolution of the text.\n     * If not set it will default to {@link PIXI.settings.RESOLUTION}.\n     * @example\n     * Text.defaultResolution = 2;\n     * Text.defaultAutoResolution = false;\n     *\n     * // text has a resolution of 2\n     * const text = new Text('This is a PixiJS text');\n     */\n    public static defaultResolution: number;\n\n    /**\n     * @see PIXI.TextMetrics.experimentalLetterSpacing\n     * @deprecated since 7.1.0\n     */\n    public static get experimentalLetterSpacing()\n    {\n        return TextMetrics.experimentalLetterSpacing;\n    }\n    public static set experimentalLetterSpacing(value)\n    {\n        if (process.env.DEBUG)\n        {\n            utils.deprecation('7.1.0',\n                'Text.experimentalLetterSpacing is deprecated, use TextMetrics.experimentalLetterSpacing');\n        }\n\n        TextMetrics.experimentalLetterSpacing = value;\n    }\n\n    /** The canvas element that everything is drawn to. */\n    public canvas: ICanvas;\n    /** The canvas 2d context that everything is drawn with. */\n    public context: ICanvasRenderingContext2D;\n    public localStyleID: number;\n    public dirty: boolean;\n\n    /**\n     * The resolution / device pixel ratio of the canvas.\n     *\n     * This is set to automatically match the renderer resolution by default, but can be overridden by setting manually.\n     * @default PIXI.settings.RESOLUTION\n     */\n    _resolution: number;\n    _autoResolution: boolean;\n\n    /**\n     * Private tracker for the current text.\n     * @private\n     */\n    protected _text: string;\n\n    /**\n     * Private tracker for the current font.\n     * @private\n     */\n    protected _font: string;\n\n    /**\n     * Private tracker for the current style.\n     * @private\n     */\n    protected _style: TextStyle;\n\n    /**\n     * Private listener to track style changes.\n     * @private\n     */\n    protected _styleListener: () => void;\n\n    /**\n     * Keep track if this Text object created it's own canvas\n     * element (`true`) or uses the constructor argument (`false`).\n     * Used to workaround a GC issues with Safari < 13 when\n     * destroying Text. See `destroy` for more info.\n     */\n    private _ownCanvas: boolean;\n\n    /**\n     * @param text - The string that you would like the text to display\n     * @param style - The style parameters\n     * @param canvas - The canvas element for drawing text\n     */\n    constructor(text?: string | number, style?: Partial<ITextStyle> | TextStyle, canvas?: ICanvas)\n    {\n        let ownCanvas = false;\n\n        if (!canvas)\n        {\n            canvas = settings.ADAPTER.createCanvas();\n            ownCanvas = true;\n        }\n\n        canvas.width = 3;\n        canvas.height = 3;\n\n        const texture = Texture.from(canvas);\n\n        texture.orig = new Rectangle();\n        texture.trim = new Rectangle();\n\n        super(texture);\n\n        this._ownCanvas = ownCanvas;\n        this.canvas = canvas;\n        this.context = canvas.getContext('2d', {\n            // required for trimming to work without warnings\n            willReadFrequently: true,\n        });\n\n        this._resolution = Text.defaultResolution ?? settings.RESOLUTION;\n        this._autoResolution = Text.defaultAutoResolution;\n        this._text = null;\n        this._style = null;\n        this._styleListener = null;\n        this._font = '';\n\n        this.text = text;\n        this.style = style;\n\n        this.localStyleID = -1;\n    }\n\n    /**\n     * Renders text to its canvas, and updates its texture.\n     *\n     * By default this is used internally to ensure the texture is correct before rendering,\n     * but it can be used called externally, for example from this class to 'pre-generate' the texture from a piece of text,\n     * and then shared across multiple Sprites.\n     * @param respectDirty - Whether to abort updating the text if the Text isn't dirty and the function is called.\n     */\n    public updateText(respectDirty: boolean): void\n    {\n        const style = this._style;\n\n        // check if style has changed..\n        if (this.localStyleID !== style.styleID)\n        {\n            this.dirty = true;\n            this.localStyleID = style.styleID;\n        }\n\n        if (!this.dirty && respectDirty)\n        {\n            return;\n        }\n\n        this._font = this._style.toFontString();\n\n        const context = this.context;\n        const measured = TextMetrics.measureText(this._text || ' ', this._style, this._style.wordWrap, this.canvas);\n        const width = measured.width;\n        const height = measured.height;\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        this.canvas.width = Math.ceil(Math.ceil((Math.max(1, width) + (style.padding * 2))) * this._resolution);\n        this.canvas.height = Math.ceil(Math.ceil((Math.max(1, height) + (style.padding * 2))) * this._resolution);\n\n        context.scale(this._resolution, this._resolution);\n\n        context.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n        context.font = this._font;\n        context.lineWidth = style.strokeThickness;\n        context.textBaseline = style.textBaseline;\n        context.lineJoin = style.lineJoin;\n        context.miterLimit = style.miterLimit;\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        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) + (style.padding * 2)) : 0;\n            const dsOffsetShadow = dsOffsetText * this._resolution;\n\n            if (isShadowPass)\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 dropShadowColor = style.dropShadowColor;\n                const dropShadowBlur = style.dropShadowBlur * this._resolution;\n                const dropShadowDistance = style.dropShadowDistance * this._resolution;\n\n                context.shadowColor = Color.shared\n                    .setValue(dropShadowColor)\n                    .setAlpha(style.dropShadowAlpha)\n                    .toRgbaString();\n                context.shadowBlur = dropShadowBlur;\n                context.shadowOffsetX = Math.cos(style.dropShadowAngle) * dropShadowDistance;\n                context.shadowOffsetY = (Math.sin(style.dropShadowAngle) * dropShadowDistance) + dsOffsetShadow;\n            }\n            else\n            {\n                // set canvas text styles\n                context.fillStyle = this._generateFillStyle(style, lines, measured);\n                // TODO: Can't have different types for getter and setter. The getter shouldn't have the number type as\n                //       the setter converts to string. See this thread for more details:\n                //       https://github.com/microsoft/TypeScript/issues/2521\n                context.strokeStyle = style.stroke as string;\n\n                context.shadowColor = 'black';\n                context.shadowBlur = 0;\n                context.shadowOffsetX = 0;\n                context.shadowOffsetY = 0;\n            }\n\n            let linePositionYShift = (lineHeight - fontProperties.fontSize) / 2;\n\n            if (lineHeight - fontProperties.fontSize < 0)\n            {\n                linePositionYShift = 0;\n            }\n\n            // draw lines line by line\n            for (let i = 0; i < lines.length; i++)\n            {\n                linePositionX = style.strokeThickness / 2;\n                linePositionY = ((style.strokeThickness / 2) + (i * lineHeight)) + fontProperties.ascent\n                    + linePositionYShift;\n\n                if (style.align === 'right')\n                {\n                    linePositionX += maxLineWidth - lineWidths[i];\n                }\n                else if (style.align === 'center')\n                {\n                    linePositionX += (maxLineWidth - lineWidths[i]) / 2;\n                }\n\n                if (style.stroke && style.strokeThickness)\n                {\n                    this.drawLetterSpacing(\n                        lines[i],\n                        linePositionX + style.padding,\n                        linePositionY + style.padding - dsOffsetText,\n                        true\n                    );\n                }\n\n                if (style.fill)\n                {\n                    this.drawLetterSpacing(\n                        lines[i],\n                        linePositionX + style.padding,\n                        linePositionY + style.padding - dsOffsetText\n                    );\n                }\n            }\n        }\n\n        this.updateTexture();\n    }\n\n    /**\n     * Render the text with letter-spacing.\n     * @param text - The text to draw\n     * @param x - Horizontal position to draw the text\n     * @param y - Vertical position to draw the text\n     * @param isStroke - Is this drawing for the outside stroke of the\n     *  text? If not, it's for the inside fill\n     */\n    private drawLetterSpacing(text: string, x: number, y: number, isStroke = false): void\n    {\n        const style = this._style;\n\n        // letterSpacing of 0 means normal\n        const letterSpacing = style.letterSpacing;\n\n        let useExperimentalLetterSpacing = false;\n\n        if (TextMetrics.experimentalLetterSpacingSupported)\n        {\n            if (TextMetrics.experimentalLetterSpacing)\n            {\n                this.context.letterSpacing = `${letterSpacing}px`;\n                this.context.textLetterSpacing = `${letterSpacing}px`;\n                useExperimentalLetterSpacing = true;\n            }\n            else\n            {\n                this.context.letterSpacing = '0px';\n                this.context.textLetterSpacing = '0px';\n            }\n        }\n\n        if (letterSpacing === 0 || useExperimentalLetterSpacing)\n        {\n            if (isStroke)\n            {\n                this.context.strokeText(text, x, y);\n            }\n            else\n            {\n                this.context.fillText(text, x, y);\n            }\n\n            return;\n        }\n\n        let currentPosition = x;\n\n        const stringArray = TextMetrics.graphemeSegmenter(text);\n        let previousWidth = this.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                this.context.strokeText(currentChar, currentPosition, y);\n            }\n            else\n            {\n                this.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 = this.context.measureText(textStr).width;\n            currentPosition += previousWidth - currentWidth + letterSpacing;\n            previousWidth = currentWidth;\n        }\n    }\n\n    /** Updates texture size based on canvas size. */\n    private updateTexture(): void\n    {\n        const canvas = this.canvas;\n\n        if (this._style.trim)\n        {\n            const trimmed = utils.trimCanvas(canvas);\n\n            if (trimmed.data)\n            {\n                canvas.width = trimmed.width;\n                canvas.height = trimmed.height;\n                this.context.putImageData(trimmed.data, 0, 0);\n            }\n        }\n\n        const texture = this._texture;\n        const style = this._style;\n        const padding = style.trim ? 0 : style.padding;\n        const baseTexture = texture.baseTexture;\n\n        texture.trim.width = texture._frame.width = canvas.width / this._resolution;\n        texture.trim.height = texture._frame.height = canvas.height / this._resolution;\n        texture.trim.x = -padding;\n        texture.trim.y = -padding;\n\n        texture.orig.width = texture._frame.width - (padding * 2);\n        texture.orig.height = texture._frame.height - (padding * 2);\n\n        // call sprite onTextureUpdate to update scale if _width or _height were set\n        this._onTextureUpdate();\n\n        baseTexture.setRealSize(canvas.width, canvas.height, this._resolution);\n\n        texture.updateUvs();\n\n        this.dirty = false;\n    }\n\n    /**\n     * Renders the object using the WebGL renderer\n     * @param renderer - The renderer\n     */\n    protected _render(renderer: Renderer): void\n    {\n        if (this._autoResolution && this._resolution !== renderer.resolution)\n        {\n            this._resolution = renderer.resolution;\n            this.dirty = true;\n        }\n\n        this.updateText(true);\n\n        super._render(renderer);\n    }\n\n    /** Updates the transform on all children of this container for rendering. */\n    public updateTransform(): void\n    {\n        this.updateText(true);\n\n        super.updateTransform();\n    }\n\n    public getBounds(skipUpdate?: boolean, rect?: Rectangle): Rectangle\n    {\n        this.updateText(true);\n\n        if (this._textureID === -1)\n        {\n            // texture was updated: recalculate transforms\n            skipUpdate = false;\n        }\n\n        return super.getBounds(skipUpdate, rect);\n    }\n\n    /**\n     * Gets the local bounds of the text object.\n     * @param rect - The output rectangle.\n     * @returns The bounds.\n     */\n    public getLocalBounds(rect?: Rectangle): Rectangle\n    {\n        this.updateText(true);\n\n        return super.getLocalBounds.call(this, rect);\n    }\n\n    /** Calculates the bounds of the Text as a rectangle. The bounds calculation takes the worldTransform into account. */\n    protected _calculateBounds(): void\n    {\n        this.calculateVertices();\n        // if we have already done this on THIS frame.\n        this._bounds.addQuad(this.vertexData);\n    }\n\n    /**\n     * Generates the fill style. Can automatically generate a gradient based on the fill style being an array\n     * @param style - The style.\n     * @param lines - The lines of text.\n     * @param metrics\n     * @returns The fill style\n     */\n    private _generateFillStyle(\n        style: TextStyle, lines: string[], metrics: TextMetrics\n    ): string | CanvasGradient | CanvasPattern\n    {\n        // TODO: Can't have different types for getter and setter. The getter shouldn't have the number type as\n        //       the setter converts to string. See this thread for more details:\n        //       https://github.com/microsoft/TypeScript/issues/2521\n        const fillStyle: string | string[] | CanvasGradient | CanvasPattern = style.fill as any;\n\n        if (!Array.isArray(fillStyle))\n        {\n            return fillStyle;\n        }\n        else if (fillStyle.length === 1)\n        {\n            return fillStyle[0];\n        }\n\n        // the gradient will be evenly spaced out according to how large the array is.\n        // ['#FF0000', '#00FF00', '#0000FF'] would created stops at 0.25, 0.5 and 0.75\n        let gradient: string[] | CanvasGradient;\n\n        // a dropshadow will enlarge the canvas and result in the gradient being\n        // generated with the incorrect dimensions\n        const dropShadowCorrection = (style.dropShadow) ? style.dropShadowDistance : 0;\n\n        // should also take padding into account, padding can offset the gradient\n        const padding = style.padding || 0;\n\n        const width = (this.canvas.width / this._resolution) - dropShadowCorrection - (padding * 2);\n        const height = (this.canvas.height / this._resolution) - dropShadowCorrection - (padding * 2);\n\n        // make a copy of the style settings, so we can manipulate them later\n        const fill = fillStyle.slice();\n        const fillGradientStops = style.fillGradientStops.slice();\n\n        // wanting to evenly distribute the fills. So an array of 4 colours should give fills of 0.25, 0.5 and 0.75\n        if (!fillGradientStops.length)\n        {\n            const lengthPlus1 = fill.length + 1;\n\n            for (let i = 1; i < lengthPlus1; ++i)\n            {\n                fillGradientStops.push(i / lengthPlus1);\n            }\n        }\n\n        // stop the bleeding of the last gradient on the line above to the top gradient of the this line\n        // by hard defining the first gradient colour at point 0, and last gradient colour at point 1\n        fill.unshift(fillStyle[0]);\n        fillGradientStops.unshift(0);\n\n        fill.push(fillStyle[fillStyle.length - 1]);\n        fillGradientStops.push(1);\n\n        if (style.fillGradientType === TEXT_GRADIENT.LINEAR_VERTICAL)\n        {\n            // start the gradient at the top center of the canvas, and end at the bottom middle of the canvas\n            gradient = this.context.createLinearGradient(width / 2, padding, width / 2, height + padding);\n\n            // we need to repeat the gradient so that each individual line of text has the same vertical gradient effect\n            // ['#FF0000', '#00FF00', '#0000FF'] over 2 lines would create stops at 0.125, 0.25, 0.375, 0.625, 0.75, 0.875\n\n            // Actual height of the text itself, not counting spacing for lineHeight/leading/dropShadow etc\n            const textHeight = metrics.fontProperties.fontSize + style.strokeThickness;\n\n            for (let i = 0; i < lines.length; i++)\n            {\n                const lastLineBottom = (metrics.lineHeight * (i - 1)) + textHeight;\n                const thisLineTop = metrics.lineHeight * i;\n                let thisLineGradientStart = thisLineTop;\n\n                // Handle case where last & this line overlap\n                if (i > 0 && lastLineBottom > thisLineTop)\n                {\n                    thisLineGradientStart = (thisLineTop + lastLineBottom) / 2;\n                }\n\n                const thisLineBottom = thisLineTop + textHeight;\n                const nextLineTop = metrics.lineHeight * (i + 1);\n                let thisLineGradientEnd = thisLineBottom;\n\n                // Handle case where this & next line overlap\n                if (i + 1 < lines.length && nextLineTop < thisLineBottom)\n                {\n                    thisLineGradientEnd = (thisLineBottom + nextLineTop) / 2;\n                }\n\n                // textHeight, but as a 0-1 size in global gradient stop space\n                const gradStopLineHeight = (thisLineGradientEnd - thisLineGradientStart) / height;\n\n                for (let j = 0; j < fill.length; j++)\n                {\n                    // 0-1 stop point for the current line, multiplied to global space afterwards\n                    let lineStop = 0;\n\n                    if (typeof fillGradientStops[j] === 'number')\n                    {\n                        lineStop = fillGradientStops[j];\n                    }\n                    else\n                    {\n                        lineStop = j / fill.length;\n                    }\n\n                    let globalStop = Math.min(1, Math.max(0,\n                        (thisLineGradientStart / height) + (lineStop * gradStopLineHeight)));\n\n                    // There's potential for floating point precision issues at the seams between gradient repeats.\n                    globalStop = Number(globalStop.toFixed(5));\n                    gradient.addColorStop(globalStop, fill[j]);\n                }\n            }\n        }\n        else\n        {\n            // start the gradient at the center left of the canvas, and end at the center right of the canvas\n            gradient = this.context.createLinearGradient(padding, height / 2, width + padding, height / 2);\n\n            // can just evenly space out the gradients in this case, as multiple lines makes no difference\n            // to an even left to right gradient\n            const totalIterations = fill.length + 1;\n            let currentIteration = 1;\n\n            for (let i = 0; i < fill.length; i++)\n            {\n                let stop: number;\n\n                if (typeof fillGradientStops[i] === 'number')\n                {\n                    stop = fillGradientStops[i];\n                }\n                else\n                {\n                    stop = currentIteration / totalIterations;\n                }\n                gradient.addColorStop(stop, fill[i]);\n                currentIteration++;\n            }\n        }\n\n        return gradient;\n    }\n\n    /**\n     * Destroys this text object.\n     *\n     * Note* Unlike a Sprite, a Text object will automatically destroy its baseTexture and texture as\n     * the majority of the time the texture will not be shared with any other Sprites.\n     * @param options - Options parameter. A boolean will act as if all options\n     *  have been set to that value\n     * @param {boolean} [options.children=false] - if set to true, all the children will have their\n     *  destroy method called as well. 'options' will be passed on to those calls.\n     * @param {boolean} [options.texture=true] - Should it destroy the current texture of the sprite as well\n     * @param {boolean} [options.baseTexture=true] - Should it destroy the base texture of the sprite as well\n     */\n    public destroy(options?: IDestroyOptions | boolean): void\n    {\n        if (typeof options === 'boolean')\n        {\n            options = { children: options };\n        }\n\n        options = Object.assign({}, defaultDestroyOptions, options);\n\n        super.destroy(options);\n\n        // set canvas width and height to 0 to workaround memory leak in Safari < 13\n        // https://stackoverflow.com/questions/52532614/total-canvas-memory-use-exceeds-the-maximum-limit-safari-12\n        if (this._ownCanvas)\n        {\n            this.canvas.height = this.canvas.width = 0;\n        }\n\n        // make sure to reset the context and canvas.. dont want this hanging around in memory!\n        this.context = null;\n        this.canvas = null;\n\n        this._style = null;\n    }\n\n    /** The width of the Text, setting this will actually modify the scale to achieve the value set. */\n    get width(): number\n    {\n        this.updateText(true);\n\n        return Math.abs(this.scale.x) * this._texture.orig.width;\n    }\n\n    set width(value: number)\n    {\n        this.updateText(true);\n\n        const s = utils.sign(this.scale.x) || 1;\n\n        this.scale.x = s * value / this._texture.orig.width;\n        this._width = value;\n    }\n\n    /** The height of the Text, setting this will actually modify the scale to achieve the value set. */\n    get height(): number\n    {\n        this.updateText(true);\n\n        return Math.abs(this.scale.y) * this._texture.orig.height;\n    }\n\n    set height(value: number)\n    {\n        this.updateText(true);\n\n        const s = utils.sign(this.scale.y) || 1;\n\n        this.scale.y = s * value / this._texture.orig.height;\n        this._height = value;\n    }\n\n    /**\n     * Set the style of the text.\n     *\n     * Set up an event listener to listen for changes on the style object and mark the text as dirty.\n     *\n     * If setting the `style` can also be partial {@link PIXI.ITextStyle}.\n     */\n    get style(): TextStyle\n    {\n        return this._style;\n    }\n\n    set style(style: TextStyle | Partial<ITextStyle>)\n    {\n        style = style || {};\n\n        if (style instanceof TextStyle)\n        {\n            this._style = style;\n        }\n        else\n        {\n            this._style = new TextStyle(style);\n        }\n\n        this.localStyleID = -1;\n        this.dirty = true;\n    }\n\n    /** Set the copy for the text object. To split a line you can use '\\n'. */\n    get text(): string\n    {\n        return this._text;\n    }\n\n    set text(text: string | number)\n    {\n        text = String(text === null || text === undefined ? '' : text);\n\n        if (this._text === text)\n        {\n            return;\n        }\n        this._text = text;\n        this.dirty = true;\n    }\n\n    /**\n     * The resolution / device pixel ratio of the canvas.\n     *\n     * This is set to automatically match the renderer resolution by default, but can be overridden by setting manually.\n     * @default 1\n     */\n    get resolution(): number\n    {\n        return this._resolution;\n    }\n\n    set resolution(value: number)\n    {\n        this._autoResolution = false;\n\n        if (this._resolution === value)\n        {\n            return;\n        }\n\n        this._resolution = value;\n        this.dirty = true;\n    }\n}\n"],"names":["_Text","i"],"mappings":"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"}