utils.mjs 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680
  1. /*!
  2. * @pixi/utils - v6.5.10
  3. * Compiled Thu, 06 Jul 2023 15:25:11 UTC
  4. *
  5. * @pixi/utils is licensed under the MIT License.
  6. * http://www.opensource.org/licenses/mit-license
  7. */
  8. import { settings } from '@pixi/settings';
  9. export { isMobile } from '@pixi/settings';
  10. export { default as EventEmitter } from 'eventemitter3';
  11. export { default as earcut } from 'earcut';
  12. import { parse, format, resolve } from 'url';
  13. import { BLEND_MODES } from '@pixi/constants';
  14. /**
  15. * This file contains redeclared types for Node `url` and `querystring` modules. These modules
  16. * don't provide their own typings but instead are a part of the full Node typings. The purpose of
  17. * this file is to redeclare the required types to avoid having the whole Node types as a
  18. * dependency.
  19. */
  20. var url = {
  21. parse: parse,
  22. format: format,
  23. resolve: resolve,
  24. };
  25. function assertPath(path) {
  26. if (typeof path !== 'string') {
  27. throw new TypeError("Path must be a string. Received " + JSON.stringify(path));
  28. }
  29. }
  30. function removeUrlParams(url) {
  31. var re = url.split('?')[0];
  32. return re.split('#')[0];
  33. }
  34. function escapeRegExp(string) {
  35. return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
  36. }
  37. function replaceAll(str, find, replace) {
  38. return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
  39. }
  40. // Resolves . and .. elements in a path with directory names
  41. function normalizeStringPosix(path, allowAboveRoot) {
  42. var res = '';
  43. var lastSegmentLength = 0;
  44. var lastSlash = -1;
  45. var dots = 0;
  46. var code;
  47. for (var i = 0; i <= path.length; ++i) {
  48. if (i < path.length) {
  49. code = path.charCodeAt(i);
  50. }
  51. else if (code === 47) {
  52. break;
  53. }
  54. else {
  55. code = 47;
  56. }
  57. if (code === 47) {
  58. if (lastSlash === i - 1 || dots === 1) ;
  59. else if (lastSlash !== i - 1 && dots === 2) {
  60. if (res.length < 2
  61. || lastSegmentLength !== 2
  62. || res.charCodeAt(res.length - 1) !== 46
  63. || res.charCodeAt(res.length - 2) !== 46) {
  64. if (res.length > 2) {
  65. var lastSlashIndex = res.lastIndexOf('/');
  66. if (lastSlashIndex !== res.length - 1) {
  67. if (lastSlashIndex === -1) {
  68. res = '';
  69. lastSegmentLength = 0;
  70. }
  71. else {
  72. res = res.slice(0, lastSlashIndex);
  73. lastSegmentLength = res.length - 1 - res.lastIndexOf('/');
  74. }
  75. lastSlash = i;
  76. dots = 0;
  77. continue;
  78. }
  79. }
  80. else if (res.length === 2 || res.length === 1) {
  81. res = '';
  82. lastSegmentLength = 0;
  83. lastSlash = i;
  84. dots = 0;
  85. continue;
  86. }
  87. }
  88. if (allowAboveRoot) {
  89. if (res.length > 0) {
  90. res += '/..';
  91. }
  92. else {
  93. res = '..';
  94. }
  95. lastSegmentLength = 2;
  96. }
  97. }
  98. else {
  99. if (res.length > 0) {
  100. res += "/" + path.slice(lastSlash + 1, i);
  101. }
  102. else {
  103. res = path.slice(lastSlash + 1, i);
  104. }
  105. lastSegmentLength = i - lastSlash - 1;
  106. }
  107. lastSlash = i;
  108. dots = 0;
  109. }
  110. else if (code === 46 && dots !== -1) {
  111. ++dots;
  112. }
  113. else {
  114. dots = -1;
  115. }
  116. }
  117. return res;
  118. }
  119. var path = {
  120. /**
  121. * Converts a path to posix format.
  122. * @param path - The path to convert to posix
  123. */
  124. toPosix: function (path) { return replaceAll(path, '\\', '/'); },
  125. /**
  126. * Checks if the path is a URL
  127. * @param path - The path to check
  128. */
  129. isUrl: function (path) { return (/^https?:/).test(this.toPosix(path)); },
  130. /**
  131. * Checks if the path is a data URL
  132. * @param path - The path to check
  133. */
  134. isDataUrl: function (path) {
  135. // eslint-disable-next-line max-len
  136. return (/^data:([a-z]+\/[a-z0-9-+.]+(;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}()_|~`]+)*)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s<>]*?)$/i)
  137. .test(path);
  138. },
  139. /**
  140. * Checks if the path has a protocol e.g. http://
  141. * This will return true for windows file paths
  142. * @param path - The path to check
  143. */
  144. hasProtocol: function (path) { return (/^[^/:]+:\//).test(this.toPosix(path)); },
  145. /**
  146. * Returns the protocol of the path e.g. http://, C:/, file:///
  147. * @param path - The path to get the protocol from
  148. */
  149. getProtocol: function (path) {
  150. assertPath(path);
  151. path = this.toPosix(path);
  152. var protocol = '';
  153. var isFile = (/^file:\/\/\//).exec(path);
  154. var isHttp = (/^[^/:]+:\/\//).exec(path);
  155. var isWindows = (/^[^/:]+:\//).exec(path);
  156. if (isFile || isHttp || isWindows) {
  157. var arr = (isFile === null || isFile === void 0 ? void 0 : isFile[0]) || (isHttp === null || isHttp === void 0 ? void 0 : isHttp[0]) || (isWindows === null || isWindows === void 0 ? void 0 : isWindows[0]);
  158. protocol = arr;
  159. path = path.slice(arr.length);
  160. }
  161. return protocol;
  162. },
  163. /**
  164. * Converts URL to an absolute path.
  165. * When loading from a Web Worker, we must use absolute paths.
  166. * If the URL is already absolute we return it as is
  167. * If it's not, we convert it
  168. * @param url - The URL to test
  169. * @param customBaseUrl - The base URL to use
  170. * @param customRootUrl - The root URL to use
  171. */
  172. toAbsolute: function (url, customBaseUrl, customRootUrl) {
  173. if (this.isDataUrl(url))
  174. { return url; }
  175. var baseUrl = removeUrlParams(this.toPosix(customBaseUrl !== null && customBaseUrl !== void 0 ? customBaseUrl : settings.ADAPTER.getBaseUrl()));
  176. var rootUrl = removeUrlParams(this.toPosix(customRootUrl !== null && customRootUrl !== void 0 ? customRootUrl : this.rootname(baseUrl)));
  177. assertPath(url);
  178. url = this.toPosix(url);
  179. // root relative url
  180. if (url.startsWith('/')) {
  181. return path.join(rootUrl, url.slice(1));
  182. }
  183. var absolutePath = this.isAbsolute(url) ? url : this.join(baseUrl, url);
  184. return absolutePath;
  185. },
  186. /**
  187. * Normalizes the given path, resolving '..' and '.' segments
  188. * @param path - The path to normalize
  189. */
  190. normalize: function (path) {
  191. path = this.toPosix(path);
  192. assertPath(path);
  193. if (path.length === 0)
  194. { return '.'; }
  195. var protocol = '';
  196. var isAbsolute = path.startsWith('/');
  197. if (this.hasProtocol(path)) {
  198. protocol = this.rootname(path);
  199. path = path.slice(protocol.length);
  200. }
  201. var trailingSeparator = path.endsWith('/');
  202. // Normalize the path
  203. path = normalizeStringPosix(path, false);
  204. if (path.length > 0 && trailingSeparator)
  205. { path += '/'; }
  206. if (isAbsolute)
  207. { return "/" + path; }
  208. return protocol + path;
  209. },
  210. /**
  211. * Determines if path is an absolute path.
  212. * Absolute paths can be urls, data urls, or paths on disk
  213. * @param path - The path to test
  214. */
  215. isAbsolute: function (path) {
  216. assertPath(path);
  217. path = this.toPosix(path);
  218. if (this.hasProtocol(path))
  219. { return true; }
  220. return path.startsWith('/');
  221. },
  222. /**
  223. * Joins all given path segments together using the platform-specific separator as a delimiter,
  224. * then normalizes the resulting path
  225. * @param segments - The segments of the path to join
  226. */
  227. join: function () {
  228. var arguments$1 = arguments;
  229. var _a;
  230. var segments = [];
  231. for (var _i = 0; _i < arguments.length; _i++) {
  232. segments[_i] = arguments$1[_i];
  233. }
  234. if (segments.length === 0) {
  235. return '.';
  236. }
  237. var joined;
  238. for (var i = 0; i < segments.length; ++i) {
  239. var arg = segments[i];
  240. assertPath(arg);
  241. if (arg.length > 0) {
  242. if (joined === undefined)
  243. { joined = arg; }
  244. else {
  245. var prevArg = (_a = segments[i - 1]) !== null && _a !== void 0 ? _a : '';
  246. if (this.extname(prevArg)) {
  247. joined += "/../" + arg;
  248. }
  249. else {
  250. joined += "/" + arg;
  251. }
  252. }
  253. }
  254. }
  255. if (joined === undefined) {
  256. return '.';
  257. }
  258. return this.normalize(joined);
  259. },
  260. /**
  261. * Returns the directory name of a path
  262. * @param path - The path to parse
  263. */
  264. dirname: function (path) {
  265. assertPath(path);
  266. if (path.length === 0)
  267. { return '.'; }
  268. path = this.toPosix(path);
  269. var code = path.charCodeAt(0);
  270. var hasRoot = code === 47;
  271. var end = -1;
  272. var matchedSlash = true;
  273. var proto = this.getProtocol(path);
  274. var origpath = path;
  275. path = path.slice(proto.length);
  276. for (var i = path.length - 1; i >= 1; --i) {
  277. code = path.charCodeAt(i);
  278. if (code === 47) {
  279. if (!matchedSlash) {
  280. end = i;
  281. break;
  282. }
  283. }
  284. else {
  285. // We saw the first non-path separator
  286. matchedSlash = false;
  287. }
  288. }
  289. // if end is -1 and its a url then we need to add the path back
  290. // eslint-disable-next-line no-nested-ternary
  291. if (end === -1)
  292. { return hasRoot ? '/' : this.isUrl(origpath) ? proto + path : proto; }
  293. if (hasRoot && end === 1)
  294. { return '//'; }
  295. return proto + path.slice(0, end);
  296. },
  297. /**
  298. * Returns the root of the path e.g. /, C:/, file:///, http://domain.com/
  299. * @param path - The path to parse
  300. */
  301. rootname: function (path) {
  302. assertPath(path);
  303. path = this.toPosix(path);
  304. var root = '';
  305. if (path.startsWith('/'))
  306. { root = '/'; }
  307. else {
  308. root = this.getProtocol(path);
  309. }
  310. if (this.isUrl(path)) {
  311. // need to find the first path separator
  312. var index = path.indexOf('/', root.length);
  313. if (index !== -1) {
  314. root = path.slice(0, index);
  315. }
  316. else
  317. { root = path; }
  318. if (!root.endsWith('/'))
  319. { root += '/'; }
  320. }
  321. return root;
  322. },
  323. /**
  324. * Returns the last portion of a path
  325. * @param path - The path to test
  326. * @param ext - Optional extension to remove
  327. */
  328. basename: function (path, ext) {
  329. assertPath(path);
  330. if (ext)
  331. { assertPath(ext); }
  332. path = this.toPosix(path);
  333. var start = 0;
  334. var end = -1;
  335. var matchedSlash = true;
  336. var i;
  337. if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
  338. if (ext.length === path.length && ext === path)
  339. { return ''; }
  340. var extIdx = ext.length - 1;
  341. var firstNonSlashEnd = -1;
  342. for (i = path.length - 1; i >= 0; --i) {
  343. var code = path.charCodeAt(i);
  344. if (code === 47) {
  345. // If we reached a path separator that was not part of a set of path
  346. // separators at the end of the string, stop now
  347. if (!matchedSlash) {
  348. start = i + 1;
  349. break;
  350. }
  351. }
  352. else {
  353. if (firstNonSlashEnd === -1) {
  354. // We saw the first non-path separator, remember this index in case
  355. // we need it if the extension ends up not matching
  356. matchedSlash = false;
  357. firstNonSlashEnd = i + 1;
  358. }
  359. if (extIdx >= 0) {
  360. // Try to match the explicit extension
  361. if (code === ext.charCodeAt(extIdx)) {
  362. if (--extIdx === -1) {
  363. // We matched the extension, so mark this as the end of our path
  364. // component
  365. end = i;
  366. }
  367. }
  368. else {
  369. // Extension does not match, so our result is the entire path
  370. // component
  371. extIdx = -1;
  372. end = firstNonSlashEnd;
  373. }
  374. }
  375. }
  376. }
  377. if (start === end)
  378. { end = firstNonSlashEnd; }
  379. else if (end === -1)
  380. { end = path.length; }
  381. return path.slice(start, end);
  382. }
  383. for (i = path.length - 1; i >= 0; --i) {
  384. if (path.charCodeAt(i) === 47) {
  385. // If we reached a path separator that was not part of a set of path
  386. // separators at the end of the string, stop now
  387. if (!matchedSlash) {
  388. start = i + 1;
  389. break;
  390. }
  391. }
  392. else if (end === -1) {
  393. // We saw the first non-path separator, mark this as the end of our
  394. // path component
  395. matchedSlash = false;
  396. end = i + 1;
  397. }
  398. }
  399. if (end === -1)
  400. { return ''; }
  401. return path.slice(start, end);
  402. },
  403. /**
  404. * Returns the extension of the path, from the last occurrence of the . (period) character to end of string in the last
  405. * portion of the path. If there is no . in the last portion of the path, or if there are no . characters other than
  406. * the first character of the basename of path, an empty string is returned.
  407. * @param path - The path to parse
  408. */
  409. extname: function (path) {
  410. assertPath(path);
  411. path = this.toPosix(path);
  412. var startDot = -1;
  413. var startPart = 0;
  414. var end = -1;
  415. var matchedSlash = true;
  416. // Track the state of characters (if any) we see before our first dot and
  417. // after any path separator we find
  418. var preDotState = 0;
  419. for (var i = path.length - 1; i >= 0; --i) {
  420. var code = path.charCodeAt(i);
  421. if (code === 47) {
  422. // If we reached a path separator that was not part of a set of path
  423. // separators at the end of the string, stop now
  424. if (!matchedSlash) {
  425. startPart = i + 1;
  426. break;
  427. }
  428. continue;
  429. }
  430. if (end === -1) {
  431. // We saw the first non-path separator, mark this as the end of our
  432. // extension
  433. matchedSlash = false;
  434. end = i + 1;
  435. }
  436. if (code === 46) {
  437. // If this is our first dot, mark it as the start of our extension
  438. if (startDot === -1)
  439. { startDot = i; }
  440. else if (preDotState !== 1)
  441. { preDotState = 1; }
  442. }
  443. else if (startDot !== -1) {
  444. // We saw a non-dot and non-path separator before our dot, so we should
  445. // have a good chance at having a non-empty extension
  446. preDotState = -1;
  447. }
  448. }
  449. if (startDot === -1 || end === -1
  450. // We saw a non-dot character immediately before the dot
  451. || preDotState === 0
  452. // The (right-most) trimmed path component is exactly '..'
  453. // eslint-disable-next-line no-mixed-operators
  454. || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
  455. return '';
  456. }
  457. return path.slice(startDot, end);
  458. },
  459. /**
  460. * Parses a path into an object containing the 'root', `dir`, `base`, `ext`, and `name` properties.
  461. * @param path - The path to parse
  462. */
  463. parse: function (path) {
  464. assertPath(path);
  465. var ret = { root: '', dir: '', base: '', ext: '', name: '' };
  466. if (path.length === 0)
  467. { return ret; }
  468. path = this.toPosix(path);
  469. var code = path.charCodeAt(0);
  470. var isAbsolute = this.isAbsolute(path);
  471. var start;
  472. ret.root = this.rootname(path);
  473. if (isAbsolute || this.hasProtocol(path)) {
  474. start = 1;
  475. }
  476. else {
  477. start = 0;
  478. }
  479. var startDot = -1;
  480. var startPart = 0;
  481. var end = -1;
  482. var matchedSlash = true;
  483. var i = path.length - 1;
  484. // Track the state of characters (if any) we see before our first dot and
  485. // after any path separator we find
  486. var preDotState = 0;
  487. // Get non-dir info
  488. for (; i >= start; --i) {
  489. code = path.charCodeAt(i);
  490. if (code === 47) {
  491. // If we reached a path separator that was not part of a set of path
  492. // separators at the end of the string, stop now
  493. if (!matchedSlash) {
  494. startPart = i + 1;
  495. break;
  496. }
  497. continue;
  498. }
  499. if (end === -1) {
  500. // We saw the first non-path separator, mark this as the end of our
  501. // extension
  502. matchedSlash = false;
  503. end = i + 1;
  504. }
  505. if (code === 46) {
  506. // If this is our first dot, mark it as the start of our extension
  507. if (startDot === -1)
  508. { startDot = i; }
  509. else if (preDotState !== 1)
  510. { preDotState = 1; }
  511. }
  512. else if (startDot !== -1) {
  513. // We saw a non-dot and non-path separator before our dot, so we should
  514. // have a good chance at having a non-empty extension
  515. preDotState = -1;
  516. }
  517. }
  518. if (startDot === -1 || end === -1
  519. // We saw a non-dot character immediately before the dot
  520. || preDotState === 0
  521. // The (right-most) trimmed path component is exactly '..'
  522. // eslint-disable-next-line no-mixed-operators
  523. || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
  524. if (end !== -1) {
  525. if (startPart === 0 && isAbsolute)
  526. { ret.base = ret.name = path.slice(1, end); }
  527. else
  528. { ret.base = ret.name = path.slice(startPart, end); }
  529. }
  530. }
  531. else {
  532. if (startPart === 0 && isAbsolute) {
  533. ret.name = path.slice(1, startDot);
  534. ret.base = path.slice(1, end);
  535. }
  536. else {
  537. ret.name = path.slice(startPart, startDot);
  538. ret.base = path.slice(startPart, end);
  539. }
  540. ret.ext = path.slice(startDot, end);
  541. }
  542. ret.dir = this.dirname(path);
  543. return ret;
  544. },
  545. sep: '/',
  546. delimiter: ':'
  547. };
  548. /**
  549. * The prefix that denotes a URL is for a retina asset.
  550. * @static
  551. * @name RETINA_PREFIX
  552. * @memberof PIXI.settings
  553. * @type {RegExp}
  554. * @default /@([0-9\.]+)x/
  555. * @example `@2x`
  556. */
  557. settings.RETINA_PREFIX = /@([0-9\.]+)x/;
  558. /**
  559. * Should the `failIfMajorPerformanceCaveat` flag be enabled as a context option used in the `isWebGLSupported` function.
  560. * If set to true, a WebGL renderer can fail to be created if the browser thinks there could be performance issues when
  561. * using WebGL.
  562. *
  563. * In PixiJS v6 this has changed from true to false by default, to allow WebGL to work in as many scenarios as possible.
  564. * However, some users may have a poor experience, for example, if a user has a gpu or driver version blacklisted by the
  565. * browser.
  566. *
  567. * If your application requires high performance rendering, you may wish to set this to false.
  568. * We recommend one of two options if you decide to set this flag to false:
  569. *
  570. * 1: Use the `pixi.js-legacy` package, which includes a Canvas renderer as a fallback in case high performance WebGL is
  571. * not supported.
  572. *
  573. * 2: Call `isWebGLSupported` (which if found in the PIXI.utils package) in your code before attempting to create a PixiJS
  574. * renderer, and show an error message to the user if the function returns false, explaining that their device & browser
  575. * combination does not support high performance WebGL.
  576. * This is a much better strategy than trying to create a PixiJS renderer and finding it then fails.
  577. * @static
  578. * @name FAIL_IF_MAJOR_PERFORMANCE_CAVEAT
  579. * @memberof PIXI.settings
  580. * @type {boolean}
  581. * @default false
  582. */
  583. settings.FAIL_IF_MAJOR_PERFORMANCE_CAVEAT = false;
  584. var saidHello = false;
  585. var VERSION = '6.5.10';
  586. /**
  587. * Skips the hello message of renderers that are created after this is run.
  588. * @function skipHello
  589. * @memberof PIXI.utils
  590. */
  591. function skipHello() {
  592. saidHello = true;
  593. }
  594. /**
  595. * Logs out the version and renderer information for this running instance of PIXI.
  596. * If you don't want to see this message you can run `PIXI.utils.skipHello()` before
  597. * creating your renderer. Keep in mind that doing that will forever make you a jerk face.
  598. * @static
  599. * @function sayHello
  600. * @memberof PIXI.utils
  601. * @param {string} type - The string renderer type to log.
  602. */
  603. function sayHello(type) {
  604. var _a;
  605. if (saidHello) {
  606. return;
  607. }
  608. if (settings.ADAPTER.getNavigator().userAgent.toLowerCase().indexOf('chrome') > -1) {
  609. var args = [
  610. "\n %c %c %c PixiJS " + VERSION + " - \u2730 " + type + " \u2730 %c %c http://www.pixijs.com/ %c %c \u2665%c\u2665%c\u2665 \n\n",
  611. 'background: #ff66a5; padding:5px 0;',
  612. 'background: #ff66a5; padding:5px 0;',
  613. 'color: #ff66a5; background: #030307; padding:5px 0;',
  614. 'background: #ff66a5; padding:5px 0;',
  615. 'background: #ffc3dc; padding:5px 0;',
  616. 'background: #ff66a5; padding:5px 0;',
  617. 'color: #ff2424; background: #fff; padding:5px 0;',
  618. 'color: #ff2424; background: #fff; padding:5px 0;',
  619. 'color: #ff2424; background: #fff; padding:5px 0;' ];
  620. (_a = globalThis.console).log.apply(_a, args);
  621. }
  622. else if (globalThis.console) {
  623. globalThis.console.log("PixiJS " + VERSION + " - " + type + " - http://www.pixijs.com/");
  624. }
  625. saidHello = true;
  626. }
  627. var supported;
  628. /**
  629. * Helper for checking for WebGL support.
  630. * @memberof PIXI.utils
  631. * @function isWebGLSupported
  632. * @returns {boolean} Is WebGL supported.
  633. */
  634. function isWebGLSupported() {
  635. if (typeof supported === 'undefined') {
  636. supported = (function supported() {
  637. var contextOptions = {
  638. stencil: true,
  639. failIfMajorPerformanceCaveat: settings.FAIL_IF_MAJOR_PERFORMANCE_CAVEAT,
  640. };
  641. try {
  642. if (!settings.ADAPTER.getWebGLRenderingContext()) {
  643. return false;
  644. }
  645. var canvas = settings.ADAPTER.createCanvas();
  646. var gl = (canvas.getContext('webgl', contextOptions)
  647. || canvas.getContext('experimental-webgl', contextOptions));
  648. var success = !!(gl && gl.getContextAttributes().stencil);
  649. if (gl) {
  650. var loseContext = gl.getExtension('WEBGL_lose_context');
  651. if (loseContext) {
  652. loseContext.loseContext();
  653. }
  654. }
  655. gl = null;
  656. return success;
  657. }
  658. catch (e) {
  659. return false;
  660. }
  661. })();
  662. }
  663. return supported;
  664. }
  665. var aliceblue = "#f0f8ff";
  666. var antiquewhite = "#faebd7";
  667. var aqua = "#00ffff";
  668. var aquamarine = "#7fffd4";
  669. var azure = "#f0ffff";
  670. var beige = "#f5f5dc";
  671. var bisque = "#ffe4c4";
  672. var black = "#000000";
  673. var blanchedalmond = "#ffebcd";
  674. var blue = "#0000ff";
  675. var blueviolet = "#8a2be2";
  676. var brown = "#a52a2a";
  677. var burlywood = "#deb887";
  678. var cadetblue = "#5f9ea0";
  679. var chartreuse = "#7fff00";
  680. var chocolate = "#d2691e";
  681. var coral = "#ff7f50";
  682. var cornflowerblue = "#6495ed";
  683. var cornsilk = "#fff8dc";
  684. var crimson = "#dc143c";
  685. var cyan = "#00ffff";
  686. var darkblue = "#00008b";
  687. var darkcyan = "#008b8b";
  688. var darkgoldenrod = "#b8860b";
  689. var darkgray = "#a9a9a9";
  690. var darkgreen = "#006400";
  691. var darkgrey = "#a9a9a9";
  692. var darkkhaki = "#bdb76b";
  693. var darkmagenta = "#8b008b";
  694. var darkolivegreen = "#556b2f";
  695. var darkorange = "#ff8c00";
  696. var darkorchid = "#9932cc";
  697. var darkred = "#8b0000";
  698. var darksalmon = "#e9967a";
  699. var darkseagreen = "#8fbc8f";
  700. var darkslateblue = "#483d8b";
  701. var darkslategray = "#2f4f4f";
  702. var darkslategrey = "#2f4f4f";
  703. var darkturquoise = "#00ced1";
  704. var darkviolet = "#9400d3";
  705. var deeppink = "#ff1493";
  706. var deepskyblue = "#00bfff";
  707. var dimgray = "#696969";
  708. var dimgrey = "#696969";
  709. var dodgerblue = "#1e90ff";
  710. var firebrick = "#b22222";
  711. var floralwhite = "#fffaf0";
  712. var forestgreen = "#228b22";
  713. var fuchsia = "#ff00ff";
  714. var gainsboro = "#dcdcdc";
  715. var ghostwhite = "#f8f8ff";
  716. var goldenrod = "#daa520";
  717. var gold = "#ffd700";
  718. var gray = "#808080";
  719. var green = "#008000";
  720. var greenyellow = "#adff2f";
  721. var grey = "#808080";
  722. var honeydew = "#f0fff0";
  723. var hotpink = "#ff69b4";
  724. var indianred = "#cd5c5c";
  725. var indigo = "#4b0082";
  726. var ivory = "#fffff0";
  727. var khaki = "#f0e68c";
  728. var lavenderblush = "#fff0f5";
  729. var lavender = "#e6e6fa";
  730. var lawngreen = "#7cfc00";
  731. var lemonchiffon = "#fffacd";
  732. var lightblue = "#add8e6";
  733. var lightcoral = "#f08080";
  734. var lightcyan = "#e0ffff";
  735. var lightgoldenrodyellow = "#fafad2";
  736. var lightgray = "#d3d3d3";
  737. var lightgreen = "#90ee90";
  738. var lightgrey = "#d3d3d3";
  739. var lightpink = "#ffb6c1";
  740. var lightsalmon = "#ffa07a";
  741. var lightseagreen = "#20b2aa";
  742. var lightskyblue = "#87cefa";
  743. var lightslategray = "#778899";
  744. var lightslategrey = "#778899";
  745. var lightsteelblue = "#b0c4de";
  746. var lightyellow = "#ffffe0";
  747. var lime = "#00ff00";
  748. var limegreen = "#32cd32";
  749. var linen = "#faf0e6";
  750. var magenta = "#ff00ff";
  751. var maroon = "#800000";
  752. var mediumaquamarine = "#66cdaa";
  753. var mediumblue = "#0000cd";
  754. var mediumorchid = "#ba55d3";
  755. var mediumpurple = "#9370db";
  756. var mediumseagreen = "#3cb371";
  757. var mediumslateblue = "#7b68ee";
  758. var mediumspringgreen = "#00fa9a";
  759. var mediumturquoise = "#48d1cc";
  760. var mediumvioletred = "#c71585";
  761. var midnightblue = "#191970";
  762. var mintcream = "#f5fffa";
  763. var mistyrose = "#ffe4e1";
  764. var moccasin = "#ffe4b5";
  765. var navajowhite = "#ffdead";
  766. var navy = "#000080";
  767. var oldlace = "#fdf5e6";
  768. var olive = "#808000";
  769. var olivedrab = "#6b8e23";
  770. var orange = "#ffa500";
  771. var orangered = "#ff4500";
  772. var orchid = "#da70d6";
  773. var palegoldenrod = "#eee8aa";
  774. var palegreen = "#98fb98";
  775. var paleturquoise = "#afeeee";
  776. var palevioletred = "#db7093";
  777. var papayawhip = "#ffefd5";
  778. var peachpuff = "#ffdab9";
  779. var peru = "#cd853f";
  780. var pink = "#ffc0cb";
  781. var plum = "#dda0dd";
  782. var powderblue = "#b0e0e6";
  783. var purple = "#800080";
  784. var rebeccapurple = "#663399";
  785. var red = "#ff0000";
  786. var rosybrown = "#bc8f8f";
  787. var royalblue = "#4169e1";
  788. var saddlebrown = "#8b4513";
  789. var salmon = "#fa8072";
  790. var sandybrown = "#f4a460";
  791. var seagreen = "#2e8b57";
  792. var seashell = "#fff5ee";
  793. var sienna = "#a0522d";
  794. var silver = "#c0c0c0";
  795. var skyblue = "#87ceeb";
  796. var slateblue = "#6a5acd";
  797. var slategray = "#708090";
  798. var slategrey = "#708090";
  799. var snow = "#fffafa";
  800. var springgreen = "#00ff7f";
  801. var steelblue = "#4682b4";
  802. var tan = "#d2b48c";
  803. var teal = "#008080";
  804. var thistle = "#d8bfd8";
  805. var tomato = "#ff6347";
  806. var turquoise = "#40e0d0";
  807. var violet = "#ee82ee";
  808. var wheat = "#f5deb3";
  809. var white = "#ffffff";
  810. var whitesmoke = "#f5f5f5";
  811. var yellow = "#ffff00";
  812. var yellowgreen = "#9acd32";
  813. var cssColorNames = {
  814. aliceblue: aliceblue,
  815. antiquewhite: antiquewhite,
  816. aqua: aqua,
  817. aquamarine: aquamarine,
  818. azure: azure,
  819. beige: beige,
  820. bisque: bisque,
  821. black: black,
  822. blanchedalmond: blanchedalmond,
  823. blue: blue,
  824. blueviolet: blueviolet,
  825. brown: brown,
  826. burlywood: burlywood,
  827. cadetblue: cadetblue,
  828. chartreuse: chartreuse,
  829. chocolate: chocolate,
  830. coral: coral,
  831. cornflowerblue: cornflowerblue,
  832. cornsilk: cornsilk,
  833. crimson: crimson,
  834. cyan: cyan,
  835. darkblue: darkblue,
  836. darkcyan: darkcyan,
  837. darkgoldenrod: darkgoldenrod,
  838. darkgray: darkgray,
  839. darkgreen: darkgreen,
  840. darkgrey: darkgrey,
  841. darkkhaki: darkkhaki,
  842. darkmagenta: darkmagenta,
  843. darkolivegreen: darkolivegreen,
  844. darkorange: darkorange,
  845. darkorchid: darkorchid,
  846. darkred: darkred,
  847. darksalmon: darksalmon,
  848. darkseagreen: darkseagreen,
  849. darkslateblue: darkslateblue,
  850. darkslategray: darkslategray,
  851. darkslategrey: darkslategrey,
  852. darkturquoise: darkturquoise,
  853. darkviolet: darkviolet,
  854. deeppink: deeppink,
  855. deepskyblue: deepskyblue,
  856. dimgray: dimgray,
  857. dimgrey: dimgrey,
  858. dodgerblue: dodgerblue,
  859. firebrick: firebrick,
  860. floralwhite: floralwhite,
  861. forestgreen: forestgreen,
  862. fuchsia: fuchsia,
  863. gainsboro: gainsboro,
  864. ghostwhite: ghostwhite,
  865. goldenrod: goldenrod,
  866. gold: gold,
  867. gray: gray,
  868. green: green,
  869. greenyellow: greenyellow,
  870. grey: grey,
  871. honeydew: honeydew,
  872. hotpink: hotpink,
  873. indianred: indianred,
  874. indigo: indigo,
  875. ivory: ivory,
  876. khaki: khaki,
  877. lavenderblush: lavenderblush,
  878. lavender: lavender,
  879. lawngreen: lawngreen,
  880. lemonchiffon: lemonchiffon,
  881. lightblue: lightblue,
  882. lightcoral: lightcoral,
  883. lightcyan: lightcyan,
  884. lightgoldenrodyellow: lightgoldenrodyellow,
  885. lightgray: lightgray,
  886. lightgreen: lightgreen,
  887. lightgrey: lightgrey,
  888. lightpink: lightpink,
  889. lightsalmon: lightsalmon,
  890. lightseagreen: lightseagreen,
  891. lightskyblue: lightskyblue,
  892. lightslategray: lightslategray,
  893. lightslategrey: lightslategrey,
  894. lightsteelblue: lightsteelblue,
  895. lightyellow: lightyellow,
  896. lime: lime,
  897. limegreen: limegreen,
  898. linen: linen,
  899. magenta: magenta,
  900. maroon: maroon,
  901. mediumaquamarine: mediumaquamarine,
  902. mediumblue: mediumblue,
  903. mediumorchid: mediumorchid,
  904. mediumpurple: mediumpurple,
  905. mediumseagreen: mediumseagreen,
  906. mediumslateblue: mediumslateblue,
  907. mediumspringgreen: mediumspringgreen,
  908. mediumturquoise: mediumturquoise,
  909. mediumvioletred: mediumvioletred,
  910. midnightblue: midnightblue,
  911. mintcream: mintcream,
  912. mistyrose: mistyrose,
  913. moccasin: moccasin,
  914. navajowhite: navajowhite,
  915. navy: navy,
  916. oldlace: oldlace,
  917. olive: olive,
  918. olivedrab: olivedrab,
  919. orange: orange,
  920. orangered: orangered,
  921. orchid: orchid,
  922. palegoldenrod: palegoldenrod,
  923. palegreen: palegreen,
  924. paleturquoise: paleturquoise,
  925. palevioletred: palevioletred,
  926. papayawhip: papayawhip,
  927. peachpuff: peachpuff,
  928. peru: peru,
  929. pink: pink,
  930. plum: plum,
  931. powderblue: powderblue,
  932. purple: purple,
  933. rebeccapurple: rebeccapurple,
  934. red: red,
  935. rosybrown: rosybrown,
  936. royalblue: royalblue,
  937. saddlebrown: saddlebrown,
  938. salmon: salmon,
  939. sandybrown: sandybrown,
  940. seagreen: seagreen,
  941. seashell: seashell,
  942. sienna: sienna,
  943. silver: silver,
  944. skyblue: skyblue,
  945. slateblue: slateblue,
  946. slategray: slategray,
  947. slategrey: slategrey,
  948. snow: snow,
  949. springgreen: springgreen,
  950. steelblue: steelblue,
  951. tan: tan,
  952. teal: teal,
  953. thistle: thistle,
  954. tomato: tomato,
  955. turquoise: turquoise,
  956. violet: violet,
  957. wheat: wheat,
  958. white: white,
  959. whitesmoke: whitesmoke,
  960. yellow: yellow,
  961. yellowgreen: yellowgreen
  962. };
  963. /**
  964. * Converts a hexadecimal color number to an [R, G, B] array of normalized floats (numbers from 0.0 to 1.0).
  965. * @example
  966. * PIXI.utils.hex2rgb(0xffffff); // returns [1, 1, 1]
  967. * @memberof PIXI.utils
  968. * @function hex2rgb
  969. * @param {number} hex - The hexadecimal number to convert
  970. * @param {number[]} [out=[]] - If supplied, this array will be used rather than returning a new one
  971. * @returns {number[]} An array representing the [R, G, B] of the color where all values are floats.
  972. */
  973. function hex2rgb(hex, out) {
  974. if (out === void 0) { out = []; }
  975. out[0] = ((hex >> 16) & 0xFF) / 255;
  976. out[1] = ((hex >> 8) & 0xFF) / 255;
  977. out[2] = (hex & 0xFF) / 255;
  978. return out;
  979. }
  980. /**
  981. * Converts a hexadecimal color number to a string.
  982. * @example
  983. * PIXI.utils.hex2string(0xffffff); // returns "#ffffff"
  984. * @memberof PIXI.utils
  985. * @function hex2string
  986. * @param {number} hex - Number in hex (e.g., `0xffffff`)
  987. * @returns {string} The string color (e.g., `"#ffffff"`).
  988. */
  989. function hex2string(hex) {
  990. var hexString = hex.toString(16);
  991. hexString = '000000'.substring(0, 6 - hexString.length) + hexString;
  992. return "#" + hexString;
  993. }
  994. /**
  995. * Converts a string to a hexadecimal color number.
  996. * It can handle:
  997. * hex strings starting with #: "#ffffff"
  998. * hex strings starting with 0x: "0xffffff"
  999. * hex strings without prefix: "ffffff"
  1000. * css colors: "black"
  1001. * @example
  1002. * PIXI.utils.string2hex("#ffffff"); // returns 0xffffff, which is 16777215 as an integer
  1003. * @memberof PIXI.utils
  1004. * @function string2hex
  1005. * @param {string} string - The string color (e.g., `"#ffffff"`)
  1006. * @returns {number} Number in hexadecimal.
  1007. */
  1008. function string2hex(string) {
  1009. if (typeof string === 'string') {
  1010. string = cssColorNames[string.toLowerCase()] || string;
  1011. if (string[0] === '#') {
  1012. string = string.slice(1);
  1013. }
  1014. }
  1015. return parseInt(string, 16);
  1016. }
  1017. /**
  1018. * Converts a color as an [R, G, B] array of normalized floats to a hexadecimal number.
  1019. * @example
  1020. * PIXI.utils.rgb2hex([1, 1, 1]); // returns 0xffffff, which is 16777215 as an integer
  1021. * @memberof PIXI.utils
  1022. * @function rgb2hex
  1023. * @param {number[]} rgb - Array of numbers where all values are normalized floats from 0.0 to 1.0.
  1024. * @returns {number} Number in hexadecimal.
  1025. */
  1026. function rgb2hex(rgb) {
  1027. return (((rgb[0] * 255) << 16) + ((rgb[1] * 255) << 8) + (rgb[2] * 255 | 0));
  1028. }
  1029. /**
  1030. * Corrects PixiJS blend, takes premultiplied alpha into account
  1031. * @memberof PIXI.utils
  1032. * @function mapPremultipliedBlendModes
  1033. * @private
  1034. * @returns {Array<number[]>} Mapped modes.
  1035. */
  1036. function mapPremultipliedBlendModes() {
  1037. var pm = [];
  1038. var npm = [];
  1039. for (var i = 0; i < 32; i++) {
  1040. pm[i] = i;
  1041. npm[i] = i;
  1042. }
  1043. pm[BLEND_MODES.NORMAL_NPM] = BLEND_MODES.NORMAL;
  1044. pm[BLEND_MODES.ADD_NPM] = BLEND_MODES.ADD;
  1045. pm[BLEND_MODES.SCREEN_NPM] = BLEND_MODES.SCREEN;
  1046. npm[BLEND_MODES.NORMAL] = BLEND_MODES.NORMAL_NPM;
  1047. npm[BLEND_MODES.ADD] = BLEND_MODES.ADD_NPM;
  1048. npm[BLEND_MODES.SCREEN] = BLEND_MODES.SCREEN_NPM;
  1049. var array = [];
  1050. array.push(npm);
  1051. array.push(pm);
  1052. return array;
  1053. }
  1054. /**
  1055. * maps premultiply flag and blendMode to adjusted blendMode
  1056. * @memberof PIXI.utils
  1057. * @constant premultiplyBlendMode
  1058. * @type {Array<number[]>}
  1059. */
  1060. var premultiplyBlendMode = mapPremultipliedBlendModes();
  1061. /**
  1062. * changes blendMode according to texture format
  1063. * @memberof PIXI.utils
  1064. * @function correctBlendMode
  1065. * @param {number} blendMode - supposed blend mode
  1066. * @param {boolean} premultiplied - whether source is premultiplied
  1067. * @returns {number} true blend mode for this texture
  1068. */
  1069. function correctBlendMode(blendMode, premultiplied) {
  1070. return premultiplyBlendMode[premultiplied ? 1 : 0][blendMode];
  1071. }
  1072. /**
  1073. * combines rgb and alpha to out array
  1074. * @memberof PIXI.utils
  1075. * @function premultiplyRgba
  1076. * @param {Float32Array|number[]} rgb - input rgb
  1077. * @param {number} alpha - alpha param
  1078. * @param {Float32Array} [out] - output
  1079. * @param {boolean} [premultiply=true] - do premultiply it
  1080. * @returns {Float32Array} vec4 rgba
  1081. */
  1082. function premultiplyRgba(rgb, alpha, out, premultiply) {
  1083. out = out || new Float32Array(4);
  1084. if (premultiply || premultiply === undefined) {
  1085. out[0] = rgb[0] * alpha;
  1086. out[1] = rgb[1] * alpha;
  1087. out[2] = rgb[2] * alpha;
  1088. }
  1089. else {
  1090. out[0] = rgb[0];
  1091. out[1] = rgb[1];
  1092. out[2] = rgb[2];
  1093. }
  1094. out[3] = alpha;
  1095. return out;
  1096. }
  1097. /**
  1098. * premultiplies tint
  1099. * @memberof PIXI.utils
  1100. * @function premultiplyTint
  1101. * @param {number} tint - integer RGB
  1102. * @param {number} alpha - floating point alpha (0.0-1.0)
  1103. * @returns {number} tint multiplied by alpha
  1104. */
  1105. function premultiplyTint(tint, alpha) {
  1106. if (alpha === 1.0) {
  1107. return (alpha * 255 << 24) + tint;
  1108. }
  1109. if (alpha === 0.0) {
  1110. return 0;
  1111. }
  1112. var R = ((tint >> 16) & 0xFF);
  1113. var G = ((tint >> 8) & 0xFF);
  1114. var B = (tint & 0xFF);
  1115. R = ((R * alpha) + 0.5) | 0;
  1116. G = ((G * alpha) + 0.5) | 0;
  1117. B = ((B * alpha) + 0.5) | 0;
  1118. return (alpha * 255 << 24) + (R << 16) + (G << 8) + B;
  1119. }
  1120. /**
  1121. * converts integer tint and float alpha to vec4 form, premultiplies by default
  1122. * @memberof PIXI.utils
  1123. * @function premultiplyTintToRgba
  1124. * @param {number} tint - input tint
  1125. * @param {number} alpha - alpha param
  1126. * @param {Float32Array} [out] - output
  1127. * @param {boolean} [premultiply=true] - do premultiply it
  1128. * @returns {Float32Array} vec4 rgba
  1129. */
  1130. function premultiplyTintToRgba(tint, alpha, out, premultiply) {
  1131. out = out || new Float32Array(4);
  1132. out[0] = ((tint >> 16) & 0xFF) / 255.0;
  1133. out[1] = ((tint >> 8) & 0xFF) / 255.0;
  1134. out[2] = (tint & 0xFF) / 255.0;
  1135. if (premultiply || premultiply === undefined) {
  1136. out[0] *= alpha;
  1137. out[1] *= alpha;
  1138. out[2] *= alpha;
  1139. }
  1140. out[3] = alpha;
  1141. return out;
  1142. }
  1143. /**
  1144. * Generic Mask Stack data structure
  1145. * @memberof PIXI.utils
  1146. * @function createIndicesForQuads
  1147. * @param {number} size - Number of quads
  1148. * @param {Uint16Array|Uint32Array} [outBuffer] - Buffer for output, length has to be `6 * size`
  1149. * @returns {Uint16Array|Uint32Array} - Resulting index buffer
  1150. */
  1151. function createIndicesForQuads(size, outBuffer) {
  1152. if (outBuffer === void 0) { outBuffer = null; }
  1153. // the total number of indices in our array, there are 6 points per quad.
  1154. var totalIndices = size * 6;
  1155. outBuffer = outBuffer || new Uint16Array(totalIndices);
  1156. if (outBuffer.length !== totalIndices) {
  1157. throw new Error("Out buffer length is incorrect, got " + outBuffer.length + " and expected " + totalIndices);
  1158. }
  1159. // fill the indices with the quads to draw
  1160. for (var i = 0, j = 0; i < totalIndices; i += 6, j += 4) {
  1161. outBuffer[i + 0] = j + 0;
  1162. outBuffer[i + 1] = j + 1;
  1163. outBuffer[i + 2] = j + 2;
  1164. outBuffer[i + 3] = j + 0;
  1165. outBuffer[i + 4] = j + 2;
  1166. outBuffer[i + 5] = j + 3;
  1167. }
  1168. return outBuffer;
  1169. }
  1170. function getBufferType(array) {
  1171. if (array.BYTES_PER_ELEMENT === 4) {
  1172. if (array instanceof Float32Array) {
  1173. return 'Float32Array';
  1174. }
  1175. else if (array instanceof Uint32Array) {
  1176. return 'Uint32Array';
  1177. }
  1178. return 'Int32Array';
  1179. }
  1180. else if (array.BYTES_PER_ELEMENT === 2) {
  1181. if (array instanceof Uint16Array) {
  1182. return 'Uint16Array';
  1183. }
  1184. }
  1185. else if (array.BYTES_PER_ELEMENT === 1) {
  1186. if (array instanceof Uint8Array) {
  1187. return 'Uint8Array';
  1188. }
  1189. }
  1190. // TODO map out the rest of the array elements!
  1191. return null;
  1192. }
  1193. /* eslint-disable object-shorthand */
  1194. var map = { Float32Array: Float32Array, Uint32Array: Uint32Array, Int32Array: Int32Array, Uint8Array: Uint8Array };
  1195. function interleaveTypedArrays(arrays, sizes) {
  1196. var outSize = 0;
  1197. var stride = 0;
  1198. var views = {};
  1199. for (var i = 0; i < arrays.length; i++) {
  1200. stride += sizes[i];
  1201. outSize += arrays[i].length;
  1202. }
  1203. var buffer = new ArrayBuffer(outSize * 4);
  1204. var out = null;
  1205. var littleOffset = 0;
  1206. for (var i = 0; i < arrays.length; i++) {
  1207. var size = sizes[i];
  1208. var array = arrays[i];
  1209. /*
  1210. @todo This is unsafe casting but consistent with how the code worked previously. Should it stay this way
  1211. or should and `getBufferTypeUnsafe` function be exposed that throws an Error if unsupported type is passed?
  1212. */
  1213. var type = getBufferType(array);
  1214. if (!views[type]) {
  1215. views[type] = new map[type](buffer);
  1216. }
  1217. out = views[type];
  1218. for (var j = 0; j < array.length; j++) {
  1219. var indexStart = ((j / size | 0) * stride) + littleOffset;
  1220. var index = j % size;
  1221. out[indexStart + index] = array[j];
  1222. }
  1223. littleOffset += size;
  1224. }
  1225. return new Float32Array(buffer);
  1226. }
  1227. // Taken from the bit-twiddle package
  1228. /**
  1229. * Rounds to next power of two.
  1230. * @function nextPow2
  1231. * @memberof PIXI.utils
  1232. * @param {number} v - input value
  1233. * @returns {number} - next rounded power of two
  1234. */
  1235. function nextPow2(v) {
  1236. v += v === 0 ? 1 : 0;
  1237. --v;
  1238. v |= v >>> 1;
  1239. v |= v >>> 2;
  1240. v |= v >>> 4;
  1241. v |= v >>> 8;
  1242. v |= v >>> 16;
  1243. return v + 1;
  1244. }
  1245. /**
  1246. * Checks if a number is a power of two.
  1247. * @function isPow2
  1248. * @memberof PIXI.utils
  1249. * @param {number} v - input value
  1250. * @returns {boolean} `true` if value is power of two
  1251. */
  1252. function isPow2(v) {
  1253. return !(v & (v - 1)) && (!!v);
  1254. }
  1255. /**
  1256. * Computes ceil of log base 2
  1257. * @function log2
  1258. * @memberof PIXI.utils
  1259. * @param {number} v - input value
  1260. * @returns {number} logarithm base 2
  1261. */
  1262. function log2(v) {
  1263. var r = (v > 0xFFFF ? 1 : 0) << 4;
  1264. v >>>= r;
  1265. var shift = (v > 0xFF ? 1 : 0) << 3;
  1266. v >>>= shift;
  1267. r |= shift;
  1268. shift = (v > 0xF ? 1 : 0) << 2;
  1269. v >>>= shift;
  1270. r |= shift;
  1271. shift = (v > 0x3 ? 1 : 0) << 1;
  1272. v >>>= shift;
  1273. r |= shift;
  1274. return r | (v >> 1);
  1275. }
  1276. /**
  1277. * Remove items from a javascript array without generating garbage
  1278. * @function removeItems
  1279. * @memberof PIXI.utils
  1280. * @param {Array<any>} arr - Array to remove elements from
  1281. * @param {number} startIdx - starting index
  1282. * @param {number} removeCount - how many to remove
  1283. */
  1284. function removeItems(arr, startIdx, removeCount) {
  1285. var length = arr.length;
  1286. var i;
  1287. if (startIdx >= length || removeCount === 0) {
  1288. return;
  1289. }
  1290. removeCount = (startIdx + removeCount > length ? length - startIdx : removeCount);
  1291. var len = length - removeCount;
  1292. for (i = startIdx; i < len; ++i) {
  1293. arr[i] = arr[i + removeCount];
  1294. }
  1295. arr.length = len;
  1296. }
  1297. /**
  1298. * Returns sign of number
  1299. * @memberof PIXI.utils
  1300. * @function sign
  1301. * @param {number} n - the number to check the sign of
  1302. * @returns {number} 0 if `n` is 0, -1 if `n` is negative, 1 if `n` is positive
  1303. */
  1304. function sign(n) {
  1305. if (n === 0)
  1306. { return 0; }
  1307. return n < 0 ? -1 : 1;
  1308. }
  1309. var nextUid = 0;
  1310. /**
  1311. * Gets the next unique identifier
  1312. * @memberof PIXI.utils
  1313. * @function uid
  1314. * @returns {number} The next unique identifier to use.
  1315. */
  1316. function uid() {
  1317. return ++nextUid;
  1318. }
  1319. // A map of warning messages already fired
  1320. var warnings = {};
  1321. /**
  1322. * Helper for warning developers about deprecated features & settings.
  1323. * A stack track for warnings is given; useful for tracking-down where
  1324. * deprecated methods/properties/classes are being used within the code.
  1325. * @memberof PIXI.utils
  1326. * @function deprecation
  1327. * @param {string} version - The version where the feature became deprecated
  1328. * @param {string} message - Message should include what is deprecated, where, and the new solution
  1329. * @param {number} [ignoreDepth=3] - The number of steps to ignore at the top of the error stack
  1330. * this is mostly to ignore internal deprecation calls.
  1331. */
  1332. function deprecation(version, message, ignoreDepth) {
  1333. if (ignoreDepth === void 0) { ignoreDepth = 3; }
  1334. // Ignore duplicat
  1335. if (warnings[message]) {
  1336. return;
  1337. }
  1338. /* eslint-disable no-console */
  1339. var stack = new Error().stack;
  1340. // Handle IE < 10 and Safari < 6
  1341. if (typeof stack === 'undefined') {
  1342. console.warn('PixiJS Deprecation Warning: ', message + "\nDeprecated since v" + version);
  1343. }
  1344. else {
  1345. // chop off the stack trace which includes PixiJS internal calls
  1346. stack = stack.split('\n').splice(ignoreDepth).join('\n');
  1347. if (console.groupCollapsed) {
  1348. console.groupCollapsed('%cPixiJS Deprecation Warning: %c%s', 'color:#614108;background:#fffbe6', 'font-weight:normal;color:#614108;background:#fffbe6', message + "\nDeprecated since v" + version);
  1349. console.warn(stack);
  1350. console.groupEnd();
  1351. }
  1352. else {
  1353. console.warn('PixiJS Deprecation Warning: ', message + "\nDeprecated since v" + version);
  1354. console.warn(stack);
  1355. }
  1356. }
  1357. /* eslint-enable no-console */
  1358. warnings[message] = true;
  1359. }
  1360. /**
  1361. * @todo Describe property usage
  1362. * @static
  1363. * @name ProgramCache
  1364. * @memberof PIXI.utils
  1365. * @type {object}
  1366. */
  1367. var ProgramCache = {};
  1368. /**
  1369. * @todo Describe property usage
  1370. * @static
  1371. * @name TextureCache
  1372. * @memberof PIXI.utils
  1373. * @type {object}
  1374. */
  1375. var TextureCache = Object.create(null);
  1376. /**
  1377. * @todo Describe property usage
  1378. * @static
  1379. * @name BaseTextureCache
  1380. * @memberof PIXI.utils
  1381. * @type {object}
  1382. */
  1383. var BaseTextureCache = Object.create(null);
  1384. /**
  1385. * Destroys all texture in the cache
  1386. * @memberof PIXI.utils
  1387. * @function destroyTextureCache
  1388. */
  1389. function destroyTextureCache() {
  1390. var key;
  1391. for (key in TextureCache) {
  1392. TextureCache[key].destroy();
  1393. }
  1394. for (key in BaseTextureCache) {
  1395. BaseTextureCache[key].destroy();
  1396. }
  1397. }
  1398. /**
  1399. * Removes all textures from cache, but does not destroy them
  1400. * @memberof PIXI.utils
  1401. * @function clearTextureCache
  1402. */
  1403. function clearTextureCache() {
  1404. var key;
  1405. for (key in TextureCache) {
  1406. delete TextureCache[key];
  1407. }
  1408. for (key in BaseTextureCache) {
  1409. delete BaseTextureCache[key];
  1410. }
  1411. }
  1412. /**
  1413. * Creates a Canvas element of the given size to be used as a target for rendering to.
  1414. * @class
  1415. * @memberof PIXI.utils
  1416. */
  1417. var CanvasRenderTarget = /** @class */ (function () {
  1418. /**
  1419. * @param width - the width for the newly created canvas
  1420. * @param height - the height for the newly created canvas
  1421. * @param {number} [resolution=PIXI.settings.RESOLUTION] - The resolution / device pixel ratio of the canvas
  1422. */
  1423. function CanvasRenderTarget(width, height, resolution) {
  1424. this.canvas = settings.ADAPTER.createCanvas();
  1425. this.context = this.canvas.getContext('2d');
  1426. this.resolution = resolution || settings.RESOLUTION;
  1427. this.resize(width, height);
  1428. }
  1429. /**
  1430. * Clears the canvas that was created by the CanvasRenderTarget class.
  1431. * @private
  1432. */
  1433. CanvasRenderTarget.prototype.clear = function () {
  1434. this.context.setTransform(1, 0, 0, 1, 0, 0);
  1435. this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
  1436. };
  1437. /**
  1438. * Resizes the canvas to the specified width and height.
  1439. * @param desiredWidth - the desired width of the canvas
  1440. * @param desiredHeight - the desired height of the canvas
  1441. */
  1442. CanvasRenderTarget.prototype.resize = function (desiredWidth, desiredHeight) {
  1443. this.canvas.width = Math.round(desiredWidth * this.resolution);
  1444. this.canvas.height = Math.round(desiredHeight * this.resolution);
  1445. };
  1446. /** Destroys this canvas. */
  1447. CanvasRenderTarget.prototype.destroy = function () {
  1448. this.context = null;
  1449. this.canvas = null;
  1450. };
  1451. Object.defineProperty(CanvasRenderTarget.prototype, "width", {
  1452. /**
  1453. * The width of the canvas buffer in pixels.
  1454. * @member {number}
  1455. */
  1456. get: function () {
  1457. return this.canvas.width;
  1458. },
  1459. set: function (val) {
  1460. this.canvas.width = Math.round(val);
  1461. },
  1462. enumerable: false,
  1463. configurable: true
  1464. });
  1465. Object.defineProperty(CanvasRenderTarget.prototype, "height", {
  1466. /**
  1467. * The height of the canvas buffer in pixels.
  1468. * @member {number}
  1469. */
  1470. get: function () {
  1471. return this.canvas.height;
  1472. },
  1473. set: function (val) {
  1474. this.canvas.height = Math.round(val);
  1475. },
  1476. enumerable: false,
  1477. configurable: true
  1478. });
  1479. return CanvasRenderTarget;
  1480. }());
  1481. /**
  1482. * Trim transparent borders from a canvas
  1483. * @memberof PIXI.utils
  1484. * @function trimCanvas
  1485. * @param {HTMLCanvasElement} canvas - the canvas to trim
  1486. * @returns {object} Trim data
  1487. */
  1488. function trimCanvas(canvas) {
  1489. // https://gist.github.com/remy/784508
  1490. var width = canvas.width;
  1491. var height = canvas.height;
  1492. var context = canvas.getContext('2d', {
  1493. willReadFrequently: true,
  1494. });
  1495. var imageData = context.getImageData(0, 0, width, height);
  1496. var pixels = imageData.data;
  1497. var len = pixels.length;
  1498. var bound = {
  1499. top: null,
  1500. left: null,
  1501. right: null,
  1502. bottom: null,
  1503. };
  1504. var data = null;
  1505. var i;
  1506. var x;
  1507. var y;
  1508. for (i = 0; i < len; i += 4) {
  1509. if (pixels[i + 3] !== 0) {
  1510. x = (i / 4) % width;
  1511. y = ~~((i / 4) / width);
  1512. if (bound.top === null) {
  1513. bound.top = y;
  1514. }
  1515. if (bound.left === null) {
  1516. bound.left = x;
  1517. }
  1518. else if (x < bound.left) {
  1519. bound.left = x;
  1520. }
  1521. if (bound.right === null) {
  1522. bound.right = x + 1;
  1523. }
  1524. else if (bound.right < x) {
  1525. bound.right = x + 1;
  1526. }
  1527. if (bound.bottom === null) {
  1528. bound.bottom = y;
  1529. }
  1530. else if (bound.bottom < y) {
  1531. bound.bottom = y;
  1532. }
  1533. }
  1534. }
  1535. if (bound.top !== null) {
  1536. width = bound.right - bound.left;
  1537. height = bound.bottom - bound.top + 1;
  1538. data = context.getImageData(bound.left, bound.top, width, height);
  1539. }
  1540. return {
  1541. height: height,
  1542. width: width,
  1543. data: data,
  1544. };
  1545. }
  1546. /**
  1547. * Regexp for data URI.
  1548. * Based on: {@link https://github.com/ragingwind/data-uri-regex}
  1549. * @static
  1550. * @constant {RegExp|string} DATA_URI
  1551. * @memberof PIXI
  1552. * @example data:image/png;base64
  1553. */
  1554. var DATA_URI = /^\s*data:(?:([\w-]+)\/([\w+.-]+))?(?:;charset=([\w-]+))?(?:;(base64))?,(.*)/i;
  1555. /**
  1556. * @memberof PIXI.utils
  1557. * @interface DecomposedDataUri
  1558. */
  1559. /**
  1560. * type, eg. `image`
  1561. * @memberof PIXI.utils.DecomposedDataUri#
  1562. * @member {string} mediaType
  1563. */
  1564. /**
  1565. * Sub type, eg. `png`
  1566. * @memberof PIXI.utils.DecomposedDataUri#
  1567. * @member {string} subType
  1568. */
  1569. /**
  1570. * @memberof PIXI.utils.DecomposedDataUri#
  1571. * @member {string} charset
  1572. */
  1573. /**
  1574. * Data encoding, eg. `base64`
  1575. * @memberof PIXI.utils.DecomposedDataUri#
  1576. * @member {string} encoding
  1577. */
  1578. /**
  1579. * The actual data
  1580. * @memberof PIXI.utils.DecomposedDataUri#
  1581. * @member {string} data
  1582. */
  1583. /**
  1584. * Split a data URI into components. Returns undefined if
  1585. * parameter `dataUri` is not a valid data URI.
  1586. * @memberof PIXI.utils
  1587. * @function decomposeDataUri
  1588. * @param {string} dataUri - the data URI to check
  1589. * @returns {PIXI.utils.DecomposedDataUri|undefined} The decomposed data uri or undefined
  1590. */
  1591. function decomposeDataUri(dataUri) {
  1592. var dataUriMatch = DATA_URI.exec(dataUri);
  1593. if (dataUriMatch) {
  1594. return {
  1595. mediaType: dataUriMatch[1] ? dataUriMatch[1].toLowerCase() : undefined,
  1596. subType: dataUriMatch[2] ? dataUriMatch[2].toLowerCase() : undefined,
  1597. charset: dataUriMatch[3] ? dataUriMatch[3].toLowerCase() : undefined,
  1598. encoding: dataUriMatch[4] ? dataUriMatch[4].toLowerCase() : undefined,
  1599. data: dataUriMatch[5],
  1600. };
  1601. }
  1602. return undefined;
  1603. }
  1604. var tempAnchor;
  1605. /**
  1606. * Sets the `crossOrigin` property for this resource based on if the url
  1607. * for this resource is cross-origin. If crossOrigin was manually set, this
  1608. * function does nothing.
  1609. * Nipped from the resource loader!
  1610. * @ignore
  1611. * @param {string} url - The url to test.
  1612. * @param {object} [loc=window.location] - The location object to test against.
  1613. * @returns {string} The crossOrigin value to use (or empty string for none).
  1614. */
  1615. function determineCrossOrigin(url$1, loc) {
  1616. if (loc === void 0) { loc = globalThis.location; }
  1617. // data: and javascript: urls are considered same-origin
  1618. if (url$1.indexOf('data:') === 0) {
  1619. return '';
  1620. }
  1621. // default is window.location
  1622. loc = loc || globalThis.location;
  1623. if (!tempAnchor) {
  1624. tempAnchor = document.createElement('a');
  1625. }
  1626. // let the browser determine the full href for the url of this resource and then
  1627. // parse with the node url lib, we can't use the properties of the anchor element
  1628. // because they don't work in IE9 :(
  1629. tempAnchor.href = url$1;
  1630. var parsedUrl = url.parse(tempAnchor.href);
  1631. var samePort = (!parsedUrl.port && loc.port === '') || (parsedUrl.port === loc.port);
  1632. // if cross origin
  1633. if (parsedUrl.hostname !== loc.hostname || !samePort || parsedUrl.protocol !== loc.protocol) {
  1634. return 'anonymous';
  1635. }
  1636. return '';
  1637. }
  1638. /**
  1639. * get the resolution / device pixel ratio of an asset by looking for the prefix
  1640. * used by spritesheets and image urls
  1641. * @memberof PIXI.utils
  1642. * @function getResolutionOfUrl
  1643. * @param {string} url - the image path
  1644. * @param {number} [defaultValue=1] - the defaultValue if no filename prefix is set.
  1645. * @returns {number} resolution / device pixel ratio of an asset
  1646. */
  1647. function getResolutionOfUrl(url, defaultValue) {
  1648. var resolution = settings.RETINA_PREFIX.exec(url);
  1649. if (resolution) {
  1650. return parseFloat(resolution[1]);
  1651. }
  1652. return defaultValue !== undefined ? defaultValue : 1;
  1653. }
  1654. export { BaseTextureCache, CanvasRenderTarget, DATA_URI, ProgramCache, TextureCache, clearTextureCache, correctBlendMode, createIndicesForQuads, decomposeDataUri, deprecation, destroyTextureCache, determineCrossOrigin, getBufferType, getResolutionOfUrl, hex2rgb, hex2string, interleaveTypedArrays, isPow2, isWebGLSupported, log2, nextPow2, path, premultiplyBlendMode, premultiplyRgba, premultiplyTint, premultiplyTintToRgba, removeItems, rgb2hex, sayHello, sign, skipHello, string2hex, trimCanvas, uid, url };
  1655. //# sourceMappingURL=utils.mjs.map