2
0

pattern.js 27 KB

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