sdfsdfs
This commit is contained in:
246
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextMetrics.d.ts
generated
vendored
Normal file
246
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextMetrics.d.ts
generated
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
import type { ICanvas } from '../../../environment/canvas/ICanvas';
|
||||
import type { ICanvasRenderingContext2D } from '../../../environment/canvas/ICanvasRenderingContext2D';
|
||||
import type { TextStyle } from '../TextStyle';
|
||||
/**
|
||||
* A number, or a string containing a number.
|
||||
* @memberof text
|
||||
* @typedef {object} FontMetrics
|
||||
* @property {number} ascent - Font ascent
|
||||
* @property {number} descent - Font descent
|
||||
* @property {number} fontSize - Font size
|
||||
*/
|
||||
export interface FontMetrics {
|
||||
ascent: number;
|
||||
descent: number;
|
||||
fontSize: number;
|
||||
}
|
||||
/**
|
||||
* The TextMetrics object represents the measurement of a block of text with a specified style.
|
||||
* @example
|
||||
* import { TextMetrics, TextStyle } from 'pixi.js';
|
||||
*
|
||||
* const style = new TextStyle({
|
||||
* fontFamily: 'Arial',
|
||||
* fontSize: 24,
|
||||
* fill: 0xff1010,
|
||||
* align: 'center',
|
||||
* });
|
||||
* const textMetrics = TextMetrics.measureText('Your text', style);
|
||||
* @memberof text
|
||||
*/
|
||||
export declare class CanvasTextMetrics {
|
||||
/** The text that was measured. */
|
||||
text: string;
|
||||
/** The style that was measured. */
|
||||
style: TextStyle;
|
||||
/** The measured width of the text. */
|
||||
width: number;
|
||||
/** The measured height of the text. */
|
||||
height: number;
|
||||
/** An array of lines of the text broken by new lines and wrapping is specified in style. */
|
||||
lines: string[];
|
||||
/** An array of the line widths for each line matched to `lines`. */
|
||||
lineWidths: number[];
|
||||
/** The measured line height for this style. */
|
||||
lineHeight: number;
|
||||
/** The maximum line width for all measured lines. */
|
||||
maxLineWidth: number;
|
||||
/** The font properties object from TextMetrics.measureFont. */
|
||||
fontProperties: FontMetrics;
|
||||
/**
|
||||
* String used for calculate font metrics.
|
||||
* These characters are all tall to help calculate the height required for text.
|
||||
*/
|
||||
static METRICS_STRING: string;
|
||||
/** Baseline symbol for calculate font metrics. */
|
||||
static BASELINE_SYMBOL: string;
|
||||
/** Baseline multiplier for calculate font metrics. */
|
||||
static BASELINE_MULTIPLIER: number;
|
||||
/** Height multiplier for setting height of canvas to calculate font metrics. */
|
||||
static HEIGHT_MULTIPLIER: number;
|
||||
/**
|
||||
* A Unicode "character", or "grapheme cluster", can be composed of multiple Unicode code points,
|
||||
* such as letters with diacritical marks (e.g. `'\u0065\u0301'`, letter e with acute)
|
||||
* or emojis with modifiers (e.g. `'\uD83E\uDDD1\u200D\uD83D\uDCBB'`, technologist).
|
||||
* The new `Intl.Segmenter` API in ES2022 can split the string into grapheme clusters correctly. If it is not available,
|
||||
* PixiJS will fallback to use the iterator of String, which can only spilt the string into code points.
|
||||
* If you want to get full functionality in environments that don't support `Intl.Segmenter` (such as Firefox),
|
||||
* you can use other libraries such as [grapheme-splitter]{@link https://www.npmjs.com/package/grapheme-splitter}
|
||||
* or [graphemer]{@link https://www.npmjs.com/package/graphemer} to create a polyfill. Since these libraries can be
|
||||
* relatively large in size to handle various Unicode grapheme clusters properly, PixiJS won't use them directly.
|
||||
*/
|
||||
static graphemeSegmenter: (s: string) => string[];
|
||||
static _experimentalLetterSpacingSupported?: boolean;
|
||||
/**
|
||||
* Checking that we can use modern canvas 2D API.
|
||||
*
|
||||
* Note: This is an unstable API, Chrome < 94 use `textLetterSpacing`, later versions use `letterSpacing`.
|
||||
* @see TextMetrics.experimentalLetterSpacing
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/ICanvasRenderingContext2D/letterSpacing
|
||||
* @see https://developer.chrome.com/origintrials/#/view_trial/3585991203293757441
|
||||
*/
|
||||
static get experimentalLetterSpacingSupported(): boolean;
|
||||
/**
|
||||
* New rendering behavior for letter-spacing which uses Chrome's new native API. This will
|
||||
* lead to more accurate letter-spacing results because it does not try to manually draw
|
||||
* each character. However, this Chrome API is experimental and may not serve all cases yet.
|
||||
* @see TextMetrics.experimentalLetterSpacingSupported
|
||||
*/
|
||||
static experimentalLetterSpacing: boolean;
|
||||
/** Cache of {@see TextMetrics.FontMetrics} objects. */
|
||||
private static _fonts;
|
||||
/** Cache of new line chars. */
|
||||
private static readonly _newlines;
|
||||
/** Cache of breaking spaces. */
|
||||
private static readonly _breakingSpaces;
|
||||
private static __canvas;
|
||||
private static __context;
|
||||
private static readonly _measurementCache;
|
||||
/**
|
||||
* @param text - the text that was measured
|
||||
* @param style - the style that was measured
|
||||
* @param width - the measured width of the text
|
||||
* @param height - the measured height of the text
|
||||
* @param lines - an array of the lines of text broken by new lines and wrapping if specified in style
|
||||
* @param lineWidths - an array of the line widths for each line matched to `lines`
|
||||
* @param lineHeight - the measured line height for this style
|
||||
* @param maxLineWidth - the maximum line width for all measured lines
|
||||
* @param {FontMetrics} fontProperties - the font properties object from TextMetrics.measureFont
|
||||
*/
|
||||
constructor(text: string, style: TextStyle, width: number, height: number, lines: string[], lineWidths: number[], lineHeight: number, maxLineWidth: number, fontProperties: FontMetrics);
|
||||
/**
|
||||
* Measures the supplied string of text and returns a Rectangle.
|
||||
* @param text - The text to measure.
|
||||
* @param style - The text style to use for measuring
|
||||
* @param canvas - optional specification of the canvas to use for measuring.
|
||||
* @param wordWrap
|
||||
* @returns Measured width and height of the text.
|
||||
*/
|
||||
static measureText(text: string, style: TextStyle, canvas?: ICanvas, wordWrap?: boolean): CanvasTextMetrics;
|
||||
private static _measureText;
|
||||
/**
|
||||
* Applies newlines to a string to have it optimally fit into the horizontal
|
||||
* bounds set by the Text object's wordWrapWidth property.
|
||||
* @param text - String to apply word wrapping to
|
||||
* @param style - the style to use when wrapping
|
||||
* @param canvas - optional specification of the canvas to use for measuring.
|
||||
* @returns New string with new lines applied where required
|
||||
*/
|
||||
private static _wordWrap;
|
||||
/**
|
||||
* Convenience function for logging each line added during the wordWrap method.
|
||||
* @param line - The line of text to add
|
||||
* @param newLine - Add new line character to end
|
||||
* @returns A formatted line
|
||||
*/
|
||||
private static _addLine;
|
||||
/**
|
||||
* Gets & sets the widths of calculated characters in a cache object
|
||||
* @param key - The key
|
||||
* @param letterSpacing - The letter spacing
|
||||
* @param cache - The cache
|
||||
* @param context - The canvas context
|
||||
* @returns The from cache.
|
||||
*/
|
||||
private static _getFromCache;
|
||||
/**
|
||||
* Determines whether we should collapse breaking spaces.
|
||||
* @param whiteSpace - The TextStyle property whiteSpace
|
||||
* @returns Should collapse
|
||||
*/
|
||||
private static _collapseSpaces;
|
||||
/**
|
||||
* Determines whether we should collapse newLine chars.
|
||||
* @param whiteSpace - The white space
|
||||
* @returns should collapse
|
||||
*/
|
||||
private static _collapseNewlines;
|
||||
/**
|
||||
* Trims breaking whitespaces from string.
|
||||
* @param text - The text
|
||||
* @returns Trimmed string
|
||||
*/
|
||||
private static _trimRight;
|
||||
/**
|
||||
* Determines if char is a newline.
|
||||
* @param char - The character
|
||||
* @returns True if newline, False otherwise.
|
||||
*/
|
||||
private static _isNewline;
|
||||
/**
|
||||
* Determines if char is a breaking whitespace.
|
||||
*
|
||||
* It allows one to determine whether char should be a breaking whitespace
|
||||
* For example certain characters in CJK langs or numbers.
|
||||
* It must return a boolean.
|
||||
* @param char - The character
|
||||
* @param [_nextChar] - The next character
|
||||
* @returns True if whitespace, False otherwise.
|
||||
*/
|
||||
static isBreakingSpace(char: string, _nextChar?: string): boolean;
|
||||
/**
|
||||
* Splits a string into words, breaking-spaces and newLine characters
|
||||
* @param text - The text
|
||||
* @returns A tokenized array
|
||||
*/
|
||||
private static _tokenize;
|
||||
/**
|
||||
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
|
||||
*
|
||||
* It allows one to customise which words should break
|
||||
* Examples are if the token is CJK or numbers.
|
||||
* It must return a boolean.
|
||||
* @param _token - The token
|
||||
* @param breakWords - The style attr break words
|
||||
* @returns Whether to break word or not
|
||||
*/
|
||||
static canBreakWords(_token: string, breakWords: boolean): boolean;
|
||||
/**
|
||||
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
|
||||
*
|
||||
* It allows one to determine whether a pair of characters
|
||||
* should be broken by newlines
|
||||
* For example certain characters in CJK langs or numbers.
|
||||
* It must return a boolean.
|
||||
* @param _char - The character
|
||||
* @param _nextChar - The next character
|
||||
* @param _token - The token/word the characters are from
|
||||
* @param _index - The index in the token of the char
|
||||
* @param _breakWords - The style attr break words
|
||||
* @returns whether to break word or not
|
||||
*/
|
||||
static canBreakChars(_char: string, _nextChar: string, _token: string, _index: number, _breakWords: boolean): boolean;
|
||||
/**
|
||||
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
|
||||
*
|
||||
* It is called when a token (usually a word) has to be split into separate pieces
|
||||
* in order to determine the point to break a word.
|
||||
* It must return an array of characters.
|
||||
* @param token - The token to split
|
||||
* @returns The characters of the token
|
||||
* @see CanvasTextMetrics.graphemeSegmenter
|
||||
*/
|
||||
static wordWrapSplit(token: string): string[];
|
||||
/**
|
||||
* Calculates the ascent, descent and fontSize of a given font-style
|
||||
* @param font - String representing the style of the font
|
||||
* @returns Font properties object
|
||||
*/
|
||||
static measureFont(font: string): FontMetrics;
|
||||
/**
|
||||
* Clear font metrics in metrics cache.
|
||||
* @param {string} [font] - font name. If font name not set then clear cache for all fonts.
|
||||
*/
|
||||
static clearMetrics(font?: string): void;
|
||||
/**
|
||||
* Cached canvas element for measuring text
|
||||
* TODO: this should be private, but isn't because of backward compat, will fix later.
|
||||
* @ignore
|
||||
*/
|
||||
static get _canvas(): ICanvas;
|
||||
/**
|
||||
* TODO: this should be private, but isn't because of backward compat, will fix later.
|
||||
* @ignore
|
||||
*/
|
||||
static get _context(): ICanvasRenderingContext2D;
|
||||
}
|
532
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextMetrics.js
generated
vendored
Normal file
532
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextMetrics.js
generated
vendored
Normal file
@@ -0,0 +1,532 @@
|
||||
'use strict';
|
||||
|
||||
var adapter = require('../../../environment/adapter.js');
|
||||
var fontStringFromTextStyle = require('./utils/fontStringFromTextStyle.js');
|
||||
|
||||
"use strict";
|
||||
const contextSettings = {
|
||||
// TextMetrics requires getImageData readback for measuring fonts.
|
||||
willReadFrequently: true
|
||||
};
|
||||
const _CanvasTextMetrics = class _CanvasTextMetrics {
|
||||
/**
|
||||
* Checking that we can use modern canvas 2D API.
|
||||
*
|
||||
* Note: This is an unstable API, Chrome < 94 use `textLetterSpacing`, later versions use `letterSpacing`.
|
||||
* @see TextMetrics.experimentalLetterSpacing
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/ICanvasRenderingContext2D/letterSpacing
|
||||
* @see https://developer.chrome.com/origintrials/#/view_trial/3585991203293757441
|
||||
*/
|
||||
static get experimentalLetterSpacingSupported() {
|
||||
let result = _CanvasTextMetrics._experimentalLetterSpacingSupported;
|
||||
if (result !== void 0) {
|
||||
const proto = adapter.DOMAdapter.get().getCanvasRenderingContext2D().prototype;
|
||||
result = _CanvasTextMetrics._experimentalLetterSpacingSupported = "letterSpacing" in proto || "textLetterSpacing" in proto;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* @param text - the text that was measured
|
||||
* @param style - the style that was measured
|
||||
* @param width - the measured width of the text
|
||||
* @param height - the measured height of the text
|
||||
* @param lines - an array of the lines of text broken by new lines and wrapping if specified in style
|
||||
* @param lineWidths - an array of the line widths for each line matched to `lines`
|
||||
* @param lineHeight - the measured line height for this style
|
||||
* @param maxLineWidth - the maximum line width for all measured lines
|
||||
* @param {FontMetrics} fontProperties - the font properties object from TextMetrics.measureFont
|
||||
*/
|
||||
constructor(text, style, width, height, lines, lineWidths, lineHeight, maxLineWidth, fontProperties) {
|
||||
this.text = text;
|
||||
this.style = style;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.lines = lines;
|
||||
this.lineWidths = lineWidths;
|
||||
this.lineHeight = lineHeight;
|
||||
this.maxLineWidth = maxLineWidth;
|
||||
this.fontProperties = fontProperties;
|
||||
}
|
||||
/**
|
||||
* Measures the supplied string of text and returns a Rectangle.
|
||||
* @param text - The text to measure.
|
||||
* @param style - The text style to use for measuring
|
||||
* @param canvas - optional specification of the canvas to use for measuring.
|
||||
* @param wordWrap
|
||||
* @returns Measured width and height of the text.
|
||||
*/
|
||||
static measureText(text = " ", style, canvas = _CanvasTextMetrics._canvas, wordWrap = style.wordWrap) {
|
||||
const textKey = `${text}:${style.styleKey}`;
|
||||
if (_CanvasTextMetrics._measurementCache[textKey])
|
||||
return _CanvasTextMetrics._measurementCache[textKey];
|
||||
const font = fontStringFromTextStyle.fontStringFromTextStyle(style);
|
||||
const fontProperties = _CanvasTextMetrics.measureFont(font);
|
||||
if (fontProperties.fontSize === 0) {
|
||||
fontProperties.fontSize = style.fontSize;
|
||||
fontProperties.ascent = style.fontSize;
|
||||
}
|
||||
const context = _CanvasTextMetrics.__context;
|
||||
context.font = font;
|
||||
const outputText = wordWrap ? _CanvasTextMetrics._wordWrap(text, style, canvas) : text;
|
||||
const lines = outputText.split(/(?:\r\n|\r|\n)/);
|
||||
const lineWidths = new Array(lines.length);
|
||||
let maxLineWidth = 0;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const lineWidth = _CanvasTextMetrics._measureText(lines[i], style.letterSpacing, context);
|
||||
lineWidths[i] = lineWidth;
|
||||
maxLineWidth = Math.max(maxLineWidth, lineWidth);
|
||||
}
|
||||
const strokeWidth = style._stroke?.width || 0;
|
||||
let width = maxLineWidth + strokeWidth;
|
||||
if (style.dropShadow) {
|
||||
width += style.dropShadow.distance;
|
||||
}
|
||||
const lineHeight = style.lineHeight || fontProperties.fontSize;
|
||||
let height = Math.max(lineHeight, fontProperties.fontSize + strokeWidth) + (lines.length - 1) * (lineHeight + style.leading);
|
||||
if (style.dropShadow) {
|
||||
height += style.dropShadow.distance;
|
||||
}
|
||||
const measurements = new _CanvasTextMetrics(
|
||||
text,
|
||||
style,
|
||||
width,
|
||||
height,
|
||||
lines,
|
||||
lineWidths,
|
||||
lineHeight + style.leading,
|
||||
maxLineWidth,
|
||||
fontProperties
|
||||
);
|
||||
return measurements;
|
||||
}
|
||||
static _measureText(text, letterSpacing, context) {
|
||||
let useExperimentalLetterSpacing = false;
|
||||
if (_CanvasTextMetrics.experimentalLetterSpacingSupported) {
|
||||
if (_CanvasTextMetrics.experimentalLetterSpacing) {
|
||||
context.letterSpacing = `${letterSpacing}px`;
|
||||
context.textLetterSpacing = `${letterSpacing}px`;
|
||||
useExperimentalLetterSpacing = true;
|
||||
} else {
|
||||
context.letterSpacing = "0px";
|
||||
context.textLetterSpacing = "0px";
|
||||
}
|
||||
}
|
||||
let width = context.measureText(text).width;
|
||||
if (width > 0) {
|
||||
if (useExperimentalLetterSpacing) {
|
||||
width -= letterSpacing;
|
||||
} else {
|
||||
width += (_CanvasTextMetrics.graphemeSegmenter(text).length - 1) * letterSpacing;
|
||||
}
|
||||
}
|
||||
return width;
|
||||
}
|
||||
/**
|
||||
* Applies newlines to a string to have it optimally fit into the horizontal
|
||||
* bounds set by the Text object's wordWrapWidth property.
|
||||
* @param text - String to apply word wrapping to
|
||||
* @param style - the style to use when wrapping
|
||||
* @param canvas - optional specification of the canvas to use for measuring.
|
||||
* @returns New string with new lines applied where required
|
||||
*/
|
||||
static _wordWrap(text, style, canvas = _CanvasTextMetrics._canvas) {
|
||||
const context = canvas.getContext("2d", contextSettings);
|
||||
let width = 0;
|
||||
let line = "";
|
||||
let lines = "";
|
||||
const cache = /* @__PURE__ */ Object.create(null);
|
||||
const { letterSpacing, whiteSpace } = style;
|
||||
const collapseSpaces = _CanvasTextMetrics._collapseSpaces(whiteSpace);
|
||||
const collapseNewlines = _CanvasTextMetrics._collapseNewlines(whiteSpace);
|
||||
let canPrependSpaces = !collapseSpaces;
|
||||
const wordWrapWidth = style.wordWrapWidth + letterSpacing;
|
||||
const tokens = _CanvasTextMetrics._tokenize(text);
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
let token = tokens[i];
|
||||
if (_CanvasTextMetrics._isNewline(token)) {
|
||||
if (!collapseNewlines) {
|
||||
lines += _CanvasTextMetrics._addLine(line);
|
||||
canPrependSpaces = !collapseSpaces;
|
||||
line = "";
|
||||
width = 0;
|
||||
continue;
|
||||
}
|
||||
token = " ";
|
||||
}
|
||||
if (collapseSpaces) {
|
||||
const currIsBreakingSpace = _CanvasTextMetrics.isBreakingSpace(token);
|
||||
const lastIsBreakingSpace = _CanvasTextMetrics.isBreakingSpace(line[line.length - 1]);
|
||||
if (currIsBreakingSpace && lastIsBreakingSpace) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const tokenWidth = _CanvasTextMetrics._getFromCache(token, letterSpacing, cache, context);
|
||||
if (tokenWidth > wordWrapWidth) {
|
||||
if (line !== "") {
|
||||
lines += _CanvasTextMetrics._addLine(line);
|
||||
line = "";
|
||||
width = 0;
|
||||
}
|
||||
if (_CanvasTextMetrics.canBreakWords(token, style.breakWords)) {
|
||||
const characters = _CanvasTextMetrics.wordWrapSplit(token);
|
||||
for (let j = 0; j < characters.length; j++) {
|
||||
let char = characters[j];
|
||||
let lastChar = char;
|
||||
let k = 1;
|
||||
while (characters[j + k]) {
|
||||
const nextChar = characters[j + k];
|
||||
if (!_CanvasTextMetrics.canBreakChars(lastChar, nextChar, token, j, style.breakWords)) {
|
||||
char += nextChar;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
lastChar = nextChar;
|
||||
k++;
|
||||
}
|
||||
j += k - 1;
|
||||
const characterWidth = _CanvasTextMetrics._getFromCache(char, letterSpacing, cache, context);
|
||||
if (characterWidth + width > wordWrapWidth) {
|
||||
lines += _CanvasTextMetrics._addLine(line);
|
||||
canPrependSpaces = false;
|
||||
line = "";
|
||||
width = 0;
|
||||
}
|
||||
line += char;
|
||||
width += characterWidth;
|
||||
}
|
||||
} else {
|
||||
if (line.length > 0) {
|
||||
lines += _CanvasTextMetrics._addLine(line);
|
||||
line = "";
|
||||
width = 0;
|
||||
}
|
||||
const isLastToken = i === tokens.length - 1;
|
||||
lines += _CanvasTextMetrics._addLine(token, !isLastToken);
|
||||
canPrependSpaces = false;
|
||||
line = "";
|
||||
width = 0;
|
||||
}
|
||||
} else {
|
||||
if (tokenWidth + width > wordWrapWidth) {
|
||||
canPrependSpaces = false;
|
||||
lines += _CanvasTextMetrics._addLine(line);
|
||||
line = "";
|
||||
width = 0;
|
||||
}
|
||||
if (line.length > 0 || !_CanvasTextMetrics.isBreakingSpace(token) || canPrependSpaces) {
|
||||
line += token;
|
||||
width += tokenWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
lines += _CanvasTextMetrics._addLine(line, false);
|
||||
return lines;
|
||||
}
|
||||
/**
|
||||
* Convenience function for logging each line added during the wordWrap method.
|
||||
* @param line - The line of text to add
|
||||
* @param newLine - Add new line character to end
|
||||
* @returns A formatted line
|
||||
*/
|
||||
static _addLine(line, newLine = true) {
|
||||
line = _CanvasTextMetrics._trimRight(line);
|
||||
line = newLine ? `${line}
|
||||
` : line;
|
||||
return line;
|
||||
}
|
||||
/**
|
||||
* Gets & sets the widths of calculated characters in a cache object
|
||||
* @param key - The key
|
||||
* @param letterSpacing - The letter spacing
|
||||
* @param cache - The cache
|
||||
* @param context - The canvas context
|
||||
* @returns The from cache.
|
||||
*/
|
||||
static _getFromCache(key, letterSpacing, cache, context) {
|
||||
let width = cache[key];
|
||||
if (typeof width !== "number") {
|
||||
width = _CanvasTextMetrics._measureText(key, letterSpacing, context) + letterSpacing;
|
||||
cache[key] = width;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
/**
|
||||
* Determines whether we should collapse breaking spaces.
|
||||
* @param whiteSpace - The TextStyle property whiteSpace
|
||||
* @returns Should collapse
|
||||
*/
|
||||
static _collapseSpaces(whiteSpace) {
|
||||
return whiteSpace === "normal" || whiteSpace === "pre-line";
|
||||
}
|
||||
/**
|
||||
* Determines whether we should collapse newLine chars.
|
||||
* @param whiteSpace - The white space
|
||||
* @returns should collapse
|
||||
*/
|
||||
static _collapseNewlines(whiteSpace) {
|
||||
return whiteSpace === "normal";
|
||||
}
|
||||
/**
|
||||
* Trims breaking whitespaces from string.
|
||||
* @param text - The text
|
||||
* @returns Trimmed string
|
||||
*/
|
||||
static _trimRight(text) {
|
||||
if (typeof text !== "string") {
|
||||
return "";
|
||||
}
|
||||
for (let i = text.length - 1; i >= 0; i--) {
|
||||
const char = text[i];
|
||||
if (!_CanvasTextMetrics.isBreakingSpace(char)) {
|
||||
break;
|
||||
}
|
||||
text = text.slice(0, -1);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
/**
|
||||
* Determines if char is a newline.
|
||||
* @param char - The character
|
||||
* @returns True if newline, False otherwise.
|
||||
*/
|
||||
static _isNewline(char) {
|
||||
if (typeof char !== "string") {
|
||||
return false;
|
||||
}
|
||||
return _CanvasTextMetrics._newlines.includes(char.charCodeAt(0));
|
||||
}
|
||||
/**
|
||||
* Determines if char is a breaking whitespace.
|
||||
*
|
||||
* It allows one to determine whether char should be a breaking whitespace
|
||||
* For example certain characters in CJK langs or numbers.
|
||||
* It must return a boolean.
|
||||
* @param char - The character
|
||||
* @param [_nextChar] - The next character
|
||||
* @returns True if whitespace, False otherwise.
|
||||
*/
|
||||
static isBreakingSpace(char, _nextChar) {
|
||||
if (typeof char !== "string") {
|
||||
return false;
|
||||
}
|
||||
return _CanvasTextMetrics._breakingSpaces.includes(char.charCodeAt(0));
|
||||
}
|
||||
/**
|
||||
* Splits a string into words, breaking-spaces and newLine characters
|
||||
* @param text - The text
|
||||
* @returns A tokenized array
|
||||
*/
|
||||
static _tokenize(text) {
|
||||
const tokens = [];
|
||||
let token = "";
|
||||
if (typeof text !== "string") {
|
||||
return tokens;
|
||||
}
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
const char = text[i];
|
||||
const nextChar = text[i + 1];
|
||||
if (_CanvasTextMetrics.isBreakingSpace(char, nextChar) || _CanvasTextMetrics._isNewline(char)) {
|
||||
if (token !== "") {
|
||||
tokens.push(token);
|
||||
token = "";
|
||||
}
|
||||
tokens.push(char);
|
||||
continue;
|
||||
}
|
||||
token += char;
|
||||
}
|
||||
if (token !== "") {
|
||||
tokens.push(token);
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
/**
|
||||
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
|
||||
*
|
||||
* It allows one to customise which words should break
|
||||
* Examples are if the token is CJK or numbers.
|
||||
* It must return a boolean.
|
||||
* @param _token - The token
|
||||
* @param breakWords - The style attr break words
|
||||
* @returns Whether to break word or not
|
||||
*/
|
||||
static canBreakWords(_token, breakWords) {
|
||||
return breakWords;
|
||||
}
|
||||
/**
|
||||
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
|
||||
*
|
||||
* It allows one to determine whether a pair of characters
|
||||
* should be broken by newlines
|
||||
* For example certain characters in CJK langs or numbers.
|
||||
* It must return a boolean.
|
||||
* @param _char - The character
|
||||
* @param _nextChar - The next character
|
||||
* @param _token - The token/word the characters are from
|
||||
* @param _index - The index in the token of the char
|
||||
* @param _breakWords - The style attr break words
|
||||
* @returns whether to break word or not
|
||||
*/
|
||||
static canBreakChars(_char, _nextChar, _token, _index, _breakWords) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
|
||||
*
|
||||
* It is called when a token (usually a word) has to be split into separate pieces
|
||||
* in order to determine the point to break a word.
|
||||
* It must return an array of characters.
|
||||
* @param token - The token to split
|
||||
* @returns The characters of the token
|
||||
* @see CanvasTextMetrics.graphemeSegmenter
|
||||
*/
|
||||
static wordWrapSplit(token) {
|
||||
return _CanvasTextMetrics.graphemeSegmenter(token);
|
||||
}
|
||||
/**
|
||||
* Calculates the ascent, descent and fontSize of a given font-style
|
||||
* @param font - String representing the style of the font
|
||||
* @returns Font properties object
|
||||
*/
|
||||
static measureFont(font) {
|
||||
if (_CanvasTextMetrics._fonts[font]) {
|
||||
return _CanvasTextMetrics._fonts[font];
|
||||
}
|
||||
const context = _CanvasTextMetrics._context;
|
||||
context.font = font;
|
||||
const metrics = context.measureText(_CanvasTextMetrics.METRICS_STRING + _CanvasTextMetrics.BASELINE_SYMBOL);
|
||||
const properties = {
|
||||
ascent: metrics.actualBoundingBoxAscent,
|
||||
descent: metrics.actualBoundingBoxDescent,
|
||||
fontSize: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
|
||||
};
|
||||
_CanvasTextMetrics._fonts[font] = properties;
|
||||
return properties;
|
||||
}
|
||||
/**
|
||||
* Clear font metrics in metrics cache.
|
||||
* @param {string} [font] - font name. If font name not set then clear cache for all fonts.
|
||||
*/
|
||||
static clearMetrics(font = "") {
|
||||
if (font) {
|
||||
delete _CanvasTextMetrics._fonts[font];
|
||||
} else {
|
||||
_CanvasTextMetrics._fonts = {};
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Cached canvas element for measuring text
|
||||
* TODO: this should be private, but isn't because of backward compat, will fix later.
|
||||
* @ignore
|
||||
*/
|
||||
static get _canvas() {
|
||||
if (!_CanvasTextMetrics.__canvas) {
|
||||
let canvas;
|
||||
try {
|
||||
const c = new OffscreenCanvas(0, 0);
|
||||
const context = c.getContext("2d", contextSettings);
|
||||
if (context?.measureText) {
|
||||
_CanvasTextMetrics.__canvas = c;
|
||||
return c;
|
||||
}
|
||||
canvas = adapter.DOMAdapter.get().createCanvas();
|
||||
} catch (ex) {
|
||||
canvas = adapter.DOMAdapter.get().createCanvas();
|
||||
}
|
||||
canvas.width = canvas.height = 10;
|
||||
_CanvasTextMetrics.__canvas = canvas;
|
||||
}
|
||||
return _CanvasTextMetrics.__canvas;
|
||||
}
|
||||
/**
|
||||
* TODO: this should be private, but isn't because of backward compat, will fix later.
|
||||
* @ignore
|
||||
*/
|
||||
static get _context() {
|
||||
if (!_CanvasTextMetrics.__context) {
|
||||
_CanvasTextMetrics.__context = _CanvasTextMetrics._canvas.getContext("2d", contextSettings);
|
||||
}
|
||||
return _CanvasTextMetrics.__context;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* String used for calculate font metrics.
|
||||
* These characters are all tall to help calculate the height required for text.
|
||||
*/
|
||||
_CanvasTextMetrics.METRICS_STRING = "|\xC9q\xC5";
|
||||
/** Baseline symbol for calculate font metrics. */
|
||||
_CanvasTextMetrics.BASELINE_SYMBOL = "M";
|
||||
/** Baseline multiplier for calculate font metrics. */
|
||||
_CanvasTextMetrics.BASELINE_MULTIPLIER = 1.4;
|
||||
/** Height multiplier for setting height of canvas to calculate font metrics. */
|
||||
_CanvasTextMetrics.HEIGHT_MULTIPLIER = 2;
|
||||
/**
|
||||
* A Unicode "character", or "grapheme cluster", can be composed of multiple Unicode code points,
|
||||
* such as letters with diacritical marks (e.g. `'\u0065\u0301'`, letter e with acute)
|
||||
* or emojis with modifiers (e.g. `'\uD83E\uDDD1\u200D\uD83D\uDCBB'`, technologist).
|
||||
* The new `Intl.Segmenter` API in ES2022 can split the string into grapheme clusters correctly. If it is not available,
|
||||
* PixiJS will fallback to use the iterator of String, which can only spilt the string into code points.
|
||||
* If you want to get full functionality in environments that don't support `Intl.Segmenter` (such as Firefox),
|
||||
* you can use other libraries such as [grapheme-splitter]{@link https://www.npmjs.com/package/grapheme-splitter}
|
||||
* or [graphemer]{@link https://www.npmjs.com/package/graphemer} to create a polyfill. Since these libraries can be
|
||||
* relatively large in size to handle various Unicode grapheme clusters properly, PixiJS won't use them directly.
|
||||
*/
|
||||
_CanvasTextMetrics.graphemeSegmenter = (() => {
|
||||
if (typeof Intl?.Segmenter === "function") {
|
||||
const segmenter = new Intl.Segmenter();
|
||||
return (s) => [...segmenter.segment(s)].map((x) => x.segment);
|
||||
}
|
||||
return (s) => [...s];
|
||||
})();
|
||||
/**
|
||||
* New rendering behavior for letter-spacing which uses Chrome's new native API. This will
|
||||
* lead to more accurate letter-spacing results because it does not try to manually draw
|
||||
* each character. However, this Chrome API is experimental and may not serve all cases yet.
|
||||
* @see TextMetrics.experimentalLetterSpacingSupported
|
||||
*/
|
||||
_CanvasTextMetrics.experimentalLetterSpacing = false;
|
||||
/** Cache of {@see TextMetrics.FontMetrics} objects. */
|
||||
_CanvasTextMetrics._fonts = {};
|
||||
/** Cache of new line chars. */
|
||||
_CanvasTextMetrics._newlines = [
|
||||
10,
|
||||
// line feed
|
||||
13
|
||||
// carriage return
|
||||
];
|
||||
/** Cache of breaking spaces. */
|
||||
_CanvasTextMetrics._breakingSpaces = [
|
||||
9,
|
||||
// character tabulation
|
||||
32,
|
||||
// space
|
||||
8192,
|
||||
// en quad
|
||||
8193,
|
||||
// em quad
|
||||
8194,
|
||||
// en space
|
||||
8195,
|
||||
// em space
|
||||
8196,
|
||||
// three-per-em space
|
||||
8197,
|
||||
// four-per-em space
|
||||
8198,
|
||||
// six-per-em space
|
||||
8200,
|
||||
// punctuation space
|
||||
8201,
|
||||
// thin space
|
||||
8202,
|
||||
// hair space
|
||||
8287,
|
||||
// medium mathematical space
|
||||
12288
|
||||
// ideographic space
|
||||
];
|
||||
_CanvasTextMetrics._measurementCache = {};
|
||||
let CanvasTextMetrics = _CanvasTextMetrics;
|
||||
|
||||
exports.CanvasTextMetrics = CanvasTextMetrics;
|
||||
//# sourceMappingURL=CanvasTextMetrics.js.map
|
1
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextMetrics.js.map
generated
vendored
Normal file
1
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextMetrics.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
530
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextMetrics.mjs
generated
vendored
Normal file
530
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextMetrics.mjs
generated
vendored
Normal file
@@ -0,0 +1,530 @@
|
||||
import { DOMAdapter } from '../../../environment/adapter.mjs';
|
||||
import { fontStringFromTextStyle } from './utils/fontStringFromTextStyle.mjs';
|
||||
|
||||
"use strict";
|
||||
const contextSettings = {
|
||||
// TextMetrics requires getImageData readback for measuring fonts.
|
||||
willReadFrequently: true
|
||||
};
|
||||
const _CanvasTextMetrics = class _CanvasTextMetrics {
|
||||
/**
|
||||
* Checking that we can use modern canvas 2D API.
|
||||
*
|
||||
* Note: This is an unstable API, Chrome < 94 use `textLetterSpacing`, later versions use `letterSpacing`.
|
||||
* @see TextMetrics.experimentalLetterSpacing
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/ICanvasRenderingContext2D/letterSpacing
|
||||
* @see https://developer.chrome.com/origintrials/#/view_trial/3585991203293757441
|
||||
*/
|
||||
static get experimentalLetterSpacingSupported() {
|
||||
let result = _CanvasTextMetrics._experimentalLetterSpacingSupported;
|
||||
if (result !== void 0) {
|
||||
const proto = DOMAdapter.get().getCanvasRenderingContext2D().prototype;
|
||||
result = _CanvasTextMetrics._experimentalLetterSpacingSupported = "letterSpacing" in proto || "textLetterSpacing" in proto;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* @param text - the text that was measured
|
||||
* @param style - the style that was measured
|
||||
* @param width - the measured width of the text
|
||||
* @param height - the measured height of the text
|
||||
* @param lines - an array of the lines of text broken by new lines and wrapping if specified in style
|
||||
* @param lineWidths - an array of the line widths for each line matched to `lines`
|
||||
* @param lineHeight - the measured line height for this style
|
||||
* @param maxLineWidth - the maximum line width for all measured lines
|
||||
* @param {FontMetrics} fontProperties - the font properties object from TextMetrics.measureFont
|
||||
*/
|
||||
constructor(text, style, width, height, lines, lineWidths, lineHeight, maxLineWidth, fontProperties) {
|
||||
this.text = text;
|
||||
this.style = style;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.lines = lines;
|
||||
this.lineWidths = lineWidths;
|
||||
this.lineHeight = lineHeight;
|
||||
this.maxLineWidth = maxLineWidth;
|
||||
this.fontProperties = fontProperties;
|
||||
}
|
||||
/**
|
||||
* Measures the supplied string of text and returns a Rectangle.
|
||||
* @param text - The text to measure.
|
||||
* @param style - The text style to use for measuring
|
||||
* @param canvas - optional specification of the canvas to use for measuring.
|
||||
* @param wordWrap
|
||||
* @returns Measured width and height of the text.
|
||||
*/
|
||||
static measureText(text = " ", style, canvas = _CanvasTextMetrics._canvas, wordWrap = style.wordWrap) {
|
||||
const textKey = `${text}:${style.styleKey}`;
|
||||
if (_CanvasTextMetrics._measurementCache[textKey])
|
||||
return _CanvasTextMetrics._measurementCache[textKey];
|
||||
const font = fontStringFromTextStyle(style);
|
||||
const fontProperties = _CanvasTextMetrics.measureFont(font);
|
||||
if (fontProperties.fontSize === 0) {
|
||||
fontProperties.fontSize = style.fontSize;
|
||||
fontProperties.ascent = style.fontSize;
|
||||
}
|
||||
const context = _CanvasTextMetrics.__context;
|
||||
context.font = font;
|
||||
const outputText = wordWrap ? _CanvasTextMetrics._wordWrap(text, style, canvas) : text;
|
||||
const lines = outputText.split(/(?:\r\n|\r|\n)/);
|
||||
const lineWidths = new Array(lines.length);
|
||||
let maxLineWidth = 0;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const lineWidth = _CanvasTextMetrics._measureText(lines[i], style.letterSpacing, context);
|
||||
lineWidths[i] = lineWidth;
|
||||
maxLineWidth = Math.max(maxLineWidth, lineWidth);
|
||||
}
|
||||
const strokeWidth = style._stroke?.width || 0;
|
||||
let width = maxLineWidth + strokeWidth;
|
||||
if (style.dropShadow) {
|
||||
width += style.dropShadow.distance;
|
||||
}
|
||||
const lineHeight = style.lineHeight || fontProperties.fontSize;
|
||||
let height = Math.max(lineHeight, fontProperties.fontSize + strokeWidth) + (lines.length - 1) * (lineHeight + style.leading);
|
||||
if (style.dropShadow) {
|
||||
height += style.dropShadow.distance;
|
||||
}
|
||||
const measurements = new _CanvasTextMetrics(
|
||||
text,
|
||||
style,
|
||||
width,
|
||||
height,
|
||||
lines,
|
||||
lineWidths,
|
||||
lineHeight + style.leading,
|
||||
maxLineWidth,
|
||||
fontProperties
|
||||
);
|
||||
return measurements;
|
||||
}
|
||||
static _measureText(text, letterSpacing, context) {
|
||||
let useExperimentalLetterSpacing = false;
|
||||
if (_CanvasTextMetrics.experimentalLetterSpacingSupported) {
|
||||
if (_CanvasTextMetrics.experimentalLetterSpacing) {
|
||||
context.letterSpacing = `${letterSpacing}px`;
|
||||
context.textLetterSpacing = `${letterSpacing}px`;
|
||||
useExperimentalLetterSpacing = true;
|
||||
} else {
|
||||
context.letterSpacing = "0px";
|
||||
context.textLetterSpacing = "0px";
|
||||
}
|
||||
}
|
||||
let width = context.measureText(text).width;
|
||||
if (width > 0) {
|
||||
if (useExperimentalLetterSpacing) {
|
||||
width -= letterSpacing;
|
||||
} else {
|
||||
width += (_CanvasTextMetrics.graphemeSegmenter(text).length - 1) * letterSpacing;
|
||||
}
|
||||
}
|
||||
return width;
|
||||
}
|
||||
/**
|
||||
* Applies newlines to a string to have it optimally fit into the horizontal
|
||||
* bounds set by the Text object's wordWrapWidth property.
|
||||
* @param text - String to apply word wrapping to
|
||||
* @param style - the style to use when wrapping
|
||||
* @param canvas - optional specification of the canvas to use for measuring.
|
||||
* @returns New string with new lines applied where required
|
||||
*/
|
||||
static _wordWrap(text, style, canvas = _CanvasTextMetrics._canvas) {
|
||||
const context = canvas.getContext("2d", contextSettings);
|
||||
let width = 0;
|
||||
let line = "";
|
||||
let lines = "";
|
||||
const cache = /* @__PURE__ */ Object.create(null);
|
||||
const { letterSpacing, whiteSpace } = style;
|
||||
const collapseSpaces = _CanvasTextMetrics._collapseSpaces(whiteSpace);
|
||||
const collapseNewlines = _CanvasTextMetrics._collapseNewlines(whiteSpace);
|
||||
let canPrependSpaces = !collapseSpaces;
|
||||
const wordWrapWidth = style.wordWrapWidth + letterSpacing;
|
||||
const tokens = _CanvasTextMetrics._tokenize(text);
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
let token = tokens[i];
|
||||
if (_CanvasTextMetrics._isNewline(token)) {
|
||||
if (!collapseNewlines) {
|
||||
lines += _CanvasTextMetrics._addLine(line);
|
||||
canPrependSpaces = !collapseSpaces;
|
||||
line = "";
|
||||
width = 0;
|
||||
continue;
|
||||
}
|
||||
token = " ";
|
||||
}
|
||||
if (collapseSpaces) {
|
||||
const currIsBreakingSpace = _CanvasTextMetrics.isBreakingSpace(token);
|
||||
const lastIsBreakingSpace = _CanvasTextMetrics.isBreakingSpace(line[line.length - 1]);
|
||||
if (currIsBreakingSpace && lastIsBreakingSpace) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const tokenWidth = _CanvasTextMetrics._getFromCache(token, letterSpacing, cache, context);
|
||||
if (tokenWidth > wordWrapWidth) {
|
||||
if (line !== "") {
|
||||
lines += _CanvasTextMetrics._addLine(line);
|
||||
line = "";
|
||||
width = 0;
|
||||
}
|
||||
if (_CanvasTextMetrics.canBreakWords(token, style.breakWords)) {
|
||||
const characters = _CanvasTextMetrics.wordWrapSplit(token);
|
||||
for (let j = 0; j < characters.length; j++) {
|
||||
let char = characters[j];
|
||||
let lastChar = char;
|
||||
let k = 1;
|
||||
while (characters[j + k]) {
|
||||
const nextChar = characters[j + k];
|
||||
if (!_CanvasTextMetrics.canBreakChars(lastChar, nextChar, token, j, style.breakWords)) {
|
||||
char += nextChar;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
lastChar = nextChar;
|
||||
k++;
|
||||
}
|
||||
j += k - 1;
|
||||
const characterWidth = _CanvasTextMetrics._getFromCache(char, letterSpacing, cache, context);
|
||||
if (characterWidth + width > wordWrapWidth) {
|
||||
lines += _CanvasTextMetrics._addLine(line);
|
||||
canPrependSpaces = false;
|
||||
line = "";
|
||||
width = 0;
|
||||
}
|
||||
line += char;
|
||||
width += characterWidth;
|
||||
}
|
||||
} else {
|
||||
if (line.length > 0) {
|
||||
lines += _CanvasTextMetrics._addLine(line);
|
||||
line = "";
|
||||
width = 0;
|
||||
}
|
||||
const isLastToken = i === tokens.length - 1;
|
||||
lines += _CanvasTextMetrics._addLine(token, !isLastToken);
|
||||
canPrependSpaces = false;
|
||||
line = "";
|
||||
width = 0;
|
||||
}
|
||||
} else {
|
||||
if (tokenWidth + width > wordWrapWidth) {
|
||||
canPrependSpaces = false;
|
||||
lines += _CanvasTextMetrics._addLine(line);
|
||||
line = "";
|
||||
width = 0;
|
||||
}
|
||||
if (line.length > 0 || !_CanvasTextMetrics.isBreakingSpace(token) || canPrependSpaces) {
|
||||
line += token;
|
||||
width += tokenWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
lines += _CanvasTextMetrics._addLine(line, false);
|
||||
return lines;
|
||||
}
|
||||
/**
|
||||
* Convenience function for logging each line added during the wordWrap method.
|
||||
* @param line - The line of text to add
|
||||
* @param newLine - Add new line character to end
|
||||
* @returns A formatted line
|
||||
*/
|
||||
static _addLine(line, newLine = true) {
|
||||
line = _CanvasTextMetrics._trimRight(line);
|
||||
line = newLine ? `${line}
|
||||
` : line;
|
||||
return line;
|
||||
}
|
||||
/**
|
||||
* Gets & sets the widths of calculated characters in a cache object
|
||||
* @param key - The key
|
||||
* @param letterSpacing - The letter spacing
|
||||
* @param cache - The cache
|
||||
* @param context - The canvas context
|
||||
* @returns The from cache.
|
||||
*/
|
||||
static _getFromCache(key, letterSpacing, cache, context) {
|
||||
let width = cache[key];
|
||||
if (typeof width !== "number") {
|
||||
width = _CanvasTextMetrics._measureText(key, letterSpacing, context) + letterSpacing;
|
||||
cache[key] = width;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
/**
|
||||
* Determines whether we should collapse breaking spaces.
|
||||
* @param whiteSpace - The TextStyle property whiteSpace
|
||||
* @returns Should collapse
|
||||
*/
|
||||
static _collapseSpaces(whiteSpace) {
|
||||
return whiteSpace === "normal" || whiteSpace === "pre-line";
|
||||
}
|
||||
/**
|
||||
* Determines whether we should collapse newLine chars.
|
||||
* @param whiteSpace - The white space
|
||||
* @returns should collapse
|
||||
*/
|
||||
static _collapseNewlines(whiteSpace) {
|
||||
return whiteSpace === "normal";
|
||||
}
|
||||
/**
|
||||
* Trims breaking whitespaces from string.
|
||||
* @param text - The text
|
||||
* @returns Trimmed string
|
||||
*/
|
||||
static _trimRight(text) {
|
||||
if (typeof text !== "string") {
|
||||
return "";
|
||||
}
|
||||
for (let i = text.length - 1; i >= 0; i--) {
|
||||
const char = text[i];
|
||||
if (!_CanvasTextMetrics.isBreakingSpace(char)) {
|
||||
break;
|
||||
}
|
||||
text = text.slice(0, -1);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
/**
|
||||
* Determines if char is a newline.
|
||||
* @param char - The character
|
||||
* @returns True if newline, False otherwise.
|
||||
*/
|
||||
static _isNewline(char) {
|
||||
if (typeof char !== "string") {
|
||||
return false;
|
||||
}
|
||||
return _CanvasTextMetrics._newlines.includes(char.charCodeAt(0));
|
||||
}
|
||||
/**
|
||||
* Determines if char is a breaking whitespace.
|
||||
*
|
||||
* It allows one to determine whether char should be a breaking whitespace
|
||||
* For example certain characters in CJK langs or numbers.
|
||||
* It must return a boolean.
|
||||
* @param char - The character
|
||||
* @param [_nextChar] - The next character
|
||||
* @returns True if whitespace, False otherwise.
|
||||
*/
|
||||
static isBreakingSpace(char, _nextChar) {
|
||||
if (typeof char !== "string") {
|
||||
return false;
|
||||
}
|
||||
return _CanvasTextMetrics._breakingSpaces.includes(char.charCodeAt(0));
|
||||
}
|
||||
/**
|
||||
* Splits a string into words, breaking-spaces and newLine characters
|
||||
* @param text - The text
|
||||
* @returns A tokenized array
|
||||
*/
|
||||
static _tokenize(text) {
|
||||
const tokens = [];
|
||||
let token = "";
|
||||
if (typeof text !== "string") {
|
||||
return tokens;
|
||||
}
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
const char = text[i];
|
||||
const nextChar = text[i + 1];
|
||||
if (_CanvasTextMetrics.isBreakingSpace(char, nextChar) || _CanvasTextMetrics._isNewline(char)) {
|
||||
if (token !== "") {
|
||||
tokens.push(token);
|
||||
token = "";
|
||||
}
|
||||
tokens.push(char);
|
||||
continue;
|
||||
}
|
||||
token += char;
|
||||
}
|
||||
if (token !== "") {
|
||||
tokens.push(token);
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
/**
|
||||
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
|
||||
*
|
||||
* It allows one to customise which words should break
|
||||
* Examples are if the token is CJK or numbers.
|
||||
* It must return a boolean.
|
||||
* @param _token - The token
|
||||
* @param breakWords - The style attr break words
|
||||
* @returns Whether to break word or not
|
||||
*/
|
||||
static canBreakWords(_token, breakWords) {
|
||||
return breakWords;
|
||||
}
|
||||
/**
|
||||
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
|
||||
*
|
||||
* It allows one to determine whether a pair of characters
|
||||
* should be broken by newlines
|
||||
* For example certain characters in CJK langs or numbers.
|
||||
* It must return a boolean.
|
||||
* @param _char - The character
|
||||
* @param _nextChar - The next character
|
||||
* @param _token - The token/word the characters are from
|
||||
* @param _index - The index in the token of the char
|
||||
* @param _breakWords - The style attr break words
|
||||
* @returns whether to break word or not
|
||||
*/
|
||||
static canBreakChars(_char, _nextChar, _token, _index, _breakWords) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
|
||||
*
|
||||
* It is called when a token (usually a word) has to be split into separate pieces
|
||||
* in order to determine the point to break a word.
|
||||
* It must return an array of characters.
|
||||
* @param token - The token to split
|
||||
* @returns The characters of the token
|
||||
* @see CanvasTextMetrics.graphemeSegmenter
|
||||
*/
|
||||
static wordWrapSplit(token) {
|
||||
return _CanvasTextMetrics.graphemeSegmenter(token);
|
||||
}
|
||||
/**
|
||||
* Calculates the ascent, descent and fontSize of a given font-style
|
||||
* @param font - String representing the style of the font
|
||||
* @returns Font properties object
|
||||
*/
|
||||
static measureFont(font) {
|
||||
if (_CanvasTextMetrics._fonts[font]) {
|
||||
return _CanvasTextMetrics._fonts[font];
|
||||
}
|
||||
const context = _CanvasTextMetrics._context;
|
||||
context.font = font;
|
||||
const metrics = context.measureText(_CanvasTextMetrics.METRICS_STRING + _CanvasTextMetrics.BASELINE_SYMBOL);
|
||||
const properties = {
|
||||
ascent: metrics.actualBoundingBoxAscent,
|
||||
descent: metrics.actualBoundingBoxDescent,
|
||||
fontSize: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
|
||||
};
|
||||
_CanvasTextMetrics._fonts[font] = properties;
|
||||
return properties;
|
||||
}
|
||||
/**
|
||||
* Clear font metrics in metrics cache.
|
||||
* @param {string} [font] - font name. If font name not set then clear cache for all fonts.
|
||||
*/
|
||||
static clearMetrics(font = "") {
|
||||
if (font) {
|
||||
delete _CanvasTextMetrics._fonts[font];
|
||||
} else {
|
||||
_CanvasTextMetrics._fonts = {};
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Cached canvas element for measuring text
|
||||
* TODO: this should be private, but isn't because of backward compat, will fix later.
|
||||
* @ignore
|
||||
*/
|
||||
static get _canvas() {
|
||||
if (!_CanvasTextMetrics.__canvas) {
|
||||
let canvas;
|
||||
try {
|
||||
const c = new OffscreenCanvas(0, 0);
|
||||
const context = c.getContext("2d", contextSettings);
|
||||
if (context?.measureText) {
|
||||
_CanvasTextMetrics.__canvas = c;
|
||||
return c;
|
||||
}
|
||||
canvas = DOMAdapter.get().createCanvas();
|
||||
} catch (ex) {
|
||||
canvas = DOMAdapter.get().createCanvas();
|
||||
}
|
||||
canvas.width = canvas.height = 10;
|
||||
_CanvasTextMetrics.__canvas = canvas;
|
||||
}
|
||||
return _CanvasTextMetrics.__canvas;
|
||||
}
|
||||
/**
|
||||
* TODO: this should be private, but isn't because of backward compat, will fix later.
|
||||
* @ignore
|
||||
*/
|
||||
static get _context() {
|
||||
if (!_CanvasTextMetrics.__context) {
|
||||
_CanvasTextMetrics.__context = _CanvasTextMetrics._canvas.getContext("2d", contextSettings);
|
||||
}
|
||||
return _CanvasTextMetrics.__context;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* String used for calculate font metrics.
|
||||
* These characters are all tall to help calculate the height required for text.
|
||||
*/
|
||||
_CanvasTextMetrics.METRICS_STRING = "|\xC9q\xC5";
|
||||
/** Baseline symbol for calculate font metrics. */
|
||||
_CanvasTextMetrics.BASELINE_SYMBOL = "M";
|
||||
/** Baseline multiplier for calculate font metrics. */
|
||||
_CanvasTextMetrics.BASELINE_MULTIPLIER = 1.4;
|
||||
/** Height multiplier for setting height of canvas to calculate font metrics. */
|
||||
_CanvasTextMetrics.HEIGHT_MULTIPLIER = 2;
|
||||
/**
|
||||
* A Unicode "character", or "grapheme cluster", can be composed of multiple Unicode code points,
|
||||
* such as letters with diacritical marks (e.g. `'\u0065\u0301'`, letter e with acute)
|
||||
* or emojis with modifiers (e.g. `'\uD83E\uDDD1\u200D\uD83D\uDCBB'`, technologist).
|
||||
* The new `Intl.Segmenter` API in ES2022 can split the string into grapheme clusters correctly. If it is not available,
|
||||
* PixiJS will fallback to use the iterator of String, which can only spilt the string into code points.
|
||||
* If you want to get full functionality in environments that don't support `Intl.Segmenter` (such as Firefox),
|
||||
* you can use other libraries such as [grapheme-splitter]{@link https://www.npmjs.com/package/grapheme-splitter}
|
||||
* or [graphemer]{@link https://www.npmjs.com/package/graphemer} to create a polyfill. Since these libraries can be
|
||||
* relatively large in size to handle various Unicode grapheme clusters properly, PixiJS won't use them directly.
|
||||
*/
|
||||
_CanvasTextMetrics.graphemeSegmenter = (() => {
|
||||
if (typeof Intl?.Segmenter === "function") {
|
||||
const segmenter = new Intl.Segmenter();
|
||||
return (s) => [...segmenter.segment(s)].map((x) => x.segment);
|
||||
}
|
||||
return (s) => [...s];
|
||||
})();
|
||||
/**
|
||||
* New rendering behavior for letter-spacing which uses Chrome's new native API. This will
|
||||
* lead to more accurate letter-spacing results because it does not try to manually draw
|
||||
* each character. However, this Chrome API is experimental and may not serve all cases yet.
|
||||
* @see TextMetrics.experimentalLetterSpacingSupported
|
||||
*/
|
||||
_CanvasTextMetrics.experimentalLetterSpacing = false;
|
||||
/** Cache of {@see TextMetrics.FontMetrics} objects. */
|
||||
_CanvasTextMetrics._fonts = {};
|
||||
/** Cache of new line chars. */
|
||||
_CanvasTextMetrics._newlines = [
|
||||
10,
|
||||
// line feed
|
||||
13
|
||||
// carriage return
|
||||
];
|
||||
/** Cache of breaking spaces. */
|
||||
_CanvasTextMetrics._breakingSpaces = [
|
||||
9,
|
||||
// character tabulation
|
||||
32,
|
||||
// space
|
||||
8192,
|
||||
// en quad
|
||||
8193,
|
||||
// em quad
|
||||
8194,
|
||||
// en space
|
||||
8195,
|
||||
// em space
|
||||
8196,
|
||||
// three-per-em space
|
||||
8197,
|
||||
// four-per-em space
|
||||
8198,
|
||||
// six-per-em space
|
||||
8200,
|
||||
// punctuation space
|
||||
8201,
|
||||
// thin space
|
||||
8202,
|
||||
// hair space
|
||||
8287,
|
||||
// medium mathematical space
|
||||
12288
|
||||
// ideographic space
|
||||
];
|
||||
_CanvasTextMetrics._measurementCache = {};
|
||||
let CanvasTextMetrics = _CanvasTextMetrics;
|
||||
|
||||
export { CanvasTextMetrics };
|
||||
//# sourceMappingURL=CanvasTextMetrics.mjs.map
|
1
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextMetrics.mjs.map
generated
vendored
Normal file
1
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextMetrics.mjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
33
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextPipe.d.ts
generated
vendored
Normal file
33
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextPipe.d.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { ExtensionType } from '../../../extensions/Extensions';
|
||||
import { BatchableSprite } from '../../sprite/BatchableSprite';
|
||||
import type { InstructionSet } from '../../../rendering/renderers/shared/instructions/InstructionSet';
|
||||
import type { RenderPipe } from '../../../rendering/renderers/shared/instructions/RenderPipe';
|
||||
import type { Texture } from '../../../rendering/renderers/shared/texture/Texture';
|
||||
import type { Renderer } from '../../../rendering/renderers/types';
|
||||
import type { Text } from '../Text';
|
||||
export declare class CanvasTextPipe implements RenderPipe<Text> {
|
||||
/** @ignore */
|
||||
static extension: {
|
||||
readonly type: readonly [ExtensionType.WebGLPipes, ExtensionType.WebGPUPipes, ExtensionType.CanvasPipes];
|
||||
readonly name: "text";
|
||||
};
|
||||
private _renderer;
|
||||
private _gpuText;
|
||||
private readonly _destroyRenderableBound;
|
||||
constructor(renderer: Renderer);
|
||||
resolutionChange(): void;
|
||||
validateRenderable(text: Text): boolean;
|
||||
addRenderable(text: Text, instructionSet: InstructionSet): void;
|
||||
updateRenderable(text: Text): void;
|
||||
destroyRenderable(text: Text): void;
|
||||
private _destroyRenderableById;
|
||||
private _updateText;
|
||||
private _updateGpuText;
|
||||
private _getGpuText;
|
||||
initGpuText(text: Text): {
|
||||
texture: Texture<import("../../..").TextureSource<any>>;
|
||||
currentKey: string;
|
||||
batchableSprite: BatchableSprite;
|
||||
};
|
||||
destroy(): void;
|
||||
}
|
132
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextPipe.js
generated
vendored
Normal file
132
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextPipe.js
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
'use strict';
|
||||
|
||||
var Extensions = require('../../../extensions/Extensions.js');
|
||||
var updateQuadBounds = require('../../../utils/data/updateQuadBounds.js');
|
||||
var PoolGroup = require('../../../utils/pool/PoolGroup.js');
|
||||
var BatchableSprite = require('../../sprite/BatchableSprite.js');
|
||||
|
||||
"use strict";
|
||||
class CanvasTextPipe {
|
||||
constructor(renderer) {
|
||||
this._gpuText = /* @__PURE__ */ Object.create(null);
|
||||
this._destroyRenderableBound = this.destroyRenderable.bind(this);
|
||||
this._renderer = renderer;
|
||||
this._renderer.runners.resolutionChange.add(this);
|
||||
}
|
||||
resolutionChange() {
|
||||
for (const i in this._gpuText) {
|
||||
const gpuText = this._gpuText[i];
|
||||
if (!gpuText)
|
||||
continue;
|
||||
const text = gpuText.batchableSprite.renderable;
|
||||
if (text._autoResolution) {
|
||||
text._resolution = this._renderer.resolution;
|
||||
text.onViewUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
validateRenderable(text) {
|
||||
const gpuText = this._getGpuText(text);
|
||||
const newKey = text._getKey();
|
||||
if (gpuText.currentKey !== newKey) {
|
||||
const { width, height } = this._renderer.canvasText.getTextureSize(
|
||||
text.text,
|
||||
text.resolution,
|
||||
text._style
|
||||
);
|
||||
if (
|
||||
// is only being used by this text:
|
||||
this._renderer.canvasText.getReferenceCount(gpuText.currentKey) === 1 && width === gpuText.texture._source.width && height === gpuText.texture._source.height
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
addRenderable(text, instructionSet) {
|
||||
const gpuText = this._getGpuText(text);
|
||||
const batchableSprite = gpuText.batchableSprite;
|
||||
if (text._didTextUpdate) {
|
||||
this._updateText(text);
|
||||
}
|
||||
this._renderer.renderPipes.batch.addToBatch(batchableSprite, instructionSet);
|
||||
}
|
||||
updateRenderable(text) {
|
||||
const gpuText = this._getGpuText(text);
|
||||
const batchableSprite = gpuText.batchableSprite;
|
||||
if (text._didTextUpdate) {
|
||||
this._updateText(text);
|
||||
}
|
||||
batchableSprite._batcher.updateElement(batchableSprite);
|
||||
}
|
||||
destroyRenderable(text) {
|
||||
text.off("destroyed", this._destroyRenderableBound);
|
||||
this._destroyRenderableById(text.uid);
|
||||
}
|
||||
_destroyRenderableById(textUid) {
|
||||
const gpuText = this._gpuText[textUid];
|
||||
this._renderer.canvasText.decreaseReferenceCount(gpuText.currentKey);
|
||||
PoolGroup.BigPool.return(gpuText.batchableSprite);
|
||||
this._gpuText[textUid] = null;
|
||||
}
|
||||
_updateText(text) {
|
||||
const newKey = text._getKey();
|
||||
const gpuText = this._getGpuText(text);
|
||||
const batchableSprite = gpuText.batchableSprite;
|
||||
if (gpuText.currentKey !== newKey) {
|
||||
this._updateGpuText(text);
|
||||
}
|
||||
text._didTextUpdate = false;
|
||||
const padding = text._style.padding;
|
||||
updateQuadBounds.updateQuadBounds(batchableSprite.bounds, text._anchor, batchableSprite.texture, padding);
|
||||
}
|
||||
_updateGpuText(text) {
|
||||
const gpuText = this._getGpuText(text);
|
||||
const batchableSprite = gpuText.batchableSprite;
|
||||
if (gpuText.texture) {
|
||||
this._renderer.canvasText.decreaseReferenceCount(gpuText.currentKey);
|
||||
}
|
||||
gpuText.texture = batchableSprite.texture = this._renderer.canvasText.getManagedTexture(text);
|
||||
gpuText.currentKey = text._getKey();
|
||||
batchableSprite.texture = gpuText.texture;
|
||||
}
|
||||
_getGpuText(text) {
|
||||
return this._gpuText[text.uid] || this.initGpuText(text);
|
||||
}
|
||||
initGpuText(text) {
|
||||
const gpuTextData = {
|
||||
texture: null,
|
||||
currentKey: "--",
|
||||
batchableSprite: PoolGroup.BigPool.get(BatchableSprite.BatchableSprite)
|
||||
};
|
||||
gpuTextData.batchableSprite.renderable = text;
|
||||
gpuTextData.batchableSprite.transform = text.groupTransform;
|
||||
gpuTextData.batchableSprite.bounds = { minX: 0, maxX: 1, minY: 0, maxY: 0 };
|
||||
gpuTextData.batchableSprite.roundPixels = this._renderer._roundPixels | text._roundPixels;
|
||||
this._gpuText[text.uid] = gpuTextData;
|
||||
text._resolution = text._autoResolution ? this._renderer.resolution : text.resolution;
|
||||
this._updateText(text);
|
||||
text.on("destroyed", this._destroyRenderableBound);
|
||||
return gpuTextData;
|
||||
}
|
||||
destroy() {
|
||||
for (const i in this._gpuText) {
|
||||
this._destroyRenderableById(i);
|
||||
}
|
||||
this._gpuText = null;
|
||||
this._renderer = null;
|
||||
}
|
||||
}
|
||||
/** @ignore */
|
||||
CanvasTextPipe.extension = {
|
||||
type: [
|
||||
Extensions.ExtensionType.WebGLPipes,
|
||||
Extensions.ExtensionType.WebGPUPipes,
|
||||
Extensions.ExtensionType.CanvasPipes
|
||||
],
|
||||
name: "text"
|
||||
};
|
||||
|
||||
exports.CanvasTextPipe = CanvasTextPipe;
|
||||
//# sourceMappingURL=CanvasTextPipe.js.map
|
1
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextPipe.js.map
generated
vendored
Normal file
1
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextPipe.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
130
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextPipe.mjs
generated
vendored
Normal file
130
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextPipe.mjs
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
import { ExtensionType } from '../../../extensions/Extensions.mjs';
|
||||
import { updateQuadBounds } from '../../../utils/data/updateQuadBounds.mjs';
|
||||
import { BigPool } from '../../../utils/pool/PoolGroup.mjs';
|
||||
import { BatchableSprite } from '../../sprite/BatchableSprite.mjs';
|
||||
|
||||
"use strict";
|
||||
class CanvasTextPipe {
|
||||
constructor(renderer) {
|
||||
this._gpuText = /* @__PURE__ */ Object.create(null);
|
||||
this._destroyRenderableBound = this.destroyRenderable.bind(this);
|
||||
this._renderer = renderer;
|
||||
this._renderer.runners.resolutionChange.add(this);
|
||||
}
|
||||
resolutionChange() {
|
||||
for (const i in this._gpuText) {
|
||||
const gpuText = this._gpuText[i];
|
||||
if (!gpuText)
|
||||
continue;
|
||||
const text = gpuText.batchableSprite.renderable;
|
||||
if (text._autoResolution) {
|
||||
text._resolution = this._renderer.resolution;
|
||||
text.onViewUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
validateRenderable(text) {
|
||||
const gpuText = this._getGpuText(text);
|
||||
const newKey = text._getKey();
|
||||
if (gpuText.currentKey !== newKey) {
|
||||
const { width, height } = this._renderer.canvasText.getTextureSize(
|
||||
text.text,
|
||||
text.resolution,
|
||||
text._style
|
||||
);
|
||||
if (
|
||||
// is only being used by this text:
|
||||
this._renderer.canvasText.getReferenceCount(gpuText.currentKey) === 1 && width === gpuText.texture._source.width && height === gpuText.texture._source.height
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
addRenderable(text, instructionSet) {
|
||||
const gpuText = this._getGpuText(text);
|
||||
const batchableSprite = gpuText.batchableSprite;
|
||||
if (text._didTextUpdate) {
|
||||
this._updateText(text);
|
||||
}
|
||||
this._renderer.renderPipes.batch.addToBatch(batchableSprite, instructionSet);
|
||||
}
|
||||
updateRenderable(text) {
|
||||
const gpuText = this._getGpuText(text);
|
||||
const batchableSprite = gpuText.batchableSprite;
|
||||
if (text._didTextUpdate) {
|
||||
this._updateText(text);
|
||||
}
|
||||
batchableSprite._batcher.updateElement(batchableSprite);
|
||||
}
|
||||
destroyRenderable(text) {
|
||||
text.off("destroyed", this._destroyRenderableBound);
|
||||
this._destroyRenderableById(text.uid);
|
||||
}
|
||||
_destroyRenderableById(textUid) {
|
||||
const gpuText = this._gpuText[textUid];
|
||||
this._renderer.canvasText.decreaseReferenceCount(gpuText.currentKey);
|
||||
BigPool.return(gpuText.batchableSprite);
|
||||
this._gpuText[textUid] = null;
|
||||
}
|
||||
_updateText(text) {
|
||||
const newKey = text._getKey();
|
||||
const gpuText = this._getGpuText(text);
|
||||
const batchableSprite = gpuText.batchableSprite;
|
||||
if (gpuText.currentKey !== newKey) {
|
||||
this._updateGpuText(text);
|
||||
}
|
||||
text._didTextUpdate = false;
|
||||
const padding = text._style.padding;
|
||||
updateQuadBounds(batchableSprite.bounds, text._anchor, batchableSprite.texture, padding);
|
||||
}
|
||||
_updateGpuText(text) {
|
||||
const gpuText = this._getGpuText(text);
|
||||
const batchableSprite = gpuText.batchableSprite;
|
||||
if (gpuText.texture) {
|
||||
this._renderer.canvasText.decreaseReferenceCount(gpuText.currentKey);
|
||||
}
|
||||
gpuText.texture = batchableSprite.texture = this._renderer.canvasText.getManagedTexture(text);
|
||||
gpuText.currentKey = text._getKey();
|
||||
batchableSprite.texture = gpuText.texture;
|
||||
}
|
||||
_getGpuText(text) {
|
||||
return this._gpuText[text.uid] || this.initGpuText(text);
|
||||
}
|
||||
initGpuText(text) {
|
||||
const gpuTextData = {
|
||||
texture: null,
|
||||
currentKey: "--",
|
||||
batchableSprite: BigPool.get(BatchableSprite)
|
||||
};
|
||||
gpuTextData.batchableSprite.renderable = text;
|
||||
gpuTextData.batchableSprite.transform = text.groupTransform;
|
||||
gpuTextData.batchableSprite.bounds = { minX: 0, maxX: 1, minY: 0, maxY: 0 };
|
||||
gpuTextData.batchableSprite.roundPixels = this._renderer._roundPixels | text._roundPixels;
|
||||
this._gpuText[text.uid] = gpuTextData;
|
||||
text._resolution = text._autoResolution ? this._renderer.resolution : text.resolution;
|
||||
this._updateText(text);
|
||||
text.on("destroyed", this._destroyRenderableBound);
|
||||
return gpuTextData;
|
||||
}
|
||||
destroy() {
|
||||
for (const i in this._gpuText) {
|
||||
this._destroyRenderableById(i);
|
||||
}
|
||||
this._gpuText = null;
|
||||
this._renderer = null;
|
||||
}
|
||||
}
|
||||
/** @ignore */
|
||||
CanvasTextPipe.extension = {
|
||||
type: [
|
||||
ExtensionType.WebGLPipes,
|
||||
ExtensionType.WebGPUPipes,
|
||||
ExtensionType.CanvasPipes
|
||||
],
|
||||
name: "text"
|
||||
};
|
||||
|
||||
export { CanvasTextPipe };
|
||||
//# sourceMappingURL=CanvasTextPipe.mjs.map
|
1
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextPipe.mjs.map
generated
vendored
Normal file
1
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextPipe.mjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
80
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextSystem.d.ts
generated
vendored
Normal file
80
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextSystem.d.ts
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
import { ExtensionType } from '../../../extensions/Extensions';
|
||||
import { TextStyle } from '../TextStyle';
|
||||
import type { ICanvas } from '../../../environment/canvas/ICanvas';
|
||||
import type { ICanvasRenderingContext2D } from '../../../environment/canvas/ICanvasRenderingContext2D';
|
||||
import type { System } from '../../../rendering/renderers/shared/system/System';
|
||||
import type { Texture } from '../../../rendering/renderers/shared/texture/Texture';
|
||||
import type { Renderer } from '../../../rendering/renderers/types';
|
||||
import type { TextOptions } from '../AbstractText';
|
||||
import type { Text } from '../Text';
|
||||
interface CanvasAndContext {
|
||||
canvas: ICanvas;
|
||||
context: ICanvasRenderingContext2D;
|
||||
}
|
||||
/**
|
||||
* System plugin to the renderer to manage canvas text.
|
||||
* @memberof rendering
|
||||
*/
|
||||
export declare class CanvasTextSystem implements System {
|
||||
/** @ignore */
|
||||
static extension: {
|
||||
readonly type: readonly [ExtensionType.WebGLSystem, ExtensionType.WebGPUSystem, ExtensionType.CanvasSystem];
|
||||
readonly name: "canvasText";
|
||||
};
|
||||
private _activeTextures;
|
||||
private readonly _renderer;
|
||||
constructor(_renderer: Renderer);
|
||||
getTextureSize(text: string, resolution: number, style: TextStyle): {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
/**
|
||||
* This is a function that will create a texture from a text string, style and resolution.
|
||||
* Useful if you want to make a texture of your text and use if for various other pixi things!
|
||||
* @param options - The options of the text that will be used to generate the texture.
|
||||
* @param options.text - the text to render
|
||||
* @param options.style - the style of the text
|
||||
* @param options.resolution - the resolution of the texture
|
||||
* @returns the newly created texture
|
||||
*/
|
||||
/** @deprecated since 8.0.0 */
|
||||
getTexture(text: string, resolution: number, style: TextStyle, textKey: string): Texture;
|
||||
getTexture(options: TextOptions): Texture;
|
||||
createTextureAndCanvas(options: {
|
||||
text: string;
|
||||
style: TextStyle;
|
||||
resolution?: number;
|
||||
}): {
|
||||
texture: Texture<import("../../..").TextureSource<any>>;
|
||||
canvasAndContext: import("../../../rendering/renderers/shared/texture/CanvasPool").CanvasAndContext;
|
||||
};
|
||||
getManagedTexture(text: Text): Texture<import("../../..").TextureSource<any>>;
|
||||
private _increaseReferenceCount;
|
||||
decreaseReferenceCount(textKey: string): void;
|
||||
getReferenceCount(textKey: string): number;
|
||||
/**
|
||||
* Renders text to its canvas, and updates its texture.
|
||||
*
|
||||
* By default this is used internally to ensure the texture is correct before rendering,
|
||||
* but it can be used called externally, for example from this class to 'pre-generate' the texture from a piece of text,
|
||||
* and then shared across multiple Sprites.
|
||||
* @param text
|
||||
* @param style
|
||||
* @param resolution
|
||||
* @param canvasAndContext
|
||||
*/
|
||||
renderTextToCanvas(text: string, style: TextStyle, resolution: number, canvasAndContext: CanvasAndContext): void;
|
||||
/**
|
||||
* Render the text with letter-spacing.
|
||||
* @param text - The text to draw
|
||||
* @param style
|
||||
* @param canvasAndContext
|
||||
* @param x - Horizontal position to draw the text
|
||||
* @param y - Vertical position to draw the text
|
||||
* @param isStroke - Is this drawing for the outside stroke of the
|
||||
* text? If not, it's for the inside fill
|
||||
*/
|
||||
private _drawLetterSpacing;
|
||||
destroy(): void;
|
||||
}
|
||||
export {};
|
264
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextSystem.js
generated
vendored
Normal file
264
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextSystem.js
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
'use strict';
|
||||
|
||||
var Color = require('../../../color/Color.js');
|
||||
var Extensions = require('../../../extensions/Extensions.js');
|
||||
var pow2 = require('../../../maths/misc/pow2.js');
|
||||
var CanvasPool = require('../../../rendering/renderers/shared/texture/CanvasPool.js');
|
||||
var TexturePool = require('../../../rendering/renderers/shared/texture/TexturePool.js');
|
||||
var getCanvasBoundingBox = require('../../../utils/canvas/getCanvasBoundingBox.js');
|
||||
var deprecation = require('../../../utils/logging/deprecation.js');
|
||||
var TextStyle = require('../TextStyle.js');
|
||||
var getPo2TextureFromSource = require('../utils/getPo2TextureFromSource.js');
|
||||
var CanvasTextMetrics = require('./CanvasTextMetrics.js');
|
||||
var fontStringFromTextStyle = require('./utils/fontStringFromTextStyle.js');
|
||||
var getCanvasFillStyle = require('./utils/getCanvasFillStyle.js');
|
||||
|
||||
"use strict";
|
||||
class CanvasTextSystem {
|
||||
constructor(_renderer) {
|
||||
this._activeTextures = {};
|
||||
this._renderer = _renderer;
|
||||
}
|
||||
getTextureSize(text, resolution, style) {
|
||||
const measured = CanvasTextMetrics.CanvasTextMetrics.measureText(text || " ", style);
|
||||
let width = Math.ceil(Math.ceil(Math.max(1, measured.width) + style.padding * 2) * resolution);
|
||||
let height = Math.ceil(Math.ceil(Math.max(1, measured.height) + style.padding * 2) * resolution);
|
||||
width = Math.ceil(width - 1e-6);
|
||||
height = Math.ceil(height - 1e-6);
|
||||
width = pow2.nextPow2(width);
|
||||
height = pow2.nextPow2(height);
|
||||
return { width, height };
|
||||
}
|
||||
getTexture(options, resolution, style, _textKey) {
|
||||
if (typeof options === "string") {
|
||||
deprecation.deprecation("8.0.0", "CanvasTextSystem.getTexture: Use object TextOptions instead of separate arguments");
|
||||
options = {
|
||||
text: options,
|
||||
style,
|
||||
resolution
|
||||
};
|
||||
}
|
||||
if (!(options.style instanceof TextStyle.TextStyle)) {
|
||||
options.style = new TextStyle.TextStyle(options.style);
|
||||
}
|
||||
const { texture, canvasAndContext } = this.createTextureAndCanvas(
|
||||
options
|
||||
);
|
||||
this._renderer.texture.initSource(texture._source);
|
||||
CanvasPool.CanvasPool.returnCanvasAndContext(canvasAndContext);
|
||||
return texture;
|
||||
}
|
||||
createTextureAndCanvas(options) {
|
||||
const { text, style } = options;
|
||||
const resolution = options.resolution ?? this._renderer.resolution;
|
||||
const measured = CanvasTextMetrics.CanvasTextMetrics.measureText(text || " ", style);
|
||||
const width = Math.ceil(Math.ceil(Math.max(1, measured.width) + style.padding * 2) * resolution);
|
||||
const height = Math.ceil(Math.ceil(Math.max(1, measured.height) + style.padding * 2) * resolution);
|
||||
const canvasAndContext = CanvasPool.CanvasPool.getOptimalCanvasAndContext(width, height);
|
||||
const { canvas } = canvasAndContext;
|
||||
this.renderTextToCanvas(text, style, resolution, canvasAndContext);
|
||||
const texture = getPo2TextureFromSource.getPo2TextureFromSource(canvas, width, height, resolution);
|
||||
if (style.trim) {
|
||||
const trimmed = getCanvasBoundingBox.getCanvasBoundingBox(canvas, resolution);
|
||||
texture.frame.copyFrom(trimmed);
|
||||
texture.updateUvs();
|
||||
}
|
||||
return { texture, canvasAndContext };
|
||||
}
|
||||
getManagedTexture(text) {
|
||||
text._resolution = text._autoResolution ? this._renderer.resolution : text.resolution;
|
||||
const textKey = text._getKey();
|
||||
if (this._activeTextures[textKey]) {
|
||||
this._increaseReferenceCount(textKey);
|
||||
return this._activeTextures[textKey].texture;
|
||||
}
|
||||
const { texture, canvasAndContext } = this.createTextureAndCanvas(text);
|
||||
this._activeTextures[textKey] = {
|
||||
canvasAndContext,
|
||||
texture,
|
||||
usageCount: 1
|
||||
};
|
||||
return texture;
|
||||
}
|
||||
_increaseReferenceCount(textKey) {
|
||||
this._activeTextures[textKey].usageCount++;
|
||||
}
|
||||
decreaseReferenceCount(textKey) {
|
||||
const activeTexture = this._activeTextures[textKey];
|
||||
activeTexture.usageCount--;
|
||||
if (activeTexture.usageCount === 0) {
|
||||
CanvasPool.CanvasPool.returnCanvasAndContext(activeTexture.canvasAndContext);
|
||||
TexturePool.TexturePool.returnTexture(activeTexture.texture);
|
||||
const source = activeTexture.texture.source;
|
||||
source.resource = null;
|
||||
source.uploadMethodId = "unknown";
|
||||
source.alphaMode = "no-premultiply-alpha";
|
||||
this._activeTextures[textKey] = null;
|
||||
}
|
||||
}
|
||||
getReferenceCount(textKey) {
|
||||
return this._activeTextures[textKey].usageCount;
|
||||
}
|
||||
/**
|
||||
* Renders text to its canvas, and updates its texture.
|
||||
*
|
||||
* By default this is used internally to ensure the texture is correct before rendering,
|
||||
* but it can be used called externally, for example from this class to 'pre-generate' the texture from a piece of text,
|
||||
* and then shared across multiple Sprites.
|
||||
* @param text
|
||||
* @param style
|
||||
* @param resolution
|
||||
* @param canvasAndContext
|
||||
*/
|
||||
renderTextToCanvas(text, style, resolution, canvasAndContext) {
|
||||
const { canvas, context } = canvasAndContext;
|
||||
const font = fontStringFromTextStyle.fontStringFromTextStyle(style);
|
||||
const measured = CanvasTextMetrics.CanvasTextMetrics.measureText(text || " ", style);
|
||||
const lines = measured.lines;
|
||||
const lineHeight = measured.lineHeight;
|
||||
const lineWidths = measured.lineWidths;
|
||||
const maxLineWidth = measured.maxLineWidth;
|
||||
const fontProperties = measured.fontProperties;
|
||||
const height = canvas.height;
|
||||
context.resetTransform();
|
||||
context.scale(resolution, resolution);
|
||||
const padding = style.padding * 2;
|
||||
context.clearRect(0, 0, measured.width + 4 + padding, measured.height + 4 + padding);
|
||||
if (style._stroke?.width) {
|
||||
const strokeStyle = style._stroke;
|
||||
context.lineWidth = strokeStyle.width;
|
||||
context.miterLimit = strokeStyle.miterLimit;
|
||||
context.lineJoin = strokeStyle.join;
|
||||
context.lineCap = strokeStyle.cap;
|
||||
}
|
||||
context.font = font;
|
||||
let linePositionX;
|
||||
let linePositionY;
|
||||
const passesCount = style.dropShadow ? 2 : 1;
|
||||
for (let i = 0; i < passesCount; ++i) {
|
||||
const isShadowPass = style.dropShadow && i === 0;
|
||||
const dsOffsetText = isShadowPass ? Math.ceil(Math.max(1, height) + style.padding * 2) : 0;
|
||||
const dsOffsetShadow = dsOffsetText * resolution;
|
||||
if (isShadowPass) {
|
||||
context.fillStyle = "black";
|
||||
context.strokeStyle = "black";
|
||||
const shadowOptions = style.dropShadow;
|
||||
const dropShadowColor = shadowOptions.color;
|
||||
const dropShadowAlpha = shadowOptions.alpha;
|
||||
context.shadowColor = Color.Color.shared.setValue(dropShadowColor).setAlpha(dropShadowAlpha).toRgbaString();
|
||||
const dropShadowBlur = shadowOptions.blur * resolution;
|
||||
const dropShadowDistance = shadowOptions.distance * resolution;
|
||||
context.shadowBlur = dropShadowBlur;
|
||||
context.shadowOffsetX = Math.cos(shadowOptions.angle) * dropShadowDistance;
|
||||
context.shadowOffsetY = Math.sin(shadowOptions.angle) * dropShadowDistance + dsOffsetShadow;
|
||||
} else {
|
||||
context.globalAlpha = style._fill?.alpha ?? 1;
|
||||
context.fillStyle = style._fill ? getCanvasFillStyle.getCanvasFillStyle(style._fill, context) : null;
|
||||
if (style._stroke?.width) {
|
||||
context.strokeStyle = getCanvasFillStyle.getCanvasFillStyle(style._stroke, context);
|
||||
}
|
||||
context.shadowColor = "black";
|
||||
}
|
||||
let linePositionYShift = (lineHeight - fontProperties.fontSize) / 2;
|
||||
if (lineHeight - fontProperties.fontSize < 0) {
|
||||
linePositionYShift = 0;
|
||||
}
|
||||
const strokeWidth = style._stroke?.width ?? 0;
|
||||
for (let i2 = 0; i2 < lines.length; i2++) {
|
||||
linePositionX = strokeWidth / 2;
|
||||
linePositionY = strokeWidth / 2 + i2 * lineHeight + fontProperties.ascent + linePositionYShift;
|
||||
if (style.align === "right") {
|
||||
linePositionX += maxLineWidth - lineWidths[i2];
|
||||
} else if (style.align === "center") {
|
||||
linePositionX += (maxLineWidth - lineWidths[i2]) / 2;
|
||||
}
|
||||
if (style._stroke?.width) {
|
||||
this._drawLetterSpacing(
|
||||
lines[i2],
|
||||
style,
|
||||
canvasAndContext,
|
||||
linePositionX + style.padding,
|
||||
linePositionY + style.padding - dsOffsetText,
|
||||
true
|
||||
);
|
||||
}
|
||||
if (style._fill !== void 0) {
|
||||
this._drawLetterSpacing(
|
||||
lines[i2],
|
||||
style,
|
||||
canvasAndContext,
|
||||
linePositionX + style.padding,
|
||||
linePositionY + style.padding - dsOffsetText
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Render the text with letter-spacing.
|
||||
* @param text - The text to draw
|
||||
* @param style
|
||||
* @param canvasAndContext
|
||||
* @param x - Horizontal position to draw the text
|
||||
* @param y - Vertical position to draw the text
|
||||
* @param isStroke - Is this drawing for the outside stroke of the
|
||||
* text? If not, it's for the inside fill
|
||||
*/
|
||||
_drawLetterSpacing(text, style, canvasAndContext, x, y, isStroke = false) {
|
||||
const { context } = canvasAndContext;
|
||||
const letterSpacing = style.letterSpacing;
|
||||
let useExperimentalLetterSpacing = false;
|
||||
if (CanvasTextMetrics.CanvasTextMetrics.experimentalLetterSpacingSupported) {
|
||||
if (CanvasTextMetrics.CanvasTextMetrics.experimentalLetterSpacing) {
|
||||
context.letterSpacing = `${letterSpacing}px`;
|
||||
context.textLetterSpacing = `${letterSpacing}px`;
|
||||
useExperimentalLetterSpacing = true;
|
||||
} else {
|
||||
context.letterSpacing = "0px";
|
||||
context.textLetterSpacing = "0px";
|
||||
}
|
||||
}
|
||||
if (letterSpacing === 0 || useExperimentalLetterSpacing) {
|
||||
if (isStroke) {
|
||||
context.strokeText(text, x, y);
|
||||
} else {
|
||||
context.fillText(text, x, y);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let currentPosition = x;
|
||||
const stringArray = CanvasTextMetrics.CanvasTextMetrics.graphemeSegmenter(text);
|
||||
let previousWidth = context.measureText(text).width;
|
||||
let currentWidth = 0;
|
||||
for (let i = 0; i < stringArray.length; ++i) {
|
||||
const currentChar = stringArray[i];
|
||||
if (isStroke) {
|
||||
context.strokeText(currentChar, currentPosition, y);
|
||||
} else {
|
||||
context.fillText(currentChar, currentPosition, y);
|
||||
}
|
||||
let textStr = "";
|
||||
for (let j = i + 1; j < stringArray.length; ++j) {
|
||||
textStr += stringArray[j];
|
||||
}
|
||||
currentWidth = context.measureText(textStr).width;
|
||||
currentPosition += previousWidth - currentWidth + letterSpacing;
|
||||
previousWidth = currentWidth;
|
||||
}
|
||||
}
|
||||
destroy() {
|
||||
this._activeTextures = null;
|
||||
}
|
||||
}
|
||||
/** @ignore */
|
||||
CanvasTextSystem.extension = {
|
||||
type: [
|
||||
Extensions.ExtensionType.WebGLSystem,
|
||||
Extensions.ExtensionType.WebGPUSystem,
|
||||
Extensions.ExtensionType.CanvasSystem
|
||||
],
|
||||
name: "canvasText"
|
||||
};
|
||||
|
||||
exports.CanvasTextSystem = CanvasTextSystem;
|
||||
//# sourceMappingURL=CanvasTextSystem.js.map
|
1
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextSystem.js.map
generated
vendored
Normal file
1
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextSystem.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
262
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextSystem.mjs
generated
vendored
Normal file
262
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextSystem.mjs
generated
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
import { Color } from '../../../color/Color.mjs';
|
||||
import { ExtensionType } from '../../../extensions/Extensions.mjs';
|
||||
import { nextPow2 } from '../../../maths/misc/pow2.mjs';
|
||||
import { CanvasPool } from '../../../rendering/renderers/shared/texture/CanvasPool.mjs';
|
||||
import { TexturePool } from '../../../rendering/renderers/shared/texture/TexturePool.mjs';
|
||||
import { getCanvasBoundingBox } from '../../../utils/canvas/getCanvasBoundingBox.mjs';
|
||||
import { deprecation } from '../../../utils/logging/deprecation.mjs';
|
||||
import { TextStyle } from '../TextStyle.mjs';
|
||||
import { getPo2TextureFromSource } from '../utils/getPo2TextureFromSource.mjs';
|
||||
import { CanvasTextMetrics } from './CanvasTextMetrics.mjs';
|
||||
import { fontStringFromTextStyle } from './utils/fontStringFromTextStyle.mjs';
|
||||
import { getCanvasFillStyle } from './utils/getCanvasFillStyle.mjs';
|
||||
|
||||
"use strict";
|
||||
class CanvasTextSystem {
|
||||
constructor(_renderer) {
|
||||
this._activeTextures = {};
|
||||
this._renderer = _renderer;
|
||||
}
|
||||
getTextureSize(text, resolution, style) {
|
||||
const measured = CanvasTextMetrics.measureText(text || " ", style);
|
||||
let width = Math.ceil(Math.ceil(Math.max(1, measured.width) + style.padding * 2) * resolution);
|
||||
let height = Math.ceil(Math.ceil(Math.max(1, measured.height) + style.padding * 2) * resolution);
|
||||
width = Math.ceil(width - 1e-6);
|
||||
height = Math.ceil(height - 1e-6);
|
||||
width = nextPow2(width);
|
||||
height = nextPow2(height);
|
||||
return { width, height };
|
||||
}
|
||||
getTexture(options, resolution, style, _textKey) {
|
||||
if (typeof options === "string") {
|
||||
deprecation("8.0.0", "CanvasTextSystem.getTexture: Use object TextOptions instead of separate arguments");
|
||||
options = {
|
||||
text: options,
|
||||
style,
|
||||
resolution
|
||||
};
|
||||
}
|
||||
if (!(options.style instanceof TextStyle)) {
|
||||
options.style = new TextStyle(options.style);
|
||||
}
|
||||
const { texture, canvasAndContext } = this.createTextureAndCanvas(
|
||||
options
|
||||
);
|
||||
this._renderer.texture.initSource(texture._source);
|
||||
CanvasPool.returnCanvasAndContext(canvasAndContext);
|
||||
return texture;
|
||||
}
|
||||
createTextureAndCanvas(options) {
|
||||
const { text, style } = options;
|
||||
const resolution = options.resolution ?? this._renderer.resolution;
|
||||
const measured = CanvasTextMetrics.measureText(text || " ", style);
|
||||
const width = Math.ceil(Math.ceil(Math.max(1, measured.width) + style.padding * 2) * resolution);
|
||||
const height = Math.ceil(Math.ceil(Math.max(1, measured.height) + style.padding * 2) * resolution);
|
||||
const canvasAndContext = CanvasPool.getOptimalCanvasAndContext(width, height);
|
||||
const { canvas } = canvasAndContext;
|
||||
this.renderTextToCanvas(text, style, resolution, canvasAndContext);
|
||||
const texture = getPo2TextureFromSource(canvas, width, height, resolution);
|
||||
if (style.trim) {
|
||||
const trimmed = getCanvasBoundingBox(canvas, resolution);
|
||||
texture.frame.copyFrom(trimmed);
|
||||
texture.updateUvs();
|
||||
}
|
||||
return { texture, canvasAndContext };
|
||||
}
|
||||
getManagedTexture(text) {
|
||||
text._resolution = text._autoResolution ? this._renderer.resolution : text.resolution;
|
||||
const textKey = text._getKey();
|
||||
if (this._activeTextures[textKey]) {
|
||||
this._increaseReferenceCount(textKey);
|
||||
return this._activeTextures[textKey].texture;
|
||||
}
|
||||
const { texture, canvasAndContext } = this.createTextureAndCanvas(text);
|
||||
this._activeTextures[textKey] = {
|
||||
canvasAndContext,
|
||||
texture,
|
||||
usageCount: 1
|
||||
};
|
||||
return texture;
|
||||
}
|
||||
_increaseReferenceCount(textKey) {
|
||||
this._activeTextures[textKey].usageCount++;
|
||||
}
|
||||
decreaseReferenceCount(textKey) {
|
||||
const activeTexture = this._activeTextures[textKey];
|
||||
activeTexture.usageCount--;
|
||||
if (activeTexture.usageCount === 0) {
|
||||
CanvasPool.returnCanvasAndContext(activeTexture.canvasAndContext);
|
||||
TexturePool.returnTexture(activeTexture.texture);
|
||||
const source = activeTexture.texture.source;
|
||||
source.resource = null;
|
||||
source.uploadMethodId = "unknown";
|
||||
source.alphaMode = "no-premultiply-alpha";
|
||||
this._activeTextures[textKey] = null;
|
||||
}
|
||||
}
|
||||
getReferenceCount(textKey) {
|
||||
return this._activeTextures[textKey].usageCount;
|
||||
}
|
||||
/**
|
||||
* Renders text to its canvas, and updates its texture.
|
||||
*
|
||||
* By default this is used internally to ensure the texture is correct before rendering,
|
||||
* but it can be used called externally, for example from this class to 'pre-generate' the texture from a piece of text,
|
||||
* and then shared across multiple Sprites.
|
||||
* @param text
|
||||
* @param style
|
||||
* @param resolution
|
||||
* @param canvasAndContext
|
||||
*/
|
||||
renderTextToCanvas(text, style, resolution, canvasAndContext) {
|
||||
const { canvas, context } = canvasAndContext;
|
||||
const font = fontStringFromTextStyle(style);
|
||||
const measured = CanvasTextMetrics.measureText(text || " ", style);
|
||||
const lines = measured.lines;
|
||||
const lineHeight = measured.lineHeight;
|
||||
const lineWidths = measured.lineWidths;
|
||||
const maxLineWidth = measured.maxLineWidth;
|
||||
const fontProperties = measured.fontProperties;
|
||||
const height = canvas.height;
|
||||
context.resetTransform();
|
||||
context.scale(resolution, resolution);
|
||||
const padding = style.padding * 2;
|
||||
context.clearRect(0, 0, measured.width + 4 + padding, measured.height + 4 + padding);
|
||||
if (style._stroke?.width) {
|
||||
const strokeStyle = style._stroke;
|
||||
context.lineWidth = strokeStyle.width;
|
||||
context.miterLimit = strokeStyle.miterLimit;
|
||||
context.lineJoin = strokeStyle.join;
|
||||
context.lineCap = strokeStyle.cap;
|
||||
}
|
||||
context.font = font;
|
||||
let linePositionX;
|
||||
let linePositionY;
|
||||
const passesCount = style.dropShadow ? 2 : 1;
|
||||
for (let i = 0; i < passesCount; ++i) {
|
||||
const isShadowPass = style.dropShadow && i === 0;
|
||||
const dsOffsetText = isShadowPass ? Math.ceil(Math.max(1, height) + style.padding * 2) : 0;
|
||||
const dsOffsetShadow = dsOffsetText * resolution;
|
||||
if (isShadowPass) {
|
||||
context.fillStyle = "black";
|
||||
context.strokeStyle = "black";
|
||||
const shadowOptions = style.dropShadow;
|
||||
const dropShadowColor = shadowOptions.color;
|
||||
const dropShadowAlpha = shadowOptions.alpha;
|
||||
context.shadowColor = Color.shared.setValue(dropShadowColor).setAlpha(dropShadowAlpha).toRgbaString();
|
||||
const dropShadowBlur = shadowOptions.blur * resolution;
|
||||
const dropShadowDistance = shadowOptions.distance * resolution;
|
||||
context.shadowBlur = dropShadowBlur;
|
||||
context.shadowOffsetX = Math.cos(shadowOptions.angle) * dropShadowDistance;
|
||||
context.shadowOffsetY = Math.sin(shadowOptions.angle) * dropShadowDistance + dsOffsetShadow;
|
||||
} else {
|
||||
context.globalAlpha = style._fill?.alpha ?? 1;
|
||||
context.fillStyle = style._fill ? getCanvasFillStyle(style._fill, context) : null;
|
||||
if (style._stroke?.width) {
|
||||
context.strokeStyle = getCanvasFillStyle(style._stroke, context);
|
||||
}
|
||||
context.shadowColor = "black";
|
||||
}
|
||||
let linePositionYShift = (lineHeight - fontProperties.fontSize) / 2;
|
||||
if (lineHeight - fontProperties.fontSize < 0) {
|
||||
linePositionYShift = 0;
|
||||
}
|
||||
const strokeWidth = style._stroke?.width ?? 0;
|
||||
for (let i2 = 0; i2 < lines.length; i2++) {
|
||||
linePositionX = strokeWidth / 2;
|
||||
linePositionY = strokeWidth / 2 + i2 * lineHeight + fontProperties.ascent + linePositionYShift;
|
||||
if (style.align === "right") {
|
||||
linePositionX += maxLineWidth - lineWidths[i2];
|
||||
} else if (style.align === "center") {
|
||||
linePositionX += (maxLineWidth - lineWidths[i2]) / 2;
|
||||
}
|
||||
if (style._stroke?.width) {
|
||||
this._drawLetterSpacing(
|
||||
lines[i2],
|
||||
style,
|
||||
canvasAndContext,
|
||||
linePositionX + style.padding,
|
||||
linePositionY + style.padding - dsOffsetText,
|
||||
true
|
||||
);
|
||||
}
|
||||
if (style._fill !== void 0) {
|
||||
this._drawLetterSpacing(
|
||||
lines[i2],
|
||||
style,
|
||||
canvasAndContext,
|
||||
linePositionX + style.padding,
|
||||
linePositionY + style.padding - dsOffsetText
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Render the text with letter-spacing.
|
||||
* @param text - The text to draw
|
||||
* @param style
|
||||
* @param canvasAndContext
|
||||
* @param x - Horizontal position to draw the text
|
||||
* @param y - Vertical position to draw the text
|
||||
* @param isStroke - Is this drawing for the outside stroke of the
|
||||
* text? If not, it's for the inside fill
|
||||
*/
|
||||
_drawLetterSpacing(text, style, canvasAndContext, x, y, isStroke = false) {
|
||||
const { context } = canvasAndContext;
|
||||
const letterSpacing = style.letterSpacing;
|
||||
let useExperimentalLetterSpacing = false;
|
||||
if (CanvasTextMetrics.experimentalLetterSpacingSupported) {
|
||||
if (CanvasTextMetrics.experimentalLetterSpacing) {
|
||||
context.letterSpacing = `${letterSpacing}px`;
|
||||
context.textLetterSpacing = `${letterSpacing}px`;
|
||||
useExperimentalLetterSpacing = true;
|
||||
} else {
|
||||
context.letterSpacing = "0px";
|
||||
context.textLetterSpacing = "0px";
|
||||
}
|
||||
}
|
||||
if (letterSpacing === 0 || useExperimentalLetterSpacing) {
|
||||
if (isStroke) {
|
||||
context.strokeText(text, x, y);
|
||||
} else {
|
||||
context.fillText(text, x, y);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let currentPosition = x;
|
||||
const stringArray = CanvasTextMetrics.graphemeSegmenter(text);
|
||||
let previousWidth = context.measureText(text).width;
|
||||
let currentWidth = 0;
|
||||
for (let i = 0; i < stringArray.length; ++i) {
|
||||
const currentChar = stringArray[i];
|
||||
if (isStroke) {
|
||||
context.strokeText(currentChar, currentPosition, y);
|
||||
} else {
|
||||
context.fillText(currentChar, currentPosition, y);
|
||||
}
|
||||
let textStr = "";
|
||||
for (let j = i + 1; j < stringArray.length; ++j) {
|
||||
textStr += stringArray[j];
|
||||
}
|
||||
currentWidth = context.measureText(textStr).width;
|
||||
currentPosition += previousWidth - currentWidth + letterSpacing;
|
||||
previousWidth = currentWidth;
|
||||
}
|
||||
}
|
||||
destroy() {
|
||||
this._activeTextures = null;
|
||||
}
|
||||
}
|
||||
/** @ignore */
|
||||
CanvasTextSystem.extension = {
|
||||
type: [
|
||||
ExtensionType.WebGLSystem,
|
||||
ExtensionType.WebGPUSystem,
|
||||
ExtensionType.CanvasSystem
|
||||
],
|
||||
name: "canvasText"
|
||||
};
|
||||
|
||||
export { CanvasTextSystem };
|
||||
//# sourceMappingURL=CanvasTextSystem.mjs.map
|
1
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextSystem.mjs.map
generated
vendored
Normal file
1
node_modules/pixi.js/lib/scene/text/canvas/CanvasTextSystem.mjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
7
node_modules/pixi.js/lib/scene/text/canvas/utils/fontStringFromTextStyle.d.ts
generated
vendored
Normal file
7
node_modules/pixi.js/lib/scene/text/canvas/utils/fontStringFromTextStyle.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { TextStyle } from '../../TextStyle';
|
||||
/**
|
||||
* Generates a font style string to use for `TextMetrics.measureFont()`.
|
||||
* @param style
|
||||
* @returns Font style string, for passing to `TextMetrics.measureFont()`
|
||||
*/
|
||||
export declare function fontStringFromTextStyle(style: TextStyle): string;
|
29
node_modules/pixi.js/lib/scene/text/canvas/utils/fontStringFromTextStyle.js
generated
vendored
Normal file
29
node_modules/pixi.js/lib/scene/text/canvas/utils/fontStringFromTextStyle.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
"use strict";
|
||||
const genericFontFamilies = [
|
||||
"serif",
|
||||
"sans-serif",
|
||||
"monospace",
|
||||
"cursive",
|
||||
"fantasy",
|
||||
"system-ui"
|
||||
];
|
||||
function fontStringFromTextStyle(style) {
|
||||
const fontSizeString = typeof style.fontSize === "number" ? `${style.fontSize}px` : style.fontSize;
|
||||
let fontFamilies = style.fontFamily;
|
||||
if (!Array.isArray(style.fontFamily)) {
|
||||
fontFamilies = style.fontFamily.split(",");
|
||||
}
|
||||
for (let i = fontFamilies.length - 1; i >= 0; i--) {
|
||||
let fontFamily = fontFamilies[i].trim();
|
||||
if (!/([\"\'])[^\'\"]+\1/.test(fontFamily) && !genericFontFamilies.includes(fontFamily)) {
|
||||
fontFamily = `"${fontFamily}"`;
|
||||
}
|
||||
fontFamilies[i] = fontFamily;
|
||||
}
|
||||
return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(",")}`;
|
||||
}
|
||||
|
||||
exports.fontStringFromTextStyle = fontStringFromTextStyle;
|
||||
//# sourceMappingURL=fontStringFromTextStyle.js.map
|
1
node_modules/pixi.js/lib/scene/text/canvas/utils/fontStringFromTextStyle.js.map
generated
vendored
Normal file
1
node_modules/pixi.js/lib/scene/text/canvas/utils/fontStringFromTextStyle.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"fontStringFromTextStyle.js","sources":["../../../../../src/scene/text/canvas/utils/fontStringFromTextStyle.ts"],"sourcesContent":["import type { TextStyle } from '../../TextStyle';\n\nconst genericFontFamilies = [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n];\n\n/**\n * Generates a font style string to use for `TextMetrics.measureFont()`.\n * @param style\n * @returns Font style string, for passing to `TextMetrics.measureFont()`\n */\nexport function fontStringFromTextStyle(style: TextStyle): string\n{\n // build canvas api font setting from individual components. Convert a numeric style.fontSize to px\n const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize;\n\n // Clean-up fontFamily property by quoting each font name\n // this will support font names with spaces\n let fontFamilies: string | string[] = style.fontFamily;\n\n if (!Array.isArray(style.fontFamily))\n {\n fontFamilies = style.fontFamily.split(',');\n }\n\n for (let i = fontFamilies.length - 1; i >= 0; i--)\n {\n // Trim any extra white-space\n let fontFamily = fontFamilies[i].trim();\n\n // Check if font already contains strings\n if (!(/([\\\"\\'])[^\\'\\\"]+\\1/).test(fontFamily) && !genericFontFamilies.includes(fontFamily))\n {\n fontFamily = `\"${fontFamily}\"`;\n }\n (fontFamilies as string[])[i] = fontFamily;\n }\n\n // eslint-disable-next-line max-len\n return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${(fontFamilies as string[]).join(',')}`;\n}\n"],"names":[],"mappings":";;;AAEA,MAAM,mBAAsB,GAAA;AAAA,EACxB,OAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AACJ,CAAA,CAAA;AAOO,SAAS,wBAAwB,KACxC,EAAA;AAEI,EAAM,MAAA,cAAA,GAAkB,OAAO,KAAM,CAAA,QAAA,KAAa,WAAY,CAAG,EAAA,KAAA,CAAM,QAAQ,CAAA,EAAA,CAAA,GAAO,KAAM,CAAA,QAAA,CAAA;AAI5F,EAAA,IAAI,eAAkC,KAAM,CAAA,UAAA,CAAA;AAE5C,EAAA,IAAI,CAAC,KAAA,CAAM,OAAQ,CAAA,KAAA,CAAM,UAAU,CACnC,EAAA;AACI,IAAe,YAAA,GAAA,KAAA,CAAM,UAAW,CAAA,KAAA,CAAM,GAAG,CAAA,CAAA;AAAA,GAC7C;AAEA,EAAA,KAAA,IAAS,IAAI,YAAa,CAAA,MAAA,GAAS,CAAG,EAAA,CAAA,IAAK,GAAG,CAC9C,EAAA,EAAA;AAEI,IAAA,IAAI,UAAa,GAAA,YAAA,CAAa,CAAC,CAAA,CAAE,IAAK,EAAA,CAAA;AAGtC,IAAI,IAAA,CAAE,qBAAsB,IAAK,CAAA,UAAU,KAAK,CAAC,mBAAA,CAAoB,QAAS,CAAA,UAAU,CACxF,EAAA;AACI,MAAA,UAAA,GAAa,IAAI,UAAU,CAAA,CAAA,CAAA,CAAA;AAAA,KAC/B;AACA,IAAC,YAAA,CAA0B,CAAC,CAAI,GAAA,UAAA,CAAA;AAAA,GACpC;AAGA,EAAA,OAAO,CAAG,EAAA,KAAA,CAAM,SAAS,CAAA,CAAA,EAAI,MAAM,WAAW,CAAA,CAAA,EAAI,KAAM,CAAA,UAAU,IAAI,cAAc,CAAA,CAAA,EAAK,YAA0B,CAAA,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,CAAA;AAChI;;;;"}
|
27
node_modules/pixi.js/lib/scene/text/canvas/utils/fontStringFromTextStyle.mjs
generated
vendored
Normal file
27
node_modules/pixi.js/lib/scene/text/canvas/utils/fontStringFromTextStyle.mjs
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
"use strict";
|
||||
const genericFontFamilies = [
|
||||
"serif",
|
||||
"sans-serif",
|
||||
"monospace",
|
||||
"cursive",
|
||||
"fantasy",
|
||||
"system-ui"
|
||||
];
|
||||
function fontStringFromTextStyle(style) {
|
||||
const fontSizeString = typeof style.fontSize === "number" ? `${style.fontSize}px` : style.fontSize;
|
||||
let fontFamilies = style.fontFamily;
|
||||
if (!Array.isArray(style.fontFamily)) {
|
||||
fontFamilies = style.fontFamily.split(",");
|
||||
}
|
||||
for (let i = fontFamilies.length - 1; i >= 0; i--) {
|
||||
let fontFamily = fontFamilies[i].trim();
|
||||
if (!/([\"\'])[^\'\"]+\1/.test(fontFamily) && !genericFontFamilies.includes(fontFamily)) {
|
||||
fontFamily = `"${fontFamily}"`;
|
||||
}
|
||||
fontFamilies[i] = fontFamily;
|
||||
}
|
||||
return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(",")}`;
|
||||
}
|
||||
|
||||
export { fontStringFromTextStyle };
|
||||
//# sourceMappingURL=fontStringFromTextStyle.mjs.map
|
1
node_modules/pixi.js/lib/scene/text/canvas/utils/fontStringFromTextStyle.mjs.map
generated
vendored
Normal file
1
node_modules/pixi.js/lib/scene/text/canvas/utils/fontStringFromTextStyle.mjs.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"fontStringFromTextStyle.mjs","sources":["../../../../../src/scene/text/canvas/utils/fontStringFromTextStyle.ts"],"sourcesContent":["import type { TextStyle } from '../../TextStyle';\n\nconst genericFontFamilies = [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n];\n\n/**\n * Generates a font style string to use for `TextMetrics.measureFont()`.\n * @param style\n * @returns Font style string, for passing to `TextMetrics.measureFont()`\n */\nexport function fontStringFromTextStyle(style: TextStyle): string\n{\n // build canvas api font setting from individual components. Convert a numeric style.fontSize to px\n const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize;\n\n // Clean-up fontFamily property by quoting each font name\n // this will support font names with spaces\n let fontFamilies: string | string[] = style.fontFamily;\n\n if (!Array.isArray(style.fontFamily))\n {\n fontFamilies = style.fontFamily.split(',');\n }\n\n for (let i = fontFamilies.length - 1; i >= 0; i--)\n {\n // Trim any extra white-space\n let fontFamily = fontFamilies[i].trim();\n\n // Check if font already contains strings\n if (!(/([\\\"\\'])[^\\'\\\"]+\\1/).test(fontFamily) && !genericFontFamilies.includes(fontFamily))\n {\n fontFamily = `\"${fontFamily}\"`;\n }\n (fontFamilies as string[])[i] = fontFamily;\n }\n\n // eslint-disable-next-line max-len\n return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${(fontFamilies as string[]).join(',')}`;\n}\n"],"names":[],"mappings":";AAEA,MAAM,mBAAsB,GAAA;AAAA,EACxB,OAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AACJ,CAAA,CAAA;AAOO,SAAS,wBAAwB,KACxC,EAAA;AAEI,EAAM,MAAA,cAAA,GAAkB,OAAO,KAAM,CAAA,QAAA,KAAa,WAAY,CAAG,EAAA,KAAA,CAAM,QAAQ,CAAA,EAAA,CAAA,GAAO,KAAM,CAAA,QAAA,CAAA;AAI5F,EAAA,IAAI,eAAkC,KAAM,CAAA,UAAA,CAAA;AAE5C,EAAA,IAAI,CAAC,KAAA,CAAM,OAAQ,CAAA,KAAA,CAAM,UAAU,CACnC,EAAA;AACI,IAAe,YAAA,GAAA,KAAA,CAAM,UAAW,CAAA,KAAA,CAAM,GAAG,CAAA,CAAA;AAAA,GAC7C;AAEA,EAAA,KAAA,IAAS,IAAI,YAAa,CAAA,MAAA,GAAS,CAAG,EAAA,CAAA,IAAK,GAAG,CAC9C,EAAA,EAAA;AAEI,IAAA,IAAI,UAAa,GAAA,YAAA,CAAa,CAAC,CAAA,CAAE,IAAK,EAAA,CAAA;AAGtC,IAAI,IAAA,CAAE,qBAAsB,IAAK,CAAA,UAAU,KAAK,CAAC,mBAAA,CAAoB,QAAS,CAAA,UAAU,CACxF,EAAA;AACI,MAAA,UAAA,GAAa,IAAI,UAAU,CAAA,CAAA,CAAA,CAAA;AAAA,KAC/B;AACA,IAAC,YAAA,CAA0B,CAAC,CAAI,GAAA,UAAA,CAAA;AAAA,GACpC;AAGA,EAAA,OAAO,CAAG,EAAA,KAAA,CAAM,SAAS,CAAA,CAAA,EAAI,MAAM,WAAW,CAAA,CAAA,EAAI,KAAM,CAAA,UAAU,IAAI,cAAc,CAAA,CAAA,EAAK,YAA0B,CAAA,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,CAAA;AAChI;;;;"}
|
3
node_modules/pixi.js/lib/scene/text/canvas/utils/getCanvasFillStyle.d.ts
generated
vendored
Normal file
3
node_modules/pixi.js/lib/scene/text/canvas/utils/getCanvasFillStyle.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import type { ICanvasRenderingContext2D } from '../../../../environment/canvas/ICanvasRenderingContext2D';
|
||||
import type { ConvertedFillStyle } from '../../../graphics/shared/FillTypes';
|
||||
export declare function getCanvasFillStyle(fillStyle: ConvertedFillStyle, context: ICanvasRenderingContext2D): string | CanvasGradient | CanvasPattern;
|
50
node_modules/pixi.js/lib/scene/text/canvas/utils/getCanvasFillStyle.js
generated
vendored
Normal file
50
node_modules/pixi.js/lib/scene/text/canvas/utils/getCanvasFillStyle.js
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
'use strict';
|
||||
|
||||
var Color = require('../../../../color/Color.js');
|
||||
var Matrix = require('../../../../maths/matrix/Matrix.js');
|
||||
var Texture = require('../../../../rendering/renderers/shared/texture/Texture.js');
|
||||
var warn = require('../../../../utils/logging/warn.js');
|
||||
var FillGradient = require('../../../graphics/shared/fill/FillGradient.js');
|
||||
var FillPattern = require('../../../graphics/shared/fill/FillPattern.js');
|
||||
|
||||
"use strict";
|
||||
function getCanvasFillStyle(fillStyle, context) {
|
||||
if (fillStyle.texture === Texture.Texture.WHITE && !fillStyle.fill) {
|
||||
return Color.Color.shared.setValue(fillStyle.color).setAlpha(fillStyle.alpha ?? 1).toHexa();
|
||||
} else if (!fillStyle.fill) {
|
||||
const pattern = context.createPattern(fillStyle.texture.source.resource, "repeat");
|
||||
const tempMatrix = fillStyle.matrix.copyTo(Matrix.Matrix.shared);
|
||||
tempMatrix.scale(fillStyle.texture.frame.width, fillStyle.texture.frame.height);
|
||||
pattern.setTransform(tempMatrix);
|
||||
return pattern;
|
||||
} else if (fillStyle.fill instanceof FillPattern.FillPattern) {
|
||||
const fillPattern = fillStyle.fill;
|
||||
const pattern = context.createPattern(fillPattern.texture.source.resource, "repeat");
|
||||
const tempMatrix = fillPattern.transform.copyTo(Matrix.Matrix.shared);
|
||||
tempMatrix.scale(
|
||||
fillPattern.texture.frame.width,
|
||||
fillPattern.texture.frame.height
|
||||
);
|
||||
pattern.setTransform(tempMatrix);
|
||||
return pattern;
|
||||
} else if (fillStyle.fill instanceof FillGradient.FillGradient) {
|
||||
const fillGradient = fillStyle.fill;
|
||||
if (fillGradient.type === "linear") {
|
||||
const gradient = context.createLinearGradient(
|
||||
fillGradient.x0,
|
||||
fillGradient.y0,
|
||||
fillGradient.x1,
|
||||
fillGradient.y1
|
||||
);
|
||||
fillGradient.gradientStops.forEach((stop) => {
|
||||
gradient.addColorStop(stop.offset, Color.Color.shared.setValue(stop.color).toHex());
|
||||
});
|
||||
return gradient;
|
||||
}
|
||||
}
|
||||
warn.warn("FillStyle not recognised", fillStyle);
|
||||
return "red";
|
||||
}
|
||||
|
||||
exports.getCanvasFillStyle = getCanvasFillStyle;
|
||||
//# sourceMappingURL=getCanvasFillStyle.js.map
|
1
node_modules/pixi.js/lib/scene/text/canvas/utils/getCanvasFillStyle.js.map
generated
vendored
Normal file
1
node_modules/pixi.js/lib/scene/text/canvas/utils/getCanvasFillStyle.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"getCanvasFillStyle.js","sources":["../../../../../src/scene/text/canvas/utils/getCanvasFillStyle.ts"],"sourcesContent":["import { Color } from '../../../../color/Color';\nimport { Matrix } from '../../../../maths/matrix/Matrix';\nimport { Texture } from '../../../../rendering/renderers/shared/texture/Texture';\nimport { warn } from '../../../../utils/logging/warn';\nimport { FillGradient } from '../../../graphics/shared/fill/FillGradient';\nimport { FillPattern } from '../../../graphics/shared/fill/FillPattern';\n\nimport type { ICanvasRenderingContext2D } from '../../../../environment/canvas/ICanvasRenderingContext2D';\nimport type { ConvertedFillStyle } from '../../../graphics/shared/FillTypes';\n\nexport function getCanvasFillStyle(\n fillStyle: ConvertedFillStyle,\n context: ICanvasRenderingContext2D): string | CanvasGradient | CanvasPattern\n{\n if (fillStyle.texture === Texture.WHITE && !fillStyle.fill)\n {\n return Color.shared.setValue(fillStyle.color).setAlpha(fillStyle.alpha ?? 1).toHexa();\n }\n else if (!fillStyle.fill)\n {\n // fancy set up...\n const pattern = context.createPattern(fillStyle.texture.source.resource, 'repeat');\n\n // create an inverted scale matrix..\n const tempMatrix = fillStyle.matrix.copyTo(Matrix.shared);\n\n tempMatrix.scale(fillStyle.texture.frame.width, fillStyle.texture.frame.height);\n\n pattern.setTransform(tempMatrix);\n\n return pattern;\n }\n else if (fillStyle.fill instanceof FillPattern)\n {\n const fillPattern = fillStyle.fill;\n\n const pattern = context.createPattern(fillPattern.texture.source.resource, 'repeat');\n\n const tempMatrix = fillPattern.transform.copyTo(Matrix.shared);\n\n tempMatrix.scale(\n fillPattern.texture.frame.width,\n fillPattern.texture.frame.height\n );\n\n pattern.setTransform(tempMatrix);\n\n return pattern;\n }\n else if (fillStyle.fill instanceof FillGradient)\n {\n const fillGradient = fillStyle.fill;\n\n if (fillGradient.type === 'linear')\n {\n const gradient = context.createLinearGradient(\n fillGradient.x0,\n fillGradient.y0,\n fillGradient.x1,\n fillGradient.y1\n );\n\n fillGradient.gradientStops.forEach((stop) =>\n {\n gradient.addColorStop(stop.offset, Color.shared.setValue(stop.color).toHex());\n });\n\n return gradient;\n }\n }\n\n // #if _DEBUG\n warn('FillStyle not recognised', fillStyle);\n // #endif\n\n return 'red';\n}\n"],"names":["Texture","Color","Matrix","FillPattern","FillGradient","warn"],"mappings":";;;;;;;;;;AAUgB,SAAA,kBAAA,CACZ,WACA,OACJ,EAAA;AACI,EAAA,IAAI,UAAU,OAAY,KAAAA,eAAA,CAAQ,KAAS,IAAA,CAAC,UAAU,IACtD,EAAA;AACI,IAAO,OAAAC,WAAA,CAAM,MAAO,CAAA,QAAA,CAAS,SAAU,CAAA,KAAK,CAAE,CAAA,QAAA,CAAS,SAAU,CAAA,KAAA,IAAS,CAAC,CAAA,CAAE,MAAO,EAAA,CAAA;AAAA,GACxF,MAAA,IACS,CAAC,SAAA,CAAU,IACpB,EAAA;AAEI,IAAA,MAAM,UAAU,OAAQ,CAAA,aAAA,CAAc,UAAU,OAAQ,CAAA,MAAA,CAAO,UAAU,QAAQ,CAAA,CAAA;AAGjF,IAAA,MAAM,UAAa,GAAA,SAAA,CAAU,MAAO,CAAA,MAAA,CAAOC,cAAO,MAAM,CAAA,CAAA;AAExD,IAAW,UAAA,CAAA,KAAA,CAAM,UAAU,OAAQ,CAAA,KAAA,CAAM,OAAO,SAAU,CAAA,OAAA,CAAQ,MAAM,MAAM,CAAA,CAAA;AAE9E,IAAA,OAAA,CAAQ,aAAa,UAAU,CAAA,CAAA;AAE/B,IAAO,OAAA,OAAA,CAAA;AAAA,GACX,MAAA,IACS,SAAU,CAAA,IAAA,YAAgBC,uBACnC,EAAA;AACI,IAAA,MAAM,cAAc,SAAU,CAAA,IAAA,CAAA;AAE9B,IAAA,MAAM,UAAU,OAAQ,CAAA,aAAA,CAAc,YAAY,OAAQ,CAAA,MAAA,CAAO,UAAU,QAAQ,CAAA,CAAA;AAEnF,IAAA,MAAM,UAAa,GAAA,WAAA,CAAY,SAAU,CAAA,MAAA,CAAOD,cAAO,MAAM,CAAA,CAAA;AAE7D,IAAW,UAAA,CAAA,KAAA;AAAA,MACP,WAAA,CAAY,QAAQ,KAAM,CAAA,KAAA;AAAA,MAC1B,WAAA,CAAY,QAAQ,KAAM,CAAA,MAAA;AAAA,KAC9B,CAAA;AAEA,IAAA,OAAA,CAAQ,aAAa,UAAU,CAAA,CAAA;AAE/B,IAAO,OAAA,OAAA,CAAA;AAAA,GACX,MAAA,IACS,SAAU,CAAA,IAAA,YAAgBE,yBACnC,EAAA;AACI,IAAA,MAAM,eAAe,SAAU,CAAA,IAAA,CAAA;AAE/B,IAAI,IAAA,YAAA,CAAa,SAAS,QAC1B,EAAA;AACI,MAAA,MAAM,WAAW,OAAQ,CAAA,oBAAA;AAAA,QACrB,YAAa,CAAA,EAAA;AAAA,QACb,YAAa,CAAA,EAAA;AAAA,QACb,YAAa,CAAA,EAAA;AAAA,QACb,YAAa,CAAA,EAAA;AAAA,OACjB,CAAA;AAEA,MAAa,YAAA,CAAA,aAAA,CAAc,OAAQ,CAAA,CAAC,IACpC,KAAA;AACI,QAAS,QAAA,CAAA,YAAA,CAAa,IAAK,CAAA,MAAA,EAAQH,WAAM,CAAA,MAAA,CAAO,SAAS,IAAK,CAAA,KAAK,CAAE,CAAA,KAAA,EAAO,CAAA,CAAA;AAAA,OAC/E,CAAA,CAAA;AAED,MAAO,OAAA,QAAA,CAAA;AAAA,KACX;AAAA,GACJ;AAGA,EAAAI,SAAA,CAAK,4BAA4B,SAAS,CAAA,CAAA;AAG1C,EAAO,OAAA,KAAA,CAAA;AACX;;;;"}
|
48
node_modules/pixi.js/lib/scene/text/canvas/utils/getCanvasFillStyle.mjs
generated
vendored
Normal file
48
node_modules/pixi.js/lib/scene/text/canvas/utils/getCanvasFillStyle.mjs
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Color } from '../../../../color/Color.mjs';
|
||||
import { Matrix } from '../../../../maths/matrix/Matrix.mjs';
|
||||
import { Texture } from '../../../../rendering/renderers/shared/texture/Texture.mjs';
|
||||
import { warn } from '../../../../utils/logging/warn.mjs';
|
||||
import { FillGradient } from '../../../graphics/shared/fill/FillGradient.mjs';
|
||||
import { FillPattern } from '../../../graphics/shared/fill/FillPattern.mjs';
|
||||
|
||||
"use strict";
|
||||
function getCanvasFillStyle(fillStyle, context) {
|
||||
if (fillStyle.texture === Texture.WHITE && !fillStyle.fill) {
|
||||
return Color.shared.setValue(fillStyle.color).setAlpha(fillStyle.alpha ?? 1).toHexa();
|
||||
} else if (!fillStyle.fill) {
|
||||
const pattern = context.createPattern(fillStyle.texture.source.resource, "repeat");
|
||||
const tempMatrix = fillStyle.matrix.copyTo(Matrix.shared);
|
||||
tempMatrix.scale(fillStyle.texture.frame.width, fillStyle.texture.frame.height);
|
||||
pattern.setTransform(tempMatrix);
|
||||
return pattern;
|
||||
} else if (fillStyle.fill instanceof FillPattern) {
|
||||
const fillPattern = fillStyle.fill;
|
||||
const pattern = context.createPattern(fillPattern.texture.source.resource, "repeat");
|
||||
const tempMatrix = fillPattern.transform.copyTo(Matrix.shared);
|
||||
tempMatrix.scale(
|
||||
fillPattern.texture.frame.width,
|
||||
fillPattern.texture.frame.height
|
||||
);
|
||||
pattern.setTransform(tempMatrix);
|
||||
return pattern;
|
||||
} else if (fillStyle.fill instanceof FillGradient) {
|
||||
const fillGradient = fillStyle.fill;
|
||||
if (fillGradient.type === "linear") {
|
||||
const gradient = context.createLinearGradient(
|
||||
fillGradient.x0,
|
||||
fillGradient.y0,
|
||||
fillGradient.x1,
|
||||
fillGradient.y1
|
||||
);
|
||||
fillGradient.gradientStops.forEach((stop) => {
|
||||
gradient.addColorStop(stop.offset, Color.shared.setValue(stop.color).toHex());
|
||||
});
|
||||
return gradient;
|
||||
}
|
||||
}
|
||||
warn("FillStyle not recognised", fillStyle);
|
||||
return "red";
|
||||
}
|
||||
|
||||
export { getCanvasFillStyle };
|
||||
//# sourceMappingURL=getCanvasFillStyle.mjs.map
|
1
node_modules/pixi.js/lib/scene/text/canvas/utils/getCanvasFillStyle.mjs.map
generated
vendored
Normal file
1
node_modules/pixi.js/lib/scene/text/canvas/utils/getCanvasFillStyle.mjs.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"getCanvasFillStyle.mjs","sources":["../../../../../src/scene/text/canvas/utils/getCanvasFillStyle.ts"],"sourcesContent":["import { Color } from '../../../../color/Color';\nimport { Matrix } from '../../../../maths/matrix/Matrix';\nimport { Texture } from '../../../../rendering/renderers/shared/texture/Texture';\nimport { warn } from '../../../../utils/logging/warn';\nimport { FillGradient } from '../../../graphics/shared/fill/FillGradient';\nimport { FillPattern } from '../../../graphics/shared/fill/FillPattern';\n\nimport type { ICanvasRenderingContext2D } from '../../../../environment/canvas/ICanvasRenderingContext2D';\nimport type { ConvertedFillStyle } from '../../../graphics/shared/FillTypes';\n\nexport function getCanvasFillStyle(\n fillStyle: ConvertedFillStyle,\n context: ICanvasRenderingContext2D): string | CanvasGradient | CanvasPattern\n{\n if (fillStyle.texture === Texture.WHITE && !fillStyle.fill)\n {\n return Color.shared.setValue(fillStyle.color).setAlpha(fillStyle.alpha ?? 1).toHexa();\n }\n else if (!fillStyle.fill)\n {\n // fancy set up...\n const pattern = context.createPattern(fillStyle.texture.source.resource, 'repeat');\n\n // create an inverted scale matrix..\n const tempMatrix = fillStyle.matrix.copyTo(Matrix.shared);\n\n tempMatrix.scale(fillStyle.texture.frame.width, fillStyle.texture.frame.height);\n\n pattern.setTransform(tempMatrix);\n\n return pattern;\n }\n else if (fillStyle.fill instanceof FillPattern)\n {\n const fillPattern = fillStyle.fill;\n\n const pattern = context.createPattern(fillPattern.texture.source.resource, 'repeat');\n\n const tempMatrix = fillPattern.transform.copyTo(Matrix.shared);\n\n tempMatrix.scale(\n fillPattern.texture.frame.width,\n fillPattern.texture.frame.height\n );\n\n pattern.setTransform(tempMatrix);\n\n return pattern;\n }\n else if (fillStyle.fill instanceof FillGradient)\n {\n const fillGradient = fillStyle.fill;\n\n if (fillGradient.type === 'linear')\n {\n const gradient = context.createLinearGradient(\n fillGradient.x0,\n fillGradient.y0,\n fillGradient.x1,\n fillGradient.y1\n );\n\n fillGradient.gradientStops.forEach((stop) =>\n {\n gradient.addColorStop(stop.offset, Color.shared.setValue(stop.color).toHex());\n });\n\n return gradient;\n }\n }\n\n // #if _DEBUG\n warn('FillStyle not recognised', fillStyle);\n // #endif\n\n return 'red';\n}\n"],"names":[],"mappings":";;;;;;;;AAUgB,SAAA,kBAAA,CACZ,WACA,OACJ,EAAA;AACI,EAAA,IAAI,UAAU,OAAY,KAAA,OAAA,CAAQ,KAAS,IAAA,CAAC,UAAU,IACtD,EAAA;AACI,IAAO,OAAA,KAAA,CAAM,MAAO,CAAA,QAAA,CAAS,SAAU,CAAA,KAAK,CAAE,CAAA,QAAA,CAAS,SAAU,CAAA,KAAA,IAAS,CAAC,CAAA,CAAE,MAAO,EAAA,CAAA;AAAA,GACxF,MAAA,IACS,CAAC,SAAA,CAAU,IACpB,EAAA;AAEI,IAAA,MAAM,UAAU,OAAQ,CAAA,aAAA,CAAc,UAAU,OAAQ,CAAA,MAAA,CAAO,UAAU,QAAQ,CAAA,CAAA;AAGjF,IAAA,MAAM,UAAa,GAAA,SAAA,CAAU,MAAO,CAAA,MAAA,CAAO,OAAO,MAAM,CAAA,CAAA;AAExD,IAAW,UAAA,CAAA,KAAA,CAAM,UAAU,OAAQ,CAAA,KAAA,CAAM,OAAO,SAAU,CAAA,OAAA,CAAQ,MAAM,MAAM,CAAA,CAAA;AAE9E,IAAA,OAAA,CAAQ,aAAa,UAAU,CAAA,CAAA;AAE/B,IAAO,OAAA,OAAA,CAAA;AAAA,GACX,MAAA,IACS,SAAU,CAAA,IAAA,YAAgB,WACnC,EAAA;AACI,IAAA,MAAM,cAAc,SAAU,CAAA,IAAA,CAAA;AAE9B,IAAA,MAAM,UAAU,OAAQ,CAAA,aAAA,CAAc,YAAY,OAAQ,CAAA,MAAA,CAAO,UAAU,QAAQ,CAAA,CAAA;AAEnF,IAAA,MAAM,UAAa,GAAA,WAAA,CAAY,SAAU,CAAA,MAAA,CAAO,OAAO,MAAM,CAAA,CAAA;AAE7D,IAAW,UAAA,CAAA,KAAA;AAAA,MACP,WAAA,CAAY,QAAQ,KAAM,CAAA,KAAA;AAAA,MAC1B,WAAA,CAAY,QAAQ,KAAM,CAAA,MAAA;AAAA,KAC9B,CAAA;AAEA,IAAA,OAAA,CAAQ,aAAa,UAAU,CAAA,CAAA;AAE/B,IAAO,OAAA,OAAA,CAAA;AAAA,GACX,MAAA,IACS,SAAU,CAAA,IAAA,YAAgB,YACnC,EAAA;AACI,IAAA,MAAM,eAAe,SAAU,CAAA,IAAA,CAAA;AAE/B,IAAI,IAAA,YAAA,CAAa,SAAS,QAC1B,EAAA;AACI,MAAA,MAAM,WAAW,OAAQ,CAAA,oBAAA;AAAA,QACrB,YAAa,CAAA,EAAA;AAAA,QACb,YAAa,CAAA,EAAA;AAAA,QACb,YAAa,CAAA,EAAA;AAAA,QACb,YAAa,CAAA,EAAA;AAAA,OACjB,CAAA;AAEA,MAAa,YAAA,CAAA,aAAA,CAAc,OAAQ,CAAA,CAAC,IACpC,KAAA;AACI,QAAS,QAAA,CAAA,YAAA,CAAa,IAAK,CAAA,MAAA,EAAQ,KAAM,CAAA,MAAA,CAAO,SAAS,IAAK,CAAA,KAAK,CAAE,CAAA,KAAA,EAAO,CAAA,CAAA;AAAA,OAC/E,CAAA,CAAA;AAED,MAAO,OAAA,QAAA,CAAA;AAAA,KACX;AAAA,GACJ;AAGA,EAAA,IAAA,CAAK,4BAA4B,SAAS,CAAA,CAAA;AAG1C,EAAO,OAAA,KAAA,CAAA;AACX;;;;"}
|
Reference in New Issue
Block a user