Greasy Fork is available in English.

ExportPDF

2024/2/25 21:45:23

  1. // ==UserScript==
  2. // @name ExportPDF
  3. // @namespace Violentmonkey Scripts
  4. // @match *://www.doc88.com/*
  5. // @match http://localhost:8080/
  6. // @match https://www.docin.com/*
  7. // @match https://book.sciencereading.cn/shop/book/Booksimple/*
  8. // @grant none
  9. // @version 2.0
  10. // @author louiesun
  11. // @license GPL-3.0-or-later
  12. // @description 2024/2/25 21:45:23
  13. // ==/UserScript==
  14.  
  15. /*
  16.  
  17. // @require file:///D:/APPS/PDFexport/lib/blob-stream.js
  18. // @require file:///D:/APPS/PDFexport/lib/FileSaver.min.js
  19. // @require file:///D:/APPS/PDFexport/lib/pdfkit.standalone.js
  20. */
  21. //不能跑!! 测试请引用下方js can't run, please require the js above
  22. //笑死 完完全全是个图片
  23. /*
  24. * # 下载文库PDF
  25. 报废了。
  26. ## 技术背景
  27. 经过浏览器开发者模式发现,均采用`HTMLcanvas`渲染。
  28.  
  29. 发现Github项目[Canvas2PDF](https://github.com/joshua-gould/canvas2pdf)。
  30.  
  31. 同时,其`README.md`:
  32. > Canvas2PDF exports your HTML canvas as PDF using JavaScript. Note that this library generates actual PDF drawing calls to create a PDF with vector graphics, unlike some alternate libraries which rasterize your canvas and place it as an image in your PDF.
  33.  
  34. 说明不是截屏。
  35.  
  36. 那么这里就只需要重载canvasctx实现为`PDFcanvas`即可。
  37.  
  38. ## 劫持经验分享
  39. API比较多,需要面对`native code`,如果不想重编译V8引擎就找到替代函数或对象并使用。
  40.  
  41. 基本上需要改掉`document.createElement`,`element.innerHTML`,可能有其它的,遇到再说,就看有没有没有经过userjs“审查”的DOM元素创建。
  42.  
  43. ## 另外
  44. 如果`svg`元素实现,直接导出矢量。
  45. 如果`div`套套,就导出div。
  46.  
  47. 只有`canvas`是需要拦截的。
  48.  
  49. ## 这将是一个折磨
  50. cao,doc88从来没有传输过矢量内容,就过来一张图片。寄了。只能OCR。
  51. 但是我劫持了canvas。
  52.  
  53.  
  54.  
  55.  
  56. > Written with [StackEdit+](https://stackedit.net/).
  57. */
  58.  
  59. // https://github.com/devongovett/pdfkit/releases/download/v0.14.0/pdfkit.standalone.js
  60. // https://github.com/devongovett/blob-stream/releases/download/v0.1.3/blob-stream.js
  61. // https://github.com/eligrey/FileSaver.js/blob/master/dist/FileSaver.min.js can't be required
  62.  
  63. /*
  64. *
  65. * A canvas to PDF converter. Uses a mock canvas context to build a PDF document.
  66. *
  67. * Licensed under the MIT license:
  68. * http://www.opensource.org/licenses/mit-license.php
  69. *
  70. * Author:
  71. * Joshua Gould
  72. *
  73. * Copyright (c) 2017 Joshua Gould
  74. */
  75.  
  76. function hex(v) {
  77. return v < 0x10
  78. ? "0" + Math.max(0, v).toString(16)
  79. : Math.min(255, v).toString(16);
  80. }
  81.  
  82. function hslToHex(h, s, l, a) {
  83. h = (h % 360) + (h < 0) * 360;
  84. s = isNaN(h) || isNaN(s) ? 0 : s;
  85. const m2 = l + (l < 0.5 ? l : 1 - l) * s;
  86. const m1 = 2 * l - m2;
  87. return rgbToHex(
  88. hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
  89. hsl2rgb(h, m1, m2),
  90. hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
  91. a,
  92. );
  93. }
  94.  
  95. function hsl2rgb(h, m1, m2) {
  96. return (
  97. (h < 60
  98. ? m1 + ((m2 - m1) * h) / 60
  99. : h < 180
  100. ? m2
  101. : h < 240
  102. ? m1 + ((m2 - m1) * (240 - h)) / 60
  103. : m1) * 255
  104. );
  105. }
  106.  
  107. const reI = "\\s*([+-]?\\d+)\\s*",
  108. reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
  109. reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
  110. reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"),
  111. reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"),
  112. reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"),
  113. reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"),
  114. reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"),
  115. reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
  116.  
  117. const rgbToHex = function (r, g, b, a) {
  118. return { c: "#" + hex(r) + hex(g) + hex(b), a: a };
  119. };
  120.  
  121. const fixColor = function (value) {
  122. let m;
  123. const format = (value + "").trim().toLowerCase();
  124. if ((m = reRgbInteger.exec(format))) {
  125. // rgb(255, 0, 0)
  126. return rgbToHex(m[1], m[2], m[3], 1);
  127. } else if ((m = reRgbPercent.exec(format))) {
  128. // // rgb(100%, 0%, 0%)
  129. return rgbToHex(
  130. (m[1] * 255) / 100,
  131. (m[2] * 255) / 100,
  132. (m[3] * 255) / 100,
  133. 1,
  134. );
  135. } else if ((m = reRgbaInteger.exec(format))) {
  136. // // rgba(255, 0, 0, 0.5)
  137. return rgbToHex(m[1], m[2], m[3], m[4]);
  138. } else if ((m = reRgbaPercent.exec(format))) {
  139. // // rgb(100%, 0%, 0%, .2)
  140. return rgbToHex(
  141. (m[1] * 255) / 100,
  142. (m[2] * 255) / 100,
  143. (m[3] * 255) / 100,
  144. m[4],
  145. );
  146. } else if ((m = reHslPercent.exec(format))) {
  147. // // hsl(120, 50%, 50%)
  148. return hslToHex(m[1], m[2] / 100, m[3] / 100);
  149. } else if ((m = reHslaPercent.exec(format))) {
  150. return hslToHex(m[1], m[2] / 100, m[3] / 100, m[4]); // hsla(120, 50%, 50%, 1)
  151. } else {
  152. return { c: value, a: 1 };
  153. }
  154. };
  155. /**
  156. *
  157. * @param stream Stream to write the PDF to.
  158. * @param options Options passed to PDFDocument constructor.
  159. * @constructor
  160. */
  161. const PdfContext = function (stream, options) {
  162. if (stream == null) {
  163. throw new Error("Stream must be provided.");
  164. }
  165.  
  166. const doc = new PDFDocument(options);
  167. this.stream = doc.pipe(stream);
  168. let fontValue = "10px Helvetica";
  169. let textAlign = "left";
  170. let textBaseline = "alphabetic";
  171. let lineHeight = doc.currentLineHeight(false);
  172. let font = fontValue;
  173.  
  174. const fontRegex =
  175. /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\'\"\sa-z]+?)\s*$/i;
  176. const defaultFontData = {
  177. style: "normal",
  178. size: 10,
  179. family: "Helvetica",
  180. weight: "normal",
  181. };
  182. const parseFont = function () {
  183. const fontPart = fontRegex.exec(font);
  184. if (fontPart === null) {
  185. return defaultFontData;
  186. }
  187. const data = {
  188. style: fontPart[1] || "normal",
  189. size: parseInt(fontPart[4]) || 10,
  190. family: fontPart[6] || "Helvetica",
  191. weight: fontPart[3] || "normal",
  192. };
  193. return data;
  194. };
  195.  
  196. Object.defineProperty(this, "fillStyle", {
  197. get: function () {
  198. return doc.fillColor();
  199. },
  200. set: function (value) {
  201. const color = fixColor(value);
  202. doc.fillColor(color.c, color.a);
  203. },
  204. });
  205. Object.defineProperty(this, "strokeStyle", {
  206. get: function () {
  207. return doc.strokeColor();
  208. },
  209. set: function (value) {
  210. const color = fixColor(value);
  211. doc.strokeColor(color.c, color.a);
  212. },
  213. });
  214. Object.defineProperty(this, "lineWidth", {
  215. get: function () {
  216. return doc.lineWidth();
  217. },
  218. set: function (value) {
  219. doc.lineWidth(value);
  220. },
  221. });
  222.  
  223. Object.defineProperty(this, "lineCap", {
  224. get: function () {
  225. return doc.lineCap();
  226. },
  227. set: function (value) {
  228. doc.lineCap(value);
  229. },
  230. });
  231. Object.defineProperty(this, "lineJoin", {
  232. get: function () {
  233. return doc.lineJoin();
  234. },
  235. set: function (value) {
  236. doc.lineJoin(value);
  237. },
  238. });
  239.  
  240. Object.defineProperty(this, "globalAlpha", {
  241. get: function () {
  242. return doc.opacity();
  243. },
  244. set: function (value) {
  245. value >= 0.0 && value <= 1.0 && doc.opacity(value);
  246. },
  247. });
  248.  
  249. Object.defineProperty(this, "font", {
  250. get: function () {
  251. return fontValue;
  252. },
  253. set: function (value) {
  254. fontValue = value;
  255. const parsedFont = parseFont(value);
  256. doc.fontSize(parsedFont.size);
  257. doc.font(parsedFont.family);
  258. lineHeight = doc.currentLineHeight(false);
  259. },
  260. });
  261.  
  262. this.end = function () {
  263. doc.end();
  264. };
  265.  
  266. this.save = function () {
  267. doc.save();
  268. };
  269.  
  270. this.restore = function () {
  271. doc.restore();
  272. };
  273.  
  274. this.scale = function (x, y) {
  275. doc.scale(x, y);
  276. };
  277.  
  278. this.rotate = function (angle) {
  279. const degrees = (angle * 180) / Math.PI;
  280. doc.rotate(degrees);
  281. };
  282.  
  283. this.translate = function (x, y) {
  284. doc.translate(x, y);
  285. };
  286.  
  287. this.transform = function (a, b, c, d, e, f) {
  288. doc.transform(a, b, c, d, e, f);
  289. };
  290.  
  291. this.beginPath = function () {
  292. // no-op
  293. };
  294.  
  295. this.moveTo = function (x, y) {
  296. doc.moveTo(x, y);
  297. };
  298.  
  299. this.closePath = function () {
  300. doc.closePath();
  301. };
  302.  
  303. this.lineTo = function (x, y) {
  304. doc.lineTo(x, y);
  305. };
  306.  
  307. this.stroke = function () {
  308. doc.stroke();
  309. };
  310.  
  311. this.fill = function () {
  312. doc.fill();
  313. };
  314.  
  315. this.rect = function (x, y, width, height) {
  316. doc.rect(x, y, width, height);
  317. };
  318.  
  319. this.fillRect = function (x, y, width, height) {
  320. doc.rect(x, y, width, height);
  321. doc.fill();
  322. };
  323.  
  324. this.strokeRect = function (x, y, width, height) {
  325. doc.rect(x, y, width, height);
  326. doc.stroke();
  327. };
  328.  
  329. /**
  330. * "Clears" a canvas by just drawing a white rectangle in the current group.
  331. */
  332. this.clearRect = function (x, y, width, height) {
  333. const oldFill = doc.fillColor();
  334. doc.fillColor("white");
  335. doc.rect(x, y, width, height);
  336. doc.fill();
  337. doc.fillColor(oldFill);
  338. };
  339.  
  340. this.arc = function (x, y, r, a0, a1, ccw) {
  341. const pi = Math.PI,
  342. tau = 2 * pi,
  343. epsilon = 1e-6,
  344. tauEpsilon = tau - epsilon;
  345. (x = +x), (y = +y), (r = +r);
  346. let dx = r * Math.cos(a0),
  347. dy = r * Math.sin(a0),
  348. x0 = x + dx,
  349. y0 = y + dy,
  350. cw = 1 ^ ccw,
  351. da = ccw ? a0 - a1 : a1 - a0;
  352.  
  353. // Is the radius negative? Error.
  354. if (r < 0) {
  355. throw new Error("negative radius: " + r);
  356. }
  357. let cmd = "";
  358. // Is this path empty? Move to (x0,y0).
  359.  
  360. cmd += "M" + x0 + "," + y0;
  361.  
  362. // // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).
  363. // else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) {
  364. // cmd += 'L' + x0 + ',' + y0;
  365. // }
  366.  
  367. // Is this arc empty? We’re done.
  368. if (!r) {
  369. return;
  370. }
  371.  
  372. // Does the angle go the wrong way? Flip the direction.
  373. if (da < 0) {
  374. da = (da % tau) + tau;
  375. }
  376.  
  377. // Is this a complete circle? Draw two arcs to complete the circle.
  378. if (da > tauEpsilon) {
  379. cmd +=
  380. "A" +
  381. r +
  382. "," +
  383. r +
  384. ",0,1," +
  385. cw +
  386. "," +
  387. (x - dx) +
  388. "," +
  389. (y - dy) +
  390. "A" +
  391. r +
  392. "," +
  393. r +
  394. ",0,1," +
  395. cw +
  396. "," +
  397. x0 +
  398. "," +
  399. y0;
  400. }
  401.  
  402. // Is this arc non-empty? Draw an arc!
  403. else if (da > epsilon) {
  404. cmd +=
  405. "A" +
  406. r +
  407. "," +
  408. r +
  409. ",0," +
  410. +(da >= pi) +
  411. "," +
  412. cw +
  413. "," +
  414. (x + r * Math.cos(a1)) +
  415. "," +
  416. (y + r * Math.sin(a1));
  417. }
  418. doc.path(cmd);
  419. };
  420.  
  421. this.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
  422. doc.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
  423. };
  424.  
  425. this.quadraticCurveTo = function (cpx, cpy, x, y) {
  426. doc.quadraticCurveTo(cpx, cpy, x, y);
  427. };
  428. this.createLinearGradient = function (x1, y1, x2, y2) {
  429. const gradient = doc.linearGradient(x1, y1, x2, y2);
  430. gradient.addColorStop = function (offset, color) {
  431. const fixedColor = fixColor(color);
  432. gradient.stop(offset, fixedColor.c, fixedColor.a);
  433. };
  434. return gradient;
  435. };
  436.  
  437. this.createRadialGradient = function (x0, y0, r0, x1, y1, r1) {
  438. const gradient = doc.radialGradient(x0, y0, r0, x1, y1, r1);
  439. gradient.addColorStop = function (offset, color) {
  440. const fixedColor = fixColor(color);
  441. gradient.stop(offset, fixedColor.c, fixedColor.a);
  442. };
  443. return gradient;
  444. };
  445.  
  446. this.adjustTextX = function (text, x) {
  447. if (textAlign !== "start" || textAlign !== "left") {
  448. const width = doc.widthOfString(text);
  449. if (textAlign === "right" || textAlign === "end") {
  450. x -= width;
  451. } else if (textAlign === "center") {
  452. x -= width / 2;
  453. }
  454. }
  455. return x;
  456. };
  457.  
  458. this.adjustTextY = function (text, y) {
  459. // baseline is top by default
  460. if (textBaseline === "bottom") {
  461. y -= lineHeight;
  462. } else if (textBaseline === "middle") {
  463. y -= lineHeight / 2;
  464. } else if (textBaseline === "alphabetic") {
  465. y -= lineHeight / 2 + 1;
  466. }
  467. return y;
  468. };
  469.  
  470. this.fillText = function (text, x, y) {
  471. x = this.adjustTextX(text, x);
  472. y = this.adjustTextY(text, y);
  473. doc.text(text, x, y, {
  474. lineBreak: false,
  475. stroke: false,
  476. fill: true,
  477. });
  478. };
  479.  
  480. this.strokeText = function (text, x, y) {
  481. x = this.adjustTextX(text, x);
  482. y = this.adjustTextY(text, y);
  483. doc.text(text, x, y, { lineBreak: false, stroke: true, fill: false });
  484. };
  485.  
  486. this.measureText = function (text) {
  487. text = "" + text;
  488. const width = doc.widthOfString(text);
  489. return { width: width, height: lineHeight };
  490. };
  491.  
  492. this.clip = function () {
  493. doc.clip();
  494. };
  495.  
  496. this.drawImage = function (image) {
  497. const args = Array.prototype.slice.call(arguments);
  498. image = args[0];
  499. let dx,
  500. dy,
  501. dw,
  502. dh,
  503. sx = 0,
  504. sy = 0,
  505. sw,
  506. sh;
  507. if (args.length === 3) {
  508. dx = args[1];
  509. dy = args[2];
  510. sw = image.width;
  511. sh = image.height;
  512. dw = sw;
  513. dh = sh;
  514. } else if (args.length === 5) {
  515. dx = args[1];
  516. dy = args[2];
  517. dw = args[3];
  518. dh = args[4];
  519. sw = image.width;
  520. sh = image.height;
  521. } else if (args.length === 9) {
  522. sx = args[1];
  523. sy = args[2];
  524. sw = args[3];
  525. sh = args[4];
  526. dx = args[5];
  527. dy = args[6];
  528. dw = args[7];
  529. dh = args[8];
  530. } else {
  531. throw new Error(
  532. "Invalid number of arguments passed to drawImage: " + arguments.length,
  533. );
  534. }
  535.  
  536. if (image.nodeName === "IMG") {
  537. const canvas = document.createElement("tcanvas");
  538. canvas.width = image.width;
  539. canvas.height = image.height;
  540. canvas.getContext("2d").drawImage(image, 0, 0);
  541. const dataURL = canvas.toDataURL("image/png");
  542. doc.image(dataURL, dx, dy, { width: dw, height: dh });
  543. } else {
  544. doc.image(image, dx, dy, { width: dw, height: dh });
  545. }
  546. };
  547.  
  548. this.setTransform = function (a, b, c, d, e, f) {
  549. const ctm = doc._ctm;
  550. const height = doc.page.height;
  551. const [a1, b1, c1, d1, e1, f1] = ctm;
  552. const determinant = a1 * d1 - b1 * c1;
  553. const inverse = [
  554. d1 / determinant,
  555. -b1 / determinant,
  556. -c1 / determinant,
  557. a1 / determinant,
  558. (c1 * f1 - d1 * e1) / determinant,
  559. (b1 * e1 - a1 * f1) / determinant,
  560. ];
  561. doc.transform(
  562. inverse[0],
  563. inverse[1],
  564. inverse[2],
  565. inverse[3],
  566. inverse[4],
  567. inverse[5],
  568. );
  569. doc.translate(0, height);
  570. doc.scale(1, -1);
  571. doc.transform(a, b, c, d, e, f);
  572. };
  573.  
  574. /**
  575. * Not yet implemented
  576. */
  577. this.createPattern = function (image, repetition) {
  578. console.log("createPattern not implemented");
  579. };
  580.  
  581. this.setLineDash = function (dashArray) {
  582. console.log("setLineDash not implemented");
  583. };
  584.  
  585. this.drawFocusIfNeeded = function () {
  586. console.log("drawFocusIfNeeded not implemented");
  587. };
  588.  
  589. this.createImageData = function () {
  590. console.log("drawFocusRing not implemented");
  591. };
  592.  
  593. this.getImageData = function () {
  594. console.log("getImageData not implemented");
  595. };
  596.  
  597. this.putImageData = function () {
  598. console.log("putImageData not implemented");
  599. };
  600.  
  601. this.globalCompositeOperation = function () {
  602. console.log("globalCompositeOperation not implemented");
  603. };
  604.  
  605. this.arcTo = function (x1, y1, x2, y2, radius) {
  606. console.log("arcTo not implemented");
  607. };
  608. };
  609.  
  610.  
  611. const ProxyContext = function (HTMLctx) {
  612. if (HTMLctx == null) {
  613. throw new Error("Origin Canvas must be provided.");
  614. }
  615. let PDFctx=new PdfContext(blobStream());
  616.  
  617. Object.defineProperty(this, "font", {
  618. get: function () {
  619. return HTMLctx.font;
  620. },
  621. set: function (value) {
  622. HTMLctx.font=value;
  623. PDFctx.font=value;
  624. },
  625. });
  626. Object.defineProperty(this, "textAlign", {
  627. get: function () {
  628. return HTMLctx.textAlign;
  629. },
  630. set: function (value) {
  631. HTMLctx.fontValue=value;
  632. PDFctx.fontValue=value;
  633. },
  634. });
  635. Object.defineProperty(this, "textBaseline", {
  636. get: function () {
  637. return HTMLctx.textBaseline;
  638. },
  639. set: function (value) {
  640. HTMLctx.fontValue=value;
  641. PDFctx.fontValue=value;
  642. },
  643. });
  644. Object.defineProperty(this, "fontRegex", {
  645. get: function () {
  646. return HTMLctx.fontRegex;
  647. },
  648. set: function (value) {
  649. HTMLctx.fontRegex=value;
  650. PDFctx.fontRegex=value;
  651. },
  652. });
  653. Object.defineProperty(this, "fillStyle", {
  654. get: function () {
  655. return HTMLctx.fillStyle;
  656. },
  657. set: function (value) {
  658. HTMLctx.fillStyle=value;
  659. PDFctx.fillStyle=value;
  660. },
  661. });
  662. Object.defineProperty(this, "strokeStyle", {
  663. get: function () {
  664. return HTMLctx.strokeStyle;
  665. },
  666. set: function (value) {
  667. HTMLctx.strokeStyle=value;
  668. PDFctx.strokeStyle=value;
  669. },
  670. });
  671. Object.defineProperty(this, "lineWidth", {
  672. get: function () {
  673. return HTMLctx.lineWidth;
  674. },
  675. set: function (value) {
  676. HTMLctx.lineWidth=value;
  677. PDFctx.lineWidth=value;
  678. },
  679. });
  680.  
  681. Object.defineProperty(this, "lineCap", {
  682. get: function () {
  683. return HTMLctx.lineCap;
  684. },
  685. set: function (value) {
  686. HTMLctx.lineCap=value;
  687. PDFctx.lineCap=value;
  688. },
  689. });
  690. Object.defineProperty(this, "lineJoin", {
  691. get: function () {
  692. return HTMLctx.lineJoin;
  693. },
  694. set: function (value) {
  695. HTMLctx.lineJoin=value;
  696. PDFctx.lineJoin=value;
  697. },
  698. });
  699.  
  700. Object.defineProperty(this, "globalAlpha", {
  701. get: function () {
  702. return HTMLctx.globalAlpha;
  703. },
  704. set: function (value) {
  705. HTMLctx.globalAlpha=value;
  706. PDFctx.globalAlpha=value;
  707. },
  708. });
  709.  
  710.  
  711. this.end = function (...arvs) {
  712. return PDFctx.end(...arvs);
  713. };
  714. this.save = function (...arvs) {
  715. PDFctx.save(...arvs);
  716. return HTMLctx.save(...arvs);
  717. };
  718. this.restore = function (...arvs) {
  719. PDFctx.restore(...arvs);
  720. return HTMLctx.restore(...arvs);
  721. };
  722. this.scale = function (...arvs) {
  723. PDFctx.scale(...arvs);
  724. return HTMLctx.scale(...arvs);
  725. };
  726. this.rotate = function (...arvs) {
  727. PDFctx.rotate(...arvs);
  728. return HTMLctx.rotate(...arvs);
  729. };
  730.  
  731. this.translate = function (...arvs) {
  732. PDFctx.translate(...arvs);
  733. return HTMLctx.translate(...arvs);
  734. };
  735.  
  736. this.transform = function (...arvs) {
  737. PDFctx.transform(...arvs);
  738. return HTMLctx.transform(...arvs);
  739. };
  740.  
  741. this.beginPath = function (...arvs) {
  742. PDFctx.beginPath(...arvs);
  743. return HTMLctx.beginPath(...arvs);
  744. };
  745.  
  746. this.moveTo = function (...arvs) {
  747. PDFctx.moveTo(...arvs);
  748. return HTMLctx.moveTo(...arvs);
  749. };
  750.  
  751. this.closePath = function (...arvs) {
  752. PDFctx.closePath(...arvs);
  753. return HTMLctx.closePath(...arvs);
  754. };
  755.  
  756. this.lineTo = function (...arvs) {
  757. PDFctx.lineTo(...arvs);
  758. return HTMLctx.lineTo(...arvs);
  759. };
  760.  
  761. this.stroke = function (...arvs) {
  762. PDFctx.stroke(...arvs);
  763. return HTMLctx.stroke(...arvs);
  764. };
  765.  
  766. this.fill = function (...arvs) {
  767. PDFctx.fill(...arvs);
  768. return HTMLctx.fill(...arvs);
  769. };
  770.  
  771. this.rect = function (...arvs) {
  772. PDFctx.rect(...arvs);
  773. return HTMLctx.rect(...arvs);
  774. };
  775.  
  776. this.fillRect = function (...arvs) {
  777. PDFctx.fillRect(...arvs);
  778. return HTMLctx.fillRect(...arvs);
  779. };
  780.  
  781. this.strokeRect = function (...arvs) {
  782. PDFctx.strokeRect(...arvs);
  783. return HTMLctx.strokeRect(...arvs);
  784. };
  785.  
  786. /**
  787. * "Clears" a canvas by just drawing a white rectangle in the current group.
  788. */
  789. this.clearRect = function (...arvs) {
  790. PDFctx.clearRect(...arvs);
  791. return HTMLctx.clearRect(...arvs);
  792. };
  793.  
  794. this.arc = function (...arvs) {
  795. PDFctx.arc(...arvs);
  796. return HTMLctx.arc(...arvs);
  797. };
  798.  
  799. this.bezierCurveTo = function (...arvs) {
  800. PDFctx.bezierCurveTo(...arvs);
  801. return HTMLctx.bezierCurveTo(...arvs);
  802. };
  803.  
  804. this.quadraticCurveTo = function (...arvs) {
  805. PDFctx.quadraticCurveTo(...arvs);
  806. return HTMLctx.quadraticCurveTo(...arvs);
  807. };
  808. this.createLinearGradient = function (...arvs) {
  809. PDFctx.createLinearGradient(...arvs);
  810. return HTMLctx.createLinearGradient(...arvs);
  811. };
  812.  
  813. this.createRadialGradient = function (...arvs) {
  814. PDFctx.createRadialGradient(...arvs);
  815. return HTML.createRadialGradient(...arvs);
  816. };
  817.  
  818. this.adjustTextX = function (...arvs) {
  819. return PDFctx.adjustTextX(...arvs);
  820. };
  821.  
  822. this.adjustTextY = function (...arvs) {
  823. return PDFctx.adjustTextY(...arvs);
  824. };
  825.  
  826. this.fillText = function (...arvs) {
  827. PDFctx.fillText(...arvs);
  828. return HTMLctx.fillText(...arvs);
  829. };
  830.  
  831. this.strokeText = function (...arvs) {
  832. PDFctx.strokeText(...arvs);
  833. return HTMLctx.strokeText(...arvs);
  834. };
  835.  
  836. this.clip = function (...arvs) {
  837. PDFctx.clip(...arvs);
  838. return HTMLctx.clip(...arvs);
  839. };
  840.  
  841. this.drawImage = function (...arvs) {
  842. PDFctx.drawImage(...arvs);
  843. return HTMLctx.drawImage(...arvs);
  844. };
  845.  
  846. this.setTransform = function (...arvs) {
  847. PDFctx.setTransform(...arvs);
  848. return HTMLctx.setTransform(...arvs);
  849. };
  850.  
  851. this.ExportPDF = function(...arvs)
  852. {
  853. PDFctx.stream.on('finish', function (...arvs) {
  854. var blob = PDFctx.stream.toBlob(...arvs);
  855. saveAs(...arvs);
  856. });
  857. PDFctx.end(...arvs);
  858. console.log(...arvs);
  859. //backgroud un completed https://segmentfault.com/a/1190000016819776
  860. }
  861.  
  862. /**
  863. * Not yet implemented
  864. */
  865. this.createPattern = function (...arvs) {
  866. return HTMLctx.createImageData(...arvs);
  867. };
  868.  
  869. this.setLineDash = function (...arvs) {
  870. return HTMLctx.createImageData(...arvs);
  871. };
  872.  
  873. this.drawFocusIfNeeded = function (...arvs) {
  874. PDFctx.drawFocusIfNeeded(...arvs);
  875. return HTMLctx.drawFocusIfNeeded(...arvs);
  876. };
  877.  
  878. this.createImageData = function (...arvs) {
  879. PDFctx.createImageData(...arvs);
  880. return HTMLctx.createImageData(...arvs);
  881. };
  882.  
  883. this.getImageData = function (...arvs) {
  884. PDFctx.getImageData(...arvs);
  885. return HTMLctx.getImageData(...arvs);
  886. };
  887.  
  888. this.putImageData = function (...arvs) {
  889. PDFctx.putImageData(...arvs);
  890. return HTMLctx.putImageData(...arvs);
  891. };
  892.  
  893. this.globalCompositeOperation = function (...arvs) {
  894. PDFctx.globalCompositeOperation(...arvs);
  895. return HTMLctx.globalCompositeOperation(...arvs);
  896. };
  897.  
  898. this.arcTo = function (...arvs) {
  899. PDFctx.globalCompositeOperation(...arvs);
  900. return HTMLctx.globalCompositeOperation(...arvs);
  901. };
  902. };
  903.  
  904. var HTMLElememtNameList=['modernizr','link','meta','style','script','noscript','template','body','section','nav','article','aside','h1','h2','h3','h4','h5','h6','header','footer','address','main','p','hr','pre','blockquote','ol','ul','li','dl','dt','dd','figure','figcaption','div','a','em','strong','small','s','cite','q','dfn','abbr','data','time','code','var','samp','kbd','sub','i','b','u','mark','ruby','rt','rp','bdi','bdo','span','br','wbr','ins','del','img','iframe','embed','object','param','video','audio','source','track','canvas','map','area','svg','math','table','caption','colgroup','col','tbody','thead','tfoot','tr','td','th','form','fieldset','legend','label','input','button','select','datalist','optgroup','option','textarea','keygen','output','progress','meter','details','summary','menuitem','menu'];
  905. var HTMLElementList=new Array(HTMLElememtNameList.length);
  906.  
  907. document.ElementList=HTMLElementList;
  908.  
  909. function ElementInit()
  910. {
  911. for(let i=0; i<HTMLElememtNameList.length; i++)
  912. HTMLElementList[i]=document.createElement(HTMLElememtNameList[i]);
  913. }
  914. ElementInit();
  915.  
  916. /*
  917. var PDFcanvasElement = Object.create(HTMLCanvasElement.prototype);
  918. PDFcanvasElement.createdCallback = function()
  919. {
  920.  
  921. };
  922. var PDFcanvasImage = window.registerElement('pdf-canvas', { prototype: HTMLElementList, extends: 'canvas' });
  923. */
  924.  
  925. // Create a class for the element
  926. /*class PDFcanvasElement extends HTMLCanvasElement {
  927. createdCallback() {
  928. this.PROXYcontext=new ProxyContext(this.getContext("2d"));
  929. this.getContext=function()
  930. {
  931. return this.PROXYcontext;
  932. };
  933. }
  934. }*/
  935. /*
  936. const { createElement: originalCreateElement } = document;
  937. document.createElement = function createElement(...args) {
  938. // function fetch() { [native code] }
  939. console.log("ele call intercepted:", ...args);
  940. return originalCreateElement(...args);
  941. };
  942. */
  943.  
  944. //customElements.define("pdf-canvas", PDFcanvasElement, { extends: "canvas" });
  945.  
  946. /*let MYcreateElement=deepClone(document.createElement);*/
  947.  
  948. function SpecialCare(elem,tagName)
  949. {
  950. if(tagName=="canvas")
  951. {
  952. elem.PROXYcontext=new ProxyContext(elem.getContext("2d"));
  953. elem.getContext=function()
  954. {
  955. return this.PROXYcontext;
  956. };
  957. console.log(elem);
  958. }
  959. Object.defineProperty(elem, "innerHTML", {
  960. set: function (str) {
  961. var telem=HTMLElementList[HTMLElememtNameList.indexOf(tagName)].cloneNode();
  962. telem.innerHTML=str;
  963.  
  964. //process the special cares.
  965. let child=telem.firstChild;
  966. while(child)
  967. {
  968. //console.log(child.nodeName);
  969. SpecialCare(child,child.nodeName.toLowerCase());
  970. child=child.nextSibling;
  971. }
  972.  
  973. while (this.firstChild) {
  974. this.removeChild(elem.lastChild);
  975. }
  976. this.appendChild(telem);
  977. //console.log(str);
  978. },
  979. });
  980. }
  981.  
  982. document.createElement = function (tagName, className, parent) {
  983. //console.log(tagName,className,parent);
  984. tagName=tagName.toLowerCase();
  985. var elem,agent=0;
  986.  
  987. //check the element create by this user js
  988. if(tagName == "tcanvas")
  989. {
  990. agent=1,tagName="canvas";
  991. }
  992. else if(tagName == "tdiv")
  993. {
  994. agent=1,tagName="div";
  995. }
  996.  
  997. //create
  998. if(HTMLElememtNameList.indexOf(tagName)>-1){
  999. elem=HTMLElementList[HTMLElememtNameList.indexOf(tagName)].cloneNode();
  1000.  
  1001. }
  1002. else
  1003. {
  1004. alert("PDFexporter Error! New element registered by the page. To be finished. ");
  1005. console.log(tagName);
  1006. elem=_documentcreateElement(tagName);
  1007. }
  1008.  
  1009. //spcial care
  1010. if(agent==0)
  1011. {
  1012. SpecialCare(elem,tagName);
  1013. }
  1014.  
  1015. if (className) {
  1016. elem.className = className || '';
  1017. }
  1018. if (parent) {
  1019. parent.appendChild(elem);
  1020. }
  1021. //console.log(elem);
  1022. return elem;
  1023. }
  1024. //
  1025. // you may need https://github.com/lisonge/Disable-CSP
  1026.  
  1027. //HTMLCanvasElement.prototype.createdCallback=(){};
  1028.  
  1029.  
  1030.