1 line
36 KiB
Plaintext
1 line
36 KiB
Plaintext
{"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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"} |