(ref: PdfRef)
| 513 | |
| 514 | // Create length resolver for stream objects with indirect /Length |
| 515 | const lengthResolver: LengthResolver = (ref: PdfRef) => { |
| 516 | // Check object cache first |
| 517 | const cacheKey = `${ref.objectNumber} ${ref.generation}`; |
| 518 | const cached = cache.get(cacheKey); |
| 519 | |
| 520 | if (cached instanceof PdfNumber) { |
| 521 | return cached.value; |
| 522 | } |
| 523 | |
| 524 | const entry = xref.get(ref.objectNumber); |
| 525 | |
| 526 | if (!entry || entry.type === "free") { |
| 527 | return null; |
| 528 | } |
| 529 | |
| 530 | // Save scanner position - we must restore it after parsing |
| 531 | // because we're in the middle of parsing a stream |
| 532 | const savedPosition = this.scanner.position; |
| 533 | |
| 534 | try { |
| 535 | let lengthObj: PdfObject | null = null; |
| 536 | |
| 537 | if (entry.type === "uncompressed") { |
| 538 | const parser = new IndirectObjectParser(this.scanner); |
| 539 | lengthObj = parser.parseObjectAt(entry.offset).value; |
| 540 | } else { |
| 541 | // Compressed: load from object stream |
| 542 | // Object streams themselves must be uncompressed (per PDF spec 7.5.7) |
| 543 | const streamEntry = xref.get(entry.streamObjNum); |
| 544 | |
| 545 | if (streamEntry?.type === "uncompressed") { |
| 546 | // Use cached object stream parser if available |
| 547 | let objStreamParser = objectStreamCache.get(entry.streamObjNum); |
| 548 | |
| 549 | if (!objStreamParser) { |
| 550 | const parser = new IndirectObjectParser(this.scanner); |
| 551 | const streamResult = parser.parseObjectAt(streamEntry.offset); |
| 552 | |
| 553 | if (streamResult.value instanceof PdfStream) { |
| 554 | objStreamParser = new ObjectStreamParser(streamResult.value); |
| 555 | |
| 556 | objectStreamCache.set(entry.streamObjNum, objStreamParser); |
| 557 | } |
| 558 | } |
| 559 | |
| 560 | if (objStreamParser) { |
| 561 | lengthObj = objStreamParser.getObject(entry.indexInStream); |
| 562 | } |
| 563 | } |
| 564 | } |
| 565 | |
| 566 | this.scanner.moveTo(savedPosition); |
| 567 | |
| 568 | if (lengthObj instanceof PdfNumber) { |
| 569 | cache.set(cacheKey, lengthObj); |
| 570 | |
| 571 | return lengthObj.value; |
| 572 | } |
no test coverage detected