text-bitmap.js 84 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843
  1. /*!
  2. * @pixi/text-bitmap - v6.5.10
  3. * Compiled Thu, 06 Jul 2023 15:25:11 UTC
  4. *
  5. * @pixi/text-bitmap is licensed under the MIT License.
  6. * http://www.opensource.org/licenses/mit-license
  7. */
  8. this.PIXI = this.PIXI || {};
  9. var _pixi_text_bitmap = (function (exports, math, settings, mesh, utils, core, text, constants, display, loaders) {
  10. 'use strict';
  11. /*! *****************************************************************************
  12. Copyright (c) Microsoft Corporation.
  13. Permission to use, copy, modify, and/or distribute this software for any
  14. purpose with or without fee is hereby granted.
  15. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  16. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  17. AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  18. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  19. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  20. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  21. PERFORMANCE OF THIS SOFTWARE.
  22. ***************************************************************************** */
  23. /* global Reflect, Promise */
  24. var extendStatics = function(d, b) {
  25. extendStatics = Object.setPrototypeOf ||
  26. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  27. function (d, b) { for (var p in b) { if (b.hasOwnProperty(p)) { d[p] = b[p]; } } };
  28. return extendStatics(d, b);
  29. };
  30. function __extends(d, b) {
  31. extendStatics(d, b);
  32. function __() { this.constructor = d; }
  33. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  34. }
  35. var __assign = function() {
  36. __assign = Object.assign || function __assign(t) {
  37. var arguments$1 = arguments;
  38. for (var s, i = 1, n = arguments.length; i < n; i++) {
  39. s = arguments$1[i];
  40. for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p)) { t[p] = s[p]; } }
  41. }
  42. return t;
  43. };
  44. return __assign.apply(this, arguments);
  45. };
  46. function __rest(s, e) {
  47. var t = {};
  48. for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  49. { t[p] = s[p]; } }
  50. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  51. { for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  52. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  53. { t[p[i]] = s[p[i]]; }
  54. } }
  55. return t;
  56. }
  57. function __decorate(decorators, target, key, desc) {
  58. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  59. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") { r = Reflect.decorate(decorators, target, key, desc); }
  60. 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; } } }
  61. return c > 3 && r && Object.defineProperty(target, key, r), r;
  62. }
  63. function __param(paramIndex, decorator) {
  64. return function (target, key) { decorator(target, key, paramIndex); }
  65. }
  66. function __metadata(metadataKey, metadataValue) {
  67. if (typeof Reflect === "object" && typeof Reflect.metadata === "function") { return Reflect.metadata(metadataKey, metadataValue); }
  68. }
  69. function __awaiter(thisArg, _arguments, P, generator) {
  70. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  71. return new (P || (P = Promise))(function (resolve, reject) {
  72. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  73. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  74. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  75. step((generator = generator.apply(thisArg, _arguments || [])).next());
  76. });
  77. }
  78. function __generator(thisArg, body) {
  79. var _ = { label: 0, sent: function() { if (t[0] & 1) { throw t[1]; } return t[1]; }, trys: [], ops: [] }, f, y, t, g;
  80. return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
  81. function verb(n) { return function (v) { return step([n, v]); }; }
  82. function step(op) {
  83. if (f) { throw new TypeError("Generator is already executing."); }
  84. while (_) { try {
  85. 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; }
  86. if (y = 0, t) { op = [op[0] & 2, t.value]; }
  87. switch (op[0]) {
  88. case 0: case 1: t = op; break;
  89. case 4: _.label++; return { value: op[1], done: false };
  90. case 5: _.label++; y = op[1]; op = [0]; continue;
  91. case 7: op = _.ops.pop(); _.trys.pop(); continue;
  92. default:
  93. if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
  94. if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
  95. if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
  96. if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
  97. if (t[2]) { _.ops.pop(); }
  98. _.trys.pop(); continue;
  99. }
  100. op = body.call(thisArg, _);
  101. } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } }
  102. if (op[0] & 5) { throw op[1]; } return { value: op[0] ? op[1] : void 0, done: true };
  103. }
  104. }
  105. function __createBinding(o, m, k, k2) {
  106. if (k2 === undefined) { k2 = k; }
  107. o[k2] = m[k];
  108. }
  109. function __exportStar(m, exports) {
  110. for (var p in m) { if (p !== "default" && !exports.hasOwnProperty(p)) { exports[p] = m[p]; } }
  111. }
  112. function __values(o) {
  113. var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
  114. if (m) { return m.call(o); }
  115. if (o && typeof o.length === "number") { return {
  116. next: function () {
  117. if (o && i >= o.length) { o = void 0; }
  118. return { value: o && o[i++], done: !o };
  119. }
  120. }; }
  121. throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
  122. }
  123. function __read(o, n) {
  124. var m = typeof Symbol === "function" && o[Symbol.iterator];
  125. if (!m) { return o; }
  126. var i = m.call(o), r, ar = [], e;
  127. try {
  128. while ((n === void 0 || n-- > 0) && !(r = i.next()).done) { ar.push(r.value); }
  129. }
  130. catch (error) { e = { error: error }; }
  131. finally {
  132. try {
  133. if (r && !r.done && (m = i["return"])) { m.call(i); }
  134. }
  135. finally { if (e) { throw e.error; } }
  136. }
  137. return ar;
  138. }
  139. function __spread() {
  140. var arguments$1 = arguments;
  141. for (var ar = [], i = 0; i < arguments.length; i++)
  142. { ar = ar.concat(__read(arguments$1[i])); }
  143. return ar;
  144. }
  145. function __spreadArrays() {
  146. var arguments$1 = arguments;
  147. for (var s = 0, i = 0, il = arguments.length; i < il; i++) { s += arguments$1[i].length; }
  148. for (var r = Array(s), k = 0, i = 0; i < il; i++)
  149. { for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
  150. { r[k] = a[j]; } }
  151. return r;
  152. };
  153. function __await(v) {
  154. return this instanceof __await ? (this.v = v, this) : new __await(v);
  155. }
  156. function __asyncGenerator(thisArg, _arguments, generator) {
  157. if (!Symbol.asyncIterator) { throw new TypeError("Symbol.asyncIterator is not defined."); }
  158. var g = generator.apply(thisArg, _arguments || []), i, q = [];
  159. return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
  160. 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); }); }; } }
  161. function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
  162. function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
  163. function fulfill(value) { resume("next", value); }
  164. function reject(value) { resume("throw", value); }
  165. function settle(f, v) { if (f(v), q.shift(), q.length) { resume(q[0][0], q[0][1]); } }
  166. }
  167. function __asyncDelegator(o) {
  168. var i, p;
  169. return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
  170. 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; }
  171. }
  172. function __asyncValues(o) {
  173. if (!Symbol.asyncIterator) { throw new TypeError("Symbol.asyncIterator is not defined."); }
  174. var m = o[Symbol.asyncIterator], i;
  175. 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);
  176. 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); }); }; }
  177. function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
  178. }
  179. function __makeTemplateObject(cooked, raw) {
  180. if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
  181. return cooked;
  182. };
  183. function __importStar(mod) {
  184. if (mod && mod.__esModule) { return mod; }
  185. var result = {};
  186. if (mod != null) { for (var k in mod) { if (Object.hasOwnProperty.call(mod, k)) { result[k] = mod[k]; } } }
  187. result.default = mod;
  188. return result;
  189. }
  190. function __importDefault(mod) {
  191. return (mod && mod.__esModule) ? mod : { default: mod };
  192. }
  193. function __classPrivateFieldGet(receiver, privateMap) {
  194. if (!privateMap.has(receiver)) {
  195. throw new TypeError("attempted to get private field on non-instance");
  196. }
  197. return privateMap.get(receiver);
  198. }
  199. function __classPrivateFieldSet(receiver, privateMap, value) {
  200. if (!privateMap.has(receiver)) {
  201. throw new TypeError("attempted to set private field on non-instance");
  202. }
  203. privateMap.set(receiver, value);
  204. return value;
  205. }
  206. /* eslint-disable max-len */
  207. /**
  208. * Normalized parsed data from .fnt files.
  209. * @memberof PIXI
  210. */
  211. var BitmapFontData = /** @class */ (function () {
  212. function BitmapFontData() {
  213. this.info = [];
  214. this.common = [];
  215. this.page = [];
  216. this.char = [];
  217. this.kerning = [];
  218. this.distanceField = [];
  219. }
  220. return BitmapFontData;
  221. }());
  222. /**
  223. * BitmapFont format that's Text-based.
  224. * @private
  225. */
  226. var TextFormat = /** @class */ (function () {
  227. function TextFormat() {
  228. }
  229. /**
  230. * Check if resource refers to txt font data.
  231. * @param data
  232. * @returns - True if resource could be treated as font data, false otherwise.
  233. */
  234. TextFormat.test = function (data) {
  235. return typeof data === 'string' && data.indexOf('info face=') === 0;
  236. };
  237. /**
  238. * Convert text font data to a javascript object.
  239. * @param txt - Raw string data to be converted
  240. * @returns - Parsed font data
  241. */
  242. TextFormat.parse = function (txt) {
  243. // Retrieve data item
  244. var items = txt.match(/^[a-z]+\s+.+$/gm);
  245. var rawData = {
  246. info: [],
  247. common: [],
  248. page: [],
  249. char: [],
  250. chars: [],
  251. kerning: [],
  252. kernings: [],
  253. distanceField: [],
  254. };
  255. for (var i in items) {
  256. // Extract item name
  257. var name = items[i].match(/^[a-z]+/gm)[0];
  258. // Extract item attribute list as string ex.: "width=10"
  259. var attributeList = items[i].match(/[a-zA-Z]+=([^\s"']+|"([^"]*)")/gm);
  260. // Convert attribute list into an object
  261. var itemData = {};
  262. for (var i_1 in attributeList) {
  263. // Split key-value pairs
  264. var split = attributeList[i_1].split('=');
  265. var key = split[0];
  266. // Remove eventual quotes from value
  267. var strValue = split[1].replace(/"/gm, '');
  268. // Try to convert value into float
  269. var floatValue = parseFloat(strValue);
  270. // Use string value case float value is NaN
  271. var value = isNaN(floatValue) ? strValue : floatValue;
  272. itemData[key] = value;
  273. }
  274. // Push current item to the resulting data
  275. rawData[name].push(itemData);
  276. }
  277. var font = new BitmapFontData();
  278. rawData.info.forEach(function (info) { return font.info.push({
  279. face: info.face,
  280. size: parseInt(info.size, 10),
  281. }); });
  282. rawData.common.forEach(function (common) { return font.common.push({
  283. lineHeight: parseInt(common.lineHeight, 10),
  284. }); });
  285. rawData.page.forEach(function (page) { return font.page.push({
  286. id: parseInt(page.id, 10),
  287. file: page.file,
  288. }); });
  289. rawData.char.forEach(function (char) { return font.char.push({
  290. id: parseInt(char.id, 10),
  291. page: parseInt(char.page, 10),
  292. x: parseInt(char.x, 10),
  293. y: parseInt(char.y, 10),
  294. width: parseInt(char.width, 10),
  295. height: parseInt(char.height, 10),
  296. xoffset: parseInt(char.xoffset, 10),
  297. yoffset: parseInt(char.yoffset, 10),
  298. xadvance: parseInt(char.xadvance, 10),
  299. }); });
  300. rawData.kerning.forEach(function (kerning) { return font.kerning.push({
  301. first: parseInt(kerning.first, 10),
  302. second: parseInt(kerning.second, 10),
  303. amount: parseInt(kerning.amount, 10),
  304. }); });
  305. rawData.distanceField.forEach(function (df) { return font.distanceField.push({
  306. distanceRange: parseInt(df.distanceRange, 10),
  307. fieldType: df.fieldType,
  308. }); });
  309. return font;
  310. };
  311. return TextFormat;
  312. }());
  313. /**
  314. * BitmapFont format that's XML-based.
  315. * @private
  316. */
  317. var XMLFormat = /** @class */ (function () {
  318. function XMLFormat() {
  319. }
  320. /**
  321. * Check if resource refers to xml font data.
  322. * @param data
  323. * @returns - True if resource could be treated as font data, false otherwise.
  324. */
  325. XMLFormat.test = function (data) {
  326. return data instanceof XMLDocument
  327. && data.getElementsByTagName('page').length
  328. && data.getElementsByTagName('info')[0].getAttribute('face') !== null;
  329. };
  330. /**
  331. * Convert the XML into BitmapFontData that we can use.
  332. * @param xml
  333. * @returns - Data to use for BitmapFont
  334. */
  335. XMLFormat.parse = function (xml) {
  336. var data = new BitmapFontData();
  337. var info = xml.getElementsByTagName('info');
  338. var common = xml.getElementsByTagName('common');
  339. var page = xml.getElementsByTagName('page');
  340. var char = xml.getElementsByTagName('char');
  341. var kerning = xml.getElementsByTagName('kerning');
  342. var distanceField = xml.getElementsByTagName('distanceField');
  343. for (var i = 0; i < info.length; i++) {
  344. data.info.push({
  345. face: info[i].getAttribute('face'),
  346. size: parseInt(info[i].getAttribute('size'), 10),
  347. });
  348. }
  349. for (var i = 0; i < common.length; i++) {
  350. data.common.push({
  351. lineHeight: parseInt(common[i].getAttribute('lineHeight'), 10),
  352. });
  353. }
  354. for (var i = 0; i < page.length; i++) {
  355. data.page.push({
  356. id: parseInt(page[i].getAttribute('id'), 10) || 0,
  357. file: page[i].getAttribute('file'),
  358. });
  359. }
  360. for (var i = 0; i < char.length; i++) {
  361. var letter = char[i];
  362. data.char.push({
  363. id: parseInt(letter.getAttribute('id'), 10),
  364. page: parseInt(letter.getAttribute('page'), 10) || 0,
  365. x: parseInt(letter.getAttribute('x'), 10),
  366. y: parseInt(letter.getAttribute('y'), 10),
  367. width: parseInt(letter.getAttribute('width'), 10),
  368. height: parseInt(letter.getAttribute('height'), 10),
  369. xoffset: parseInt(letter.getAttribute('xoffset'), 10),
  370. yoffset: parseInt(letter.getAttribute('yoffset'), 10),
  371. xadvance: parseInt(letter.getAttribute('xadvance'), 10),
  372. });
  373. }
  374. for (var i = 0; i < kerning.length; i++) {
  375. data.kerning.push({
  376. first: parseInt(kerning[i].getAttribute('first'), 10),
  377. second: parseInt(kerning[i].getAttribute('second'), 10),
  378. amount: parseInt(kerning[i].getAttribute('amount'), 10),
  379. });
  380. }
  381. for (var i = 0; i < distanceField.length; i++) {
  382. data.distanceField.push({
  383. fieldType: distanceField[i].getAttribute('fieldType'),
  384. distanceRange: parseInt(distanceField[i].getAttribute('distanceRange'), 10),
  385. });
  386. }
  387. return data;
  388. };
  389. return XMLFormat;
  390. }());
  391. /**
  392. * BitmapFont format that's XML-based.
  393. * @private
  394. */
  395. var XMLStringFormat = /** @class */ (function () {
  396. function XMLStringFormat() {
  397. }
  398. /**
  399. * Check if resource refers to text xml font data.
  400. * @param data
  401. * @returns - True if resource could be treated as font data, false otherwise.
  402. */
  403. XMLStringFormat.test = function (data) {
  404. if (typeof data === 'string' && data.indexOf('<font>') > -1) {
  405. var xml = new globalThis.DOMParser().parseFromString(data, 'text/xml');
  406. return XMLFormat.test(xml);
  407. }
  408. return false;
  409. };
  410. /**
  411. * Convert the text XML into BitmapFontData that we can use.
  412. * @param xmlTxt
  413. * @returns - Data to use for BitmapFont
  414. */
  415. XMLStringFormat.parse = function (xmlTxt) {
  416. var xml = new globalThis.DOMParser().parseFromString(xmlTxt, 'text/xml');
  417. return XMLFormat.parse(xml);
  418. };
  419. return XMLStringFormat;
  420. }());
  421. // Registered formats, maybe make this extensible in the future?
  422. var formats = [
  423. TextFormat,
  424. XMLFormat,
  425. XMLStringFormat ];
  426. /**
  427. * Auto-detect BitmapFont parsing format based on data.
  428. * @private
  429. * @param {any} data - Data to detect format
  430. * @returns {any} Format or null
  431. */
  432. function autoDetectFormat(data) {
  433. for (var i = 0; i < formats.length; i++) {
  434. if (formats[i].test(data)) {
  435. return formats[i];
  436. }
  437. }
  438. return null;
  439. }
  440. // TODO: Prevent code duplication b/w generateFillStyle & Text#generateFillStyle
  441. /**
  442. * Generates the fill style. Can automatically generate a gradient based on the fill style being an array
  443. * @private
  444. * @param canvas
  445. * @param context
  446. * @param {object} style - The style.
  447. * @param resolution
  448. * @param {string[]} lines - The lines of text.
  449. * @param metrics
  450. * @returns {string|number|CanvasGradient} The fill style
  451. */
  452. function generateFillStyle(canvas, context, style, resolution, lines, metrics) {
  453. // TODO: Can't have different types for getter and setter. The getter shouldn't have the number type as
  454. // the setter converts to string. See this thread for more details:
  455. // https://github.com/microsoft/TypeScript/issues/2521
  456. var fillStyle = style.fill;
  457. if (!Array.isArray(fillStyle)) {
  458. return fillStyle;
  459. }
  460. else if (fillStyle.length === 1) {
  461. return fillStyle[0];
  462. }
  463. // the gradient will be evenly spaced out according to how large the array is.
  464. // ['#FF0000', '#00FF00', '#0000FF'] would created stops at 0.25, 0.5 and 0.75
  465. var gradient;
  466. // a dropshadow will enlarge the canvas and result in the gradient being
  467. // generated with the incorrect dimensions
  468. var dropShadowCorrection = (style.dropShadow) ? style.dropShadowDistance : 0;
  469. // should also take padding into account, padding can offset the gradient
  470. var padding = style.padding || 0;
  471. var width = (canvas.width / resolution) - dropShadowCorrection - (padding * 2);
  472. var height = (canvas.height / resolution) - dropShadowCorrection - (padding * 2);
  473. // make a copy of the style settings, so we can manipulate them later
  474. var fill = fillStyle.slice();
  475. var fillGradientStops = style.fillGradientStops.slice();
  476. // wanting to evenly distribute the fills. So an array of 4 colours should give fills of 0.25, 0.5 and 0.75
  477. if (!fillGradientStops.length) {
  478. var lengthPlus1 = fill.length + 1;
  479. for (var i = 1; i < lengthPlus1; ++i) {
  480. fillGradientStops.push(i / lengthPlus1);
  481. }
  482. }
  483. // stop the bleeding of the last gradient on the line above to the top gradient of the this line
  484. // by hard defining the first gradient colour at point 0, and last gradient colour at point 1
  485. fill.unshift(fillStyle[0]);
  486. fillGradientStops.unshift(0);
  487. fill.push(fillStyle[fillStyle.length - 1]);
  488. fillGradientStops.push(1);
  489. if (style.fillGradientType === text.TEXT_GRADIENT.LINEAR_VERTICAL) {
  490. // start the gradient at the top center of the canvas, and end at the bottom middle of the canvas
  491. gradient = context.createLinearGradient(width / 2, padding, width / 2, height + padding);
  492. // we need to repeat the gradient so that each individual line of text has the same vertical gradient effect
  493. // ['#FF0000', '#00FF00', '#0000FF'] over 2 lines would create stops at 0.125, 0.25, 0.375, 0.625, 0.75, 0.875
  494. // There's potential for floating point precision issues at the seams between gradient repeats.
  495. // The loop below generates the stops in order, so track the last generated one to prevent
  496. // floating point precision from making us go the teeniest bit backwards, resulting in
  497. // the first and last colors getting swapped.
  498. var lastIterationStop = 0;
  499. // Actual height of the text itself, not counting spacing for lineHeight/leading/dropShadow etc
  500. var textHeight = metrics.fontProperties.fontSize + style.strokeThickness;
  501. // textHeight, but as a 0-1 size in global gradient stop space
  502. var gradStopLineHeight = textHeight / height;
  503. for (var i = 0; i < lines.length; i++) {
  504. var thisLineTop = metrics.lineHeight * i;
  505. for (var j = 0; j < fill.length; j++) {
  506. // 0-1 stop point for the current line, multiplied to global space afterwards
  507. var lineStop = 0;
  508. if (typeof fillGradientStops[j] === 'number') {
  509. lineStop = fillGradientStops[j];
  510. }
  511. else {
  512. lineStop = j / fill.length;
  513. }
  514. var globalStop = (thisLineTop / height) + (lineStop * gradStopLineHeight);
  515. // Prevent color stop generation going backwards from floating point imprecision
  516. var clampedStop = Math.max(lastIterationStop, globalStop);
  517. clampedStop = Math.min(clampedStop, 1); // Cap at 1 as well for safety's sake to avoid a possible throw.
  518. gradient.addColorStop(clampedStop, fill[j]);
  519. lastIterationStop = clampedStop;
  520. }
  521. }
  522. }
  523. else {
  524. // start the gradient at the center left of the canvas, and end at the center right of the canvas
  525. gradient = context.createLinearGradient(padding, height / 2, width + padding, height / 2);
  526. // can just evenly space out the gradients in this case, as multiple lines makes no difference
  527. // to an even left to right gradient
  528. var totalIterations = fill.length + 1;
  529. var currentIteration = 1;
  530. for (var i = 0; i < fill.length; i++) {
  531. var stop = void 0;
  532. if (typeof fillGradientStops[i] === 'number') {
  533. stop = fillGradientStops[i];
  534. }
  535. else {
  536. stop = currentIteration / totalIterations;
  537. }
  538. gradient.addColorStop(stop, fill[i]);
  539. currentIteration++;
  540. }
  541. }
  542. return gradient;
  543. }
  544. // TODO: Prevent code duplication b/w drawGlyph & Text#updateText
  545. /**
  546. * Draws the glyph `metrics.text` on the given canvas.
  547. *
  548. * Ignored because not directly exposed.
  549. * @ignore
  550. * @param {HTMLCanvasElement} canvas
  551. * @param {CanvasRenderingContext2D} context
  552. * @param {TextMetrics} metrics
  553. * @param {number} x
  554. * @param {number} y
  555. * @param {number} resolution
  556. * @param {TextStyle} style
  557. */
  558. function drawGlyph(canvas, context, metrics, x, y, resolution, style) {
  559. var char = metrics.text;
  560. var fontProperties = metrics.fontProperties;
  561. context.translate(x, y);
  562. context.scale(resolution, resolution);
  563. var tx = style.strokeThickness / 2;
  564. var ty = -(style.strokeThickness / 2);
  565. context.font = style.toFontString();
  566. context.lineWidth = style.strokeThickness;
  567. context.textBaseline = style.textBaseline;
  568. context.lineJoin = style.lineJoin;
  569. context.miterLimit = style.miterLimit;
  570. // set canvas text styles
  571. context.fillStyle = generateFillStyle(canvas, context, style, resolution, [char], metrics);
  572. context.strokeStyle = style.stroke;
  573. if (style.dropShadow) {
  574. var dropShadowColor = style.dropShadowColor;
  575. var rgb = utils.hex2rgb(typeof dropShadowColor === 'number' ? dropShadowColor : utils.string2hex(dropShadowColor));
  576. var dropShadowBlur = style.dropShadowBlur * resolution;
  577. var dropShadowDistance = style.dropShadowDistance * resolution;
  578. context.shadowColor = "rgba(" + rgb[0] * 255 + "," + rgb[1] * 255 + "," + rgb[2] * 255 + "," + style.dropShadowAlpha + ")";
  579. context.shadowBlur = dropShadowBlur;
  580. context.shadowOffsetX = Math.cos(style.dropShadowAngle) * dropShadowDistance;
  581. context.shadowOffsetY = Math.sin(style.dropShadowAngle) * dropShadowDistance;
  582. }
  583. else {
  584. context.shadowColor = 'black';
  585. context.shadowBlur = 0;
  586. context.shadowOffsetX = 0;
  587. context.shadowOffsetY = 0;
  588. }
  589. if (style.stroke && style.strokeThickness) {
  590. context.strokeText(char, tx, ty + metrics.lineHeight - fontProperties.descent);
  591. }
  592. if (style.fill) {
  593. context.fillText(char, tx, ty + metrics.lineHeight - fontProperties.descent);
  594. }
  595. context.setTransform(1, 0, 0, 1, 0, 0); // defaults needed for older browsers (e.g. Opera 29)
  596. context.fillStyle = 'rgba(0, 0, 0, 0)';
  597. }
  598. /**
  599. * Ponyfill for IE because it doesn't support `Array.from`
  600. * @param text
  601. * @private
  602. */
  603. function splitTextToCharacters(text) {
  604. return Array.from ? Array.from(text) : text.split('');
  605. }
  606. /**
  607. * Processes the passed character set data and returns a flattened array of all the characters.
  608. *
  609. * Ignored because not directly exposed.
  610. * @ignore
  611. * @param {string | string[] | string[][] } chars
  612. * @returns {string[]} the flattened array of characters
  613. */
  614. function resolveCharacters(chars) {
  615. // Split the chars string into individual characters
  616. if (typeof chars === 'string') {
  617. chars = [chars];
  618. }
  619. // Handle an array of characters+ranges
  620. var result = [];
  621. for (var i = 0, j = chars.length; i < j; i++) {
  622. var item = chars[i];
  623. // Handle range delimited by start/end chars
  624. if (Array.isArray(item)) {
  625. if (item.length !== 2) {
  626. throw new Error("[BitmapFont]: Invalid character range length, expecting 2 got " + item.length + ".");
  627. }
  628. var startCode = item[0].charCodeAt(0);
  629. var endCode = item[1].charCodeAt(0);
  630. if (endCode < startCode) {
  631. throw new Error('[BitmapFont]: Invalid character range.');
  632. }
  633. for (var i_1 = startCode, j_1 = endCode; i_1 <= j_1; i_1++) {
  634. result.push(String.fromCharCode(i_1));
  635. }
  636. }
  637. // Handle a character set string
  638. else {
  639. result.push.apply(result, splitTextToCharacters(item));
  640. }
  641. }
  642. if (result.length === 0) {
  643. throw new Error('[BitmapFont]: Empty set when resolving characters.');
  644. }
  645. return result;
  646. }
  647. /**
  648. * Ponyfill for IE because it doesn't support `codePointAt`
  649. * @param str
  650. * @private
  651. */
  652. function extractCharCode(str) {
  653. return str.codePointAt ? str.codePointAt(0) : str.charCodeAt(0);
  654. }
  655. /**
  656. * BitmapFont represents a typeface available for use with the BitmapText class. Use the `install`
  657. * method for adding a font to be used.
  658. * @memberof PIXI
  659. */
  660. var BitmapFont = /** @class */ (function () {
  661. /**
  662. * @param data
  663. * @param textures
  664. * @param ownsTextures - Setting to `true` will destroy page textures
  665. * when the font is uninstalled.
  666. */
  667. function BitmapFont(data, textures, ownsTextures) {
  668. var _a, _b;
  669. var info = data.info[0];
  670. var common = data.common[0];
  671. var page = data.page[0];
  672. var distanceField = data.distanceField[0];
  673. var res = utils.getResolutionOfUrl(page.file);
  674. var pageTextures = {};
  675. this._ownsTextures = ownsTextures;
  676. this.font = info.face;
  677. this.size = info.size;
  678. this.lineHeight = common.lineHeight / res;
  679. this.chars = {};
  680. this.pageTextures = pageTextures;
  681. // Convert the input Texture, Textures or object
  682. // into a page Texture lookup by "id"
  683. for (var i = 0; i < data.page.length; i++) {
  684. var _c = data.page[i], id = _c.id, file = _c.file;
  685. pageTextures[id] = textures instanceof Array
  686. ? textures[i] : textures[file];
  687. // only MSDF and SDF fonts need no-premultiplied-alpha
  688. if ((distanceField === null || distanceField === void 0 ? void 0 : distanceField.fieldType) && distanceField.fieldType !== 'none') {
  689. pageTextures[id].baseTexture.alphaMode = constants.ALPHA_MODES.NO_PREMULTIPLIED_ALPHA;
  690. pageTextures[id].baseTexture.mipmap = constants.MIPMAP_MODES.OFF;
  691. }
  692. }
  693. // parse letters
  694. for (var i = 0; i < data.char.length; i++) {
  695. var _d = data.char[i], id = _d.id, page_1 = _d.page;
  696. var _e = data.char[i], x = _e.x, y = _e.y, width = _e.width, height = _e.height, xoffset = _e.xoffset, yoffset = _e.yoffset, xadvance = _e.xadvance;
  697. x /= res;
  698. y /= res;
  699. width /= res;
  700. height /= res;
  701. xoffset /= res;
  702. yoffset /= res;
  703. xadvance /= res;
  704. var rect = new math.Rectangle(x + (pageTextures[page_1].frame.x / res), y + (pageTextures[page_1].frame.y / res), width, height);
  705. this.chars[id] = {
  706. xOffset: xoffset,
  707. yOffset: yoffset,
  708. xAdvance: xadvance,
  709. kerning: {},
  710. texture: new core.Texture(pageTextures[page_1].baseTexture, rect),
  711. page: page_1,
  712. };
  713. }
  714. // parse kernings
  715. for (var i = 0; i < data.kerning.length; i++) {
  716. var _f = data.kerning[i], first = _f.first, second = _f.second, amount = _f.amount;
  717. first /= res;
  718. second /= res;
  719. amount /= res;
  720. if (this.chars[second]) {
  721. this.chars[second].kerning[first] = amount;
  722. }
  723. }
  724. // Store distance field information
  725. this.distanceFieldRange = distanceField === null || distanceField === void 0 ? void 0 : distanceField.distanceRange;
  726. this.distanceFieldType = (_b = (_a = distanceField === null || distanceField === void 0 ? void 0 : distanceField.fieldType) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : 'none';
  727. }
  728. /** Remove references to created glyph textures. */
  729. BitmapFont.prototype.destroy = function () {
  730. for (var id in this.chars) {
  731. this.chars[id].texture.destroy();
  732. this.chars[id].texture = null;
  733. }
  734. for (var id in this.pageTextures) {
  735. if (this._ownsTextures) {
  736. this.pageTextures[id].destroy(true);
  737. }
  738. this.pageTextures[id] = null;
  739. }
  740. // Set readonly null.
  741. this.chars = null;
  742. this.pageTextures = null;
  743. };
  744. /**
  745. * Register a new bitmap font.
  746. * @param data - The
  747. * characters map that could be provided as xml or raw string.
  748. * @param textures - List of textures for each page.
  749. * @param ownsTextures - Set to `true` to destroy page textures
  750. * when the font is uninstalled. By default fonts created with
  751. * `BitmapFont.from` or from the `BitmapFontLoader` are `true`.
  752. * @returns {PIXI.BitmapFont} Result font object with font, size, lineHeight
  753. * and char fields.
  754. */
  755. BitmapFont.install = function (data, textures, ownsTextures) {
  756. var fontData;
  757. if (data instanceof BitmapFontData) {
  758. fontData = data;
  759. }
  760. else {
  761. var format = autoDetectFormat(data);
  762. if (!format) {
  763. throw new Error('Unrecognized data format for font.');
  764. }
  765. fontData = format.parse(data);
  766. }
  767. // Single texture, convert to list
  768. if (textures instanceof core.Texture) {
  769. textures = [textures];
  770. }
  771. var font = new BitmapFont(fontData, textures, ownsTextures);
  772. BitmapFont.available[font.font] = font;
  773. return font;
  774. };
  775. /**
  776. * Remove bitmap font by name.
  777. * @param name - Name of the font to uninstall.
  778. */
  779. BitmapFont.uninstall = function (name) {
  780. var font = BitmapFont.available[name];
  781. if (!font) {
  782. throw new Error("No font found named '" + name + "'");
  783. }
  784. font.destroy();
  785. delete BitmapFont.available[name];
  786. };
  787. /**
  788. * Generates a bitmap-font for the given style and character set. This does not support
  789. * kernings yet. With `style` properties, only the following non-layout properties are used:
  790. *
  791. * - {@link PIXI.TextStyle#dropShadow|dropShadow}
  792. * - {@link PIXI.TextStyle#dropShadowDistance|dropShadowDistance}
  793. * - {@link PIXI.TextStyle#dropShadowColor|dropShadowColor}
  794. * - {@link PIXI.TextStyle#dropShadowBlur|dropShadowBlur}
  795. * - {@link PIXI.TextStyle#dropShadowAngle|dropShadowAngle}
  796. * - {@link PIXI.TextStyle#fill|fill}
  797. * - {@link PIXI.TextStyle#fillGradientStops|fillGradientStops}
  798. * - {@link PIXI.TextStyle#fillGradientType|fillGradientType}
  799. * - {@link PIXI.TextStyle#fontFamily|fontFamily}
  800. * - {@link PIXI.TextStyle#fontSize|fontSize}
  801. * - {@link PIXI.TextStyle#fontVariant|fontVariant}
  802. * - {@link PIXI.TextStyle#fontWeight|fontWeight}
  803. * - {@link PIXI.TextStyle#lineJoin|lineJoin}
  804. * - {@link PIXI.TextStyle#miterLimit|miterLimit}
  805. * - {@link PIXI.TextStyle#stroke|stroke}
  806. * - {@link PIXI.TextStyle#strokeThickness|strokeThickness}
  807. * - {@link PIXI.TextStyle#textBaseline|textBaseline}
  808. * @param name - The name of the custom font to use with BitmapText.
  809. * @param textStyle - Style options to render with BitmapFont.
  810. * @param options - Setup options for font or name of the font.
  811. * @param {string|string[]|string[][]} [options.chars=PIXI.BitmapFont.ALPHANUMERIC] - characters included
  812. * in the font set. You can also use ranges. For example, `[['a', 'z'], ['A', 'Z'], "!@#$%^&*()~{}[] "]`.
  813. * Don't forget to include spaces ' ' in your character set!
  814. * @param {number} [options.resolution=1] - Render resolution for glyphs.
  815. * @param {number} [options.textureWidth=512] - Optional width of atlas, smaller values to reduce memory.
  816. * @param {number} [options.textureHeight=512] - Optional height of atlas, smaller values to reduce memory.
  817. * @param {number} [options.padding=4] - Padding between glyphs on texture atlas.
  818. * @returns Font generated by style options.
  819. * @example
  820. * PIXI.BitmapFont.from("TitleFont", {
  821. * fontFamily: "Arial",
  822. * fontSize: 12,
  823. * strokeThickness: 2,
  824. * fill: "purple"
  825. * });
  826. *
  827. * const title = new PIXI.BitmapText("This is the title", { fontName: "TitleFont" });
  828. */
  829. BitmapFont.from = function (name, textStyle, options) {
  830. if (!name) {
  831. throw new Error('[BitmapFont] Property `name` is required.');
  832. }
  833. var _a = Object.assign({}, BitmapFont.defaultOptions, options), chars = _a.chars, padding = _a.padding, resolution = _a.resolution, textureWidth = _a.textureWidth, textureHeight = _a.textureHeight;
  834. var charsList = resolveCharacters(chars);
  835. var style = textStyle instanceof text.TextStyle ? textStyle : new text.TextStyle(textStyle);
  836. var lineWidth = textureWidth;
  837. var fontData = new BitmapFontData();
  838. fontData.info[0] = {
  839. face: style.fontFamily,
  840. size: style.fontSize,
  841. };
  842. fontData.common[0] = {
  843. lineHeight: style.fontSize,
  844. };
  845. var positionX = 0;
  846. var positionY = 0;
  847. var canvas;
  848. var context;
  849. var baseTexture;
  850. var maxCharHeight = 0;
  851. var baseTextures = [];
  852. var textures = [];
  853. for (var i = 0; i < charsList.length; i++) {
  854. if (!canvas) {
  855. canvas = settings.settings.ADAPTER.createCanvas();
  856. canvas.width = textureWidth;
  857. canvas.height = textureHeight;
  858. context = canvas.getContext('2d');
  859. baseTexture = new core.BaseTexture(canvas, { resolution: resolution });
  860. baseTextures.push(baseTexture);
  861. textures.push(new core.Texture(baseTexture));
  862. fontData.page.push({
  863. id: textures.length - 1,
  864. file: '',
  865. });
  866. }
  867. // Measure glyph dimensions
  868. var character = charsList[i];
  869. var metrics = text.TextMetrics.measureText(character, style, false, canvas);
  870. var width = metrics.width;
  871. var height = Math.ceil(metrics.height);
  872. // This is ugly - but italics are given more space so they don't overlap
  873. var textureGlyphWidth = Math.ceil((style.fontStyle === 'italic' ? 2 : 1) * width);
  874. // Can't fit char anymore: next canvas please!
  875. if (positionY >= textureHeight - (height * resolution)) {
  876. if (positionY === 0) {
  877. // We don't want user debugging an infinite loop (or do we? :)
  878. throw new Error("[BitmapFont] textureHeight " + textureHeight + "px is too small "
  879. + ("(fontFamily: '" + style.fontFamily + "', fontSize: " + style.fontSize + "px, char: '" + character + "')"));
  880. }
  881. --i;
  882. // Create new atlas once current has filled up
  883. canvas = null;
  884. context = null;
  885. baseTexture = null;
  886. positionY = 0;
  887. positionX = 0;
  888. maxCharHeight = 0;
  889. continue;
  890. }
  891. maxCharHeight = Math.max(height + metrics.fontProperties.descent, maxCharHeight);
  892. // Wrap line once full row has been rendered
  893. if ((textureGlyphWidth * resolution) + positionX >= lineWidth) {
  894. if (positionX === 0) {
  895. // Avoid infinite loop (There can be some very wide char like '\uFDFD'!)
  896. throw new Error("[BitmapFont] textureWidth " + textureWidth + "px is too small "
  897. + ("(fontFamily: '" + style.fontFamily + "', fontSize: " + style.fontSize + "px, char: '" + character + "')"));
  898. }
  899. --i;
  900. positionY += maxCharHeight * resolution;
  901. positionY = Math.ceil(positionY);
  902. positionX = 0;
  903. maxCharHeight = 0;
  904. continue;
  905. }
  906. drawGlyph(canvas, context, metrics, positionX, positionY, resolution, style);
  907. // Unique (numeric) ID mapping to this glyph
  908. var id = extractCharCode(metrics.text);
  909. // Create a texture holding just the glyph
  910. fontData.char.push({
  911. id: id,
  912. page: textures.length - 1,
  913. x: positionX / resolution,
  914. y: positionY / resolution,
  915. width: textureGlyphWidth,
  916. height: height,
  917. xoffset: 0,
  918. yoffset: 0,
  919. xadvance: Math.ceil(width
  920. - (style.dropShadow ? style.dropShadowDistance : 0)
  921. - (style.stroke ? style.strokeThickness : 0)),
  922. });
  923. positionX += (textureGlyphWidth + (2 * padding)) * resolution;
  924. positionX = Math.ceil(positionX);
  925. }
  926. if (!(options === null || options === void 0 ? void 0 : options.skipKerning)) {
  927. // Brute-force kerning info, this can be expensive b/c it's an O(n²),
  928. // but we're using measureText which is native and fast.
  929. for (var i = 0, len = charsList.length; i < len; i++) {
  930. var first = charsList[i];
  931. for (var j = 0; j < len; j++) {
  932. var second = charsList[j];
  933. var c1 = context.measureText(first).width;
  934. var c2 = context.measureText(second).width;
  935. var total = context.measureText(first + second).width;
  936. var amount = total - (c1 + c2);
  937. if (amount) {
  938. fontData.kerning.push({
  939. first: extractCharCode(first),
  940. second: extractCharCode(second),
  941. amount: amount,
  942. });
  943. }
  944. }
  945. }
  946. }
  947. var font = new BitmapFont(fontData, textures, true);
  948. // Make it easier to replace a font
  949. if (BitmapFont.available[name] !== undefined) {
  950. BitmapFont.uninstall(name);
  951. }
  952. BitmapFont.available[name] = font;
  953. return font;
  954. };
  955. /**
  956. * This character set includes all the letters in the alphabet (both lower- and upper- case).
  957. * @type {string[][]}
  958. * @example
  959. * BitmapFont.from("ExampleFont", style, { chars: BitmapFont.ALPHA })
  960. */
  961. BitmapFont.ALPHA = [['a', 'z'], ['A', 'Z'], ' '];
  962. /**
  963. * This character set includes all decimal digits (from 0 to 9).
  964. * @type {string[][]}
  965. * @example
  966. * BitmapFont.from("ExampleFont", style, { chars: BitmapFont.NUMERIC })
  967. */
  968. BitmapFont.NUMERIC = [['0', '9']];
  969. /**
  970. * This character set is the union of `BitmapFont.ALPHA` and `BitmapFont.NUMERIC`.
  971. * @type {string[][]}
  972. */
  973. BitmapFont.ALPHANUMERIC = [['a', 'z'], ['A', 'Z'], ['0', '9'], ' '];
  974. /**
  975. * This character set consists of all the ASCII table.
  976. * @member {string[][]}
  977. * @see http://www.asciitable.com/
  978. */
  979. BitmapFont.ASCII = [[' ', '~']];
  980. /**
  981. * Collection of default options when using `BitmapFont.from`.
  982. * @property {number} [resolution=1] -
  983. * @property {number} [textureWidth=512] -
  984. * @property {number} [textureHeight=512] -
  985. * @property {number} [padding=4] -
  986. * @property {string|string[]|string[][]} chars = PIXI.BitmapFont.ALPHANUMERIC
  987. */
  988. BitmapFont.defaultOptions = {
  989. resolution: 1,
  990. textureWidth: 512,
  991. textureHeight: 512,
  992. padding: 4,
  993. chars: BitmapFont.ALPHANUMERIC,
  994. };
  995. /** Collection of available/installed fonts. */
  996. BitmapFont.available = {};
  997. return BitmapFont;
  998. }());
  999. var msdfFrag = "// Pixi texture info\r\nvarying vec2 vTextureCoord;\r\nuniform sampler2D uSampler;\r\n\r\n// Tint\r\nuniform vec4 uColor;\r\n\r\n// on 2D applications fwidth is screenScale / glyphAtlasScale * distanceFieldRange\r\nuniform float uFWidth;\r\n\r\nvoid main(void) {\r\n\r\n // To stack MSDF and SDF we need a non-pre-multiplied-alpha texture.\r\n vec4 texColor = texture2D(uSampler, vTextureCoord);\r\n\r\n // MSDF\r\n float median = texColor.r + texColor.g + texColor.b -\r\n min(texColor.r, min(texColor.g, texColor.b)) -\r\n max(texColor.r, max(texColor.g, texColor.b));\r\n // SDF\r\n median = min(median, texColor.a);\r\n\r\n float screenPxDistance = uFWidth * (median - 0.5);\r\n float alpha = clamp(screenPxDistance + 0.5, 0.0, 1.0);\r\n if (median < 0.01) {\r\n alpha = 0.0;\r\n } else if (median > 0.99) {\r\n alpha = 1.0;\r\n }\r\n\r\n // NPM Textures, NPM outputs\r\n gl_FragColor = vec4(uColor.rgb, uColor.a * alpha);\r\n\r\n}\r\n";
  1000. var msdfVert = "// Mesh material default fragment\r\nattribute vec2 aVertexPosition;\r\nattribute vec2 aTextureCoord;\r\n\r\nuniform mat3 projectionMatrix;\r\nuniform mat3 translationMatrix;\r\nuniform mat3 uTextureMatrix;\r\n\r\nvarying vec2 vTextureCoord;\r\n\r\nvoid main(void)\r\n{\r\n gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\r\n\r\n vTextureCoord = (uTextureMatrix * vec3(aTextureCoord, 1.0)).xy;\r\n}\r\n";
  1001. // If we ever need more than two pools, please make a Dict or something better.
  1002. var pageMeshDataDefaultPageMeshData = [];
  1003. var pageMeshDataMSDFPageMeshData = [];
  1004. var charRenderDataPool = [];
  1005. /**
  1006. * A BitmapText object will create a line or multiple lines of text using bitmap font.
  1007. *
  1008. * The primary advantage of this class over Text is that all of your textures are pre-generated and loading,
  1009. * meaning that rendering is fast, and changing text has no performance implications.
  1010. *
  1011. * Supporting character sets other than latin, such as CJK languages, may be impractical due to the number of characters.
  1012. *
  1013. * To split a line you can use '\n', '\r' or '\r\n' in your string.
  1014. *
  1015. * PixiJS can auto-generate fonts on-the-fly using BitmapFont or use fnt files provided by:
  1016. * http://www.angelcode.com/products/bmfont/ for Windows or
  1017. * http://www.bmglyph.com/ for Mac.
  1018. *
  1019. * You can also use SDF, MSDF and MTSDF BitmapFonts for vector-like scaling appearance provided by:
  1020. * https://github.com/soimy/msdf-bmfont-xml for SDF and MSDF fnt files or
  1021. * https://github.com/Chlumsky/msdf-atlas-gen for SDF, MSDF and MTSDF json files
  1022. *
  1023. * A BitmapText can only be created when the font is loaded.
  1024. *
  1025. * ```js
  1026. * // in this case the font is in a file called 'desyrel.fnt'
  1027. * let bitmapText = new PIXI.BitmapText("text using a fancy font!", {
  1028. * fontName: "Desyrel",
  1029. * fontSize: 35,
  1030. * align: "right"
  1031. * });
  1032. * ```
  1033. * @memberof PIXI
  1034. */
  1035. var BitmapText = /** @class */ (function (_super) {
  1036. __extends(BitmapText, _super);
  1037. /**
  1038. * @param text - A string that you would like the text to display.
  1039. * @param style - The style parameters.
  1040. * @param {string} style.fontName - The installed BitmapFont name.
  1041. * @param {number} [style.fontSize] - The size of the font in pixels, e.g. 24. If undefined,
  1042. *. this will default to the BitmapFont size.
  1043. * @param {string} [style.align='left'] - Alignment for multiline text ('left', 'center', 'right' or 'justify'),
  1044. * does not affect single line text.
  1045. * @param {number} [style.tint=0xFFFFFF] - The tint color.
  1046. * @param {number} [style.letterSpacing=0] - The amount of spacing between letters.
  1047. * @param {number} [style.maxWidth=0] - The max width of the text before line wrapping.
  1048. */
  1049. function BitmapText(text, style) {
  1050. if (style === void 0) { style = {}; }
  1051. var _this = _super.call(this) || this;
  1052. /**
  1053. * Private tracker for the current tint.
  1054. * @private
  1055. */
  1056. _this._tint = 0xFFFFFF;
  1057. // Apply the defaults
  1058. var _a = Object.assign({}, BitmapText.styleDefaults, style), align = _a.align, tint = _a.tint, maxWidth = _a.maxWidth, letterSpacing = _a.letterSpacing, fontName = _a.fontName, fontSize = _a.fontSize;
  1059. if (!BitmapFont.available[fontName]) {
  1060. throw new Error("Missing BitmapFont \"" + fontName + "\"");
  1061. }
  1062. _this._activePagesMeshData = [];
  1063. _this._textWidth = 0;
  1064. _this._textHeight = 0;
  1065. _this._align = align;
  1066. _this._tint = tint;
  1067. _this._font = undefined;
  1068. _this._fontName = fontName;
  1069. _this._fontSize = fontSize;
  1070. _this.text = text;
  1071. _this._maxWidth = maxWidth;
  1072. _this._maxLineHeight = 0;
  1073. _this._letterSpacing = letterSpacing;
  1074. _this._anchor = new math.ObservablePoint(function () { _this.dirty = true; }, _this, 0, 0);
  1075. _this._roundPixels = settings.settings.ROUND_PIXELS;
  1076. _this.dirty = true;
  1077. _this._resolution = settings.settings.RESOLUTION;
  1078. _this._autoResolution = true;
  1079. _this._textureCache = {};
  1080. return _this;
  1081. }
  1082. /** Renders text and updates it when needed. This should only be called if the BitmapFont is regenerated. */
  1083. BitmapText.prototype.updateText = function () {
  1084. var _a;
  1085. var data = BitmapFont.available[this._fontName];
  1086. var fontSize = this.fontSize;
  1087. var scale = fontSize / data.size;
  1088. var pos = new math.Point();
  1089. var chars = [];
  1090. var lineWidths = [];
  1091. var lineSpaces = [];
  1092. var text = this._text.replace(/(?:\r\n|\r)/g, '\n') || ' ';
  1093. var charsInput = splitTextToCharacters(text);
  1094. var maxWidth = this._maxWidth * data.size / fontSize;
  1095. var pageMeshDataPool = data.distanceFieldType === 'none'
  1096. ? pageMeshDataDefaultPageMeshData : pageMeshDataMSDFPageMeshData;
  1097. var prevCharCode = null;
  1098. var lastLineWidth = 0;
  1099. var maxLineWidth = 0;
  1100. var line = 0;
  1101. var lastBreakPos = -1;
  1102. var lastBreakWidth = 0;
  1103. var spacesRemoved = 0;
  1104. var maxLineHeight = 0;
  1105. var spaceCount = 0;
  1106. for (var i = 0; i < charsInput.length; i++) {
  1107. var char = charsInput[i];
  1108. var charCode = extractCharCode(char);
  1109. if ((/(?:\s)/).test(char)) {
  1110. lastBreakPos = i;
  1111. lastBreakWidth = lastLineWidth;
  1112. spaceCount++;
  1113. }
  1114. if (char === '\r' || char === '\n') {
  1115. lineWidths.push(lastLineWidth);
  1116. lineSpaces.push(-1);
  1117. maxLineWidth = Math.max(maxLineWidth, lastLineWidth);
  1118. ++line;
  1119. ++spacesRemoved;
  1120. pos.x = 0;
  1121. pos.y += data.lineHeight;
  1122. prevCharCode = null;
  1123. spaceCount = 0;
  1124. continue;
  1125. }
  1126. var charData = data.chars[charCode];
  1127. if (!charData) {
  1128. continue;
  1129. }
  1130. if (prevCharCode && charData.kerning[prevCharCode]) {
  1131. pos.x += charData.kerning[prevCharCode];
  1132. }
  1133. var charRenderData = charRenderDataPool.pop() || {
  1134. texture: core.Texture.EMPTY,
  1135. line: 0,
  1136. charCode: 0,
  1137. prevSpaces: 0,
  1138. position: new math.Point(),
  1139. };
  1140. charRenderData.texture = charData.texture;
  1141. charRenderData.line = line;
  1142. charRenderData.charCode = charCode;
  1143. charRenderData.position.x = pos.x + charData.xOffset + (this._letterSpacing / 2);
  1144. charRenderData.position.y = pos.y + charData.yOffset;
  1145. charRenderData.prevSpaces = spaceCount;
  1146. chars.push(charRenderData);
  1147. lastLineWidth = charRenderData.position.x
  1148. + Math.max(charData.xAdvance - charData.xOffset, charData.texture.orig.width);
  1149. pos.x += charData.xAdvance + this._letterSpacing;
  1150. maxLineHeight = Math.max(maxLineHeight, (charData.yOffset + charData.texture.height));
  1151. prevCharCode = charCode;
  1152. if (lastBreakPos !== -1 && maxWidth > 0 && pos.x > maxWidth) {
  1153. ++spacesRemoved;
  1154. utils.removeItems(chars, 1 + lastBreakPos - spacesRemoved, 1 + i - lastBreakPos);
  1155. i = lastBreakPos;
  1156. lastBreakPos = -1;
  1157. lineWidths.push(lastBreakWidth);
  1158. lineSpaces.push(chars.length > 0 ? chars[chars.length - 1].prevSpaces : 0);
  1159. maxLineWidth = Math.max(maxLineWidth, lastBreakWidth);
  1160. line++;
  1161. pos.x = 0;
  1162. pos.y += data.lineHeight;
  1163. prevCharCode = null;
  1164. spaceCount = 0;
  1165. }
  1166. }
  1167. var lastChar = charsInput[charsInput.length - 1];
  1168. if (lastChar !== '\r' && lastChar !== '\n') {
  1169. if ((/(?:\s)/).test(lastChar)) {
  1170. lastLineWidth = lastBreakWidth;
  1171. }
  1172. lineWidths.push(lastLineWidth);
  1173. maxLineWidth = Math.max(maxLineWidth, lastLineWidth);
  1174. lineSpaces.push(-1);
  1175. }
  1176. var lineAlignOffsets = [];
  1177. for (var i = 0; i <= line; i++) {
  1178. var alignOffset = 0;
  1179. if (this._align === 'right') {
  1180. alignOffset = maxLineWidth - lineWidths[i];
  1181. }
  1182. else if (this._align === 'center') {
  1183. alignOffset = (maxLineWidth - lineWidths[i]) / 2;
  1184. }
  1185. else if (this._align === 'justify') {
  1186. alignOffset = lineSpaces[i] < 0 ? 0 : (maxLineWidth - lineWidths[i]) / lineSpaces[i];
  1187. }
  1188. lineAlignOffsets.push(alignOffset);
  1189. }
  1190. var lenChars = chars.length;
  1191. var pagesMeshData = {};
  1192. var newPagesMeshData = [];
  1193. var activePagesMeshData = this._activePagesMeshData;
  1194. pageMeshDataPool.push.apply(pageMeshDataPool, activePagesMeshData);
  1195. for (var i = 0; i < lenChars; i++) {
  1196. var texture = chars[i].texture;
  1197. var baseTextureUid = texture.baseTexture.uid;
  1198. if (!pagesMeshData[baseTextureUid]) {
  1199. var pageMeshData = pageMeshDataPool.pop();
  1200. if (!pageMeshData) {
  1201. var geometry = new mesh.MeshGeometry();
  1202. var material = void 0;
  1203. var meshBlendMode = void 0;
  1204. if (data.distanceFieldType === 'none') {
  1205. material = new mesh.MeshMaterial(core.Texture.EMPTY);
  1206. meshBlendMode = constants.BLEND_MODES.NORMAL;
  1207. }
  1208. else {
  1209. material = new mesh.MeshMaterial(core.Texture.EMPTY, { program: core.Program.from(msdfVert, msdfFrag), uniforms: { uFWidth: 0 } });
  1210. meshBlendMode = constants.BLEND_MODES.NORMAL_NPM;
  1211. }
  1212. var mesh$1 = new mesh.Mesh(geometry, material);
  1213. mesh$1.blendMode = meshBlendMode;
  1214. pageMeshData = {
  1215. index: 0,
  1216. indexCount: 0,
  1217. vertexCount: 0,
  1218. uvsCount: 0,
  1219. total: 0,
  1220. mesh: mesh$1,
  1221. vertices: null,
  1222. uvs: null,
  1223. indices: null,
  1224. };
  1225. }
  1226. // reset data..
  1227. pageMeshData.index = 0;
  1228. pageMeshData.indexCount = 0;
  1229. pageMeshData.vertexCount = 0;
  1230. pageMeshData.uvsCount = 0;
  1231. pageMeshData.total = 0;
  1232. // TODO need to get page texture here somehow..
  1233. var _textureCache = this._textureCache;
  1234. _textureCache[baseTextureUid] = _textureCache[baseTextureUid] || new core.Texture(texture.baseTexture);
  1235. pageMeshData.mesh.texture = _textureCache[baseTextureUid];
  1236. pageMeshData.mesh.tint = this._tint;
  1237. newPagesMeshData.push(pageMeshData);
  1238. pagesMeshData[baseTextureUid] = pageMeshData;
  1239. }
  1240. pagesMeshData[baseTextureUid].total++;
  1241. }
  1242. // lets find any previously active pageMeshDatas that are no longer required for
  1243. // the updated text (if any), removed and return them to the pool.
  1244. for (var i = 0; i < activePagesMeshData.length; i++) {
  1245. if (newPagesMeshData.indexOf(activePagesMeshData[i]) === -1) {
  1246. this.removeChild(activePagesMeshData[i].mesh);
  1247. }
  1248. }
  1249. // next lets add any new meshes, that have not yet been added to this BitmapText
  1250. // we only add if its not already a child of this BitmapObject
  1251. for (var i = 0; i < newPagesMeshData.length; i++) {
  1252. if (newPagesMeshData[i].mesh.parent !== this) {
  1253. this.addChild(newPagesMeshData[i].mesh);
  1254. }
  1255. }
  1256. // active page mesh datas are set to be the new pages added.
  1257. this._activePagesMeshData = newPagesMeshData;
  1258. for (var i in pagesMeshData) {
  1259. var pageMeshData = pagesMeshData[i];
  1260. var total = pageMeshData.total;
  1261. // lets only allocate new buffers if we can fit the new text in the current ones..
  1262. // unless that is, we will be batching. Currently batching dose not respect the size property of mesh
  1263. if (!(((_a = pageMeshData.indices) === null || _a === void 0 ? void 0 : _a.length) > 6 * total) || pageMeshData.vertices.length < mesh.Mesh.BATCHABLE_SIZE * 2) {
  1264. pageMeshData.vertices = new Float32Array(4 * 2 * total);
  1265. pageMeshData.uvs = new Float32Array(4 * 2 * total);
  1266. pageMeshData.indices = new Uint16Array(6 * total);
  1267. }
  1268. else {
  1269. var total_1 = pageMeshData.total;
  1270. var vertices = pageMeshData.vertices;
  1271. // Clear the garbage at the end of the vertices buffer. This will prevent the bounds miscalculation.
  1272. for (var i_1 = total_1 * 4 * 2; i_1 < vertices.length; i_1++) {
  1273. vertices[i_1] = 0;
  1274. }
  1275. }
  1276. // as a buffer maybe bigger than the current word, we set the size of the meshMaterial
  1277. // to match the number of letters needed
  1278. pageMeshData.mesh.size = 6 * total;
  1279. }
  1280. for (var i = 0; i < lenChars; i++) {
  1281. var char = chars[i];
  1282. var offset = char.position.x + (lineAlignOffsets[char.line] * (this._align === 'justify' ? char.prevSpaces : 1));
  1283. if (this._roundPixels) {
  1284. offset = Math.round(offset);
  1285. }
  1286. var xPos = offset * scale;
  1287. var yPos = char.position.y * scale;
  1288. var texture = char.texture;
  1289. var pageMesh = pagesMeshData[texture.baseTexture.uid];
  1290. var textureFrame = texture.frame;
  1291. var textureUvs = texture._uvs;
  1292. var index = pageMesh.index++;
  1293. pageMesh.indices[(index * 6) + 0] = 0 + (index * 4);
  1294. pageMesh.indices[(index * 6) + 1] = 1 + (index * 4);
  1295. pageMesh.indices[(index * 6) + 2] = 2 + (index * 4);
  1296. pageMesh.indices[(index * 6) + 3] = 0 + (index * 4);
  1297. pageMesh.indices[(index * 6) + 4] = 2 + (index * 4);
  1298. pageMesh.indices[(index * 6) + 5] = 3 + (index * 4);
  1299. pageMesh.vertices[(index * 8) + 0] = xPos;
  1300. pageMesh.vertices[(index * 8) + 1] = yPos;
  1301. pageMesh.vertices[(index * 8) + 2] = xPos + (textureFrame.width * scale);
  1302. pageMesh.vertices[(index * 8) + 3] = yPos;
  1303. pageMesh.vertices[(index * 8) + 4] = xPos + (textureFrame.width * scale);
  1304. pageMesh.vertices[(index * 8) + 5] = yPos + (textureFrame.height * scale);
  1305. pageMesh.vertices[(index * 8) + 6] = xPos;
  1306. pageMesh.vertices[(index * 8) + 7] = yPos + (textureFrame.height * scale);
  1307. pageMesh.uvs[(index * 8) + 0] = textureUvs.x0;
  1308. pageMesh.uvs[(index * 8) + 1] = textureUvs.y0;
  1309. pageMesh.uvs[(index * 8) + 2] = textureUvs.x1;
  1310. pageMesh.uvs[(index * 8) + 3] = textureUvs.y1;
  1311. pageMesh.uvs[(index * 8) + 4] = textureUvs.x2;
  1312. pageMesh.uvs[(index * 8) + 5] = textureUvs.y2;
  1313. pageMesh.uvs[(index * 8) + 6] = textureUvs.x3;
  1314. pageMesh.uvs[(index * 8) + 7] = textureUvs.y3;
  1315. }
  1316. this._textWidth = maxLineWidth * scale;
  1317. this._textHeight = (pos.y + data.lineHeight) * scale;
  1318. for (var i in pagesMeshData) {
  1319. var pageMeshData = pagesMeshData[i];
  1320. // apply anchor
  1321. if (this.anchor.x !== 0 || this.anchor.y !== 0) {
  1322. var vertexCount = 0;
  1323. var anchorOffsetX = this._textWidth * this.anchor.x;
  1324. var anchorOffsetY = this._textHeight * this.anchor.y;
  1325. for (var i_2 = 0; i_2 < pageMeshData.total; i_2++) {
  1326. pageMeshData.vertices[vertexCount++] -= anchorOffsetX;
  1327. pageMeshData.vertices[vertexCount++] -= anchorOffsetY;
  1328. pageMeshData.vertices[vertexCount++] -= anchorOffsetX;
  1329. pageMeshData.vertices[vertexCount++] -= anchorOffsetY;
  1330. pageMeshData.vertices[vertexCount++] -= anchorOffsetX;
  1331. pageMeshData.vertices[vertexCount++] -= anchorOffsetY;
  1332. pageMeshData.vertices[vertexCount++] -= anchorOffsetX;
  1333. pageMeshData.vertices[vertexCount++] -= anchorOffsetY;
  1334. }
  1335. }
  1336. this._maxLineHeight = maxLineHeight * scale;
  1337. var vertexBuffer = pageMeshData.mesh.geometry.getBuffer('aVertexPosition');
  1338. var textureBuffer = pageMeshData.mesh.geometry.getBuffer('aTextureCoord');
  1339. var indexBuffer = pageMeshData.mesh.geometry.getIndex();
  1340. vertexBuffer.data = pageMeshData.vertices;
  1341. textureBuffer.data = pageMeshData.uvs;
  1342. indexBuffer.data = pageMeshData.indices;
  1343. vertexBuffer.update();
  1344. textureBuffer.update();
  1345. indexBuffer.update();
  1346. }
  1347. for (var i = 0; i < chars.length; i++) {
  1348. charRenderDataPool.push(chars[i]);
  1349. }
  1350. this._font = data;
  1351. this.dirty = false;
  1352. };
  1353. BitmapText.prototype.updateTransform = function () {
  1354. this.validate();
  1355. this.containerUpdateTransform();
  1356. };
  1357. BitmapText.prototype._render = function (renderer) {
  1358. if (this._autoResolution && this._resolution !== renderer.resolution) {
  1359. this._resolution = renderer.resolution;
  1360. this.dirty = true;
  1361. }
  1362. // Update the uniform
  1363. var _a = BitmapFont.available[this._fontName], distanceFieldRange = _a.distanceFieldRange, distanceFieldType = _a.distanceFieldType, size = _a.size;
  1364. if (distanceFieldType !== 'none') {
  1365. // Inject the shader code with the correct value
  1366. var _b = this.worldTransform, a = _b.a, b = _b.b, c = _b.c, d = _b.d;
  1367. var dx = Math.sqrt((a * a) + (b * b));
  1368. var dy = Math.sqrt((c * c) + (d * d));
  1369. var worldScale = (Math.abs(dx) + Math.abs(dy)) / 2;
  1370. var fontScale = this.fontSize / size;
  1371. for (var _i = 0, _c = this._activePagesMeshData; _i < _c.length; _i++) {
  1372. var mesh = _c[_i];
  1373. mesh.mesh.shader.uniforms.uFWidth = worldScale * distanceFieldRange * fontScale * this._resolution;
  1374. }
  1375. }
  1376. _super.prototype._render.call(this, renderer);
  1377. };
  1378. /**
  1379. * Validates text before calling parent's getLocalBounds
  1380. * @returns - The rectangular bounding area
  1381. */
  1382. BitmapText.prototype.getLocalBounds = function () {
  1383. this.validate();
  1384. return _super.prototype.getLocalBounds.call(this);
  1385. };
  1386. /**
  1387. * Updates text when needed
  1388. * @private
  1389. */
  1390. BitmapText.prototype.validate = function () {
  1391. var font = BitmapFont.available[this._fontName];
  1392. if (!font) {
  1393. throw new Error("Missing BitmapFont \"" + this._fontName + "\"");
  1394. }
  1395. if (this._font !== font) {
  1396. this.dirty = true;
  1397. }
  1398. if (this.dirty) {
  1399. this.updateText();
  1400. }
  1401. };
  1402. Object.defineProperty(BitmapText.prototype, "tint", {
  1403. /**
  1404. * The tint of the BitmapText object.
  1405. * @default 0xffffff
  1406. */
  1407. get: function () {
  1408. return this._tint;
  1409. },
  1410. set: function (value) {
  1411. if (this._tint === value)
  1412. { return; }
  1413. this._tint = value;
  1414. for (var i = 0; i < this._activePagesMeshData.length; i++) {
  1415. this._activePagesMeshData[i].mesh.tint = value;
  1416. }
  1417. },
  1418. enumerable: false,
  1419. configurable: true
  1420. });
  1421. Object.defineProperty(BitmapText.prototype, "align", {
  1422. /**
  1423. * The alignment of the BitmapText object.
  1424. * @member {string}
  1425. * @default 'left'
  1426. */
  1427. get: function () {
  1428. return this._align;
  1429. },
  1430. set: function (value) {
  1431. if (this._align !== value) {
  1432. this._align = value;
  1433. this.dirty = true;
  1434. }
  1435. },
  1436. enumerable: false,
  1437. configurable: true
  1438. });
  1439. Object.defineProperty(BitmapText.prototype, "fontName", {
  1440. /** The name of the BitmapFont. */
  1441. get: function () {
  1442. return this._fontName;
  1443. },
  1444. set: function (value) {
  1445. if (!BitmapFont.available[value]) {
  1446. throw new Error("Missing BitmapFont \"" + value + "\"");
  1447. }
  1448. if (this._fontName !== value) {
  1449. this._fontName = value;
  1450. this.dirty = true;
  1451. }
  1452. },
  1453. enumerable: false,
  1454. configurable: true
  1455. });
  1456. Object.defineProperty(BitmapText.prototype, "fontSize", {
  1457. /** The size of the font to display. */
  1458. get: function () {
  1459. var _a;
  1460. return (_a = this._fontSize) !== null && _a !== void 0 ? _a : BitmapFont.available[this._fontName].size;
  1461. },
  1462. set: function (value) {
  1463. if (this._fontSize !== value) {
  1464. this._fontSize = value;
  1465. this.dirty = true;
  1466. }
  1467. },
  1468. enumerable: false,
  1469. configurable: true
  1470. });
  1471. Object.defineProperty(BitmapText.prototype, "anchor", {
  1472. /**
  1473. * The anchor sets the origin point of the text.
  1474. *
  1475. * The default is `(0,0)`, this means the text's origin is the top left.
  1476. *
  1477. * Setting the anchor to `(0.5,0.5)` means the text's origin is centered.
  1478. *
  1479. * Setting the anchor to `(1,1)` would mean the text's origin point will be the bottom right corner.
  1480. */
  1481. get: function () {
  1482. return this._anchor;
  1483. },
  1484. set: function (value) {
  1485. if (typeof value === 'number') {
  1486. this._anchor.set(value);
  1487. }
  1488. else {
  1489. this._anchor.copyFrom(value);
  1490. }
  1491. },
  1492. enumerable: false,
  1493. configurable: true
  1494. });
  1495. Object.defineProperty(BitmapText.prototype, "text", {
  1496. /** The text of the BitmapText object. */
  1497. get: function () {
  1498. return this._text;
  1499. },
  1500. set: function (text) {
  1501. text = String(text === null || text === undefined ? '' : text);
  1502. if (this._text === text) {
  1503. return;
  1504. }
  1505. this._text = text;
  1506. this.dirty = true;
  1507. },
  1508. enumerable: false,
  1509. configurable: true
  1510. });
  1511. Object.defineProperty(BitmapText.prototype, "maxWidth", {
  1512. /**
  1513. * The max width of this bitmap text in pixels. If the text provided is longer than the
  1514. * value provided, line breaks will be automatically inserted in the last whitespace.
  1515. * Disable by setting the value to 0.
  1516. */
  1517. get: function () {
  1518. return this._maxWidth;
  1519. },
  1520. set: function (value) {
  1521. if (this._maxWidth === value) {
  1522. return;
  1523. }
  1524. this._maxWidth = value;
  1525. this.dirty = true;
  1526. },
  1527. enumerable: false,
  1528. configurable: true
  1529. });
  1530. Object.defineProperty(BitmapText.prototype, "maxLineHeight", {
  1531. /**
  1532. * The max line height. This is useful when trying to use the total height of the Text,
  1533. * i.e. when trying to vertically align.
  1534. * @readonly
  1535. */
  1536. get: function () {
  1537. this.validate();
  1538. return this._maxLineHeight;
  1539. },
  1540. enumerable: false,
  1541. configurable: true
  1542. });
  1543. Object.defineProperty(BitmapText.prototype, "textWidth", {
  1544. /**
  1545. * The width of the overall text, different from fontSize,
  1546. * which is defined in the style object.
  1547. * @readonly
  1548. */
  1549. get: function () {
  1550. this.validate();
  1551. return this._textWidth;
  1552. },
  1553. enumerable: false,
  1554. configurable: true
  1555. });
  1556. Object.defineProperty(BitmapText.prototype, "letterSpacing", {
  1557. /** Additional space between characters. */
  1558. get: function () {
  1559. return this._letterSpacing;
  1560. },
  1561. set: function (value) {
  1562. if (this._letterSpacing !== value) {
  1563. this._letterSpacing = value;
  1564. this.dirty = true;
  1565. }
  1566. },
  1567. enumerable: false,
  1568. configurable: true
  1569. });
  1570. Object.defineProperty(BitmapText.prototype, "roundPixels", {
  1571. /**
  1572. * If true PixiJS will Math.floor() x/y values when rendering, stopping pixel interpolation.
  1573. * Advantages can include sharper image quality (like text) and faster rendering on canvas.
  1574. * The main disadvantage is movement of objects may appear less smooth.
  1575. * To set the global default, change {@link PIXI.settings.ROUND_PIXELS}
  1576. * @default PIXI.settings.ROUND_PIXELS
  1577. */
  1578. get: function () {
  1579. return this._roundPixels;
  1580. },
  1581. set: function (value) {
  1582. if (value !== this._roundPixels) {
  1583. this._roundPixels = value;
  1584. this.dirty = true;
  1585. }
  1586. },
  1587. enumerable: false,
  1588. configurable: true
  1589. });
  1590. Object.defineProperty(BitmapText.prototype, "textHeight", {
  1591. /**
  1592. * The height of the overall text, different from fontSize,
  1593. * which is defined in the style object.
  1594. * @readonly
  1595. */
  1596. get: function () {
  1597. this.validate();
  1598. return this._textHeight;
  1599. },
  1600. enumerable: false,
  1601. configurable: true
  1602. });
  1603. Object.defineProperty(BitmapText.prototype, "resolution", {
  1604. /**
  1605. * The resolution / device pixel ratio of the canvas.
  1606. *
  1607. * This is set to automatically match the renderer resolution by default, but can be overridden by setting manually.
  1608. * @default 1
  1609. */
  1610. get: function () {
  1611. return this._resolution;
  1612. },
  1613. set: function (value) {
  1614. this._autoResolution = false;
  1615. if (this._resolution === value) {
  1616. return;
  1617. }
  1618. this._resolution = value;
  1619. this.dirty = true;
  1620. },
  1621. enumerable: false,
  1622. configurable: true
  1623. });
  1624. BitmapText.prototype.destroy = function (options) {
  1625. var _textureCache = this._textureCache;
  1626. var data = BitmapFont.available[this._fontName];
  1627. var pageMeshDataPool = data.distanceFieldType === 'none'
  1628. ? pageMeshDataDefaultPageMeshData : pageMeshDataMSDFPageMeshData;
  1629. pageMeshDataPool.push.apply(pageMeshDataPool, this._activePagesMeshData);
  1630. for (var _i = 0, _a = this._activePagesMeshData; _i < _a.length; _i++) {
  1631. var pageMeshData = _a[_i];
  1632. this.removeChild(pageMeshData.mesh);
  1633. }
  1634. this._activePagesMeshData = [];
  1635. // Release references to any cached textures in page pool
  1636. pageMeshDataPool
  1637. .filter(function (page) { return _textureCache[page.mesh.texture.baseTexture.uid]; })
  1638. .forEach(function (page) {
  1639. page.mesh.texture = core.Texture.EMPTY;
  1640. });
  1641. for (var id in _textureCache) {
  1642. var texture = _textureCache[id];
  1643. texture.destroy();
  1644. delete _textureCache[id];
  1645. }
  1646. this._font = null;
  1647. this._textureCache = null;
  1648. _super.prototype.destroy.call(this, options);
  1649. };
  1650. BitmapText.styleDefaults = {
  1651. align: 'left',
  1652. tint: 0xFFFFFF,
  1653. maxWidth: 0,
  1654. letterSpacing: 0,
  1655. };
  1656. return BitmapText;
  1657. }(display.Container));
  1658. /**
  1659. * {@link PIXI.Loader Loader} middleware for loading
  1660. * bitmap-based fonts suitable for using with {@link PIXI.BitmapText}.
  1661. * @memberof PIXI
  1662. */
  1663. var BitmapFontLoader = /** @class */ (function () {
  1664. function BitmapFontLoader() {
  1665. }
  1666. /**
  1667. * Called when the plugin is installed.
  1668. * @see PIXI.extensions.add
  1669. */
  1670. BitmapFontLoader.add = function () {
  1671. loaders.LoaderResource.setExtensionXhrType('fnt', loaders.LoaderResource.XHR_RESPONSE_TYPE.TEXT);
  1672. };
  1673. /**
  1674. * Called after a resource is loaded.
  1675. * @see PIXI.Loader.loaderMiddleware
  1676. * @param this
  1677. * @param {PIXI.LoaderResource} resource
  1678. * @param {Function} next
  1679. */
  1680. BitmapFontLoader.use = function (resource, next) {
  1681. var format = autoDetectFormat(resource.data);
  1682. // Resource was not recognised as any of the expected font data format
  1683. if (!format) {
  1684. next();
  1685. return;
  1686. }
  1687. var baseUrl = BitmapFontLoader.getBaseUrl(this, resource);
  1688. var data = format.parse(resource.data);
  1689. var textures = {};
  1690. // Handle completed, when the number of textures
  1691. // load is the same number as references in the fnt file
  1692. var completed = function (page) {
  1693. textures[page.metadata.pageFile] = page.texture;
  1694. if (Object.keys(textures).length === data.page.length) {
  1695. resource.bitmapFont = BitmapFont.install(data, textures, true);
  1696. next();
  1697. }
  1698. };
  1699. for (var i = 0; i < data.page.length; ++i) {
  1700. var pageFile = data.page[i].file;
  1701. var url = baseUrl + pageFile;
  1702. var exists = false;
  1703. // incase the image is loaded outside
  1704. // using the same loader, resource will be available
  1705. for (var name in this.resources) {
  1706. var bitmapResource = this.resources[name];
  1707. if (bitmapResource.url === url) {
  1708. bitmapResource.metadata.pageFile = pageFile;
  1709. if (bitmapResource.texture) {
  1710. completed(bitmapResource);
  1711. }
  1712. else {
  1713. bitmapResource.onAfterMiddleware.add(completed);
  1714. }
  1715. exists = true;
  1716. break;
  1717. }
  1718. }
  1719. // texture is not loaded, we'll attempt to add
  1720. // it to the load and add the texture to the list
  1721. if (!exists) {
  1722. // Standard loading options for images
  1723. var options = {
  1724. crossOrigin: resource.crossOrigin,
  1725. loadType: loaders.LoaderResource.LOAD_TYPE.IMAGE,
  1726. metadata: Object.assign({ pageFile: pageFile }, resource.metadata.imageMetadata),
  1727. parentResource: resource,
  1728. };
  1729. this.add(url, options, completed);
  1730. }
  1731. }
  1732. };
  1733. /**
  1734. * Get folder path from a resource.
  1735. * @param loader
  1736. * @param resource
  1737. */
  1738. BitmapFontLoader.getBaseUrl = function (loader, resource) {
  1739. var resUrl = !resource.isDataUrl ? BitmapFontLoader.dirname(resource.url) : '';
  1740. if (resource.isDataUrl) {
  1741. if (resUrl === '.') {
  1742. resUrl = '';
  1743. }
  1744. if (loader.baseUrl && resUrl) {
  1745. // if baseurl has a trailing slash then add one to resUrl so the replace works below
  1746. if (loader.baseUrl.charAt(loader.baseUrl.length - 1) === '/') {
  1747. resUrl += '/';
  1748. }
  1749. }
  1750. }
  1751. // remove baseUrl from resUrl
  1752. resUrl = resUrl.replace(loader.baseUrl, '');
  1753. // if there is an resUrl now, it needs a trailing slash. Ensure that it does if the string isn't empty.
  1754. if (resUrl && resUrl.charAt(resUrl.length - 1) !== '/') {
  1755. resUrl += '/';
  1756. }
  1757. return resUrl;
  1758. };
  1759. /**
  1760. * Replacement for NodeJS's path.dirname
  1761. * @param {string} url - Path to get directory for
  1762. */
  1763. BitmapFontLoader.dirname = function (url) {
  1764. var dir = url
  1765. .replace(/\\/g, '/') // convert windows notation to UNIX notation, URL-safe because it's a forbidden character
  1766. .replace(/\/$/, '') // replace trailing slash
  1767. .replace(/\/[^\/]*$/, ''); // remove everything after the last
  1768. // File request is relative, use current directory
  1769. if (dir === url) {
  1770. return '.';
  1771. }
  1772. // Started with a slash
  1773. else if (dir === '') {
  1774. return '/';
  1775. }
  1776. return dir;
  1777. };
  1778. /** @ignore */
  1779. BitmapFontLoader.extension = core.ExtensionType.Loader;
  1780. return BitmapFontLoader;
  1781. }());
  1782. exports.BitmapFont = BitmapFont;
  1783. exports.BitmapFontData = BitmapFontData;
  1784. exports.BitmapFontLoader = BitmapFontLoader;
  1785. exports.BitmapText = BitmapText;
  1786. exports.TextFormat = TextFormat;
  1787. exports.XMLFormat = XMLFormat;
  1788. exports.XMLStringFormat = XMLStringFormat;
  1789. exports.autoDetectFormat = autoDetectFormat;
  1790. Object.defineProperty(exports, '__esModule', { value: true });
  1791. return exports;
  1792. })({}, PIXI, PIXI, PIXI, PIXI.utils, PIXI, PIXI, PIXI, PIXI, PIXI);
  1793. Object.assign(this.PIXI, _pixi_text_bitmap);
  1794. //# sourceMappingURL=text-bitmap.js.map