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()); } }