@embedpdf/engines 1.0.7 → 1.0.9
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.
- package/dist/index.cjs +405 -258
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +101 -56
- package/dist/index.js +406 -259
- package/dist/index.js.map +1 -1
- package/dist/pdfium-direct-engine.cjs +379 -232
- package/dist/pdfium-direct-engine.cjs.map +1 -1
- package/dist/pdfium-direct-engine.d.ts +95 -50
- package/dist/pdfium-direct-engine.js +380 -233
- package/dist/pdfium-direct-engine.js.map +1 -1
- package/dist/pdfium-worker-engine.cjs +21 -21
- package/dist/pdfium-worker-engine.cjs.map +1 -1
- package/dist/pdfium-worker-engine.d.ts +7 -7
- package/dist/pdfium-worker-engine.js +21 -21
- package/dist/pdfium-worker-engine.js.map +1 -1
- package/dist/pdfium.cjs +382 -235
- package/dist/pdfium.cjs.map +1 -1
- package/dist/pdfium.d.ts +95 -50
- package/dist/pdfium.js +383 -236
- package/dist/pdfium.js.map +1 -1
- package/dist/preact.cjs +5 -3
- package/dist/preact.cjs.map +1 -1
- package/dist/preact.d.ts +4 -3
- package/dist/preact.js +5 -3
- package/dist/preact.js.map +1 -1
- package/dist/react.cjs +5 -3
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.ts +4 -3
- package/dist/react.js +5 -3
- package/dist/react.js.map +1 -1
- package/dist/worker.cjs +20 -20
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.ts +7 -7
- package/dist/worker.js +20 -20
- package/dist/worker.js.map +1 -1
- package/package.json +3 -3
package/dist/pdfium.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NoopLogger, PdfTaskHelper, PdfErrorCode, Task, Rotation, PdfAnnotationSubtype, stripPdfUnwantedMarkers, dateToPdfDate, PdfPageObjectType, pdfAlphaColorToWebAlphaColor, webAlphaColorToPdfAlphaColor,
|
|
1
|
+
import { NoopLogger, PdfTaskHelper, PdfErrorCode, Task, Rotation, PdfAnnotationSubtype, stripPdfUnwantedMarkers, PdfAnnotationBorderStyle, dateToPdfDate, PdfAnnotationColorType, PdfPageObjectType, pdfAlphaColorToWebAlphaColor, webAlphaColorToPdfAlphaColor, quadToRect, pdfDateToDate, flagsToNames, PDF_FORM_FIELD_TYPE, toIntRect, transformRect, makeMatrix, AppearanceMode, toIntSize, transformSize, PdfActionType, PdfZoomMode, MatchFlag, rectToQuad } from '@embedpdf/models';
|
|
2
2
|
import { init } from '@embedpdf/pdfium';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -910,7 +910,7 @@ class PdfiumEngine {
|
|
|
910
910
|
let isSucceed = false;
|
|
911
911
|
switch (annotation.type) {
|
|
912
912
|
case PdfAnnotationSubtype.INK:
|
|
913
|
-
isSucceed = this.addInkStroke(page, pageCtx.pagePtr, annotationPtr, annotation
|
|
913
|
+
isSucceed = this.addInkStroke(page, pageCtx.pagePtr, annotationPtr, annotation);
|
|
914
914
|
break;
|
|
915
915
|
case PdfAnnotationSubtype.STAMP:
|
|
916
916
|
isSucceed = this.addStampContent(ctx.docPtr, page, pageCtx.pagePtr, annotationPtr, annotation.rect, annotation.contents);
|
|
@@ -919,7 +919,7 @@ class PdfiumEngine {
|
|
|
919
919
|
case PdfAnnotationSubtype.STRIKEOUT:
|
|
920
920
|
case PdfAnnotationSubtype.SQUIGGLY:
|
|
921
921
|
case PdfAnnotationSubtype.HIGHLIGHT:
|
|
922
|
-
isSucceed = this.addTextMarkupContent(page, annotationPtr, annotation);
|
|
922
|
+
isSucceed = this.addTextMarkupContent(page, pageCtx.pagePtr, annotationPtr, annotation);
|
|
923
923
|
break;
|
|
924
924
|
}
|
|
925
925
|
if (!isSucceed) {
|
|
@@ -931,6 +931,7 @@ class PdfiumEngine {
|
|
|
931
931
|
message: 'can not add content of the annotation',
|
|
932
932
|
});
|
|
933
933
|
}
|
|
934
|
+
this.pdfiumModule.EPDFAnnot_GenerateAppearance(annotationPtr);
|
|
934
935
|
this.pdfiumModule.FPDFPage_GenerateContent(pageCtx.pagePtr);
|
|
935
936
|
const annotId = this.pdfiumModule.FPDFPage_GetAnnotIndex(pageCtx.pagePtr, annotationPtr);
|
|
936
937
|
this.pdfiumModule.FPDFPage_CloseAnnot(annotationPtr);
|
|
@@ -988,7 +989,7 @@ class PdfiumEngine {
|
|
|
988
989
|
/* clear every existing stroke first */
|
|
989
990
|
if (!this.pdfiumModule.FPDFAnnot_RemoveInkList(annotPtr))
|
|
990
991
|
break;
|
|
991
|
-
ok = this.addInkStroke(page, pageCtx.pagePtr, annotPtr, annotation
|
|
992
|
+
ok = this.addInkStroke(page, pageCtx.pagePtr, annotPtr, annotation);
|
|
992
993
|
break;
|
|
993
994
|
}
|
|
994
995
|
/* ── Stamp ───────────────────────────────────────────────────────────── */
|
|
@@ -1006,7 +1007,7 @@ class PdfiumEngine {
|
|
|
1006
1007
|
case PdfAnnotationSubtype.STRIKEOUT:
|
|
1007
1008
|
case PdfAnnotationSubtype.SQUIGGLY: {
|
|
1008
1009
|
/* replace quad-points / colour / strings in one go */
|
|
1009
|
-
ok = this.addTextMarkupContent(page, annotPtr, annotation
|
|
1010
|
+
ok = this.addTextMarkupContent(page, pageCtx.pagePtr, annotPtr, annotation);
|
|
1010
1011
|
break;
|
|
1011
1012
|
}
|
|
1012
1013
|
/* ── Unsupported edits – fall through to error ───────────────────────── */
|
|
@@ -1015,6 +1016,7 @@ class PdfiumEngine {
|
|
|
1015
1016
|
}
|
|
1016
1017
|
/* 3 ── regenerate appearance if payload was changed ───────────────────── */
|
|
1017
1018
|
if (ok) {
|
|
1019
|
+
this.pdfiumModule.EPDFAnnot_GenerateAppearance(annotPtr);
|
|
1018
1020
|
this.pdfiumModule.FPDFPage_GenerateContent(pageCtx.pagePtr);
|
|
1019
1021
|
}
|
|
1020
1022
|
/* 4 ── tidy-up native handles ──────────────────────────────────────────── */
|
|
@@ -1028,85 +1030,6 @@ class PdfiumEngine {
|
|
|
1028
1030
|
message: 'failed to update annotation',
|
|
1029
1031
|
});
|
|
1030
1032
|
}
|
|
1031
|
-
/**
|
|
1032
|
-
* {@inheritDoc @embedpdf/models!PdfEngine.transformPageAnnotation}
|
|
1033
|
-
*
|
|
1034
|
-
* @public
|
|
1035
|
-
*/
|
|
1036
|
-
transformPageAnnotation(doc, page, annotation, transformation) {
|
|
1037
|
-
this.logger.debug(LOG_SOURCE$1, LOG_CATEGORY$1, 'transformPageAnnotation', doc, page, annotation, transformation);
|
|
1038
|
-
this.logger.perf(LOG_SOURCE$1, LOG_CATEGORY$1, `TransformPageAnnotation`, 'Begin', `${doc.id}-${page.index}`);
|
|
1039
|
-
const ctx = this.cache.getContext(doc.id);
|
|
1040
|
-
if (!ctx) {
|
|
1041
|
-
this.logger.perf(LOG_SOURCE$1, LOG_CATEGORY$1, `TransformPageAnnotation`, 'End', `${doc.id}-${page.index}`);
|
|
1042
|
-
return PdfTaskHelper.reject({
|
|
1043
|
-
code: PdfErrorCode.DocNotOpen,
|
|
1044
|
-
message: 'document does not open',
|
|
1045
|
-
});
|
|
1046
|
-
}
|
|
1047
|
-
const pageCtx = ctx.acquirePage(page.index);
|
|
1048
|
-
const annotationPtr = this.pdfiumModule.FPDFPage_GetAnnot(pageCtx.pagePtr, annotation.id);
|
|
1049
|
-
const rect = {
|
|
1050
|
-
origin: {
|
|
1051
|
-
x: annotation.rect.origin.x + transformation.offset.x,
|
|
1052
|
-
y: annotation.rect.origin.y + transformation.offset.y,
|
|
1053
|
-
},
|
|
1054
|
-
size: {
|
|
1055
|
-
width: annotation.rect.size.width * transformation.scale.width,
|
|
1056
|
-
height: annotation.rect.size.height * transformation.scale.height,
|
|
1057
|
-
},
|
|
1058
|
-
};
|
|
1059
|
-
if (!this.setPageAnnoRect(page, pageCtx.pagePtr, annotationPtr, rect)) {
|
|
1060
|
-
this.pdfiumModule.FPDFPage_CloseAnnot(annotationPtr);
|
|
1061
|
-
pageCtx.release();
|
|
1062
|
-
this.logger.perf(LOG_SOURCE$1, LOG_CATEGORY$1, `TransformPageAnnotation`, 'End', `${doc.id}-${page.index}`);
|
|
1063
|
-
return PdfTaskHelper.reject({
|
|
1064
|
-
code: PdfErrorCode.CantSetAnnotRect,
|
|
1065
|
-
message: 'can not set the rect of the annotation',
|
|
1066
|
-
});
|
|
1067
|
-
}
|
|
1068
|
-
switch (annotation.type) {
|
|
1069
|
-
case PdfAnnotationSubtype.INK:
|
|
1070
|
-
{
|
|
1071
|
-
if (!this.pdfiumModule.FPDFAnnot_RemoveInkList(annotationPtr)) {
|
|
1072
|
-
this.pdfiumModule.FPDFPage_CloseAnnot(annotationPtr);
|
|
1073
|
-
pageCtx.release();
|
|
1074
|
-
this.logger.perf(LOG_SOURCE$1, LOG_CATEGORY$1, `TransformPageAnnotation`, 'End', `${doc.id}-${page.index}`);
|
|
1075
|
-
return PdfTaskHelper.reject({
|
|
1076
|
-
code: PdfErrorCode.CantRemoveInkList,
|
|
1077
|
-
message: 'can not set the rect of the annotation',
|
|
1078
|
-
});
|
|
1079
|
-
}
|
|
1080
|
-
const inkList = annotation.inkList.map((inkStroke) => {
|
|
1081
|
-
return {
|
|
1082
|
-
points: inkStroke.points.map((point) => {
|
|
1083
|
-
return {
|
|
1084
|
-
x: rect.origin.x +
|
|
1085
|
-
(point.x - annotation.rect.origin.x) * transformation.scale.width,
|
|
1086
|
-
y: rect.origin.y +
|
|
1087
|
-
(point.y - annotation.rect.origin.y) * transformation.scale.height,
|
|
1088
|
-
};
|
|
1089
|
-
}),
|
|
1090
|
-
};
|
|
1091
|
-
});
|
|
1092
|
-
if (!this.addInkStroke(page, pageCtx.pagePtr, annotationPtr, inkList)) {
|
|
1093
|
-
this.pdfiumModule.FPDFPage_CloseAnnot(annotationPtr);
|
|
1094
|
-
pageCtx.release();
|
|
1095
|
-
this.logger.perf(LOG_SOURCE$1, LOG_CATEGORY$1, `TransformPageAnnotation`, 'End', `${doc.id}-${page.index}`);
|
|
1096
|
-
return PdfTaskHelper.reject({
|
|
1097
|
-
code: PdfErrorCode.CantAddInkStoke,
|
|
1098
|
-
message: 'can not add stroke to the ink list of annotation',
|
|
1099
|
-
});
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
1102
|
-
break;
|
|
1103
|
-
}
|
|
1104
|
-
this.pdfiumModule.FPDFPage_GenerateContent(pageCtx.pagePtr);
|
|
1105
|
-
this.pdfiumModule.FPDFPage_CloseAnnot(annotationPtr);
|
|
1106
|
-
pageCtx.release();
|
|
1107
|
-
this.logger.perf(LOG_SOURCE$1, LOG_CATEGORY$1, `TransformPageAnnotation`, 'End', `${doc.id}-${page.index}`);
|
|
1108
|
-
return PdfTaskHelper.resolve(true);
|
|
1109
|
-
}
|
|
1110
1033
|
/**
|
|
1111
1034
|
* {@inheritDoc @embedpdf/models!PdfEngine.removePageAnnotation}
|
|
1112
1035
|
*
|
|
@@ -1727,21 +1650,27 @@ class PdfiumEngine {
|
|
|
1727
1650
|
*
|
|
1728
1651
|
* @private
|
|
1729
1652
|
*/
|
|
1730
|
-
addInkStroke(page, pagePtr, annotationPtr,
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1653
|
+
addInkStroke(page, pagePtr, annotationPtr, annotation) {
|
|
1654
|
+
if (!this.setBorderStyle(annotationPtr, PdfAnnotationBorderStyle.SOLID, annotation.strokeWidth)) {
|
|
1655
|
+
return false;
|
|
1656
|
+
}
|
|
1657
|
+
if (!this.setPageAnnoRect(page, pagePtr, annotationPtr, annotation.rect)) {
|
|
1658
|
+
return false;
|
|
1659
|
+
}
|
|
1660
|
+
if (!this.setInkList(page, annotationPtr, annotation.inkList)) {
|
|
1661
|
+
return false;
|
|
1662
|
+
}
|
|
1663
|
+
if (!this.setAnnotString(annotationPtr, 'T', annotation.author || '')) {
|
|
1664
|
+
return false;
|
|
1665
|
+
}
|
|
1666
|
+
if (!this.setAnnotString(annotationPtr, 'M', dateToPdfDate(annotation.modified))) {
|
|
1667
|
+
return false;
|
|
1668
|
+
}
|
|
1669
|
+
if (!this.setAnnotationColor(annotationPtr, {
|
|
1670
|
+
color: annotation.color ?? '#FFFF00',
|
|
1671
|
+
opacity: annotation.opacity ?? 1,
|
|
1672
|
+
}, PdfAnnotationColorType.Color)) {
|
|
1673
|
+
return false;
|
|
1745
1674
|
}
|
|
1746
1675
|
return true;
|
|
1747
1676
|
}
|
|
@@ -1754,7 +1683,10 @@ class PdfiumEngine {
|
|
|
1754
1683
|
*
|
|
1755
1684
|
* @private
|
|
1756
1685
|
*/
|
|
1757
|
-
addTextMarkupContent(page, annotationPtr, annotation
|
|
1686
|
+
addTextMarkupContent(page, pagePtr, annotationPtr, annotation) {
|
|
1687
|
+
if (!this.setPageAnnoRect(page, pagePtr, annotationPtr, annotation.rect)) {
|
|
1688
|
+
return false;
|
|
1689
|
+
}
|
|
1758
1690
|
if (!this.syncQuadPointsAnno(page, annotationPtr, annotation.segmentRects)) {
|
|
1759
1691
|
return false;
|
|
1760
1692
|
}
|
|
@@ -1770,7 +1702,7 @@ class PdfiumEngine {
|
|
|
1770
1702
|
if (!this.setAnnotationColor(annotationPtr, {
|
|
1771
1703
|
color: annotation.color ?? '#FFFF00',
|
|
1772
1704
|
opacity: annotation.opacity ?? 1,
|
|
1773
|
-
},
|
|
1705
|
+
}, PdfAnnotationColorType.Color)) {
|
|
1774
1706
|
return false;
|
|
1775
1707
|
}
|
|
1776
1708
|
return true;
|
|
@@ -2417,14 +2349,13 @@ class PdfiumEngine {
|
|
|
2417
2349
|
*
|
|
2418
2350
|
* @private
|
|
2419
2351
|
*/
|
|
2420
|
-
readAnnotationColor(annotationPtr) {
|
|
2352
|
+
readAnnotationColor(annotationPtr, colorType = PdfAnnotationColorType.Color) {
|
|
2421
2353
|
const rPtr = this.malloc(4);
|
|
2422
2354
|
const gPtr = this.malloc(4);
|
|
2423
2355
|
const bPtr = this.malloc(4);
|
|
2424
2356
|
const aPtr = this.malloc(4);
|
|
2425
2357
|
// colourType 0 = "colour" (stroke/fill); other types are interior/border
|
|
2426
|
-
const ok = this.pdfiumModule.
|
|
2427
|
-
/* colorType = */ 0, rPtr, gPtr, bPtr, aPtr);
|
|
2358
|
+
const ok = this.pdfiumModule.EPDFAnnot_GetColor(annotationPtr, colorType, rPtr, gPtr, bPtr, aPtr);
|
|
2428
2359
|
let colour;
|
|
2429
2360
|
if (ok) {
|
|
2430
2361
|
colour = {
|
|
@@ -2441,97 +2372,6 @@ class PdfiumEngine {
|
|
|
2441
2372
|
return colour;
|
|
2442
2373
|
}
|
|
2443
2374
|
/* --------------------------------------------------------------------------- */
|
|
2444
|
-
/**
|
|
2445
|
-
* Extract the fill (or, if absent, the stroke) colour from a **path object**
|
|
2446
|
-
* inside an appearance stream.
|
|
2447
|
-
*
|
|
2448
|
-
* Works for simple highlights produced by Chrome, Preview, etc. that paint a
|
|
2449
|
-
* single filled rectangle with the desired tint.
|
|
2450
|
-
*
|
|
2451
|
-
* @param pathPtr - pointer to a `FPDF_PAGEOBJECT` of type **PATH**
|
|
2452
|
-
* @returns RGBA tuple or `undefined` when no colour is set on the path
|
|
2453
|
-
*
|
|
2454
|
-
* @private
|
|
2455
|
-
*/
|
|
2456
|
-
getColorFromPath(pathPtr) {
|
|
2457
|
-
const r = this.malloc(4), g = this.malloc(4), b = this.malloc(4), a = this.malloc(4);
|
|
2458
|
-
const fillOk = this.pdfiumModule.FPDFPageObj_GetFillColor(pathPtr, r, g, b, a);
|
|
2459
|
-
const strokeOk = !fillOk && // try stroke only if fill failed
|
|
2460
|
-
this.pdfiumModule.FPDFPageObj_GetStrokeColor(pathPtr, r, g, b, a);
|
|
2461
|
-
const ok = fillOk || strokeOk;
|
|
2462
|
-
let c;
|
|
2463
|
-
if (ok) {
|
|
2464
|
-
c = {
|
|
2465
|
-
red: this.pdfiumModule.pdfium.getValue(r, 'i32') & 0xff,
|
|
2466
|
-
green: this.pdfiumModule.pdfium.getValue(g, 'i32') & 0xff,
|
|
2467
|
-
blue: this.pdfiumModule.pdfium.getValue(b, 'i32') & 0xff,
|
|
2468
|
-
alpha: this.pdfiumModule.pdfium.getValue(a, 'i32') & 0xff,
|
|
2469
|
-
};
|
|
2470
|
-
}
|
|
2471
|
-
this.free(r);
|
|
2472
|
-
this.free(g);
|
|
2473
|
-
this.free(b);
|
|
2474
|
-
this.free(a);
|
|
2475
|
-
return c;
|
|
2476
|
-
}
|
|
2477
|
-
/* --------------------------------------------------------------------------- */
|
|
2478
|
-
/**
|
|
2479
|
-
* Recursively walk a page-object tree (PATHs and nested FORM XObjects) until
|
|
2480
|
-
* a colour can be extracted.
|
|
2481
|
-
*
|
|
2482
|
-
* Acrobat often wraps its highlight rectangle in a Form XObject referenced by
|
|
2483
|
-
* the "Do" operator, so this function drills down unlimited depth.
|
|
2484
|
-
*
|
|
2485
|
-
* @param objPtr - pointer to a `FPDF_PAGEOBJECT`
|
|
2486
|
-
* @returns First RGBA tint found, or `undefined` if none of the descendants
|
|
2487
|
-
* carry an explicit fill/stroke colour
|
|
2488
|
-
*
|
|
2489
|
-
* @private
|
|
2490
|
-
*/
|
|
2491
|
-
walkPageObjTree(objPtr) {
|
|
2492
|
-
const type = this.pdfiumModule.FPDFPageObj_GetType(objPtr);
|
|
2493
|
-
if (type === PdfPageObjectType.PATH)
|
|
2494
|
-
return this.getColorFromPath(objPtr);
|
|
2495
|
-
if (type !== PdfPageObjectType.FORM)
|
|
2496
|
-
return undefined;
|
|
2497
|
-
const cnt = this.pdfiumModule.FPDFFormObj_CountObjects(objPtr);
|
|
2498
|
-
for (let i = 0; i < cnt; i++) {
|
|
2499
|
-
const child = this.pdfiumModule.FPDFFormObj_GetObject(objPtr, i);
|
|
2500
|
-
if (!child)
|
|
2501
|
-
continue;
|
|
2502
|
-
const c = this.walkPageObjTree(child);
|
|
2503
|
-
if (c)
|
|
2504
|
-
return c;
|
|
2505
|
-
}
|
|
2506
|
-
return undefined;
|
|
2507
|
-
}
|
|
2508
|
-
/* --------------------------------------------------------------------------- */
|
|
2509
|
-
/**
|
|
2510
|
-
* Iterate over every top-level object in the annotation's **appearance stream**
|
|
2511
|
-
* and invoke {@link walkPageObjTree} to locate a usable tint.
|
|
2512
|
-
*
|
|
2513
|
-
* Catches:
|
|
2514
|
-
* • Simple filled path (Preview, Chrome)
|
|
2515
|
-
* • Form XObject containing the path (Acrobat)
|
|
2516
|
-
*
|
|
2517
|
-
* @param annotPtr - pointer to an `FPDF_ANNOTATION`
|
|
2518
|
-
* @returns RGBA tuple or `undefined` when no colour can be resolved from AP
|
|
2519
|
-
*
|
|
2520
|
-
* @private
|
|
2521
|
-
*/
|
|
2522
|
-
colorFromAppearance(annotPtr) {
|
|
2523
|
-
const n = this.pdfiumModule.FPDFAnnot_GetObjectCount(annotPtr);
|
|
2524
|
-
for (let i = 0; i < n; i++) {
|
|
2525
|
-
const obj = this.pdfiumModule.FPDFAnnot_GetObject(annotPtr, i);
|
|
2526
|
-
if (!obj)
|
|
2527
|
-
continue;
|
|
2528
|
-
const c = this.walkPageObjTree(obj);
|
|
2529
|
-
if (c)
|
|
2530
|
-
return c;
|
|
2531
|
-
}
|
|
2532
|
-
return undefined;
|
|
2533
|
-
}
|
|
2534
|
-
/* --------------------------------------------------------------------------- */
|
|
2535
2375
|
/**
|
|
2536
2376
|
* Resolve the visible fill colour for **Highlight / Underline / StrikeOut /
|
|
2537
2377
|
* Squiggly** markup annotations.
|
|
@@ -2547,10 +2387,8 @@ class PdfiumEngine {
|
|
|
2547
2387
|
*
|
|
2548
2388
|
* @private
|
|
2549
2389
|
*/
|
|
2550
|
-
resolveAnnotationColor(annotationPtr, fallback = { red: 255, green: 245, blue: 155, alpha: 255 }) {
|
|
2551
|
-
const pdfColor = this.readAnnotationColor(annotationPtr) ??
|
|
2552
|
-
this.colorFromAppearance(annotationPtr) ?? // 2 – AP stream walk
|
|
2553
|
-
fallback; // 3 – default
|
|
2390
|
+
resolveAnnotationColor(annotationPtr, colorType = PdfAnnotationColorType.Color, fallback = { red: 255, green: 245, blue: 155, alpha: 255 }) {
|
|
2391
|
+
const pdfColor = this.readAnnotationColor(annotationPtr, colorType) ?? fallback;
|
|
2554
2392
|
return pdfAlphaColorToWebAlphaColor(pdfColor);
|
|
2555
2393
|
}
|
|
2556
2394
|
/**
|
|
@@ -2564,14 +2402,115 @@ class PdfiumEngine {
|
|
|
2564
2402
|
*
|
|
2565
2403
|
* @private
|
|
2566
2404
|
*/
|
|
2567
|
-
setAnnotationColor(annotationPtr, webAlphaColor,
|
|
2405
|
+
setAnnotationColor(annotationPtr, webAlphaColor, colorType = PdfAnnotationColorType.Color) {
|
|
2568
2406
|
const pdfAlphaColor = webAlphaColorToPdfAlphaColor(webAlphaColor);
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2407
|
+
return this.pdfiumModule.EPDFAnnot_SetColor(annotationPtr, colorType, pdfAlphaColor.red & 0xff, pdfAlphaColor.green & 0xff, pdfAlphaColor.blue & 0xff, (pdfAlphaColor.alpha ?? 255) & 0xff);
|
|
2408
|
+
}
|
|
2409
|
+
/**
|
|
2410
|
+
* Border‐style + width helper
|
|
2411
|
+
*
|
|
2412
|
+
* Tries the new PDFium helper `EPDFAnnot_GetBorderStyle()` (patch series
|
|
2413
|
+
* 9 July 2025).
|
|
2414
|
+
*
|
|
2415
|
+
* @param annotationPtr pointer to an `FPDF_ANNOTATION`
|
|
2416
|
+
* @returns `{ ok, style, width }`
|
|
2417
|
+
* • `ok` – `true` when the call succeeded
|
|
2418
|
+
* • `style` – `PdfAnnotationBorderStyle` enum
|
|
2419
|
+
* • `width` – stroke-width in points (defaults to 0 pt)
|
|
2420
|
+
*/
|
|
2421
|
+
getBorderStyle(annotationPtr) {
|
|
2422
|
+
/* 1 ── allocate tmp storage for the returned width ─────────────── */
|
|
2423
|
+
const widthPtr = this.malloc(4);
|
|
2424
|
+
let width = 0;
|
|
2425
|
+
let style = PdfAnnotationBorderStyle.UNKNOWN;
|
|
2426
|
+
let ok = false;
|
|
2427
|
+
style = this.pdfiumModule.EPDFAnnot_GetBorderStyle(annotationPtr, widthPtr);
|
|
2428
|
+
width = this.pdfiumModule.pdfium.getValue(widthPtr, 'float');
|
|
2429
|
+
ok = style !== PdfAnnotationBorderStyle.UNKNOWN;
|
|
2430
|
+
this.free(widthPtr);
|
|
2431
|
+
return { ok, style, width };
|
|
2432
|
+
}
|
|
2433
|
+
setBorderStyle(annotationPtr, style, width) {
|
|
2434
|
+
return this.pdfiumModule.EPDFAnnot_SetBorderStyle(annotationPtr, style, width);
|
|
2435
|
+
}
|
|
2436
|
+
/**
|
|
2437
|
+
* Border-effect (“cloudy”) helper
|
|
2438
|
+
*
|
|
2439
|
+
* Calls the new PDFium function `EPDFAnnot_GetBorderEffect()` (July 2025).
|
|
2440
|
+
*
|
|
2441
|
+
* @param annotationPtr pointer to an `FPDF_ANNOTATION`
|
|
2442
|
+
* @returns `{ ok, intensity }`
|
|
2443
|
+
* • `ok` – `true` when the annotation *does* have a
|
|
2444
|
+
* valid cloudy-border effect
|
|
2445
|
+
* • `intensity` – radius/intensity value (0 when `ok` is false)
|
|
2446
|
+
*/
|
|
2447
|
+
getBorderEffect(annotationPtr) {
|
|
2448
|
+
const intensityPtr = this.malloc(4);
|
|
2449
|
+
const ok = !!this.pdfiumModule.EPDFAnnot_GetBorderEffect(annotationPtr, intensityPtr);
|
|
2450
|
+
const intensity = ok ? this.pdfiumModule.pdfium.getValue(intensityPtr, 'float') : 0;
|
|
2451
|
+
this.free(intensityPtr);
|
|
2452
|
+
return { ok, intensity };
|
|
2453
|
+
}
|
|
2454
|
+
/**
|
|
2455
|
+
* Rectangle-differences helper ( /RD array on Square / Circle annots )
|
|
2456
|
+
*
|
|
2457
|
+
* Calls `EPDFAnnot_GetRectangleDifferences()` introduced in July 2025.
|
|
2458
|
+
*
|
|
2459
|
+
* @param annotationPtr pointer to an `FPDF_ANNOTATION`
|
|
2460
|
+
* @returns `{ ok, left, top, right, bottom }`
|
|
2461
|
+
* • `ok` – `true` when the annotation *has* an /RD entry
|
|
2462
|
+
* • the four floats are 0 when `ok` is false
|
|
2463
|
+
*/
|
|
2464
|
+
getRectangleDifferences(annotationPtr) {
|
|
2465
|
+
/* tmp storage ─────────────────────────────────────────── */
|
|
2466
|
+
const lPtr = this.malloc(4);
|
|
2467
|
+
const tPtr = this.malloc(4);
|
|
2468
|
+
const rPtr = this.malloc(4);
|
|
2469
|
+
const bPtr = this.malloc(4);
|
|
2470
|
+
const ok = !!this.pdfiumModule.EPDFAnnot_GetRectangleDifferences(annotationPtr, lPtr, tPtr, rPtr, bPtr);
|
|
2471
|
+
const pdf = this.pdfiumModule.pdfium;
|
|
2472
|
+
const left = pdf.getValue(lPtr, 'float');
|
|
2473
|
+
const top = pdf.getValue(tPtr, 'float');
|
|
2474
|
+
const right = pdf.getValue(rPtr, 'float');
|
|
2475
|
+
const bottom = pdf.getValue(bPtr, 'float');
|
|
2476
|
+
/* cleanup ─────────────────────────────────────────────── */
|
|
2477
|
+
this.free(lPtr);
|
|
2478
|
+
this.free(tPtr);
|
|
2479
|
+
this.free(rPtr);
|
|
2480
|
+
this.free(bPtr);
|
|
2481
|
+
return { ok, left, top, right, bottom };
|
|
2482
|
+
}
|
|
2483
|
+
/**
|
|
2484
|
+
* Dash-pattern helper ( /BS → /D array, dashed borders only )
|
|
2485
|
+
*
|
|
2486
|
+
* Uses the two new PDFium helpers:
|
|
2487
|
+
* • `EPDFAnnot_GetBorderDashPatternCount`
|
|
2488
|
+
* • `EPDFAnnot_GetBorderDashPattern`
|
|
2489
|
+
*
|
|
2490
|
+
* @param annotationPtr pointer to an `FPDF_ANNOTATION`
|
|
2491
|
+
* @returns `{ ok, pattern }`
|
|
2492
|
+
* • `ok` – `true` when the annot is dashed *and* the array
|
|
2493
|
+
* was retrieved successfully
|
|
2494
|
+
* • `pattern` – numeric array of dash/space lengths (empty when `ok` is false)
|
|
2495
|
+
*/
|
|
2496
|
+
getBorderDashPattern(annotationPtr) {
|
|
2497
|
+
const count = this.pdfiumModule.EPDFAnnot_GetBorderDashPatternCount(annotationPtr);
|
|
2498
|
+
if (count === 0) {
|
|
2499
|
+
return { ok: false, pattern: [] };
|
|
2500
|
+
}
|
|
2501
|
+
/* allocate `count` floats on the WASM heap */
|
|
2502
|
+
const arrPtr = this.malloc(4 * count);
|
|
2503
|
+
const okNative = !!this.pdfiumModule.EPDFAnnot_GetBorderDashPattern(annotationPtr, arrPtr, count);
|
|
2504
|
+
/* copy out */
|
|
2505
|
+
const pattern = [];
|
|
2506
|
+
if (okNative) {
|
|
2507
|
+
const pdf = this.pdfiumModule.pdfium;
|
|
2508
|
+
for (let i = 0; i < count; i++) {
|
|
2509
|
+
pattern.push(pdf.getValue(arrPtr + 4 * i, 'float'));
|
|
2510
|
+
}
|
|
2573
2511
|
}
|
|
2574
|
-
|
|
2512
|
+
this.free(arrPtr);
|
|
2513
|
+
return { ok: okNative, pattern };
|
|
2575
2514
|
}
|
|
2576
2515
|
/**
|
|
2577
2516
|
* Read `/QuadPoints` from any annotation and convert each quadrilateral to
|
|
@@ -2670,6 +2609,62 @@ class PdfiumEngine {
|
|
|
2670
2609
|
this.free(buf);
|
|
2671
2610
|
return true;
|
|
2672
2611
|
}
|
|
2612
|
+
/**
|
|
2613
|
+
* Read ink list from annotation
|
|
2614
|
+
* @param page - logical page info object (`PdfPageObject`)
|
|
2615
|
+
* @param annotationPtr - pointer to the annotation whose ink list is needed
|
|
2616
|
+
* @returns ink list
|
|
2617
|
+
*/
|
|
2618
|
+
getInkList(page, annotationPtr) {
|
|
2619
|
+
const inkList = [];
|
|
2620
|
+
const count = this.pdfiumModule.FPDFAnnot_GetInkListCount(annotationPtr);
|
|
2621
|
+
for (let i = 0; i < count; i++) {
|
|
2622
|
+
const points = [];
|
|
2623
|
+
const pointsCount = this.pdfiumModule.FPDFAnnot_GetInkListPath(annotationPtr, i, 0, 0);
|
|
2624
|
+
if (pointsCount > 0) {
|
|
2625
|
+
const pointMemorySize = 8;
|
|
2626
|
+
const pointsPtr = this.malloc(pointsCount * pointMemorySize);
|
|
2627
|
+
this.pdfiumModule.FPDFAnnot_GetInkListPath(annotationPtr, i, pointsPtr, pointsCount);
|
|
2628
|
+
for (let j = 0; j < pointsCount; j++) {
|
|
2629
|
+
const pointX = this.pdfiumModule.pdfium.getValue(pointsPtr + j * 8, 'float');
|
|
2630
|
+
const pointY = this.pdfiumModule.pdfium.getValue(pointsPtr + j * 8 + 4, 'float');
|
|
2631
|
+
const { x, y } = this.convertPagePointToDevicePoint(page, {
|
|
2632
|
+
x: pointX,
|
|
2633
|
+
y: pointY,
|
|
2634
|
+
});
|
|
2635
|
+
points.push({ x, y });
|
|
2636
|
+
}
|
|
2637
|
+
this.free(pointsPtr);
|
|
2638
|
+
}
|
|
2639
|
+
inkList.push({ points });
|
|
2640
|
+
}
|
|
2641
|
+
return inkList;
|
|
2642
|
+
}
|
|
2643
|
+
/**
|
|
2644
|
+
* Add ink list to annotation
|
|
2645
|
+
* @param page - logical page info object (`PdfPageObject`)
|
|
2646
|
+
* @param annotationPtr - pointer to the annotation whose ink list is needed
|
|
2647
|
+
* @param annotation - annotation object (`PdfInkAnnoObject`)
|
|
2648
|
+
* @returns `true` if the operation was successful
|
|
2649
|
+
*/
|
|
2650
|
+
setInkList(page, annotationPtr, inkList) {
|
|
2651
|
+
for (const inkStroke of inkList) {
|
|
2652
|
+
const inkPointsCount = inkStroke.points.length;
|
|
2653
|
+
const inkPointsPtr = this.malloc(inkPointsCount * 8);
|
|
2654
|
+
for (let i = 0; i < inkPointsCount; i++) {
|
|
2655
|
+
const point = inkStroke.points[i];
|
|
2656
|
+
const { x, y } = this.convertDevicePointToPagePoint(page, point);
|
|
2657
|
+
this.pdfiumModule.pdfium.setValue(inkPointsPtr + i * 8, x, 'float');
|
|
2658
|
+
this.pdfiumModule.pdfium.setValue(inkPointsPtr + i * 8 + 4, y, 'float');
|
|
2659
|
+
}
|
|
2660
|
+
if (this.pdfiumModule.FPDFAnnot_AddInkStroke(annotationPtr, inkPointsPtr, inkPointsCount) === -1) {
|
|
2661
|
+
this.free(inkPointsPtr);
|
|
2662
|
+
return false;
|
|
2663
|
+
}
|
|
2664
|
+
this.free(inkPointsPtr);
|
|
2665
|
+
}
|
|
2666
|
+
return true;
|
|
2667
|
+
}
|
|
2673
2668
|
/**
|
|
2674
2669
|
* Read pdf text annotation
|
|
2675
2670
|
* @param page - pdf page infor
|
|
@@ -2846,32 +2841,15 @@ class PdfiumEngine {
|
|
|
2846
2841
|
const author = this.getAnnotString(annotationPtr, 'T');
|
|
2847
2842
|
const modifiedRaw = this.getAnnotString(annotationPtr, 'M');
|
|
2848
2843
|
const modified = pdfDateToDate(modifiedRaw);
|
|
2849
|
-
const
|
|
2850
|
-
const
|
|
2851
|
-
|
|
2852
|
-
const points = [];
|
|
2853
|
-
const pointsCount = this.pdfiumModule.FPDFAnnot_GetInkListPath(annotationPtr, i, 0, 0);
|
|
2854
|
-
if (pointsCount > 0) {
|
|
2855
|
-
const pointMemorySize = 8;
|
|
2856
|
-
const pointsPtr = this.malloc(pointsCount * pointMemorySize);
|
|
2857
|
-
this.pdfiumModule.FPDFAnnot_GetInkListPath(annotationPtr, i, pointsPtr, pointsCount);
|
|
2858
|
-
for (let j = 0; j < pointsCount; j++) {
|
|
2859
|
-
const pointX = this.pdfiumModule.pdfium.getValue(pointsPtr + j * 8, 'float');
|
|
2860
|
-
const pointY = this.pdfiumModule.pdfium.getValue(pointsPtr + j * 8 + 4, 'float');
|
|
2861
|
-
const { x, y } = this.convertPagePointToDevicePoint(page, {
|
|
2862
|
-
x: pointX,
|
|
2863
|
-
y: pointY,
|
|
2864
|
-
});
|
|
2865
|
-
points.push({ x, y });
|
|
2866
|
-
}
|
|
2867
|
-
this.free(pointsPtr);
|
|
2868
|
-
}
|
|
2869
|
-
inkList.push({ points });
|
|
2870
|
-
}
|
|
2844
|
+
const webAlphaColor = this.resolveAnnotationColor(annotationPtr);
|
|
2845
|
+
const { width: strokeWidth } = this.getBorderStyle(annotationPtr);
|
|
2846
|
+
const inkList = this.getInkList(page, annotationPtr);
|
|
2871
2847
|
return {
|
|
2872
2848
|
pageIndex: page.index,
|
|
2873
2849
|
id: index,
|
|
2874
2850
|
type: PdfAnnotationSubtype.INK,
|
|
2851
|
+
...webAlphaColor,
|
|
2852
|
+
strokeWidth,
|
|
2875
2853
|
rect,
|
|
2876
2854
|
inkList,
|
|
2877
2855
|
author,
|
|
@@ -3325,6 +3303,39 @@ class PdfiumEngine {
|
|
|
3325
3303
|
this.free(matrixPtr);
|
|
3326
3304
|
return { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 };
|
|
3327
3305
|
}
|
|
3306
|
+
/**
|
|
3307
|
+
* Return the stroke-width declared in the annotation’s /Border or /BS entry.
|
|
3308
|
+
* Falls back to 1 pt when nothing is defined.
|
|
3309
|
+
*
|
|
3310
|
+
* @param annotationPtr - pointer to pdf annotation
|
|
3311
|
+
* @returns stroke-width
|
|
3312
|
+
*
|
|
3313
|
+
* @private
|
|
3314
|
+
*/
|
|
3315
|
+
getStrokeWidth(annotationPtr) {
|
|
3316
|
+
// FPDFAnnot_GetBorder(annot, &hRadius, &vRadius, &borderWidth)
|
|
3317
|
+
const hPtr = this.malloc(4);
|
|
3318
|
+
const vPtr = this.malloc(4);
|
|
3319
|
+
const wPtr = this.malloc(4);
|
|
3320
|
+
const ok = this.pdfiumModule.FPDFAnnot_GetBorder(annotationPtr, hPtr, vPtr, wPtr);
|
|
3321
|
+
const width = ok ? this.pdfiumModule.pdfium.getValue(wPtr, 'float') : 1; // default 1 pt
|
|
3322
|
+
this.free(hPtr);
|
|
3323
|
+
this.free(vPtr);
|
|
3324
|
+
this.free(wPtr);
|
|
3325
|
+
return width;
|
|
3326
|
+
}
|
|
3327
|
+
/**
|
|
3328
|
+
* Fetches the `/F` flag bit-field from an annotation.
|
|
3329
|
+
*
|
|
3330
|
+
* @param annotationPtr pointer to an `FPDF_ANNOTATION`
|
|
3331
|
+
* @returns `{ raw, flags }`
|
|
3332
|
+
* • `raw` – the 32-bit integer returned by PDFium
|
|
3333
|
+
* • `flags` – object with individual booleans
|
|
3334
|
+
*/
|
|
3335
|
+
getAnnotationFlags(annotationPtr) {
|
|
3336
|
+
const rawFlags = this.pdfiumModule.FPDFAnnot_GetFlags(annotationPtr); // number
|
|
3337
|
+
return flagsToNames(rawFlags);
|
|
3338
|
+
}
|
|
3328
3339
|
/**
|
|
3329
3340
|
* Read circle annotation
|
|
3330
3341
|
* @param page - pdf page infor
|
|
@@ -3336,18 +3347,51 @@ class PdfiumEngine {
|
|
|
3336
3347
|
* @private
|
|
3337
3348
|
*/
|
|
3338
3349
|
readPdfCircleAnno(page, pagePtr, annotationPtr, index) {
|
|
3350
|
+
const flags = this.getAnnotationFlags(annotationPtr);
|
|
3339
3351
|
const pageRect = this.readPageAnnoRect(annotationPtr);
|
|
3340
3352
|
const rect = this.convertPageRectToDeviceRect(page, pagePtr, pageRect);
|
|
3341
3353
|
const author = this.getAnnotString(annotationPtr, 'T');
|
|
3342
3354
|
const modifiedRaw = this.getAnnotString(annotationPtr, 'M');
|
|
3343
3355
|
const modified = pdfDateToDate(modifiedRaw);
|
|
3356
|
+
const { color, opacity } = this.resolveAnnotationColor(annotationPtr, PdfAnnotationColorType.InteriorColor);
|
|
3357
|
+
const { color: strokeColor } = this.resolveAnnotationColor(annotationPtr);
|
|
3358
|
+
let { style: strokeStyle, width: strokeWidth } = this.getBorderStyle(annotationPtr);
|
|
3359
|
+
let cloudyBorderIntensity;
|
|
3360
|
+
let cloudyBorderInset;
|
|
3361
|
+
if (strokeStyle === PdfAnnotationBorderStyle.CLOUDY ||
|
|
3362
|
+
strokeStyle === PdfAnnotationBorderStyle.UNKNOWN) {
|
|
3363
|
+
const { ok: hasEffect, intensity } = this.getBorderEffect(annotationPtr);
|
|
3364
|
+
if (hasEffect) {
|
|
3365
|
+
cloudyBorderIntensity = intensity;
|
|
3366
|
+
strokeStyle = PdfAnnotationBorderStyle.CLOUDY;
|
|
3367
|
+
const { ok: hasInset, left, top, right, bottom, } = this.getRectangleDifferences(annotationPtr);
|
|
3368
|
+
if (hasInset)
|
|
3369
|
+
cloudyBorderInset = [left, top, right, bottom];
|
|
3370
|
+
}
|
|
3371
|
+
}
|
|
3372
|
+
let strokeDashArray;
|
|
3373
|
+
if (strokeStyle === PdfAnnotationBorderStyle.DASHED) {
|
|
3374
|
+
const { ok, pattern } = this.getBorderDashPattern(annotationPtr);
|
|
3375
|
+
if (ok) {
|
|
3376
|
+
strokeDashArray = pattern;
|
|
3377
|
+
}
|
|
3378
|
+
}
|
|
3344
3379
|
return {
|
|
3345
3380
|
pageIndex: page.index,
|
|
3346
3381
|
id: index,
|
|
3347
3382
|
type: PdfAnnotationSubtype.CIRCLE,
|
|
3383
|
+
flags,
|
|
3384
|
+
color,
|
|
3385
|
+
opacity,
|
|
3386
|
+
strokeWidth,
|
|
3387
|
+
strokeColor,
|
|
3388
|
+
strokeStyle,
|
|
3348
3389
|
rect,
|
|
3349
3390
|
author,
|
|
3350
3391
|
modified,
|
|
3392
|
+
...(cloudyBorderIntensity !== undefined && { cloudyBorderIntensity }),
|
|
3393
|
+
...(cloudyBorderInset !== undefined && { cloudyBorderInset }),
|
|
3394
|
+
...(strokeDashArray !== undefined && { strokeDashArray }),
|
|
3351
3395
|
};
|
|
3352
3396
|
}
|
|
3353
3397
|
/**
|
|
@@ -3361,18 +3405,51 @@ class PdfiumEngine {
|
|
|
3361
3405
|
* @private
|
|
3362
3406
|
*/
|
|
3363
3407
|
readPdfSquareAnno(page, pagePtr, annotationPtr, index) {
|
|
3408
|
+
const flags = this.getAnnotationFlags(annotationPtr);
|
|
3364
3409
|
const pageRect = this.readPageAnnoRect(annotationPtr);
|
|
3365
3410
|
const rect = this.convertPageRectToDeviceRect(page, pagePtr, pageRect);
|
|
3366
3411
|
const author = this.getAnnotString(annotationPtr, 'T');
|
|
3367
3412
|
const modifiedRaw = this.getAnnotString(annotationPtr, 'M');
|
|
3368
3413
|
const modified = pdfDateToDate(modifiedRaw);
|
|
3414
|
+
const { color, opacity } = this.resolveAnnotationColor(annotationPtr, PdfAnnotationColorType.InteriorColor);
|
|
3415
|
+
const { color: strokeColor } = this.resolveAnnotationColor(annotationPtr);
|
|
3416
|
+
let { style: strokeStyle, width: strokeWidth } = this.getBorderStyle(annotationPtr);
|
|
3417
|
+
let cloudyBorderIntensity;
|
|
3418
|
+
let cloudyBorderInset;
|
|
3419
|
+
if (strokeStyle === PdfAnnotationBorderStyle.CLOUDY ||
|
|
3420
|
+
strokeStyle === PdfAnnotationBorderStyle.UNKNOWN) {
|
|
3421
|
+
const { ok: hasEffect, intensity } = this.getBorderEffect(annotationPtr);
|
|
3422
|
+
if (hasEffect) {
|
|
3423
|
+
cloudyBorderIntensity = intensity;
|
|
3424
|
+
strokeStyle = PdfAnnotationBorderStyle.CLOUDY;
|
|
3425
|
+
const { ok: hasInset, left, top, right, bottom, } = this.getRectangleDifferences(annotationPtr);
|
|
3426
|
+
if (hasInset)
|
|
3427
|
+
cloudyBorderInset = [left, top, right, bottom];
|
|
3428
|
+
}
|
|
3429
|
+
}
|
|
3430
|
+
let strokeDashArray;
|
|
3431
|
+
if (strokeStyle === PdfAnnotationBorderStyle.DASHED) {
|
|
3432
|
+
const { ok, pattern } = this.getBorderDashPattern(annotationPtr);
|
|
3433
|
+
if (ok) {
|
|
3434
|
+
strokeDashArray = pattern;
|
|
3435
|
+
}
|
|
3436
|
+
}
|
|
3369
3437
|
return {
|
|
3370
3438
|
pageIndex: page.index,
|
|
3371
3439
|
id: index,
|
|
3372
3440
|
type: PdfAnnotationSubtype.SQUARE,
|
|
3441
|
+
flags,
|
|
3442
|
+
color,
|
|
3443
|
+
opacity,
|
|
3444
|
+
strokeColor,
|
|
3445
|
+
strokeWidth,
|
|
3446
|
+
strokeStyle,
|
|
3373
3447
|
rect,
|
|
3374
3448
|
author,
|
|
3375
3449
|
modified,
|
|
3450
|
+
...(cloudyBorderIntensity !== undefined && { cloudyBorderIntensity }),
|
|
3451
|
+
...(cloudyBorderInset !== undefined && { cloudyBorderInset }),
|
|
3452
|
+
...(strokeDashArray !== undefined && { strokeDashArray }),
|
|
3376
3453
|
};
|
|
3377
3454
|
}
|
|
3378
3455
|
/**
|
|
@@ -3558,6 +3635,81 @@ class PdfiumEngine {
|
|
|
3558
3635
|
options,
|
|
3559
3636
|
};
|
|
3560
3637
|
}
|
|
3638
|
+
/**
|
|
3639
|
+
* {@inheritDoc @embedpdf/models!PdfEngine.renderAnnotation}
|
|
3640
|
+
*
|
|
3641
|
+
* @public
|
|
3642
|
+
*/
|
|
3643
|
+
renderAnnotation(doc, page, annotation, scaleFactor, rotation, dpr = 1, // device-pixel-ratio (canvas)
|
|
3644
|
+
mode = AppearanceMode.Normal, imageType = 'image/webp') {
|
|
3645
|
+
this.logger.debug(LOG_SOURCE$1, LOG_CATEGORY$1, 'renderAnnotation', doc, page, annotation, scaleFactor, rotation, dpr, mode, imageType);
|
|
3646
|
+
this.logger.perf(LOG_SOURCE$1, LOG_CATEGORY$1, `RenderAnnotation`, 'Begin', `${doc.id}-${page.index}-${annotation.id}`);
|
|
3647
|
+
const task = new Task();
|
|
3648
|
+
const ctx = this.cache.getContext(doc.id);
|
|
3649
|
+
if (!ctx) {
|
|
3650
|
+
this.logger.perf(LOG_SOURCE$1, LOG_CATEGORY$1, `RenderAnnotation`, 'End', `${doc.id}-${page.index}-${annotation.id}`);
|
|
3651
|
+
return PdfTaskHelper.reject({
|
|
3652
|
+
code: PdfErrorCode.DocNotOpen,
|
|
3653
|
+
message: 'document does not open',
|
|
3654
|
+
});
|
|
3655
|
+
}
|
|
3656
|
+
/* ── 1. grab native handles ───────────────────────────────────────── */
|
|
3657
|
+
const pageCtx = ctx.acquirePage(page.index);
|
|
3658
|
+
const annotPtr = this.pdfiumModule.FPDFPage_GetAnnot(pageCtx.pagePtr, annotation.id);
|
|
3659
|
+
if (!annotPtr) {
|
|
3660
|
+
pageCtx.release();
|
|
3661
|
+
this.logger.perf(LOG_SOURCE$1, LOG_CATEGORY$1, `RenderAnnotation`, 'End', `${doc.id}-${page.index}-${annotation.id}`);
|
|
3662
|
+
return PdfTaskHelper.reject({
|
|
3663
|
+
code: PdfErrorCode.NotFound,
|
|
3664
|
+
message: 'annotation not found',
|
|
3665
|
+
});
|
|
3666
|
+
}
|
|
3667
|
+
const finalScale = scaleFactor * dpr;
|
|
3668
|
+
/* ── 2. decide bitmap size (integer pixels) ──────────────────────── */
|
|
3669
|
+
const annotRect = annotation.rect;
|
|
3670
|
+
const bitmapRect = toIntRect(transformRect(page.size, annotRect, rotation, finalScale));
|
|
3671
|
+
const format = BitmapFormat.Bitmap_BGRA;
|
|
3672
|
+
const bytesPerPixel = 4;
|
|
3673
|
+
const bitmapHeapLength = bitmapRect.size.width * bitmapRect.size.height * bytesPerPixel;
|
|
3674
|
+
const bitmapHeapPtr = this.malloc(bitmapHeapLength);
|
|
3675
|
+
const bitmapPtr = this.pdfiumModule.FPDFBitmap_CreateEx(bitmapRect.size.width, bitmapRect.size.height, format, bitmapHeapPtr, bitmapRect.size.width * bytesPerPixel);
|
|
3676
|
+
this.pdfiumModule.FPDFBitmap_FillRect(bitmapPtr, 0, 0, bitmapRect.size.width, bitmapRect.size.height, 0x00000000);
|
|
3677
|
+
const matrix = makeMatrix(annotation.rect, rotation, finalScale);
|
|
3678
|
+
// Allocate memory for the matrix on the wasm heap and write to it
|
|
3679
|
+
const matrixSize = 6 * 4;
|
|
3680
|
+
const matrixPtr = this.malloc(matrixSize);
|
|
3681
|
+
const matrixView = new Float32Array(this.pdfiumModule.pdfium.HEAPF32.buffer, matrixPtr, 6);
|
|
3682
|
+
matrixView.set([matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f]);
|
|
3683
|
+
/* ── 5. call the native helper with the new matrix ───────────────── */
|
|
3684
|
+
const FLAGS = RenderFlag.REVERSE_BYTE_ORDER;
|
|
3685
|
+
const ok = !!this.pdfiumModule.EPDF_RenderAnnotBitmap(bitmapPtr, pageCtx.pagePtr, annotPtr, mode, matrixPtr, FLAGS);
|
|
3686
|
+
/* ── 6. tear down native resources ───────────────────────────────── */
|
|
3687
|
+
this.free(matrixPtr); // Free the matrix memory
|
|
3688
|
+
this.pdfiumModule.FPDFBitmap_Destroy(bitmapPtr);
|
|
3689
|
+
this.pdfiumModule.FPDFPage_CloseAnnot(annotPtr);
|
|
3690
|
+
pageCtx.release();
|
|
3691
|
+
if (!ok) {
|
|
3692
|
+
this.free(bitmapHeapPtr);
|
|
3693
|
+
this.logger.perf(LOG_SOURCE$1, LOG_CATEGORY$1, `RenderAnnotation`, 'End', `${doc.id}-${page.index}-${annotation.id}`);
|
|
3694
|
+
return PdfTaskHelper.reject({
|
|
3695
|
+
code: PdfErrorCode.Unknown,
|
|
3696
|
+
message: 'EPDF_RenderAnnotBitmap failed',
|
|
3697
|
+
});
|
|
3698
|
+
}
|
|
3699
|
+
/* ── 6. copy out + convert to Blob (reuse existing converter) ─────── */
|
|
3700
|
+
const data = this.pdfiumModule.pdfium.HEAPU8.subarray(bitmapHeapPtr, bitmapHeapPtr + bitmapHeapLength);
|
|
3701
|
+
const imageData = {
|
|
3702
|
+
data: new Uint8ClampedArray(data),
|
|
3703
|
+
width: bitmapRect.size.width,
|
|
3704
|
+
height: bitmapRect.size.height,
|
|
3705
|
+
};
|
|
3706
|
+
this.free(bitmapHeapPtr);
|
|
3707
|
+
this.logger.perf(LOG_SOURCE$1, LOG_CATEGORY$1, `RenderAnnotation`, 'End', `${doc.id}-${page.index}-${annotation.id}`);
|
|
3708
|
+
this.imageDataConverter(imageData, imageType)
|
|
3709
|
+
.then((blob) => task.resolve(blob))
|
|
3710
|
+
.catch((err) => task.reject({ code: PdfErrorCode.Unknown, message: String(err) }));
|
|
3711
|
+
return task;
|
|
3712
|
+
}
|
|
3561
3713
|
/**
|
|
3562
3714
|
* render rectangle of pdf page to image
|
|
3563
3715
|
* @param docPtr - pointer to pdf document object
|
|
@@ -3928,12 +4080,7 @@ class PdfiumEngine {
|
|
|
3928
4080
|
task.resolve(false);
|
|
3929
4081
|
return task;
|
|
3930
4082
|
}
|
|
3931
|
-
|
|
3932
|
-
const shouldClearAP = annotation.type === PdfAnnotationSubtype.HIGHLIGHT ||
|
|
3933
|
-
annotation.type === PdfAnnotationSubtype.UNDERLINE ||
|
|
3934
|
-
annotation.type === PdfAnnotationSubtype.STRIKEOUT ||
|
|
3935
|
-
annotation.type === PdfAnnotationSubtype.SQUIGGLY;
|
|
3936
|
-
const ok = this.setAnnotationColor(annotPtr, color, shouldClearAP, which);
|
|
4083
|
+
const ok = this.setAnnotationColor(annotPtr, color, which);
|
|
3937
4084
|
/* 4 ── regenerate appearance & clean-up ───────────────────────────────── */
|
|
3938
4085
|
if (ok) {
|
|
3939
4086
|
this.pdfiumModule.FPDFPage_GenerateContent(pageCtx.pagePtr);
|
|
@@ -4343,6 +4490,9 @@ class EngineRunner {
|
|
|
4343
4490
|
case 'renderPageRect':
|
|
4344
4491
|
task = this.engine[name](...args);
|
|
4345
4492
|
break;
|
|
4493
|
+
case 'renderAnnotation':
|
|
4494
|
+
task = this.engine[name](...args);
|
|
4495
|
+
break;
|
|
4346
4496
|
case 'renderThumbnail':
|
|
4347
4497
|
task = this.engine[name](...args);
|
|
4348
4498
|
break;
|
|
@@ -4358,9 +4508,6 @@ class EngineRunner {
|
|
|
4358
4508
|
case 'updatePageAnnotation':
|
|
4359
4509
|
task = this.engine[name](...args);
|
|
4360
4510
|
break;
|
|
4361
|
-
case 'transformPageAnnotation':
|
|
4362
|
-
task = this.engine[name](...args);
|
|
4363
|
-
break;
|
|
4364
4511
|
case 'removePageAnnotation':
|
|
4365
4512
|
task = this.engine[name](...args);
|
|
4366
4513
|
break;
|