* Copy a reference, creating the referenced object in dest if needed. * * Handles circular references by registering a placeholder before * recursively copying the referenced object's contents.
(ref: PdfRef)
| 169 | * recursively copying the referenced object's contents. |
| 170 | */ |
| 171 | private copyRef(ref: PdfRef): PdfRef { |
| 172 | const key = `${ref.objectNumber}:${ref.generation}`; |
| 173 | |
| 174 | // Already copied (or being copied)? |
| 175 | const existing = this.refMap.get(key); |
| 176 | |
| 177 | if (existing) { |
| 178 | return existing; |
| 179 | } |
| 180 | |
| 181 | // Resolve the source object |
| 182 | const srcObj = this.source.getObject(ref); |
| 183 | |
| 184 | if (srcObj === null) { |
| 185 | // Referenced object doesn't exist - this shouldn't happen in valid PDFs |
| 186 | // but we handle it gracefully by returning a ref to a null object |
| 187 | const nullRef = this.dest.register(new PdfDict()); |
| 188 | this.refMap.set(key, nullRef); |
| 189 | |
| 190 | return nullRef; |
| 191 | } |
| 192 | |
| 193 | // For dicts and streams, we can handle circular references by: |
| 194 | // 1. Create a clone/placeholder in dest and register it first |
| 195 | // 2. Then copy contents (which may reference back to us) |
| 196 | // This way, any back-references will find our ref in the map |
| 197 | |
| 198 | if (srcObj instanceof PdfStream) { |
| 199 | return this.copyStreamRef(key, srcObj); |
| 200 | } |
| 201 | |
| 202 | if (srcObj instanceof PdfDict) { |
| 203 | return this.copyDictRef(key, srcObj); |
| 204 | } |
| 205 | |
| 206 | if (srcObj instanceof PdfArray) { |
| 207 | // Arrays can contain circular refs too |
| 208 | const items: PdfObject[] = []; |
| 209 | |
| 210 | for (const item of srcObj) { |
| 211 | items.push(this.copyObject(item)); |
| 212 | } |
| 213 | |
| 214 | const copiedArr = new PdfArray(items); |
| 215 | const destRef = this.dest.register(copiedArr); |
| 216 | this.refMap.set(key, destRef); |
| 217 | |
| 218 | return destRef; |
| 219 | } |
| 220 | |
| 221 | // Primitives - just register them |
| 222 | const destRef = this.dest.register(srcObj); |
| 223 | this.refMap.set(key, destRef); |
| 224 | |
| 225 | return destRef; |
| 226 | } |
| 227 | |
| 228 | /** |
no test coverage detected