示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#4
0
        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);
        }
示例#5
0
        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);
        }
示例#6
0
        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);
        }
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#9
0
            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);
            }
示例#10
0
        /// <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());
            }
        }
示例#11
0
        /// <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());
            }
        }
示例#12
0
 public void CompletePdf(IndirectReferenceToken catalogReference, IndirectReferenceToken documentInformationReference = null)
 {
     TokenWriter.WriteCrossReferenceTable(offsets, catalogReference.Data, Stream, documentInformationReference?.Data);
 }
示例#13
0
        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());
            }
        }
示例#14
0
        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());
            }
        }