@u1f992/pdfdiff 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/.github/workflows/gh-pages.yml +6 -1
  2. package/dist/browser.js +1219 -19
  3. package/dist/browser.js.map +1 -1
  4. package/dist/cli-png-worker.d.ts +13 -0
  5. package/dist/cli-png-worker.d.ts.map +1 -0
  6. package/dist/cli-png-worker.js +303 -0
  7. package/dist/cli-png-worker.js.map +1 -0
  8. package/dist/cli.js +240 -26
  9. package/dist/cli.js.map +1 -1
  10. package/dist/diff.d.ts +2 -1
  11. package/dist/diff.d.ts.map +1 -1
  12. package/dist/image.d.ts.map +1 -1
  13. package/dist/index.d.ts +2 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.html +6 -1
  16. package/dist/index.js +123 -15
  17. package/dist/index.js.map +1 -1
  18. package/dist/pdf.d.ts.map +1 -1
  19. package/dist/perf.d.ts +16 -0
  20. package/dist/perf.d.ts.map +1 -0
  21. package/dist/squoosh_png_bg.wasm +0 -0
  22. package/dist/style.css +12 -0
  23. package/dist/transferable.d.ts +7 -0
  24. package/dist/transferable.d.ts.map +1 -0
  25. package/dist/version.d.ts +2 -0
  26. package/dist/version.d.ts.map +1 -0
  27. package/dist/worker.d.ts +9 -0
  28. package/dist/worker.d.ts.map +1 -1
  29. package/dist/worker.js +274 -88
  30. package/dist/worker.js.map +1 -1
  31. package/package.json +5 -2
  32. package/rollup.config.js +20 -0
  33. package/scripts/version.ts +35 -0
  34. package/src/browser.ts +119 -5
  35. package/src/cli-png-worker.ts +59 -0
  36. package/src/cli.ts +106 -21
  37. package/src/diff.ts +99 -34
  38. package/src/image.ts +3 -0
  39. package/src/index.html +6 -1
  40. package/src/index.ts +53 -27
  41. package/src/pdf.ts +9 -1
  42. package/src/perf.ts +94 -0
  43. package/src/style.css +12 -0
  44. package/src/transferable.ts +30 -0
  45. package/src/worker.ts +77 -54
package/dist/pdf.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"pdf.d.ts","sourceRoot":"","sources":["../src/pdf.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,wBAAiB,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,wDAI7C;AA8BD,wBAAsB,WAAW,CAC/B,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,yBAcf"}
1
+ {"version":3,"file":"pdf.d.ts","sourceRoot":"","sources":["../src/pdf.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAG9C,wBAAiB,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,wDAI7C;AA8BD,wBAAsB,WAAW,CAC/B,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,yBAqBf"}
package/dist/perf.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ export type Counters = Readonly<Record<string, number>>;
2
+ export type Span = {
3
+ stop(): void;
4
+ };
5
+ type Perf = {
6
+ readonly enabled: boolean;
7
+ span(key: string): Span;
8
+ incr(key: string, delta?: number): void;
9
+ setMax(key: string, value: number): void;
10
+ merge(other: Counters): void;
11
+ dump(): Counters;
12
+ reset(): void;
13
+ };
14
+ export declare const perf: Perf;
15
+ export {};
16
+ //# sourceMappingURL=perf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perf.d.ts","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"AAiCA,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAExD,MAAM,MAAM,IAAI,GAAG;IAAE,IAAI,IAAI,IAAI,CAAA;CAAE,CAAC;AAEpC,KAAK,IAAI,GAAG;IACV,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,KAAK,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC7B,IAAI,IAAI,QAAQ,CAAC;IACjB,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AAgDF,eAAO,MAAM,IAAI,EAAE,IAAuC,CAAC"}
Binary file
package/dist/style.css CHANGED
@@ -11,9 +11,21 @@
11
11
  .diff-table {
12
12
  border: 1px solid black;
13
13
  border-collapse: collapse;
14
+ width: 100%;
15
+ table-layout: fixed;
14
16
  }
15
17
 
16
18
  .diff-table th,
17
19
  .diff-table td {
18
20
  border: 1px solid black;
19
21
  }
22
+
23
+ .diff-table img {
24
+ display: block;
25
+ max-width: 100%;
26
+ height: auto;
27
+ }
28
+
29
+ body.hide-no-diff .diff-details.no-diff {
30
+ display: none;
31
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Slice a typed-array view into a standalone backing buffer of the same kind
3
+ * (ArrayBuffer in, ArrayBuffer out; SharedArrayBuffer in, SharedArrayBuffer
4
+ * out). The buffer kind is preserved through the generic parameter.
5
+ */
6
+ export declare function sliceBackingBuffer<TArrayBuffer extends ArrayBufferLike>(src: Uint8Array<TArrayBuffer> | Uint8ClampedArray<TArrayBuffer>): TArrayBuffer;
7
+ //# sourceMappingURL=transferable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transferable.d.ts","sourceRoot":"","sources":["../src/transferable.ts"],"names":[],"mappings":"AAiBA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,SAAS,eAAe,EACrE,GAAG,EAAE,UAAU,CAAC,YAAY,CAAC,GAAG,iBAAiB,CAAC,YAAY,CAAC,GAC9D,YAAY,CAKd"}
@@ -0,0 +1,2 @@
1
+ export declare const VERSION = "0.2.2";
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAU,CAAC"}
package/dist/worker.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { type Pallet } from "./diff.ts";
2
2
  import { type AlignStrategy } from "./image.ts";
3
+ import { type Counters } from "./perf.ts";
3
4
  export type InitMessage = {
4
5
  type: "init";
5
6
  aBytes: Uint8Array;
@@ -14,6 +15,9 @@ export type PageMessage = {
14
15
  type: "page";
15
16
  index: number;
16
17
  };
18
+ export type LoadedMessage = {
19
+ type: "loaded";
20
+ };
17
21
  export type ReadyMessage = {
18
22
  type: "ready";
19
23
  };
@@ -38,5 +42,10 @@ export type PageResultMessage = {
38
42
  addition: [number, number][];
39
43
  deletion: [number, number][];
40
44
  modification: [number, number][];
45
+ perf?: Counters | undefined;
46
+ };
47
+ export type ErrorMessage = {
48
+ type: "error";
49
+ message: string;
41
50
  };
42
51
  //# sourceMappingURL=worker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAkB,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAIpB,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC;IACxD,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC;IACxD,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC;IAC3D,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IAC7B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IAC7B,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;CAClC,CAAC"}
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAkB,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGhD,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,QAAQ,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC;IACxD,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC;IACxD,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC;IAC3D,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IAC7B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IAC7B,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IACjC,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC"}
package/dist/worker.js CHANGED
@@ -3212,6 +3212,82 @@ read:function(e,t,i,r,n){var a,o,s=8*n-r-1,l=(1<<s)-1,u=l>>1,h=-7,c=i?n-1:0,f=i?
3212
3212
  * rgbquant.ts - part of Image Quantization Library
3213
3213
  */"function"==typeof setImmediate?setImmediate:"undefined"!=typeof process&&(null==process||process.nextTick);const QuantizeOptionsSchema=z.object({colors:z.number().optional(),colorDistanceFormula:z.union([z.literal("cie94-textiles"),z.literal("cie94-graphic-arts"),z.literal("ciede2000"),z.literal("color-metric"),z.literal("euclidean"),z.literal("euclidean-bt709-noalpha"),z.literal("euclidean-bt709"),z.literal("manhattan"),z.literal("manhattan-bt709"),z.literal("manhattan-nommyde"),z.literal("pngquant")]).optional(),paletteQuantization:z.union([z.literal("neuquant"),z.literal("neuquant-float"),z.literal("rgbquant"),z.literal("wuquant")]).optional(),imageQuantization:z.union([z.literal("nearest"),z.literal("riemersma"),z.literal("floyd-steinberg"),z.literal("false-floyd-steinberg"),z.literal("stucki"),z.literal("atkinson"),z.literal("jarvis"),z.literal("burkes"),z.literal("sierra"),z.literal("two-sierra"),z.literal("sierra-lite")]).optional()}),methods={quantize(e,t){const{colors:i,colorDistanceFormula:r,paletteQuantization:n,imageQuantization:a}=QuantizeOptionsSchema.parse(t),o=utils_exports.PointContainer.fromUint8Array(e.bitmap.data,e.bitmap.width,e.bitmap.height),s=applyPaletteSync(o,buildPaletteSync([o],{colors:i,colorDistanceFormula:r,paletteQuantization:n}),{colorDistanceFormula:r,imageQuantization:a});return e.bitmap.data=Buffer.from(s.toUint8Array()),e}};var parseBmfontAscii=function(e){if(!e)throw new Error("no data provided");var t={pages:[],chars:[],kernings:[]},i=(e=e.toString().trim()).split(/\r\n?|\n/g);if(0===i.length)throw new Error("no data in BMFont file");for(var r=0;r<i.length;r++){var n=splitLine(i[r],r);if(n)if("page"===n.key){if("number"!=typeof n.data.id)throw new Error("malformed file at line "+r+" -- needs page id=N");if("string"!=typeof n.data.file)throw new Error("malformed file at line "+r+' -- needs page file="path"');t.pages[n.data.id]=n.data.file;}else "chars"===n.key||"kernings"===n.key||("char"===n.key?t.chars.push(n.data):"kerning"===n.key?t.kernings.push(n.data):t[n.key]=n.data);}return t};function splitLine(e,t){if(!(e=e.replace(/\t+/g," ").trim()))return null;var i=e.indexOf(" ");if(-1===i)throw new Error("no named row at line "+t);var r=e.substring(0,i);e=(e=(e=(e=e.substring(i+1)).replace(/letter=[\'\"]\S+[\'\"]/gi,"")).split("=")).map((function(e){return e.trim().match(/(".*?"|[^"\s]+)+(?=\s*|\s*$)/g)}));for(var n=[],a=0;a<e.length;a++){var o=e[a];0===a?n.push({key:o[0],data:""}):a===e.length-1?n[n.length-1].data=parseData(o[0]):(n[n.length-1].data=parseData(o[0]),n.push({key:o[1],data:""}));}var s={key:r,data:{}};return n.forEach((function(e){s.data[e.key]=e.data;})),s}function parseData(e){return e&&0!==e.length?0===e.indexOf('"')||0===e.indexOf("'")?e.substring(1,e.length-1):-1!==e.indexOf(",")?parseIntList$1(e):parseInt(e,10):""}function parseIntList$1(e){return e.split(",").map((function(e){return parseInt(e,10)}))}getDefaultExportFromCjs(parseBmfontAscii);var GLYPH_DESIGNER_ERROR="chasrset",parseAttribs=function(e){for(var t in e=Object.assign({},e),GLYPH_DESIGNER_ERROR in e&&(e.charset=e[GLYPH_DESIGNER_ERROR],delete e[GLYPH_DESIGNER_ERROR]),e)"face"!==t&&"charset"!==t&&(e[t]="padding"===t||"spacing"===t?parseIntList(e[t]):parseInt(e[t],10));return e};function parseIntList(e){return e.split(",").map((function(e){return parseInt(e,10)}))}var xmlParseFromString=void 0!==self.DOMParser?function(e){return (new self.DOMParser).parseFromString(e,"application/xml")}:void 0!==self.ActiveXObject&&new self.ActiveXObject("Microsoft.XMLDOM")?function(e){var t=new self.ActiveXObject("Microsoft.XMLDOM");return t.async="false",t.loadXML(e),t}:function(e){var t=document.createElement("div");return t.innerHTML=e,t},parseAttributes=parseAttribs,parseFromString=xmlParseFromString,NAME_MAP={scaleh:"scaleH",scalew:"scaleW",stretchh:"stretchH",lineheight:"lineHeight",alphachnl:"alphaChnl",redchnl:"redChnl",greenchnl:"greenChnl",bluechnl:"blueChnl"},browser=function(e){e=e.toString();var t=parseFromString(e),i={pages:[],chars:[],kernings:[]};["info","common"].forEach((function(e){var r=t.getElementsByTagName(e)[0];r&&(i[e]=parseAttributes(getAttribs(r)));}));var r=t.getElementsByTagName("pages")[0];if(!r)throw new Error("malformed file -- no <pages> element");for(var n=r.getElementsByTagName("page"),a=0;a<n.length;a++){var o=n[a],s=parseInt(o.getAttribute("id"),10),l=o.getAttribute("file");if(isNaN(s))throw new Error('malformed file -- page "id" attribute is NaN');if(!l)throw new Error('malformed file -- needs page "file" attribute');i.pages[parseInt(s,10)]=l;}return ["chars","kernings"].forEach((function(e){var r=t.getElementsByTagName(e)[0];if(r)for(var n=e.substring(0,e.length-1),a=r.getElementsByTagName(n),o=0;o<a.length;o++){var s=a[o];i[e].push(parseAttributes(getAttribs(s)));}})),i};function getAttribs(e){return getAttribList(e).reduce((function(e,t){return e[mapName(t.nodeName)]=t.nodeValue,e}),{})}function getAttribList(e){for(var t=[],i=0;i<e.attributes.length;i++)t.push(e.attributes[i]);return t}function mapName(e){return NAME_MAP[e.toLowerCase()]||e}getDefaultExportFromCjs(browser);var HEADER$1=[66,77,70],parseBmfontBinary=function(e){if(e.length<6)throw new Error("invalid buffer length for BMFont");var t=HEADER$1.every((function(t,i){return e.readUInt8(i)===t}));if(!t)throw new Error("BMFont missing BMF byte header");var i=3;if(e.readUInt8(i++)>3)throw new Error("Only supports BMFont Binary v3 (BMFont App v1.10)");for(var r={kernings:[],chars:[]},n=0;n<5;n++)i+=readBlock(r,e,i);return r};function readBlock(e,t,i){if(i>t.length-1)return 0;var r=t.readUInt8(i++),n=t.readInt32LE(i);switch(i+=4,r){case 1:e.info=readInfo(t,i);break;case 2:e.common=readCommon(t,i);break;case 3:e.pages=readPages(t,i,n);break;case 4:e.chars=readChars(t,i,n);break;case 5:e.kernings=readKernings(t,i,n);}return 5+n}function readInfo(e,t){var i={};i.size=e.readInt16LE(t);var r=e.readUInt8(t+2);return i.smooth=r>>7&1,i.unicode=r>>6&1,i.italic=r>>5&1,i.bold=r>>4&1,r>>3&1&&(i.fixedHeight=1),i.charset=e.readUInt8(t+3)||"",i.stretchH=e.readUInt16LE(t+4),i.aa=e.readUInt8(t+6),i.padding=[e.readInt8(t+7),e.readInt8(t+8),e.readInt8(t+9),e.readInt8(t+10)],i.spacing=[e.readInt8(t+11),e.readInt8(t+12)],i.outline=e.readUInt8(t+13),i.face=readStringNT(e,t+14),i}function readCommon(e,t){var i={};return i.lineHeight=e.readUInt16LE(t),i.base=e.readUInt16LE(t+2),i.scaleW=e.readUInt16LE(t+4),i.scaleH=e.readUInt16LE(t+6),i.pages=e.readUInt16LE(t+8),e.readUInt8(t+10),i.packed=0,i.alphaChnl=e.readUInt8(t+11),i.redChnl=e.readUInt8(t+12),i.greenChnl=e.readUInt8(t+13),i.blueChnl=e.readUInt8(t+14),i}function readPages(e,t,i){for(var r=[],n=readNameNT(e,t),a=n.length+1,o=i/a,s=0;s<o;s++)r[s]=e.slice(t,t+n.length).toString("utf8"),t+=a;return r}function readChars(e,t,i){for(var r=[],n=i/20,a=0;a<n;a++){var o={},s=20*a;o.id=e.readUInt32LE(t+0+s),o.x=e.readUInt16LE(t+4+s),o.y=e.readUInt16LE(t+6+s),o.width=e.readUInt16LE(t+8+s),o.height=e.readUInt16LE(t+10+s),o.xoffset=e.readInt16LE(t+12+s),o.yoffset=e.readInt16LE(t+14+s),o.xadvance=e.readInt16LE(t+16+s),o.page=e.readUInt8(t+18+s),o.chnl=e.readUInt8(t+19+s),r[a]=o;}return r}function readKernings(e,t,i){for(var r=[],n=i/10,a=0;a<n;a++){var o={},s=10*a;o.first=e.readUInt32LE(t+0+s),o.second=e.readUInt32LE(t+4+s),o.amount=e.readInt16LE(t+8+s),r[a]=o;}return r}function readNameNT(e,t){for(var i=t;i<e.length&&0!==e[i];i++);return e.slice(t,i)}function readStringNT(e,t){return readNameNT(e,t).toString("utf8")}getDefaultExportFromCjs(parseBmfontBinary);function e(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}const t=e=>{if(!e)return null;const i={};switch(e.type){case "ELEMENT":{let n={};const a=E(e.value.attributes),o=t(e.value.children);if(a&&(n=Object.assign(n,a)),o){const t=r(e.value.children);n=Object.assign(n,t);}i[e.value.type]=n;break}case "ATTRIBUTE":{const t=e.value;i[t.name]=t.value;break}case "CONTENT":return {content:e.value}}return i},r=e=>e&&Array.isArray(e)&&0!==e.length?n(e)?{content:e[0].value}:{children:e.map(t)}:null,n=e=>e&&Array.isArray(e)&&1===e.length&&"CONTENT"===e[0].type,E=e=>e&&Array.isArray(e)?e.map(t).reduce(((e,t)=>Object.assign(e,t)),{}):null;var s={convert:e=>t(e.value.children[0])},a={Token:(e,t)=>({type:e,value:t}),TOKEN_TYPE:{OPEN_BRACKET:"OPEN_BRACKET",ELEMENT_TYPE:"ELEMENT_TYPE",CLOSE_ELEMENT:"CLOSE_ELEMENT",ATTRIB_NAME:"ATTRIB_NAME",ATTRIB_VALUE:"ATTRIB_VALUE",ASSIGN:"ASSIGN",CLOSE_BRACKET:"CLOSE_BRACKET",CONTENT:"CONTENT",EOF:"EOF"}};const{Token:T,TOKEN_TYPE:u}=a,c=T("EOF"),l=e=>" "===e||"\n"===e||"\r"===e||"\t"===e,o=e=>e.replace(/'/g,'"');var N={createLexer:function(e){let t=null,i=(e=>{let t=0;for(;t<e.length&&l(e[t]);)t++;return ((e,t)=>{if(e.startsWith("<?xml",t)){const i=e.length;for(;t<i;)if("?"!==e[t])t++;else {if(">"===e[t+1])return t+2;t++;}}return t})(e,t)})(e),r=[];const n=()=>e[i],a=()=>t!==c&&i<e.length,s=e=>'"'===e||"'"===e,h=()=>{for(;a()&&l(e[i]);)i++;},f=t=>{if(a()){if("<"===e[i]){let t="<";return i++,a()&&"/"===e[i]?(i++,t="</"):a()&&"!"===e[i]&&"-"===e[i+1]&&"-"===e[i+2]&&(i++,i++,i++,t="\x3c!--"),t}if("/"===n()){let e="/";return i++,a()&&">"===n()&&(i++,e="/>"),e}if("="===e[i]||">"===e[i]){const t=e[i];return i++,t}}return d(!!t)},d=t=>{const r=t?/[^>=<]/u:/[a-zA-Z0-9_:-]/;let n=i;for(;a()&&e[i].match(r);)i++;return o(e.substring(n,i))},p=()=>{const l=i;h();const m=i-l;if(a())if(t&&t.type===u.OPEN_BRACKET){h();const e=f(false);t=T(u.ELEMENT_TYPE,e),r.push(e);}else if(t&&t.type===u.ASSIGN){a()&&s(n())&&i++;let r=i;for(;a()&&!s(n());)i++;const l=o(e.substring(r,i));i++,t=T(u.ATTRIB_VALUE,l);}else {h();let o=f(true);switch(o){case "=":t=t.type===u.ATTRIB_NAME?T(u.ASSIGN):T(u.CONTENT,o);break;case "</":{const n=i;for(;">"!==e[i];)i++;t=T(u.CLOSE_ELEMENT,e.substring(n,i)),i++,r.pop();break}case "/>":{const e=r.pop();t=T(u.CLOSE_ELEMENT,e);break}case "\x3c!--":{const t=["!","-","-"];for(;a()&&(">"!==t[2]||"-"!==t[1]||"-"!==t[0]);)t.shift(),t.push(e[i]),i++;return p()}case ">":t=T(u.CLOSE_BRACKET);break;case "<":t=T(u.OPEN_BRACKET);break;default:if(o&&o.length>0){if(t.type===u.CLOSE_BRACKET){let e="";"<"!==n()&&(e=d(true)),t=T(u.CONTENT,o+e);}else if(t.type!==u.ATTRIB_NAME&&t.type!==u.CONTENT)t.type===u.CLOSE_ELEMENT?(o=" ".repeat(m)+o,t=T(u.CONTENT,o)):t=T(u.ATTRIB_NAME,o);else {const e=" ".repeat(m)+o;t=T(u.CONTENT,e);}break}{const t='Unknown Syntax : "'+e[i]+'"';throw new Error(t)}}}else t=c;return t};return {peek:n,next:p,hasNext:a}}};const{createLexer:i}=N,{Token:p,TOKEN_TYPE:O}=a,[A,f,C,h]=["ROOT","ELEMENT","ATTRIBUTE","CONTENT"],_=(e,t)=>({type:e,value:t}),L=e=>_(h,e),y=(e,t,i)=>_(f,{type:e,attributes:t,children:i}),v=(e,t)=>_(C,{name:e,value:t}),S=(e,t)=>{const i=[];for(;e.hasNext();){const r=e.next();switch(r.type){case O.OPEN_BRACKET:{const t=e.next(),[r,n]=R(e);let a=[];n.type!==O.CLOSE_ELEMENT&&(a=S(e,t)),a&&a.length>0&&a[0].type===O.CONTENT&&(a=b(a)),i.push(y(t.value,r,a));break}case O.CLOSE_ELEMENT:if(r.value===t.value)return i;break;case O.CONTENT:i.push(L(r.value));break;case O.EOF:return i;default:throw new Error(`Unknown Lexem type: ${r.type} "${r.value}, scoping element: ${t.value}"`)}}return i},R=e=>{const t=[];let i=e.peek();if(!e.hasNext()||i&&i.type===O.CLOSE_BRACKET||i&&i.type===O.CLOSE_ELEMENT)return [t,i];for(i=e.next();e.hasNext()&&i&&i.type!==O.CLOSE_BRACKET&&i.type!==O.CLOSE_ELEMENT;){const r=i;e.next();const n=e.next(),a=v(r.value,n.value);t.push(a),i=e.next();}return [t,i]};function b(e){let t=[],i="";return e.forEach((e=>{e.type===O.CONTENT?i+=e.value:(i.length&&(t.push(L(i)),i=""),t.push(e));})),i.length&&t.push(L(i)),t}var B={transpile:function(e,t){const r=(e=>_(A,{children:S(e,p(A,"ROOT"))}))(i(e));return t?t.convert(r):r}};const M=s,{transpile:x}=B;var k=e({convertXML:function(e,t){return x(e,t||M)},createAST:function(e){return x(e)}}),simpleXmlToJson_min=k,xmlPackage=getDefaultExportFromCjs(simpleXmlToJson_min);const {convertXML:convertXML}=xmlPackage;createJimp({formats:[png]});Buffer.from([66,77,70,3]);var pixelmatch_1=pixelmatch;const defaultOptions={threshold:.1,includeAA:false,alpha:.1,aaColor:[255,255,0],diffColor:[255,0,0],diffColorAlt:null,diffMask:false};function pixelmatch(e,t,i,r,n,a){if(!isPixelData(e)||!isPixelData(t)||i&&!isPixelData(i))throw new Error("Image data: Uint8Array, Uint8ClampedArray or Buffer expected.");if(e.length!==t.length||i&&i.length!==e.length)throw new Error("Image sizes do not match.");if(e.length!==r*n*4)throw new Error("Image data size does not match width/height.");a=Object.assign({},defaultOptions,a);const o=r*n,s=new Uint32Array(e.buffer,e.byteOffset,o),l=new Uint32Array(t.buffer,t.byteOffset,o);let u=true;for(let e=0;e<o;e++)if(s[e]!==l[e]){u=false;break}if(u){if(i&&!a.diffMask)for(let t=0;t<o;t++)drawGrayPixel(e,4*t,a.alpha,i);return 0}const h=35215*a.threshold*a.threshold;let c=0;for(let o=0;o<n;o++)for(let s=0;s<r;s++){const l=4*(o*r+s),u=colorDelta(e,t,l,l);Math.abs(u)>h?a.includeAA||!antialiased(e,s,o,r,n,t)&&!antialiased(t,s,o,r,n,e)?(i&&drawPixel(i,l,...u<0&&a.diffColorAlt||a.diffColor),c++):i&&!a.diffMask&&drawPixel(i,l,...a.aaColor):i&&(a.diffMask||drawGrayPixel(e,l,a.alpha,i));}return c}function isPixelData(e){return ArrayBuffer.isView(e)&&1===e.constructor.BYTES_PER_ELEMENT}function antialiased(e,t,i,r,n,a){const o=Math.max(t-1,0),s=Math.max(i-1,0),l=Math.min(t+1,r-1),u=Math.min(i+1,n-1),h=4*(i*r+t);let c,f,d,p,m=t===o||t===l||i===s||i===u?1:0,_=0,g=0;for(let n=o;n<=l;n++)for(let a=s;a<=u;a++){if(n===t&&a===i)continue;const o=colorDelta(e,e,h,4*(a*r+n),true);if(0===o){if(m++,m>2)return false}else o<_?(_=o,c=n,f=a):o>g&&(g=o,d=n,p=a);}return 0!==_&&0!==g&&(hasManySiblings(e,c,f,r,n)&&hasManySiblings(a,c,f,r,n)||hasManySiblings(e,d,p,r,n)&&hasManySiblings(a,d,p,r,n))}function hasManySiblings(e,t,i,r,n){const a=Math.max(t-1,0),o=Math.max(i-1,0),s=Math.min(t+1,r-1),l=Math.min(i+1,n-1),u=4*(i*r+t);let h=t===a||t===s||i===o||i===l?1:0;for(let n=a;n<=s;n++)for(let a=o;a<=l;a++){if(n===t&&a===i)continue;const o=4*(a*r+n);if(e[u]===e[o]&&e[u+1]===e[o+1]&&e[u+2]===e[o+2]&&e[u+3]===e[o+3]&&h++,h>2)return true}return false}function colorDelta(e,t,i,r,n){let a=e[i+0],o=e[i+1],s=e[i+2],l=e[i+3],u=t[r+0],h=t[r+1],c=t[r+2],f=t[r+3];if(l===f&&a===u&&o===h&&s===c)return 0;l<255&&(l/=255,a=blend(a,l),o=blend(o,l),s=blend(s,l)),f<255&&(f/=255,u=blend(u,f),h=blend(h,f),c=blend(c,f));const d=rgb2y(a,o,s),p=rgb2y(u,h,c),m=d-p;if(n)return m;const _=rgb2i(a,o,s)-rgb2i(u,h,c),g=rgb2q(a,o,s)-rgb2q(u,h,c),b=.5053*m*m+.299*_*_+.1957*g*g;return d>p?-b:b}function rgb2y(e,t,i){return .29889531*e+.58662247*t+.11448223*i}function rgb2i(e,t,i){return .59597799*e-.2741761*t-.32180189*i}function rgb2q(e,t,i){return .21147017*e-.52261711*t+.31114694*i}function blend(e,t){return 255+(e-255)*t}function drawPixel(e,t,i,r,n){e[t+0]=i,e[t+1]=r,e[t+2]=n,e[t+3]=255;}function drawGrayPixel(e,t,i,r){const n=blend(rgb2y(e[t+0],e[t+1],e[t+2]),i*e[t+3]/255);drawPixel(r,t,n,n,n);}getDefaultExportFromCjs(pixelmatch_1);const defaultPlugins=[methods$h,methods$g,methods$f,methods$e,methods$c,methods$a,methods$b,methods$9,methods$8,methods$7,methods$6,methods$5,methods$4,methods$3,methods$d,methods$2,methods$1,methods],defaultFormats=[bmp,msBmp,gif,jpeg$2,png,tiff];({bmp:bmp().mime,gif:gif().mime,jpeg:jpeg$2().mime,png:png().mime,tiff:tiff().mime});const Jimp=createJimp({formats:defaultFormats,plugins:defaultPlugins});
3214
3214
 
3215
+ /*
3216
+ * Copyright (C) 2025 Koutaro Mukai
3217
+ *
3218
+ * This program is free software: you can redistribute it and/or modify
3219
+ * it under the terms of the GNU General Public License as published by
3220
+ * the Free Software Foundation, either version 3 of the License, or
3221
+ * (at your option) any later version.
3222
+ *
3223
+ * This program is distributed in the hope that it will be useful,
3224
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3225
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3226
+ * GNU General Public License for more details.
3227
+ *
3228
+ * You should have received a copy of the GNU General Public License
3229
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
3230
+ */
3231
+ const _enabled = (() => {
3232
+ try {
3233
+ if (typeof process !== "undefined" &&
3234
+ process.env &&
3235
+ process.env.PDFDIFF_PROFILE === "1") {
3236
+ return true;
3237
+ }
3238
+ }
3239
+ catch {
3240
+ // process not available (e.g. in some browser worker environments)
3241
+ }
3242
+ const g = globalThis;
3243
+ return g.__PDFDIFF_PROFILE__ === true;
3244
+ })();
3245
+ const _counters = Object.create(null);
3246
+ const _NOOP_SPAN = Object.freeze({ stop() { } });
3247
+ const _noop = () => { };
3248
+ const _emptyDump = () => Object.freeze({});
3249
+ const _realPerf = {
3250
+ enabled: true,
3251
+ span(key) {
3252
+ const t0 = performance.now();
3253
+ return {
3254
+ stop() {
3255
+ _counters[key] = (_counters[key] ?? 0) + (performance.now() - t0);
3256
+ },
3257
+ };
3258
+ },
3259
+ incr(key, delta = 1) {
3260
+ _counters[key] = (_counters[key] ?? 0) + delta;
3261
+ },
3262
+ setMax(key, value) {
3263
+ const cur = _counters[key];
3264
+ if (cur === undefined || value > cur)
3265
+ _counters[key] = value;
3266
+ },
3267
+ merge(other) {
3268
+ for (const k of Object.keys(other)) {
3269
+ _counters[k] = (_counters[k] ?? 0) + other[k];
3270
+ }
3271
+ },
3272
+ dump() {
3273
+ return { ..._counters };
3274
+ },
3275
+ reset() {
3276
+ for (const k of Object.keys(_counters))
3277
+ delete _counters[k];
3278
+ },
3279
+ };
3280
+ const _noopPerf = {
3281
+ enabled: false,
3282
+ span: () => _NOOP_SPAN,
3283
+ incr: _noop,
3284
+ setMax: _noop,
3285
+ merge: _noop,
3286
+ dump: _emptyDump,
3287
+ reset: _noop,
3288
+ };
3289
+ const perf = _enabled ? _realPerf : _noopPerf;
3290
+
3215
3291
  /*
3216
3292
  * Copyright (C) 2025 Koutaro Mukai
3217
3293
  *
@@ -3266,6 +3342,7 @@ function alignSize(images, align) {
3266
3342
  : alignImage(img, largerWidth, largerHeight, align));
3267
3343
  }
3268
3344
  function composeLayers(canvasWidth, canvasHeight, layers) {
3345
+ const _span = perf.span("image.compose_ms");
3269
3346
  const canvas = createEmptyImage(canvasWidth, canvasHeight);
3270
3347
  const dData = canvas.bitmap.data;
3271
3348
  for (const [image, opacity] of layers) {
@@ -3293,6 +3370,7 @@ function composeLayers(canvasWidth, canvasHeight, layers) {
3293
3370
  }
3294
3371
  }
3295
3372
  }
3373
+ _span.stop();
3296
3374
  return canvas;
3297
3375
  }
3298
3376
 
@@ -3313,54 +3391,119 @@ function composeLayers(canvasWidth, canvasHeight, layers) {
3313
3391
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
3314
3392
  */
3315
3393
  function drawDifference(a, b, mask, pallet, align) {
3316
- const [aNew, bNew, maskNew] = alignSize([a, b, mask], align);
3394
+ const sAlign = perf.span("diff.align_ms");
3395
+ let aNew;
3396
+ let bNew;
3397
+ let maskNew;
3398
+ if (mask !== null) {
3399
+ [aNew, bNew, maskNew] = alignSize([a, b, mask], align);
3400
+ }
3401
+ else {
3402
+ [aNew, bNew] = alignSize([a, b], align);
3403
+ maskNew = null;
3404
+ }
3405
+ sAlign.stop();
3317
3406
  const width = aNew.width;
3318
3407
  const height = aNew.height;
3319
3408
  const aData = aNew.bitmap.data;
3320
3409
  const bData = bNew.bitmap.data;
3321
- const mData = maskNew.bitmap.data;
3410
+ const mData = maskNew !== null ? maskNew.bitmap.data : null;
3411
+ const sCreate = perf.span("diff.createEmpty_ms");
3322
3412
  const diffImage = createEmptyImage(width, height);
3323
3413
  const dData = diffImage.bitmap.data;
3414
+ sCreate.stop();
3324
3415
  const addition = [];
3325
3416
  const deletion = [];
3326
3417
  const modification = [];
3327
- for (let x = 0; x < width; x++) {
3328
- for (let y = 0; y < height; y++) {
3329
- const idx = (y * width + x) * 4;
3330
- if (mData[idx + 3] !== 0)
3331
- continue;
3332
- const aAlpha = aData[idx + 3];
3333
- const bAlpha = bData[idx + 3];
3334
- if (aAlpha === bAlpha &&
3335
- aData[idx] === bData[idx] &&
3336
- aData[idx + 1] === bData[idx + 1] &&
3337
- aData[idx + 2] === bData[idx + 2]) {
3338
- continue;
3339
- }
3340
- if (aAlpha === 0 && bAlpha === 0)
3341
- continue;
3342
- let target;
3343
- let color;
3344
- if (aAlpha === 0) {
3345
- target = addition;
3346
- color = pallet.addition;
3347
- }
3348
- else if (bAlpha === 0) {
3349
- target = deletion;
3350
- color = pallet.deletion;
3418
+ const sScan = perf.span("diff.scan_ms");
3419
+ let diffPixels = 0;
3420
+ if (mData !== null) {
3421
+ for (let x = 0; x < width; x++) {
3422
+ for (let y = 0; y < height; y++) {
3423
+ const idx = (y * width + x) * 4;
3424
+ if (mData[idx + 3] !== 0)
3425
+ continue;
3426
+ const aAlpha = aData[idx + 3];
3427
+ const bAlpha = bData[idx + 3];
3428
+ if (aAlpha === bAlpha &&
3429
+ aData[idx] === bData[idx] &&
3430
+ aData[idx + 1] === bData[idx + 1] &&
3431
+ aData[idx + 2] === bData[idx + 2]) {
3432
+ continue;
3433
+ }
3434
+ if (aAlpha === 0 && bAlpha === 0)
3435
+ continue;
3436
+ let target;
3437
+ let color;
3438
+ if (aAlpha === 0) {
3439
+ target = addition;
3440
+ color = pallet.addition;
3441
+ }
3442
+ else if (bAlpha === 0) {
3443
+ target = deletion;
3444
+ color = pallet.deletion;
3445
+ }
3446
+ else {
3447
+ target = modification;
3448
+ color = pallet.modification;
3449
+ }
3450
+ target.push([x, y]);
3451
+ diffPixels++;
3452
+ dData[idx] = color[0];
3453
+ dData[idx + 1] = color[1];
3454
+ dData[idx + 2] = color[2];
3455
+ dData[idx + 3] = color[3];
3351
3456
  }
3352
- else {
3353
- target = modification;
3354
- color = pallet.modification;
3457
+ }
3458
+ }
3459
+ else {
3460
+ for (let x = 0; x < width; x++) {
3461
+ for (let y = 0; y < height; y++) {
3462
+ const idx = (y * width + x) * 4;
3463
+ const aAlpha = aData[idx + 3];
3464
+ const bAlpha = bData[idx + 3];
3465
+ if (aAlpha === bAlpha &&
3466
+ aData[idx] === bData[idx] &&
3467
+ aData[idx + 1] === bData[idx + 1] &&
3468
+ aData[idx + 2] === bData[idx + 2]) {
3469
+ continue;
3470
+ }
3471
+ if (aAlpha === 0 && bAlpha === 0)
3472
+ continue;
3473
+ let target;
3474
+ let color;
3475
+ if (aAlpha === 0) {
3476
+ target = addition;
3477
+ color = pallet.addition;
3478
+ }
3479
+ else if (bAlpha === 0) {
3480
+ target = deletion;
3481
+ color = pallet.deletion;
3482
+ }
3483
+ else {
3484
+ target = modification;
3485
+ color = pallet.modification;
3486
+ }
3487
+ target.push([x, y]);
3488
+ diffPixels++;
3489
+ dData[idx] = color[0];
3490
+ dData[idx + 1] = color[1];
3491
+ dData[idx + 2] = color[2];
3492
+ dData[idx + 3] = color[3];
3355
3493
  }
3356
- target.push([x, y]);
3357
- dData[idx] = color[0];
3358
- dData[idx + 1] = color[1];
3359
- dData[idx + 2] = color[2];
3360
- dData[idx + 3] = color[3];
3361
3494
  }
3362
3495
  }
3363
- return { diff: diffImage, addition, deletion, modification };
3496
+ sScan.stop();
3497
+ perf.incr("diff.diffPixels", diffPixels);
3498
+ perf.incr("diff.totalPixels", width * height);
3499
+ perf.incr("diff.pages");
3500
+ return {
3501
+ diff: diffImage,
3502
+ addition,
3503
+ deletion,
3504
+ modification,
3505
+ hasDiff: diffPixels > 0,
3506
+ };
3364
3507
  }
3365
3508
 
3366
3509
  /*
@@ -3406,13 +3549,45 @@ function pixmapToRGBA(pixmap) {
3406
3549
  }
3407
3550
  async function pageToImage(page, dpi, alpha) {
3408
3551
  const zoom = dpi / 72;
3552
+ const sToPixmap = perf.span("pdf.toPixmap_ms");
3409
3553
  const pixmap = page.toPixmap([zoom, 0, 0, zoom, 0, 0], ColorSpace.DeviceRGB, alpha);
3410
3554
  const width = pixmap.getWidth();
3411
3555
  const height = pixmap.getHeight();
3556
+ sToPixmap.stop();
3557
+ const sRgba = perf.span("pdf.pixmapToRGBA_ms");
3412
3558
  const data = pixmapToRGBA(pixmap);
3413
3559
  pixmap.destroy();
3414
3560
  page.destroy();
3415
- return Jimp.fromBitmap({ width, height, data });
3561
+ sRgba.stop();
3562
+ const sFromBitmap = perf.span("pdf.fromBitmap_ms");
3563
+ const result = Jimp.fromBitmap({ width, height, data });
3564
+ sFromBitmap.stop();
3565
+ return result;
3566
+ }
3567
+
3568
+ /*
3569
+ * Copyright (C) 2025 Koutaro Mukai
3570
+ *
3571
+ * This program is free software: you can redistribute it and/or modify
3572
+ * it under the terms of the GNU General Public License as published by
3573
+ * the Free Software Foundation, either version 3 of the License, or
3574
+ * (at your option) any later version.
3575
+ *
3576
+ * This program is distributed in the hope that it will be useful,
3577
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3578
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3579
+ * GNU General Public License for more details.
3580
+ *
3581
+ * You should have received a copy of the GNU General Public License
3582
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
3583
+ */
3584
+ /**
3585
+ * Slice a typed-array view into a standalone backing buffer of the same kind
3586
+ * (ArrayBuffer in, ArrayBuffer out; SharedArrayBuffer in, SharedArrayBuffer
3587
+ * out). The buffer kind is preserved through the generic parameter.
3588
+ */
3589
+ function sliceBackingBuffer(src) {
3590
+ return src.buffer.slice(src.byteOffset, src.byteOffset + src.byteLength);
3416
3591
  }
3417
3592
 
3418
3593
  /*
@@ -3435,15 +3610,8 @@ let pdfA;
3435
3610
  let pdfB;
3436
3611
  let pdfMask;
3437
3612
  let opts;
3438
- function toTransferable(src) {
3439
- const view = src instanceof Uint8Array || src instanceof Uint8ClampedArray
3440
- ? src
3441
- : Uint8Array.from(src);
3442
- const out = new ArrayBuffer(view.byteLength);
3443
- new Uint8Array(out).set(view);
3444
- return out;
3445
- }
3446
3613
  async function processPage(index) {
3614
+ const sLoad = perf.span("worker.pageToImageAll_ms");
3447
3615
  const [pageA, pageB, pageMask] = (await Promise.all([
3448
3616
  index < pdfA.countPages()
3449
3617
  ? pageToImage(pdfA.loadPage(index), opts.dpi, opts.alpha)
@@ -3453,63 +3621,81 @@ async function processPage(index) {
3453
3621
  : createEmptyImage(1, 1),
3454
3622
  index < pdfMask.countPages()
3455
3623
  ? pageToImage(pdfMask.loadPage(index), opts.dpi, opts.alpha)
3456
- : createEmptyImage(1, 1),
3624
+ : Promise.resolve(null),
3457
3625
  ]));
3458
- const { diff: diffLayer, addition, deletion, modification, } = drawDifference(pageA, pageB, pageMask, opts.pallet, opts.align);
3459
- const diff = composeLayers(pageA.width, pageA.height, [
3626
+ sLoad.stop();
3627
+ const sDiff = perf.span("worker.drawDifference_ms");
3628
+ const { diff: diffLayer, addition, deletion, modification, hasDiff, } = drawDifference(pageA, pageB, pageMask, opts.pallet, opts.align);
3629
+ sDiff.stop();
3630
+ const sCompose = perf.span("worker.composeLayers_ms");
3631
+ const layers = [
3460
3632
  [pageA, 0.2],
3461
3633
  [pageB, 0.2],
3462
- [diffLayer, 1],
3463
- ]);
3634
+ ];
3635
+ if (hasDiff)
3636
+ layers.push([diffLayer, 1]);
3637
+ const diff = composeLayers(pageA.width, pageA.height, layers);
3638
+ sCompose.stop();
3639
+ const sXfer = perf.span("worker.toTransferable_ms");
3640
+ const aBuf = sliceBackingBuffer(pageA.bitmap.data);
3641
+ const bBuf = sliceBackingBuffer(pageB.bitmap.data);
3642
+ const dBuf = sliceBackingBuffer(diff.bitmap.data);
3643
+ sXfer.stop();
3644
+ perf.incr("worker.pages");
3645
+ let pagePerf;
3646
+ if (perf.enabled) {
3647
+ pagePerf = perf.dump();
3648
+ perf.reset();
3649
+ }
3464
3650
  return {
3465
3651
  type: "pageResult",
3466
3652
  index,
3467
- a: {
3468
- width: pageA.width,
3469
- height: pageA.height,
3470
- data: toTransferable(pageA.bitmap.data),
3471
- },
3472
- b: {
3473
- width: pageB.width,
3474
- height: pageB.height,
3475
- data: toTransferable(pageB.bitmap.data),
3476
- },
3477
- diff: {
3478
- width: diff.width,
3479
- height: diff.height,
3480
- data: toTransferable(diff.bitmap.data),
3481
- },
3653
+ a: { width: pageA.width, height: pageA.height, data: aBuf },
3654
+ b: { width: pageB.width, height: pageB.height, data: bBuf },
3655
+ diff: { width: diff.width, height: diff.height, data: dBuf },
3482
3656
  addition,
3483
3657
  deletion,
3484
3658
  modification,
3659
+ perf: pagePerf,
3485
3660
  };
3486
3661
  }
3487
3662
  self.addEventListener("message", async (e) => {
3488
- const msg = e.data;
3489
- if (msg.type === "init") {
3490
- pdfA = PDFDocument.openDocument(msg.aBytes, "application/pdf");
3491
- pdfB = PDFDocument.openDocument(msg.bBytes, "application/pdf");
3492
- pdfMask = msg.maskBytes
3493
- ? PDFDocument.openDocument(msg.maskBytes, "application/pdf")
3494
- : new PDFDocument();
3495
- opts = {
3496
- dpi: msg.dpi,
3497
- alpha: msg.alpha,
3498
- pallet: msg.pallet,
3499
- align: msg.align,
3500
- };
3501
- if (pdfA.countPages() > 0)
3502
- pdfA.loadPage(0).destroy();
3503
- const ready = { type: "ready" };
3504
- self.postMessage(ready);
3663
+ try {
3664
+ const msg = e.data;
3665
+ if (msg.type === "init") {
3666
+ pdfA = PDFDocument.openDocument(msg.aBytes, "application/pdf");
3667
+ pdfB = PDFDocument.openDocument(msg.bBytes, "application/pdf");
3668
+ pdfMask = msg.maskBytes
3669
+ ? PDFDocument.openDocument(msg.maskBytes, "application/pdf")
3670
+ : new PDFDocument();
3671
+ opts = {
3672
+ dpi: msg.dpi,
3673
+ alpha: msg.alpha,
3674
+ pallet: msg.pallet,
3675
+ align: msg.align,
3676
+ };
3677
+ if (pdfA.countPages() > 0)
3678
+ pdfA.loadPage(0).destroy();
3679
+ const ready = { type: "ready" };
3680
+ self.postMessage(ready);
3681
+ }
3682
+ else if (msg.type === "page") {
3683
+ const result = await processPage(msg.index);
3684
+ self.postMessage(result, [
3685
+ result.a.data,
3686
+ result.b.data,
3687
+ result.diff.data,
3688
+ ]);
3689
+ }
3505
3690
  }
3506
- else if (msg.type === "page") {
3507
- const result = await processPage(msg.index);
3508
- self.postMessage(result, [
3509
- result.a.data,
3510
- result.b.data,
3511
- result.diff.data,
3512
- ]);
3691
+ catch (err) {
3692
+ const errorMsg = {
3693
+ type: "error",
3694
+ message: err instanceof Error ? `${err.message}\n${err.stack}` : String(err),
3695
+ };
3696
+ self.postMessage(errorMsg);
3513
3697
  }
3514
3698
  });
3699
+ const loaded = { type: "loaded" };
3700
+ self.postMessage(loaded);
3515
3701
  //# sourceMappingURL=worker.js.map