pattern.js 27 KB

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