internal Reader(IInputStream stream, Files.File file) { this.parser = new FileParser(stream, file); }
protected override void WriteIncremental( ) { // 1. Original content (head, body and previous trailer). FileParser parser = file.Reader.Parser; stream.Write(parser.Stream); // 2. Body update (modified indirect objects insertion). int xrefSize = file.IndirectObjects.Count; StringBuilder xrefBuilder = new StringBuilder(XRefChunk); { /* * NOTE: Incremental xref table comprises multiple sections * each one composed by multiple subsections; this update * adds a new section. */ StringBuilder xrefSubBuilder = new StringBuilder(); // Xref-table subsection builder. int xrefSubCount = 0; // Xref-table subsection counter. int prevKey = 0; // Previous-entry object number. foreach ( KeyValuePair <int, PdfIndirectObject> indirectObjectEntry in file.IndirectObjects.ModifiedObjects ) { // Is the object in the current subsection? /* * NOTE: To belong to the current subsection, the object entry MUST be contiguous with the * previous (condition 1) or the iteration has to have been just started (condition 2). */ if (indirectObjectEntry.Key - prevKey == 1 || prevKey == 0) // Current subsection continues. { xrefSubCount++; } else // Current subsection terminates. { // End current subsection! AppendXRefSubsection( xrefBuilder, prevKey - xrefSubCount + 1, xrefSubCount, xrefSubBuilder ); // Begin next subsection! xrefSubBuilder.Length = 0; xrefSubCount = 1; } prevKey = indirectObjectEntry.Key; // Current entry insertion. if (indirectObjectEntry.Value.IsInUse()) // In-use entry. { // Add in-use entry! AppendXRefEntry( xrefSubBuilder, indirectObjectEntry.Value.Reference, stream.Length ); // Add in-use entry content! indirectObjectEntry.Value.WriteTo(stream, file); } else // Free entry. { // Add free entry! /* * NOTE: We purposely neglect the linked list of free entries (see IndirectObjects.remove(int)), * so that this entry links directly back to object number 0, having a generation number of 65535 * (not reusable) [PDF:1.6:3.4.3]. */ AppendXRefEntry( xrefSubBuilder, indirectObjectEntry.Value.Reference, 0 ); } } // End last subsection! AppendXRefSubsection( xrefBuilder, prevKey - xrefSubCount + 1, xrefSubCount, xrefSubBuilder ); } // 3. XRef-table last section. long startxref = stream.Length; stream.Write(xrefBuilder.ToString()); // 4. Trailer. WriteTrailer(startxref, xrefSize, parser); }
public ObjectEntry(PdfDataObject dataObject, FileParser parser) : this(parser) { this.dataObject = dataObject; this.offset = -1; // Undefined -- to set on stream serialization. }
public ObjectEntry(int offset, FileParser parser) : this(parser) { this.dataObject = null; this.offset = offset; }
private ObjectEntry(FileParser parser) { this.parser = parser; }
internal Reader(IInputStream stream, Files.File file, string password = null, System.IO.Stream keyStoreInputStream = null) { this.parser = new FileParser(stream, file, password, keyStoreInputStream); }
protected override void WriteIncremental() { // 1. Original content (header, body and previous trailer). FileParser parser = file.Reader.Parser; stream.Write(parser.Stream); // 2. Body update (modified indirect objects insertion). XRefEntry xrefStreamEntry; { // Create the xref stream! /* * NOTE: Incremental xref information structure comprises multiple sections; this update adds * a new section. */ XRefStream xrefStream = new XRefStream(file); // 2.1. Indirect objects. IndirectObjects indirectObjects = file.IndirectObjects; // 2.1.1. Modified indirect objects serialization. XRefEntry prevFreeEntry = null; /* * NOTE: Any uncompressed indirect object will be compressed. */ ObjectStream objectStream = null; /* * NOTE: Any previously-compressed indirect object will have its original object stream * updated through a new extension object stream. */ IDictionary <int, ObjectStream> extensionObjectStreams = new Dictionary <int, ObjectStream>(); int indirectObjectsPrecompressCount = indirectObjects.Count; foreach (PdfIndirectObject indirectObject in new List <PdfIndirectObject>(indirectObjects.ModifiedObjects.Values)) { if (indirectObject.IsCompressible()) { if (objectStream == null || objectStream.Count >= ObjectStreamMaxEntryCount) { file.Register(objectStream = new ObjectStream()); } indirectObject.Compress(objectStream); } prevFreeEntry = AddXRefEntry( indirectObject, xrefStream, prevFreeEntry, extensionObjectStreams ); } // 2.1.2. Additional object streams serialization. for (int index = indirectObjectsPrecompressCount, limit = indirectObjects.Count; index < limit; index++) { prevFreeEntry = AddXRefEntry( indirectObjects[index], xrefStream, prevFreeEntry, null ); } if (prevFreeEntry != null) { prevFreeEntry.Offset = 0; // Links back to the first free object. NOTE: The first entry in the table (object number 0) is always free. } // 2.2. XRef stream. UpdateTrailer(xrefStream.Header, stream); xrefStream.Header[PdfName.Prev] = PdfInteger.Get((int)parser.RetrieveXRefOffset()); AddXRefEntry( /* * NOTE: This xref stream indirect object is purposely temporary (i.e. not registered into * the file's indirect objects collection). */ new PdfIndirectObject( file, xrefStream, xrefStreamEntry = new XRefEntry(indirectObjects.Count, 0, (int)stream.Length, XRefEntry.UsageEnum.InUse) ), xrefStream, null, null ); } // 3. Tail. WriteTail(xrefStreamEntry.Offset); }