public ObjectToken WriteObject(Stream stream, IToken token, int?reservedNumber = null) { int number; if (reservedNumber.HasValue) { if (!reservedNumbers.Remove(reservedNumber.Value)) { throw new InvalidOperationException(); } number = reservedNumber.Value; } else { number = CurrentNumber++; } var reference = new IndirectReference(number, 0); var obj = new ObjectToken(stream.Position, reference, token); objectOffsets.Add(reference, obj.Position); TokenWriter.WriteToken(obj, stream); return(obj); }
public override IndirectReferenceToken WriteToken(IToken token) { if (!Initialized) { InitializePdf(DefaultVersion); } ms.SetLength(0); TokenWriter.WriteToken(token, ms); var contents = ms.ToArray(); if (AttemptDeduplication && hashes.TryGetValue(contents, out var value)) { return(value); } var ir = ReserveObjectNumber(); if (AttemptDeduplication) { hashes.Add(contents, ir); } offsets.Add(ir.Data, Stream.Position); TokenWriter.WriteObject(ir.Data.ObjectNumber, ir.Data.Generation, contents, Stream); return(ir); }
public ObjectToken WriteObject(Stream stream, IToken token) { var reference = new IndirectReference(CurrentNumber++, 0); var obj = new ObjectToken(stream.Position, reference, token); objectOffsets.Add(reference, obj.Position); TokenWriter.WriteToken(obj, stream); return(obj); }
private static ObjectToken WriteObject(IToken content, Stream stream, Dictionary <IndirectReference, long> objectOffsets, ref int number) { var reference = new IndirectReference(number++, 0); var obj = new ObjectToken(stream.Position, reference, content); objectOffsets.Add(reference, obj.Position); // TODO: write TokenWriter.WriteToken(obj, stream); return(obj); }
public virtual IndirectReferenceToken WriteToken(IToken token, IndirectReferenceToken indirectReference) { if (!Initialized) { InitializePdf(DefaultVersion); } offsets.Add(indirectReference.Data, Stream.Position); var obj = new ObjectToken(Stream.Position, indirectReference.Data, token); TokenWriter.WriteToken(obj, Stream); return(indirectReference); }
public virtual IndirectReferenceToken WriteToken(IToken token) { if (!Initialized) { InitializePdf(DefaultVersion); } var ir = ReserveObjectNumber(); offsets.Add(ir.Data, Stream.Position); var obj = new ObjectToken(Stream.Position, ir.Data, token); TokenWriter.WriteToken(obj, Stream); return(ir); }
public override IndirectReferenceToken WriteToken(IToken token, IndirectReferenceToken indirectReference) { if (!Initialized) { InitializePdf(DefaultVersion); } ms.SetLength(0); TokenWriter.WriteToken(token, ms); var contents = ms.ToArray(); hashes.Add(contents, indirectReference); offsets.Add(indirectReference.Data, Stream.Position); TokenWriter.WriteObject(indirectReference.Data.ObjectNumber, indirectReference.Data.Generation, contents, Stream); return(indirectReference); }
public void Flush(decimal version, IndirectReferenceToken catalogReference) { if (catalogReference == null) { throw new ArgumentNullException(nameof(catalogReference)); } WriteString($"%PDF-{version:0.0}", Stream); Stream.WriteText("%"); Stream.WriteByte(169); Stream.WriteByte(205); Stream.WriteByte(196); Stream.WriteByte(210); Stream.WriteNewLine(); var offsets = new Dictionary <IndirectReference, long>(); ObjectToken catalogToken = null; foreach (var pair in tokenReferences) { var referenceToken = pair.Key; var token = pair.Value; var offset = Stream.Position; var obj = new ObjectToken(offset, referenceToken.Data, token); TokenWriter.WriteToken(obj, Stream); offsets.Add(referenceToken.Data, offset); if (catalogToken == null && referenceToken == catalogReference) { catalogToken = obj; } } if (catalogToken == null) { throw new Exception("Catalog object wasn't found"); } // TODO: Support document information TokenWriter.WriteCrossReferenceTable(offsets, catalogToken, Stream, null); }
public byte[] Build() { if (memory == null) { throw new ObjectDisposedException("Merger closed already"); } if (documentPages.Count < 1) { throw new PdfDocumentFormatException("Empty document"); } var pagesDictionary = new DictionaryToken(new Dictionary <NameToken, IToken> { { NameToken.Type, NameToken.Pages }, { NameToken.Kids, new ArrayToken(documentPages) }, { NameToken.Count, new NumericToken(pageCount) } }); var pagesRef = context.WriteObject(memory, pagesDictionary, (int)rootPagesIndirectReference.Data.ObjectNumber); var catalog = new DictionaryToken(new Dictionary <NameToken, IToken> { { NameToken.Type, NameToken.Catalog }, { NameToken.Pages, new IndirectReferenceToken(pagesRef.Number) } }); var catalogRef = context.WriteObject(memory, catalog); TokenWriter.WriteCrossReferenceTable(context.ObjectOffsets, catalogRef, memory, null); if (currentVersion != DefaultVersion) { memory.Seek(0, SeekOrigin.Begin); WriteHeaderToStream(); } var bytes = memory.ToArray(); Close(); return(bytes); }
/// <summary> /// Builds a PDF document from the current content of this builder and its pages. /// </summary> /// <returns>The bytes of the resulting PDF document.</returns> public byte[] Build() { var context = new BuilderContext(); var fontsWritten = new Dictionary <Guid, ObjectToken>(); using (var memory = new MemoryStream()) { // Header WriteString("%PDF-1.7", memory); // Files with binary data should contain a 2nd comment line followed by 4 bytes with values > 127 memory.WriteText("%"); memory.WriteByte(169); memory.WriteByte(205); memory.WriteByte(196); memory.WriteByte(210); memory.WriteNewLine(); // Body foreach (var font in fonts) { var fontObj = font.Value.FontProgram.WriteFont(font.Value.FontKey.Name, memory, context); fontsWritten.Add(font.Key, fontObj); } var resources = new Dictionary <NameToken, IToken> { { NameToken.ProcSet, new ArrayToken(new [] { NameToken.Create("PDF"), NameToken.Create("Text") }) } }; if (fontsWritten.Count > 0) { var fontsDictionary = new DictionaryToken(fontsWritten.Select(x => (fonts[x.Key].FontKey.Name, (IToken) new IndirectReferenceToken(x.Value.Number))) .ToDictionary(x => x.Item1, x => x.Item2)); var fontsDictionaryRef = context.WriteObject(memory, fontsDictionary); resources.Add(NameToken.Font, new IndirectReferenceToken(fontsDictionaryRef.Number)); } var reserved = context.ReserveNumber(); var parentIndirect = new IndirectReferenceToken(new IndirectReference(reserved, 0)); var pageReferences = new List <IndirectReferenceToken>(); foreach (var page in pages) { var pageDictionary = new Dictionary <NameToken, IToken> { { NameToken.Type, NameToken.Page }, { NameToken.Resources, new DictionaryToken(resources) }, { NameToken.MediaBox, RectangleToArray(page.Value.PageSize) }, { NameToken.Parent, parentIndirect } }; if (page.Value.Operations.Count > 0) { var contentStream = WriteContentStream(page.Value.Operations); var contentStreamObj = context.WriteObject(memory, contentStream); pageDictionary[NameToken.Contents] = new IndirectReferenceToken(contentStreamObj.Number); } var pageRef = context.WriteObject(memory, new DictionaryToken(pageDictionary)); pageReferences.Add(new IndirectReferenceToken(pageRef.Number)); } var pagesDictionary = new DictionaryToken(new Dictionary <NameToken, IToken> { { NameToken.Type, NameToken.Pages }, { NameToken.Kids, new ArrayToken(pageReferences) }, { NameToken.Count, new NumericToken(pageReferences.Count) } }); var pagesRef = context.WriteObject(memory, pagesDictionary, reserved); var catalog = new DictionaryToken(new Dictionary <NameToken, IToken> { { NameToken.Type, NameToken.Catalog }, { NameToken.Pages, new IndirectReferenceToken(pagesRef.Number) } }); var catalogRef = context.WriteObject(memory, catalog); var informationReference = default(IndirectReference?); if (IncludeDocumentInformation) { var informationDictionary = DocumentInformation.ToDictionary(); if (informationDictionary.Count > 0) { var dictionary = new DictionaryToken(informationDictionary); informationReference = context.WriteObject(memory, dictionary).Number; } } TokenWriter.WriteCrossReferenceTable(context.ObjectOffsets, catalogRef, memory, informationReference); return(memory.ToArray()); } }
/// <summary> /// Builds a PDF document from the current content of this builder and its pages. /// </summary> /// <returns>The bytes of the resulting PDF document.</returns> public byte[] Build() { var fontsWritten = new Dictionary <Guid, ObjectToken>(); using (var memory = new MemoryStream()) { // Header WriteString("%PDF-1.7", memory); // Files with binary data should contain a 2nd comment line followed by 4 bytes with values > 127 memory.WriteText("%"); memory.WriteByte(169); memory.WriteByte(205); memory.WriteByte(196); memory.WriteByte(210); memory.WriteNewLine(); // Body foreach (var font in fonts) { var fontObj = font.Value.FontProgram.WriteFont(font.Value.FontKey.Name, memory, context); fontsWritten.Add(font.Key, fontObj); } foreach (var image in images) { var streamToken = new StreamToken(image.Value.StreamDictionary, image.Value.StreamData); context.WriteObject(memory, streamToken, image.Value.ObjectNumber); } var procSet = new List <NameToken> { NameToken.Create("PDF"), NameToken.Text, NameToken.ImageB, NameToken.ImageC, NameToken.ImageI }; var resources = new Dictionary <NameToken, IToken> { { NameToken.ProcSet, new ArrayToken(procSet) } }; if (fontsWritten.Count > 0) { var fontsDictionary = new DictionaryToken(fontsWritten.Select(x => (fonts[x.Key].FontKey.Name, (IToken) new IndirectReferenceToken(x.Value.Number))) .ToDictionary(x => x.Item1, x => x.Item2)); var fontsDictionaryRef = context.WriteObject(memory, fontsDictionary); resources.Add(NameToken.Font, new IndirectReferenceToken(fontsDictionaryRef.Number)); } var reserved = context.ReserveNumber(); var parentIndirect = new IndirectReferenceToken(new IndirectReference(reserved, 0)); var pageReferences = new List <IndirectReferenceToken>(); foreach (var page in pages) { var individualResources = new Dictionary <NameToken, IToken>(resources); var pageDictionary = new Dictionary <NameToken, IToken> { { NameToken.Type, NameToken.Page }, { NameToken.MediaBox, RectangleToArray(page.Value.PageSize) }, { NameToken.Parent, parentIndirect } }; if (page.Value.Resources.Count > 0) { foreach (var kvp in page.Value.Resources) { // TODO: combine resources if value is dictionary or array, otherwise overwrite. individualResources[kvp.Key] = kvp.Value; } } pageDictionary[NameToken.Resources] = new DictionaryToken(individualResources); if (page.Value.Operations.Count > 0) { var contentStream = WriteContentStream(page.Value.Operations); var contentStreamObj = context.WriteObject(memory, contentStream); pageDictionary[NameToken.Contents] = new IndirectReferenceToken(contentStreamObj.Number); } var pageRef = context.WriteObject(memory, new DictionaryToken(pageDictionary)); pageReferences.Add(new IndirectReferenceToken(pageRef.Number)); } var pagesDictionaryData = new Dictionary <NameToken, IToken> { { NameToken.Type, NameToken.Pages }, { NameToken.Kids, new ArrayToken(pageReferences) }, { NameToken.Count, new NumericToken(pageReferences.Count) } }; var pagesDictionary = new DictionaryToken(pagesDictionaryData); var pagesRef = context.WriteObject(memory, pagesDictionary, reserved); var catalogDictionary = new Dictionary <NameToken, IToken> { { NameToken.Type, NameToken.Catalog }, { NameToken.Pages, new IndirectReferenceToken(pagesRef.Number) } }; if (ArchiveStandard != PdfAStandard.None) { Func <IToken, ObjectToken> writerFunc = x => context.WriteObject(memory, x); PdfABaselineRuleBuilder.Obey(catalogDictionary, writerFunc, DocumentInformation, ArchiveStandard); switch (ArchiveStandard) { case PdfAStandard.A1A: PdfA1ARuleBuilder.Obey(catalogDictionary); break; case PdfAStandard.A2B: break; case PdfAStandard.A2A: PdfA1ARuleBuilder.Obey(catalogDictionary); break; } } var catalog = new DictionaryToken(catalogDictionary); var catalogRef = context.WriteObject(memory, catalog); var informationReference = default(IndirectReference?); if (IncludeDocumentInformation) { var informationDictionary = DocumentInformation.ToDictionary(); if (informationDictionary.Count > 0) { var dictionary = new DictionaryToken(informationDictionary); informationReference = context.WriteObject(memory, dictionary).Number; } } TokenWriter.WriteCrossReferenceTable(context.ObjectOffsets, catalogRef, memory, informationReference); return(memory.ToArray()); } }
public void CompletePdf(IndirectReferenceToken catalogReference, IndirectReferenceToken documentInformationReference = null) { TokenWriter.WriteCrossReferenceTable(offsets, catalogReference.Data, Stream, documentInformationReference?.Data); }
public byte[] Build() { var context = new BuilderContext(); var fontsWritten = new Dictionary <Guid, ObjectToken>(); using (var memory = new MemoryStream()) { // Header WriteString("%PDF-1.7", memory); // Body foreach (var font in fonts) { var fontObj = font.Value.FontProgram.WriteFont(font.Value.FontKey.Name, memory, context); fontsWritten.Add(font.Key, fontObj); } var resources = new Dictionary <NameToken, IToken> { { NameToken.ProcSet, new ArrayToken(new [] { NameToken.Create("PDF"), NameToken.Create("Text") }) } }; if (fontsWritten.Count > 0) { var fontsDictionary = new DictionaryToken(fontsWritten.Select(x => (fonts[x.Key].FontKey.Name, (IToken) new IndirectReferenceToken(x.Value.Number))) .ToDictionary(x => x.Item1, x => x.Item2)); var fontsDictionaryRef = context.WriteObject(memory, fontsDictionary); resources.Add(NameToken.Font, new IndirectReferenceToken(fontsDictionaryRef.Number)); } var pageReferences = new List <IndirectReferenceToken>(); foreach (var page in pages) { var pageDictionary = new Dictionary <NameToken, IToken> { { NameToken.Type, NameToken.Page }, { NameToken.Resources, new DictionaryToken(resources) }, { NameToken.MediaBox, RectangleToArray(page.Value.PageSize) } }; if (page.Value.Operations.Count > 0) { var contentStream = WriteContentStream(page.Value.Operations); var contentStreamObj = context.WriteObject(memory, contentStream); pageDictionary[NameToken.Contents] = new IndirectReferenceToken(contentStreamObj.Number); } var pageRef = context.WriteObject(memory, new DictionaryToken(pageDictionary)); pageReferences.Add(new IndirectReferenceToken(pageRef.Number)); } var pagesDictionary = new DictionaryToken(new Dictionary <NameToken, IToken> { { NameToken.Type, NameToken.Pages }, { NameToken.Kids, new ArrayToken(pageReferences) }, { NameToken.Count, new NumericToken(1) } }); var pagesRef = context.WriteObject(memory, pagesDictionary); var catalog = new DictionaryToken(new Dictionary <NameToken, IToken> { { NameToken.Type, NameToken.Catalog }, { NameToken.Pages, new IndirectReferenceToken(pagesRef.Number) } }); var catalogRef = context.WriteObject(memory, catalog); TokenWriter.WriteCrossReferenceTable(context.ObjectOffsets, catalogRef, memory); return(memory.ToArray()); } }
public byte[] Build() { var objectLocations = new Dictionary <IndirectReference, long>(); var fontsWritten = new Dictionary <Guid, ObjectToken>(); var number = 1; using (var memory = new MemoryStream()) { // Header WriteString("%PDF-1.7", memory); // Body foreach (var font in fonts) { var widths = new ArrayToken(new[] { new NumericToken(0), new NumericToken(255) }); var widthsObj = WriteObject(widths, memory, objectLocations, ref number); // TODO // var descriptorRef = new IndirectReference(number++, 0); var dictionary = new DictionaryToken(new Dictionary <IToken, IToken> { { NameToken.Type, NameToken.Font }, { NameToken.Subtype, NameToken.TrueType }, { NameToken.FirstChar, new NumericToken(0) }, { NameToken.LastChar, new NumericToken(255) }, { NameToken.Encoding, NameToken.WinAnsiEncoding }, { NameToken.Widths, widthsObj }, //{ NameToken.FontDesc, new IndirectReferenceToken(descriptorRef) } }); var fontObj = WriteObject(dictionary, memory, objectLocations, ref number); fontsWritten.Add(font.Key, fontObj); } var resources = new Dictionary <IToken, IToken> { { NameToken.ProcSet, new ArrayToken(new [] { NameToken.Create("PDF"), NameToken.Create("Text") }) } }; if (fontsWritten.Count > 0) { var fontsDictionary = new DictionaryToken(fontsWritten.Select(x => ((IToken)fonts[x.Key].FontKey.Name, (IToken) new IndirectReferenceToken(x.Value.Number))) .ToDictionary(x => x.Item1, x => x.Item2)); var fontsDictionaryRef = WriteObject(fontsDictionary, memory, objectLocations, ref number); resources.Add(NameToken.Font, new IndirectReferenceToken(fontsDictionaryRef.Number)); } var page = new DictionaryToken(new Dictionary <IToken, IToken> { { NameToken.Type, NameToken.Page }, { NameToken.Resources, new DictionaryToken(resources) }, { NameToken.MediaBox, RectangleToArray(pages[1].PageSize) } }); var pageRef = WriteObject(page, memory, objectLocations, ref number); var pagesDictionary = new DictionaryToken(new Dictionary <IToken, IToken> { { NameToken.Type, NameToken.Pages }, { NameToken.Kids, new ArrayToken(new [] { new IndirectReferenceToken(pageRef.Number) }) }, { NameToken.Count, new NumericToken(1) } }); var pagesRef = WriteObject(pagesDictionary, memory, objectLocations, ref number); var catalog = new DictionaryToken(new Dictionary <IToken, IToken> { { NameToken.Type, NameToken.Catalog }, { NameToken.Pages, new IndirectReferenceToken(pagesRef.Number) } }); var catalogRef = WriteObject(catalog, memory, objectLocations, ref number); TokenWriter.WriteCrossReferenceTable(objectLocations, catalogRef, memory); return(memory.ToArray()); } }