pixi.js
Version:
<p align="center"> <a href="https://pixijs.com" target="_blank" rel="noopener noreferrer"> <img height="150" src="https://files.pixijs.download/branding/pixijs-logo-transparent-dark.svg?v=1" alt="PixiJS logo"> </a> </p> <br/> <p align="center">
1 lines • 20.8 kB
Source Map (JSON)
{"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\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(text, style, padding, resolution, canvasAndContext);\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 text - The text to render\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 */\n private _renderTextToCanvas(\n text: string,\n style: TextStyle,\n padding: number,\n resolution: number,\n canvasAndContext: CanvasAndContext\n ): void\n {\n const { canvas, context } = canvasAndContext;\n\n const font = fontStringFromTextStyle(style);\n\n const measured = CanvasTextMetrics.measureText(text || ' ', style);// , canvas);\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 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 // 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\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 else\n {\n context.fillStyle = style._fill ? getCanvasFillStyle(style._fill, context, measured) : null;\n\n if (style._stroke?.width)\n {\n const padding = style._stroke.width * style._stroke.alignment;\n\n context.strokeStyle = getCanvasFillStyle(style._stroke, context, measured, padding);\n }\n\n context.shadowColor = 'black';\n }\n\n let linePositionYShift = (lineHeight - fontProperties.fontSize) / 2;\n\n if (lineHeight - fontProperties.fontSize < 0)\n {\n linePositionYShift = 0;\n }\n\n const strokeWidth = style._stroke?.width ?? 0;\n\n // draw lines line by line\n for (let i = 0; i < lines.length; i++)\n {\n linePositionX = strokeWidth / 2;\n linePositionY = ((strokeWidth / 2) + (i * lineHeight)) + fontProperties.ascent + 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?.width)\n {\n this._drawLetterSpacing(\n lines[i],\n style,\n canvasAndContext,\n linePositionX + padding,\n linePositionY + padding - dsOffsetText,\n true\n );\n }\n\n if (style._fill !== undefined)\n {\n this._drawLetterSpacing(\n lines[i],\n style,\n canvasAndContext,\n linePositionX + padding,\n linePositionY + padding - dsOffsetText\n );\n }\n }\n }\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 * @private\n */\n private _drawLetterSpacing(\n text: string,\n style: TextStyle,\n canvasAndContext: CanvasAndContext,\n x: number, y: number,\n isStroke = false\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)\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 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 previousWidth = currentWidth;\n }\n }\n}\n\n/** @internal */\nexport const CanvasTextGenerator = new CanvasTextGeneratorClass();\n"],"names":["padding","i"],"mappings":"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"}