pattern.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  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. Object.defineProperty(exports, "__esModule", {
  17. value: true
  18. });
  19. exports.getTilingPatternIR = exports.Pattern = undefined;
  20. var _util = require('../shared/util');
  21. var _colorspace = require('./colorspace');
  22. var _primitives = require('./primitives');
  23. var _function = require('./function');
  24. var ShadingType = {
  25. FUNCTION_BASED: 1,
  26. AXIAL: 2,
  27. RADIAL: 3,
  28. FREE_FORM_MESH: 4,
  29. LATTICE_FORM_MESH: 5,
  30. COONS_PATCH_MESH: 6,
  31. TENSOR_PATCH_MESH: 7
  32. };
  33. var Pattern = function PatternClosure() {
  34. function Pattern() {
  35. (0, _util.error)('should not call Pattern constructor');
  36. }
  37. Pattern.prototype = {
  38. getPattern: function Pattern_getPattern(ctx) {
  39. (0, _util.error)('Should not call Pattern.getStyle: ' + ctx);
  40. }
  41. };
  42. Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref, res, handler) {
  43. var dict = (0, _primitives.isStream)(shading) ? shading.dict : shading;
  44. var type = dict.get('ShadingType');
  45. try {
  46. switch (type) {
  47. case ShadingType.AXIAL:
  48. case ShadingType.RADIAL:
  49. return new Shadings.RadialAxial(dict, matrix, xref, res);
  50. case ShadingType.FREE_FORM_MESH:
  51. case ShadingType.LATTICE_FORM_MESH:
  52. case ShadingType.COONS_PATCH_MESH:
  53. case ShadingType.TENSOR_PATCH_MESH:
  54. return new Shadings.Mesh(shading, matrix, xref, res);
  55. default:
  56. throw new Error('Unsupported ShadingType: ' + type);
  57. }
  58. } catch (ex) {
  59. if (ex instanceof _util.MissingDataException) {
  60. throw ex;
  61. }
  62. handler.send('UnsupportedFeature', { featureId: _util.UNSUPPORTED_FEATURES.shadingPattern });
  63. (0, _util.warn)(ex);
  64. return new Shadings.Dummy();
  65. }
  66. };
  67. return Pattern;
  68. }();
  69. var Shadings = {};
  70. Shadings.SMALL_NUMBER = 1e-6;
  71. Shadings.RadialAxial = function RadialAxialClosure() {
  72. function RadialAxial(dict, matrix, xref, res) {
  73. this.matrix = matrix;
  74. this.coordsArr = dict.getArray('Coords');
  75. this.shadingType = dict.get('ShadingType');
  76. this.type = 'Pattern';
  77. var cs = dict.get('ColorSpace', 'CS');
  78. cs = _colorspace.ColorSpace.parse(cs, xref, res);
  79. this.cs = cs;
  80. var t0 = 0.0,
  81. t1 = 1.0;
  82. if (dict.has('Domain')) {
  83. var domainArr = dict.getArray('Domain');
  84. t0 = domainArr[0];
  85. t1 = domainArr[1];
  86. }
  87. var extendStart = false,
  88. extendEnd = false;
  89. if (dict.has('Extend')) {
  90. var extendArr = dict.getArray('Extend');
  91. extendStart = extendArr[0];
  92. extendEnd = extendArr[1];
  93. }
  94. if (this.shadingType === ShadingType.RADIAL && (!extendStart || !extendEnd)) {
  95. var x1 = this.coordsArr[0];
  96. var y1 = this.coordsArr[1];
  97. var r1 = this.coordsArr[2];
  98. var x2 = this.coordsArr[3];
  99. var y2 = this.coordsArr[4];
  100. var r2 = this.coordsArr[5];
  101. var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
  102. if (r1 <= r2 + distance && r2 <= r1 + distance) {
  103. (0, _util.warn)('Unsupported radial gradient.');
  104. }
  105. }
  106. this.extendStart = extendStart;
  107. this.extendEnd = extendEnd;
  108. var fnObj = dict.get('Function');
  109. var fn = _function.PDFFunction.parseArray(xref, fnObj);
  110. var diff = t1 - t0;
  111. var step = diff / 10;
  112. var colorStops = this.colorStops = [];
  113. if (t0 >= t1 || step <= 0) {
  114. (0, _util.info)('Bad shading domain.');
  115. return;
  116. }
  117. var color = new Float32Array(cs.numComps),
  118. ratio = new Float32Array(1);
  119. var rgbColor;
  120. for (var i = t0; i <= t1; i += step) {
  121. ratio[0] = i;
  122. fn(ratio, 0, color, 0);
  123. rgbColor = cs.getRgb(color, 0);
  124. var cssColor = _util.Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
  125. colorStops.push([(i - t0) / diff, cssColor]);
  126. }
  127. var background = 'transparent';
  128. if (dict.has('Background')) {
  129. rgbColor = cs.getRgb(dict.get('Background'), 0);
  130. background = _util.Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
  131. }
  132. if (!extendStart) {
  133. colorStops.unshift([0, background]);
  134. colorStops[1][0] += Shadings.SMALL_NUMBER;
  135. }
  136. if (!extendEnd) {
  137. colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER;
  138. colorStops.push([1, background]);
  139. }
  140. this.colorStops = colorStops;
  141. }
  142. RadialAxial.prototype = {
  143. getIR: function RadialAxial_getIR() {
  144. var coordsArr = this.coordsArr;
  145. var shadingType = this.shadingType;
  146. var type, p0, p1, r0, r1;
  147. if (shadingType === ShadingType.AXIAL) {
  148. p0 = [coordsArr[0], coordsArr[1]];
  149. p1 = [coordsArr[2], coordsArr[3]];
  150. r0 = null;
  151. r1 = null;
  152. type = 'axial';
  153. } else if (shadingType === ShadingType.RADIAL) {
  154. p0 = [coordsArr[0], coordsArr[1]];
  155. p1 = [coordsArr[3], coordsArr[4]];
  156. r0 = coordsArr[2];
  157. r1 = coordsArr[5];
  158. type = 'radial';
  159. } else {
  160. (0, _util.error)('getPattern type unknown: ' + shadingType);
  161. }
  162. var matrix = this.matrix;
  163. if (matrix) {
  164. p0 = _util.Util.applyTransform(p0, matrix);
  165. p1 = _util.Util.applyTransform(p1, matrix);
  166. if (shadingType === ShadingType.RADIAL) {
  167. var scale = _util.Util.singularValueDecompose2dScale(matrix);
  168. r0 *= scale[0];
  169. r1 *= scale[1];
  170. }
  171. }
  172. return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1];
  173. }
  174. };
  175. return RadialAxial;
  176. }();
  177. Shadings.Mesh = function MeshClosure() {
  178. function MeshStreamReader(stream, context) {
  179. this.stream = stream;
  180. this.context = context;
  181. this.buffer = 0;
  182. this.bufferLength = 0;
  183. var numComps = context.numComps;
  184. this.tmpCompsBuf = new Float32Array(numComps);
  185. var csNumComps = context.colorSpace.numComps;
  186. this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
  187. }
  188. MeshStreamReader.prototype = {
  189. get hasData() {
  190. if (this.stream.end) {
  191. return this.stream.pos < this.stream.end;
  192. }
  193. if (this.bufferLength > 0) {
  194. return true;
  195. }
  196. var nextByte = this.stream.getByte();
  197. if (nextByte < 0) {
  198. return false;
  199. }
  200. this.buffer = nextByte;
  201. this.bufferLength = 8;
  202. return true;
  203. },
  204. readBits: function MeshStreamReader_readBits(n) {
  205. var buffer = this.buffer;
  206. var bufferLength = this.bufferLength;
  207. if (n === 32) {
  208. if (bufferLength === 0) {
  209. return (this.stream.getByte() << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte()) >>> 0;
  210. }
  211. buffer = buffer << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte();
  212. var nextByte = this.stream.getByte();
  213. this.buffer = nextByte & (1 << bufferLength) - 1;
  214. return (buffer << 8 - bufferLength | (nextByte & 0xFF) >> bufferLength) >>> 0;
  215. }
  216. if (n === 8 && bufferLength === 0) {
  217. return this.stream.getByte();
  218. }
  219. while (bufferLength < n) {
  220. buffer = buffer << 8 | this.stream.getByte();
  221. bufferLength += 8;
  222. }
  223. bufferLength -= n;
  224. this.bufferLength = bufferLength;
  225. this.buffer = buffer & (1 << bufferLength) - 1;
  226. return buffer >> bufferLength;
  227. },
  228. align: function MeshStreamReader_align() {
  229. this.buffer = 0;
  230. this.bufferLength = 0;
  231. },
  232. readFlag: function MeshStreamReader_readFlag() {
  233. return this.readBits(this.context.bitsPerFlag);
  234. },
  235. readCoordinate: function MeshStreamReader_readCoordinate() {
  236. var bitsPerCoordinate = this.context.bitsPerCoordinate;
  237. var xi = this.readBits(bitsPerCoordinate);
  238. var yi = this.readBits(bitsPerCoordinate);
  239. var decode = this.context.decode;
  240. var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 2.3283064365386963e-10;
  241. return [xi * scale * (decode[1] - decode[0]) + decode[0], yi * scale * (decode[3] - decode[2]) + decode[2]];
  242. },
  243. readComponents: function MeshStreamReader_readComponents() {
  244. var numComps = this.context.numComps;
  245. var bitsPerComponent = this.context.bitsPerComponent;
  246. var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 2.3283064365386963e-10;
  247. var decode = this.context.decode;
  248. var components = this.tmpCompsBuf;
  249. for (var i = 0, j = 4; i < numComps; i++, j += 2) {
  250. var ci = this.readBits(bitsPerComponent);
  251. components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
  252. }
  253. var color = this.tmpCsCompsBuf;
  254. if (this.context.colorFn) {
  255. this.context.colorFn(components, 0, color, 0);
  256. }
  257. return this.context.colorSpace.getRgb(color, 0);
  258. }
  259. };
  260. function decodeType4Shading(mesh, reader) {
  261. var coords = mesh.coords;
  262. var colors = mesh.colors;
  263. var operators = [];
  264. var ps = [];
  265. var verticesLeft = 0;
  266. while (reader.hasData) {
  267. var f = reader.readFlag();
  268. var coord = reader.readCoordinate();
  269. var color = reader.readComponents();
  270. if (verticesLeft === 0) {
  271. (0, _util.assert)(0 <= f && f <= 2, 'Unknown type4 flag');
  272. switch (f) {
  273. case 0:
  274. verticesLeft = 3;
  275. break;
  276. case 1:
  277. ps.push(ps[ps.length - 2], ps[ps.length - 1]);
  278. verticesLeft = 1;
  279. break;
  280. case 2:
  281. ps.push(ps[ps.length - 3], ps[ps.length - 1]);
  282. verticesLeft = 1;
  283. break;
  284. }
  285. operators.push(f);
  286. }
  287. ps.push(coords.length);
  288. coords.push(coord);
  289. colors.push(color);
  290. verticesLeft--;
  291. reader.align();
  292. }
  293. mesh.figures.push({
  294. type: 'triangles',
  295. coords: new Int32Array(ps),
  296. colors: new Int32Array(ps)
  297. });
  298. }
  299. function decodeType5Shading(mesh, reader, verticesPerRow) {
  300. var coords = mesh.coords;
  301. var colors = mesh.colors;
  302. var ps = [];
  303. while (reader.hasData) {
  304. var coord = reader.readCoordinate();
  305. var color = reader.readComponents();
  306. ps.push(coords.length);
  307. coords.push(coord);
  308. colors.push(color);
  309. }
  310. mesh.figures.push({
  311. type: 'lattice',
  312. coords: new Int32Array(ps),
  313. colors: new Int32Array(ps),
  314. verticesPerRow: verticesPerRow
  315. });
  316. }
  317. var MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
  318. var MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
  319. var TRIANGLE_DENSITY = 20;
  320. var getB = function getBClosure() {
  321. function buildB(count) {
  322. var lut = [];
  323. for (var i = 0; i <= count; i++) {
  324. var t = i / count,
  325. t_ = 1 - t;
  326. lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_, 3 * t * t * t_, t * t * t]));
  327. }
  328. return lut;
  329. }
  330. var cache = [];
  331. return function getB(count) {
  332. if (!cache[count]) {
  333. cache[count] = buildB(count);
  334. }
  335. return cache[count];
  336. };
  337. }();
  338. function buildFigureFromPatch(mesh, index) {
  339. var figure = mesh.figures[index];
  340. (0, _util.assert)(figure.type === 'patch', 'Unexpected patch mesh figure');
  341. var coords = mesh.coords,
  342. colors = mesh.colors;
  343. var pi = figure.coords;
  344. var ci = figure.colors;
  345. var figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
  346. var figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
  347. var figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
  348. var figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
  349. var splitXBy = Math.ceil((figureMaxX - figureMinX) * TRIANGLE_DENSITY / (mesh.bounds[2] - mesh.bounds[0]));
  350. splitXBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy));
  351. var splitYBy = Math.ceil((figureMaxY - figureMinY) * TRIANGLE_DENSITY / (mesh.bounds[3] - mesh.bounds[1]));
  352. splitYBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy));
  353. var verticesPerRow = splitXBy + 1;
  354. var figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
  355. var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
  356. var k = 0;
  357. var cl = new Uint8Array(3),
  358. cr = new Uint8Array(3);
  359. var c0 = colors[ci[0]],
  360. c1 = colors[ci[1]],
  361. c2 = colors[ci[2]],
  362. c3 = colors[ci[3]];
  363. var bRow = getB(splitYBy),
  364. bCol = getB(splitXBy);
  365. for (var row = 0; row <= splitYBy; row++) {
  366. cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
  367. cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
  368. cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
  369. cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
  370. cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
  371. cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
  372. for (var col = 0; col <= splitXBy; col++, k++) {
  373. if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
  374. continue;
  375. }
  376. var x = 0,
  377. y = 0;
  378. var q = 0;
  379. for (var i = 0; i <= 3; i++) {
  380. for (var j = 0; j <= 3; j++, q++) {
  381. var m = bRow[row][i] * bCol[col][j];
  382. x += coords[pi[q]][0] * m;
  383. y += coords[pi[q]][1] * m;
  384. }
  385. }
  386. figureCoords[k] = coords.length;
  387. coords.push([x, y]);
  388. figureColors[k] = colors.length;
  389. var newColor = new Uint8Array(3);
  390. newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
  391. newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
  392. newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
  393. colors.push(newColor);
  394. }
  395. }
  396. figureCoords[0] = pi[0];
  397. figureColors[0] = ci[0];
  398. figureCoords[splitXBy] = pi[3];
  399. figureColors[splitXBy] = ci[1];
  400. figureCoords[verticesPerRow * splitYBy] = pi[12];
  401. figureColors[verticesPerRow * splitYBy] = ci[2];
  402. figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
  403. figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
  404. mesh.figures[index] = {
  405. type: 'lattice',
  406. coords: figureCoords,
  407. colors: figureColors,
  408. verticesPerRow: verticesPerRow
  409. };
  410. }
  411. function decodeType6Shading(mesh, reader) {
  412. var coords = mesh.coords;
  413. var colors = mesh.colors;
  414. var ps = new Int32Array(16);
  415. var cs = new Int32Array(4);
  416. while (reader.hasData) {
  417. var f = reader.readFlag();
  418. (0, _util.assert)(0 <= f && f <= 3, 'Unknown type6 flag');
  419. var i, ii;
  420. var pi = coords.length;
  421. for (i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
  422. coords.push(reader.readCoordinate());
  423. }
  424. var ci = colors.length;
  425. for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
  426. colors.push(reader.readComponents());
  427. }
  428. var tmp1, tmp2, tmp3, tmp4;
  429. switch (f) {
  430. case 0:
  431. ps[12] = pi + 3;
  432. ps[13] = pi + 4;
  433. ps[14] = pi + 5;
  434. ps[15] = pi + 6;
  435. ps[8] = pi + 2;
  436. ps[11] = pi + 7;
  437. ps[4] = pi + 1;
  438. ps[7] = pi + 8;
  439. ps[0] = pi;
  440. ps[1] = pi + 11;
  441. ps[2] = pi + 10;
  442. ps[3] = pi + 9;
  443. cs[2] = ci + 1;
  444. cs[3] = ci + 2;
  445. cs[0] = ci;
  446. cs[1] = ci + 3;
  447. break;
  448. case 1:
  449. tmp1 = ps[12];
  450. tmp2 = ps[13];
  451. tmp3 = ps[14];
  452. tmp4 = ps[15];
  453. ps[12] = tmp4;
  454. ps[13] = pi + 0;
  455. ps[14] = pi + 1;
  456. ps[15] = pi + 2;
  457. ps[8] = tmp3;
  458. ps[11] = pi + 3;
  459. ps[4] = tmp2;
  460. ps[7] = pi + 4;
  461. ps[0] = tmp1;
  462. ps[1] = pi + 7;
  463. ps[2] = pi + 6;
  464. ps[3] = pi + 5;
  465. tmp1 = cs[2];
  466. tmp2 = cs[3];
  467. cs[2] = tmp2;
  468. cs[3] = ci;
  469. cs[0] = tmp1;
  470. cs[1] = ci + 1;
  471. break;
  472. case 2:
  473. tmp1 = ps[15];
  474. tmp2 = ps[11];
  475. ps[12] = ps[3];
  476. ps[13] = pi + 0;
  477. ps[14] = pi + 1;
  478. ps[15] = pi + 2;
  479. ps[8] = ps[7];
  480. ps[11] = pi + 3;
  481. ps[4] = tmp2;
  482. ps[7] = pi + 4;
  483. ps[0] = tmp1;
  484. ps[1] = pi + 7;
  485. ps[2] = pi + 6;
  486. ps[3] = pi + 5;
  487. tmp1 = cs[3];
  488. cs[2] = cs[1];
  489. cs[3] = ci;
  490. cs[0] = tmp1;
  491. cs[1] = ci + 1;
  492. break;
  493. case 3:
  494. ps[12] = ps[0];
  495. ps[13] = pi + 0;
  496. ps[14] = pi + 1;
  497. ps[15] = pi + 2;
  498. ps[8] = ps[1];
  499. ps[11] = pi + 3;
  500. ps[4] = ps[2];
  501. ps[7] = pi + 4;
  502. ps[0] = ps[3];
  503. ps[1] = pi + 7;
  504. ps[2] = pi + 6;
  505. ps[3] = pi + 5;
  506. cs[2] = cs[0];
  507. cs[3] = ci;
  508. cs[0] = cs[1];
  509. cs[1] = ci + 1;
  510. break;
  511. }
  512. ps[5] = coords.length;
  513. coords.push([(-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9, (-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9]);
  514. ps[6] = coords.length;
  515. coords.push([(-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9, (-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9]);
  516. ps[9] = coords.length;
  517. coords.push([(-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9, (-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9]);
  518. ps[10] = coords.length;
  519. coords.push([(-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9, (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9]);
  520. mesh.figures.push({
  521. type: 'patch',
  522. coords: new Int32Array(ps),
  523. colors: new Int32Array(cs)
  524. });
  525. }
  526. }
  527. function decodeType7Shading(mesh, reader) {
  528. var coords = mesh.coords;
  529. var colors = mesh.colors;
  530. var ps = new Int32Array(16);
  531. var cs = new Int32Array(4);
  532. while (reader.hasData) {
  533. var f = reader.readFlag();
  534. (0, _util.assert)(0 <= f && f <= 3, 'Unknown type7 flag');
  535. var i, ii;
  536. var pi = coords.length;
  537. for (i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
  538. coords.push(reader.readCoordinate());
  539. }
  540. var ci = colors.length;
  541. for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
  542. colors.push(reader.readComponents());
  543. }
  544. var tmp1, tmp2, tmp3, tmp4;
  545. switch (f) {
  546. case 0:
  547. ps[12] = pi + 3;
  548. ps[13] = pi + 4;
  549. ps[14] = pi + 5;
  550. ps[15] = pi + 6;
  551. ps[8] = pi + 2;
  552. ps[9] = pi + 13;
  553. ps[10] = pi + 14;
  554. ps[11] = pi + 7;
  555. ps[4] = pi + 1;
  556. ps[5] = pi + 12;
  557. ps[6] = pi + 15;
  558. ps[7] = pi + 8;
  559. ps[0] = pi;
  560. ps[1] = pi + 11;
  561. ps[2] = pi + 10;
  562. ps[3] = pi + 9;
  563. cs[2] = ci + 1;
  564. cs[3] = ci + 2;
  565. cs[0] = ci;
  566. cs[1] = ci + 3;
  567. break;
  568. case 1:
  569. tmp1 = ps[12];
  570. tmp2 = ps[13];
  571. tmp3 = ps[14];
  572. tmp4 = ps[15];
  573. ps[12] = tmp4;
  574. ps[13] = pi + 0;
  575. ps[14] = pi + 1;
  576. ps[15] = pi + 2;
  577. ps[8] = tmp3;
  578. ps[9] = pi + 9;
  579. ps[10] = pi + 10;
  580. ps[11] = pi + 3;
  581. ps[4] = tmp2;
  582. ps[5] = pi + 8;
  583. ps[6] = pi + 11;
  584. ps[7] = pi + 4;
  585. ps[0] = tmp1;
  586. ps[1] = pi + 7;
  587. ps[2] = pi + 6;
  588. ps[3] = pi + 5;
  589. tmp1 = cs[2];
  590. tmp2 = cs[3];
  591. cs[2] = tmp2;
  592. cs[3] = ci;
  593. cs[0] = tmp1;
  594. cs[1] = ci + 1;
  595. break;
  596. case 2:
  597. tmp1 = ps[15];
  598. tmp2 = ps[11];
  599. ps[12] = ps[3];
  600. ps[13] = pi + 0;
  601. ps[14] = pi + 1;
  602. ps[15] = pi + 2;
  603. ps[8] = ps[7];
  604. ps[9] = pi + 9;
  605. ps[10] = pi + 10;
  606. ps[11] = pi + 3;
  607. ps[4] = tmp2;
  608. ps[5] = pi + 8;
  609. ps[6] = pi + 11;
  610. ps[7] = pi + 4;
  611. ps[0] = tmp1;
  612. ps[1] = pi + 7;
  613. ps[2] = pi + 6;
  614. ps[3] = pi + 5;
  615. tmp1 = cs[3];
  616. cs[2] = cs[1];
  617. cs[3] = ci;
  618. cs[0] = tmp1;
  619. cs[1] = ci + 1;
  620. break;
  621. case 3:
  622. ps[12] = ps[0];
  623. ps[13] = pi + 0;
  624. ps[14] = pi + 1;
  625. ps[15] = pi + 2;
  626. ps[8] = ps[1];
  627. ps[9] = pi + 9;
  628. ps[10] = pi + 10;
  629. ps[11] = pi + 3;
  630. ps[4] = ps[2];
  631. ps[5] = pi + 8;
  632. ps[6] = pi + 11;
  633. ps[7] = pi + 4;
  634. ps[0] = ps[3];
  635. ps[1] = pi + 7;
  636. ps[2] = pi + 6;
  637. ps[3] = pi + 5;
  638. cs[2] = cs[0];
  639. cs[3] = ci;
  640. cs[0] = cs[1];
  641. cs[1] = ci + 1;
  642. break;
  643. }
  644. mesh.figures.push({
  645. type: 'patch',
  646. coords: new Int32Array(ps),
  647. colors: new Int32Array(cs)
  648. });
  649. }
  650. }
  651. function updateBounds(mesh) {
  652. var minX = mesh.coords[0][0],
  653. minY = mesh.coords[0][1],
  654. maxX = minX,
  655. maxY = minY;
  656. for (var i = 1, ii = mesh.coords.length; i < ii; i++) {
  657. var x = mesh.coords[i][0],
  658. y = mesh.coords[i][1];
  659. minX = minX > x ? x : minX;
  660. minY = minY > y ? y : minY;
  661. maxX = maxX < x ? x : maxX;
  662. maxY = maxY < y ? y : maxY;
  663. }
  664. mesh.bounds = [minX, minY, maxX, maxY];
  665. }
  666. function packData(mesh) {
  667. var i, ii, j, jj;
  668. var coords = mesh.coords;
  669. var coordsPacked = new Float32Array(coords.length * 2);
  670. for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
  671. var xy = coords[i];
  672. coordsPacked[j++] = xy[0];
  673. coordsPacked[j++] = xy[1];
  674. }
  675. mesh.coords = coordsPacked;
  676. var colors = mesh.colors;
  677. var colorsPacked = new Uint8Array(colors.length * 3);
  678. for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
  679. var c = colors[i];
  680. colorsPacked[j++] = c[0];
  681. colorsPacked[j++] = c[1];
  682. colorsPacked[j++] = c[2];
  683. }
  684. mesh.colors = colorsPacked;
  685. var figures = mesh.figures;
  686. for (i = 0, ii = figures.length; i < ii; i++) {
  687. var figure = figures[i],
  688. ps = figure.coords,
  689. cs = figure.colors;
  690. for (j = 0, jj = ps.length; j < jj; j++) {
  691. ps[j] *= 2;
  692. cs[j] *= 3;
  693. }
  694. }
  695. }
  696. function Mesh(stream, matrix, xref, res) {
  697. (0, _util.assert)((0, _primitives.isStream)(stream), 'Mesh data is not a stream');
  698. var dict = stream.dict;
  699. this.matrix = matrix;
  700. this.shadingType = dict.get('ShadingType');
  701. this.type = 'Pattern';
  702. this.bbox = dict.getArray('BBox');
  703. var cs = dict.get('ColorSpace', 'CS');
  704. cs = _colorspace.ColorSpace.parse(cs, xref, res);
  705. this.cs = cs;
  706. this.background = dict.has('Background') ? cs.getRgb(dict.get('Background'), 0) : null;
  707. var fnObj = dict.get('Function');
  708. var fn = fnObj ? _function.PDFFunction.parseArray(xref, fnObj) : null;
  709. this.coords = [];
  710. this.colors = [];
  711. this.figures = [];
  712. var decodeContext = {
  713. bitsPerCoordinate: dict.get('BitsPerCoordinate'),
  714. bitsPerComponent: dict.get('BitsPerComponent'),
  715. bitsPerFlag: dict.get('BitsPerFlag'),
  716. decode: dict.getArray('Decode'),
  717. colorFn: fn,
  718. colorSpace: cs,
  719. numComps: fn ? 1 : cs.numComps
  720. };
  721. var reader = new MeshStreamReader(stream, decodeContext);
  722. var patchMesh = false;
  723. switch (this.shadingType) {
  724. case ShadingType.FREE_FORM_MESH:
  725. decodeType4Shading(this, reader);
  726. break;
  727. case ShadingType.LATTICE_FORM_MESH:
  728. var verticesPerRow = dict.get('VerticesPerRow') | 0;
  729. (0, _util.assert)(verticesPerRow >= 2, 'Invalid VerticesPerRow');
  730. decodeType5Shading(this, reader, verticesPerRow);
  731. break;
  732. case ShadingType.COONS_PATCH_MESH:
  733. decodeType6Shading(this, reader);
  734. patchMesh = true;
  735. break;
  736. case ShadingType.TENSOR_PATCH_MESH:
  737. decodeType7Shading(this, reader);
  738. patchMesh = true;
  739. break;
  740. default:
  741. (0, _util.error)('Unsupported mesh type.');
  742. break;
  743. }
  744. if (patchMesh) {
  745. updateBounds(this);
  746. for (var i = 0, ii = this.figures.length; i < ii; i++) {
  747. buildFigureFromPatch(this, i);
  748. }
  749. }
  750. updateBounds(this);
  751. packData(this);
  752. }
  753. Mesh.prototype = {
  754. getIR: function Mesh_getIR() {
  755. return ['Mesh', this.shadingType, this.coords, this.colors, this.figures, this.bounds, this.matrix, this.bbox, this.background];
  756. }
  757. };
  758. return Mesh;
  759. }();
  760. Shadings.Dummy = function DummyClosure() {
  761. function Dummy() {
  762. this.type = 'Pattern';
  763. }
  764. Dummy.prototype = {
  765. getIR: function Dummy_getIR() {
  766. return ['Dummy'];
  767. }
  768. };
  769. return Dummy;
  770. }();
  771. function getTilingPatternIR(operatorList, dict, args) {
  772. var matrix = dict.getArray('Matrix');
  773. var bbox = _util.Util.normalizeRect(dict.getArray('BBox'));
  774. var xstep = dict.get('XStep');
  775. var ystep = dict.get('YStep');
  776. var paintType = dict.get('PaintType');
  777. var tilingType = dict.get('TilingType');
  778. if (bbox[2] - bbox[0] === 0 || bbox[3] - bbox[1] === 0) {
  779. throw new Error('getTilingPatternIR - invalid /BBox array: [' + bbox + '].');
  780. }
  781. return ['TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, paintType, tilingType];
  782. }
  783. exports.Pattern = Pattern;
  784. exports.getTilingPatternIR = getTilingPatternIR;