@embedpdf/engine-services 3.0.0-next.10 → 3.0.0-next.12
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 +737 -311
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +59 -4
- package/dist/index.d.ts +59 -4
- package/dist/index.js +738 -313
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1212,11 +1212,143 @@ function readI32(mem, ptr, byteOffset = 0) {
|
|
|
1212
1212
|
return Number(mem.peek(ptr, "i32", byteOffset));
|
|
1213
1213
|
}
|
|
1214
1214
|
//#endregion
|
|
1215
|
+
//#region src/features/destinations/destinationViewCodes.ts
|
|
1216
|
+
/**
|
|
1217
|
+
* `PDFDEST_VIEW_*` fit-type codes (public/fpdf_doc.h) — the shared
|
|
1218
|
+
* vocabulary of `FPDFDest_GetView` (read) and `EPDFDest_CreateView`
|
|
1219
|
+
* (write). XYZ is listed for completeness but never goes through
|
|
1220
|
+
* CreateView (it has its own null-aware constructor).
|
|
1221
|
+
*/
|
|
1222
|
+
const DEST_VIEW = {
|
|
1223
|
+
unknown: 0,
|
|
1224
|
+
xyz: 1,
|
|
1225
|
+
fit: 2,
|
|
1226
|
+
fitH: 3,
|
|
1227
|
+
fitV: 4,
|
|
1228
|
+
fitR: 5,
|
|
1229
|
+
fitB: 6,
|
|
1230
|
+
fitBH: 7,
|
|
1231
|
+
fitBV: 8
|
|
1232
|
+
};
|
|
1233
|
+
/** Wire destination kind → PDFDEST_VIEW code, for the non-XYZ kinds. */
|
|
1234
|
+
const VIEW_CODE_BY_KIND = {
|
|
1235
|
+
fit: DEST_VIEW.fit,
|
|
1236
|
+
fitH: DEST_VIEW.fitH,
|
|
1237
|
+
fitV: DEST_VIEW.fitV,
|
|
1238
|
+
fitR: DEST_VIEW.fitR,
|
|
1239
|
+
fitB: DEST_VIEW.fitB,
|
|
1240
|
+
fitBH: DEST_VIEW.fitBH,
|
|
1241
|
+
fitBV: DEST_VIEW.fitBV
|
|
1242
|
+
};
|
|
1243
|
+
//#endregion
|
|
1244
|
+
//#region src/features/destinations/readDestination.ts
|
|
1245
|
+
const MAX_VIEW_PARAMS = 4;
|
|
1246
|
+
/**
|
|
1247
|
+
* Materialise one explicit `PdfDestination` from a live `destPtr`. PDFium
|
|
1248
|
+
* already resolved named destinations before handing us the pointer, so
|
|
1249
|
+
* only explicit arrays arrive here (the rule `PdfDestination` documents).
|
|
1250
|
+
*
|
|
1251
|
+
* Returns `null` when the destination is unreadable: no visible indirect page
|
|
1252
|
+
* in the document, or an unknown fit type. Coordinates stay raw PDF user
|
|
1253
|
+
* space — no conversion at this layer.
|
|
1254
|
+
*
|
|
1255
|
+
* Shared by the link reader, `goto` action-node payloads, and the document
|
|
1256
|
+
* `openDestination`; the outline/bookmark port reuses it too.
|
|
1257
|
+
*/
|
|
1258
|
+
function readDestination(fn, mem, docPtr, destPtr) {
|
|
1259
|
+
const pageObjectNumber = fn.EPDFDest_GetPageObjectNumber(docPtr, destPtr);
|
|
1260
|
+
if (pageObjectNumber === 0) return null;
|
|
1261
|
+
const view = withScratchN(mem, [4, MAX_VIEW_PARAMS * 4], ([countPtr, paramsPtr]) => {
|
|
1262
|
+
const code = fn.FPDFDest_GetView(destPtr, countPtr, paramsPtr);
|
|
1263
|
+
const count = Math.min(readI32(mem, countPtr), MAX_VIEW_PARAMS);
|
|
1264
|
+
const params = [];
|
|
1265
|
+
for (let i = 0; i < count; i++) params.push(readF32(mem, paramsPtr, i * 4));
|
|
1266
|
+
return {
|
|
1267
|
+
code,
|
|
1268
|
+
params
|
|
1269
|
+
};
|
|
1270
|
+
});
|
|
1271
|
+
const at = (i) => i < view.params.length ? view.params[i] : null;
|
|
1272
|
+
switch (view.code) {
|
|
1273
|
+
case DEST_VIEW.xyz: return {
|
|
1274
|
+
kind: "xyz",
|
|
1275
|
+
pageObjectNumber,
|
|
1276
|
+
...readXyzLocation(fn, mem, destPtr)
|
|
1277
|
+
};
|
|
1278
|
+
case DEST_VIEW.fit: return {
|
|
1279
|
+
kind: "fit",
|
|
1280
|
+
pageObjectNumber
|
|
1281
|
+
};
|
|
1282
|
+
case DEST_VIEW.fitH: return {
|
|
1283
|
+
kind: "fitH",
|
|
1284
|
+
pageObjectNumber,
|
|
1285
|
+
top: at(0)
|
|
1286
|
+
};
|
|
1287
|
+
case DEST_VIEW.fitV: return {
|
|
1288
|
+
kind: "fitV",
|
|
1289
|
+
pageObjectNumber,
|
|
1290
|
+
left: at(0)
|
|
1291
|
+
};
|
|
1292
|
+
case DEST_VIEW.fitR:
|
|
1293
|
+
if (view.params.length < 4) return {
|
|
1294
|
+
kind: "fit",
|
|
1295
|
+
pageObjectNumber
|
|
1296
|
+
};
|
|
1297
|
+
return {
|
|
1298
|
+
kind: "fitR",
|
|
1299
|
+
pageObjectNumber,
|
|
1300
|
+
left: view.params[0],
|
|
1301
|
+
bottom: view.params[1],
|
|
1302
|
+
right: view.params[2],
|
|
1303
|
+
top: view.params[3]
|
|
1304
|
+
};
|
|
1305
|
+
case DEST_VIEW.fitB: return {
|
|
1306
|
+
kind: "fitB",
|
|
1307
|
+
pageObjectNumber
|
|
1308
|
+
};
|
|
1309
|
+
case DEST_VIEW.fitBH: return {
|
|
1310
|
+
kind: "fitBH",
|
|
1311
|
+
pageObjectNumber,
|
|
1312
|
+
top: at(0)
|
|
1313
|
+
};
|
|
1314
|
+
case DEST_VIEW.fitBV: return {
|
|
1315
|
+
kind: "fitBV",
|
|
1316
|
+
pageObjectNumber,
|
|
1317
|
+
left: at(0)
|
|
1318
|
+
};
|
|
1319
|
+
default: return null;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
/** `/XYZ` null-aware axes via `FPDFDest_GetLocationInPage` (FPDF_BOOL is 4 bytes). */
|
|
1323
|
+
function readXyzLocation(fn, mem, destPtr) {
|
|
1324
|
+
return withScratchN(mem, [
|
|
1325
|
+
4,
|
|
1326
|
+
4,
|
|
1327
|
+
4,
|
|
1328
|
+
4,
|
|
1329
|
+
4,
|
|
1330
|
+
4
|
|
1331
|
+
], ([hasLeft, hasTop, hasZoom, left, top, zoom]) => {
|
|
1332
|
+
if (!fn.FPDFDest_GetLocationInPage(destPtr, hasLeft, hasTop, hasZoom, left, top, zoom)) return {
|
|
1333
|
+
left: null,
|
|
1334
|
+
top: null,
|
|
1335
|
+
zoom: null
|
|
1336
|
+
};
|
|
1337
|
+
return {
|
|
1338
|
+
left: readI32(mem, hasLeft) ? readF32(mem, left) : null,
|
|
1339
|
+
top: readI32(mem, hasTop) ? readF32(mem, top) : null,
|
|
1340
|
+
zoom: readI32(mem, hasZoom) ? readF32(mem, zoom) : null
|
|
1341
|
+
};
|
|
1342
|
+
});
|
|
1343
|
+
}
|
|
1344
|
+
//#endregion
|
|
1215
1345
|
//#region src/features/actions/ActionModelReader.ts
|
|
1216
1346
|
const DEFAULT_ACTION_READ_BUDGET = {
|
|
1217
1347
|
maxModels: 512,
|
|
1218
1348
|
maxNodes: 16384,
|
|
1219
|
-
maxScriptCodeUnits: 16e6
|
|
1349
|
+
maxScriptCodeUnits: 16e6,
|
|
1350
|
+
maxTargetEntries: 4096,
|
|
1351
|
+
maxPayloadCodeUnits: 262144
|
|
1220
1352
|
};
|
|
1221
1353
|
const ACTION_TYPE_BY_CODE = {
|
|
1222
1354
|
0: "unknown",
|
|
@@ -1244,22 +1376,20 @@ const WARNING_MALFORMED_NEXT = 2;
|
|
|
1244
1376
|
const WARNING_INCOMPLETE = 4;
|
|
1245
1377
|
const INVALID_NODE_U32 = 4294967295;
|
|
1246
1378
|
/** Decode one `EPDF_ACTION_TYPE_*` code — the shared vocabulary consumers
|
|
1247
|
-
*
|
|
1379
|
+
* use so action-shaped surfaces cannot drift. */
|
|
1248
1380
|
function actionTypeFromCode(code) {
|
|
1249
1381
|
return ACTION_TYPE_BY_CODE[code] ?? "unknown";
|
|
1250
1382
|
}
|
|
1251
|
-
/**
|
|
1252
|
-
*
|
|
1253
|
-
function isValidActionNodeId(raw) {
|
|
1254
|
-
return raw !== -1 && raw >>> 0 !== INVALID_NODE_U32;
|
|
1255
|
-
}
|
|
1256
|
-
/** Mutable aggregate budget shared by every action model in one read job. */
|
|
1383
|
+
/** Mutable aggregate budget shared by every action model in one read job.
|
|
1384
|
+
* Payload budgets are RESERVED before the backing buffer is allocated. */
|
|
1257
1385
|
var ActionReadBudgetTracker = class {
|
|
1258
1386
|
constructor(limits = DEFAULT_ACTION_READ_BUDGET) {
|
|
1259
1387
|
this.limits = limits;
|
|
1260
1388
|
_defineProperty(this, "models", 0);
|
|
1261
1389
|
_defineProperty(this, "nodes", 0);
|
|
1262
1390
|
_defineProperty(this, "scriptCodeUnits", 0);
|
|
1391
|
+
_defineProperty(this, "targetEntries", 0);
|
|
1392
|
+
_defineProperty(this, "payloadCodeUnits", 0);
|
|
1263
1393
|
}
|
|
1264
1394
|
addModel(nodeCount) {
|
|
1265
1395
|
this.models += 1;
|
|
@@ -1270,11 +1400,23 @@ var ActionReadBudgetTracker = class {
|
|
|
1270
1400
|
this.scriptCodeUnits += script.length;
|
|
1271
1401
|
this.assertWithinBudget();
|
|
1272
1402
|
}
|
|
1403
|
+
/** Charge target entries BEFORE the target array is walked. */
|
|
1404
|
+
reserveTargets(count) {
|
|
1405
|
+
this.targetEntries += count;
|
|
1406
|
+
this.assertWithinBudget();
|
|
1407
|
+
}
|
|
1408
|
+
/** Charge payload text BEFORE the scratch buffer for it is allocated. */
|
|
1409
|
+
reservePayloadBytes(length) {
|
|
1410
|
+
this.payloadCodeUnits += length;
|
|
1411
|
+
this.assertWithinBudget();
|
|
1412
|
+
}
|
|
1273
1413
|
assertWithinBudget() {
|
|
1274
|
-
if (this.models > this.limits.maxModels || this.nodes > this.limits.maxNodes || this.scriptCodeUnits > this.limits.maxScriptCodeUnits) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.MalformedPdf, "aggregate PDF action read budget exceeded", { details: {
|
|
1414
|
+
if (this.models > this.limits.maxModels || this.nodes > this.limits.maxNodes || this.scriptCodeUnits > this.limits.maxScriptCodeUnits || this.targetEntries > this.limits.maxTargetEntries || this.payloadCodeUnits > this.limits.maxPayloadCodeUnits) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.MalformedPdf, "aggregate PDF action read budget exceeded", { details: {
|
|
1275
1415
|
models: this.models,
|
|
1276
1416
|
nodes: this.nodes,
|
|
1277
1417
|
scriptCodeUnits: this.scriptCodeUnits,
|
|
1418
|
+
targetEntries: this.targetEntries,
|
|
1419
|
+
payloadCodeUnits: this.payloadCodeUnits,
|
|
1278
1420
|
limits: this.limits
|
|
1279
1421
|
} });
|
|
1280
1422
|
}
|
|
@@ -1282,8 +1424,17 @@ var ActionReadBudgetTracker = class {
|
|
|
1282
1424
|
/**
|
|
1283
1425
|
* Convert and close one detached native action model. This is the only
|
|
1284
1426
|
* native-model walker used by document, page, field, and annotation reads.
|
|
1427
|
+
*
|
|
1428
|
+
* `docPtr` resolves `goto` destinations (page identity + named-destination
|
|
1429
|
+
* lookup); every caller reads within an open document session.
|
|
1430
|
+
*
|
|
1431
|
+
* Payload rule: a node whose payload cannot be materialised (a goto without
|
|
1432
|
+
* a resolvable destination, a javascript node with no `/JS`, a withheld
|
|
1433
|
+
* target list) degrades to `{ type: 'unknown' }` with its original `/S` on
|
|
1434
|
+
* `subtype`, and the tree gains the `'payload-dropped'` warning — impossible
|
|
1435
|
+
* states stay unrepresentable while malformed documents stay readable.
|
|
1285
1436
|
*/
|
|
1286
|
-
function readActionModel(fn, mem, modelPtr, budget) {
|
|
1437
|
+
function readActionModel(fn, mem, docPtr, modelPtr, budget) {
|
|
1287
1438
|
if (modelPtr === _embedpdf_engine_runtime.NULL_PTR) return null;
|
|
1288
1439
|
try {
|
|
1289
1440
|
const nodeCount = fn.EPDFAction_GetNodeCount(modelPtr);
|
|
@@ -1293,13 +1444,61 @@ function readActionModel(fn, mem, modelPtr, budget) {
|
|
|
1293
1444
|
const incomplete = !fn.EPDFAction_IsComplete(modelPtr);
|
|
1294
1445
|
const rootId = normalizeOptionalNodeId(fn.EPDFAction_GetRootNode(modelPtr), nodeCount);
|
|
1295
1446
|
const visiting = /* @__PURE__ */ new Set();
|
|
1447
|
+
let payloadDropped = false;
|
|
1448
|
+
/** Probe the two-call length first and charge the budget BEFORE the
|
|
1449
|
+
* scratch buffer for the value is allocated. */
|
|
1450
|
+
const readPayloadString = (call) => {
|
|
1451
|
+
const length = call(_embedpdf_engine_runtime.NULL_PTR, 0);
|
|
1452
|
+
if (length <= 0) return null;
|
|
1453
|
+
budget.reservePayloadBytes(length);
|
|
1454
|
+
return readUtf8String(mem, call);
|
|
1455
|
+
};
|
|
1456
|
+
const readOutBool = (read) => withScratchN(mem, [4], ([outPtr]) => read(outPtr) ? readI32(mem, outPtr) !== 0 : null);
|
|
1457
|
+
const readTargetObjectNumber = (nodeId, index) => withScratchN(mem, [4], ([outPtr]) => {
|
|
1458
|
+
if (!fn.EPDFAction_GetNodeTargetObjectNumber(modelPtr, nodeId, index, outPtr)) return null;
|
|
1459
|
+
const value = readI32(mem, outPtr) >>> 0;
|
|
1460
|
+
return value === 0 ? null : value;
|
|
1461
|
+
});
|
|
1462
|
+
const readTargets = (nodeId, count) => {
|
|
1463
|
+
const targets = [];
|
|
1464
|
+
for (let index = 0; index < count; index++) {
|
|
1465
|
+
const name = readPayloadString((buf, capacity) => fn.EPDFAction_GetNodeTargetName(modelPtr, nodeId, index, buf, capacity));
|
|
1466
|
+
if (name !== null) {
|
|
1467
|
+
targets.push({
|
|
1468
|
+
kind: "name",
|
|
1469
|
+
name
|
|
1470
|
+
});
|
|
1471
|
+
continue;
|
|
1472
|
+
}
|
|
1473
|
+
const objectNumber = readTargetObjectNumber(nodeId, index);
|
|
1474
|
+
if (objectNumber === null) return null;
|
|
1475
|
+
targets.push({
|
|
1476
|
+
kind: "objectNumber",
|
|
1477
|
+
objectNumber
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
return targets;
|
|
1481
|
+
};
|
|
1482
|
+
const readResetFormState = (nodeId) => withScratchN(mem, [4, 4], ([hasFieldsPtr, excludePtr]) => {
|
|
1483
|
+
if (!fn.EPDFAction_GetNodeResetForm(modelPtr, nodeId, hasFieldsPtr, excludePtr)) return null;
|
|
1484
|
+
return {
|
|
1485
|
+
hasFields: readI32(mem, hasFieldsPtr) !== 0,
|
|
1486
|
+
exclude: readI32(mem, excludePtr) !== 0
|
|
1487
|
+
};
|
|
1488
|
+
});
|
|
1489
|
+
const readSubmitFormState = (nodeId) => withScratchN(mem, [4, 4], ([hasFieldsPtr, flagsPtr]) => {
|
|
1490
|
+
if (!fn.EPDFAction_GetNodeSubmitForm(modelPtr, nodeId, hasFieldsPtr, flagsPtr)) return null;
|
|
1491
|
+
return {
|
|
1492
|
+
hasFields: readI32(mem, hasFieldsPtr) !== 0,
|
|
1493
|
+
flags: readI32(mem, flagsPtr) >>> 0
|
|
1494
|
+
};
|
|
1495
|
+
});
|
|
1296
1496
|
const readNode = (nodeId) => {
|
|
1297
1497
|
if (visiting.has(nodeId)) throw malformedActionModel("native action model contains a cycle", { nodeId });
|
|
1298
1498
|
visiting.add(nodeId);
|
|
1299
1499
|
try {
|
|
1500
|
+
const type = actionTypeFromCode(fn.EPDFAction_GetNodeType(modelPtr, nodeId));
|
|
1300
1501
|
const subtype = readUtf8String(mem, (buf, capacity) => fn.EPDFAction_GetNodeSubtype(modelPtr, nodeId, buf, capacity)) ?? "";
|
|
1301
|
-
const script = fn.EPDFAction_NodeHasJavaScript(modelPtr, nodeId) ? readUtf16String(mem, (buf, capacity) => fn.EPDFAction_GetNodeJavaScript(modelPtr, nodeId, buf, capacity)) ?? "" : void 0;
|
|
1302
|
-
if (script !== void 0) budget.addScript(script);
|
|
1303
1502
|
const nextCount = fn.EPDFAction_GetNextCount(modelPtr, nodeId);
|
|
1304
1503
|
if (!Number.isInteger(nextCount) || nextCount < 0) throw malformedActionModel("invalid action child count", {
|
|
1305
1504
|
nodeId,
|
|
@@ -1310,21 +1509,157 @@ function readActionModel(fn, mem, modelPtr, budget) {
|
|
|
1310
1509
|
const childId = normalizeNodeId(fn.EPDFAction_GetNextAt(modelPtr, nodeId, index), nodeCount);
|
|
1311
1510
|
next.push(readNode(childId));
|
|
1312
1511
|
}
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1512
|
+
const degraded = () => {
|
|
1513
|
+
payloadDropped = true;
|
|
1514
|
+
return {
|
|
1515
|
+
type: "unknown",
|
|
1516
|
+
subtype,
|
|
1517
|
+
next
|
|
1518
|
+
};
|
|
1318
1519
|
};
|
|
1520
|
+
switch (type) {
|
|
1521
|
+
case "javascript": {
|
|
1522
|
+
if (!fn.EPDFAction_NodeHasJavaScript(modelPtr, nodeId)) return degraded();
|
|
1523
|
+
const script = readUtf16String(mem, (buf, capacity) => fn.EPDFAction_GetNodeJavaScript(modelPtr, nodeId, buf, capacity)) ?? "";
|
|
1524
|
+
budget.addScript(script);
|
|
1525
|
+
return {
|
|
1526
|
+
type,
|
|
1527
|
+
subtype,
|
|
1528
|
+
script,
|
|
1529
|
+
next
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
case "rendition": {
|
|
1533
|
+
if (!fn.EPDFAction_NodeHasJavaScript(modelPtr, nodeId)) return {
|
|
1534
|
+
type,
|
|
1535
|
+
subtype,
|
|
1536
|
+
next
|
|
1537
|
+
};
|
|
1538
|
+
const script = readUtf16String(mem, (buf, capacity) => fn.EPDFAction_GetNodeJavaScript(modelPtr, nodeId, buf, capacity)) ?? "";
|
|
1539
|
+
budget.addScript(script);
|
|
1540
|
+
return {
|
|
1541
|
+
type,
|
|
1542
|
+
subtype,
|
|
1543
|
+
script,
|
|
1544
|
+
next
|
|
1545
|
+
};
|
|
1546
|
+
}
|
|
1547
|
+
case "goto": {
|
|
1548
|
+
const destPtr = fn.EPDFAction_GetNodeDest(docPtr, modelPtr, nodeId);
|
|
1549
|
+
const destination = destPtr !== _embedpdf_engine_runtime.NULL_PTR ? readDestination(fn, mem, docPtr, destPtr) : null;
|
|
1550
|
+
return destination ? {
|
|
1551
|
+
type,
|
|
1552
|
+
subtype,
|
|
1553
|
+
destination,
|
|
1554
|
+
next
|
|
1555
|
+
} : degraded();
|
|
1556
|
+
}
|
|
1557
|
+
case "uri": {
|
|
1558
|
+
const uri = readPayloadString((buf, capacity) => fn.EPDFAction_GetNodeURI(docPtr, modelPtr, nodeId, buf, capacity));
|
|
1559
|
+
if (uri === null) return degraded();
|
|
1560
|
+
return {
|
|
1561
|
+
type,
|
|
1562
|
+
subtype,
|
|
1563
|
+
uri,
|
|
1564
|
+
isMap: readOutBool((outPtr) => fn.EPDFAction_GetNodeURIIsMap(modelPtr, nodeId, outPtr)) ?? false,
|
|
1565
|
+
next
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
case "named": {
|
|
1569
|
+
const name = readPayloadString((buf, capacity) => fn.EPDFAction_GetNodeName(modelPtr, nodeId, buf, capacity));
|
|
1570
|
+
return name === null ? degraded() : {
|
|
1571
|
+
type,
|
|
1572
|
+
subtype,
|
|
1573
|
+
name,
|
|
1574
|
+
next
|
|
1575
|
+
};
|
|
1576
|
+
}
|
|
1577
|
+
case "hide": {
|
|
1578
|
+
const count = fn.EPDFAction_GetNodeTargetCount(modelPtr, nodeId);
|
|
1579
|
+
if (!Number.isInteger(count) || count < 0) return degraded();
|
|
1580
|
+
budget.reserveTargets(count);
|
|
1581
|
+
const targets = readTargets(nodeId, count);
|
|
1582
|
+
if (targets === null) return degraded();
|
|
1583
|
+
return {
|
|
1584
|
+
type,
|
|
1585
|
+
subtype,
|
|
1586
|
+
targets,
|
|
1587
|
+
hide: readOutBool((outPtr) => fn.EPDFAction_GetNodeHideFlag(modelPtr, nodeId, outPtr)) ?? true,
|
|
1588
|
+
next
|
|
1589
|
+
};
|
|
1590
|
+
}
|
|
1591
|
+
case "reset-form": {
|
|
1592
|
+
const state = readResetFormState(nodeId);
|
|
1593
|
+
const count = fn.EPDFAction_GetNodeTargetCount(modelPtr, nodeId);
|
|
1594
|
+
if (state === null || !Number.isInteger(count) || count < 0) return degraded();
|
|
1595
|
+
budget.reserveTargets(count);
|
|
1596
|
+
const fields = state.hasFields ? readTargets(nodeId, count) : null;
|
|
1597
|
+
if (state.hasFields && fields === null) return degraded();
|
|
1598
|
+
return {
|
|
1599
|
+
type,
|
|
1600
|
+
subtype,
|
|
1601
|
+
fields,
|
|
1602
|
+
exclude: state.exclude,
|
|
1603
|
+
next
|
|
1604
|
+
};
|
|
1605
|
+
}
|
|
1606
|
+
case "submit-form": {
|
|
1607
|
+
if (typeof fn.EPDFAction_GetNodeSubmitForm !== "function") return {
|
|
1608
|
+
type,
|
|
1609
|
+
subtype,
|
|
1610
|
+
next
|
|
1611
|
+
};
|
|
1612
|
+
const state = readSubmitFormState(nodeId);
|
|
1613
|
+
if (state === null) return degraded();
|
|
1614
|
+
const url = readPayloadString((buf, capacity) => fn.EPDFAction_GetNodeSubmitFormURL(modelPtr, nodeId, buf, capacity));
|
|
1615
|
+
if (url === null) return degraded();
|
|
1616
|
+
const count = fn.EPDFAction_GetNodeTargetCount(modelPtr, nodeId);
|
|
1617
|
+
if (!Number.isInteger(count) || count < 0) return degraded();
|
|
1618
|
+
budget.reserveTargets(count);
|
|
1619
|
+
const fields = state.hasFields ? readTargets(nodeId, count) : null;
|
|
1620
|
+
if (state.hasFields && fields === null) return degraded();
|
|
1621
|
+
const charSet = readPayloadString((buf, capacity) => fn.EPDFAction_GetNodeSubmitFormCharSet(modelPtr, nodeId, buf, capacity));
|
|
1622
|
+
return {
|
|
1623
|
+
type,
|
|
1624
|
+
subtype,
|
|
1625
|
+
payload: {
|
|
1626
|
+
url,
|
|
1627
|
+
fields,
|
|
1628
|
+
flags: (0, _embedpdf_engine_core_runtime.decodeSubmitFormFlags)(state.flags),
|
|
1629
|
+
...charSet === null ? {} : { charSet }
|
|
1630
|
+
},
|
|
1631
|
+
next
|
|
1632
|
+
};
|
|
1633
|
+
}
|
|
1634
|
+
case "goto-remote":
|
|
1635
|
+
case "goto-embedded":
|
|
1636
|
+
case "launch": {
|
|
1637
|
+
const filePath = readPayloadString((buf, capacity) => fn.EPDFAction_GetNodeFilePath(modelPtr, nodeId, buf, capacity));
|
|
1638
|
+
return filePath === null ? degraded() : {
|
|
1639
|
+
type,
|
|
1640
|
+
subtype,
|
|
1641
|
+
filePath,
|
|
1642
|
+
next
|
|
1643
|
+
};
|
|
1644
|
+
}
|
|
1645
|
+
default: return {
|
|
1646
|
+
type,
|
|
1647
|
+
subtype,
|
|
1648
|
+
next
|
|
1649
|
+
};
|
|
1650
|
+
}
|
|
1319
1651
|
} finally {
|
|
1320
1652
|
visiting.delete(nodeId);
|
|
1321
1653
|
}
|
|
1322
1654
|
};
|
|
1655
|
+
const root = rootId === null ? null : readNode(rootId);
|
|
1656
|
+
const warnings = warningsFromFlags(warningFlags, incomplete);
|
|
1657
|
+
if (payloadDropped) warnings.push("payload-dropped");
|
|
1323
1658
|
return {
|
|
1324
|
-
root
|
|
1659
|
+
root,
|
|
1325
1660
|
incomplete,
|
|
1326
1661
|
warningFlags,
|
|
1327
|
-
warnings
|
|
1662
|
+
warnings
|
|
1328
1663
|
};
|
|
1329
1664
|
} finally {
|
|
1330
1665
|
fn.EPDFAction_CloseModel(modelPtr);
|
|
@@ -1397,15 +1732,16 @@ var PagesReader = class {
|
|
|
1397
1732
|
});
|
|
1398
1733
|
return {
|
|
1399
1734
|
pageCount: pages.length,
|
|
1400
|
-
pages
|
|
1735
|
+
pages,
|
|
1736
|
+
namedPages: readNamedPages(fn, mem, docPtr)
|
|
1401
1737
|
};
|
|
1402
1738
|
});
|
|
1403
1739
|
}
|
|
1404
1740
|
};
|
|
1405
1741
|
function readPageActions(fn, mem, docPtr, pageObjectNumber, budget) {
|
|
1406
1742
|
const actions = {};
|
|
1407
|
-
const open = readActionModel(fn, mem, fn.EPDFDoc_GetPageActionModel(docPtr, pageObjectNumber, 0), budget);
|
|
1408
|
-
const close = readActionModel(fn, mem, fn.EPDFDoc_GetPageActionModel(docPtr, pageObjectNumber, 1), budget);
|
|
1743
|
+
const open = readActionModel(fn, mem, docPtr, fn.EPDFDoc_GetPageActionModel(docPtr, pageObjectNumber, 0), budget);
|
|
1744
|
+
const close = readActionModel(fn, mem, docPtr, fn.EPDFDoc_GetPageActionModel(docPtr, pageObjectNumber, 1), budget);
|
|
1409
1745
|
if (open) actions.open = open;
|
|
1410
1746
|
if (close) actions.close = close;
|
|
1411
1747
|
return open || close ? actions : void 0;
|
|
@@ -1462,6 +1798,41 @@ function readUserUnit(fn, mem, docPtr, index, userUnitPtr) {
|
|
|
1462
1798
|
function readLabel(fn, mem, docPtr, index) {
|
|
1463
1799
|
return readUtf16String(mem, (buf, capacity) => fn.FPDF_GetPageLabel(docPtr, index, buf, capacity), null) || null;
|
|
1464
1800
|
}
|
|
1801
|
+
const NAMED_PAGE_TREES = [0, 1];
|
|
1802
|
+
const NAMED_PAGE_KIND_PAGE = 0;
|
|
1803
|
+
const NAMED_PAGE_KIND_TEMPLATE = 1;
|
|
1804
|
+
/**
|
|
1805
|
+
* The catalog's `/Names /Pages` and `/Names /Templates` registrations, in
|
|
1806
|
+
* tree order, each value classified by the fork (page / template /
|
|
1807
|
+
* dangling). Page-identity data like `label`, so it ships inside the same
|
|
1808
|
+
* snapshot — a registration is only meaningful against the page set that
|
|
1809
|
+
* contains its target.
|
|
1810
|
+
*/
|
|
1811
|
+
function readNamedPages(fn, mem, docPtr) {
|
|
1812
|
+
const entries = [];
|
|
1813
|
+
withScratchN(mem, [4, 4], ([objNumPtr, kindPtr]) => {
|
|
1814
|
+
for (const tree of NAMED_PAGE_TREES) {
|
|
1815
|
+
const count = fn.EPDFDoc_GetNamedPageCount(docPtr, tree);
|
|
1816
|
+
for (let index = 0; index < count; index++) {
|
|
1817
|
+
const name = readUtf16String(mem, (buf, capacity) => fn.EPDFDoc_GetNamedPageAt(docPtr, tree, index, buf, capacity, objNumPtr, kindPtr), "");
|
|
1818
|
+
if (name === null) continue;
|
|
1819
|
+
const objectNumber = Number(mem.peek(objNumPtr, "i32")) >>> 0;
|
|
1820
|
+
const kind = Number(mem.peek(kindPtr, "i32"));
|
|
1821
|
+
entries.push({
|
|
1822
|
+
name,
|
|
1823
|
+
target: kind === NAMED_PAGE_KIND_PAGE ? {
|
|
1824
|
+
kind: "page",
|
|
1825
|
+
pageObjectNumber: objectNumber
|
|
1826
|
+
} : kind === NAMED_PAGE_KIND_TEMPLATE ? {
|
|
1827
|
+
kind: "template",
|
|
1828
|
+
objectNumber
|
|
1829
|
+
} : { kind: "dangling" }
|
|
1830
|
+
});
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
});
|
|
1834
|
+
return entries;
|
|
1835
|
+
}
|
|
1465
1836
|
//#endregion
|
|
1466
1837
|
//#region src/features/pages/PagesMutator.ts
|
|
1467
1838
|
/**
|
|
@@ -1609,6 +1980,38 @@ var PagesMutator = class {
|
|
|
1609
1980
|
cache: null
|
|
1610
1981
|
};
|
|
1611
1982
|
}
|
|
1983
|
+
/**
|
|
1984
|
+
* Register `name` → page in `/Names /Pages` (create, or replace what the
|
|
1985
|
+
* key points at); with `replace`, drop that other key first — a rename as
|
|
1986
|
+
* one job. Named pages are LAYOUT: page identity and order are untouched
|
|
1987
|
+
* (no registry refresh, no revision bumps) and the fresh snapshot is
|
|
1988
|
+
* returned like `move()`.
|
|
1989
|
+
*/
|
|
1990
|
+
setName(input, signal) {
|
|
1991
|
+
throwIfAborted(signal);
|
|
1992
|
+
if (input.name.length === 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, "pages.setName requires a non-empty name");
|
|
1993
|
+
const { fn, mem } = this.runtime;
|
|
1994
|
+
const docPtr = this.session.requireDocPtr();
|
|
1995
|
+
this.session.recordByObjectNumber(input.pageObjectNumber);
|
|
1996
|
+
if (input.replace !== void 0 && input.replace !== input.name && input.replace.length > 0) writeUtf16String(mem, input.replace, (ptr) => fn.EPDFDoc_RemoveNamedPage(docPtr, ptr));
|
|
1997
|
+
if (!writeUtf16String(mem, input.name, (ptr) => fn.EPDFDoc_SetNamedPage(docPtr, ptr, input.pageObjectNumber))) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.Unknown, `EPDFDoc_SetNamedPage rejected '${input.name}' for page ${input.pageObjectNumber}`);
|
|
1998
|
+
return {
|
|
1999
|
+
layout: new PagesReader(this.runtime, this.session).read(signal),
|
|
2000
|
+
cache: null
|
|
2001
|
+
};
|
|
2002
|
+
}
|
|
2003
|
+
/** Remove one `/Names /Pages` registration; the page stays. */
|
|
2004
|
+
removeName(input, signal) {
|
|
2005
|
+
throwIfAborted(signal);
|
|
2006
|
+
if (input.name.length === 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, "pages.removeName requires a non-empty name");
|
|
2007
|
+
const { fn, mem } = this.runtime;
|
|
2008
|
+
const docPtr = this.session.requireDocPtr();
|
|
2009
|
+
if (!writeUtf16String(mem, input.name, (ptr) => fn.EPDFDoc_RemoveNamedPage(docPtr, ptr))) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.NotFound, `pages.removeName: no /Names /Pages registration '${input.name}'`);
|
|
2010
|
+
return {
|
|
2011
|
+
layout: new PagesReader(this.runtime, this.session).read(signal),
|
|
2012
|
+
cache: null
|
|
2013
|
+
};
|
|
2014
|
+
}
|
|
1612
2015
|
/** Shared input check: non-empty, no duplicate PONs. */
|
|
1613
2016
|
requireUniquePons(op, pageObjectNumbers) {
|
|
1614
2017
|
if (pageObjectNumbers.length === 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, `${op} requires at least one page`);
|
|
@@ -1621,7 +2024,7 @@ var PagesMutator = class {
|
|
|
1621
2024
|
};
|
|
1622
2025
|
//#endregion
|
|
1623
2026
|
//#region src/features/pages/PagesExtractor.ts
|
|
1624
|
-
const FPDF_NO_INCREMENTAL$
|
|
2027
|
+
const FPDF_NO_INCREMENTAL$2 = 2;
|
|
1625
2028
|
/**
|
|
1626
2029
|
* Export a subset of pages as a standalone PDF. A READ over the session:
|
|
1627
2030
|
* `FPDF_ImportPagesByIndex` copies pages into a scratch document, so the
|
|
@@ -1660,7 +2063,7 @@ var PagesExtractor = class {
|
|
|
1660
2063
|
for (let i = 0; i < indices.length; i++) mem.poke(idxPtr, "i32", indices[i], 4 * i);
|
|
1661
2064
|
if (!fn.FPDF_ImportPagesByIndex(destPtr, srcPtr, idxPtr, indices.length, 0)) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.Unknown, `FPDF_ImportPagesByIndex rejected the request (indices=[${indices.join(",")}])`);
|
|
1662
2065
|
mem.poke(sizePtr, "i32", 0);
|
|
1663
|
-
pdfPtr = fn.EPDF_SaveDocumentToOwnedBuffer(destPtr, FPDF_NO_INCREMENTAL$
|
|
2066
|
+
pdfPtr = fn.EPDF_SaveDocumentToOwnedBuffer(destPtr, FPDF_NO_INCREMENTAL$2, sizePtr);
|
|
1664
2067
|
const size = Number(mem.peek(sizePtr, "i32"));
|
|
1665
2068
|
if (!pdfPtr || size <= 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.DocOpenFailed, "failed to save extracted pages");
|
|
1666
2069
|
const bytes = mem.readBytes(pdfPtr, size);
|
|
@@ -2212,6 +2615,13 @@ function readQuadPoints(fn, mem, annotPtr) {
|
|
|
2212
2615
|
return out;
|
|
2213
2616
|
});
|
|
2214
2617
|
}
|
|
2618
|
+
/**
|
|
2619
|
+
* `/Name` as text, whatever its value (`EPDFAnnot_GetName`): a standard
|
|
2620
|
+
* icon/stamp name or a custom identifier. `null` when absent.
|
|
2621
|
+
*/
|
|
2622
|
+
function readAnnotName(fn, mem, annotPtr) {
|
|
2623
|
+
return readUtf8String(mem, (buf, capacity) => fn.EPDFAnnot_GetName(annotPtr, buf, capacity));
|
|
2624
|
+
}
|
|
2215
2625
|
//#endregion
|
|
2216
2626
|
//#region src/features/annotations/internal/read/readAnnotationTransformMetadata.ts
|
|
2217
2627
|
/**
|
|
@@ -2461,29 +2871,29 @@ function normalizeChecksum(raw) {
|
|
|
2461
2871
|
//#endregion
|
|
2462
2872
|
//#region src/features/annotations/internal/annotationIcon.ts
|
|
2463
2873
|
/**
|
|
2464
|
-
* `/Name` icon ↔
|
|
2465
|
-
*
|
|
2466
|
-
*
|
|
2467
|
-
*
|
|
2468
|
-
*
|
|
2469
|
-
*/
|
|
2470
|
-
const
|
|
2471
|
-
comment:
|
|
2472
|
-
key:
|
|
2473
|
-
note:
|
|
2474
|
-
help:
|
|
2475
|
-
"new-paragraph":
|
|
2476
|
-
paragraph:
|
|
2477
|
-
insert:
|
|
2874
|
+
* `/Name` icon vocabulary ↔ PDF name mapping for text and file-attachment
|
|
2875
|
+
* annotations (ISO 32000-2 tables 175 and 184). The wire speaks the
|
|
2876
|
+
* kebab-case ids; `EPDFAnnot_SetName` / `EPDFAnnot_GetName` speak the PDF
|
|
2877
|
+
* names. An unknown PDF name reads as the subtype's default (the reader
|
|
2878
|
+
* draws the default glyph for names it does not know — spec behavior).
|
|
2879
|
+
*/
|
|
2880
|
+
const NOTE_ICON_TO_NAME = Object.freeze({
|
|
2881
|
+
comment: "Comment",
|
|
2882
|
+
key: "Key",
|
|
2883
|
+
note: "Note",
|
|
2884
|
+
help: "Help",
|
|
2885
|
+
"new-paragraph": "NewParagraph",
|
|
2886
|
+
paragraph: "Paragraph",
|
|
2887
|
+
insert: "Insert"
|
|
2478
2888
|
});
|
|
2479
|
-
const
|
|
2480
|
-
const
|
|
2481
|
-
graph:
|
|
2482
|
-
"push-pin":
|
|
2483
|
-
paperclip:
|
|
2484
|
-
tag:
|
|
2889
|
+
const NOTE_NAME_TO_ICON = Object.freeze(Object.fromEntries(Object.entries(NOTE_ICON_TO_NAME).map(([icon, name]) => [name, icon])));
|
|
2890
|
+
const FILE_ICON_TO_NAME = Object.freeze({
|
|
2891
|
+
graph: "Graph",
|
|
2892
|
+
"push-pin": "PushPin",
|
|
2893
|
+
paperclip: "Paperclip",
|
|
2894
|
+
tag: "Tag"
|
|
2485
2895
|
});
|
|
2486
|
-
const
|
|
2896
|
+
const FILE_NAME_TO_ICON = Object.freeze(Object.fromEntries(Object.entries(FILE_ICON_TO_NAME).map(([icon, name]) => [name, icon])));
|
|
2487
2897
|
//#endregion
|
|
2488
2898
|
//#region src/features/annotations/internal/read/readFileAttachmentAnnotation.ts
|
|
2489
2899
|
/** Default `/C` — matches the generator's default icon fill and the writer default. */
|
|
@@ -2505,7 +2915,7 @@ function readFileAttachment(fn, mem, annotPtr, base) {
|
|
|
2505
2915
|
const color = readAnnotColor(fn, mem, annotPtr) ?? { ...DEFAULT_FILE_ATTACHMENT_COLOR$1 };
|
|
2506
2916
|
const ca = readAnnotOpacity(fn, mem, annotPtr);
|
|
2507
2917
|
const opacity = ca == null ? 1 : Math.max(0, Math.min(1, ca));
|
|
2508
|
-
const icon =
|
|
2918
|
+
const icon = FILE_NAME_TO_ICON[readAnnotName(fn, mem, annotPtr) ?? ""] ?? DEFAULT_FILE_ATTACHMENT_ICON;
|
|
2509
2919
|
const attachmentPtr = fn.FPDFAnnot_GetFileAttachment(annotPtr);
|
|
2510
2920
|
const file = attachmentPtr ? readAttachmentFileInfo(fn, mem, attachmentPtr) : { name: "" };
|
|
2511
2921
|
return {
|
|
@@ -2823,167 +3233,67 @@ function readLine(fn, mem, annotPtr, base) {
|
|
|
2823
3233
|
};
|
|
2824
3234
|
}
|
|
2825
3235
|
//#endregion
|
|
2826
|
-
//#region src/features/annotations/internal/destinationViewCodes.ts
|
|
2827
|
-
/**
|
|
2828
|
-
* `PDFDEST_VIEW_*` fit-type codes (public/fpdf_doc.h) — the shared
|
|
2829
|
-
* vocabulary of `FPDFDest_GetView` (read) and `EPDFDest_CreateView`
|
|
2830
|
-
* (write). XYZ is listed for completeness but never goes through
|
|
2831
|
-
* CreateView (it has its own null-aware constructor).
|
|
2832
|
-
*/
|
|
2833
|
-
const DEST_VIEW = {
|
|
2834
|
-
unknown: 0,
|
|
2835
|
-
xyz: 1,
|
|
2836
|
-
fit: 2,
|
|
2837
|
-
fitH: 3,
|
|
2838
|
-
fitV: 4,
|
|
2839
|
-
fitR: 5,
|
|
2840
|
-
fitB: 6,
|
|
2841
|
-
fitBH: 7,
|
|
2842
|
-
fitBV: 8
|
|
2843
|
-
};
|
|
2844
|
-
/** Wire destination kind → PDFDEST_VIEW code, for the non-XYZ kinds. */
|
|
2845
|
-
const VIEW_CODE_BY_KIND = {
|
|
2846
|
-
fit: DEST_VIEW.fit,
|
|
2847
|
-
fitH: DEST_VIEW.fitH,
|
|
2848
|
-
fitV: DEST_VIEW.fitV,
|
|
2849
|
-
fitR: DEST_VIEW.fitR,
|
|
2850
|
-
fitB: DEST_VIEW.fitB,
|
|
2851
|
-
fitBH: DEST_VIEW.fitBH,
|
|
2852
|
-
fitBV: DEST_VIEW.fitBV
|
|
2853
|
-
};
|
|
2854
|
-
//#endregion
|
|
2855
|
-
//#region src/features/annotations/internal/read/readDestination.ts
|
|
2856
|
-
const MAX_VIEW_PARAMS = 4;
|
|
2857
|
-
/**
|
|
2858
|
-
* Materialise one explicit `PdfDestination` from a live `destPtr`. PDFium
|
|
2859
|
-
* already resolved named destinations before handing us the pointer, so
|
|
2860
|
-
* only explicit arrays arrive here (the rule `PdfDestination` documents).
|
|
2861
|
-
*
|
|
2862
|
-
* Returns `null` when the destination is unreadable: no visible indirect page
|
|
2863
|
-
* in the document, or an unknown fit type. Coordinates stay raw PDF user
|
|
2864
|
-
* space — no conversion at this layer.
|
|
2865
|
-
*
|
|
2866
|
-
* Shared by the link reader today; the outline/bookmark port reuses it.
|
|
2867
|
-
*/
|
|
2868
|
-
function readDestination(fn, mem, docPtr, destPtr) {
|
|
2869
|
-
const pageObjectNumber = fn.EPDFDest_GetPageObjectNumber(docPtr, destPtr);
|
|
2870
|
-
if (pageObjectNumber === 0) return null;
|
|
2871
|
-
const view = withScratchN(mem, [4, MAX_VIEW_PARAMS * 4], ([countPtr, paramsPtr]) => {
|
|
2872
|
-
const code = fn.FPDFDest_GetView(destPtr, countPtr, paramsPtr);
|
|
2873
|
-
const count = Math.min(readI32(mem, countPtr), MAX_VIEW_PARAMS);
|
|
2874
|
-
const params = [];
|
|
2875
|
-
for (let i = 0; i < count; i++) params.push(readF32(mem, paramsPtr, i * 4));
|
|
2876
|
-
return {
|
|
2877
|
-
code,
|
|
2878
|
-
params
|
|
2879
|
-
};
|
|
2880
|
-
});
|
|
2881
|
-
const at = (i) => i < view.params.length ? view.params[i] : null;
|
|
2882
|
-
switch (view.code) {
|
|
2883
|
-
case DEST_VIEW.xyz: return {
|
|
2884
|
-
kind: "xyz",
|
|
2885
|
-
pageObjectNumber,
|
|
2886
|
-
...readXyzLocation(fn, mem, destPtr)
|
|
2887
|
-
};
|
|
2888
|
-
case DEST_VIEW.fit: return {
|
|
2889
|
-
kind: "fit",
|
|
2890
|
-
pageObjectNumber
|
|
2891
|
-
};
|
|
2892
|
-
case DEST_VIEW.fitH: return {
|
|
2893
|
-
kind: "fitH",
|
|
2894
|
-
pageObjectNumber,
|
|
2895
|
-
top: at(0)
|
|
2896
|
-
};
|
|
2897
|
-
case DEST_VIEW.fitV: return {
|
|
2898
|
-
kind: "fitV",
|
|
2899
|
-
pageObjectNumber,
|
|
2900
|
-
left: at(0)
|
|
2901
|
-
};
|
|
2902
|
-
case DEST_VIEW.fitR:
|
|
2903
|
-
if (view.params.length < 4) return {
|
|
2904
|
-
kind: "fit",
|
|
2905
|
-
pageObjectNumber
|
|
2906
|
-
};
|
|
2907
|
-
return {
|
|
2908
|
-
kind: "fitR",
|
|
2909
|
-
pageObjectNumber,
|
|
2910
|
-
left: view.params[0],
|
|
2911
|
-
bottom: view.params[1],
|
|
2912
|
-
right: view.params[2],
|
|
2913
|
-
top: view.params[3]
|
|
2914
|
-
};
|
|
2915
|
-
case DEST_VIEW.fitB: return {
|
|
2916
|
-
kind: "fitB",
|
|
2917
|
-
pageObjectNumber
|
|
2918
|
-
};
|
|
2919
|
-
case DEST_VIEW.fitBH: return {
|
|
2920
|
-
kind: "fitBH",
|
|
2921
|
-
pageObjectNumber,
|
|
2922
|
-
top: at(0)
|
|
2923
|
-
};
|
|
2924
|
-
case DEST_VIEW.fitBV: return {
|
|
2925
|
-
kind: "fitBV",
|
|
2926
|
-
pageObjectNumber,
|
|
2927
|
-
left: at(0)
|
|
2928
|
-
};
|
|
2929
|
-
default: return null;
|
|
2930
|
-
}
|
|
2931
|
-
}
|
|
2932
|
-
/** `/XYZ` null-aware axes via `FPDFDest_GetLocationInPage` (FPDF_BOOL is 4 bytes). */
|
|
2933
|
-
function readXyzLocation(fn, mem, destPtr) {
|
|
2934
|
-
return withScratchN(mem, [
|
|
2935
|
-
4,
|
|
2936
|
-
4,
|
|
2937
|
-
4,
|
|
2938
|
-
4,
|
|
2939
|
-
4,
|
|
2940
|
-
4
|
|
2941
|
-
], ([hasLeft, hasTop, hasZoom, left, top, zoom]) => {
|
|
2942
|
-
if (!fn.FPDFDest_GetLocationInPage(destPtr, hasLeft, hasTop, hasZoom, left, top, zoom)) return {
|
|
2943
|
-
left: null,
|
|
2944
|
-
top: null,
|
|
2945
|
-
zoom: null
|
|
2946
|
-
};
|
|
2947
|
-
return {
|
|
2948
|
-
left: readI32(mem, hasLeft) ? readF32(mem, left) : null,
|
|
2949
|
-
top: readI32(mem, hasTop) ? readF32(mem, top) : null,
|
|
2950
|
-
zoom: readI32(mem, hasZoom) ? readF32(mem, zoom) : null
|
|
2951
|
-
};
|
|
2952
|
-
});
|
|
2953
|
-
}
|
|
2954
|
-
//#endregion
|
|
2955
3236
|
//#region src/features/annotations/internal/read/readLinkAnnotation.ts
|
|
2956
3237
|
/**
|
|
2957
3238
|
* Link reader: rect/flags/relationship ride the base (a link grouped to an
|
|
2958
3239
|
* annotation is plain `inReplyTo` + `replyType: 'group'`); this module only
|
|
2959
3240
|
* materialises the normalized target.
|
|
2960
3241
|
*
|
|
2961
|
-
* ONE truth,
|
|
2962
|
-
*
|
|
2963
|
-
*
|
|
2964
|
-
*
|
|
2965
|
-
* and Named-blind) is deliberately not consulted; `FPDFLink_GetDest`
|
|
2966
|
-
* remains only for the data-only direct `/Dest`, which is not an action.
|
|
3242
|
+
* ONE truth, one projection: the target is a pure function of the SAME
|
|
3243
|
+
* payload-carrying action tree the scripting plane reads
|
|
3244
|
+
* (`base.actions.activate`) — no second native read exists any more, so the
|
|
3245
|
+
* two action-shaped surfaces cannot drift by construction.
|
|
2967
3246
|
*
|
|
2968
|
-
* `/A`
|
|
2969
|
-
*
|
|
2970
|
-
*
|
|
3247
|
+
* `/A` precedence, pinned: an activate action that exists but cannot be
|
|
3248
|
+
* executed (an `incomplete` tree, a degraded/unreadable root) projects
|
|
3249
|
+
* `unsupported` — a broken action is a dead link, never an invitation to
|
|
3250
|
+
* guess. The direct `/Dest` (which is data, not an action) is consulted
|
|
3251
|
+
* ONLY when no `/A` exists at all.
|
|
2971
3252
|
*/
|
|
2972
3253
|
function readLink(fn, mem, annotPtr, base, _rawSubtypeCode, ctx) {
|
|
2973
3254
|
return {
|
|
2974
3255
|
...base,
|
|
2975
3256
|
subtype: "link",
|
|
2976
|
-
target: readLinkTarget(fn, mem, annotPtr, ctx)
|
|
3257
|
+
target: readLinkTarget(fn, mem, annotPtr, base, ctx)
|
|
2977
3258
|
};
|
|
2978
3259
|
}
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
3260
|
+
/**
|
|
3261
|
+
* Project the navigation view from a payload-carrying activate tree. Pure —
|
|
3262
|
+
* shared with any consumer that wants the root-level navigation reading of a
|
|
3263
|
+
* tree (the link plugin's no-actions-plugin fallback uses the same law).
|
|
3264
|
+
*/
|
|
3265
|
+
function linkTargetFromActionTree(tree) {
|
|
3266
|
+
if (tree.incomplete) return { kind: "unsupported" };
|
|
3267
|
+
const root = tree.root;
|
|
3268
|
+
if (!root) return { kind: "unsupported" };
|
|
3269
|
+
switch (root.type) {
|
|
3270
|
+
case "goto": return {
|
|
3271
|
+
kind: "goto",
|
|
3272
|
+
destination: root.destination
|
|
3273
|
+
};
|
|
3274
|
+
case "uri": return {
|
|
3275
|
+
kind: "uri",
|
|
3276
|
+
uri: root.uri
|
|
3277
|
+
};
|
|
3278
|
+
case "goto-remote": return {
|
|
3279
|
+
kind: "goto-remote",
|
|
3280
|
+
file: root.filePath
|
|
3281
|
+
};
|
|
3282
|
+
case "launch": return {
|
|
3283
|
+
kind: "launch",
|
|
3284
|
+
path: root.filePath
|
|
3285
|
+
};
|
|
3286
|
+
case "javascript": return { kind: "javascript" };
|
|
3287
|
+
case "named": return {
|
|
3288
|
+
kind: "named",
|
|
3289
|
+
name: root.name
|
|
3290
|
+
};
|
|
3291
|
+
default: return { kind: "unsupported" };
|
|
2986
3292
|
}
|
|
3293
|
+
}
|
|
3294
|
+
function readLinkTarget(fn, mem, annotPtr, base, ctx) {
|
|
3295
|
+
const activate = base.actions?.activate;
|
|
3296
|
+
if (activate) return linkTargetFromActionTree(activate);
|
|
2987
3297
|
const linkPtr = fn.FPDFAnnot_GetLink(annotPtr);
|
|
2988
3298
|
if (!linkPtr) return null;
|
|
2989
3299
|
const destPtr = fn.FPDFLink_GetDest(ctx.docPtr, linkPtr);
|
|
@@ -2994,43 +3304,6 @@ function readLinkTarget(fn, mem, annotPtr, ctx) {
|
|
|
2994
3304
|
destination
|
|
2995
3305
|
} : { kind: "unsupported" };
|
|
2996
3306
|
}
|
|
2997
|
-
/** Classify the root action node and fetch its payload — the projection. */
|
|
2998
|
-
function readRootTarget(fn, mem, modelPtr, node, ctx) {
|
|
2999
|
-
switch (actionTypeFromCode(fn.EPDFAction_GetNodeType(modelPtr, node))) {
|
|
3000
|
-
case "goto": {
|
|
3001
|
-
const destPtr = fn.EPDFAction_GetNodeDest(ctx.docPtr, modelPtr, node);
|
|
3002
|
-
const destination = destPtr ? readDestination(fn, mem, ctx.docPtr, destPtr) : null;
|
|
3003
|
-
return destination ? {
|
|
3004
|
-
kind: "goto",
|
|
3005
|
-
destination
|
|
3006
|
-
} : { kind: "unsupported" };
|
|
3007
|
-
}
|
|
3008
|
-
case "uri": {
|
|
3009
|
-
const uri = readUtf8String(mem, (buf, capacity) => fn.EPDFAction_GetNodeURI(ctx.docPtr, modelPtr, node, buf, capacity));
|
|
3010
|
-
return uri == null ? { kind: "unsupported" } : {
|
|
3011
|
-
kind: "uri",
|
|
3012
|
-
uri
|
|
3013
|
-
};
|
|
3014
|
-
}
|
|
3015
|
-
case "goto-remote": return {
|
|
3016
|
-
kind: "goto-remote",
|
|
3017
|
-
file: readUtf8String(mem, (buf, capacity) => fn.EPDFAction_GetNodeFilePath(modelPtr, node, buf, capacity)) ?? ""
|
|
3018
|
-
};
|
|
3019
|
-
case "launch": return {
|
|
3020
|
-
kind: "launch",
|
|
3021
|
-
path: readUtf8String(mem, (buf, capacity) => fn.EPDFAction_GetNodeFilePath(modelPtr, node, buf, capacity)) ?? ""
|
|
3022
|
-
};
|
|
3023
|
-
case "javascript": return { kind: "javascript" };
|
|
3024
|
-
case "named": {
|
|
3025
|
-
const name = readUtf8String(mem, (buf, capacity) => fn.EPDFAction_GetNodeName(modelPtr, node, buf, capacity));
|
|
3026
|
-
return name == null ? { kind: "unsupported" } : {
|
|
3027
|
-
kind: "named",
|
|
3028
|
-
name
|
|
3029
|
-
};
|
|
3030
|
-
}
|
|
3031
|
-
default: return { kind: "unsupported" };
|
|
3032
|
-
}
|
|
3033
|
-
}
|
|
3034
3307
|
//#endregion
|
|
3035
3308
|
//#region src/features/annotations/internal/read/readRedactAnnotation.ts
|
|
3036
3309
|
/** Default `/C` marking outline (red) — the redaction marking convention and
|
|
@@ -3111,45 +3384,10 @@ function readSquare(fn, mem, annotPtr, base) {
|
|
|
3111
3384
|
};
|
|
3112
3385
|
}
|
|
3113
3386
|
//#endregion
|
|
3114
|
-
//#region src/features/annotations/internal/stampName.ts
|
|
3115
|
-
/**
|
|
3116
|
-
* Stamp `/Name` label ↔ `FPDF_ANNOT_NAME` enum code mapping for the
|
|
3117
|
-
* `EPDFAnnot_SetName` / `EPDFAnnot_GetName` fork helpers. Labels are the
|
|
3118
|
-
* PDF spec / Adobe literal name values (ISO 32000 §12.5.6.12 table 181
|
|
3119
|
-
* plus the Adobe SB/SH extended set the fork supports). Codes mirror the
|
|
3120
|
-
* `FPDF_ANNOT_NAME` enum in `public/fpdf_annot.h` — same pattern as
|
|
3121
|
-
* `lineEnding.ts` keeping engine-core PDFium-free.
|
|
3122
|
-
*/
|
|
3123
|
-
const STAMP_NAME_TO_CODE = Object.freeze({
|
|
3124
|
-
Approved: 13,
|
|
3125
|
-
Experimental: 14,
|
|
3126
|
-
NotApproved: 15,
|
|
3127
|
-
AsIs: 16,
|
|
3128
|
-
Expired: 17,
|
|
3129
|
-
NotForPublicRelease: 18,
|
|
3130
|
-
Confidential: 19,
|
|
3131
|
-
Final: 20,
|
|
3132
|
-
Sold: 21,
|
|
3133
|
-
Departmental: 22,
|
|
3134
|
-
ForComment: 23,
|
|
3135
|
-
TopSecret: 24,
|
|
3136
|
-
Draft: 25,
|
|
3137
|
-
ForPublicRelease: 26,
|
|
3138
|
-
Completed: 27,
|
|
3139
|
-
Void: 28,
|
|
3140
|
-
PreliminaryResults: 29,
|
|
3141
|
-
InformationOnly: 30,
|
|
3142
|
-
Rejected: 31,
|
|
3143
|
-
Witness: 32,
|
|
3144
|
-
InitialHere: 33,
|
|
3145
|
-
SignHere: 34,
|
|
3146
|
-
Accepted: 35
|
|
3147
|
-
});
|
|
3148
|
-
const STAMP_CODE_TO_NAME = Object.freeze(Object.fromEntries(Object.entries(STAMP_NAME_TO_CODE).map(([name, code]) => [code, name])));
|
|
3149
|
-
//#endregion
|
|
3150
3387
|
//#region src/features/annotations/internal/read/readStampAnnotation.ts
|
|
3151
3388
|
/**
|
|
3152
|
-
* Stamp DTO: base + `/Name`
|
|
3389
|
+
* Stamp DTO: base + `/Name` (standard or custom identifier, verbatim) +
|
|
3390
|
+
* transform metadata. The visual content
|
|
3153
3391
|
* stays in the `/AP` stream — rendered via `renderAppearanceImages()`,
|
|
3154
3392
|
* never surfaced as DTO data.
|
|
3155
3393
|
*/
|
|
@@ -3159,16 +3397,11 @@ function readStamp(fn, mem, annotPtr, base) {
|
|
|
3159
3397
|
return {
|
|
3160
3398
|
...base,
|
|
3161
3399
|
subtype: "stamp",
|
|
3162
|
-
name:
|
|
3400
|
+
name: readAnnotName(fn, mem, annotPtr),
|
|
3163
3401
|
...rotation != null ? { rotation } : {},
|
|
3164
3402
|
...unrotatedRect != null ? { unrotatedRect } : {}
|
|
3165
3403
|
};
|
|
3166
3404
|
}
|
|
3167
|
-
function readStampName(fn, mem, annotPtr) {
|
|
3168
|
-
const known = STAMP_CODE_TO_NAME[fn.EPDFAnnot_GetName(annotPtr)];
|
|
3169
|
-
if (known !== void 0) return known;
|
|
3170
|
-
return readAnnotString(fn, mem, annotPtr, "Name");
|
|
3171
|
-
}
|
|
3172
3405
|
//#endregion
|
|
3173
3406
|
//#region src/features/annotations/internal/annotationState.ts
|
|
3174
3407
|
/**
|
|
@@ -3224,7 +3457,7 @@ function readText(fn, mem, annotPtr, base) {
|
|
|
3224
3457
|
const color = readAnnotColor(fn, mem, annotPtr) ?? { ...DEFAULT_NOTE_COLOR$1 };
|
|
3225
3458
|
const ca = readAnnotOpacity(fn, mem, annotPtr);
|
|
3226
3459
|
const opacity = ca == null ? 1 : Math.max(0, Math.min(1, ca));
|
|
3227
|
-
const icon =
|
|
3460
|
+
const icon = NOTE_NAME_TO_ICON[readAnnotName(fn, mem, annotPtr) ?? ""] ?? DEFAULT_NOTE_ICON;
|
|
3228
3461
|
const stateRaw = readAnnotString(fn, mem, annotPtr, "State");
|
|
3229
3462
|
const stateModelRaw = readAnnotString(fn, mem, annotPtr, "StateModel");
|
|
3230
3463
|
return {
|
|
@@ -3540,7 +3773,7 @@ function readOptions(runtime, model, fieldIndex) {
|
|
|
3540
3773
|
return options;
|
|
3541
3774
|
}
|
|
3542
3775
|
/** Read one field of the native model into its per-family DTO. */
|
|
3543
|
-
function readFieldAt(runtime, model, fieldIndex, actionBudget = new ActionReadBudgetTracker()) {
|
|
3776
|
+
function readFieldAt(runtime, model, fieldIndex, docPtr, actionBudget = new ActionReadBudgetTracker()) {
|
|
3544
3777
|
const { fn } = runtime;
|
|
3545
3778
|
const fieldObjectNumber = fn.EPDFForm_GetFieldObjNum(model, fieldIndex);
|
|
3546
3779
|
const name = readWide(runtime, (buf, cap) => fn.EPDFForm_GetFieldName(model, fieldIndex, buf, cap));
|
|
@@ -3548,7 +3781,7 @@ function readFieldAt(runtime, model, fieldIndex, actionBudget = new ActionReadBu
|
|
|
3548
3781
|
const family = FAMILY_BY_CODE[fn.EPDFForm_GetFieldFamily(model, fieldIndex)] ?? "unknown";
|
|
3549
3782
|
const valueEntry = readValueEntry(runtime, model, fieldIndex, false);
|
|
3550
3783
|
const defaultValueEntry = readValueEntry(runtime, model, fieldIndex, true);
|
|
3551
|
-
const actions = readFieldActions(runtime, model, fieldIndex, actionBudget);
|
|
3784
|
+
const actions = readFieldActions(runtime, model, fieldIndex, docPtr, actionBudget);
|
|
3552
3785
|
const base = {
|
|
3553
3786
|
ref: fieldObjectNumber > 0 ? {
|
|
3554
3787
|
kind: "objectNumber",
|
|
@@ -3647,12 +3880,12 @@ function readFieldAt(runtime, model, fieldIndex, actionBudget = new ActionReadBu
|
|
|
3647
3880
|
}
|
|
3648
3881
|
}
|
|
3649
3882
|
/** Read the whole native model into a detached {@link FormSnapshot}. */
|
|
3650
|
-
function readFormSnapshot(runtime, model) {
|
|
3883
|
+
function readFormSnapshot(runtime, model, docPtr) {
|
|
3651
3884
|
const { fn } = runtime;
|
|
3652
3885
|
const count = fn.EPDFForm_CountFields(model);
|
|
3653
3886
|
const fields = [];
|
|
3654
3887
|
const actionBudget = new ActionReadBudgetTracker();
|
|
3655
|
-
for (let i = 0; i < count; i++) fields.push(readFieldAt(runtime, model, i, actionBudget));
|
|
3888
|
+
for (let i = 0; i < count; i++) fields.push(readFieldAt(runtime, model, i, docPtr, actionBudget));
|
|
3656
3889
|
const calculationOrder = [];
|
|
3657
3890
|
const calculationCount = fn.EPDFForm_CountCalculationOrder(model);
|
|
3658
3891
|
for (let index = 0; index < calculationCount; index++) {
|
|
@@ -3688,7 +3921,7 @@ function entryScalar(entry) {
|
|
|
3688
3921
|
if (entry.kind === "array") return entry.values[0] ?? "";
|
|
3689
3922
|
return "";
|
|
3690
3923
|
}
|
|
3691
|
-
function readFieldActions(runtime, model, fieldIndex, budget) {
|
|
3924
|
+
function readFieldActions(runtime, model, fieldIndex, docPtr, budget) {
|
|
3692
3925
|
const { fn, mem } = runtime;
|
|
3693
3926
|
const entries = [
|
|
3694
3927
|
["keystroke", 0],
|
|
@@ -3698,7 +3931,7 @@ function readFieldActions(runtime, model, fieldIndex, budget) {
|
|
|
3698
3931
|
];
|
|
3699
3932
|
const actions = {};
|
|
3700
3933
|
for (const [key, event] of entries) {
|
|
3701
|
-
const action = readActionModel(fn, mem, fn.EPDFForm_GetFieldActionModel(model, fieldIndex, event), budget);
|
|
3934
|
+
const action = readActionModel(fn, mem, docPtr, fn.EPDFForm_GetFieldActionModel(model, fieldIndex, event), budget);
|
|
3702
3935
|
if (action) actions[key] = action;
|
|
3703
3936
|
}
|
|
3704
3937
|
return Object.keys(actions).length > 0 ? actions : void 0;
|
|
@@ -3944,7 +4177,7 @@ function blendModeFromCode(code) {
|
|
|
3944
4177
|
* per-subtype reader builds its DTO by extending this with its own
|
|
3945
4178
|
* fields and `subtype: '...'` discriminator.
|
|
3946
4179
|
*/
|
|
3947
|
-
function readAnnotationBase(fn, mem, annotPtr, pageObjectNumber, index, revision, actionBudget = new ActionReadBudgetTracker()) {
|
|
4180
|
+
function readAnnotationBase(fn, mem, docPtr, annotPtr, pageObjectNumber, index, revision, actionBudget = new ActionReadBudgetTracker()) {
|
|
3948
4181
|
const identity = readAnnotationIdentity(fn, mem, annotPtr, pageObjectNumber, index, revision);
|
|
3949
4182
|
const rect = readAnnotRect(fn, mem, annotPtr);
|
|
3950
4183
|
const flags = readAnnotFlags(fn, annotPtr);
|
|
@@ -3956,7 +4189,7 @@ function readAnnotationBase(fn, mem, annotPtr, pageObjectNumber, index, revision
|
|
|
3956
4189
|
const blendMode = blendModeFromCode(fn.EPDFAnnot_GetBlendMode(annotPtr));
|
|
3957
4190
|
const embd = readEmbedMetadata(fn, mem, annotPtr);
|
|
3958
4191
|
const relationship = readAnnotationRelationship(fn, mem, annotPtr, pageObjectNumber);
|
|
3959
|
-
const actions = readAnnotationActions(fn, mem, annotPtr, actionBudget);
|
|
4192
|
+
const actions = readAnnotationActions(fn, mem, docPtr, annotPtr, actionBudget);
|
|
3960
4193
|
return {
|
|
3961
4194
|
ref: identity.ref,
|
|
3962
4195
|
pageObjectNumber,
|
|
@@ -3980,7 +4213,7 @@ function readAnnotationBase(fn, mem, annotPtr, pageObjectNumber, index, revision
|
|
|
3980
4213
|
...actions ? { actions } : {}
|
|
3981
4214
|
};
|
|
3982
4215
|
}
|
|
3983
|
-
function readAnnotationActions(fn, mem, annotPtr, budget) {
|
|
4216
|
+
function readAnnotationActions(fn, mem, docPtr, annotPtr, budget) {
|
|
3984
4217
|
const events = [
|
|
3985
4218
|
["activate", 0],
|
|
3986
4219
|
["cursorEnter", 1],
|
|
@@ -3996,7 +4229,7 @@ function readAnnotationActions(fn, mem, annotPtr, budget) {
|
|
|
3996
4229
|
];
|
|
3997
4230
|
const actions = {};
|
|
3998
4231
|
for (const [key, event] of events) {
|
|
3999
|
-
const action = readActionModel(fn, mem, fn.EPDFAnnot_GetActionModel(annotPtr, event), budget);
|
|
4232
|
+
const action = readActionModel(fn, mem, docPtr, fn.EPDFAnnot_GetActionModel(annotPtr, event), budget);
|
|
4000
4233
|
if (action) actions[key] = action;
|
|
4001
4234
|
}
|
|
4002
4235
|
return Object.keys(actions).length > 0 ? actions : void 0;
|
|
@@ -4027,7 +4260,7 @@ function collectPageAnnotations(input) {
|
|
|
4027
4260
|
const annotPtr = getAnnotPtrAt(i);
|
|
4028
4261
|
if (!annotPtr) continue;
|
|
4029
4262
|
try {
|
|
4030
|
-
const base = readAnnotationBase(fn, mem, annotPtr, pageObjectNumber, i, revision, actionBudget);
|
|
4263
|
+
const base = readAnnotationBase(fn, mem, readCtx.docPtr, annotPtr, pageObjectNumber, i, revision, actionBudget);
|
|
4031
4264
|
const subtypeCode = fn.FPDFAnnot_GetSubtype(annotPtr);
|
|
4032
4265
|
const { reader } = pickReader(subtypeCode);
|
|
4033
4266
|
const dto = reader(fn, mem, annotPtr, base, subtypeCode, readCtx);
|
|
@@ -4965,7 +5198,7 @@ function computeMutationImpact(inputs) {
|
|
|
4965
5198
|
* `AnnotationUpdateResult.updated`.
|
|
4966
5199
|
*/
|
|
4967
5200
|
function readAnnotationFromPtr(fn, mem, annotPtr, pageObjectNumber, index, revision, ctx) {
|
|
4968
|
-
const base = readAnnotationBase(fn, mem, annotPtr, pageObjectNumber, index, revision);
|
|
5201
|
+
const base = readAnnotationBase(fn, mem, ctx.docPtr, annotPtr, pageObjectNumber, index, revision);
|
|
4969
5202
|
const subtypeCode = fn.FPDFAnnot_GetSubtype(annotPtr);
|
|
4970
5203
|
const { reader } = pickReader(subtypeCode);
|
|
4971
5204
|
return reader(fn, mem, annotPtr, base, subtypeCode, ctx);
|
|
@@ -5246,7 +5479,7 @@ function isFileAttachmentSubtype(subtype) {
|
|
|
5246
5479
|
return subtype === "file-attachment";
|
|
5247
5480
|
}
|
|
5248
5481
|
function setFileAttachmentIcon(fn, annotPtr, icon) {
|
|
5249
|
-
if (!fn.EPDFAnnot_SetName(annotPtr,
|
|
5482
|
+
if (!fn.EPDFAnnot_SetName(annotPtr, FILE_ICON_TO_NAME[icon])) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.Unknown, "EPDFAnnot_SetName returned false");
|
|
5250
5483
|
}
|
|
5251
5484
|
function requireFileResource(file, ctx) {
|
|
5252
5485
|
const resource = ctx?.resources?.[file.resource];
|
|
@@ -5908,12 +6141,12 @@ const STAMP_FIT_TO_CODE = {
|
|
|
5908
6141
|
* creating an annotation or strengthening a weak annotation id.
|
|
5909
6142
|
*/
|
|
5910
6143
|
function preflightStampDraft(draft, ctx) {
|
|
5911
|
-
if (draft.name !== void 0)
|
|
6144
|
+
if (draft.name !== void 0) requireStampName(draft.name);
|
|
5912
6145
|
requireStampFit(draft.fit ?? "contain");
|
|
5913
6146
|
requireStampContent(draft.source, ctx);
|
|
5914
6147
|
}
|
|
5915
6148
|
function preflightStampPatch(patch, ctx) {
|
|
5916
|
-
if (patch.name !== void 0)
|
|
6149
|
+
if (patch.name !== void 0 && patch.name !== null) requireStampName(patch.name);
|
|
5917
6150
|
requireStampFit(patch.fit ?? "contain");
|
|
5918
6151
|
if (patch.source !== void 0) requireStampContent(patch.source, ctx);
|
|
5919
6152
|
}
|
|
@@ -5939,7 +6172,8 @@ function applyStampDraft(fn, mem, annotPtr, draft, ctx) {
|
|
|
5939
6172
|
}
|
|
5940
6173
|
function applyStampPatch(fn, mem, annotPtr, patch, ctx) {
|
|
5941
6174
|
applyAnnotationBasePatch(fn, mem, annotPtr, patch);
|
|
5942
|
-
if (patch.name
|
|
6175
|
+
if (patch.name === null) fn.EPDFAnnot_RemoveKey(annotPtr, "Name");
|
|
6176
|
+
else if (patch.name !== void 0) setStampName(fn, annotPtr, patch.name);
|
|
5943
6177
|
if (patch.source !== void 0) {
|
|
5944
6178
|
const rect = patch.rect ?? readAnnotRect(fn, mem, annotPtr);
|
|
5945
6179
|
authorStampAppearance(fn, mem, annotPtr, patch.source, patch.fit ?? "contain", {
|
|
@@ -5959,15 +6193,14 @@ function applyStampPatch(fn, mem, annotPtr, patch, ctx) {
|
|
|
5959
6193
|
function isStampSubtype(subtype) {
|
|
5960
6194
|
return subtype === "stamp";
|
|
5961
6195
|
}
|
|
6196
|
+
/** Any non-empty name: standard ('Approved') or custom ('#LBGiYhk8V…') —
|
|
6197
|
+
* the fork writes a name object and escapes it; predefined sets are a
|
|
6198
|
+
* reader concern (ISO 32000-2 table 187 allows additional names). */
|
|
5962
6199
|
function setStampName(fn, annotPtr, name) {
|
|
5963
|
-
|
|
5964
|
-
if (code === void 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.Unknown, "stamp name preflight invariant broken");
|
|
5965
|
-
if (!fn.EPDFAnnot_SetName(annotPtr, code)) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.Unknown, "EPDFAnnot_SetName returned false");
|
|
6200
|
+
if (!fn.EPDFAnnot_SetName(annotPtr, name)) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.Unknown, "EPDFAnnot_SetName returned false");
|
|
5966
6201
|
}
|
|
5967
|
-
function
|
|
5968
|
-
|
|
5969
|
-
if (code === void 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, `unknown stamp name '${name}'; supported names: ${Object.keys(STAMP_NAME_TO_CODE).join(", ")}`);
|
|
5970
|
-
return code;
|
|
6202
|
+
function requireStampName(name) {
|
|
6203
|
+
if (name.length === 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, "stamp name must be non-empty");
|
|
5971
6204
|
}
|
|
5972
6205
|
function requireStampFit(fit) {
|
|
5973
6206
|
if (STAMP_FIT_TO_CODE[fit] === void 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, `unknown stamp fit '${String(fit)}'; expected contain, cover, or fill`);
|
|
@@ -6155,7 +6388,7 @@ function isTextSubtype(subtype) {
|
|
|
6155
6388
|
return subtype === "text";
|
|
6156
6389
|
}
|
|
6157
6390
|
function setNoteIcon(fn, annotPtr, icon) {
|
|
6158
|
-
if (!fn.EPDFAnnot_SetName(annotPtr,
|
|
6391
|
+
if (!fn.EPDFAnnot_SetName(annotPtr, NOTE_ICON_TO_NAME[icon])) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.Unknown, "EPDFAnnot_SetName returned false");
|
|
6159
6392
|
}
|
|
6160
6393
|
//#endregion
|
|
6161
6394
|
//#region src/features/annotations/internal/write/writeVertexAnnotation.ts
|
|
@@ -6882,6 +7115,141 @@ var AnnotationMutator = class {
|
|
|
6882
7115
|
}
|
|
6883
7116
|
};
|
|
6884
7117
|
//#endregion
|
|
7118
|
+
//#region src/features/annotations/AnnotationFlattener.ts
|
|
7119
|
+
const FLATTEN_FAIL$1 = 0;
|
|
7120
|
+
const FLATTEN_SUCCESS$1 = 1;
|
|
7121
|
+
const FLATTEN_NOTHING_TO_DO$1 = 2;
|
|
7122
|
+
const STATUS_APPLIED = 0;
|
|
7123
|
+
const STATUS_NOT_ON_PAGE = 2;
|
|
7124
|
+
const FPDF_NO_INCREMENTAL$1 = 2;
|
|
7125
|
+
/**
|
|
7126
|
+
* The annotation-plane flatten verbs — `pages.flatten` for a chosen set:
|
|
7127
|
+
* in place (`flatten`) or into a new single-page document
|
|
7128
|
+
* (`exportAppearance`). Both resolve refs to native handles on the page,
|
|
7129
|
+
* hand the SET to the fork (one candidate plan, one placement writer — the
|
|
7130
|
+
* same code whole-page flatten runs), and release every handle afterwards.
|
|
7131
|
+
*/
|
|
7132
|
+
var AnnotationFlattener = class {
|
|
7133
|
+
constructor(runtime, session) {
|
|
7134
|
+
this.runtime = runtime;
|
|
7135
|
+
this.session = session;
|
|
7136
|
+
}
|
|
7137
|
+
flatten(pageObjectNumber, refs, usage, signal) {
|
|
7138
|
+
throwIfAborted(signal);
|
|
7139
|
+
this.requireRefs("annotations.flatten", pageObjectNumber, refs);
|
|
7140
|
+
const { fn, mem } = this.runtime;
|
|
7141
|
+
const pool = this.session.pagePool();
|
|
7142
|
+
const pagePtr = pool.acquire(pageObjectNumber);
|
|
7143
|
+
try {
|
|
7144
|
+
const annotPtrs = this.resolveAll(pagePtr, refs);
|
|
7145
|
+
let code;
|
|
7146
|
+
let statuses;
|
|
7147
|
+
try {
|
|
7148
|
+
[code, statuses] = this.withHandleArray(annotPtrs, (arrayPtr) => withScratch(mem, 4 * refs.length, (statusPtr) => {
|
|
7149
|
+
const rc = fn.EPDFPage_FlattenAnnotations(pagePtr, arrayPtr, refs.length, usage === "print" ? 1 : 0, statusPtr);
|
|
7150
|
+
const out = [];
|
|
7151
|
+
for (let i = 0; i < refs.length; i++) out.push(Number(mem.peek(statusPtr, "i32", 4 * i)));
|
|
7152
|
+
return [rc, out];
|
|
7153
|
+
}));
|
|
7154
|
+
} finally {
|
|
7155
|
+
for (const annotPtr of annotPtrs) fn.FPDFPage_CloseAnnot(annotPtr);
|
|
7156
|
+
}
|
|
7157
|
+
if (code === FLATTEN_FAIL$1) {
|
|
7158
|
+
const foreign = statuses.findIndex((status) => status === STATUS_NOT_ON_PAGE);
|
|
7159
|
+
throw new _embedpdf_engine_core_runtime.EngineError(foreign >= 0 ? _embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg : _embedpdf_engine_core_runtime.EngineErrorCode.Unknown, foreign >= 0 ? `annotations.flatten: ref ${foreign} is not an annotation of page ${pageObjectNumber}` : "native annotation flatten failed after preflight");
|
|
7160
|
+
}
|
|
7161
|
+
const results = refs.map((ref, i) => ({
|
|
7162
|
+
ref,
|
|
7163
|
+
status: statuses[i] === STATUS_APPLIED ? "applied" : "skipped"
|
|
7164
|
+
}));
|
|
7165
|
+
if (code === FLATTEN_NOTHING_TO_DO$1 || code !== FLATTEN_SUCCESS$1) return {
|
|
7166
|
+
pageObjectNumber,
|
|
7167
|
+
usage,
|
|
7168
|
+
results,
|
|
7169
|
+
meta: null
|
|
7170
|
+
};
|
|
7171
|
+
this.session.noteMutation();
|
|
7172
|
+
this.session.bumpRevision(pageObjectNumber);
|
|
7173
|
+
try {
|
|
7174
|
+
new AnnotationReader(this.runtime, this.session).list(pageObjectNumber, signal);
|
|
7175
|
+
} catch {}
|
|
7176
|
+
return {
|
|
7177
|
+
pageObjectNumber,
|
|
7178
|
+
usage,
|
|
7179
|
+
results,
|
|
7180
|
+
meta: {
|
|
7181
|
+
affectedPages: [this.session.pageState(pageObjectNumber)],
|
|
7182
|
+
cacheDelta: null
|
|
7183
|
+
}
|
|
7184
|
+
};
|
|
7185
|
+
} finally {
|
|
7186
|
+
pool.release(pageObjectNumber);
|
|
7187
|
+
}
|
|
7188
|
+
}
|
|
7189
|
+
exportAppearance(pageObjectNumber, refs, signal) {
|
|
7190
|
+
throwIfAborted(signal);
|
|
7191
|
+
this.requireRefs("annotations.exportAppearance", pageObjectNumber, refs);
|
|
7192
|
+
const { fn, mem } = this.runtime;
|
|
7193
|
+
const pool = this.session.pagePool();
|
|
7194
|
+
const pagePtr = pool.acquire(pageObjectNumber);
|
|
7195
|
+
let exportedPtr = null;
|
|
7196
|
+
let pdfPtr = null;
|
|
7197
|
+
try {
|
|
7198
|
+
const annotPtrs = this.resolveAll(pagePtr, refs);
|
|
7199
|
+
try {
|
|
7200
|
+
exportedPtr = this.withHandleArray(annotPtrs, (arrayPtr) => fn.EPDFPage_ExportAnnotationsAsDocument(pagePtr, arrayPtr, refs.length));
|
|
7201
|
+
} finally {
|
|
7202
|
+
for (const annotPtr of annotPtrs) fn.FPDFPage_CloseAnnot(annotPtr);
|
|
7203
|
+
}
|
|
7204
|
+
if (!exportedPtr) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, "annotations.exportAppearance: every ref must be a visible annotation of this page with a normal appearance");
|
|
7205
|
+
return withScratch(mem, 4, (sizePtr) => {
|
|
7206
|
+
mem.poke(sizePtr, "i32", 0);
|
|
7207
|
+
pdfPtr = fn.EPDF_SaveDocumentToOwnedBuffer(exportedPtr, FPDF_NO_INCREMENTAL$1, sizePtr);
|
|
7208
|
+
const size = Number(mem.peek(sizePtr, "i32"));
|
|
7209
|
+
if (!pdfPtr || size <= 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.DocOpenFailed, "failed to save exported appearances");
|
|
7210
|
+
const bytes = mem.readBytes(pdfPtr, size);
|
|
7211
|
+
const buffer = new ArrayBuffer(bytes.byteLength);
|
|
7212
|
+
new Uint8Array(buffer).set(bytes);
|
|
7213
|
+
return {
|
|
7214
|
+
bytes: buffer,
|
|
7215
|
+
size
|
|
7216
|
+
};
|
|
7217
|
+
});
|
|
7218
|
+
} finally {
|
|
7219
|
+
if (pdfPtr) fn.EPDF_FreeBuffer(pdfPtr);
|
|
7220
|
+
if (exportedPtr) fn.FPDF_CloseDocument(exportedPtr);
|
|
7221
|
+
pool.release(pageObjectNumber);
|
|
7222
|
+
}
|
|
7223
|
+
}
|
|
7224
|
+
/** Resolve every ref on `pagePtr` (NotFound / InvalidReference from the
|
|
7225
|
+
* resolver on caller error); on any failure, close what was opened. */
|
|
7226
|
+
resolveAll(pagePtr, refs) {
|
|
7227
|
+
const { fn } = this.runtime;
|
|
7228
|
+
const annotPtrs = [];
|
|
7229
|
+
try {
|
|
7230
|
+
for (const ref of refs) annotPtrs.push(resolveAnnotPtr(this.runtime, this.session, pagePtr, ref));
|
|
7231
|
+
return annotPtrs;
|
|
7232
|
+
} catch (error) {
|
|
7233
|
+
for (const annotPtr of annotPtrs) fn.FPDFPage_CloseAnnot(annotPtr);
|
|
7234
|
+
throw error;
|
|
7235
|
+
}
|
|
7236
|
+
}
|
|
7237
|
+
/** Marshal an `FPDF_ANNOTATION*` array for the call's duration. */
|
|
7238
|
+
withHandleArray(annotPtrs, body) {
|
|
7239
|
+
const { mem } = this.runtime;
|
|
7240
|
+
const isWasm = this.runtime.kind === "wasm";
|
|
7241
|
+
const ptrSize = isWasm ? 4 : 8;
|
|
7242
|
+
return withScratch(mem, Math.max(1, annotPtrs.length * ptrSize), (arrayPtr) => {
|
|
7243
|
+
annotPtrs.forEach((ptr, i) => isWasm ? mem.poke(arrayPtr, "i32", Number(ptr), i * 4) : mem.poke(arrayPtr, "i64", ptr, i * 8));
|
|
7244
|
+
return body(arrayPtr);
|
|
7245
|
+
});
|
|
7246
|
+
}
|
|
7247
|
+
requireRefs(op, pageObjectNumber, refs) {
|
|
7248
|
+
if (refs.length === 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, `${op} requires at least one ref`);
|
|
7249
|
+
for (const ref of refs) if (ref.pageObjectNumber !== pageObjectNumber) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, `${op} refs must all target page ${pageObjectNumber}; got ref on page ${ref.pageObjectNumber}`);
|
|
7250
|
+
}
|
|
7251
|
+
};
|
|
7252
|
+
//#endregion
|
|
6885
7253
|
//#region src/features/pages/PagesFlattener.ts
|
|
6886
7254
|
const FLATTEN_FAIL = 0;
|
|
6887
7255
|
const FLATTEN_SUCCESS = 1;
|
|
@@ -8183,13 +8551,13 @@ var FormReader = class {
|
|
|
8183
8551
|
snapshot(signal) {
|
|
8184
8552
|
throwIfAborted(signal);
|
|
8185
8553
|
const model = acquireFormModel(this.runtime, this.session);
|
|
8186
|
-
return readFormSnapshot(this.runtime, model);
|
|
8554
|
+
return readFormSnapshot(this.runtime, model, this.session.requireDocPtr());
|
|
8187
8555
|
}
|
|
8188
8556
|
field(ref, signal) {
|
|
8189
8557
|
throwIfAborted(signal);
|
|
8190
8558
|
const model = acquireFormModel(this.runtime, this.session);
|
|
8191
8559
|
const { fieldIndex } = resolveFieldRef(this.runtime, model, ref);
|
|
8192
|
-
return readFieldAt(this.runtime, model, fieldIndex);
|
|
8560
|
+
return readFieldAt(this.runtime, model, fieldIndex, this.session.requireDocPtr());
|
|
8193
8561
|
}
|
|
8194
8562
|
/**
|
|
8195
8563
|
* Serialize form data. Exports read the reconciled view (recovered
|
|
@@ -8345,7 +8713,7 @@ var FormMutator = class {
|
|
|
8345
8713
|
const model = acquireFormModel(this.runtime, this.session);
|
|
8346
8714
|
const resolved = resolveFieldRef(this.runtime, model, ref);
|
|
8347
8715
|
this.assertWritable(resolved.fieldObjectNumber);
|
|
8348
|
-
const before = readFieldAt(this.runtime, model, resolved.fieldIndex);
|
|
8716
|
+
const before = readFieldAt(this.runtime, model, resolved.fieldIndex, this.session.requireDocPtr());
|
|
8349
8717
|
if (!FAMILY_BY_VALUE_TYPE[value.type].includes(before.family)) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, `value type '${value.type}' does not apply to a '${before.family}' field`);
|
|
8350
8718
|
const changed = this.applyWrite(resolved.fieldObjectNumber, value);
|
|
8351
8719
|
return this.readBack(resolved.fieldObjectNumber, changed);
|
|
@@ -8381,7 +8749,7 @@ var FormMutator = class {
|
|
|
8381
8749
|
const fresh = acquireFormModel(this.runtime, this.session);
|
|
8382
8750
|
return {
|
|
8383
8751
|
...counters,
|
|
8384
|
-
snapshot: readFormSnapshot(this.runtime, fresh),
|
|
8752
|
+
snapshot: readFormSnapshot(this.runtime, fresh, this.session.requireDocPtr()),
|
|
8385
8753
|
meta: EMPTY_META$1
|
|
8386
8754
|
};
|
|
8387
8755
|
}
|
|
@@ -8454,7 +8822,7 @@ var FormMutator = class {
|
|
|
8454
8822
|
const model = acquireFormModel(this.runtime, this.session);
|
|
8455
8823
|
const resolved = resolveFieldRef(this.runtime, model, ref);
|
|
8456
8824
|
this.assertWritable(resolved.fieldObjectNumber);
|
|
8457
|
-
const before = readFieldAt(this.runtime, model, resolved.fieldIndex);
|
|
8825
|
+
const before = readFieldAt(this.runtime, model, resolved.fieldIndex, this.session.requireDocPtr());
|
|
8458
8826
|
if (before.family !== patch.family) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, `patch family '${patch.family}' does not match field family '${before.family}'`);
|
|
8459
8827
|
const fieldObjectNumber = resolved.fieldObjectNumber;
|
|
8460
8828
|
if (patch.name !== void 0) this.applyWideSetter(fn.EPDFForm_SetFieldName, fieldObjectNumber, patch.name, `cannot rename to "${patch.name}" (sibling conflict or invalid)`);
|
|
@@ -8485,7 +8853,7 @@ var FormMutator = class {
|
|
|
8485
8853
|
const model = acquireFormModel(this.runtime, this.session);
|
|
8486
8854
|
const resolved = resolveFieldRef(this.runtime, model, ref);
|
|
8487
8855
|
this.assertWritable(resolved.fieldObjectNumber);
|
|
8488
|
-
const before = readFieldAt(this.runtime, model, resolved.fieldIndex);
|
|
8856
|
+
const before = readFieldAt(this.runtime, model, resolved.fieldIndex, this.session.requireDocPtr());
|
|
8489
8857
|
if (!withScratchN(mem, [256 * 4, 4], ([buf, countPtr]) => {
|
|
8490
8858
|
mem.poke(countPtr, "i32", 0);
|
|
8491
8859
|
return fn.EPDFForm_DeleteField(this.session.requireDocPtr(), resolved.fieldObjectNumber, buf, 256, countPtr);
|
|
@@ -8505,7 +8873,7 @@ var FormMutator = class {
|
|
|
8505
8873
|
const model = acquireFormModel(this.runtime, this.session);
|
|
8506
8874
|
const resolved = resolveFieldRef(this.runtime, model, ref);
|
|
8507
8875
|
this.assertWritable(resolved.fieldObjectNumber);
|
|
8508
|
-
const before = readFieldAt(this.runtime, model, resolved.fieldIndex);
|
|
8876
|
+
const before = readFieldAt(this.runtime, model, resolved.fieldIndex, this.session.requireDocPtr());
|
|
8509
8877
|
const toggle = before.family === "checkbox" || before.family === "radio";
|
|
8510
8878
|
const state = toggle ? onState ?? (before.family === "checkbox" ? "Yes" : "") : "";
|
|
8511
8879
|
if (toggle && (!state || state === "Off")) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, "attaching to a radio group needs a non-\"Off\" onState");
|
|
@@ -8551,7 +8919,7 @@ var FormMutator = class {
|
|
|
8551
8919
|
const fresh = acquireFormModel(this.runtime, this.session);
|
|
8552
8920
|
const fieldIndex = this.runtime.fn.EPDFForm_GetFieldIndexByObjNum(fresh, fieldObjectNumber);
|
|
8553
8921
|
if (fieldIndex < 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.Unknown, "form field vanished after write");
|
|
8554
|
-
return readFieldAt(this.runtime, fresh, fieldIndex);
|
|
8922
|
+
return readFieldAt(this.runtime, fresh, fieldIndex, this.session.requireDocPtr());
|
|
8555
8923
|
}
|
|
8556
8924
|
assertWritable(fieldObjectNumber) {
|
|
8557
8925
|
if (fieldObjectNumber === 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, "form field is stored as a direct object and cannot be written");
|
|
@@ -8597,7 +8965,7 @@ var FormMutator = class {
|
|
|
8597
8965
|
const fresh = acquireFormModel(this.runtime, this.session);
|
|
8598
8966
|
const fieldIndex = this.runtime.fn.EPDFForm_GetFieldIndexByObjNum(fresh, fieldObjectNumber);
|
|
8599
8967
|
if (fieldIndex < 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.Unknown, "form field vanished after write");
|
|
8600
|
-
const field = readFieldAt(this.runtime, fresh, fieldIndex);
|
|
8968
|
+
const field = readFieldAt(this.runtime, fresh, fieldIndex, this.session.requireDocPtr());
|
|
8601
8969
|
const changedSet = new Set(changedObjNums);
|
|
8602
8970
|
return {
|
|
8603
8971
|
field,
|
|
@@ -8743,7 +9111,7 @@ var FormsEffectsApplier = class {
|
|
|
8743
9111
|
if (refs.length === 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, "reset effect requires at least one field");
|
|
8744
9112
|
const model = acquireFormModel(this.runtime, this.session);
|
|
8745
9113
|
const resolved = refs.map((ref) => this.resolve(model, ref));
|
|
8746
|
-
const fields = resolved.map(({ fieldIndex }) => readFieldAt(this.runtime, model, fieldIndex, actionBudget));
|
|
9114
|
+
const fields = resolved.map(({ fieldIndex }) => readFieldAt(this.runtime, model, fieldIndex, this.session.requireDocPtr(), actionBudget));
|
|
8747
9115
|
validateEffect(effect, fields);
|
|
8748
9116
|
return {
|
|
8749
9117
|
effect,
|
|
@@ -8768,7 +9136,7 @@ var FormsEffectsApplier = class {
|
|
|
8768
9136
|
const model = acquireFormModel(this.runtime, this.session);
|
|
8769
9137
|
const index = this.runtime.fn.EPDFForm_GetFieldIndexByObjNum(model, fieldObjectNumber);
|
|
8770
9138
|
if (index < 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidReference, "form field disappeared");
|
|
8771
|
-
return readFieldAt(this.runtime, model, index, actionBudget);
|
|
9139
|
+
return readFieldAt(this.runtime, model, index, this.session.requireDocPtr(), actionBudget);
|
|
8772
9140
|
}
|
|
8773
9141
|
readFieldsBestEffort(fieldObjectNumbers, actionBudget) {
|
|
8774
9142
|
const fields = [];
|
|
@@ -9135,22 +9503,26 @@ var DocumentActionsReader = class {
|
|
|
9135
9503
|
} finally {
|
|
9136
9504
|
fn.FPDFDoc_CloseJavaScriptAction(namedPtr);
|
|
9137
9505
|
}
|
|
9138
|
-
|
|
9506
|
+
budget.reservePayloadBytes(name.length);
|
|
9507
|
+
const action = requireAction(readActionModel(fn, mem, docPtr, fn.EPDFDoc_GetNamedJavaScriptActionModel(docPtr, index), budget), "name-tree script", index);
|
|
9139
9508
|
nameTreeScripts.push({
|
|
9140
9509
|
name,
|
|
9141
9510
|
action
|
|
9142
9511
|
});
|
|
9143
9512
|
}
|
|
9144
|
-
const openAction = readActionModel(fn, mem, fn.EPDFDoc_GetOpenActionModel(docPtr), budget);
|
|
9513
|
+
const openAction = readActionModel(fn, mem, docPtr, fn.EPDFDoc_GetOpenActionModel(docPtr), budget);
|
|
9514
|
+
const openDestPtr = openAction ? _embedpdf_engine_runtime.NULL_PTR : fn.EPDFDoc_GetOpenActionDest(docPtr);
|
|
9515
|
+
const openDestination = openDestPtr !== _embedpdf_engine_runtime.NULL_PTR ? readDestination(fn, mem, docPtr, openDestPtr) : null;
|
|
9145
9516
|
const additional = {};
|
|
9146
9517
|
for (const [key, event] of DOCUMENT_ACTION_EVENTS) {
|
|
9147
9518
|
throwIfAborted(signal);
|
|
9148
|
-
const action = readActionModel(fn, mem, fn.EPDFDoc_GetAdditionalActionModel(docPtr, event), budget);
|
|
9519
|
+
const action = readActionModel(fn, mem, docPtr, fn.EPDFDoc_GetAdditionalActionModel(docPtr, event), budget);
|
|
9149
9520
|
if (action) additional[key] = action;
|
|
9150
9521
|
}
|
|
9151
9522
|
return {
|
|
9152
9523
|
nameTreeScripts,
|
|
9153
9524
|
openAction,
|
|
9525
|
+
openDestination,
|
|
9154
9526
|
...additional
|
|
9155
9527
|
};
|
|
9156
9528
|
}
|
|
@@ -9484,6 +9856,18 @@ var WorkerHost = class {
|
|
|
9484
9856
|
case "pages.delete":
|
|
9485
9857
|
resultPack = this.handlePagesDelete(msg, ctrl.signal);
|
|
9486
9858
|
break;
|
|
9859
|
+
case "pages.setName":
|
|
9860
|
+
resultPack = this.handlePagesSetName(msg, ctrl.signal);
|
|
9861
|
+
break;
|
|
9862
|
+
case "annotations.flatten":
|
|
9863
|
+
resultPack = this.handleAnnotationsFlatten(msg, ctrl.signal);
|
|
9864
|
+
break;
|
|
9865
|
+
case "annotations.exportAppearance":
|
|
9866
|
+
resultPack = this.handleAnnotationsExportAppearance(msg, ctrl.signal);
|
|
9867
|
+
break;
|
|
9868
|
+
case "pages.removeName":
|
|
9869
|
+
resultPack = this.handlePagesRemoveName(msg, ctrl.signal);
|
|
9870
|
+
break;
|
|
9487
9871
|
case "pages.flatten":
|
|
9488
9872
|
resultPack = this.handlePagesFlatten(msg, ctrl.signal);
|
|
9489
9873
|
break;
|
|
@@ -9711,6 +10095,27 @@ var WorkerHost = class {
|
|
|
9711
10095
|
result
|
|
9712
10096
|
}, req.artifactPath);
|
|
9713
10097
|
}
|
|
10098
|
+
handleAnnotationsFlatten(req, signal) {
|
|
10099
|
+
const session = this.requireSession(req);
|
|
10100
|
+
const result = new AnnotationFlattener(this.runtime, session).flatten(req.pageObjectNumber, req.refs, req.usage, signal);
|
|
10101
|
+
if (result.meta === null) return (0, _embedpdf_engine_core_runtime.wirePack)({
|
|
10102
|
+
tag: "annotations.flatten",
|
|
10103
|
+
result
|
|
10104
|
+
});
|
|
10105
|
+
return this.finishMutation(session, {
|
|
10106
|
+
tag: "annotations.flatten",
|
|
10107
|
+
result
|
|
10108
|
+
}, req.artifactPath);
|
|
10109
|
+
}
|
|
10110
|
+
handleAnnotationsExportAppearance(req, signal) {
|
|
10111
|
+
const session = this.requireSession(req);
|
|
10112
|
+
const exported = new AnnotationFlattener(this.runtime, session).exportAppearance(req.pageObjectNumber, req.refs, signal);
|
|
10113
|
+
return (0, _embedpdf_engine_core_runtime.wirePack)({
|
|
10114
|
+
tag: "annotations.exportAppearance",
|
|
10115
|
+
bytes: exported.bytes,
|
|
10116
|
+
size: exported.size
|
|
10117
|
+
}, [exported.bytes]);
|
|
10118
|
+
}
|
|
9714
10119
|
handleAnnotationsMove(req, signal) {
|
|
9715
10120
|
const session = this.requireSession(req);
|
|
9716
10121
|
const result = new AnnotationMutator(this.runtime, session).move(req.pageObjectNumber, req.refs, req.toIndex, signal);
|
|
@@ -9750,6 +10155,26 @@ var WorkerHost = class {
|
|
|
9750
10155
|
result
|
|
9751
10156
|
}, req.artifactPath);
|
|
9752
10157
|
}
|
|
10158
|
+
handlePagesSetName(req, signal) {
|
|
10159
|
+
const session = this.requireSession(req);
|
|
10160
|
+
const result = new PagesMutator(this.runtime, session).setName({
|
|
10161
|
+
name: req.name,
|
|
10162
|
+
pageObjectNumber: req.pageObjectNumber,
|
|
10163
|
+
...req.replace !== void 0 ? { replace: req.replace } : {}
|
|
10164
|
+
}, signal);
|
|
10165
|
+
return this.finishMutation(session, {
|
|
10166
|
+
tag: "pages.setName",
|
|
10167
|
+
result
|
|
10168
|
+
}, req.artifactPath);
|
|
10169
|
+
}
|
|
10170
|
+
handlePagesRemoveName(req, signal) {
|
|
10171
|
+
const session = this.requireSession(req);
|
|
10172
|
+
const result = new PagesMutator(this.runtime, session).removeName({ name: req.name }, signal);
|
|
10173
|
+
return this.finishMutation(session, {
|
|
10174
|
+
tag: "pages.removeName",
|
|
10175
|
+
result
|
|
10176
|
+
}, req.artifactPath);
|
|
10177
|
+
}
|
|
9753
10178
|
handlePagesFlatten(req, signal) {
|
|
9754
10179
|
const session = this.requireSession(req);
|
|
9755
10180
|
const result = new PagesFlattener(this.runtime, session).flatten(req.pageObjectNumbers, req.usage, signal);
|
|
@@ -10327,6 +10752,7 @@ function passwordRequiredProbe() {
|
|
|
10327
10752
|
exports.ALL_STANDARD_SECURITY_PERMISSIONS = ALL_STANDARD_SECURITY_PERMISSIONS;
|
|
10328
10753
|
exports.ActionReadBudgetTracker = ActionReadBudgetTracker;
|
|
10329
10754
|
exports.AnnotationAppearanceReader = AnnotationAppearanceReader;
|
|
10755
|
+
exports.AnnotationFlattener = AnnotationFlattener;
|
|
10330
10756
|
exports.AnnotationMutator = AnnotationMutator;
|
|
10331
10757
|
exports.AnnotationReader = AnnotationReader;
|
|
10332
10758
|
exports.AttachmentMutator = AttachmentMutator;
|