| 1 |
- {"version":3,"file":"text.min.mjs","sources":["../../../../node_modules/tslib/tslib.es6.js","../../src/const.ts","../../src/TextStyle.ts","../../src/TextMetrics.ts","../../src/Text.ts"],"sourcesContent":["/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport function __createBinding(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n}\r\n\r\nexport function __exportStar(m, exports) {\r\n for (var p in m) if (p !== \"default\" && !exports.hasOwnProperty(p)) exports[p] = m[p];\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\r\n result.default = mod;\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, privateMap) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to get private field on non-instance\");\r\n }\r\n return privateMap.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, privateMap, value) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to set private field on non-instance\");\r\n }\r\n privateMap.set(receiver, value);\r\n return value;\r\n}\r\n","/**\n * Constants that define the type of gradient on text.\n * @static\n * @constant\n * @name TEXT_GRADIENT\n * @memberof PIXI\n * @type {object}\n * @property {number} LINEAR_VERTICAL Vertical gradient\n * @property {number} LINEAR_HORIZONTAL Linear gradient\n */\nexport enum TEXT_GRADIENT\n// eslint-disable-next-line @typescript-eslint/indent\n{\n LINEAR_VERTICAL = 0,\n LINEAR_HORIZONTAL = 1\n}\n","// disabling eslint for now, going to rewrite this in v5\n/* eslint-disable */\n\nimport { TEXT_GRADIENT } from './const';\nimport { hex2string } from '@pixi/utils';\n\nexport type TextStyleAlign = 'left'|'center'|'right'|'justify';\nexport type TextStyleFill = string|string[]|number|number[]|CanvasGradient|CanvasPattern;\nexport type TextStyleFontStyle = 'normal'|'italic'|'oblique';\nexport type TextStyleFontVariant = 'normal'|'small-caps';\nexport type TextStyleFontWeight = 'normal'|'bold'|'bolder'|'lighter'|'100'|'200'|'300'|'400'|'500'|'600'|'700'|'800'|'900';\nexport type TextStyleLineJoin = 'miter'|'round'|'bevel';\nexport type TextStyleTextBaseline = 'alphabetic'|'top'|'hanging'|'middle'|'ideographic'|'bottom';\nexport type TextStyleWhiteSpace = 'normal'|'pre'|'pre-line';\n\nexport interface ITextStyle {\n align: TextStyleAlign;\n breakWords: boolean;\n dropShadow: boolean;\n dropShadowAlpha: number;\n dropShadowAngle: number;\n dropShadowBlur: number;\n dropShadowColor: string|number;\n dropShadowDistance: number;\n fill: TextStyleFill;\n fillGradientType: TEXT_GRADIENT;\n fillGradientStops: number[];\n fontFamily: string | string[];\n fontSize: number | string;\n fontStyle: TextStyleFontStyle;\n fontVariant: TextStyleFontVariant;\n fontWeight: TextStyleFontWeight;\n letterSpacing: number;\n lineHeight: number;\n lineJoin: TextStyleLineJoin;\n miterLimit: number;\n padding: number;\n stroke: string|number;\n strokeThickness: number;\n textBaseline: TextStyleTextBaseline;\n trim: boolean;\n whiteSpace: TextStyleWhiteSpace;\n wordWrap: boolean;\n wordWrapWidth: number;\n leading: number;\n}\n\nconst defaultStyle: ITextStyle = {\n align: 'left',\n breakWords: false,\n dropShadow: false,\n dropShadowAlpha: 1,\n dropShadowAngle: Math.PI / 6,\n dropShadowBlur: 0,\n dropShadowColor: 'black',\n dropShadowDistance: 5,\n fill: 'black',\n fillGradientType: TEXT_GRADIENT.LINEAR_VERTICAL,\n fillGradientStops: [],\n fontFamily: 'Arial',\n fontSize: 26,\n fontStyle: 'normal',\n fontVariant: 'normal',\n fontWeight: 'normal',\n letterSpacing: 0,\n lineHeight: 0,\n lineJoin: 'miter',\n miterLimit: 10,\n padding: 0,\n stroke: 'black',\n strokeThickness: 0,\n textBaseline: 'alphabetic',\n trim: false,\n whiteSpace: 'pre',\n wordWrap: false,\n wordWrapWidth: 100,\n leading: 0,\n};\n\nconst genericFontFamilies = [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n];\n\n/**\n * A TextStyle Object contains information to decorate a Text objects.\n *\n * An instance can be shared between multiple Text objects; then changing the style will update all text objects using it.\n *\n * A tool can be used to generate a text style [here](https://pixijs.io/pixi-text-style).\n *\n * @memberof PIXI\n */\nexport class TextStyle implements ITextStyle\n{\n public styleID: number;\n\n protected _align: TextStyleAlign;\n protected _breakWords: boolean;\n protected _dropShadow: boolean;\n protected _dropShadowAlpha: number;\n protected _dropShadowAngle: number;\n protected _dropShadowBlur: number;\n protected _dropShadowColor: string|number;\n protected _dropShadowDistance: number;\n protected _fill: TextStyleFill;\n protected _fillGradientType: TEXT_GRADIENT;\n protected _fillGradientStops: number[];\n protected _fontFamily: string|string[];\n protected _fontSize: number|string;\n protected _fontStyle: TextStyleFontStyle;\n protected _fontVariant: TextStyleFontVariant;\n protected _fontWeight: TextStyleFontWeight;\n protected _letterSpacing: number;\n protected _lineHeight: number;\n protected _lineJoin: TextStyleLineJoin;\n protected _miterLimit: number;\n protected _padding: number;\n protected _stroke: string|number;\n protected _strokeThickness: number;\n protected _textBaseline: TextStyleTextBaseline;\n protected _trim: boolean;\n protected _whiteSpace: TextStyleWhiteSpace;\n protected _wordWrap: boolean;\n protected _wordWrapWidth: number;\n protected _leading: number;\n\n /**\n * @param {object} [style] - The style parameters\n * @param {string} [style.align='left'] - Alignment for multiline text ('left', 'center' or 'right'),\n * does not affect single line text\n * @param {boolean} [style.breakWords=false] - Indicates if lines can be wrapped within words, it\n * needs wordWrap to be set to true\n * @param {boolean} [style.dropShadow=false] - Set a drop shadow for the text\n * @param {number} [style.dropShadowAlpha=1] - Set alpha for the drop shadow\n * @param {number} [style.dropShadowAngle=Math.PI/6] - Set a angle of the drop shadow\n * @param {number} [style.dropShadowBlur=0] - Set a shadow blur radius\n * @param {string|number} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00'\n * @param {number} [style.dropShadowDistance=5] - Set a distance of the drop shadow\n * @param {string|string[]|number|number[]|CanvasGradient|CanvasPattern} [style.fill='black'] - A canvas\n * fillstyle that will be used on the text e.g 'red', '#00FF00'. Can be an array to create a gradient\n * eg ['#000000','#FFFFFF']\n * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN}\n * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fill is an array of colours\n * to create a gradient, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT}\n * @param {number[]} [style.fillGradientStops] - If fill is an array of colours to create a gradient, this array can set\n * the stop points (numbers between 0 and 1) for the color, overriding the default behaviour of evenly spacing them.\n * @param {string|string[]} [style.fontFamily='Arial'] - The font family\n * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string,\n * equivalents are '26px','20pt','160%' or '1.6em')\n * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique')\n * @param {string} [style.fontVariant='normal'] - The font variant ('normal' or 'small-caps')\n * @param {string} [style.fontWeight='normal'] - The font weight ('normal', 'bold', 'bolder', 'lighter' and '100',\n * '200', '300', '400', '500', '600', '700', '800' or '900')\n * @param {number} [style.leading=0] - The space between lines\n * @param {number} [style.letterSpacing=0] - The amount of spacing between letters, default is 0\n * @param {number} [style.lineHeight] - The line height, a number that represents the vertical space that a letter uses\n * @param {string} [style.lineJoin='miter'] - The lineJoin property sets the type of corner created, it can resolve\n * spiked text issues. Possible values \"miter\" (creates a sharp corner), \"round\" (creates a round corner) or \"bevel\"\n * (creates a squared corner).\n * @param {number} [style.miterLimit=10] - The miter limit to use when using the 'miter' lineJoin mode. This can reduce\n * or increase the spikiness of rendered text.\n * @param {number} [style.padding=0] - Occasionally some fonts are cropped. Adding some padding will prevent this from\n * happening by adding padding to all sides of the text.\n * @param {string|number} [style.stroke='black'] - A canvas fillstyle that will be used on the text stroke\n * e.g 'blue', '#FCFF00'\n * @param {number} [style.strokeThickness=0] - A number that represents the thickness of the stroke.\n * Default is 0 (no stroke)\n * @param {boolean} [style.trim=false] - Trim transparent borders\n * @param {string} [style.textBaseline='alphabetic'] - The baseline of the text that is rendered.\n * @param {string} [style.whiteSpace='pre'] - Determines whether newlines & spaces are collapsed or preserved \"normal\"\n * (collapse, collapse), \"pre\" (preserve, preserve) | \"pre-line\" (preserve, collapse). It needs wordWrap to be set to true\n * @param {boolean} [style.wordWrap=false] - Indicates if word wrap should be used\n * @param {number} [style.wordWrapWidth=100] - The width at which text will wrap, it needs wordWrap to be set to true\n */\n constructor(style?: Partial<ITextStyle>)\n {\n this.styleID = 0;\n\n this.reset();\n\n deepCopyProperties(this, style, style);\n }\n\n /**\n * Creates a new TextStyle object with the same values as this one.\n * Note that the only the properties of the object are cloned.\n *\n * @return New cloned TextStyle object\n */\n public clone(): TextStyle\n {\n const clonedProperties: Partial<ITextStyle> = {};\n\n deepCopyProperties(clonedProperties, this, defaultStyle);\n\n return new TextStyle(clonedProperties);\n }\n\n /** Resets all properties to the defaults specified in TextStyle.prototype._default */\n public reset(): void\n {\n deepCopyProperties(this, defaultStyle, defaultStyle);\n }\n\n /**\n * Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text\n *\n * @member {string}\n */\n get align(): TextStyleAlign\n {\n return this._align;\n }\n set align(align: TextStyleAlign)\n {\n if (this._align !== align)\n {\n this._align = align;\n this.styleID++;\n }\n }\n\n /** Indicates if lines can be wrapped within words, it needs wordWrap to be set to true. */\n get breakWords(): boolean\n {\n return this._breakWords;\n }\n set breakWords(breakWords: boolean)\n {\n if (this._breakWords !== breakWords)\n {\n this._breakWords = breakWords;\n this.styleID++;\n }\n }\n\n /** Set a drop shadow for the text. */\n get dropShadow(): boolean\n {\n return this._dropShadow;\n }\n set dropShadow(dropShadow: boolean)\n {\n if (this._dropShadow !== dropShadow)\n {\n this._dropShadow = dropShadow;\n this.styleID++;\n }\n }\n\n /** Set alpha for the drop shadow. */\n get dropShadowAlpha(): number\n {\n return this._dropShadowAlpha;\n }\n set dropShadowAlpha(dropShadowAlpha: number)\n {\n if (this._dropShadowAlpha !== dropShadowAlpha)\n {\n this._dropShadowAlpha = dropShadowAlpha;\n this.styleID++;\n }\n }\n\n /** Set a angle of the drop shadow. */\n get dropShadowAngle(): number\n {\n return this._dropShadowAngle;\n }\n set dropShadowAngle(dropShadowAngle: number)\n {\n if (this._dropShadowAngle !== dropShadowAngle)\n {\n this._dropShadowAngle = dropShadowAngle;\n this.styleID++;\n }\n }\n\n /** Set a shadow blur radius. */\n get dropShadowBlur(): number\n {\n return this._dropShadowBlur;\n }\n set dropShadowBlur(dropShadowBlur: number)\n {\n if (this._dropShadowBlur !== dropShadowBlur)\n {\n this._dropShadowBlur = dropShadowBlur;\n this.styleID++;\n }\n }\n\n /** A fill style to be used on the dropshadow e.g 'red', '#00FF00'. */\n get dropShadowColor(): number | string\n {\n return this._dropShadowColor;\n }\n set dropShadowColor(dropShadowColor: number | string)\n {\n const outputColor = getColor(dropShadowColor);\n if (this._dropShadowColor !== outputColor)\n {\n this._dropShadowColor = outputColor;\n this.styleID++;\n }\n }\n\n /** Set a distance of the drop shadow. */\n get dropShadowDistance(): number\n {\n return this._dropShadowDistance;\n }\n set dropShadowDistance(dropShadowDistance: number)\n {\n if (this._dropShadowDistance !== dropShadowDistance)\n {\n this._dropShadowDistance = dropShadowDistance;\n this.styleID++;\n }\n }\n\n /**\n * A canvas fillstyle that will be used on the text e.g 'red', '#00FF00'.\n *\n * Can be an array to create a gradient eg ['#000000','#FFFFFF']\n * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN}\n *\n * @member {string|string[]|number|number[]|CanvasGradient|CanvasPattern}\n */\n get fill(): TextStyleFill\n {\n return this._fill;\n }\n set fill(fill: TextStyleFill)\n {\n // TODO: Can't have different types for getter and setter. The getter shouldn't have the number type as\n // the setter converts to string. See this thread for more details:\n // https://github.com/microsoft/TypeScript/issues/2521\n // TODO: Not sure if getColor works properly with CanvasGradient and/or CanvasPattern, can't pass in\n // without casting here.\n const outputColor = getColor(fill as any);\n if (this._fill !== outputColor)\n {\n this._fill = outputColor;\n this.styleID++;\n }\n }\n\n /**\n * If fill is an array of colours to create a gradient, this can change the type/direction of the gradient.\n *\n * @see PIXI.TEXT_GRADIENT\n */\n get fillGradientType(): TEXT_GRADIENT\n {\n return this._fillGradientType;\n }\n set fillGradientType(fillGradientType: TEXT_GRADIENT)\n {\n if (this._fillGradientType !== fillGradientType)\n {\n this._fillGradientType = fillGradientType;\n this.styleID++;\n }\n }\n\n /**\n * If fill is an array of colours to create a gradient, this array can set the stop points\n * (numbers between 0 and 1) for the color, overriding the default behaviour of evenly spacing them.\n */\n get fillGradientStops(): number[]\n {\n return this._fillGradientStops;\n }\n set fillGradientStops(fillGradientStops: number[])\n {\n if (!areArraysEqual(this._fillGradientStops,fillGradientStops))\n {\n this._fillGradientStops = fillGradientStops;\n this.styleID++;\n }\n }\n\n /** The font family. */\n get fontFamily(): string | string[]\n {\n return this._fontFamily;\n }\n set fontFamily(fontFamily: string | string[])\n {\n if (this.fontFamily !== fontFamily)\n {\n this._fontFamily = fontFamily;\n this.styleID++;\n }\n }\n\n /**\n * The font size\n * (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em')\n */\n get fontSize(): number | string\n {\n return this._fontSize;\n }\n set fontSize(fontSize: number | string)\n {\n if (this._fontSize !== fontSize)\n {\n this._fontSize = fontSize;\n this.styleID++;\n }\n }\n\n /**\n * The font style\n * ('normal', 'italic' or 'oblique')\n *\n * @member {string}\n */\n get fontStyle(): TextStyleFontStyle\n {\n return this._fontStyle;\n }\n set fontStyle(fontStyle: TextStyleFontStyle)\n {\n if (this._fontStyle !== fontStyle)\n {\n this._fontStyle = fontStyle;\n this.styleID++;\n }\n }\n\n /**\n * The font variant\n * ('normal' or 'small-caps')\n *\n * @member {string}\n */\n get fontVariant(): TextStyleFontVariant\n {\n return this._fontVariant;\n }\n set fontVariant(fontVariant: TextStyleFontVariant)\n {\n if (this._fontVariant !== fontVariant)\n {\n this._fontVariant = fontVariant;\n this.styleID++;\n }\n }\n\n /**\n * The font weight\n * ('normal', 'bold', 'bolder', 'lighter' and '100', '200', '300', '400', '500', '600', '700', 800' or '900')\n *\n * @member {string}\n */\n get fontWeight(): TextStyleFontWeight\n {\n return this._fontWeight;\n }\n set fontWeight(fontWeight: TextStyleFontWeight)\n {\n if (this._fontWeight !== fontWeight)\n {\n this._fontWeight = fontWeight;\n this.styleID++;\n }\n }\n\n /** The amount of spacing between letters, default is 0. */\n get letterSpacing(): number\n {\n return this._letterSpacing;\n }\n set letterSpacing(letterSpacing: number)\n {\n if (this._letterSpacing !== letterSpacing)\n {\n this._letterSpacing = letterSpacing;\n this.styleID++;\n }\n }\n\n /** The line height, a number that represents the vertical space that a letter uses. */\n get lineHeight(): number\n {\n return this._lineHeight;\n }\n set lineHeight(lineHeight: number)\n {\n if (this._lineHeight !== lineHeight)\n {\n this._lineHeight = lineHeight;\n this.styleID++;\n }\n }\n\n /** The space between lines. */\n get leading(): number\n {\n return this._leading;\n }\n set leading(leading: number)\n {\n if (this._leading !== leading)\n {\n this._leading = leading;\n this.styleID++;\n }\n }\n\n /**\n * The lineJoin property sets the type of corner created, it can resolve spiked text issues.\n * Default is 'miter' (creates a sharp corner).\n *\n * @member {string}\n */\n get lineJoin(): TextStyleLineJoin\n {\n return this._lineJoin;\n }\n set lineJoin(lineJoin: TextStyleLineJoin)\n {\n if (this._lineJoin !== lineJoin)\n {\n this._lineJoin = lineJoin;\n this.styleID++;\n }\n }\n\n /**\n * The miter limit to use when using the 'miter' lineJoin mode.\n *\n * This can reduce or increase the spikiness of rendered text.\n */\n get miterLimit(): number\n {\n return this._miterLimit;\n }\n set miterLimit(miterLimit: number)\n {\n if (this._miterLimit !== miterLimit)\n {\n this._miterLimit = miterLimit;\n this.styleID++;\n }\n }\n\n /**\n * Occasionally some fonts are cropped. Adding some padding will prevent this from happening\n * by adding padding to all sides of the text.\n */\n get padding(): number\n {\n return this._padding;\n }\n set padding(padding: number)\n {\n if (this._padding !== padding)\n {\n this._padding = padding;\n this.styleID++;\n }\n }\n\n /**\n * A canvas fillstyle that will be used on the text stroke\n * e.g 'blue', '#FCFF00'\n */\n get stroke(): string | number\n {\n return this._stroke;\n }\n set stroke(stroke: string | number)\n {\n // TODO: Can't have different types for getter and setter. The getter shouldn't have the number type as\n // the setter converts to string. See this thread for more details:\n // https://github.com/microsoft/TypeScript/issues/2521\n const outputColor = getColor(stroke);\n if (this._stroke !== outputColor)\n {\n this._stroke = outputColor;\n this.styleID++;\n }\n }\n\n /**\n * A number that represents the thickness of the stroke.\n *\n * @default 0\n */\n get strokeThickness(): number\n {\n return this._strokeThickness;\n }\n set strokeThickness(strokeThickness: number)\n {\n if (this._strokeThickness !== strokeThickness)\n {\n this._strokeThickness = strokeThickness;\n this.styleID++;\n }\n }\n\n /**\n * The baseline of the text that is rendered.\n *\n * @member {string}\n */\n get textBaseline(): TextStyleTextBaseline\n {\n return this._textBaseline;\n }\n set textBaseline(textBaseline: TextStyleTextBaseline)\n {\n if (this._textBaseline !== textBaseline)\n {\n this._textBaseline = textBaseline;\n this.styleID++;\n }\n }\n\n /** Trim transparent borders. */\n get trim(): boolean\n {\n return this._trim;\n }\n set trim(trim: boolean)\n {\n if (this._trim !== trim)\n {\n this._trim = trim;\n this.styleID++;\n }\n }\n\n /**\n * How newlines and spaces should be handled.\n * Default is 'pre' (preserve, preserve).\n *\n * value | New lines | Spaces\n * --- | --- | ---\n * 'normal' | Collapse | Collapse\n * 'pre' | Preserve | Preserve\n * 'pre-line' | Preserve | Collapse\n *\n * @member {string}\n */\n get whiteSpace(): TextStyleWhiteSpace\n {\n return this._whiteSpace;\n }\n set whiteSpace(whiteSpace: TextStyleWhiteSpace)\n {\n if (this._whiteSpace !== whiteSpace)\n {\n this._whiteSpace = whiteSpace;\n this.styleID++;\n }\n }\n\n /** Indicates if word wrap should be used. */\n get wordWrap(): boolean\n {\n return this._wordWrap;\n }\n set wordWrap(wordWrap: boolean)\n {\n if (this._wordWrap !== wordWrap)\n {\n this._wordWrap = wordWrap;\n this.styleID++;\n }\n }\n\n /** The width at which text will wrap, it needs wordWrap to be set to true. */\n get wordWrapWidth(): number\n {\n return this._wordWrapWidth;\n }\n set wordWrapWidth(wordWrapWidth: number)\n {\n if (this._wordWrapWidth !== wordWrapWidth)\n {\n this._wordWrapWidth = wordWrapWidth;\n this.styleID++;\n }\n }\n\n /**\n * Generates a font style string to use for `TextMetrics.measureFont()`.\n *\n * @return Font style string, for passing to `TextMetrics.measureFont()`\n */\n public toFontString(): string\n {\n // build canvas api font setting from individual components. Convert a numeric this.fontSize to px\n const fontSizeString = (typeof this.fontSize === 'number') ? `${this.fontSize}px` : this.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[] = this.fontFamily;\n\n if (!Array.isArray(this.fontFamily))\n {\n fontFamilies = this.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.indexOf(fontFamily) < 0)\n {\n fontFamily = `\"${fontFamily}\"`;\n }\n (fontFamilies as string[])[i] = fontFamily;\n }\n\n return `${this.fontStyle} ${this.fontVariant} ${this.fontWeight} ${fontSizeString} ${(fontFamilies as string[]).join(',')}`;\n }\n}\n\n/**\n * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string.\n * @private\n * @param color\n * @return The color as a string.\n */\nfunction getSingleColor(color: string|number): string\n{\n if (typeof color === 'number')\n {\n return hex2string(color);\n }\n else if (typeof color === 'string')\n {\n if ( color.indexOf('0x') === 0 )\n {\n color = color.replace('0x', '#');\n }\n }\n\n return color;\n}\n\n/**\n * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string.\n * This version can also convert array of colors\n * @private\n * @param color\n * @return The color as a string.\n */\nfunction getColor(color: (string|number)[]): string[];\nfunction getColor(color: string|number): string;\nfunction getColor(color: string|number|(string|number)[]): string|string[]\n{\n if (!Array.isArray(color))\n {\n return getSingleColor(color);\n }\n else\n {\n for (let i = 0; i < color.length; ++i)\n {\n color[i] = getSingleColor(color[i]);\n }\n\n return color as string[];\n }\n}\n\n/**\n * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string.\n * This version can also convert array of colors\n * @private\n * @param array1 - First array to compare\n * @param array2 - Second array to compare\n * @return Do the arrays contain the same values in the same order\n */\nfunction areArraysEqual<T>(array1: T[], array2: T[]): boolean\n{\n if (!Array.isArray(array1) || !Array.isArray(array2))\n {\n return false;\n }\n\n if (array1.length !== array2.length)\n {\n return false;\n }\n\n for (let i = 0; i < array1.length; ++i)\n {\n if (array1[i] !== array2[i])\n {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Utility function to ensure that object properties are copied by value, and not by reference\n * @private\n * @param target - Target object to copy properties into\n * @param source - Source object for the properties to copy\n * @param propertyObj - Object containing properties names we want to loop over\n */\nfunction deepCopyProperties(target: Record<string, any>, source: Record<string, any>, propertyObj: Record<string, any>): void {\n for (const prop in propertyObj) {\n if (Array.isArray(source[prop])) {\n target[prop] = source[prop].slice();\n } else {\n target[prop] = source[prop];\n }\n }\n}\n","import { settings } from '@pixi/settings';\n\nimport type { TextStyle, TextStyleWhiteSpace } from './TextStyle';\n\ninterface IFontMetrics\n{\n ascent: number;\n descent: number;\n fontSize: number;\n}\n\ntype CharacterWidthCache = { [key: string]: number };\n\n// Default settings used for all getContext calls\nconst contextSettings = {\n // TextMetrics requires getImageData readback for measuring fonts.\n willReadFrequently: true,\n} as CanvasRenderingContext2DSettings;\n\n/**\n * The TextMetrics object represents the measurement of a block of text with a specified style.\n *\n * ```js\n * let style = new PIXI.TextStyle({fontFamily : 'Arial', fontSize: 24, fill : 0xff1010, align : 'center'})\n * let textMetrics = PIXI.TextMetrics.measureText('Your text', style)\n * ```\n * @memberof PIXI\n */\nexport class TextMetrics\n{\n /** The text that was measured. */\n public text: string;\n\n /** The style that was measured. */\n public style: TextStyle;\n\n /** The measured width of the text. */\n public width: number;\n\n /** The measured height of the text. */\n public height: number;\n\n /** An array of lines of the text broken by new lines and wrapping is specified in style. */\n public lines: string[];\n\n /** An array of the line widths for each line matched to `lines`. */\n public lineWidths: number[];\n\n /** The measured line height for this style. */\n public lineHeight: number;\n\n /** The maximum line width for all measured lines. */\n public maxLineWidth: number;\n\n /**\n * The font properties object from TextMetrics.measureFont.\n * @type {PIXI.IFontMetrics}\n */\n public fontProperties: IFontMetrics;\n\n public static METRICS_STRING: string;\n public static BASELINE_SYMBOL: string;\n public static BASELINE_MULTIPLIER: number;\n public static HEIGHT_MULTIPLIER: number;\n\n private static __canvas: HTMLCanvasElement | OffscreenCanvas;\n private static __context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\n\n // TODO: These should be protected but they're initialized outside of the class.\n public static _fonts: { [font: string]: IFontMetrics };\n public static _newlines: number[];\n public static _breakingSpaces: number[];\n\n /**\n * @param text - the text that was measured\n * @param style - the style that was measured\n * @param width - the measured width of the text\n * @param height - the measured height of the text\n * @param lines - an array of the lines of text broken by new lines and wrapping if specified in style\n * @param lineWidths - an array of the line widths for each line matched to `lines`\n * @param lineHeight - the measured line height for this style\n * @param maxLineWidth - the maximum line width for all measured lines\n * @param {PIXI.IFontMetrics} fontProperties - the font properties object from TextMetrics.measureFont\n */\n constructor(text: string, style: TextStyle, width: number, height: number, lines: string[], lineWidths: number[],\n lineHeight: number, maxLineWidth: number, fontProperties: IFontMetrics)\n {\n this.text = text;\n this.style = style;\n this.width = width;\n this.height = height;\n this.lines = lines;\n this.lineWidths = lineWidths;\n this.lineHeight = lineHeight;\n this.maxLineWidth = maxLineWidth;\n this.fontProperties = fontProperties;\n }\n\n /**\n * Measures the supplied string of text and returns a Rectangle.\n * @param text - The text to measure.\n * @param style - The text style to use for measuring\n * @param wordWrap - Override for if word-wrap should be applied to the text.\n * @param canvas - optional specification of the canvas to use for measuring.\n * @returns Measured width and height of the text.\n */\n public static measureText(\n text: string,\n style: TextStyle,\n wordWrap?: boolean,\n canvas: HTMLCanvasElement | OffscreenCanvas = TextMetrics._canvas\n ): TextMetrics\n {\n wordWrap = (wordWrap === undefined || wordWrap === null) ? style.wordWrap : wordWrap;\n const font = style.toFontString();\n const fontProperties = TextMetrics.measureFont(font);\n\n // fallback in case UA disallow canvas data extraction\n // (toDataURI, getImageData functions)\n if (fontProperties.fontSize === 0)\n {\n fontProperties.fontSize = style.fontSize as number;\n fontProperties.ascent = style.fontSize as number;\n }\n\n const context = canvas.getContext('2d', contextSettings);\n\n context.font = font;\n\n const outputText = wordWrap ? TextMetrics.wordWrap(text, style, canvas) : text;\n const lines = outputText.split(/(?:\\r\\n|\\r|\\n)/);\n const lineWidths = new Array<number>(lines.length);\n let maxLineWidth = 0;\n\n for (let i = 0; i < lines.length; i++)\n {\n const lineWidth = context.measureText(lines[i]).width + ((lines[i].length - 1) * style.letterSpacing);\n\n lineWidths[i] = lineWidth;\n maxLineWidth = Math.max(maxLineWidth, lineWidth);\n }\n let width = maxLineWidth + style.strokeThickness;\n\n if (style.dropShadow)\n {\n width += style.dropShadowDistance;\n }\n\n const lineHeight = style.lineHeight || fontProperties.fontSize + style.strokeThickness;\n let height = Math.max(lineHeight, fontProperties.fontSize + style.strokeThickness)\n + ((lines.length - 1) * (lineHeight + style.leading));\n\n if (style.dropShadow)\n {\n height += style.dropShadowDistance;\n }\n\n return new TextMetrics(\n text,\n style,\n width,\n height,\n lines,\n lineWidths,\n lineHeight + style.leading,\n maxLineWidth,\n fontProperties\n );\n }\n\n /**\n * Applies newlines to a string to have it optimally fit into the horizontal\n * bounds set by the Text object's wordWrapWidth property.\n * @param text - String to apply word wrapping to\n * @param style - the style to use when wrapping\n * @param canvas - optional specification of the canvas to use for measuring.\n * @returns New string with new lines applied where required\n */\n private static wordWrap(\n text: string,\n style: TextStyle,\n canvas: HTMLCanvasElement | OffscreenCanvas = TextMetrics._canvas\n ): string\n {\n const context = canvas.getContext('2d', contextSettings);\n\n let width = 0;\n let line = '';\n let lines = '';\n\n const cache: CharacterWidthCache = Object.create(null);\n const { letterSpacing, whiteSpace } = style;\n\n // How to handle whitespaces\n const collapseSpaces = TextMetrics.collapseSpaces(whiteSpace);\n const collapseNewlines = TextMetrics.collapseNewlines(whiteSpace);\n\n // whether or not spaces may be added to the beginning of lines\n let canPrependSpaces = !collapseSpaces;\n\n // There is letterSpacing after every char except the last one\n // t_h_i_s_' '_i_s_' '_a_n_' '_e_x_a_m_p_l_e_' '_!\n // so for convenience the above needs to be compared to width + 1 extra letterSpace\n // t_h_i_s_' '_i_s_' '_a_n_' '_e_x_a_m_p_l_e_' '_!_\n // ________________________________________________\n // And then the final space is simply no appended to each line\n const wordWrapWidth = style.wordWrapWidth + letterSpacing;\n\n // break text into words, spaces and newline chars\n const tokens = TextMetrics.tokenize(text);\n\n for (let i = 0; i < tokens.length; i++)\n {\n // get the word, space or newlineChar\n let token = tokens[i];\n\n // if word is a new line\n if (TextMetrics.isNewline(token))\n {\n // keep the new line\n if (!collapseNewlines)\n {\n lines += TextMetrics.addLine(line);\n canPrependSpaces = !collapseSpaces;\n line = '';\n width = 0;\n continue;\n }\n\n // if we should collapse new lines\n // we simply convert it into a space\n token = ' ';\n }\n\n // if we should collapse repeated whitespaces\n if (collapseSpaces)\n {\n // check both this and the last tokens for spaces\n const currIsBreakingSpace = TextMetrics.isBreakingSpace(token);\n const lastIsBreakingSpace = TextMetrics.isBreakingSpace(line[line.length - 1]);\n\n if (currIsBreakingSpace && lastIsBreakingSpace)\n {\n continue;\n }\n }\n\n // get word width from cache if possible\n const tokenWidth = TextMetrics.getFromCache(token, letterSpacing, cache, context);\n\n // word is longer than desired bounds\n if (tokenWidth > wordWrapWidth)\n {\n // if we are not already at the beginning of a line\n if (line !== '')\n {\n // start newlines for overflow words\n lines += TextMetrics.addLine(line);\n line = '';\n width = 0;\n }\n\n // break large word over multiple lines\n if (TextMetrics.canBreakWords(token, style.breakWords))\n {\n // break word into characters\n const characters = TextMetrics.wordWrapSplit(token);\n\n // loop the characters\n for (let j = 0; j < characters.length; j++)\n {\n let char = characters[j];\n\n let k = 1;\n // we are not at the end of the token\n\n while (characters[j + k])\n {\n const nextChar = characters[j + k];\n const lastChar = char[char.length - 1];\n\n // should not split chars\n if (!TextMetrics.canBreakChars(lastChar, nextChar, token, j, style.breakWords))\n {\n // combine chars & move forward one\n char += nextChar;\n }\n else\n {\n break;\n }\n\n k++;\n }\n\n j += char.length - 1;\n\n const characterWidth = TextMetrics.getFromCache(char, letterSpacing, cache, context);\n\n if (characterWidth + width > wordWrapWidth)\n {\n lines += TextMetrics.addLine(line);\n canPrependSpaces = false;\n line = '';\n width = 0;\n }\n\n line += char;\n width += characterWidth;\n }\n }\n\n // run word out of the bounds\n else\n {\n // if there are words in this line already\n // finish that line and start a new one\n if (line.length > 0)\n {\n lines += TextMetrics.addLine(line);\n line = '';\n width = 0;\n }\n\n const isLastToken = i === tokens.length - 1;\n\n // give it its own line if it's not the end\n lines += TextMetrics.addLine(token, !isLastToken);\n canPrependSpaces = false;\n line = '';\n width = 0;\n }\n }\n\n // word could fit\n else\n {\n // word won't fit because of existing words\n // start a new line\n if (tokenWidth + width > wordWrapWidth)\n {\n // if its a space we don't want it\n canPrependSpaces = false;\n\n // add a new line\n lines += TextMetrics.addLine(line);\n\n // start a new line\n line = '';\n width = 0;\n }\n\n // don't add spaces to the beginning of lines\n if (line.length > 0 || !TextMetrics.isBreakingSpace(token) || canPrependSpaces)\n {\n // add the word to the current line\n line += token;\n\n // update width counter\n width += tokenWidth;\n }\n }\n }\n\n lines += TextMetrics.addLine(line, false);\n\n return lines;\n }\n\n /**\n * Convienience function for logging each line added during the wordWrap method.\n * @param line - The line of text to add\n * @param newLine - Add new line character to end\n * @returns A formatted line\n */\n private static addLine(line: string, newLine = true): string\n {\n line = TextMetrics.trimRight(line);\n\n line = (newLine) ? `${line}\\n` : line;\n\n return line;\n }\n\n /**\n * Gets & sets the widths of calculated characters in a cache object\n * @param key - The key\n * @param letterSpacing - The letter spacing\n * @param cache - The cache\n * @param context - The canvas context\n * @returns The from cache.\n */\n private static getFromCache(key: string, letterSpacing: number, cache: CharacterWidthCache,\n context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D): number\n {\n let width = cache[key];\n\n if (typeof width !== 'number')\n {\n const spacing = ((key.length) * letterSpacing);\n\n width = context.measureText(key).width + spacing;\n cache[key] = width;\n }\n\n return width;\n }\n\n /**\n * Determines whether we should collapse breaking spaces.\n * @param whiteSpace - The TextStyle property whiteSpace\n * @returns Should collapse\n */\n private static collapseSpaces(whiteSpace: TextStyleWhiteSpace): boolean\n {\n return (whiteSpace === 'normal' || whiteSpace === 'pre-line');\n }\n\n /**\n * Determines whether we should collapse newLine chars.\n * @param whiteSpace - The white space\n * @returns should collapse\n */\n private static collapseNewlines(whiteSpace: TextStyleWhiteSpace): boolean\n {\n return (whiteSpace === 'normal');\n }\n\n /**\n * Trims breaking whitespaces from string.\n * @param text - The text\n * @returns Trimmed string\n */\n private static trimRight(text: string): string\n {\n if (typeof text !== 'string')\n {\n return '';\n }\n\n for (let i = text.length - 1; i >= 0; i--)\n {\n const char = text[i];\n\n if (!TextMetrics.isBreakingSpace(char))\n {\n break;\n }\n\n text = text.slice(0, -1);\n }\n\n return text;\n }\n\n /**\n * Determines if char is a newline.\n * @param char - The character\n * @returns True if newline, False otherwise.\n */\n private static isNewline(char: string): boolean\n {\n if (typeof char !== 'string')\n {\n return false;\n }\n\n return (TextMetrics._newlines.indexOf(char.charCodeAt(0)) >= 0);\n }\n\n /**\n * Determines if char is a breaking whitespace.\n *\n * It allows one to determine whether char should be a breaking whitespace\n * For example certain characters in CJK langs or numbers.\n * It must return a boolean.\n * @param char - The character\n * @param [_nextChar] - The next character\n * @returns True if whitespace, False otherwise.\n */\n static isBreakingSpace(char: string, _nextChar?: string): boolean\n {\n if (typeof char !== 'string')\n {\n return false;\n }\n\n return (TextMetrics._breakingSpaces.indexOf(char.charCodeAt(0)) >= 0);\n }\n\n /**\n * Splits a string into words, breaking-spaces and newLine characters\n * @param text - The text\n * @returns A tokenized array\n */\n private static tokenize(text: string): string[]\n {\n const tokens: string[] = [];\n let token = '';\n\n if (typeof text !== 'string')\n {\n return tokens;\n }\n\n for (let i = 0; i < text.length; i++)\n {\n const char = text[i];\n const nextChar = text[i + 1];\n\n if (TextMetrics.isBreakingSpace(char, nextChar) || TextMetrics.isNewline(char))\n {\n if (token !== '')\n {\n tokens.push(token);\n token = '';\n }\n\n tokens.push(char);\n\n continue;\n }\n\n token += char;\n }\n\n if (token !== '')\n {\n tokens.push(token);\n }\n\n return tokens;\n }\n\n /**\n * Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.\n *\n * It allows one to customise which words should break\n * Examples are if the token is CJK or numbers.\n * It must return a boolean.\n * @param _token - The token\n * @param breakWords - The style attr break words\n * @returns Whether to break word or not\n */\n static canBreakWords(_token: string, breakWords: boolean): boolean\n {\n return breakWords;\n }\n\n /**\n * Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.\n *\n * It allows one to determine whether a pair of characters\n * should be broken by newlines\n * For example certain characters in CJK langs or numbers.\n * It must return a boolean.\n * @param _char - The character\n * @param _nextChar - The next character\n * @param _token - The token/word the characters are from\n * @param _index - The index in the token of the char\n * @param _breakWords - The style attr break words\n * @returns whether to break word or not\n */\n static canBreakChars(_char: string, _nextChar: string, _token: string, _index: number,\n _breakWords: boolean): boolean\n {\n return true;\n }\n\n /**\n * Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.\n *\n * It is called when a token (usually a word) has to be split into separate pieces\n * in order to determine the point to break a word.\n * It must return an array of characters.\n * @example\n * // Correctly splits emojis, eg \"🤪🤪\" will result in two element array, each with one emoji.\n * TextMetrics.wordWrapSplit = (token) => [...token];\n * @param token - The token to split\n * @returns The characters of the token\n */\n static wordWrapSplit(token: string): string[]\n {\n return token.split('');\n }\n\n /**\n * Calculates the ascent, descent and fontSize of a given font-style\n * @param font - String representing the style of the font\n * @returns Font properties object\n */\n public static measureFont(font: string): IFontMetrics\n {\n // as this method is used for preparing assets, don't recalculate things if we don't need to\n if (TextMetrics._fonts[font])\n {\n return TextMetrics._fonts[font];\n }\n\n const properties: IFontMetrics = {\n ascent: 0,\n descent: 0,\n fontSize: 0,\n };\n\n const canvas = TextMetrics._canvas;\n const context = TextMetrics._context;\n\n context.font = font;\n\n const metricsString = TextMetrics.METRICS_STRING + TextMetrics.BASELINE_SYMBOL;\n const width = Math.ceil(context.measureText(metricsString).width);\n let baseline = Math.ceil(context.measureText(TextMetrics.BASELINE_SYMBOL).width);\n const height = Math.ceil(TextMetrics.HEIGHT_MULTIPLIER * baseline);\n\n baseline = baseline * TextMetrics.BASELINE_MULTIPLIER | 0;\n\n canvas.width = width;\n canvas.height = height;\n\n context.fillStyle = '#f00';\n context.fillRect(0, 0, width, height);\n\n context.font = font;\n\n context.textBaseline = 'alphabetic';\n context.fillStyle = '#000';\n context.fillText(metricsString, 0, baseline);\n\n const imagedata = context.getImageData(0, 0, width, height).data;\n const pixels = imagedata.length;\n const line = width * 4;\n\n let i = 0;\n let idx = 0;\n let stop = false;\n\n // ascent. scan from top to bottom until we find a non red pixel\n for (i = 0; i < baseline; ++i)\n {\n for (let j = 0; j < line; j += 4)\n {\n if (imagedata[idx + j] !== 255)\n {\n stop = true;\n break;\n }\n }\n if (!stop)\n {\n idx += line;\n }\n else\n {\n break;\n }\n }\n\n properties.ascent = baseline - i;\n\n idx = pixels - line;\n stop = false;\n\n // descent. scan from bottom to top until we find a non red pixel\n for (i = height; i > baseline; --i)\n {\n for (let j = 0; j < line; j += 4)\n {\n if (imagedata[idx + j] !== 255)\n {\n stop = true;\n break;\n }\n }\n\n if (!stop)\n {\n idx -= line;\n }\n else\n {\n break;\n }\n }\n\n properties.descent = i - baseline;\n properties.fontSize = properties.ascent + properties.descent;\n\n TextMetrics._fonts[font] = properties;\n\n return properties;\n }\n\n /**\n * Clear font metrics in metrics cache.\n * @param {string} [font] - font name. If font name not set then clear cache for all fonts.\n */\n public static clearMetrics(font = ''): void\n {\n if (font)\n {\n delete TextMetrics._fonts[font];\n }\n else\n {\n TextMetrics._fonts = {};\n }\n }\n\n /**\n * Cached canvas element for measuring text\n * TODO: this should be private, but isn't because of backward compat, will fix later.\n * @ignore\n */\n public static get _canvas(): HTMLCanvasElement | OffscreenCanvas\n {\n if (!TextMetrics.__canvas)\n {\n let canvas: HTMLCanvasElement | OffscreenCanvas;\n\n try\n {\n // OffscreenCanvas2D measureText can be up to 40% faster.\n const c = new OffscreenCanvas(0, 0);\n const context = c.getContext('2d', contextSettings);\n\n if (context && context.measureText)\n {\n TextMetrics.__canvas = c;\n\n return c;\n }\n\n canvas = settings.ADAPTER.createCanvas();\n }\n catch (ex)\n {\n canvas = settings.ADAPTER.createCanvas();\n }\n canvas.width = canvas.height = 10;\n TextMetrics.__canvas = canvas;\n }\n\n return TextMetrics.__canvas;\n }\n\n /**\n * TODO: this should be private, but isn't because of backward compat, will fix later.\n * @ignore\n */\n public static get _context(): CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D\n {\n if (!TextMetrics.__context)\n {\n TextMetrics.__context = TextMetrics._canvas.getContext('2d', contextSettings);\n }\n\n return TextMetrics.__context;\n }\n}\n\n/**\n * Internal return object for {@link PIXI.TextMetrics.measureFont `TextMetrics.measureFont`}.\n * @typedef {object} FontMetrics\n * @property {number} ascent - The ascent distance\n * @property {number} descent - The descent distance\n * @property {number} fontSize - Font size from ascent to descent\n * @memberof PIXI.TextMetrics\n * @private\n */\n\n/**\n * Cache of {@see PIXI.TextMetrics.FontMetrics} objects.\n * @memberof PIXI.TextMetrics\n * @type {object}\n * @private\n */\nTextMetrics._fonts = {};\n\n/**\n * String used for calculate font metrics.\n * These characters are all tall to help calculate the height required for text.\n * @static\n * @memberof PIXI.TextMetrics\n * @name METRICS_STRING\n * @type {string}\n * @default |ÉqÅ\n */\nTextMetrics.METRICS_STRING = '|ÉqÅ';\n\n/**\n * Baseline symbol for calculate font metrics.\n * @static\n * @memberof PIXI.TextMetrics\n * @name BASELINE_SYMBOL\n * @type {string}\n * @default M\n */\nTextMetrics.BASELINE_SYMBOL = 'M';\n\n/**\n * Baseline multiplier for calculate font metrics.\n * @static\n * @memberof PIXI.TextMetrics\n * @name BASELINE_MULTIPLIER\n * @type {number}\n * @default 1.4\n */\nTextMetrics.BASELINE_MULTIPLIER = 1.4;\n\n/**\n * Height multiplier for setting height of canvas to calculate font metrics.\n * @static\n * @memberof PIXI.TextMetrics\n * @name HEIGHT_MULTIPLIER\n * @type {number}\n * @default 2.00\n */\nTextMetrics.HEIGHT_MULTIPLIER = 2.0;\n\n/**\n * Cache of new line chars.\n * @memberof PIXI.TextMetrics\n * @type {number[]}\n * @private\n */\nTextMetrics._newlines = [\n 0x000A, // line feed\n 0x000D, // carriage return\n];\n\n/**\n * Cache of breaking spaces.\n * @memberof PIXI.TextMetrics\n * @type {number[]}\n * @private\n */\nTextMetrics._breakingSpaces = [\n 0x0009, // character tabulation\n 0x0020, // space\n 0x2000, // en quad\n 0x2001, // em quad\n 0x2002, // en space\n 0x2003, // em space\n 0x2004, // three-per-em space\n 0x2005, // four-per-em space\n 0x2006, // six-per-em space\n 0x2008, // punctuation space\n 0x2009, // thin space\n 0x200A, // hair space\n 0x205F, // medium mathematical space\n 0x3000, // ideographic space\n];\n\n/**\n * A number, or a string containing a number.\n * @memberof PIXI\n * @typedef {object} IFontMetrics\n * @property {number} ascent - Font ascent\n * @property {number} descent - Font descent\n * @property {number} fontSize - Font size\n */\n","/* eslint max-depth: [2, 8] */\nimport { Sprite } from '@pixi/sprite';\nimport { Texture } from '@pixi/core';\nimport { settings } from '@pixi/settings';\nimport { Rectangle } from '@pixi/math';\nimport { sign, trimCanvas, hex2rgb, string2hex } from '@pixi/utils';\nimport { TEXT_GRADIENT } from './const';\nimport { TextStyle } from './TextStyle';\nimport { TextMetrics } from './TextMetrics';\n\nimport type { IDestroyOptions } from '@pixi/display';\nimport type { Renderer } from '@pixi/core';\nimport type { ITextStyle } from './TextStyle';\n\nconst defaultDestroyOptions: IDestroyOptions = {\n texture: true,\n children: false,\n baseTexture: true,\n};\n\ninterface ModernContext2D extends CanvasRenderingContext2D\n{\n // for chrome less 94\n textLetterSpacing?: number;\n // for chrome greater 94\n letterSpacing?: number;\n}\n\n/**\n * A Text Object will create a line or multiple lines of text.\n *\n * The text is created using the [Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API).\n *\n * The primary advantage of this class over BitmapText is that you have great control over the style of the text,\n * which you can change at runtime.\n *\n * The primary disadvantages is that each piece of text has it's own texture, which can use more memory.\n * When text changes, this texture has to be re-generated and re-uploaded to the GPU, taking up time.\n *\n * To split a line you can use '\\n' in your text string, or, on the `style` object,\n * change its `wordWrap` property to true and and give the `wordWrapWidth` property a value.\n *\n * A Text can be created directly from a string and a style object,\n * which can be generated [here](https://pixijs.io/pixi-text-style).\n *\n * ```js\n * let text = new PIXI.Text('This is a PixiJS text',{fontFamily : 'Arial', fontSize: 24, fill : 0xff1010, align : 'center'});\n * ```\n * @memberof PIXI\n */\nexport class Text extends Sprite\n{\n /**\n * New behavior for `lineHeight` that's meant to mimic HTML text. A value of `true` will\n * make sure the first baseline is offset by the `lineHeight` value if it is greater than `fontSize`.\n * A value of `false` will use the legacy behavior and not change the baseline of the first line.\n * In the next major release, we'll enable this by default.\n */\n public static nextLineHeightBehavior = false;\n\n /**\n * New rendering behavior for letter-spacing which uses Chrome's new native API. This will\n * lead to more accurate letter-spacing results because it does not try to manually draw\n * each character. However, this Chrome API is experimental and may not serve all cases yet.\n */\n public static experimentalLetterSpacing = false;\n\n /** The canvas element that everything is drawn to. */\n public canvas: HTMLCanvasElement;\n /** The canvas 2d context that everything is drawn with. */\n public context: ModernContext2D;\n public localStyleID: number;\n public dirty: boolean;\n\n /**\n * The resolution / device pixel ratio of the canvas.\n *\n * This is set to automatically match the renderer resolution by default, but can be overridden by setting manually.\n * @default PIXI.settings.RESOLUTION\n */\n _resolution: number;\n _autoResolution: boolean;\n\n /**\n * Private tracker for the current text.\n * @private\n */\n protected _text: string;\n\n /**\n * Private tracker for the current font.\n * @private\n */\n protected _font: string;\n\n /**\n * Private tracker for the current style.\n * @private\n */\n protected _style: TextStyle;\n\n /**\n * Private listener to track style changes.\n * @private\n */\n protected _styleListener: () => void;\n\n /**\n * Keep track if this Text object created it's own canvas\n * element (`true`) or uses the constructor argument (`false`).\n * Used to workaround a GC issues with Safari < 13 when\n * destroying Text. See `destroy` for more info.\n */\n private _ownCanvas: boolean;\n\n /**\n * @param text - The string that you would like the text to display\n * @param {object|PIXI.TextStyle} [style] - The style parameters\n * @param canvas - The canvas element for drawing text\n */\n constructor(text?: string | number, style?: Partial<ITextStyle> | TextStyle, canvas?: HTMLCanvasElement)\n {\n let ownCanvas = false;\n\n if (!canvas)\n {\n canvas = settings.ADAPTER.createCanvas();\n ownCanvas = true;\n }\n\n canvas.width = 3;\n canvas.height = 3;\n\n const texture = Texture.from(canvas);\n\n texture.orig = new Rectangle();\n texture.trim = new Rectangle();\n\n super(texture);\n\n this._ownCanvas = ownCanvas;\n this.canvas = canvas;\n this.context = canvas.getContext('2d', {\n // required for trimming to work without warnings\n willReadFrequently: true,\n }) as CanvasRenderingContext2D;\n\n this._resolution = settings.RESOLUTION;\n this._autoResolution = true;\n this._text = null;\n this._style = null;\n this._styleListener = null;\n this._font = '';\n\n this.text = text;\n this.style = style;\n\n this.localStyleID = -1;\n }\n\n /**\n * Renders text to its canvas, and updates its texture.\n *\n * By default this is used internally to ensure the texture is correct before rendering,\n * but it can be used called externally, for example from this class to 'pre-generate' the texture from a piece of text,\n * and then shared across multiple Sprites.\n * @param respectDirty - Whether to abort updating the text if the Text isn't dirty and the function is called.\n */\n public updateText(respectDirty: boolean): void\n {\n const style = this._style;\n\n // check if style has changed..\n if (this.localStyleID !== style.styleID)\n {\n this.dirty = true;\n this.localStyleID = style.styleID;\n }\n\n if (!this.dirty && respectDirty)\n {\n return;\n }\n\n this._font = this._style.toFontString();\n\n const context = this.context;\n const measured = TextMetrics.measureText(this._text || ' ', this._style, this._style.wordWrap, this.canvas);\n const width = measured.width;\n const height = measured.height;\n const lines = measured.lines;\n const lineHeight = measured.lineHeight;\n const lineWidths = measured.lineWidths;\n const maxLineWidth = measured.maxLineWidth;\n const fontProperties = measured.fontProperties;\n\n this.canvas.width = Math.ceil(Math.ceil((Math.max(1, width) + (style.padding * 2))) * this._resolution);\n this.canvas.height = Math.ceil(Math.ceil((Math.max(1, height) + (style.padding * 2))) * this._resolution);\n\n context.scale(this._resolution, this._resolution);\n\n context.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n context.font = this._font;\n context.lineWidth = style.strokeThickness;\n context.textBaseline = style.textBaseline;\n context.lineJoin = style.lineJoin;\n context.miterLimit = style.miterLimit;\n\n let linePositionX: number;\n let linePositionY: number;\n\n // require 2 passes if a shadow; the first to draw the drop shadow, the second to draw the text\n const passesCount = style.dropShadow ? 2 : 1;\n\n // For v4, we drew text at the colours of the drop shadow underneath the normal text. This gave the correct zIndex,\n // but features such as alpha and shadowblur did not look right at all, since we were using actual text as a shadow.\n //\n // For v5.0.0, we moved over to just use the canvas API for drop shadows, which made them look much nicer and more\n // visually please, but now because the stroke is drawn and then the fill, drop shadows would appear on both the fill\n // and the stroke; and fill drop shadows would appear over the top of the stroke.\n //\n // For v5.1.1, the new route is to revert to v4 style of drawing text first to get the drop shadows underneath normal\n // text, but instead drawing text in the correct location, we'll draw it off screen (-paddingY), and then adjust the\n // drop shadow so only that appears on screen (+paddingY). Now we'll have the correct draw order of the shadow\n // beneath the text, whilst also having the proper text shadow styling.\n for (let i = 0; i < passesCount; ++i)\n {\n const isShadowPass = style.dropShadow && i === 0;\n // we only want the drop shadow, so put text way off-screen\n const dsOffsetText = isShadowPass ? Math.ceil(Math.max(1, height) + (style.padding * 2)) : 0;\n const dsOffsetShadow = dsOffsetText * this._resolution;\n\n if (isShadowPass)\n {\n // On Safari, text with gradient and drop shadows together do not position correctly\n // if the scale of the canvas is not 1: https://bugs.webkit.org/show_bug.cgi?id=197689\n // Therefore we'll set the styles to be a plain black whilst generating this drop shadow\n context.fillStyle = 'black';\n context.strokeStyle = 'black';\n\n const dropShadowColor = style.dropShadowColor;\n const rgb = hex2rgb(typeof dropShadowColor === 'number' ? dropShadowColor : string2hex(dropShadowColor));\n const dropShadowBlur = style.dropShadowBlur * this._resolution;\n const dropShadowDistance = style.dropShadowDistance * this._resolution;\n\n context.shadowColor = `rgba(${rgb[0] * 255},${rgb[1] * 255},${rgb[2] * 255},${style.dropShadowAlpha})`;\n context.shadowBlur = dropShadowBlur;\n context.shadowOffsetX = Math.cos(style.dropShadowAngle) * dropShadowDistance;\n context.shadowOffsetY = (Math.sin(style.dropShadowAngle) * dropShadowDistance) + dsOffsetShadow;\n }\n else\n {\n // set canvas text styles\n context.fillStyle = this._generateFillStyle(style, lines, measured);\n // TODO: Can't have different types for getter and setter. The getter shouldn't have the number type as\n // the setter converts to string. See this thread for more details:\n // https://github.com/microsoft/TypeScript/issues/2521\n context.strokeStyle = style.stroke as string;\n\n context.shadowColor = 'black';\n context.shadowBlur = 0;\n context.shadowOffsetX = 0;\n context.shadowOffsetY = 0;\n }\n\n let linePositionYShift = (lineHeight - fontProperties.fontSize) / 2;\n\n if (!Text.nextLineHeightBehavior || lineHeight - fontProperties.fontSize < 0)\n {\n linePositionYShift = 0;\n }\n\n // draw lines line by line\n for (let i = 0; i < lines.length; i++)\n {\n linePositionX = style.strokeThickness / 2;\n linePositionY = ((style.strokeThickness / 2) + (i * lineHeight)) + fontProperties.ascent\n + linePositionYShift;\n\n if (style.align === 'right')\n {\n linePositionX += maxLineWidth - lineWidths[i];\n }\n else if (style.align === 'center')\n {\n linePositionX += (maxLineWidth - lineWidths[i]) / 2;\n }\n\n if (style.stroke && style.strokeThickness)\n {\n this.drawLetterSpacing(\n lines[i],\n linePositionX + style.padding,\n linePositionY + style.padding - dsOffsetText,\n true\n );\n }\n\n if (style.fill)\n {\n this.drawLetterSpacing(\n lines[i],\n linePositionX + style.padding,\n linePositionY + style.padding - dsOffsetText\n );\n }\n }\n }\n\n this.updateTexture();\n }\n\n /**\n * Render the text with letter-spacing.\n * @param text - The text to draw\n * @param x - Horizontal position to draw the text\n * @param y - Vertical position to draw the text\n * @param isStroke - Is this drawing for the outside stroke of the\n * text? If not, it's for the inside fill\n */\n private drawLetterSpacing(text: string, x: number, y: number, isStroke = false): void\n {\n const style = this._style;\n\n // letterSpacing of 0 means normal\n const letterSpacing = style.letterSpacing;\n\n // Checking that we can use moddern canvas2D api\n // https://developer.chrome.com/origintrials/#/view_trial/3585991203293757441\n // note: this is unstable API, Chrome less 94 use a `textLetterSpacing`, newest use a letterSpacing\n // eslint-disable-next-line max-len\n const supportLetterSpacing = Text.experimentalLetterSpacing\n && ('letterSpacing' in CanvasRenderingContext2D.prototype\n || 'textLetterSpacing' in CanvasRenderingContext2D.prototype);\n\n if (letterSpacing === 0 || supportLetterSpacing)\n {\n if (supportLetterSpacing)\n {\n this.context.letterSpacing = letterSpacing;\n this.context.textLetterSpacing = letterSpacing;\n }\n\n if (isStroke)\n {\n this.context.strokeText(text, x, y);\n }\n else\n {\n this.context.fillText(text, x, y);\n }\n\n return;\n }\n\n let currentPosition = x;\n\n // Using Array.from correctly splits characters whilst keeping emoji together.\n // This is not supported on IE as it requires ES6, so regular text splitting occurs.\n // This also doesn't account for emoji that are multiple emoji put together to make something else.\n // Handling all of this would require a big library itself.\n // https://medium.com/@giltayar/iterating-over-emoji-characters-the-es6-way-f06e4589516\n // https://github.com/orling/grapheme-splitter\n const stringArray = Array.from ? Array.from(text) : text.split('');\n let previousWidth = this.context.measureText(text).width;\n let currentWidth = 0;\n\n for (let i = 0; i < stringArray.length; ++i)\n {\n const currentChar = stringArray[i];\n\n if (isStroke)\n {\n this.context.strokeText(currentChar, currentPosition, y);\n }\n else\n {\n this.context.fillText(currentChar, currentPosition, y);\n }\n let textStr = '';\n\n for (let j = i + 1; j < stringArray.length; ++j)\n {\n textStr += stringArray[j];\n }\n currentWidth = this.context.measureText(textStr).width;\n currentPosition += previousWidth - currentWidth + letterSpacing;\n previousWidth = currentWidth;\n }\n }\n\n /** Updates texture size based on canvas size. */\n private updateTexture(): void\n {\n const canvas = this.canvas;\n\n if (this._style.trim)\n {\n const trimmed = trimCanvas(canvas);\n\n if (trimmed.data)\n {\n canvas.width = trimmed.width;\n canvas.height = trimmed.height;\n this.context.putImageData(trimmed.data, 0, 0);\n }\n }\n\n const texture = this._texture;\n const style = this._style;\n const padding = style.trim ? 0 : style.padding;\n const baseTexture = texture.baseTexture;\n\n texture.trim.width = texture._frame.width = canvas.width / this._resolution;\n texture.trim.height = texture._frame.height = canvas.height / this._resolution;\n texture.trim.x = -padding;\n texture.trim.y = -padding;\n\n texture.orig.width = texture._frame.width - (padding * 2);\n texture.orig.height = texture._frame.height - (padding * 2);\n\n // call sprite onTextureUpdate to update scale if _width or _height were set\n this._onTextureUpdate();\n\n baseTexture.setRealSize(canvas.width, canvas.height, this._resolution);\n\n texture.updateUvs();\n\n this.dirty = false;\n }\n\n /**\n * Renders the object using the WebGL renderer\n * @param renderer - The renderer\n */\n protected _render(renderer: Renderer): void\n {\n if (this._autoResolution && this._resolution !== renderer.resolution)\n {\n this._resolution = renderer.resolution;\n this.dirty = true;\n }\n\n this.updateText(true);\n\n super._render(renderer);\n }\n\n /** Updates the transform on all children of this container for rendering. */\n public updateTransform(): void\n {\n this.updateText(true);\n\n super.updateTransform();\n }\n\n public getBounds(skipUpdate?: boolean, rect?: Rectangle): Rectangle\n {\n this.updateText(true);\n\n if (this._textureID === -1)\n {\n // texture was updated: recalculate transforms\n skipUpdate = false;\n }\n\n return super.getBounds(skipUpdate, rect);\n }\n\n /**\n * Gets the local bounds of the text object.\n * @param rect - The output rectangle.\n * @returns The bounds.\n */\n public getLocalBounds(rect?: Rectangle): Rectangle\n {\n this.updateText(true);\n\n return super.getLocalBounds.call(this, rect);\n }\n\n /** Calculates the bounds of the Text as a rectangle. The bounds calculation takes the worldTransform into account. */\n protected _calculateBounds(): void\n {\n this.calculateVertices();\n // if we have already done this on THIS frame.\n this._bounds.addQuad(this.vertexData);\n }\n\n /**\n * Generates the fill style. Can automatically generate a gradient based on the fill style being an array\n * @param style - The style.\n * @param lines - The lines of text.\n * @param metrics\n * @returns The fill style\n */\n private _generateFillStyle(\n style: TextStyle, lines: string[], metrics: TextMetrics\n ): string | CanvasGradient | CanvasPattern\n {\n // TODO: Can't have different types for getter and setter. The getter shouldn't have the number type as\n // the setter converts to string. See this thread for more details:\n // https://github.com/microsoft/TypeScript/issues/2521\n const fillStyle: string | string[] | CanvasGradient | CanvasPattern = style.fill as any;\n\n if (!Array.isArray(fillStyle))\n {\n return fillStyle;\n }\n else if (fillStyle.length === 1)\n {\n return fillStyle[0];\n }\n\n // the gradient will be evenly spaced out according to how large the array is.\n // ['#FF0000', '#00FF00', '#0000FF'] would created stops at 0.25, 0.5 and 0.75\n let gradient: string[] | CanvasGradient;\n\n // a dropshadow will enlarge the canvas and result in the gradient being\n // generated with the incorrect dimensions\n const dropShadowCorrection = (style.dropShadow) ? style.dropShadowDistance : 0;\n\n // should also take padding into account, padding can offset the gradient\n const padding = style.padding || 0;\n\n const width = (this.canvas.width / this._resolution) - dropShadowCorrection - (padding * 2);\n const height = (this.canvas.height / this._resolution) - dropShadowCorrection - (padding * 2);\n\n // make a copy of the style settings, so we can manipulate them later\n const fill = fillStyle.slice();\n const fillGradientStops = style.fillGradientStops.slice();\n\n // wanting to evenly distribute the fills. So an array of 4 colours should give fills of 0.25, 0.5 and 0.75\n if (!fillGradientStops.length)\n {\n const lengthPlus1 = fill.length + 1;\n\n for (let i = 1; i < lengthPlus1; ++i)\n {\n fillGradientStops.push(i / lengthPlus1);\n }\n }\n\n // stop the bleeding of the last gradient on the line above to the top gradient of the this line\n // by hard defining the first gradient colour at point 0, and last gradient colour at point 1\n fill.unshift(fillStyle[0]);\n fillGradientStops.unshift(0);\n\n fill.push(fillStyle[fillStyle.length - 1]);\n fillGradientStops.push(1);\n\n if (style.fillGradientType === TEXT_GRADIENT.LINEAR_VERTICAL)\n {\n // start the gradient at the top center of the canvas, and end at the bottom middle of the canvas\n gradient = this.context.createLinearGradient(width / 2, padding, width / 2, height + padding);\n\n // we need to repeat the gradient so that each individual line of text has the same vertical gradient effect\n // ['#FF0000', '#00FF00', '#0000FF'] over 2 lines would create stops at 0.125, 0.25, 0.375, 0.625, 0.75, 0.875\n\n // Actual height of the text itself, not counting spacing for lineHeight/leading/dropShadow etc\n const textHeight = metrics.fontProperties.fontSize + style.strokeThickness;\n\n for (let i = 0; i < lines.length; i++)\n {\n const lastLineBottom = (metrics.lineHeight * (i - 1)) + textHeight;\n const thisLineTop = metrics.lineHeight * i;\n let thisLineGradientStart = thisLineTop;\n\n // Handle case where last & this line overlap\n if (i > 0 && lastLineBottom > thisLineTop)\n {\n thisLineGradientStart = (thisLineTop + lastLineBottom) / 2;\n }\n\n const thisLineBottom = thisLineTop + textHeight;\n const nextLineTop = metrics.lineHeight * (i + 1);\n let thisLineGradientEnd = thisLineBottom;\n\n // Handle case where this & next line overlap\n if (i + 1 < lines.length && nextLineTop < thisLineBottom)\n {\n thisLineGradientEnd = (thisLineBottom + nextLineTop) / 2;\n }\n\n // textHeight, but as a 0-1 size in global gradient stop space\n const gradStopLineHeight = (thisLineGradientEnd - thisLineGradientStart) / height;\n\n for (let j = 0; j < fill.length; j++)\n {\n // 0-1 stop point for the current line, multiplied to global space afterwards\n let lineStop = 0;\n\n if (typeof fillGradientStops[j] === 'number')\n {\n lineStop = fillGradientStops[j];\n }\n else\n {\n lineStop = j / fill.length;\n }\n\n let globalStop = Math.min(1, Math.max(0,\n (thisLineGradientStart / height) + (lineStop * gradStopLineHeight)));\n\n // There's potential for floating point precision issues at the seams between gradient repeats.\n globalStop = Number(globalStop.toFixed(5));\n gradient.addColorStop(globalStop, fill[j]);\n }\n }\n }\n else\n {\n // start the gradient at the center left of the canvas, and end at the center right of the canvas\n gradient = this.context.createLinearGradient(padding, height / 2, width + padding, height / 2);\n\n // can just evenly space out the gradients in this case, as multiple lines makes no difference\n // to an even left to right gradient\n const totalIterations = fill.length + 1;\n let currentIteration = 1;\n\n for (let i = 0; i < fill.length; i++)\n {\n let stop: number;\n\n if (typeof fillGradientStops[i] === 'number')\n {\n stop = fillGradientStops[i];\n }\n else\n {\n stop = currentIteration / totalIterations;\n }\n gradient.addColorStop(stop, fill[i]);\n currentIteration++;\n }\n }\n\n return gradient;\n }\n\n /**\n * Destroys this text object.\n *\n * Note* Unlike a Sprite, a Text object will automatically destroy its baseTexture and texture as\n * the majority of the time the texture will not be shared with any other Sprites.\n * @param options - Options parameter. A boolean will act as if all options\n * have been set to that value\n * @param {boolean} [options.children=false] - if set to true, all the children will have their\n * destroy method called as well. 'options' will be passed on to those calls.\n * @param {boolean} [options.texture=true] - Should it destroy the current texture of the sprite as well\n * @param {boolean} [options.baseTexture=true] - Should it destroy the base texture of the sprite as well\n */\n public destroy(options?: IDestroyOptions | boolean): void\n {\n if (typeof options === 'boolean')\n {\n options = { children: options };\n }\n\n options = Object.assign({}, defaultDestroyOptions, options);\n\n super.destroy(options);\n\n // set canvas width and height to 0 to workaround memory leak in Safari < 13\n // https://stackoverflow.com/questions/52532614/total-canvas-memory-use-exceeds-the-maximum-limit-safari-12\n if (this._ownCanvas)\n {\n this.canvas.height = this.canvas.width = 0;\n }\n\n // make sure to reset the context and canvas.. dont want this hanging around in memory!\n this.context = null;\n this.canvas = null;\n\n this._style = null;\n }\n\n /** The width of the Text, setting this will actually modify the scale to achieve the value set. */\n get width(): number\n {\n this.updateText(true);\n\n return Math.abs(this.scale.x) * this._texture.orig.width;\n }\n\n set width(value: number)\n {\n this.updateText(true);\n\n const s = sign(this.scale.x) || 1;\n\n this.scale.x = s * value / this._texture.orig.width;\n this._width = value;\n }\n\n /** The height of the Text, setting this will actually modify the scale to achieve the value set. */\n get height(): number\n {\n this.updateText(true);\n\n return Math.abs(this.scale.y) * this._texture.orig.height;\n }\n\n set height(value: number)\n {\n this.updateText(true);\n\n const s = sign(this.scale.y) || 1;\n\n this.scale.y = s * value / this._texture.orig.height;\n this._height = value;\n }\n\n /**\n * Set the style of the text.\n *\n * Set up an event listener to listen for changes on the style object and mark the text as dirty.\n */\n get style(): TextStyle | Partial<ITextStyle>\n {\n // TODO: Can't have different types for getter and setter. The getter shouldn't have the ITextStyle\n // since the setter creates the TextStyle. See this thread for more details:\n // https://github.com/microsoft/TypeScript/issues/2521\n return this._style;\n }\n\n set style(style: TextStyle | Partial<ITextStyle>)\n {\n style = style || {};\n\n if (style instanceof TextStyle)\n {\n this._style = style;\n }\n else\n {\n this._style = new TextStyle(style);\n }\n\n this.localStyleID = -1;\n this.dirty = true;\n }\n\n /** Set the copy for the text object. To split a line you can use '\\n'. */\n get text(): string\n {\n return this._text;\n }\n\n set text(text: string | number)\n {\n text = String(text === null || text === undefined ? '' : text);\n\n if (this._text === text)\n {\n return;\n }\n this._text = text;\n this.dirty = true;\n }\n\n /**\n * The resolution / device pixel ratio of the canvas.\n *\n * This is set to automatically match the renderer resolution by default, but can be overridden by setting manually.\n * @default 1\n */\n get resolution(): number\n {\n return this._resolution;\n }\n\n set resolution(value: number)\n {\n this._autoResolution = false;\n\n if (this._resolution === value)\n {\n return;\n }\n\n this._resolution = value;\n this.dirty = true;\n }\n}\n"],"names":["TEXT_GRADIENT","extendStatics","d","b","Object","setPrototypeOf","__proto__","Array","p","hasOwnProperty","defaultStyle","align","breakWords","dropShadow","dropShadowAlpha","dropShadowAngle","Math","PI","dropShadowBlur","dropShadowColor","dropShadowDistance","fill","fillGradientType","LINEAR_VERTICAL","fillGradientStops","fontFamily","fontSize","fontStyle","fontVariant","fontWeight","letterSpacing","lineHeight","lineJoin","miterLimit","padding","stroke","strokeThickness","textBaseline","trim","whiteSpace","wordWrap","wordWrapWidth","leading","genericFontFamilies","TextStyle","style","this","styleID","reset","deepCopyProperties","prototype","clone","clonedProperties","defineProperty","get","_align","set","_breakWords","_dropShadow","_dropShadowAlpha","_dropShadowAngle","_dropShadowBlur","_dropShadowColor","outputColor","getColor","_dropShadowDistance","_fill","_fillGradientType","_fillGradientStops","array1","array2","isArray","length","i","areArraysEqual","_fontFamily","_fontSize","_fontStyle","_fontVariant","_fontWeight","_letterSpacing","_lineHeight","_leading","_lineJoin","_miterLimit","_padding","_stroke","_strokeThickness","_textBaseline","_trim","_whiteSpace","_wordWrap","_wordWrapWidth","toFontString","fontSizeString","fontFamilies","split","test","indexOf","join","getSingleColor","color","hex2string","replace","target","source","propertyObj","prop","slice","contextSettings","willReadFrequently","TextMetrics","text","width","height","lines","lineWidths","maxLineWidth","fontProperties","measureText","canvas","_canvas","font","measureFont","ascent","context","getContext","lineWidth","max","line","cache","create","collapseSpaces","collapseNewlines","canPrependSpaces","tokens","tokenize","token","isNewline","addLine","currIsBreakingSpace","isBreakingSpace","lastIsBreakingSpace","tokenWidth","getFromCache","canBreakWords","characters","wordWrapSplit","j","char","k","nextChar","lastChar","canBreakChars","characterWidth","isLastToken","newLine","trimRight","key","spacing","_newlines","charCodeAt","_nextChar","_breakingSpaces","push","_token","_char","_index","_fonts","properties","descent","_context","metricsString","METRICS_STRING","BASELINE_SYMBOL","ceil","baseline","HEIGHT_MULTIPLIER","BASELINE_MULTIPLIER","fillStyle","fillRect","fillText","imagedata","getImageData","data","pixels","idx","stop","clearMetrics","__canvas","c","OffscreenCanvas","settings","ADAPTER","createCanvas","ex","__context","defaultDestroyOptions","texture","children","baseTexture","Text","_super","_this","ownCanvas","Texture","from","orig","Rectangle","call","_ownCanvas","_resolution","RESOLUTION","_autoResolution","_text","_style","_styleListener","_font","localStyleID","__","constructor","__extends","updateText","respectDirty","dirty","linePositionX","linePositionY","measured","scale","clearRect","passesCount","isShadowPass","dsOffsetText","dsOffsetShadow","strokeStyle","rgb","hex2rgb","string2hex","shadowColor","shadowBlur","shadowOffsetX","cos","shadowOffsetY","sin","_generateFillStyle","linePositionYShift","nextLineHeightBehavior","i_1","drawLetterSpacing","updateTexture","x","y","isStroke","supportLetterSpacing","experimentalLetterSpacing","CanvasRenderingContext2D","textLetterSpacing","strokeText","currentPosition","stringArray","previousWidth","currentWidth","currentChar","textStr","trimmed","trimCanvas","putImageData","_texture","_frame","_onTextureUpdate","setRealSize","updateUvs","_render","renderer","resolution","updateTransform","getBounds","skipUpdate","rect","_textureID","getLocalBounds","_calculateBounds","calculateVertices","_bounds","addQuad","vertexData","metrics","gradient","dropShadowCorrection","lengthPlus1","unshift","createLinearGradient","textHeight","lastLineBottom","thisLineTop","thisLineGradientStart","thisLineBottom","nextLineTop","thisLineGradientEnd","gradStopLineHeight","lineStop","globalStop","min","Number","toFixed","addColorStop","totalIterations","currentIteration","destroy","options","assign","abs","value","s","sign","_width","_height","String","Sprite"],"mappings":"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"}
|