/// <summary> /// Initializes a new instance of the <see cref="PdfTrailer"/> class from a <see cref="PdfCrossReferenceStream"/>. /// </summary> public PdfTrailer(PdfCrossReferenceStream trailer) : base(trailer._document) { _document = trailer._document; // /ID [<09F877EBF282E9408ED1882A9A21D9F2><2A4938E896006F499AC1C2EA7BFB08E4>] // /Info 7 0 R // /Root 1 0 R // /Size 10 PdfReference iref = trailer.Elements.GetReference(Keys.Info); if (iref != null) { Elements.SetReference(Keys.Info, iref); } Elements.SetReference(Keys.Root, trailer.Elements.GetReference(Keys.Root)); Elements.SetInteger(Keys.Size, trailer.Elements.GetInteger(Keys.Size)); PdfArray id = trailer.Elements.GetArray(Keys.ID); if (id != null) { Elements.SetValue(Keys.ID, id); } }
/// <summary> /// Initializes a new instance of the <see cref="PdfTrailer"/> class from a <see cref="PdfCrossReferenceStream"/>. /// </summary> public PdfTrailer(PdfCrossReferenceStream trailer) : base(trailer._document) { _document = trailer._document; // /ID [<09F877EBF282E9408ED1882A9A21D9F2><2A4938E896006F499AC1C2EA7BFB08E4>] // /Info 7 0 R // /Root 1 0 R // /Size 10 PdfReference iref = trailer.Elements.GetReference(Keys.Info); if (iref != null) Elements.SetReference(Keys.Info, iref); Elements.SetReference(Keys.Root, trailer.Elements.GetReference(Keys.Root)); Elements.SetInteger(Keys.Size, trailer.Elements.GetInteger(Keys.Size)); PdfArray id = trailer.Elements.GetArray(Keys.ID); if (id != null) Elements.SetValue(Keys.ID, id); }
/// <summary> /// Reads cross reference stream(s). /// </summary> private PdfTrailer ReadXRefStream(PdfCrossReferenceTable xrefTable) { // Read cross reference stream. //Debug.Assert(_lexer.Symbol == Symbol.Integer); int number = _lexer.TokenToInteger; int generation = ReadInteger(); Debug.Assert(generation == 0); ReadSymbol(Symbol.Obj); ReadSymbol(Symbol.BeginDictionary); PdfObjectID objectID = new PdfObjectID(number, generation); PdfCrossReferenceStream xrefStream = new PdfCrossReferenceStream(_document); ReadDictionary(xrefStream, false); ReadSymbol(Symbol.BeginStream); ReadStream(xrefStream); //xrefTable.Add(new PdfReference(objectID, position)); PdfReference iref = new PdfReference(xrefStream); iref.ObjectID = objectID; iref.Value = xrefStream; xrefTable.Add(iref); Debug.Assert(xrefStream.Stream != null); //string sValue = new RawEncoding().GetString(xrefStream.Stream.UnfilteredValue,); //sValue.GetType(); byte[] bytesRaw = xrefStream.Stream.UnfilteredValue; byte[] bytes = bytesRaw; // HACK: Should be done in UnfilteredValue. if (xrefStream.Stream.HasDecodeParams) { int predictor = xrefStream.Stream.DecodePredictor; int columns = xrefStream.Stream.DecodeColumns; bytes = DecodeCrossReferenceStream(bytesRaw, columns, predictor); } #if DEBUG_ for (int idx = 0; idx < bytes.Length; idx++) { if (idx % 4 == 0) Console.WriteLine(); Console.Write("{0:000} ", (int)bytes[idx]); } Console.WriteLine(); #endif // bytes.GetType(); // Add to table. // xrefTable.Add(new PdfReference(objectID, -1)); int size = xrefStream.Elements.GetInteger(PdfCrossReferenceStream.Keys.Size); PdfArray index = xrefStream.Elements.GetValue(PdfCrossReferenceStream.Keys.Index) as PdfArray; int prev = xrefStream.Elements.GetInteger(PdfCrossReferenceStream.Keys.Prev); PdfArray w = (PdfArray)xrefStream.Elements.GetValue(PdfCrossReferenceStream.Keys.W); // E.g.: W[1 2 1] ¤ Index[7 12] ¤ Size 19 // Setup subsections. int subsectionCount; int[][] subsections = null; int subsectionEntryCount = 0; if (index == null) { // Setup with default values. subsectionCount = 1; subsections = new int[subsectionCount][]; subsections[0] = new int[] { 0, size }; // HACK: What is size? Contratiction in PDF reference. subsectionEntryCount = size; } else { // Read subsections from array. Debug.Assert(index.Elements.Count % 2 == 0); subsectionCount = index.Elements.Count / 2; subsections = new int[subsectionCount][]; for (int idx = 0; idx < subsectionCount; idx++) { subsections[idx] = new int[] { index.Elements.GetInteger(2 * idx), index.Elements.GetInteger(2 * idx + 1) }; subsectionEntryCount += subsections[idx][1]; } } // W key. Debug.Assert(w.Elements.Count == 3); int[] wsize = { w.Elements.GetInteger(0), w.Elements.GetInteger(1), w.Elements.GetInteger(2) }; int wsum = StreamHelper.WSize(wsize); if (wsum * subsectionEntryCount != bytes.Length) GetType(); Debug.Assert(wsum * subsectionEntryCount == bytes.Length, "Check implementation here."); int testcount = subsections[0][1]; int[] currentSubsection = subsections[0]; #if DEBUG && CORE if (PdfDiagnostics.TraceXrefStreams) { for (int idx = 0; idx < testcount; idx++) { uint field1 = StreamHelper.ReadBytes(bytes, idx * wsum, wsize[0]); uint field2 = StreamHelper.ReadBytes(bytes, idx * wsum + wsize[0], wsize[1]); uint field3 = StreamHelper.ReadBytes(bytes, idx * wsum + wsize[0] + wsize[1], wsize[2]); string res = String.Format("{0,2:00}: {1} {2,5} {3} // ", idx, field1, field2, field3); switch (field1) { case 0: res += "Fee list: object number, generation number"; break; case 1: res += "Not compresed: offset, generation number"; break; case 2: res += "Compressed: object stream object number, index in stream"; break; default: res += "??? Type undefined"; break; } Debug.WriteLine(res); } } #endif int index2 = -1; for (int ssc = 0; ssc < subsectionCount; ssc++) { int abc = subsections[ssc][1]; for (int idx = 0; idx < abc; idx++) { index2++; PdfCrossReferenceStream.CrossReferenceStreamEntry item = new PdfCrossReferenceStream.CrossReferenceStreamEntry(); item.Type = StreamHelper.ReadBytes(bytes, index2 * wsum, wsize[0]); item.Field2 = StreamHelper.ReadBytes(bytes, index2 * wsum + wsize[0], wsize[1]); item.Field3 = StreamHelper.ReadBytes(bytes, index2 * wsum + wsize[0] + wsize[1], wsize[2]); xrefStream.Entries.Add(item); switch (item.Type) { case 0: // Nothing to do, not needed. break; case 1: // offset / generation number //// Even it is restricted, an object can exists in more than one subsection. //// (PDF Reference Implementation Notes 15). int position = (int)item.Field2; objectID = ReadObjectNumber(position); #if DEBUG if (objectID.ObjectNumber == 1074) GetType(); #endif Debug.Assert(objectID.GenerationNumber == item.Field3); //// Ignore the latter one. if (!xrefTable.Contains(objectID)) { #if DEBUG GetType(); #endif // Add iref for all uncrompressed objects. xrefTable.Add(new PdfReference(objectID, position)); } break; case 2: // Nothing to do yet. break; } } } return xrefStream; }