@embedpdf/engines 2.3.0 → 2.4.1

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 (51) hide show
  1. package/dist/{browser-C6QEa8uk.cjs → browser-13mzox-R.cjs} +2 -2
  2. package/dist/{browser-C6QEa8uk.cjs.map → browser-13mzox-R.cjs.map} +1 -1
  3. package/dist/{browser-awZxztMA.js → browser-qfUHZxQ6.js} +7 -3
  4. package/dist/{browser-awZxztMA.js.map → browser-qfUHZxQ6.js.map} +1 -1
  5. package/dist/{direct-engine-nrX_KvVy.js → direct-engine-5RWKENek.js} +311 -4
  6. package/dist/direct-engine-5RWKENek.js.map +1 -0
  7. package/dist/direct-engine-DnHo6z8a.cjs +2 -0
  8. package/dist/direct-engine-DnHo6z8a.cjs.map +1 -0
  9. package/dist/index.cjs +1 -1
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.js +12 -3
  12. package/dist/index.js.map +1 -1
  13. package/dist/lib/converters/browser.d.ts +2 -2
  14. package/dist/lib/converters/index.cjs +1 -1
  15. package/dist/lib/converters/index.js +1 -1
  16. package/dist/lib/converters/types.d.ts +12 -2
  17. package/dist/lib/orchestrator/pdf-engine.d.ts +3 -0
  18. package/dist/lib/orchestrator/remote-executor.d.ts +3 -0
  19. package/dist/lib/pdfium/engine.d.ts +91 -0
  20. package/dist/lib/pdfium/index.cjs +1 -1
  21. package/dist/lib/pdfium/index.js +4 -4
  22. package/dist/lib/pdfium/web/direct-engine.cjs +1 -1
  23. package/dist/lib/pdfium/web/direct-engine.js +3 -3
  24. package/dist/lib/pdfium/web/worker-engine.cjs +1 -1
  25. package/dist/lib/pdfium/web/worker-engine.cjs.map +1 -1
  26. package/dist/lib/pdfium/web/worker-engine.js +12 -3
  27. package/dist/lib/pdfium/web/worker-engine.js.map +1 -1
  28. package/dist/lib/webworker/engine.cjs +1 -1
  29. package/dist/lib/webworker/engine.cjs.map +1 -1
  30. package/dist/lib/webworker/engine.d.ts +18 -0
  31. package/dist/lib/webworker/engine.js +47 -0
  32. package/dist/lib/webworker/engine.js.map +1 -1
  33. package/dist/pdf-engine-B4lt8-5f.cjs +2 -0
  34. package/dist/pdf-engine-B4lt8-5f.cjs.map +1 -0
  35. package/dist/{pdf-engine-ChjNHvQd.js → pdf-engine-CVXuu1xQ.js} +30 -1
  36. package/dist/pdf-engine-CVXuu1xQ.js.map +1 -0
  37. package/dist/preact/index.cjs +1 -1
  38. package/dist/preact/index.js +1 -1
  39. package/dist/react/index.cjs +1 -1
  40. package/dist/react/index.js +1 -1
  41. package/dist/svelte/index.cjs +1 -1
  42. package/dist/svelte/index.js +1 -1
  43. package/dist/vue/index.cjs +1 -1
  44. package/dist/vue/index.js +1 -1
  45. package/package.json +5 -5
  46. package/dist/direct-engine-Dwkk7o9U.cjs +0 -2
  47. package/dist/direct-engine-Dwkk7o9U.cjs.map +0 -1
  48. package/dist/direct-engine-nrX_KvVy.js.map +0 -1
  49. package/dist/pdf-engine-ChjNHvQd.js.map +0 -1
  50. package/dist/pdf-engine-DgNNP62W.cjs +0 -2
  51. package/dist/pdf-engine-DgNNP62W.cjs.map +0 -1
@@ -1,2 +1,2 @@
1
- "use strict";class e extends Error{constructor(e){super(e),this.name="ImageConverterError"}}const t=(t,r="image/webp",n)=>{if("undefined"==typeof document)return Promise.reject(new e("document is not available. This converter requires a browser environment."));const a=t(),o=new ImageData(a.data,a.width,a.height);return new Promise((t,a)=>{const i=document.createElement("canvas");i.width=o.width,i.height=o.height,i.getContext("2d").putImageData(o,0,0),i.toBlob(r=>{r?t(r):a(new e("Canvas toBlob returned null"))},r,n)})};exports.ImageConverterError=e,exports.browserImageDataToBlobConverter=t,exports.createHybridImageConverter=function(e){return async(r,n="image/webp",a)=>{try{const t=r(),o=new Uint8ClampedArray(t.data);return await e.encode({data:o,width:t.width,height:t.height},n,a)}catch(o){return console.warn("Worker encoding failed, falling back to main-thread Canvas:",o),t(r,n,a)}}},exports.createWorkerPoolImageConverter=function(e){return(t,r="image/webp",n)=>{const a=t(),o=new Uint8ClampedArray(a.data);return e.encode({data:o,width:a.width,height:a.height},r,n)}};
2
- //# sourceMappingURL=browser-C6QEa8uk.cjs.map
1
+ "use strict";class e extends Error{constructor(e){super(e),this.name="ImageConverterError"}}const t=(t,r="image/webp",n)=>{if("undefined"==typeof document)return Promise.reject(new e("document is not available. This converter requires a browser environment."));const a=t(),o=new ImageData(a.data,a.width,a.height);return new Promise((t,a)=>{const i=document.createElement("canvas");i.width=o.width,i.height=o.height,i.getContext("2d").putImageData(o,0,0),i.toBlob(r=>{r?t(r):a(new e("Canvas toBlob returned null"))},r,n)})};exports.ImageConverterError=e,exports.browserImageDataToBlobConverter=t,exports.createHybridImageConverter=function(e){const r=async(r,n="image/webp",a)=>{try{const t=r(),o=new Uint8ClampedArray(t.data);return await e.encode({data:o,width:t.width,height:t.height},n,a)}catch(o){return console.warn("Worker encoding failed, falling back to main-thread Canvas:",o),t(r,n,a)}};return r.destroy=()=>e.destroy(),r},exports.createWorkerPoolImageConverter=function(e){const t=(t,r="image/webp",n)=>{const a=t(),o=new Uint8ClampedArray(a.data);return e.encode({data:o,width:a.width,height:a.height},r,n)};return t.destroy=()=>e.destroy(),t};
2
+ //# sourceMappingURL=browser-13mzox-R.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser-C6QEa8uk.cjs","sources":["../src/lib/converters/browser.ts"],"sourcesContent":["import type { ImageConversionTypes } from '@embedpdf/models';\nimport type { ImageDataConverter, LazyImageData } from './types';\nimport { ImageEncoderWorkerPool } from '../image-encoder';\n\n// ============================================================================\n// Error Classes\n// ============================================================================\n\nexport class ImageConverterError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ImageConverterError';\n }\n}\n\n// ============================================================================\n// Browser Converters\n// ============================================================================\n\n/**\n * Main-thread Canvas-based image converter\n * Simple and works everywhere, but blocks the main thread during encoding\n *\n * Use this as a fallback when worker-based encoding isn't available\n */\nexport const browserImageDataToBlobConverter: ImageDataConverter<Blob> = (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/webp',\n quality?: number,\n): Promise<Blob> => {\n if (typeof document === 'undefined') {\n return Promise.reject(\n new ImageConverterError(\n 'document is not available. This converter requires a browser environment.',\n ),\n );\n }\n\n const pdfImage = getImageData();\n const imageData = new ImageData(pdfImage.data, pdfImage.width, pdfImage.height);\n\n return new Promise((resolve, reject) => {\n const canvas = document.createElement('canvas');\n canvas.width = imageData.width;\n canvas.height = imageData.height;\n canvas.getContext('2d')!.putImageData(imageData, 0, 0);\n\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new ImageConverterError('Canvas toBlob returned null'));\n }\n },\n imageType,\n quality,\n );\n });\n};\n\n/**\n * Worker pool image converter using OffscreenCanvas in dedicated workers\n * Non-blocking - encoding happens off the main thread\n *\n * This is the preferred approach for performance\n *\n * @param workerPool - Instance of ImageEncoderWorkerPool\n * @returns ImageDataConverter function\n */\nexport function createWorkerPoolImageConverter(\n workerPool: ImageEncoderWorkerPool,\n): ImageDataConverter<Blob> {\n return (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/webp',\n quality?: number,\n ): Promise<Blob> => {\n const pdfImage = getImageData();\n\n // Copy the data since we'll transfer it to another worker\n const dataCopy = new Uint8ClampedArray(pdfImage.data);\n\n return workerPool.encode(\n {\n data: dataCopy,\n width: pdfImage.width,\n height: pdfImage.height,\n },\n imageType,\n quality,\n );\n };\n}\n\n/**\n * Hybrid converter: Worker pool (OffscreenCanvas) → Main thread Canvas fallback\n *\n * Best of both worlds:\n * - Primary: Non-blocking worker-based encoding with OffscreenCanvas\n * - Fallback: Main-thread Canvas for older browsers without OffscreenCanvas in workers\n *\n * @param workerPool - Instance of ImageEncoderWorkerPool\n * @returns ImageDataConverter function\n */\nexport function createHybridImageConverter(\n workerPool: ImageEncoderWorkerPool,\n): ImageDataConverter<Blob> {\n return async (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/webp',\n quality?: number,\n ): Promise<Blob> => {\n try {\n // Try worker pool encoding first (OffscreenCanvas in worker)\n const pdfImage = getImageData();\n const dataCopy = new Uint8ClampedArray(pdfImage.data);\n\n return await workerPool.encode(\n {\n data: dataCopy,\n width: pdfImage.width,\n height: pdfImage.height,\n },\n imageType,\n quality,\n );\n } catch (error) {\n // Fallback to main-thread Canvas\n console.warn('Worker encoding failed, falling back to main-thread Canvas:', error);\n return browserImageDataToBlobConverter(getImageData, imageType, quality);\n }\n };\n}\n"],"names":["ImageConverterError","Error","constructor","message","super","this","name","browserImageDataToBlobConverter","getImageData","imageType","quality","document","Promise","reject","pdfImage","imageData","ImageData","data","width","height","resolve","canvas","createElement","getContext","putImageData","toBlob","blob","workerPool","async","dataCopy","Uint8ClampedArray","encode","error","console","warn"],"mappings":"aAQO,MAAMA,UAA4BC,MACvC,WAAAC,CAAYC,GACVC,MAAMD,GACNE,KAAKC,KAAO,qBACd,EAaK,MAAMC,EAA4D,CACvEC,EACAC,EAAkC,aAClCC,KAEA,GAAwB,oBAAbC,SACT,OAAOC,QAAQC,OACb,IAAIb,EACF,8EAKN,MAAMc,EAAWN,IACXO,EAAY,IAAIC,UAAUF,EAASG,KAAMH,EAASI,MAAOJ,EAASK,QAExE,OAAO,IAAIP,QAAQ,CAACQ,EAASP,KAC3B,MAAMQ,EAASV,SAASW,cAAc,UACtCD,EAAOH,MAAQH,EAAUG,MACzBG,EAAOF,OAASJ,EAAUI,OAC1BE,EAAOE,WAAW,MAAOC,aAAaT,EAAW,EAAG,GAEpDM,EAAOI,OACJC,IACKA,EACFN,EAAQM,GAERb,EAAO,IAAIb,EAAoB,iCAGnCS,EACAC,iHAiDC,SACLiB,GAEA,OAAOC,MACLpB,EACAC,EAAkC,aAClCC,KAEA,IAEE,MAAMI,EAAWN,IACXqB,EAAW,IAAIC,kBAAkBhB,EAASG,MAEhD,aAAaU,EAAWI,OACtB,CACEd,KAAMY,EACNX,MAAOJ,EAASI,MAChBC,OAAQL,EAASK,QAEnBV,EACAC,EAEJ,OAASsB,GAGP,OADAC,QAAQC,KAAK,8DAA+DF,GACrEzB,EAAgCC,EAAcC,EAAWC,EAClE,EAEJ,yCA/DO,SACLiB,GAEA,MAAO,CACLnB,EACAC,EAAkC,aAClCC,KAEA,MAAMI,EAAWN,IAGXqB,EAAW,IAAIC,kBAAkBhB,EAASG,MAEhD,OAAOU,EAAWI,OAChB,CACEd,KAAMY,EACNX,MAAOJ,EAASI,MAChBC,OAAQL,EAASK,QAEnBV,EACAC,GAGN"}
1
+ {"version":3,"file":"browser-13mzox-R.cjs","sources":["../src/lib/converters/browser.ts"],"sourcesContent":["import type { ImageConversionTypes } from '@embedpdf/models';\nimport type { ImageDataConverter, LazyImageData } from './types';\nimport { ImageEncoderWorkerPool } from '../image-encoder';\n\n// ============================================================================\n// Error Classes\n// ============================================================================\n\nexport class ImageConverterError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ImageConverterError';\n }\n}\n\n// ============================================================================\n// Browser Converters\n// ============================================================================\n\n/**\n * Main-thread Canvas-based image converter\n * Simple and works everywhere, but blocks the main thread during encoding\n *\n * Use this as a fallback when worker-based encoding isn't available\n */\nexport const browserImageDataToBlobConverter: ImageDataConverter<Blob> = (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/webp',\n quality?: number,\n): Promise<Blob> => {\n if (typeof document === 'undefined') {\n return Promise.reject(\n new ImageConverterError(\n 'document is not available. This converter requires a browser environment.',\n ),\n );\n }\n\n const pdfImage = getImageData();\n const imageData = new ImageData(pdfImage.data, pdfImage.width, pdfImage.height);\n\n return new Promise((resolve, reject) => {\n const canvas = document.createElement('canvas');\n canvas.width = imageData.width;\n canvas.height = imageData.height;\n canvas.getContext('2d')!.putImageData(imageData, 0, 0);\n\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new ImageConverterError('Canvas toBlob returned null'));\n }\n },\n imageType,\n quality,\n );\n });\n};\n\n/**\n * Worker pool image converter using OffscreenCanvas in dedicated workers\n * Non-blocking - encoding happens off the main thread\n *\n * This is the preferred approach for performance\n *\n * @param workerPool - Instance of ImageEncoderWorkerPool\n * @returns ImageDataConverter function with destroy() for cleanup\n */\nexport function createWorkerPoolImageConverter(\n workerPool: ImageEncoderWorkerPool,\n): ImageDataConverter<Blob> {\n const converter: ImageDataConverter<Blob> = (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/webp',\n quality?: number,\n ): Promise<Blob> => {\n const pdfImage = getImageData();\n\n // Copy the data since we'll transfer it to another worker\n const dataCopy = new Uint8ClampedArray(pdfImage.data);\n\n return workerPool.encode(\n {\n data: dataCopy,\n width: pdfImage.width,\n height: pdfImage.height,\n },\n imageType,\n quality,\n );\n };\n\n // Attach destroy method to clean up worker pool\n converter.destroy = () => workerPool.destroy();\n\n return converter;\n}\n\n/**\n * Hybrid converter: Worker pool (OffscreenCanvas) → Main thread Canvas fallback\n *\n * Best of both worlds:\n * - Primary: Non-blocking worker-based encoding with OffscreenCanvas\n * - Fallback: Main-thread Canvas for older browsers without OffscreenCanvas in workers\n *\n * @param workerPool - Instance of ImageEncoderWorkerPool\n * @returns ImageDataConverter function with destroy() for cleanup\n */\nexport function createHybridImageConverter(\n workerPool: ImageEncoderWorkerPool,\n): ImageDataConverter<Blob> {\n const converter: ImageDataConverter<Blob> = async (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/webp',\n quality?: number,\n ): Promise<Blob> => {\n try {\n // Try worker pool encoding first (OffscreenCanvas in worker)\n const pdfImage = getImageData();\n const dataCopy = new Uint8ClampedArray(pdfImage.data);\n\n return await workerPool.encode(\n {\n data: dataCopy,\n width: pdfImage.width,\n height: pdfImage.height,\n },\n imageType,\n quality,\n );\n } catch (error) {\n // Fallback to main-thread Canvas\n console.warn('Worker encoding failed, falling back to main-thread Canvas:', error);\n return browserImageDataToBlobConverter(getImageData, imageType, quality);\n }\n };\n\n // Attach destroy method to clean up worker pool\n converter.destroy = () => workerPool.destroy();\n\n return converter;\n}\n"],"names":["ImageConverterError","Error","constructor","message","super","this","name","browserImageDataToBlobConverter","getImageData","imageType","quality","document","Promise","reject","pdfImage","imageData","ImageData","data","width","height","resolve","canvas","createElement","getContext","putImageData","toBlob","blob","workerPool","converter","async","dataCopy","Uint8ClampedArray","encode","error","console","warn","destroy"],"mappings":"aAQO,MAAMA,UAA4BC,MACvC,WAAAC,CAAYC,GACVC,MAAMD,GACNE,KAAKC,KAAO,qBACd,EAaK,MAAMC,EAA4D,CACvEC,EACAC,EAAkC,aAClCC,KAEA,GAAwB,oBAAbC,SACT,OAAOC,QAAQC,OACb,IAAIb,EACF,8EAKN,MAAMc,EAAWN,IACXO,EAAY,IAAIC,UAAUF,EAASG,KAAMH,EAASI,MAAOJ,EAASK,QAExE,OAAO,IAAIP,QAAQ,CAACQ,EAASP,KAC3B,MAAMQ,EAASV,SAASW,cAAc,UACtCD,EAAOH,MAAQH,EAAUG,MACzBG,EAAOF,OAASJ,EAAUI,OAC1BE,EAAOE,WAAW,MAAOC,aAAaT,EAAW,EAAG,GAEpDM,EAAOI,OACJC,IACKA,EACFN,EAAQM,GAERb,EAAO,IAAIb,EAAoB,iCAGnCS,EACAC,iHAsDC,SACLiB,GAEA,MAAMC,EAAsCC,MAC1CrB,EACAC,EAAkC,aAClCC,KAEA,IAEE,MAAMI,EAAWN,IACXsB,EAAW,IAAIC,kBAAkBjB,EAASG,MAEhD,aAAaU,EAAWK,OACtB,CACEf,KAAMa,EACNZ,MAAOJ,EAASI,MAChBC,OAAQL,EAASK,QAEnBV,EACAC,EAEJ,OAASuB,GAGP,OADAC,QAAQC,KAAK,8DAA+DF,GACrE1B,EAAgCC,EAAcC,EAAWC,EAClE,GAMF,OAFAkB,EAAUQ,QAAU,IAAMT,EAAWS,UAE9BR,CACT,yCAzEO,SACLD,GAEA,MAAMC,EAAsC,CAC1CpB,EACAC,EAAkC,aAClCC,KAEA,MAAMI,EAAWN,IAGXsB,EAAW,IAAIC,kBAAkBjB,EAASG,MAEhD,OAAOU,EAAWK,OAChB,CACEf,KAAMa,EACNZ,MAAOJ,EAASI,MAChBC,OAAQL,EAASK,QAEnBV,EACAC,IAOJ,OAFAkB,EAAUQ,QAAU,IAAMT,EAAWS,UAE9BR,CACT"}
@@ -33,7 +33,7 @@ const browserImageDataToBlobConverter = (getImageData, imageType = "image/webp",
33
33
  });
34
34
  };
35
35
  function createWorkerPoolImageConverter(workerPool) {
36
- return (getImageData, imageType = "image/webp", quality) => {
36
+ const converter = (getImageData, imageType = "image/webp", quality) => {
37
37
  const pdfImage = getImageData();
38
38
  const dataCopy = new Uint8ClampedArray(pdfImage.data);
39
39
  return workerPool.encode(
@@ -46,9 +46,11 @@ function createWorkerPoolImageConverter(workerPool) {
46
46
  quality
47
47
  );
48
48
  };
49
+ converter.destroy = () => workerPool.destroy();
50
+ return converter;
49
51
  }
50
52
  function createHybridImageConverter(workerPool) {
51
- return async (getImageData, imageType = "image/webp", quality) => {
53
+ const converter = async (getImageData, imageType = "image/webp", quality) => {
52
54
  try {
53
55
  const pdfImage = getImageData();
54
56
  const dataCopy = new Uint8ClampedArray(pdfImage.data);
@@ -66,6 +68,8 @@ function createHybridImageConverter(workerPool) {
66
68
  return browserImageDataToBlobConverter(getImageData, imageType, quality);
67
69
  }
68
70
  };
71
+ converter.destroy = () => workerPool.destroy();
72
+ return converter;
69
73
  }
70
74
  export {
71
75
  ImageConverterError as I,
@@ -73,4 +77,4 @@ export {
73
77
  browserImageDataToBlobConverter as b,
74
78
  createWorkerPoolImageConverter as c
75
79
  };
76
- //# sourceMappingURL=browser-awZxztMA.js.map
80
+ //# sourceMappingURL=browser-qfUHZxQ6.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser-awZxztMA.js","sources":["../src/lib/converters/browser.ts"],"sourcesContent":["import type { ImageConversionTypes } from '@embedpdf/models';\nimport type { ImageDataConverter, LazyImageData } from './types';\nimport { ImageEncoderWorkerPool } from '../image-encoder';\n\n// ============================================================================\n// Error Classes\n// ============================================================================\n\nexport class ImageConverterError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ImageConverterError';\n }\n}\n\n// ============================================================================\n// Browser Converters\n// ============================================================================\n\n/**\n * Main-thread Canvas-based image converter\n * Simple and works everywhere, but blocks the main thread during encoding\n *\n * Use this as a fallback when worker-based encoding isn't available\n */\nexport const browserImageDataToBlobConverter: ImageDataConverter<Blob> = (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/webp',\n quality?: number,\n): Promise<Blob> => {\n if (typeof document === 'undefined') {\n return Promise.reject(\n new ImageConverterError(\n 'document is not available. This converter requires a browser environment.',\n ),\n );\n }\n\n const pdfImage = getImageData();\n const imageData = new ImageData(pdfImage.data, pdfImage.width, pdfImage.height);\n\n return new Promise((resolve, reject) => {\n const canvas = document.createElement('canvas');\n canvas.width = imageData.width;\n canvas.height = imageData.height;\n canvas.getContext('2d')!.putImageData(imageData, 0, 0);\n\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new ImageConverterError('Canvas toBlob returned null'));\n }\n },\n imageType,\n quality,\n );\n });\n};\n\n/**\n * Worker pool image converter using OffscreenCanvas in dedicated workers\n * Non-blocking - encoding happens off the main thread\n *\n * This is the preferred approach for performance\n *\n * @param workerPool - Instance of ImageEncoderWorkerPool\n * @returns ImageDataConverter function\n */\nexport function createWorkerPoolImageConverter(\n workerPool: ImageEncoderWorkerPool,\n): ImageDataConverter<Blob> {\n return (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/webp',\n quality?: number,\n ): Promise<Blob> => {\n const pdfImage = getImageData();\n\n // Copy the data since we'll transfer it to another worker\n const dataCopy = new Uint8ClampedArray(pdfImage.data);\n\n return workerPool.encode(\n {\n data: dataCopy,\n width: pdfImage.width,\n height: pdfImage.height,\n },\n imageType,\n quality,\n );\n };\n}\n\n/**\n * Hybrid converter: Worker pool (OffscreenCanvas) → Main thread Canvas fallback\n *\n * Best of both worlds:\n * - Primary: Non-blocking worker-based encoding with OffscreenCanvas\n * - Fallback: Main-thread Canvas for older browsers without OffscreenCanvas in workers\n *\n * @param workerPool - Instance of ImageEncoderWorkerPool\n * @returns ImageDataConverter function\n */\nexport function createHybridImageConverter(\n workerPool: ImageEncoderWorkerPool,\n): ImageDataConverter<Blob> {\n return async (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/webp',\n quality?: number,\n ): Promise<Blob> => {\n try {\n // Try worker pool encoding first (OffscreenCanvas in worker)\n const pdfImage = getImageData();\n const dataCopy = new Uint8ClampedArray(pdfImage.data);\n\n return await workerPool.encode(\n {\n data: dataCopy,\n width: pdfImage.width,\n height: pdfImage.height,\n },\n imageType,\n quality,\n );\n } catch (error) {\n // Fallback to main-thread Canvas\n console.warn('Worker encoding failed, falling back to main-thread Canvas:', error);\n return browserImageDataToBlobConverter(getImageData, imageType, quality);\n }\n };\n}\n"],"names":[],"mappings":"AAQO,MAAM,4BAA4B,MAAM;AAAA,EAC7C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAYO,MAAM,kCAA4D,CACvE,cACA,YAAkC,cAClC,YACkB;AAClB,MAAI,OAAO,aAAa,aAAa;AACnC,WAAO,QAAQ;AAAA,MACb,IAAI;AAAA,QACF;AAAA,MAAA;AAAA,IACF;AAAA,EAEJ;AAEA,QAAM,WAAW,aAAA;AACjB,QAAM,YAAY,IAAI,UAAU,SAAS,MAAM,SAAS,OAAO,SAAS,MAAM;AAE9E,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,QAAQ,UAAU;AACzB,WAAO,SAAS,UAAU;AAC1B,WAAO,WAAW,IAAI,EAAG,aAAa,WAAW,GAAG,CAAC;AAErD,WAAO;AAAA,MACL,CAAC,SAAS;AACR,YAAI,MAAM;AACR,kBAAQ,IAAI;AAAA,QACd,OAAO;AACL,iBAAO,IAAI,oBAAoB,6BAA6B,CAAC;AAAA,QAC/D;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ,CAAC;AACH;AAWO,SAAS,+BACd,YAC0B;AAC1B,SAAO,CACL,cACA,YAAkC,cAClC,YACkB;AAClB,UAAM,WAAW,aAAA;AAGjB,UAAM,WAAW,IAAI,kBAAkB,SAAS,IAAI;AAEpD,WAAO,WAAW;AAAA,MAChB;AAAA,QACE,MAAM;AAAA,QACN,OAAO,SAAS;AAAA,QAChB,QAAQ,SAAS;AAAA,MAAA;AAAA,MAEnB;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AACF;AAYO,SAAS,2BACd,YAC0B;AAC1B,SAAO,OACL,cACA,YAAkC,cAClC,YACkB;AAClB,QAAI;AAEF,YAAM,WAAW,aAAA;AACjB,YAAM,WAAW,IAAI,kBAAkB,SAAS,IAAI;AAEpD,aAAO,MAAM,WAAW;AAAA,QACtB;AAAA,UACE,MAAM;AAAA,UACN,OAAO,SAAS;AAAA,UAChB,QAAQ,SAAS;AAAA,QAAA;AAAA,QAEnB;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ,SAAS,OAAO;AAEd,cAAQ,KAAK,+DAA+D,KAAK;AACjF,aAAO,gCAAgC,cAAc,WAAW,OAAO;AAAA,IACzE;AAAA,EACF;AACF;"}
1
+ {"version":3,"file":"browser-qfUHZxQ6.js","sources":["../src/lib/converters/browser.ts"],"sourcesContent":["import type { ImageConversionTypes } from '@embedpdf/models';\nimport type { ImageDataConverter, LazyImageData } from './types';\nimport { ImageEncoderWorkerPool } from '../image-encoder';\n\n// ============================================================================\n// Error Classes\n// ============================================================================\n\nexport class ImageConverterError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ImageConverterError';\n }\n}\n\n// ============================================================================\n// Browser Converters\n// ============================================================================\n\n/**\n * Main-thread Canvas-based image converter\n * Simple and works everywhere, but blocks the main thread during encoding\n *\n * Use this as a fallback when worker-based encoding isn't available\n */\nexport const browserImageDataToBlobConverter: ImageDataConverter<Blob> = (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/webp',\n quality?: number,\n): Promise<Blob> => {\n if (typeof document === 'undefined') {\n return Promise.reject(\n new ImageConverterError(\n 'document is not available. This converter requires a browser environment.',\n ),\n );\n }\n\n const pdfImage = getImageData();\n const imageData = new ImageData(pdfImage.data, pdfImage.width, pdfImage.height);\n\n return new Promise((resolve, reject) => {\n const canvas = document.createElement('canvas');\n canvas.width = imageData.width;\n canvas.height = imageData.height;\n canvas.getContext('2d')!.putImageData(imageData, 0, 0);\n\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new ImageConverterError('Canvas toBlob returned null'));\n }\n },\n imageType,\n quality,\n );\n });\n};\n\n/**\n * Worker pool image converter using OffscreenCanvas in dedicated workers\n * Non-blocking - encoding happens off the main thread\n *\n * This is the preferred approach for performance\n *\n * @param workerPool - Instance of ImageEncoderWorkerPool\n * @returns ImageDataConverter function with destroy() for cleanup\n */\nexport function createWorkerPoolImageConverter(\n workerPool: ImageEncoderWorkerPool,\n): ImageDataConverter<Blob> {\n const converter: ImageDataConverter<Blob> = (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/webp',\n quality?: number,\n ): Promise<Blob> => {\n const pdfImage = getImageData();\n\n // Copy the data since we'll transfer it to another worker\n const dataCopy = new Uint8ClampedArray(pdfImage.data);\n\n return workerPool.encode(\n {\n data: dataCopy,\n width: pdfImage.width,\n height: pdfImage.height,\n },\n imageType,\n quality,\n );\n };\n\n // Attach destroy method to clean up worker pool\n converter.destroy = () => workerPool.destroy();\n\n return converter;\n}\n\n/**\n * Hybrid converter: Worker pool (OffscreenCanvas) → Main thread Canvas fallback\n *\n * Best of both worlds:\n * - Primary: Non-blocking worker-based encoding with OffscreenCanvas\n * - Fallback: Main-thread Canvas for older browsers without OffscreenCanvas in workers\n *\n * @param workerPool - Instance of ImageEncoderWorkerPool\n * @returns ImageDataConverter function with destroy() for cleanup\n */\nexport function createHybridImageConverter(\n workerPool: ImageEncoderWorkerPool,\n): ImageDataConverter<Blob> {\n const converter: ImageDataConverter<Blob> = async (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/webp',\n quality?: number,\n ): Promise<Blob> => {\n try {\n // Try worker pool encoding first (OffscreenCanvas in worker)\n const pdfImage = getImageData();\n const dataCopy = new Uint8ClampedArray(pdfImage.data);\n\n return await workerPool.encode(\n {\n data: dataCopy,\n width: pdfImage.width,\n height: pdfImage.height,\n },\n imageType,\n quality,\n );\n } catch (error) {\n // Fallback to main-thread Canvas\n console.warn('Worker encoding failed, falling back to main-thread Canvas:', error);\n return browserImageDataToBlobConverter(getImageData, imageType, quality);\n }\n };\n\n // Attach destroy method to clean up worker pool\n converter.destroy = () => workerPool.destroy();\n\n return converter;\n}\n"],"names":[],"mappings":"AAQO,MAAM,4BAA4B,MAAM;AAAA,EAC7C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAYO,MAAM,kCAA4D,CACvE,cACA,YAAkC,cAClC,YACkB;AAClB,MAAI,OAAO,aAAa,aAAa;AACnC,WAAO,QAAQ;AAAA,MACb,IAAI;AAAA,QACF;AAAA,MAAA;AAAA,IACF;AAAA,EAEJ;AAEA,QAAM,WAAW,aAAA;AACjB,QAAM,YAAY,IAAI,UAAU,SAAS,MAAM,SAAS,OAAO,SAAS,MAAM;AAE9E,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,QAAQ,UAAU;AACzB,WAAO,SAAS,UAAU;AAC1B,WAAO,WAAW,IAAI,EAAG,aAAa,WAAW,GAAG,CAAC;AAErD,WAAO;AAAA,MACL,CAAC,SAAS;AACR,YAAI,MAAM;AACR,kBAAQ,IAAI;AAAA,QACd,OAAO;AACL,iBAAO,IAAI,oBAAoB,6BAA6B,CAAC;AAAA,QAC/D;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ,CAAC;AACH;AAWO,SAAS,+BACd,YAC0B;AAC1B,QAAM,YAAsC,CAC1C,cACA,YAAkC,cAClC,YACkB;AAClB,UAAM,WAAW,aAAA;AAGjB,UAAM,WAAW,IAAI,kBAAkB,SAAS,IAAI;AAEpD,WAAO,WAAW;AAAA,MAChB;AAAA,QACE,MAAM;AAAA,QACN,OAAO,SAAS;AAAA,QAChB,QAAQ,SAAS;AAAA,MAAA;AAAA,MAEnB;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAGA,YAAU,UAAU,MAAM,WAAW,QAAA;AAErC,SAAO;AACT;AAYO,SAAS,2BACd,YAC0B;AAC1B,QAAM,YAAsC,OAC1C,cACA,YAAkC,cAClC,YACkB;AAClB,QAAI;AAEF,YAAM,WAAW,aAAA;AACjB,YAAM,WAAW,IAAI,kBAAkB,SAAS,IAAI;AAEpD,aAAO,MAAM,WAAW;AAAA,QACtB;AAAA,UACE,MAAM;AAAA,UACN,OAAO,SAAS;AAAA,UAChB,QAAQ,SAAS;AAAA,QAAA;AAAA,QAEnB;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ,SAAS,OAAO;AAEd,cAAQ,KAAK,+DAA+D,KAAK;AACjF,aAAO,gCAAgC,cAAc,WAAW,OAAO;AAAA,IACzE;AAAA,EACF;AAGA,YAAU,UAAU,MAAM,WAAW,QAAA;AAErC,SAAO;AACT;"}
@@ -1,7 +1,7 @@
1
1
  import { init } from "@embedpdf/pdfium";
2
- import { Rotation, NoopLogger, PdfTaskHelper, PdfErrorCode, pdfDateToDate, isUuidV4, uuidV4, PdfAnnotationSubtype, PdfPageFlattenFlag, stripPdfUnwantedMarkers, PdfAnnotationIcon, PdfAnnotationBorderStyle, PdfAnnotationColorType, PdfAnnotationLineEnding, PdfStampFit, PdfTrappedStatus, pdfColorToWebColor, webColorToPdfColor, pdfAlphaToWebOpacity, webOpacityToPdfAlpha, PdfAnnotationReplyType, dateToPdfDate, quadToRect, rectToQuad, PdfStandardFont, PdfPageObjectType, flagsToNames, namesToFlags, PDF_FORM_FIELD_TYPE, AppearanceMode, Task, toIntRect, transformRect, buildUserToDeviceMatrix, PdfZoomMode, PdfActionType } from "@embedpdf/models";
3
- import { P as PdfEngine } from "./pdf-engine-ChjNHvQd.js";
4
- import { b as browserImageDataToBlobConverter } from "./browser-awZxztMA.js";
2
+ import { Rotation, NoopLogger, PdfTaskHelper, PdfErrorCode, pdfDateToDate, isUuidV4, uuidV4, PdfAnnotationSubtype, PdfPageFlattenFlag, stripPdfUnwantedMarkers, PdfAnnotationIcon, PdfAnnotationBorderStyle, PdfAnnotationColorType, PdfAnnotationLineEnding, PdfStandardFont, PdfStampFit, PdfTrappedStatus, pdfColorToWebColor, webColorToPdfColor, pdfAlphaToWebOpacity, webOpacityToPdfAlpha, PdfAnnotationReplyType, dateToPdfDate, quadToRect, rectToQuad, PdfPageObjectType, flagsToNames, namesToFlags, PDF_FORM_FIELD_TYPE, AppearanceMode, Task, toIntRect, transformRect, buildUserToDeviceMatrix, PdfZoomMode, PdfActionType } from "@embedpdf/models";
3
+ import { P as PdfEngine } from "./pdf-engine-CVXuu1xQ.js";
4
+ import { b as browserImageDataToBlobConverter } from "./browser-qfUHZxQ6.js";
5
5
  function readString(wasmModule, readChars, parseChars, defaultLength = 100) {
6
6
  let buffer = wasmModule.wasmExports.malloc(defaultLength);
7
7
  for (let i = 0; i < defaultLength; i++) {
@@ -1598,6 +1598,9 @@ class PdfiumNative {
1598
1598
  case PdfAnnotationSubtype.LINK:
1599
1599
  isSucceed = this.addLinkContent(ctx.docPtr, pageCtx.pagePtr, annotationPtr, annotation);
1600
1600
  break;
1601
+ case PdfAnnotationSubtype.REDACT:
1602
+ isSucceed = this.addRedactContent(page, pageCtx.pagePtr, annotationPtr, annotation);
1603
+ break;
1601
1604
  }
1602
1605
  if (!isSucceed) {
1603
1606
  this.pdfiumModule.FPDFPage_RemoveAnnot(pageCtx.pagePtr, annotationPtr);
@@ -1743,6 +1746,11 @@ class PdfiumNative {
1743
1746
  ok = this.addLinkContent(ctx.docPtr, pageCtx.pagePtr, annotPtr, annotation);
1744
1747
  break;
1745
1748
  }
1749
+ /* ── Redact ───────────────────────────────────────────────────────────── */
1750
+ case PdfAnnotationSubtype.REDACT: {
1751
+ ok = this.addRedactContent(page, pageCtx.pagePtr, annotPtr, annotation);
1752
+ break;
1753
+ }
1746
1754
  /* ── Unsupported edits – fall through to error ───────────────────────── */
1747
1755
  default:
1748
1756
  ok = false;
@@ -3021,6 +3029,73 @@ class PdfiumNative {
3021
3029
  }
3022
3030
  return this.applyBaseAnnotationProperties(pagePtr, annotationPtr, annotation);
3023
3031
  }
3032
+ /**
3033
+ * Add content to redact annotation
3034
+ * @param page - page info
3035
+ * @param pagePtr - pointer to page object
3036
+ * @param annotationPtr - pointer to redact annotation
3037
+ * @param annotation - redact annotation
3038
+ * @returns whether redact content is added to annotation
3039
+ *
3040
+ * @private
3041
+ */
3042
+ addRedactContent(page, pagePtr, annotationPtr, annotation) {
3043
+ if (!this.syncQuadPointsAnno(page, annotationPtr, annotation.segmentRects)) {
3044
+ return false;
3045
+ }
3046
+ if (!this.setAnnotationOpacity(annotationPtr, annotation.opacity ?? 1)) {
3047
+ return false;
3048
+ }
3049
+ if (!annotation.color || annotation.color === "transparent") {
3050
+ if (!this.pdfiumModule.EPDFAnnot_ClearColor(annotationPtr, PdfAnnotationColorType.InteriorColor)) {
3051
+ return false;
3052
+ }
3053
+ } else if (!this.setAnnotationColor(
3054
+ annotationPtr,
3055
+ annotation.color,
3056
+ PdfAnnotationColorType.InteriorColor
3057
+ )) {
3058
+ return false;
3059
+ }
3060
+ if (!annotation.overlayColor || annotation.overlayColor === "transparent") {
3061
+ if (!this.pdfiumModule.EPDFAnnot_ClearColor(annotationPtr, PdfAnnotationColorType.OverlayColor)) {
3062
+ return false;
3063
+ }
3064
+ } else if (!this.setAnnotationColor(
3065
+ annotationPtr,
3066
+ annotation.overlayColor,
3067
+ PdfAnnotationColorType.OverlayColor
3068
+ )) {
3069
+ return false;
3070
+ }
3071
+ if (!annotation.strokeColor || annotation.strokeColor === "transparent") {
3072
+ if (!this.pdfiumModule.EPDFAnnot_ClearColor(annotationPtr, PdfAnnotationColorType.Color)) {
3073
+ return false;
3074
+ }
3075
+ } else if (!this.setAnnotationColor(annotationPtr, annotation.strokeColor, PdfAnnotationColorType.Color)) {
3076
+ return false;
3077
+ }
3078
+ if (!this.setOverlayText(annotationPtr, annotation.overlayText)) {
3079
+ return false;
3080
+ }
3081
+ if (annotation.overlayTextRepeat !== void 0 && !this.setOverlayTextRepeat(annotationPtr, annotation.overlayTextRepeat)) {
3082
+ return false;
3083
+ }
3084
+ if (annotation.fontFamily !== void 0 || annotation.fontSize !== void 0) {
3085
+ if (!this.setAnnotationDefaultAppearance(
3086
+ annotationPtr,
3087
+ annotation.fontFamily ?? PdfStandardFont.Helvetica,
3088
+ annotation.fontSize ?? 12,
3089
+ annotation.fontColor ?? "#000000"
3090
+ )) {
3091
+ return false;
3092
+ }
3093
+ }
3094
+ if (annotation.textAlign !== void 0 && !this.setAnnotationTextAlignment(annotationPtr, annotation.textAlign)) {
3095
+ return false;
3096
+ }
3097
+ return this.applyBaseAnnotationProperties(pagePtr, annotationPtr, annotation);
3098
+ }
3024
3099
  /**
3025
3100
  * Add contents to stamp annotation
3026
3101
  * @param docPtr - pointer to pdf document object
@@ -3936,6 +4011,11 @@ class PdfiumNative {
3936
4011
  annotation = this.readPdfCaretAnno(page, annotationPtr, index);
3937
4012
  }
3938
4013
  break;
4014
+ case PdfAnnotationSubtype.REDACT:
4015
+ {
4016
+ annotation = this.readPdfRedactAnno(page, annotationPtr, index);
4017
+ }
4018
+ break;
3939
4019
  default:
3940
4020
  {
3941
4021
  annotation = this.readPdfAnno(page, subType, annotationPtr, index);
@@ -4076,6 +4156,64 @@ class PdfiumNative {
4076
4156
  setAnnotationVerticalAlignment(annotationPtr, alignment) {
4077
4157
  return !!this.pdfiumModule.EPDFAnnot_SetVerticalAlignment(annotationPtr, alignment);
4078
4158
  }
4159
+ /**
4160
+ * Get the overlay text from a Redact annotation.
4161
+ *
4162
+ * @param annotationPtr pointer returned by `FPDFPage_GetAnnot`
4163
+ * @returns overlay text string or `undefined` if not set
4164
+ *
4165
+ * @private
4166
+ */
4167
+ getOverlayText(annotationPtr) {
4168
+ const len = this.pdfiumModule.EPDFAnnot_GetOverlayText(annotationPtr, 0, 0);
4169
+ if (len === 0) return void 0;
4170
+ const bytes = (len + 1) * 2;
4171
+ const ptr = this.memoryManager.malloc(bytes);
4172
+ this.pdfiumModule.EPDFAnnot_GetOverlayText(annotationPtr, ptr, bytes);
4173
+ const value = this.pdfiumModule.pdfium.UTF16ToString(ptr);
4174
+ this.memoryManager.free(ptr);
4175
+ return value || void 0;
4176
+ }
4177
+ /**
4178
+ * Set the overlay text on a Redact annotation.
4179
+ *
4180
+ * @param annotationPtr pointer returned by `FPDFPage_GetAnnot`
4181
+ * @param text overlay text to set, or undefined/empty to clear
4182
+ * @returns `true` on success
4183
+ *
4184
+ * @private
4185
+ */
4186
+ setOverlayText(annotationPtr, text) {
4187
+ if (!text) {
4188
+ return this.pdfiumModule.EPDFAnnot_SetOverlayText(annotationPtr, 0);
4189
+ }
4190
+ return this.withWString(text, (wPtr) => {
4191
+ return this.pdfiumModule.EPDFAnnot_SetOverlayText(annotationPtr, wPtr);
4192
+ });
4193
+ }
4194
+ /**
4195
+ * Get whether overlay text repeats in a Redact annotation.
4196
+ *
4197
+ * @param annotationPtr pointer returned by `FPDFPage_GetAnnot`
4198
+ * @returns `true` if overlay text repeats
4199
+ *
4200
+ * @private
4201
+ */
4202
+ getOverlayTextRepeat(annotationPtr) {
4203
+ return this.pdfiumModule.EPDFAnnot_GetOverlayTextRepeat(annotationPtr);
4204
+ }
4205
+ /**
4206
+ * Set whether overlay text repeats in a Redact annotation.
4207
+ *
4208
+ * @param annotationPtr pointer returned by `FPDFPage_GetAnnot`
4209
+ * @param repeat whether overlay text should repeat
4210
+ * @returns `true` on success
4211
+ *
4212
+ * @private
4213
+ */
4214
+ setOverlayTextRepeat(annotationPtr, repeat) {
4215
+ return this.pdfiumModule.EPDFAnnot_SetOverlayTextRepeat(annotationPtr, repeat);
4216
+ }
4079
4217
  /**
4080
4218
  * Return the **default appearance** (font, size, colour) declared in the
4081
4219
  * `/DA` string of a **FreeText** annotation.
@@ -4592,6 +4730,132 @@ class PdfiumNative {
4592
4730
  this.logger.perf("PDFiumEngine", "Engine", label, "End", `${doc.id}-${page.index}`);
4593
4731
  return PdfTaskHelper.resolve(!!ok);
4594
4732
  }
4733
+ /**
4734
+ * Apply a single redaction annotation, permanently removing content underneath
4735
+ * and flattening the RO (Redact Overlay) appearance stream if present.
4736
+ * The annotation is removed after successful application.
4737
+ *
4738
+ * @param doc - document object
4739
+ * @param page - page object
4740
+ * @param annotation - the redact annotation to apply
4741
+ * @returns true if successful
4742
+ */
4743
+ applyRedaction(doc, page, annotation) {
4744
+ this.logger.debug(
4745
+ LOG_SOURCE,
4746
+ LOG_CATEGORY,
4747
+ "applyRedaction",
4748
+ doc.id,
4749
+ page.index,
4750
+ annotation.id
4751
+ );
4752
+ const label = "ApplyRedaction";
4753
+ this.logger.perf(LOG_SOURCE, LOG_CATEGORY, label, "Begin", `${doc.id}-${page.index}`);
4754
+ const ctx = this.cache.getContext(doc.id);
4755
+ if (!ctx) {
4756
+ this.logger.perf(LOG_SOURCE, LOG_CATEGORY, label, "End", `${doc.id}-${page.index}`);
4757
+ return PdfTaskHelper.reject({
4758
+ code: PdfErrorCode.DocNotOpen,
4759
+ message: "document does not open"
4760
+ });
4761
+ }
4762
+ const pageCtx = ctx.acquirePage(page.index);
4763
+ const annotPtr = this.getAnnotationByName(pageCtx.pagePtr, annotation.id);
4764
+ if (!annotPtr) {
4765
+ pageCtx.release();
4766
+ this.logger.perf(LOG_SOURCE, LOG_CATEGORY, label, "End", `${doc.id}-${page.index}`);
4767
+ return PdfTaskHelper.reject({
4768
+ code: PdfErrorCode.NotFound,
4769
+ message: "annotation not found"
4770
+ });
4771
+ }
4772
+ const ok = this.pdfiumModule.EPDFAnnot_ApplyRedaction(pageCtx.pagePtr, annotPtr);
4773
+ this.pdfiumModule.FPDFPage_CloseAnnot(annotPtr);
4774
+ if (ok) {
4775
+ this.pdfiumModule.FPDFPage_GenerateContent(pageCtx.pagePtr);
4776
+ }
4777
+ pageCtx.disposeImmediate();
4778
+ this.logger.perf(LOG_SOURCE, LOG_CATEGORY, label, "End", `${doc.id}-${page.index}`);
4779
+ return PdfTaskHelper.resolve(!!ok);
4780
+ }
4781
+ /**
4782
+ * Apply all redaction annotations on a page, permanently removing content
4783
+ * underneath each one and flattening RO streams if present.
4784
+ * All redact annotations are removed after successful application.
4785
+ *
4786
+ * @param doc - document object
4787
+ * @param page - page object
4788
+ * @returns true if any redactions were applied
4789
+ */
4790
+ applyAllRedactions(doc, page) {
4791
+ this.logger.debug(LOG_SOURCE, LOG_CATEGORY, "applyAllRedactions", doc.id, page.index);
4792
+ const label = "ApplyAllRedactions";
4793
+ this.logger.perf(LOG_SOURCE, LOG_CATEGORY, label, "Begin", `${doc.id}-${page.index}`);
4794
+ const ctx = this.cache.getContext(doc.id);
4795
+ if (!ctx) {
4796
+ this.logger.perf(LOG_SOURCE, LOG_CATEGORY, label, "End", `${doc.id}-${page.index}`);
4797
+ return PdfTaskHelper.reject({
4798
+ code: PdfErrorCode.DocNotOpen,
4799
+ message: "document does not open"
4800
+ });
4801
+ }
4802
+ const pageCtx = ctx.acquirePage(page.index);
4803
+ const ok = this.pdfiumModule.EPDFPage_ApplyRedactions(pageCtx.pagePtr);
4804
+ if (ok) {
4805
+ this.pdfiumModule.FPDFPage_GenerateContent(pageCtx.pagePtr);
4806
+ }
4807
+ pageCtx.disposeImmediate();
4808
+ this.logger.perf(LOG_SOURCE, LOG_CATEGORY, label, "End", `${doc.id}-${page.index}`);
4809
+ return PdfTaskHelper.resolve(!!ok);
4810
+ }
4811
+ /**
4812
+ * Flatten an annotation's appearance (AP/N) to page content.
4813
+ * The annotation's visual appearance becomes part of the page itself.
4814
+ * The annotation is automatically removed after flattening.
4815
+ *
4816
+ * @param doc - document object
4817
+ * @param page - page object
4818
+ * @param annotation - the annotation to flatten
4819
+ * @returns true if successful
4820
+ */
4821
+ flattenAnnotation(doc, page, annotation) {
4822
+ this.logger.debug(
4823
+ LOG_SOURCE,
4824
+ LOG_CATEGORY,
4825
+ "flattenAnnotation",
4826
+ doc.id,
4827
+ page.index,
4828
+ annotation.id
4829
+ );
4830
+ const label = "FlattenAnnotation";
4831
+ this.logger.perf(LOG_SOURCE, LOG_CATEGORY, label, "Begin", `${doc.id}-${page.index}`);
4832
+ const ctx = this.cache.getContext(doc.id);
4833
+ if (!ctx) {
4834
+ this.logger.perf(LOG_SOURCE, LOG_CATEGORY, label, "End", `${doc.id}-${page.index}`);
4835
+ return PdfTaskHelper.reject({
4836
+ code: PdfErrorCode.DocNotOpen,
4837
+ message: "document does not open"
4838
+ });
4839
+ }
4840
+ const pageCtx = ctx.acquirePage(page.index);
4841
+ const annotPtr = this.getAnnotationByName(pageCtx.pagePtr, annotation.id);
4842
+ if (!annotPtr) {
4843
+ pageCtx.release();
4844
+ this.logger.perf(LOG_SOURCE, LOG_CATEGORY, label, "End", `${doc.id}-${page.index}`);
4845
+ return PdfTaskHelper.reject({
4846
+ code: PdfErrorCode.NotFound,
4847
+ message: "annotation not found"
4848
+ });
4849
+ }
4850
+ const ok = this.pdfiumModule.EPDFAnnot_Flatten(pageCtx.pagePtr, annotPtr);
4851
+ this.pdfiumModule.FPDFPage_CloseAnnot(annotPtr);
4852
+ if (ok) {
4853
+ this.pdfiumModule.FPDFPage_GenerateContent(pageCtx.pagePtr);
4854
+ }
4855
+ pageCtx.disposeImmediate();
4856
+ this.logger.perf(LOG_SOURCE, LOG_CATEGORY, label, "End", `${doc.id}-${page.index}`);
4857
+ return PdfTaskHelper.resolve(!!ok);
4858
+ }
4595
4859
  /** Pack device-space Rects into an FS_QUADPOINTSF[] buffer (page space). */
4596
4860
  allocFSQuadsBufferFromRects(page, rects) {
4597
4861
  const STRIDE = 32;
@@ -5152,6 +5416,49 @@ class PdfiumNative {
5152
5416
  ...this.readBaseAnnotationProperties(annotationPtr)
5153
5417
  };
5154
5418
  }
5419
+ /**
5420
+ * Read pdf redact annotation
5421
+ * @param page - pdf page info
5422
+ * @param annotationPtr - pointer to pdf annotation
5423
+ * @param index - index of annotation in the pdf page
5424
+ * @returns pdf redact annotation
5425
+ *
5426
+ * @private
5427
+ */
5428
+ readPdfRedactAnno(page, annotationPtr, index) {
5429
+ const pageRect = this.readPageAnnoRect(annotationPtr);
5430
+ const rect = this.convertPageRectToDeviceRect(page, pageRect);
5431
+ const segmentRects = this.getQuadPointsAnno(page, annotationPtr);
5432
+ const color = this.getAnnotationColor(annotationPtr, PdfAnnotationColorType.InteriorColor);
5433
+ const overlayColor = this.getAnnotationColor(
5434
+ annotationPtr,
5435
+ PdfAnnotationColorType.OverlayColor
5436
+ );
5437
+ const strokeColor = this.getAnnotationColor(annotationPtr, PdfAnnotationColorType.Color);
5438
+ const opacity = this.getAnnotationOpacity(annotationPtr);
5439
+ const overlayText = this.getOverlayText(annotationPtr);
5440
+ const overlayTextRepeat = this.getOverlayTextRepeat(annotationPtr);
5441
+ const da = this.getAnnotationDefaultAppearance(annotationPtr);
5442
+ const textAlign = this.getAnnotationTextAlignment(annotationPtr);
5443
+ return {
5444
+ pageIndex: page.index,
5445
+ id: index,
5446
+ type: PdfAnnotationSubtype.REDACT,
5447
+ rect,
5448
+ segmentRects,
5449
+ color,
5450
+ overlayColor,
5451
+ strokeColor,
5452
+ opacity,
5453
+ overlayText,
5454
+ overlayTextRepeat,
5455
+ fontFamily: da == null ? void 0 : da.fontFamily,
5456
+ fontSize: da == null ? void 0 : da.fontSize,
5457
+ fontColor: da == null ? void 0 : da.fontColor,
5458
+ textAlign,
5459
+ ...this.readBaseAnnotationProperties(annotationPtr)
5460
+ };
5461
+ }
5155
5462
  /**
5156
5463
  * Read pdf stamp annotation
5157
5464
  * @param page - pdf page infor
@@ -7293,4 +7600,4 @@ export {
7293
7600
  isValidCustomKey as i,
7294
7601
  readString as r
7295
7602
  };
7296
- //# sourceMappingURL=direct-engine-nrX_KvVy.js.map
7603
+ //# sourceMappingURL=direct-engine-5RWKENek.js.map