/// <summary>Writes cross reference table and trailer to PDF.</summary>
        /// <param name="document">
        /// is the current
        /// <see cref="PdfDocument">document</see>
        /// </param>
        /// <param name="fileId">field id</param>
        /// <param name="crypto">pdf encryption</param>
        protected internal virtual void WriteXrefTableAndTrailer(PdfDocument document, PdfObject fileId, PdfObject
                                                                 crypto)
        {
            PdfWriter writer = document.GetWriter();

            if (!document.properties.appendMode)
            {
                for (int i = count; i > 0; --i)
                {
                    PdfIndirectReference lastRef = xref[i];
                    if (lastRef == null || lastRef.IsFree())
                    {
                        RemoveFreeRefFromList(i);
                        --count;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            PdfStream xrefStream = null;

            if (writer.IsFullCompression())
            {
                xrefStream = new PdfStream();
                xrefStream.MakeIndirect(document);
            }
            IList <int> sections          = CreateSections(document, false);
            bool        noModifiedObjects = (sections.Count == 0) || (xrefStream != null && sections.Count == 2 && sections[0
                                                                      ] == count && sections[1] == 1);

            if (document.properties.appendMode && noModifiedObjects)
            {
                // No modifications in document
                xref = null;
                return;
            }
            document.CheckIsoConformance(this, IsoKey.XREF_TABLE);
            long startxref  = writer.GetCurrentPos();
            long xRefStmPos = -1;

            if (xrefStream != null)
            {
                xrefStream.Put(PdfName.Type, PdfName.XRef);
                xrefStream.Put(PdfName.ID, fileId);
                if (crypto != null)
                {
                    xrefStream.Put(PdfName.Encrypt, crypto);
                }
                xrefStream.Put(PdfName.Size, new PdfNumber(this.Size()));
                int offsetSize = GetOffsetSize(Math.Max(startxref, Size()));
                xrefStream.Put(PdfName.W, new PdfArray(JavaUtil.ArraysAsList((PdfObject) new PdfNumber(1), new PdfNumber(offsetSize
                                                                                                                         ), new PdfNumber(2))));
                xrefStream.Put(PdfName.Info, document.GetDocumentInfo().GetPdfObject());
                xrefStream.Put(PdfName.Root, document.GetCatalog().GetPdfObject());
                PdfArray index = new PdfArray();
                foreach (int?section in sections)
                {
                    index.Add(new PdfNumber((int)section));
                }
                if (document.properties.appendMode && !document.reader.hybridXref)
                {
                    // "not meaningful in hybrid-reference files"
                    PdfNumber lastXref = new PdfNumber(document.reader.GetLastXref());
                    xrefStream.Put(PdfName.Prev, lastXref);
                }
                xrefStream.Put(PdfName.Index, index);
                xrefStream.GetIndirectReference().SetOffset(startxref);
                iText.Kernel.Pdf.PdfXrefTable xrefTable = document.GetXref();
                for (int k = 0; k < sections.Count; k += 2)
                {
                    int first = (int)sections[k];
                    int len   = (int)sections[k + 1];
                    for (int i = first; i < first + len; i++)
                    {
                        PdfIndirectReference reference = xrefTable.Get(i);
                        if (reference.IsFree())
                        {
                            xrefStream.GetOutputStream().Write(0);
                            xrefStream.GetOutputStream().Write(reference.GetOffset(), offsetSize);
                            xrefStream.GetOutputStream().Write(reference.GetGenNumber(), 2);
                        }
                        else
                        {
                            if (reference.GetObjStreamNumber() == 0)
                            {
                                xrefStream.GetOutputStream().Write(1);
                                xrefStream.GetOutputStream().Write(reference.GetOffset(), offsetSize);
                                xrefStream.GetOutputStream().Write(reference.GetGenNumber(), 2);
                            }
                            else
                            {
                                xrefStream.GetOutputStream().Write(2);
                                xrefStream.GetOutputStream().Write(reference.GetObjStreamNumber(), offsetSize);
                                xrefStream.GetOutputStream().Write(reference.GetIndex(), 2);
                            }
                        }
                    }
                }
                xrefStream.Flush();
                xRefStmPos = startxref;
            }
            // For documents with hybrid cross-reference table, i.e. containing xref streams as well as regular xref sections,
            // we write additional regular xref section at the end of the document because the /Prev reference from
            // xref stream to a regular xref section doesn't seem to be valid
            bool needsRegularXref = !writer.IsFullCompression() || (document.properties.appendMode && document.reader.
                                                                    hybridXref);

            if (needsRegularXref)
            {
                startxref = writer.GetCurrentPos();
                writer.WriteString("xref\n");
                iText.Kernel.Pdf.PdfXrefTable xrefTable = document.GetXref();
                if (xRefStmPos != -1)
                {
                    // Get rid of all objects from object stream. This is done for hybrid documents
                    sections = CreateSections(document, true);
                }
                for (int k = 0; k < sections.Count; k += 2)
                {
                    int first = (int)sections[k];
                    int len   = (int)sections[k + 1];
                    writer.WriteInteger(first).WriteSpace().WriteInteger(len).WriteByte((byte)'\n');
                    for (int i = first; i < first + len; i++)
                    {
                        PdfIndirectReference reference = xrefTable.Get(i);
                        StringBuilder        off       = new StringBuilder("0000000000").Append(reference.GetOffset());
                        StringBuilder        gen       = new StringBuilder("00000").Append(reference.GetGenNumber());
                        writer.WriteString(off.JSubstring(off.Length - 10, off.Length)).WriteSpace().WriteString(gen.JSubstring(gen
                                                                                                                                .Length - 5, gen.Length)).WriteSpace();
                        if (reference.IsFree())
                        {
                            writer.WriteBytes(freeXRefEntry);
                        }
                        else
                        {
                            writer.WriteBytes(inUseXRefEntry);
                        }
                    }
                }
                PdfDictionary trailer = document.GetTrailer();
                // Remove all unused keys in case stamp mode in case original file has full compression, but destination file has not.
                trailer.Remove(PdfName.W);
                trailer.Remove(PdfName.Index);
                trailer.Remove(PdfName.Type);
                trailer.Remove(PdfName.Length);
                trailer.Put(PdfName.Size, new PdfNumber(this.Size()));
                trailer.Put(PdfName.ID, fileId);
                if (xRefStmPos != -1)
                {
                    trailer.Put(PdfName.XRefStm, new PdfNumber(xRefStmPos));
                }
                if (crypto != null)
                {
                    trailer.Put(PdfName.Encrypt, crypto);
                }
                writer.WriteString("trailer\n");
                if (document.properties.appendMode)
                {
                    PdfNumber lastXref = new PdfNumber(document.reader.GetLastXref());
                    trailer.Put(PdfName.Prev, lastXref);
                }
                writer.Write(document.GetTrailer());
                writer.Write('\n');
            }
            WriteKeyInfo(document);
            writer.WriteString("startxref\n").WriteLong(startxref).WriteString("\n%%EOF\n");
            xref = null;
            freeReferencesLinkedList.Clear();
        }
Example #2
0
 /// <summary>Create instance of document outline.</summary>
 /// <param name="title">the text that shall be displayed on the screen for this item.</param>
 /// <param name="content">Outline dictionary</param>
 /// <param name="pdfDocument">
 ///
 /// <see cref="PdfDocument"/>
 /// the outline belongs to.
 /// </param>
 internal PdfOutline(String title, PdfDictionary content, PdfDocument pdfDocument)
 {
     this.title   = title;
     this.content = content;
     this.pdfDoc  = pdfDocument;
 }
 public abstract byte[] Decode(byte[] arg1, PdfName arg2, PdfObject arg3, PdfDictionary arg4);
Example #4
0
        public virtual PdfDictionary BuildTree()
        {
            int?[] numbers = new int?[items.Count];
            numbers = items.Keys.ToArray(numbers);
            JavaUtil.Sort(numbers);
            if (numbers.Length <= NODE_SIZE)
            {
                PdfDictionary dic = new PdfDictionary();
                PdfArray      ar  = new PdfArray();
                for (int k = 0; k < numbers.Length; ++k)
                {
                    ar.Add(new PdfNumber((int)numbers[k]));
                    ar.Add(items.Get(numbers[k]));
                }
                dic.Put(PdfName.Nums, ar);
                return(dic);
            }
            int skip = NODE_SIZE;

            PdfDictionary[] kids = new PdfDictionary[(numbers.Length + NODE_SIZE - 1) / NODE_SIZE];
            for (int i = 0; i < kids.Length; ++i)
            {
                int           offset = i * NODE_SIZE;
                int           end    = Math.Min(offset + NODE_SIZE, numbers.Length);
                PdfDictionary dic    = new PdfDictionary();
                PdfArray      arr    = new PdfArray();
                arr.Add(new PdfNumber((int)numbers[offset]));
                arr.Add(new PdfNumber((int)numbers[end - 1]));
                dic.Put(PdfName.Limits, arr);
                arr = new PdfArray();
                for (; offset < end; ++offset)
                {
                    arr.Add(new PdfNumber((int)numbers[offset]));
                    arr.Add(items.Get(numbers[offset]));
                }
                dic.Put(PdfName.Nums, arr);
                dic.MakeIndirect(catalog.GetDocument());
                kids[i] = dic;
            }
            int top = kids.Length;

            while (true)
            {
                if (top <= NODE_SIZE)
                {
                    PdfArray arr = new PdfArray();
                    for (int k = 0; k < top; ++k)
                    {
                        arr.Add(kids[k]);
                    }
                    PdfDictionary dic = new PdfDictionary();
                    dic.Put(PdfName.Kids, arr);
                    return(dic);
                }
                skip *= NODE_SIZE;
                int tt = (numbers.Length + skip - 1) / skip;
                for (int k = 0; k < tt; ++k)
                {
                    int           offset = k * NODE_SIZE;
                    int           end    = Math.Min(offset + NODE_SIZE, top);
                    PdfDictionary dic    = (PdfDictionary) new PdfDictionary().MakeIndirect(catalog.GetDocument());
                    PdfArray      arr    = new PdfArray();
                    arr.Add(new PdfNumber((int)numbers[k * skip]));
                    arr.Add(new PdfNumber((int)numbers[Math.Min((k + 1) * skip, numbers.Length) - 1]));
                    dic.Put(PdfName.Limits, arr);
                    arr = new PdfArray();
                    for (; offset < end; ++offset)
                    {
                        arr.Add(kids[offset]);
                    }
                    dic.Put(PdfName.Kids, arr);
                    kids[k] = dic;
                }
                top = tt;
            }
        }
        public virtual void TestPdfNamesFetching()
        {
            byte[][] namesBytes = new byte[][] { new byte[] { 35, 67, 51, 35, 57, 67, 98, 101, 114, 115, 99, 104, 114,
                                                              105, 102, 116, 95, 49 }, new byte[] { 35, 67, 51, 35, 57, 67, 98, 101, 114, 115, 99, 104, 114, 105, 102
                                                                                                    , 116, 95, 50 }, new byte[] { 65, 114, 116, 105, 99, 108, 101 }, new byte[] { 66, 105, 108, 100, 117,
                                                                                                                                                                                  110, 116, 101, 114, 115, 99, 104, 114, 105, 102, 116 }, new byte[] { 78, 111, 114, 109, 97, 108, 80, 97
                                                                                                                                                                                                                                                       , 114, 97, 103, 114, 97, 112, 104, 83, 116, 121, 108, 101 }, new byte[] { 83, 116, 111, 114, 121 }, new
                                                 byte[] { 84, 79, 67, 45, 49 }, new byte[] { 84, 79, 67, 45, 50, 45, 50 }, new byte[] { 84, 79, 67, 45,
                                                                                                                                        72, 101, 97, 100 }, new byte[] { 84, 97, 98, 101, 108, 108, 101 }, new byte[] { 84, 97, 98, 101, 108,
                                                                                                                                                                                                                        108, 101, 95, 72, 101, 97, 100 }, new byte[] { 84, 97, 98, 101, 108, 108, 101, 95, 102, 101, 116, 116 }
                                                 , new byte[] { 84, 101, 120, 116, 95, 73, 78, 70, 79 }, new byte[] { 84, 101, 120, 116, 95, 73, 110, 102
                                                                                                                      , 111, 95, 72, 101, 97, 100 }, new byte[] { 84, 101, 120, 116, 107, 35, 67, 51, 35, 66, 54, 114, 112,
                                                                                                                                                                  101, 114 }, new byte[] { 84, 101, 120, 116, 107, 35, 67, 51, 35, 66, 54, 114, 112, 101, 114, 45, 69, 114
                                                                                                                                                                                           , 115, 116, 122, 101, 105, 108, 101 }, new byte[] { 84, 101, 120, 116, 107, 35, 67, 51, 35, 66, 54, 114
                                                                                                                                                                                                                                               , 112, 101, 114, 95, 66, 97, 99, 107 }, new byte[] { 95, 78, 111, 95, 112, 97, 114, 97, 103, 114, 97,
                                                                                                                                                                                                                                                                                                    112, 104, 95, 115, 116, 121, 108, 101, 95 } };
            // /#C3#9Cberschrift_1
            // /#C3#9Cberschrift_2
            // /Article
            // /Bildunterschrift
            // /NormalParagraphStyle
            // /Story
            // /TOC-1
            // /TOC-2-2
            // /TOC-Head
            // /Tabelle
            // /Tabelle_Head
            // /Tabelle_fett
            // /Text_INFO
            // /Text_Info_Head
            // /Textk#C3#B6rper
            // /Textk#C3#B6rper-Erstzeile
            // /Textk#C3#B6rper_Back
            // /_No_paragraph_style_
            bool[] haveValue = new bool[] { true, true, false, true, true, true, false, false, false, false, false, false
                                            , false, false, false, false, false, false };
            IList <PdfName> names = new List <PdfName>();

            for (int i = 0; i < namesBytes.Length; i++)
            {
                byte[]  b = namesBytes[i];
                PdfName n = new PdfName(b);
                names.Add(n);
                if (haveValue[i])
                {
                    n.GenerateValue();
                }
            }
            PdfDictionary dict = new PdfDictionary();

            foreach (PdfName name in names)
            {
                dict.Put(name, new PdfName("dummy"));
            }
            PdfName expectedToContain = new PdfName("Article");
            bool    found             = false;

            foreach (PdfName pdfName in dict.KeySet())
            {
                found = pdfName.Equals(expectedToContain);
                if (found)
                {
                    break;
                }
            }
            NUnit.Framework.Assert.IsTrue(found);
            NUnit.Framework.Assert.IsTrue(dict.ContainsKey(expectedToContain));
        }