function.js 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2020 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * Javascript code in this page
  21. */
  22. "use strict";
  23. Object.defineProperty(exports, "__esModule", {
  24. value: true
  25. });
  26. exports.isPDFFunction = isPDFFunction;
  27. exports.PostScriptCompiler = exports.PostScriptEvaluator = exports.PDFFunctionFactory = void 0;
  28. var _primitives = require("./primitives.js");
  29. var _util = require("../shared/util.js");
  30. var _ps_parser = require("./ps_parser.js");
  31. var _image_utils = require("./image_utils.js");
  32. class PDFFunctionFactory {
  33. constructor({
  34. xref,
  35. isEvalSupported = true
  36. }) {
  37. this.xref = xref;
  38. this.isEvalSupported = isEvalSupported !== false;
  39. this._localFunctionCache = null;
  40. }
  41. create(fn) {
  42. const cachedFunction = this.getCached(fn);
  43. if (cachedFunction) {
  44. return cachedFunction;
  45. }
  46. const parsedFunction = PDFFunction.parse({
  47. xref: this.xref,
  48. isEvalSupported: this.isEvalSupported,
  49. fn: fn instanceof _primitives.Ref ? this.xref.fetch(fn) : fn
  50. });
  51. this._cache(fn, parsedFunction);
  52. return parsedFunction;
  53. }
  54. createFromArray(fnObj) {
  55. const cachedFunction = this.getCached(fnObj);
  56. if (cachedFunction) {
  57. return cachedFunction;
  58. }
  59. const parsedFunction = PDFFunction.parseArray({
  60. xref: this.xref,
  61. isEvalSupported: this.isEvalSupported,
  62. fnObj: fnObj instanceof _primitives.Ref ? this.xref.fetch(fnObj) : fnObj
  63. });
  64. this._cache(fnObj, parsedFunction);
  65. return parsedFunction;
  66. }
  67. getCached(cacheKey) {
  68. let fnRef;
  69. if (cacheKey instanceof _primitives.Ref) {
  70. fnRef = cacheKey;
  71. } else if (cacheKey instanceof _primitives.Dict) {
  72. fnRef = cacheKey.objId;
  73. } else if ((0, _primitives.isStream)(cacheKey)) {
  74. fnRef = cacheKey.dict && cacheKey.dict.objId;
  75. }
  76. if (fnRef) {
  77. if (!this._localFunctionCache) {
  78. this._localFunctionCache = new _image_utils.LocalFunctionCache();
  79. }
  80. const localFunction = this._localFunctionCache.getByRef(fnRef);
  81. if (localFunction) {
  82. return localFunction;
  83. }
  84. }
  85. return null;
  86. }
  87. _cache(cacheKey, parsedFunction) {
  88. if (!parsedFunction) {
  89. throw new Error('PDFFunctionFactory._cache - expected "parsedFunction" argument.');
  90. }
  91. let fnRef;
  92. if (cacheKey instanceof _primitives.Ref) {
  93. fnRef = cacheKey;
  94. } else if (cacheKey instanceof _primitives.Dict) {
  95. fnRef = cacheKey.objId;
  96. } else if ((0, _primitives.isStream)(cacheKey)) {
  97. fnRef = cacheKey.dict && cacheKey.dict.objId;
  98. }
  99. if (fnRef) {
  100. if (!this._localFunctionCache) {
  101. this._localFunctionCache = new _image_utils.LocalFunctionCache();
  102. }
  103. this._localFunctionCache.set(null, fnRef, parsedFunction);
  104. }
  105. }
  106. }
  107. exports.PDFFunctionFactory = PDFFunctionFactory;
  108. function toNumberArray(arr) {
  109. if (!Array.isArray(arr)) {
  110. return null;
  111. }
  112. const length = arr.length;
  113. for (let i = 0; i < length; i++) {
  114. if (typeof arr[i] !== "number") {
  115. const result = new Array(length);
  116. for (let j = 0; j < length; j++) {
  117. result[j] = +arr[j];
  118. }
  119. return result;
  120. }
  121. }
  122. return arr;
  123. }
  124. var PDFFunction = function PDFFunctionClosure() {
  125. const CONSTRUCT_SAMPLED = 0;
  126. const CONSTRUCT_INTERPOLATED = 2;
  127. const CONSTRUCT_STICHED = 3;
  128. const CONSTRUCT_POSTSCRIPT = 4;
  129. return {
  130. getSampleArray(size, outputSize, bps, stream) {
  131. var i, ii;
  132. var length = 1;
  133. for (i = 0, ii = size.length; i < ii; i++) {
  134. length *= size[i];
  135. }
  136. length *= outputSize;
  137. var array = new Array(length);
  138. var codeSize = 0;
  139. var codeBuf = 0;
  140. var sampleMul = 1.0 / (2.0 ** bps - 1);
  141. var strBytes = stream.getBytes((length * bps + 7) / 8);
  142. var strIdx = 0;
  143. for (i = 0; i < length; i++) {
  144. while (codeSize < bps) {
  145. codeBuf <<= 8;
  146. codeBuf |= strBytes[strIdx++];
  147. codeSize += 8;
  148. }
  149. codeSize -= bps;
  150. array[i] = (codeBuf >> codeSize) * sampleMul;
  151. codeBuf &= (1 << codeSize) - 1;
  152. }
  153. return array;
  154. },
  155. getIR({
  156. xref,
  157. isEvalSupported,
  158. fn
  159. }) {
  160. var dict = fn.dict;
  161. if (!dict) {
  162. dict = fn;
  163. }
  164. var types = [this.constructSampled, null, this.constructInterpolated, this.constructStiched, this.constructPostScript];
  165. var typeNum = dict.get("FunctionType");
  166. var typeFn = types[typeNum];
  167. if (!typeFn) {
  168. throw new _util.FormatError("Unknown type of function");
  169. }
  170. return typeFn.call(this, {
  171. xref,
  172. isEvalSupported,
  173. fn,
  174. dict
  175. });
  176. },
  177. fromIR({
  178. xref,
  179. isEvalSupported,
  180. IR
  181. }) {
  182. var type = IR[0];
  183. switch (type) {
  184. case CONSTRUCT_SAMPLED:
  185. return this.constructSampledFromIR({
  186. xref,
  187. isEvalSupported,
  188. IR
  189. });
  190. case CONSTRUCT_INTERPOLATED:
  191. return this.constructInterpolatedFromIR({
  192. xref,
  193. isEvalSupported,
  194. IR
  195. });
  196. case CONSTRUCT_STICHED:
  197. return this.constructStichedFromIR({
  198. xref,
  199. isEvalSupported,
  200. IR
  201. });
  202. default:
  203. return this.constructPostScriptFromIR({
  204. xref,
  205. isEvalSupported,
  206. IR
  207. });
  208. }
  209. },
  210. parse({
  211. xref,
  212. isEvalSupported,
  213. fn
  214. }) {
  215. const IR = this.getIR({
  216. xref,
  217. isEvalSupported,
  218. fn
  219. });
  220. return this.fromIR({
  221. xref,
  222. isEvalSupported,
  223. IR
  224. });
  225. },
  226. parseArray({
  227. xref,
  228. isEvalSupported,
  229. fnObj
  230. }) {
  231. if (!Array.isArray(fnObj)) {
  232. return this.parse({
  233. xref,
  234. isEvalSupported,
  235. fn: fnObj
  236. });
  237. }
  238. var fnArray = [];
  239. for (var j = 0, jj = fnObj.length; j < jj; j++) {
  240. fnArray.push(this.parse({
  241. xref,
  242. isEvalSupported,
  243. fn: xref.fetchIfRef(fnObj[j])
  244. }));
  245. }
  246. return function (src, srcOffset, dest, destOffset) {
  247. for (var i = 0, ii = fnArray.length; i < ii; i++) {
  248. fnArray[i](src, srcOffset, dest, destOffset + i);
  249. }
  250. };
  251. },
  252. constructSampled({
  253. xref,
  254. isEvalSupported,
  255. fn,
  256. dict
  257. }) {
  258. function toMultiArray(arr) {
  259. var inputLength = arr.length;
  260. var out = [];
  261. var index = 0;
  262. for (var i = 0; i < inputLength; i += 2) {
  263. out[index] = [arr[i], arr[i + 1]];
  264. ++index;
  265. }
  266. return out;
  267. }
  268. var domain = toNumberArray(dict.getArray("Domain"));
  269. var range = toNumberArray(dict.getArray("Range"));
  270. if (!domain || !range) {
  271. throw new _util.FormatError("No domain or range");
  272. }
  273. var inputSize = domain.length / 2;
  274. var outputSize = range.length / 2;
  275. domain = toMultiArray(domain);
  276. range = toMultiArray(range);
  277. var size = toNumberArray(dict.getArray("Size"));
  278. var bps = dict.get("BitsPerSample");
  279. var order = dict.get("Order") || 1;
  280. if (order !== 1) {
  281. (0, _util.info)("No support for cubic spline interpolation: " + order);
  282. }
  283. var encode = toNumberArray(dict.getArray("Encode"));
  284. if (!encode) {
  285. encode = [];
  286. for (var i = 0; i < inputSize; ++i) {
  287. encode.push([0, size[i] - 1]);
  288. }
  289. } else {
  290. encode = toMultiArray(encode);
  291. }
  292. var decode = toNumberArray(dict.getArray("Decode"));
  293. if (!decode) {
  294. decode = range;
  295. } else {
  296. decode = toMultiArray(decode);
  297. }
  298. var samples = this.getSampleArray(size, outputSize, bps, fn);
  299. return [CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size, outputSize, 2 ** bps - 1, range];
  300. },
  301. constructSampledFromIR({
  302. xref,
  303. isEvalSupported,
  304. IR
  305. }) {
  306. function interpolate(x, xmin, xmax, ymin, ymax) {
  307. return ymin + (x - xmin) * ((ymax - ymin) / (xmax - xmin));
  308. }
  309. return function constructSampledFromIRResult(src, srcOffset, dest, destOffset) {
  310. var m = IR[1];
  311. var domain = IR[2];
  312. var encode = IR[3];
  313. var decode = IR[4];
  314. var samples = IR[5];
  315. var size = IR[6];
  316. var n = IR[7];
  317. var range = IR[9];
  318. var cubeVertices = 1 << m;
  319. var cubeN = new Float64Array(cubeVertices);
  320. var cubeVertex = new Uint32Array(cubeVertices);
  321. var i, j;
  322. for (j = 0; j < cubeVertices; j++) {
  323. cubeN[j] = 1;
  324. }
  325. var k = n,
  326. pos = 1;
  327. for (i = 0; i < m; ++i) {
  328. var domain_2i = domain[i][0];
  329. var domain_2i_1 = domain[i][1];
  330. var xi = Math.min(Math.max(src[srcOffset + i], domain_2i), domain_2i_1);
  331. var e = interpolate(xi, domain_2i, domain_2i_1, encode[i][0], encode[i][1]);
  332. var size_i = size[i];
  333. e = Math.min(Math.max(e, 0), size_i - 1);
  334. var e0 = e < size_i - 1 ? Math.floor(e) : e - 1;
  335. var n0 = e0 + 1 - e;
  336. var n1 = e - e0;
  337. var offset0 = e0 * k;
  338. var offset1 = offset0 + k;
  339. for (j = 0; j < cubeVertices; j++) {
  340. if (j & pos) {
  341. cubeN[j] *= n1;
  342. cubeVertex[j] += offset1;
  343. } else {
  344. cubeN[j] *= n0;
  345. cubeVertex[j] += offset0;
  346. }
  347. }
  348. k *= size_i;
  349. pos <<= 1;
  350. }
  351. for (j = 0; j < n; ++j) {
  352. var rj = 0;
  353. for (i = 0; i < cubeVertices; i++) {
  354. rj += samples[cubeVertex[i] + j] * cubeN[i];
  355. }
  356. rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
  357. dest[destOffset + j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
  358. }
  359. };
  360. },
  361. constructInterpolated({
  362. xref,
  363. isEvalSupported,
  364. fn,
  365. dict
  366. }) {
  367. var c0 = toNumberArray(dict.getArray("C0")) || [0];
  368. var c1 = toNumberArray(dict.getArray("C1")) || [1];
  369. var n = dict.get("N");
  370. var length = c0.length;
  371. var diff = [];
  372. for (var i = 0; i < length; ++i) {
  373. diff.push(c1[i] - c0[i]);
  374. }
  375. return [CONSTRUCT_INTERPOLATED, c0, diff, n];
  376. },
  377. constructInterpolatedFromIR({
  378. xref,
  379. isEvalSupported,
  380. IR
  381. }) {
  382. var c0 = IR[1];
  383. var diff = IR[2];
  384. var n = IR[3];
  385. var length = diff.length;
  386. return function constructInterpolatedFromIRResult(src, srcOffset, dest, destOffset) {
  387. var x = n === 1 ? src[srcOffset] : src[srcOffset] ** n;
  388. for (var j = 0; j < length; ++j) {
  389. dest[destOffset + j] = c0[j] + x * diff[j];
  390. }
  391. };
  392. },
  393. constructStiched({
  394. xref,
  395. isEvalSupported,
  396. fn,
  397. dict
  398. }) {
  399. var domain = toNumberArray(dict.getArray("Domain"));
  400. if (!domain) {
  401. throw new _util.FormatError("No domain");
  402. }
  403. var inputSize = domain.length / 2;
  404. if (inputSize !== 1) {
  405. throw new _util.FormatError("Bad domain for stiched function");
  406. }
  407. var fnRefs = dict.get("Functions");
  408. var fns = [];
  409. for (var i = 0, ii = fnRefs.length; i < ii; ++i) {
  410. fns.push(this.parse({
  411. xref,
  412. isEvalSupported,
  413. fn: xref.fetchIfRef(fnRefs[i])
  414. }));
  415. }
  416. var bounds = toNumberArray(dict.getArray("Bounds"));
  417. var encode = toNumberArray(dict.getArray("Encode"));
  418. return [CONSTRUCT_STICHED, domain, bounds, encode, fns];
  419. },
  420. constructStichedFromIR({
  421. xref,
  422. isEvalSupported,
  423. IR
  424. }) {
  425. var domain = IR[1];
  426. var bounds = IR[2];
  427. var encode = IR[3];
  428. var fns = IR[4];
  429. var tmpBuf = new Float32Array(1);
  430. return function constructStichedFromIRResult(src, srcOffset, dest, destOffset) {
  431. var clip = function constructStichedFromIRClip(v, min, max) {
  432. if (v > max) {
  433. v = max;
  434. } else if (v < min) {
  435. v = min;
  436. }
  437. return v;
  438. };
  439. var v = clip(src[srcOffset], domain[0], domain[1]);
  440. for (var i = 0, ii = bounds.length; i < ii; ++i) {
  441. if (v < bounds[i]) {
  442. break;
  443. }
  444. }
  445. var dmin = domain[0];
  446. if (i > 0) {
  447. dmin = bounds[i - 1];
  448. }
  449. var dmax = domain[1];
  450. if (i < bounds.length) {
  451. dmax = bounds[i];
  452. }
  453. var rmin = encode[2 * i];
  454. var rmax = encode[2 * i + 1];
  455. tmpBuf[0] = dmin === dmax ? rmin : rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);
  456. fns[i](tmpBuf, 0, dest, destOffset);
  457. };
  458. },
  459. constructPostScript({
  460. xref,
  461. isEvalSupported,
  462. fn,
  463. dict
  464. }) {
  465. var domain = toNumberArray(dict.getArray("Domain"));
  466. var range = toNumberArray(dict.getArray("Range"));
  467. if (!domain) {
  468. throw new _util.FormatError("No domain.");
  469. }
  470. if (!range) {
  471. throw new _util.FormatError("No range.");
  472. }
  473. var lexer = new _ps_parser.PostScriptLexer(fn);
  474. var parser = new _ps_parser.PostScriptParser(lexer);
  475. var code = parser.parse();
  476. return [CONSTRUCT_POSTSCRIPT, domain, range, code];
  477. },
  478. constructPostScriptFromIR({
  479. xref,
  480. isEvalSupported,
  481. IR
  482. }) {
  483. var domain = IR[1];
  484. var range = IR[2];
  485. var code = IR[3];
  486. if (isEvalSupported && _util.IsEvalSupportedCached.value) {
  487. const compiled = new PostScriptCompiler().compile(code, domain, range);
  488. if (compiled) {
  489. return new Function("src", "srcOffset", "dest", "destOffset", compiled);
  490. }
  491. }
  492. (0, _util.info)("Unable to compile PS function");
  493. var numOutputs = range.length >> 1;
  494. var numInputs = domain.length >> 1;
  495. var evaluator = new PostScriptEvaluator(code);
  496. var cache = Object.create(null);
  497. var MAX_CACHE_SIZE = 2048 * 4;
  498. var cache_available = MAX_CACHE_SIZE;
  499. var tmpBuf = new Float32Array(numInputs);
  500. return function constructPostScriptFromIRResult(src, srcOffset, dest, destOffset) {
  501. var i, value;
  502. var key = "";
  503. var input = tmpBuf;
  504. for (i = 0; i < numInputs; i++) {
  505. value = src[srcOffset + i];
  506. input[i] = value;
  507. key += value + "_";
  508. }
  509. var cachedValue = cache[key];
  510. if (cachedValue !== undefined) {
  511. dest.set(cachedValue, destOffset);
  512. return;
  513. }
  514. var output = new Float32Array(numOutputs);
  515. var stack = evaluator.execute(input);
  516. var stackIndex = stack.length - numOutputs;
  517. for (i = 0; i < numOutputs; i++) {
  518. value = stack[stackIndex + i];
  519. var bound = range[i * 2];
  520. if (value < bound) {
  521. value = bound;
  522. } else {
  523. bound = range[i * 2 + 1];
  524. if (value > bound) {
  525. value = bound;
  526. }
  527. }
  528. output[i] = value;
  529. }
  530. if (cache_available > 0) {
  531. cache_available--;
  532. cache[key] = output;
  533. }
  534. dest.set(output, destOffset);
  535. };
  536. }
  537. };
  538. }();
  539. function isPDFFunction(v) {
  540. var fnDict;
  541. if (typeof v !== "object") {
  542. return false;
  543. } else if ((0, _primitives.isDict)(v)) {
  544. fnDict = v;
  545. } else if ((0, _primitives.isStream)(v)) {
  546. fnDict = v.dict;
  547. } else {
  548. return false;
  549. }
  550. return fnDict.has("FunctionType");
  551. }
  552. var PostScriptStack = function PostScriptStackClosure() {
  553. var MAX_STACK_SIZE = 100;
  554. function PostScriptStack(initialStack) {
  555. this.stack = !initialStack ? [] : Array.prototype.slice.call(initialStack, 0);
  556. }
  557. PostScriptStack.prototype = {
  558. push: function PostScriptStack_push(value) {
  559. if (this.stack.length >= MAX_STACK_SIZE) {
  560. throw new Error("PostScript function stack overflow.");
  561. }
  562. this.stack.push(value);
  563. },
  564. pop: function PostScriptStack_pop() {
  565. if (this.stack.length <= 0) {
  566. throw new Error("PostScript function stack underflow.");
  567. }
  568. return this.stack.pop();
  569. },
  570. copy: function PostScriptStack_copy(n) {
  571. if (this.stack.length + n >= MAX_STACK_SIZE) {
  572. throw new Error("PostScript function stack overflow.");
  573. }
  574. var stack = this.stack;
  575. for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) {
  576. stack.push(stack[i]);
  577. }
  578. },
  579. index: function PostScriptStack_index(n) {
  580. this.push(this.stack[this.stack.length - n - 1]);
  581. },
  582. roll: function PostScriptStack_roll(n, p) {
  583. var stack = this.stack;
  584. var l = stack.length - n;
  585. var r = stack.length - 1,
  586. c = l + (p - Math.floor(p / n) * n),
  587. i,
  588. j,
  589. t;
  590. for (i = l, j = r; i < j; i++, j--) {
  591. t = stack[i];
  592. stack[i] = stack[j];
  593. stack[j] = t;
  594. }
  595. for (i = l, j = c - 1; i < j; i++, j--) {
  596. t = stack[i];
  597. stack[i] = stack[j];
  598. stack[j] = t;
  599. }
  600. for (i = c, j = r; i < j; i++, j--) {
  601. t = stack[i];
  602. stack[i] = stack[j];
  603. stack[j] = t;
  604. }
  605. }
  606. };
  607. return PostScriptStack;
  608. }();
  609. var PostScriptEvaluator = function PostScriptEvaluatorClosure() {
  610. function PostScriptEvaluator(operators) {
  611. this.operators = operators;
  612. }
  613. PostScriptEvaluator.prototype = {
  614. execute: function PostScriptEvaluator_execute(initialStack) {
  615. var stack = new PostScriptStack(initialStack);
  616. var counter = 0;
  617. var operators = this.operators;
  618. var length = operators.length;
  619. var operator, a, b;
  620. while (counter < length) {
  621. operator = operators[counter++];
  622. if (typeof operator === "number") {
  623. stack.push(operator);
  624. continue;
  625. }
  626. switch (operator) {
  627. case "jz":
  628. b = stack.pop();
  629. a = stack.pop();
  630. if (!a) {
  631. counter = b;
  632. }
  633. break;
  634. case "j":
  635. a = stack.pop();
  636. counter = a;
  637. break;
  638. case "abs":
  639. a = stack.pop();
  640. stack.push(Math.abs(a));
  641. break;
  642. case "add":
  643. b = stack.pop();
  644. a = stack.pop();
  645. stack.push(a + b);
  646. break;
  647. case "and":
  648. b = stack.pop();
  649. a = stack.pop();
  650. if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
  651. stack.push(a && b);
  652. } else {
  653. stack.push(a & b);
  654. }
  655. break;
  656. case "atan":
  657. a = stack.pop();
  658. stack.push(Math.atan(a));
  659. break;
  660. case "bitshift":
  661. b = stack.pop();
  662. a = stack.pop();
  663. if (a > 0) {
  664. stack.push(a << b);
  665. } else {
  666. stack.push(a >> b);
  667. }
  668. break;
  669. case "ceiling":
  670. a = stack.pop();
  671. stack.push(Math.ceil(a));
  672. break;
  673. case "copy":
  674. a = stack.pop();
  675. stack.copy(a);
  676. break;
  677. case "cos":
  678. a = stack.pop();
  679. stack.push(Math.cos(a));
  680. break;
  681. case "cvi":
  682. a = stack.pop() | 0;
  683. stack.push(a);
  684. break;
  685. case "cvr":
  686. break;
  687. case "div":
  688. b = stack.pop();
  689. a = stack.pop();
  690. stack.push(a / b);
  691. break;
  692. case "dup":
  693. stack.copy(1);
  694. break;
  695. case "eq":
  696. b = stack.pop();
  697. a = stack.pop();
  698. stack.push(a === b);
  699. break;
  700. case "exch":
  701. stack.roll(2, 1);
  702. break;
  703. case "exp":
  704. b = stack.pop();
  705. a = stack.pop();
  706. stack.push(a ** b);
  707. break;
  708. case "false":
  709. stack.push(false);
  710. break;
  711. case "floor":
  712. a = stack.pop();
  713. stack.push(Math.floor(a));
  714. break;
  715. case "ge":
  716. b = stack.pop();
  717. a = stack.pop();
  718. stack.push(a >= b);
  719. break;
  720. case "gt":
  721. b = stack.pop();
  722. a = stack.pop();
  723. stack.push(a > b);
  724. break;
  725. case "idiv":
  726. b = stack.pop();
  727. a = stack.pop();
  728. stack.push(a / b | 0);
  729. break;
  730. case "index":
  731. a = stack.pop();
  732. stack.index(a);
  733. break;
  734. case "le":
  735. b = stack.pop();
  736. a = stack.pop();
  737. stack.push(a <= b);
  738. break;
  739. case "ln":
  740. a = stack.pop();
  741. stack.push(Math.log(a));
  742. break;
  743. case "log":
  744. a = stack.pop();
  745. stack.push(Math.log(a) / Math.LN10);
  746. break;
  747. case "lt":
  748. b = stack.pop();
  749. a = stack.pop();
  750. stack.push(a < b);
  751. break;
  752. case "mod":
  753. b = stack.pop();
  754. a = stack.pop();
  755. stack.push(a % b);
  756. break;
  757. case "mul":
  758. b = stack.pop();
  759. a = stack.pop();
  760. stack.push(a * b);
  761. break;
  762. case "ne":
  763. b = stack.pop();
  764. a = stack.pop();
  765. stack.push(a !== b);
  766. break;
  767. case "neg":
  768. a = stack.pop();
  769. stack.push(-a);
  770. break;
  771. case "not":
  772. a = stack.pop();
  773. if ((0, _util.isBool)(a)) {
  774. stack.push(!a);
  775. } else {
  776. stack.push(~a);
  777. }
  778. break;
  779. case "or":
  780. b = stack.pop();
  781. a = stack.pop();
  782. if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
  783. stack.push(a || b);
  784. } else {
  785. stack.push(a | b);
  786. }
  787. break;
  788. case "pop":
  789. stack.pop();
  790. break;
  791. case "roll":
  792. b = stack.pop();
  793. a = stack.pop();
  794. stack.roll(a, b);
  795. break;
  796. case "round":
  797. a = stack.pop();
  798. stack.push(Math.round(a));
  799. break;
  800. case "sin":
  801. a = stack.pop();
  802. stack.push(Math.sin(a));
  803. break;
  804. case "sqrt":
  805. a = stack.pop();
  806. stack.push(Math.sqrt(a));
  807. break;
  808. case "sub":
  809. b = stack.pop();
  810. a = stack.pop();
  811. stack.push(a - b);
  812. break;
  813. case "true":
  814. stack.push(true);
  815. break;
  816. case "truncate":
  817. a = stack.pop();
  818. a = a < 0 ? Math.ceil(a) : Math.floor(a);
  819. stack.push(a);
  820. break;
  821. case "xor":
  822. b = stack.pop();
  823. a = stack.pop();
  824. if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
  825. stack.push(a !== b);
  826. } else {
  827. stack.push(a ^ b);
  828. }
  829. break;
  830. default:
  831. throw new _util.FormatError(`Unknown operator ${operator}`);
  832. }
  833. }
  834. return stack.stack;
  835. }
  836. };
  837. return PostScriptEvaluator;
  838. }();
  839. exports.PostScriptEvaluator = PostScriptEvaluator;
  840. var PostScriptCompiler = function PostScriptCompilerClosure() {
  841. function AstNode(type) {
  842. this.type = type;
  843. }
  844. AstNode.prototype.visit = function (visitor) {
  845. (0, _util.unreachable)("abstract method");
  846. };
  847. function AstArgument(index, min, max) {
  848. AstNode.call(this, "args");
  849. this.index = index;
  850. this.min = min;
  851. this.max = max;
  852. }
  853. AstArgument.prototype = Object.create(AstNode.prototype);
  854. AstArgument.prototype.visit = function (visitor) {
  855. visitor.visitArgument(this);
  856. };
  857. function AstLiteral(number) {
  858. AstNode.call(this, "literal");
  859. this.number = number;
  860. this.min = number;
  861. this.max = number;
  862. }
  863. AstLiteral.prototype = Object.create(AstNode.prototype);
  864. AstLiteral.prototype.visit = function (visitor) {
  865. visitor.visitLiteral(this);
  866. };
  867. function AstBinaryOperation(op, arg1, arg2, min, max) {
  868. AstNode.call(this, "binary");
  869. this.op = op;
  870. this.arg1 = arg1;
  871. this.arg2 = arg2;
  872. this.min = min;
  873. this.max = max;
  874. }
  875. AstBinaryOperation.prototype = Object.create(AstNode.prototype);
  876. AstBinaryOperation.prototype.visit = function (visitor) {
  877. visitor.visitBinaryOperation(this);
  878. };
  879. function AstMin(arg, max) {
  880. AstNode.call(this, "max");
  881. this.arg = arg;
  882. this.min = arg.min;
  883. this.max = max;
  884. }
  885. AstMin.prototype = Object.create(AstNode.prototype);
  886. AstMin.prototype.visit = function (visitor) {
  887. visitor.visitMin(this);
  888. };
  889. function AstVariable(index, min, max) {
  890. AstNode.call(this, "var");
  891. this.index = index;
  892. this.min = min;
  893. this.max = max;
  894. }
  895. AstVariable.prototype = Object.create(AstNode.prototype);
  896. AstVariable.prototype.visit = function (visitor) {
  897. visitor.visitVariable(this);
  898. };
  899. function AstVariableDefinition(variable, arg) {
  900. AstNode.call(this, "definition");
  901. this.variable = variable;
  902. this.arg = arg;
  903. }
  904. AstVariableDefinition.prototype = Object.create(AstNode.prototype);
  905. AstVariableDefinition.prototype.visit = function (visitor) {
  906. visitor.visitVariableDefinition(this);
  907. };
  908. function ExpressionBuilderVisitor() {
  909. this.parts = [];
  910. }
  911. ExpressionBuilderVisitor.prototype = {
  912. visitArgument(arg) {
  913. this.parts.push("Math.max(", arg.min, ", Math.min(", arg.max, ", src[srcOffset + ", arg.index, "]))");
  914. },
  915. visitVariable(variable) {
  916. this.parts.push("v", variable.index);
  917. },
  918. visitLiteral(literal) {
  919. this.parts.push(literal.number);
  920. },
  921. visitBinaryOperation(operation) {
  922. this.parts.push("(");
  923. operation.arg1.visit(this);
  924. this.parts.push(" ", operation.op, " ");
  925. operation.arg2.visit(this);
  926. this.parts.push(")");
  927. },
  928. visitVariableDefinition(definition) {
  929. this.parts.push("var ");
  930. definition.variable.visit(this);
  931. this.parts.push(" = ");
  932. definition.arg.visit(this);
  933. this.parts.push(";");
  934. },
  935. visitMin(max) {
  936. this.parts.push("Math.min(");
  937. max.arg.visit(this);
  938. this.parts.push(", ", max.max, ")");
  939. },
  940. toString() {
  941. return this.parts.join("");
  942. }
  943. };
  944. function buildAddOperation(num1, num2) {
  945. if (num2.type === "literal" && num2.number === 0) {
  946. return num1;
  947. }
  948. if (num1.type === "literal" && num1.number === 0) {
  949. return num2;
  950. }
  951. if (num2.type === "literal" && num1.type === "literal") {
  952. return new AstLiteral(num1.number + num2.number);
  953. }
  954. return new AstBinaryOperation("+", num1, num2, num1.min + num2.min, num1.max + num2.max);
  955. }
  956. function buildMulOperation(num1, num2) {
  957. if (num2.type === "literal") {
  958. if (num2.number === 0) {
  959. return new AstLiteral(0);
  960. } else if (num2.number === 1) {
  961. return num1;
  962. } else if (num1.type === "literal") {
  963. return new AstLiteral(num1.number * num2.number);
  964. }
  965. }
  966. if (num1.type === "literal") {
  967. if (num1.number === 0) {
  968. return new AstLiteral(0);
  969. } else if (num1.number === 1) {
  970. return num2;
  971. }
  972. }
  973. var min = Math.min(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max);
  974. var max = Math.max(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max);
  975. return new AstBinaryOperation("*", num1, num2, min, max);
  976. }
  977. function buildSubOperation(num1, num2) {
  978. if (num2.type === "literal") {
  979. if (num2.number === 0) {
  980. return num1;
  981. } else if (num1.type === "literal") {
  982. return new AstLiteral(num1.number - num2.number);
  983. }
  984. }
  985. if (num2.type === "binary" && num2.op === "-" && num1.type === "literal" && num1.number === 1 && num2.arg1.type === "literal" && num2.arg1.number === 1) {
  986. return num2.arg2;
  987. }
  988. return new AstBinaryOperation("-", num1, num2, num1.min - num2.max, num1.max - num2.min);
  989. }
  990. function buildMinOperation(num1, max) {
  991. if (num1.min >= max) {
  992. return new AstLiteral(max);
  993. } else if (num1.max <= max) {
  994. return num1;
  995. }
  996. return new AstMin(num1, max);
  997. }
  998. function PostScriptCompiler() {}
  999. PostScriptCompiler.prototype = {
  1000. compile: function PostScriptCompiler_compile(code, domain, range) {
  1001. var stack = [];
  1002. var instructions = [];
  1003. var inputSize = domain.length >> 1,
  1004. outputSize = range.length >> 1;
  1005. var lastRegister = 0;
  1006. var n, j;
  1007. var num1, num2, ast1, ast2, tmpVar, item;
  1008. for (let i = 0; i < inputSize; i++) {
  1009. stack.push(new AstArgument(i, domain[i * 2], domain[i * 2 + 1]));
  1010. }
  1011. for (let i = 0, ii = code.length; i < ii; i++) {
  1012. item = code[i];
  1013. if (typeof item === "number") {
  1014. stack.push(new AstLiteral(item));
  1015. continue;
  1016. }
  1017. switch (item) {
  1018. case "add":
  1019. if (stack.length < 2) {
  1020. return null;
  1021. }
  1022. num2 = stack.pop();
  1023. num1 = stack.pop();
  1024. stack.push(buildAddOperation(num1, num2));
  1025. break;
  1026. case "cvr":
  1027. if (stack.length < 1) {
  1028. return null;
  1029. }
  1030. break;
  1031. case "mul":
  1032. if (stack.length < 2) {
  1033. return null;
  1034. }
  1035. num2 = stack.pop();
  1036. num1 = stack.pop();
  1037. stack.push(buildMulOperation(num1, num2));
  1038. break;
  1039. case "sub":
  1040. if (stack.length < 2) {
  1041. return null;
  1042. }
  1043. num2 = stack.pop();
  1044. num1 = stack.pop();
  1045. stack.push(buildSubOperation(num1, num2));
  1046. break;
  1047. case "exch":
  1048. if (stack.length < 2) {
  1049. return null;
  1050. }
  1051. ast1 = stack.pop();
  1052. ast2 = stack.pop();
  1053. stack.push(ast1, ast2);
  1054. break;
  1055. case "pop":
  1056. if (stack.length < 1) {
  1057. return null;
  1058. }
  1059. stack.pop();
  1060. break;
  1061. case "index":
  1062. if (stack.length < 1) {
  1063. return null;
  1064. }
  1065. num1 = stack.pop();
  1066. if (num1.type !== "literal") {
  1067. return null;
  1068. }
  1069. n = num1.number;
  1070. if (n < 0 || !Number.isInteger(n) || stack.length < n) {
  1071. return null;
  1072. }
  1073. ast1 = stack[stack.length - n - 1];
  1074. if (ast1.type === "literal" || ast1.type === "var") {
  1075. stack.push(ast1);
  1076. break;
  1077. }
  1078. tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);
  1079. stack[stack.length - n - 1] = tmpVar;
  1080. stack.push(tmpVar);
  1081. instructions.push(new AstVariableDefinition(tmpVar, ast1));
  1082. break;
  1083. case "dup":
  1084. if (stack.length < 1) {
  1085. return null;
  1086. }
  1087. if (typeof code[i + 1] === "number" && code[i + 2] === "gt" && code[i + 3] === i + 7 && code[i + 4] === "jz" && code[i + 5] === "pop" && code[i + 6] === code[i + 1]) {
  1088. num1 = stack.pop();
  1089. stack.push(buildMinOperation(num1, code[i + 1]));
  1090. i += 6;
  1091. break;
  1092. }
  1093. ast1 = stack[stack.length - 1];
  1094. if (ast1.type === "literal" || ast1.type === "var") {
  1095. stack.push(ast1);
  1096. break;
  1097. }
  1098. tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);
  1099. stack[stack.length - 1] = tmpVar;
  1100. stack.push(tmpVar);
  1101. instructions.push(new AstVariableDefinition(tmpVar, ast1));
  1102. break;
  1103. case "roll":
  1104. if (stack.length < 2) {
  1105. return null;
  1106. }
  1107. num2 = stack.pop();
  1108. num1 = stack.pop();
  1109. if (num2.type !== "literal" || num1.type !== "literal") {
  1110. return null;
  1111. }
  1112. j = num2.number;
  1113. n = num1.number;
  1114. if (n <= 0 || !Number.isInteger(n) || !Number.isInteger(j) || stack.length < n) {
  1115. return null;
  1116. }
  1117. j = (j % n + n) % n;
  1118. if (j === 0) {
  1119. break;
  1120. }
  1121. Array.prototype.push.apply(stack, stack.splice(stack.length - n, n - j));
  1122. break;
  1123. default:
  1124. return null;
  1125. }
  1126. }
  1127. if (stack.length !== outputSize) {
  1128. return null;
  1129. }
  1130. var result = [];
  1131. instructions.forEach(function (instruction) {
  1132. var statementBuilder = new ExpressionBuilderVisitor();
  1133. instruction.visit(statementBuilder);
  1134. result.push(statementBuilder.toString());
  1135. });
  1136. stack.forEach(function (expr, i) {
  1137. var statementBuilder = new ExpressionBuilderVisitor();
  1138. expr.visit(statementBuilder);
  1139. var min = range[i * 2],
  1140. max = range[i * 2 + 1];
  1141. var out = [statementBuilder.toString()];
  1142. if (min > expr.min) {
  1143. out.unshift("Math.max(", min, ", ");
  1144. out.push(")");
  1145. }
  1146. if (max < expr.max) {
  1147. out.unshift("Math.min(", max, ", ");
  1148. out.push(")");
  1149. }
  1150. out.unshift("dest[destOffset + ", i, "] = ");
  1151. out.push(";");
  1152. result.push(out.join(""));
  1153. });
  1154. return result.join("\n");
  1155. }
  1156. };
  1157. return PostScriptCompiler;
  1158. }();
  1159. exports.PostScriptCompiler = PostScriptCompiler;