2
0

function_spec.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. /* Copyright 2017 Mozilla Foundation
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. 'use strict';
  16. var coreFunction = require('../../core/function.js');
  17. var corePsParser = require('../../core/ps_parser.js');
  18. var coreStream = require('../../core/stream.js');
  19. var sharedUtil = require('../../shared/util.js');
  20. var PostScriptEvaluator = coreFunction.PostScriptEvaluator;
  21. var PostScriptCompiler = coreFunction.PostScriptCompiler;
  22. var PostScriptParser = corePsParser.PostScriptParser;
  23. var PostScriptLexer = corePsParser.PostScriptLexer;
  24. var StringStream = coreStream.StringStream;
  25. var isArray = sharedUtil.isArray;
  26. describe('function', function () {
  27. beforeEach(function () {
  28. jasmine.addMatchers({
  29. toMatchArray: function (util, customEqualityTesters) {
  30. return {
  31. compare: function (actual, expected) {
  32. var result = {};
  33. if (actual.length !== expected.length) {
  34. result.pass = false;
  35. result.message = 'Array length: ' + actual.length + ', expected: ' + expected.length;
  36. return result;
  37. }
  38. result.pass = true;
  39. for (var i = 0; i < expected.length; i++) {
  40. var a = actual[i],
  41. b = expected[i];
  42. if (isArray(b)) {
  43. if (a.length !== b.length) {
  44. result.pass = false;
  45. break;
  46. }
  47. for (var j = 0; j < a.length; j++) {
  48. var suba = a[j],
  49. subb = b[j];
  50. if (suba !== subb) {
  51. result.pass = false;
  52. break;
  53. }
  54. }
  55. } else {
  56. if (a !== b) {
  57. result.pass = false;
  58. break;
  59. }
  60. }
  61. }
  62. return result;
  63. }
  64. };
  65. }
  66. });
  67. });
  68. describe('PostScriptParser', function () {
  69. function parse(program) {
  70. var stream = new StringStream(program);
  71. var parser = new PostScriptParser(new PostScriptLexer(stream));
  72. return parser.parse();
  73. }
  74. it('parses empty programs', function () {
  75. var output = parse('{}');
  76. expect(output.length).toEqual(0);
  77. });
  78. it('parses positive numbers', function () {
  79. var number = 999;
  80. var program = parse('{ ' + number + ' }');
  81. var expectedProgram = [number];
  82. expect(program).toMatchArray(expectedProgram);
  83. });
  84. it('parses negative numbers', function () {
  85. var number = -999;
  86. var program = parse('{ ' + number + ' }');
  87. var expectedProgram = [number];
  88. expect(program).toMatchArray(expectedProgram);
  89. });
  90. it('parses negative floats', function () {
  91. var number = 3.3;
  92. var program = parse('{ ' + number + ' }');
  93. var expectedProgram = [number];
  94. expect(program).toMatchArray(expectedProgram);
  95. });
  96. it('parses operators', function () {
  97. var program = parse('{ sub }');
  98. var expectedProgram = ['sub'];
  99. expect(program).toMatchArray(expectedProgram);
  100. });
  101. it('parses if statements', function () {
  102. var program = parse('{ { 99 } if }');
  103. var expectedProgram = [3, 'jz', 99];
  104. expect(program).toMatchArray(expectedProgram);
  105. });
  106. it('parses ifelse statements', function () {
  107. var program = parse('{ { 99 } { 44 } ifelse }');
  108. var expectedProgram = [5, 'jz', 99, 6, 'j', 44];
  109. expect(program).toMatchArray(expectedProgram);
  110. });
  111. it('handles missing brackets', function () {
  112. expect(function () {
  113. parse('{');
  114. }).toThrow(new Error('Unexpected symbol: found undefined expected 1.'));
  115. });
  116. it('handles junk after the end', function () {
  117. var number = 3.3;
  118. var program = parse('{ ' + number + ' }#');
  119. var expectedProgram = [number];
  120. expect(program).toMatchArray(expectedProgram);
  121. });
  122. });
  123. describe('PostScriptEvaluator', function () {
  124. function evaluate(program) {
  125. var stream = new StringStream(program);
  126. var parser = new PostScriptParser(new PostScriptLexer(stream));
  127. var code = parser.parse();
  128. var evaluator = new PostScriptEvaluator(code);
  129. var output = evaluator.execute();
  130. return output;
  131. }
  132. it('pushes stack', function () {
  133. var stack = evaluate('{ 99 }');
  134. var expectedStack = [99];
  135. expect(stack).toMatchArray(expectedStack);
  136. });
  137. it('handles if with true', function () {
  138. var stack = evaluate('{ 1 {99} if }');
  139. var expectedStack = [99];
  140. expect(stack).toMatchArray(expectedStack);
  141. });
  142. it('handles if with false', function () {
  143. var stack = evaluate('{ 0 {99} if }');
  144. var expectedStack = [];
  145. expect(stack).toMatchArray(expectedStack);
  146. });
  147. it('handles ifelse with true', function () {
  148. var stack = evaluate('{ 1 {99} {77} ifelse }');
  149. var expectedStack = [99];
  150. expect(stack).toMatchArray(expectedStack);
  151. });
  152. it('handles ifelse with false', function () {
  153. var stack = evaluate('{ 0 {99} {77} ifelse }');
  154. var expectedStack = [77];
  155. expect(stack).toMatchArray(expectedStack);
  156. });
  157. it('handles nested if', function () {
  158. var stack = evaluate('{ 1 {1 {77} if} if }');
  159. var expectedStack = [77];
  160. expect(stack).toMatchArray(expectedStack);
  161. });
  162. it('abs', function () {
  163. var stack = evaluate('{ -2 abs }');
  164. var expectedStack = [2];
  165. expect(stack).toMatchArray(expectedStack);
  166. });
  167. it('adds', function () {
  168. var stack = evaluate('{ 1 2 add }');
  169. var expectedStack = [3];
  170. expect(stack).toMatchArray(expectedStack);
  171. });
  172. it('boolean and', function () {
  173. var stack = evaluate('{ true false and }');
  174. var expectedStack = [false];
  175. expect(stack).toMatchArray(expectedStack);
  176. });
  177. it('bitwise and', function () {
  178. var stack = evaluate('{ 254 1 and }');
  179. var expectedStack = [254 & 1];
  180. expect(stack).toMatchArray(expectedStack);
  181. });
  182. it('calculates the inverse tangent of a number', function () {
  183. var stack = evaluate('{ 90 atan }');
  184. var expectedStack = [Math.atan(90)];
  185. expect(stack).toMatchArray(expectedStack);
  186. });
  187. it('handles bitshifting ', function () {
  188. var stack = evaluate('{ 50 2 bitshift }');
  189. var expectedStack = [200];
  190. expect(stack).toMatchArray(expectedStack);
  191. });
  192. it('calculates the ceiling value', function () {
  193. var stack = evaluate('{ 9.9 ceiling }');
  194. var expectedStack = [10];
  195. expect(stack).toMatchArray(expectedStack);
  196. });
  197. it('copies', function () {
  198. var stack = evaluate('{ 99 98 2 copy }');
  199. var expectedStack = [99, 98, 99, 98];
  200. expect(stack).toMatchArray(expectedStack);
  201. });
  202. it('calculates the cosine of a number', function () {
  203. var stack = evaluate('{ 90 cos }');
  204. var expectedStack = [Math.cos(90)];
  205. expect(stack).toMatchArray(expectedStack);
  206. });
  207. it('converts to int', function () {
  208. var stack = evaluate('{ 9.9 cvi }');
  209. var expectedStack = [9];
  210. expect(stack).toMatchArray(expectedStack);
  211. });
  212. it('converts negatives to int', function () {
  213. var stack = evaluate('{ -9.9 cvi }');
  214. var expectedStack = [-9];
  215. expect(stack).toMatchArray(expectedStack);
  216. });
  217. it('converts to real', function () {
  218. var stack = evaluate('{ 55.34 cvr }');
  219. var expectedStack = [55.34];
  220. expect(stack).toMatchArray(expectedStack);
  221. });
  222. it('divides', function () {
  223. var stack = evaluate('{ 6 5 div }');
  224. var expectedStack = [1.2];
  225. expect(stack).toMatchArray(expectedStack);
  226. });
  227. it('maps division by zero to infinity', function () {
  228. var stack = evaluate('{ 6 0 div }');
  229. var expectedStack = [Infinity];
  230. expect(stack).toMatchArray(expectedStack);
  231. });
  232. it('duplicates', function () {
  233. var stack = evaluate('{ 99 dup }');
  234. var expectedStack = [99, 99];
  235. expect(stack).toMatchArray(expectedStack);
  236. });
  237. it('accepts an equality', function () {
  238. var stack = evaluate('{ 9 9 eq }');
  239. var expectedStack = [true];
  240. expect(stack).toMatchArray(expectedStack);
  241. });
  242. it('rejects an inequality', function () {
  243. var stack = evaluate('{ 9 8 eq }');
  244. var expectedStack = [false];
  245. expect(stack).toMatchArray(expectedStack);
  246. });
  247. it('exchanges', function () {
  248. var stack = evaluate('{ 44 99 exch }');
  249. var expectedStack = [99, 44];
  250. expect(stack).toMatchArray(expectedStack);
  251. });
  252. it('handles exponentiation', function () {
  253. var stack = evaluate('{ 10 2 exp }');
  254. var expectedStack = [100];
  255. expect(stack).toMatchArray(expectedStack);
  256. });
  257. it('pushes false onto the stack', function () {
  258. var stack = evaluate('{ false }');
  259. var expectedStack = [false];
  260. expect(stack).toMatchArray(expectedStack);
  261. });
  262. it('calculates the floor value', function () {
  263. var stack = evaluate('{ 9.9 floor }');
  264. var expectedStack = [9];
  265. expect(stack).toMatchArray(expectedStack);
  266. });
  267. it('handles greater than or equal to', function () {
  268. var stack = evaluate('{ 10 9 ge }');
  269. var expectedStack = [true];
  270. expect(stack).toMatchArray(expectedStack);
  271. });
  272. it('rejects less than for greater than or equal to', function () {
  273. var stack = evaluate('{ 8 9 ge }');
  274. var expectedStack = [false];
  275. expect(stack).toMatchArray(expectedStack);
  276. });
  277. it('handles greater than', function () {
  278. var stack = evaluate('{ 10 9 gt }');
  279. var expectedStack = [true];
  280. expect(stack).toMatchArray(expectedStack);
  281. });
  282. it('rejects less than or equal for greater than', function () {
  283. var stack = evaluate('{ 9 9 gt }');
  284. var expectedStack = [false];
  285. expect(stack).toMatchArray(expectedStack);
  286. });
  287. it('divides to integer', function () {
  288. var stack = evaluate('{ 2 3 idiv }');
  289. var expectedStack = [0];
  290. expect(stack).toMatchArray(expectedStack);
  291. });
  292. it('divides to negative integer', function () {
  293. var stack = evaluate('{ -2 3 idiv }');
  294. var expectedStack = [0];
  295. expect(stack).toMatchArray(expectedStack);
  296. });
  297. it('duplicates index', function () {
  298. var stack = evaluate('{ 4 3 2 1 2 index }');
  299. var expectedStack = [4, 3, 2, 1, 3];
  300. expect(stack).toMatchArray(expectedStack);
  301. });
  302. it('handles less than or equal to', function () {
  303. var stack = evaluate('{ 9 10 le }');
  304. var expectedStack = [true];
  305. expect(stack).toMatchArray(expectedStack);
  306. });
  307. it('rejects greater than for less than or equal to', function () {
  308. var stack = evaluate('{ 10 9 le }');
  309. var expectedStack = [false];
  310. expect(stack).toMatchArray(expectedStack);
  311. });
  312. it('calculates the natural logarithm', function () {
  313. var stack = evaluate('{ 10 ln }');
  314. var expectedStack = [Math.log(10)];
  315. expect(stack).toMatchArray(expectedStack);
  316. });
  317. it('calculates the base 10 logarithm', function () {
  318. var stack = evaluate('{ 100 log }');
  319. var expectedStack = [2];
  320. expect(stack).toMatchArray(expectedStack);
  321. });
  322. it('handles less than', function () {
  323. var stack = evaluate('{ 9 10 lt }');
  324. var expectedStack = [true];
  325. expect(stack).toMatchArray(expectedStack);
  326. });
  327. it('rejects greater than or equal to for less than', function () {
  328. var stack = evaluate('{ 10 9 lt }');
  329. var expectedStack = [false];
  330. expect(stack).toMatchArray(expectedStack);
  331. });
  332. it('performs the modulo operation', function () {
  333. var stack = evaluate('{ 4 3 mod }');
  334. var expectedStack = [1];
  335. expect(stack).toMatchArray(expectedStack);
  336. });
  337. it('multiplies two numbers (positive result)', function () {
  338. var stack = evaluate('{ 9 8 mul }');
  339. var expectedStack = [72];
  340. expect(stack).toMatchArray(expectedStack);
  341. });
  342. it('multiplies two numbers (negative result)', function () {
  343. var stack = evaluate('{ 9 -8 mul }');
  344. var expectedStack = [-72];
  345. expect(stack).toMatchArray(expectedStack);
  346. });
  347. it('accepts an inequality', function () {
  348. var stack = evaluate('{ 9 8 ne }');
  349. var expectedStack = [true];
  350. expect(stack).toMatchArray(expectedStack);
  351. });
  352. it('rejects an equality', function () {
  353. var stack = evaluate('{ 9 9 ne }');
  354. var expectedStack = [false];
  355. expect(stack).toMatchArray(expectedStack);
  356. });
  357. it('negates', function () {
  358. var stack = evaluate('{ 4.5 neg }');
  359. var expectedStack = [-4.5];
  360. expect(stack).toMatchArray(expectedStack);
  361. });
  362. it('boolean not', function () {
  363. var stack = evaluate('{ true not }');
  364. var expectedStack = [false];
  365. expect(stack).toMatchArray(expectedStack);
  366. });
  367. it('bitwise not', function () {
  368. var stack = evaluate('{ 12 not }');
  369. var expectedStack = [-13];
  370. expect(stack).toMatchArray(expectedStack);
  371. });
  372. it('boolean or', function () {
  373. var stack = evaluate('{ true false or }');
  374. var expectedStack = [true];
  375. expect(stack).toMatchArray(expectedStack);
  376. });
  377. it('bitwise or', function () {
  378. var stack = evaluate('{ 254 1 or }');
  379. var expectedStack = [254 | 1];
  380. expect(stack).toMatchArray(expectedStack);
  381. });
  382. it('pops stack', function () {
  383. var stack = evaluate('{ 1 2 pop }');
  384. var expectedStack = [1];
  385. expect(stack).toMatchArray(expectedStack);
  386. });
  387. it('rolls stack right', function () {
  388. var stack = evaluate('{ 1 3 2 2 4 1 roll }');
  389. var expectedStack = [2, 1, 3, 2];
  390. expect(stack).toMatchArray(expectedStack);
  391. });
  392. it('rolls stack left', function () {
  393. var stack = evaluate('{ 1 3 2 2 4 -1 roll }');
  394. var expectedStack = [3, 2, 2, 1];
  395. expect(stack).toMatchArray(expectedStack);
  396. });
  397. it('rounds a number', function () {
  398. var stack = evaluate('{ 9.52 round }');
  399. var expectedStack = [10];
  400. expect(stack).toMatchArray(expectedStack);
  401. });
  402. it('calculates the sine of a number', function () {
  403. var stack = evaluate('{ 90 sin }');
  404. var expectedStack = [Math.sin(90)];
  405. expect(stack).toMatchArray(expectedStack);
  406. });
  407. it('calculates a square root (integer)', function () {
  408. var stack = evaluate('{ 100 sqrt }');
  409. var expectedStack = [10];
  410. expect(stack).toMatchArray(expectedStack);
  411. });
  412. it('calculates a square root (float)', function () {
  413. var stack = evaluate('{ 99 sqrt }');
  414. var expectedStack = [Math.sqrt(99)];
  415. expect(stack).toMatchArray(expectedStack);
  416. });
  417. it('subtracts (positive result)', function () {
  418. var stack = evaluate('{ 6 4 sub }');
  419. var expectedStack = [2];
  420. expect(stack).toMatchArray(expectedStack);
  421. });
  422. it('subtracts (negative result)', function () {
  423. var stack = evaluate('{ 4 6 sub }');
  424. var expectedStack = [-2];
  425. expect(stack).toMatchArray(expectedStack);
  426. });
  427. it('pushes true onto the stack', function () {
  428. var stack = evaluate('{ true }');
  429. var expectedStack = [true];
  430. expect(stack).toMatchArray(expectedStack);
  431. });
  432. it('truncates a number', function () {
  433. var stack = evaluate('{ 35.004 truncate }');
  434. var expectedStack = [35];
  435. expect(stack).toMatchArray(expectedStack);
  436. });
  437. it('calculates an exclusive or value', function () {
  438. var stack = evaluate('{ 3 9 xor }');
  439. var expectedStack = [10];
  440. expect(stack).toMatchArray(expectedStack);
  441. });
  442. });
  443. describe('PostScriptCompiler', function () {
  444. function check(code, domain, range, samples) {
  445. var compiler = new PostScriptCompiler();
  446. var compiledCode = compiler.compile(code, domain, range);
  447. if (samples === null) {
  448. expect(compiledCode).toBeNull();
  449. } else {
  450. expect(compiledCode).not.toBeNull();
  451. var fn = new Function('src', 'srcOffset', 'dest', 'destOffset', compiledCode);
  452. for (var i = 0; i < samples.length; i++) {
  453. var out = new Float32Array(samples[i].output.length);
  454. fn(samples[i].input, 0, out, 0);
  455. expect(Array.prototype.slice.call(out, 0)).toMatchArray(samples[i].output);
  456. }
  457. }
  458. }
  459. it('check compiled add', function () {
  460. check([0.25, 0.5, 'add'], [], [0, 1], [{
  461. input: [],
  462. output: [0.75]
  463. }]);
  464. check([0, 'add'], [0, 1], [0, 1], [{
  465. input: [0.25],
  466. output: [0.25]
  467. }]);
  468. check([0.5, 'add'], [0, 1], [0, 1], [{
  469. input: [0.25],
  470. output: [0.75]
  471. }]);
  472. check([0, 'exch', 'add'], [0, 1], [0, 1], [{
  473. input: [0.25],
  474. output: [0.25]
  475. }]);
  476. check([0.5, 'exch', 'add'], [0, 1], [0, 1], [{
  477. input: [0.25],
  478. output: [0.75]
  479. }]);
  480. check(['add'], [0, 1, 0, 1], [0, 1], [{
  481. input: [0.25, 0.5],
  482. output: [0.75]
  483. }]);
  484. check(['add'], [0, 1], [0, 1], null);
  485. });
  486. it('check compiled sub', function () {
  487. check([0.5, 0.25, 'sub'], [], [0, 1], [{
  488. input: [],
  489. output: [0.25]
  490. }]);
  491. check([0, 'sub'], [0, 1], [0, 1], [{
  492. input: [0.25],
  493. output: [0.25]
  494. }]);
  495. check([0.5, 'sub'], [0, 1], [0, 1], [{
  496. input: [0.75],
  497. output: [0.25]
  498. }]);
  499. check([0, 'exch', 'sub'], [0, 1], [-1, 1], [{
  500. input: [0.25],
  501. output: [-0.25]
  502. }]);
  503. check([0.75, 'exch', 'sub'], [0, 1], [-1, 1], [{
  504. input: [0.25],
  505. output: [0.5]
  506. }]);
  507. check(['sub'], [0, 1, 0, 1], [-1, 1], [{
  508. input: [0.25, 0.5],
  509. output: [-0.25]
  510. }]);
  511. check(['sub'], [0, 1], [0, 1], null);
  512. check([1, 'dup', 3, 2, 'roll', 'sub', 'sub'], [0, 1], [0, 1], [{
  513. input: [0.75],
  514. output: [0.75]
  515. }]);
  516. });
  517. it('check compiled mul', function () {
  518. check([0.25, 0.5, 'mul'], [], [0, 1], [{
  519. input: [],
  520. output: [0.125]
  521. }]);
  522. check([0, 'mul'], [0, 1], [0, 1], [{
  523. input: [0.25],
  524. output: [0]
  525. }]);
  526. check([0.5, 'mul'], [0, 1], [0, 1], [{
  527. input: [0.25],
  528. output: [0.125]
  529. }]);
  530. check([1, 'mul'], [0, 1], [0, 1], [{
  531. input: [0.25],
  532. output: [0.25]
  533. }]);
  534. check([0, 'exch', 'mul'], [0, 1], [0, 1], [{
  535. input: [0.25],
  536. output: [0]
  537. }]);
  538. check([0.5, 'exch', 'mul'], [0, 1], [0, 1], [{
  539. input: [0.25],
  540. output: [0.125]
  541. }]);
  542. check([1, 'exch', 'mul'], [0, 1], [0, 1], [{
  543. input: [0.25],
  544. output: [0.25]
  545. }]);
  546. check(['mul'], [0, 1, 0, 1], [0, 1], [{
  547. input: [0.25, 0.5],
  548. output: [0.125]
  549. }]);
  550. check(['mul'], [0, 1], [0, 1], null);
  551. });
  552. it('check compiled max', function () {
  553. check(['dup', 0.75, 'gt', 7, 'jz', 'pop', 0.75], [0, 1], [0, 1], [{
  554. input: [0.5],
  555. output: [0.5]
  556. }]);
  557. check(['dup', 0.75, 'gt', 7, 'jz', 'pop', 0.75], [0, 1], [0, 1], [{
  558. input: [1],
  559. output: [0.75]
  560. }]);
  561. check(['dup', 0.75, 'gt', 5, 'jz', 'pop', 0.75], [0, 1], [0, 1], null);
  562. });
  563. it('check pop/roll/index', function () {
  564. check([1, 'pop'], [0, 1], [0, 1], [{
  565. input: [0.5],
  566. output: [0.5]
  567. }]);
  568. check([1, 3, -1, 'roll'], [0, 1, 0, 1], [0, 1, 0, 1, 0, 1], [{
  569. input: [0.25, 0.5],
  570. output: [0.5, 1, 0.25]
  571. }]);
  572. check([1, 3, 1, 'roll'], [0, 1, 0, 1], [0, 1, 0, 1, 0, 1], [{
  573. input: [0.25, 0.5],
  574. output: [1, 0.25, 0.5]
  575. }]);
  576. check([1, 3, 1.5, 'roll'], [0, 1, 0, 1], [0, 1, 0, 1, 0, 1], null);
  577. check([1, 1, 'index'], [0, 1], [0, 1, 0, 1, 0, 1], [{
  578. input: [0.5],
  579. output: [0.5, 1, 0.5]
  580. }]);
  581. check([1, 3, 'index', 'pop'], [0, 1], [0, 1], null);
  582. check([1, 0.5, 'index', 'pop'], [0, 1], [0, 1], null);
  583. });
  584. it('check input boundaries', function () {
  585. check([], [0, 0.5], [0, 1], [{
  586. input: [1],
  587. output: [0.5]
  588. }]);
  589. check([], [0.5, 1], [0, 1], [{
  590. input: [0],
  591. output: [0.5]
  592. }]);
  593. check(['dup'], [0.5, 0.75], [0, 1, 0, 1], [{
  594. input: [0],
  595. output: [0.5, 0.5]
  596. }]);
  597. check([], [100, 1001], [0, 10000], [{
  598. input: [1000],
  599. output: [1000]
  600. }]);
  601. });
  602. it('check output boundaries', function () {
  603. check([], [0, 1], [0, 0.5], [{
  604. input: [1],
  605. output: [0.5]
  606. }]);
  607. check([], [0, 1], [0.5, 1], [{
  608. input: [0],
  609. output: [0.5]
  610. }]);
  611. check(['dup'], [0, 1], [0.5, 1, 0.75, 1], [{
  612. input: [0],
  613. output: [0.5, 0.75]
  614. }]);
  615. check([], [0, 10000], [100, 1001], [{
  616. input: [1000],
  617. output: [1000]
  618. }]);
  619. });
  620. it('compile optimized', function () {
  621. var compiler = new PostScriptCompiler();
  622. var code = [0, 'add', 1, 1, 3, -1, 'roll', 'sub', 'sub', 1, 'mul'];
  623. var compiledCode = compiler.compile(code, [0, 1], [0, 1]);
  624. expect(compiledCode).toEqual('dest[destOffset + 0] = Math.max(0, Math.min(1, src[srcOffset + 0]));');
  625. });
  626. });
  627. });