/// <summary> /// Adds a cross reference entry to the table. Used when parsing the trailer. /// </summary> public void Add(PdfReference iref) { if (iref.ObjectID.IsEmpty) iref.ObjectID = new PdfObjectID(GetNewObjectNumber()); if (this.objectTable.ContainsKey(iref.ObjectID)) throw new InvalidOperationException("Object already in table."); this.objectTable.Add(iref.ObjectID, iref); }
/// <summary> /// Adds a cross reference entry to the table. Used when parsing the trailer. /// </summary> public void Add(PdfReference iref) { #if DEBUG if (iref.ObjectID.ObjectNumber == 948) GetType(); #endif if (iref.ObjectID.IsEmpty) iref.ObjectID = new PdfObjectID(GetNewObjectNumber()); if (ObjectTable.ContainsKey(iref.ObjectID)) throw new InvalidOperationException("Object already in table."); ObjectTable.Add(iref.ObjectID, iref); }
/// <summary> /// Calculates the transitive closure of the specified PdfObject with the specified depth, i.e. all indirect objects /// recursively reachable from the specified object in up to maximally depth steps. /// </summary> public PdfReference[] TransitiveClosure(PdfObject pdfObject, int depth) { CheckConsistence(); Dictionary<PdfItem, object> objects = new Dictionary<PdfItem, object>(); this.overflow = new Dictionary<PdfItem, object>(); TransitiveClosureImplementation(objects, pdfObject, ref depth); TryAgain: if (this.overflow.Count > 0) { PdfObject[] array = new PdfObject[this.overflow.Count]; this.overflow.Keys.CopyTo(array, 0); this.overflow = new Dictionary<PdfItem, object>(); for (int idx = 0; idx < array.Length; idx++) { //PdfObject o = array[idx]; //o.GetType(); PdfObject obj = array[idx]; //if (!objects.Contains(obj)) // objects.Add(obj, null); TransitiveClosureImplementation(objects, obj, ref depth); } goto TryAgain; } CheckConsistence(); ICollection collection = objects.Keys; int count = collection.Count; PdfReference[] irefs = new PdfReference[count]; collection.CopyTo(irefs, 0); #if true_ for (int i = 0; i < count; i++) for (int j = 0; j < count; j++) if (i != j) { Debug.Assert(Object.ReferenceEquals(irefs[i].Document, this.document)); Debug.Assert(irefs[i] != irefs[j]); Debug.Assert(!Object.ReferenceEquals(irefs[i], irefs[j])); Debug.Assert(!Object.ReferenceEquals(irefs[i].Value, irefs[j].Value)); Debug.Assert(!Object.ReferenceEquals(irefs[i].ObjectID, irefs[j].Value.ObjectID)); Debug.Assert(irefs[i].ObjectNumber != irefs[j].Value.ObjectNumber); Debug.Assert(Object.ReferenceEquals(irefs[i].Document, irefs[j].Document)); GetType(); } #endif return irefs; }
/// <summary> /// Recursively converts the page tree into a flat array. /// </summary> PdfDictionary[] GetKids(PdfReference iref, PdfPage.InheritedValues values, PdfDictionary parent) { // TODO: inherit inheritable keys... PdfDictionary kid = (PdfDictionary)iref.Value; if (kid.Elements.GetName(Keys.Type) == "/Page") { PdfPage.InheritValues(kid, values); return new PdfDictionary[] { kid }; } else { Debug.Assert(kid.Elements.GetName(Keys.Type) == "/Pages"); PdfPage.InheritValues(kid, ref values); ArrayList list = new ArrayList(); PdfArray kids = kid.Elements["/Kids"] as PdfArray; foreach (PdfReference xref2 in kids) list.AddRange(GetKids(xref2, values, kid)); int count = list.Count; Debug.Assert(count == kid.Elements.GetInteger("/Count")); return (PdfDictionary[])list.ToArray(typeof(PdfDictionary)); } }
/// <summary> /// Retrieves the raw data for the colorspace. /// </summary> /// <returns>The raw data from the PdfArray of PdfReference.</returns> protected virtual IEnumerable<byte> GetRawPalette(PdfReference reference) { if (reference == null) throw new ArgumentNullException("reference", "The reference index was null."); var value = (reference.Value as PdfDictionary); if (value == null) return(new byte[0]); return (value.Stream.UnfilteredValue); }
public void CheckConsistence() { Dictionary<PdfReference, object> ht1 = new Dictionary<PdfReference, object>(); foreach (PdfReference iref in this.objectTable.Values) { Debug.Assert(!ht1.ContainsKey(iref), "Duplicate iref."); Debug.Assert(iref.Value != null); ht1.Add(iref, null); } Dictionary<PdfObjectID, object> ht2 = new Dictionary<PdfObjectID, object>(); foreach (PdfReference iref in this.objectTable.Values) { Debug.Assert(!ht2.ContainsKey(iref.ObjectID), "Duplicate iref."); ht2.Add(iref.ObjectID, null); } ICollection collection = this.objectTable.Values; int count = collection.Count; PdfReference[] irefs = new PdfReference[count]; collection.CopyTo(irefs, 0); #if true_ for (int i = 0; i < count; i++) for (int j = 0; j < count; j++) if (i != j) { Debug.Assert(Object.ReferenceEquals(irefs[i].Document, this.document)); Debug.Assert(irefs[i] != irefs[j]); Debug.Assert(!Object.ReferenceEquals(irefs[i], irefs[j])); Debug.Assert(!Object.ReferenceEquals(irefs[i].Value, irefs[j].Value)); Debug.Assert(!Object.ReferenceEquals(irefs[i].ObjectID, irefs[j].Value.ObjectID)); Debug.Assert(irefs[i].ObjectNumber != irefs[j].Value.ObjectNumber); Debug.Assert(Object.ReferenceEquals(irefs[i].Document, irefs[j].Document)); GetType(); } #endif }
/// <summary> /// Parses whatever comes until the specified stop symbol is reached. /// </summary> void ParseObject(Symbol stop) { #if DEBUG_ ParseObjectCounter++; Debug.WriteLine(ParseObjectCounter.ToString()); if (ParseObjectCounter == 178) GetType(); #endif Symbol symbol; while ((symbol = ScanNextToken()) != Symbol.Eof) { if (symbol == stop) return; switch (symbol) { case Symbol.Comment: // ignore comments break; case Symbol.Null: this.stack.Shift(PdfNull.Value); break; case Symbol.Boolean: this.stack.Shift(new PdfBoolean(this.lexer.TokenToBoolean)); break; case Symbol.Integer: this.stack.Shift(new PdfInteger(this.lexer.TokenToInteger)); break; case Symbol.UInteger: this.stack.Shift(new PdfUInteger(this.lexer.TokenToUInteger)); break; case Symbol.Real: this.stack.Shift(new PdfReal(this.lexer.TokenToReal)); break; case Symbol.String: //this.stack.Shift(new PdfString(this.lexer.Token, PdfStringFlags.PDFDocEncoding)); this.stack.Shift(new PdfString(this.lexer.Token, PdfStringFlags.RawEncoding)); break; case Symbol.UnicodeString: this.stack.Shift(new PdfString(this.lexer.Token, PdfStringFlags.Unicode)); break; case Symbol.HexString: this.stack.Shift(new PdfString(this.lexer.Token, PdfStringFlags.HexLiteral)); break; case Symbol.UnicodeHexString: this.stack.Shift(new PdfString(this.lexer.Token, PdfStringFlags.Unicode | PdfStringFlags.HexLiteral)); break; case Symbol.Name: this.stack.Shift(new PdfName(this.lexer.Token)); break; case Symbol.R: { Debug.Assert(this.stack.GetItem(-1) is PdfInteger && this.stack.GetItem(-2) is PdfInteger); PdfObjectID objectID = new PdfObjectID(this.stack.GetInteger(-2), this.stack.GetInteger(-1)); PdfReference iref = this.document.irefTable[objectID]; if (iref == null) { // If a document has more than one PdfXRefTable it is possible that the first trailer has // indirect references to objects whos iref entry is not yet read in. if (this.document.irefTable.IsUnderConstruction) { // XRefTable not complete when trailer is read. Create temporary irefs that are // removed later in PdfTrailer.FixXRefs. iref = new PdfReference(objectID, 0); this.stack.Reduce(iref, 2); break; } // PDF Reference section 3.2.9: // An indirect reference to an undefined object is not an error; // it is simply treated as a reference to the null object. this.stack.Reduce(PdfNull.Value, 2); // Let's see what null objects are good for... //Debug.Assert(false, "Null object detected!"); //this.stack.Reduce(PdfNull.Value, 2); } else this.stack.Reduce(iref, 2); break; } case Symbol.BeginArray: PdfArray array = new PdfArray(this.document); ReadArray(array, false); this.stack.Shift(array); break; case Symbol.BeginDictionary: PdfDictionary dict = new PdfDictionary(this.document); ReadDictionary(dict, false); this.stack.Shift(dict); break; case Symbol.BeginStream: throw new NotImplementedException(); default: string error = this.lexer.Token; Debug.Assert(false, "Unexpected: " + error); break; } } throw new PdfReaderException("Unexpected end of file."); }
PdfItem ReadReference(PdfReference iref, bool includeReferences) { throw new NotImplementedException("ReadReference"); }
public void Remove(PdfReference iref) { ObjectTable.Remove(iref.ObjectID); }
/// <summary> /// Recursively converts the page tree into a flat array. /// </summary> PdfDictionary[] GetKids(PdfReference iref, PdfPage.InheritedValues values, PdfDictionary parent) { // TODO: inherit inheritable keys... PdfDictionary kid = (PdfDictionary)iref.Value; if (kid.Elements.GetName(Keys.Type) == "/Page") { PdfPage.InheritValues(kid, values); return new PdfDictionary[] { kid }; } else { Debug.Assert(kid.Elements.GetName(Keys.Type) == "/Pages"); PdfPage.InheritValues(kid, ref values); List<PdfDictionary> list = new List<PdfDictionary>(); PdfArray kids = kid.Elements["/Kids"] as PdfArray; //newTHHO 15.10.2007 begin if (kids == null) { PdfReference xref3 = kid.Elements["/Kids"] as PdfReference; kids = xref3.Value as PdfArray; } //newTHHO 15.10.2007 end foreach (PdfReference xref2 in kids) list.AddRange(GetKids(xref2, values, kid)); int count = list.Count; Debug.Assert(count == kid.Elements.GetInteger("/Count")); //return (PdfDictionary[])list.ToArray(typeof(PdfDictionary)); return list.ToArray(); } }
/// <summary> /// Adds a cloned object to this table. /// </summary> /// <param name="externalID">The object identifier in the forein object.</param> /// <param name="iref">The cross reference to the clone of the forein object, which belongs to /// this document. In general the clone has a different object identifier.</param> public void Add(PdfObjectID externalID, PdfReference iref) { this.externalIDs[externalID.ToString()] = iref; }
public void Remove(PdfReference iref) { this.objectTable.Remove(iref.ObjectID); }
/// <summary> /// Reads the compressed object with the specified index in the object stream /// of the object with the specified object id. /// </summary> internal PdfReference ReadCompressedObject(PdfObjectID objectID, int index) { PdfReference iref; #if true Debug.Assert(_document._irefTable.ObjectTable.ContainsKey(objectID)); if (!_document._irefTable.ObjectTable.TryGetValue(objectID, out iref)) { throw new NotImplementedException("This case is not coded or something else went wrong"); } #else // We should never come here because the object stream must be a type 1 entry in the xref stream // and iref was created before. // Has the specified object already an iref in the object table? if (!_document._irefTable.ObjectTable.TryGetValue(objectID, out iref)) { try { #if true_ iref = new PdfReference(objectID,); iref.ObjectID = objectID; _document._irefTable.Add(os); #else PdfDictionary dict = (PdfDictionary)ReadObject(null, objectID, false, false); PdfObjectStream os = new PdfObjectStream(dict); iref = new PdfReference(os); iref.ObjectID = objectID; _document._irefTable.Add(os); #endif } catch (Exception ex) { Debug.WriteLine(ex.Message); throw; } } #endif // Read in object stream object when we come here for the very first time. if (iref.Value == null) { try { Debug.Assert(_document._irefTable.Contains(iref.ObjectID)); PdfDictionary pdfObject = (PdfDictionary)ReadObject(null, iref.ObjectID, false, false); PdfObjectStream objectStream = new PdfObjectStream(pdfObject); Debug.Assert(objectStream.Reference == iref); // objectStream.Reference = iref; Superfluous, see Assert in line before. Debug.Assert(objectStream.Reference.Value != null, "Something went wrong."); } catch (Exception ex) { Debug.WriteLine(ex.Message); throw; } } Debug.Assert(iref.Value != null); PdfObjectStream objectStreamStream = iref.Value as PdfObjectStream; if (objectStreamStream == null) { Debug.Assert(((PdfDictionary)iref.Value).Elements.GetName("/Type") == "/ObjStm"); objectStreamStream = new PdfObjectStream((PdfDictionary)iref.Value); Debug.Assert(objectStreamStream.Reference == iref); // objectStream.Reference = iref; Superfluous, see Assert in line before. Debug.Assert(objectStreamStream.Reference.Value != null, "Something went wrong."); } Debug.Assert(objectStreamStream != null); //PdfObjectStream objectStreamStream = (PdfObjectStream)iref.Value; if (objectStreamStream == null) throw new Exception("Something went wrong here."); return objectStreamStream.ReadCompressedObject(index); }
/// <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; }
internal PdfFormXObject(PdfDocument thisDocument, PdfImportedObjectTable importedObjectTable, XPdfForm form) : base(thisDocument) { Debug.Assert(importedObjectTable != null); Debug.Assert(ReferenceEquals(thisDocument, importedObjectTable.Owner)); Elements.SetName(Keys.Type, "/XObject"); Elements.SetName(Keys.Subtype, "/Form"); if (form.IsTemplate) { Debug.Assert(importedObjectTable == null); // TODO more initialization here??? return; } XPdfForm pdfForm = form; // Get import page PdfPages importPages = importedObjectTable.ExternalDocument.Pages; if (pdfForm.PageNumber < 1 || pdfForm.PageNumber > importPages.Count) { PSSR.ImportPageNumberOutOfRange(pdfForm.PageNumber, importPages.Count, form._path); } PdfPage importPage = importPages[pdfForm.PageNumber - 1]; // Import resources PdfItem res = importPage.Elements["/Resources"]; if (res != null) // unlikely but possible { #if true // Get root object PdfObject root; if (res is PdfReference) { root = ((PdfReference)res).Value; } else { root = (PdfDictionary)res; } root = ImportClosure(importedObjectTable, thisDocument, root); // If the root was a direct object, make it indirect. if (root.Reference == null) { thisDocument._irefTable.Add(root); } Debug.Assert(root.Reference != null); Elements["/Resources"] = root.Reference; #else // Get transitive closure PdfObject[] resources = importPage.Owner.Internals.GetClosure(resourcesRoot); int count = resources.Length; #if DEBUG_ for (int idx = 0; idx < count; idx++) { Debug.Assert(resources[idx].XRef != null); Debug.Assert(resources[idx].XRef.Document != null); Debug.Assert(resources[idx].Document != null); if (resources[idx].ObjectID.ObjectNumber == 12) { GetType(); } } #endif // 1st step. Already imported objects are reused and new ones are cloned. for (int idx = 0; idx < count; idx++) { PdfObject obj = resources[idx]; if (importedObjectTable.Contains(obj.ObjectID)) { // external object was already imported PdfReference iref = importedObjectTable[obj.ObjectID]; Debug.Assert(iref != null); Debug.Assert(iref.Value != null); Debug.Assert(iref.Document == Owner); // replace external object by the already clone counterpart resources[idx] = iref.Value; } else { // External object was not imported earlier and must be cloned PdfObject clone = obj.Clone(); Debug.Assert(clone.Reference == null); clone.Document = Owner; if (obj.Reference != null) { // add it to this (the importer) document Owner.irefTable.Add(clone); Debug.Assert(clone.Reference != null); // save old object identifier importedObjectTable.Add(obj.ObjectID, clone.Reference); //Debug.WriteLine("Cloned: " + obj.ObjectID.ToString()); } else { // The root object (the /Resources value) is not an indirect object Debug.Assert(idx == 0); // add it to this (the importer) document Owner.irefTable.Add(clone); Debug.Assert(clone.Reference != null); } // replace external object by its clone resources[idx] = clone; } } #if DEBUG_ for (int idx = 0; idx < count; idx++) { Debug.Assert(resources[idx].XRef != null); Debug.Assert(resources[idx].XRef.Document != null); Debug.Assert(resources[idx].Document != null); if (resources[idx].ObjectID.ObjectNumber == 12) { GetType(); } } #endif // 2nd step. Fix up indirect references that still refers to the import document. for (int idx = 0; idx < count; idx++) { PdfObject obj = resources[idx]; Debug.Assert(obj.Owner != null); FixUpObject(importedObjectTable, importedObjectTable.Owner, obj); } // Set resources key to the root of the clones Elements["/Resources"] = resources[0].Reference; #endif } // Take /Rotate into account. PdfRectangle rect = importPage.Elements.GetRectangle(PdfPage.Keys.MediaBox); // Reduce rotation to 0, 90, 180, or 270. int rotate = (importPage.Elements.GetInteger(PdfPage.Keys.Rotate) % 360 + 360) % 360; //rotate = 0; if (rotate == 0) { // Set bounding box to media box. Elements["/BBox"] = rect; } else { // TODO: Have to adjust bounding box? (I think not, but I'm not sure -> wait for problem) Elements["/BBox"] = rect; // Rotate the image such that it is upright. XMatrix matrix = new XMatrix(); double width = rect.Width; double height = rect.Height; matrix.RotateAtPrepend(-rotate, new XPoint(width / 2, height / 2)); // Translate the image such that its center lies on the center of the rotated bounding box. double offset = (height - width) / 2; if (rotate == 90) { // TODO It seems we can simplify this as the sign of offset changes too. if (height > width) { matrix.TranslatePrepend(offset, offset); // Tested. } else { matrix.TranslatePrepend(offset, offset); // TODO Test case. } } else if (rotate == 270) { // TODO It seems we can simplify this as the sign of offset changes too. if (height > width) { matrix.TranslatePrepend(-offset, -offset); // Tested. } else { matrix.TranslatePrepend(-offset, -offset); // Tested. } } //string item = "[" + PdfEncoders.ToString(matrix) + "]"; //Elements[Keys.Matrix] = new PdfLiteral(item); Elements.SetMatrix(Keys.Matrix, matrix); } // Preserve filter because the content keeps unmodified. PdfContent content = importPage.Contents.CreateSingleContent(); #if !DEBUG content.Compressed = true; #endif PdfItem filter = content.Elements["/Filter"]; if (filter != null) { Elements["/Filter"] = filter.Clone(); } // (no cloning needed because the bytes keep untouched) Stream = content.Stream; // new PdfStream(bytes, this); Elements.SetInteger("/Length", content.Stream.Value.Length); }
/// <summary> /// Replace all indirect references to external objects by their cloned counterparts /// owned by the importer document. /// </summary> void FixUpObject_old(PdfImportedObjectTable iot, PdfObject value) { // TODO: merge with PdfXObject.FixUpObject PdfDictionary dict; PdfArray array; if ((dict = value as PdfDictionary) != null) { // Set document for cloned direct objects if (dict.Owner == null) { dict.Document = Owner; } else { Debug.Assert(dict.Owner == Owner); } // Search for indirect references in all keys PdfName[] names = dict.Elements.KeyNames; foreach (PdfName name in names) { PdfItem item = dict.Elements[name]; // Is item an iref? PdfReference iref = item as PdfReference; if (iref != null) { // Does the iref already belong to this document? if (iref.Document == Owner) { // Yes: fine continue; } else { Debug.Assert(iref.Document == iot.ExternalDocument); // No: replace with iref of cloned object PdfReference newXRef = iot[iref.ObjectID]; Debug.Assert(newXRef != null); Debug.Assert(newXRef.Document == Owner); dict.Elements[name] = newXRef; } } else if (item is PdfObject) { // Fix up inner objects FixUpObject_old(iot, (PdfObject)item); } } } else if ((array = value as PdfArray) != null) { // Set document for cloned direct objects if (array.Owner == null) { array.Document = Owner; } else { Debug.Assert(array.Owner == Owner); } // Search for indirect references in all array elements int count = array.Elements.Count; for (int idx = 0; idx < count; idx++) { PdfItem item = array.Elements[idx]; // Is item an iref? PdfReference iref = item as PdfReference; if (iref != null) { // Does the iref belongs to this document? if (iref.Document == Owner) { // Yes: fine continue; } else { Debug.Assert(iref.Document == iot.ExternalDocument); // No: replace with iref of cloned object PdfReference newXRef = iot[iref.ObjectID]; Debug.Assert(newXRef != null); Debug.Assert(newXRef.Document == Owner); array.Elements[idx] = newXRef; } } else if (item is PdfObject) { // Fix up inner objects FixUpObject_old(iot, (PdfObject)item); } } } }
void TransitiveClosureImplementation(Dictionary <PdfItem, object> objects, PdfObject pdfObject /*, ref int depth*/) { try { _nestingLevel++; if (_nestingLevel >= 1000) { if (!_overflow.ContainsKey(pdfObject)) { _overflow.Add(pdfObject, null); } return; } #if DEBUG_ //enterCount++; if (enterCount == 5400) { GetType(); } //if (!Object.ReferenceEquals(pdfObject.Owner, _document)) // GetType(); //////Debug.Assert(Object.ReferenceEquals(pdfObject27.Document, _document)); // if (item is PdfObject && ((PdfObject)item).ObjectID.ObjectNumber == 5) // Debug.WriteLine("items: " + ((PdfObject)item).ObjectID.ToString()); //if (pdfObject.ObjectNumber == 5) // GetType(); #endif IEnumerable enumerable = null; //(IEnumerator)pdfObject; PdfDictionary dict; PdfArray array; if ((dict = pdfObject as PdfDictionary) != null) { enumerable = dict.Elements.Values; } else if ((array = pdfObject as PdfArray) != null) { enumerable = array.Elements; } else { Debug.Assert(false, "Should not come here."); } if (enumerable != null) { foreach (PdfItem item in enumerable) { PdfReference iref = item as PdfReference; if (iref != null) { // Is this an indirect reference to an object that does not exist? //if (iref.Document == null) //{ // Debug.WriteLine("Dead object detected: " + iref.ObjectID.ToString()); // PdfReference dead = DeadObject; // iref.ObjectID = dead.ObjectID; // iref.Document = _document; // iref.SetObject(dead.Value); // PdfDictionary dict = (PdfDictionary)dead.Value; // dict.Elements["/DeadObjectCount"] = // new PdfInteger(dict.Elements.GetInteger("/DeadObjectCount") + 1); // iref = dead; //} if (!ReferenceEquals(iref.Document, _document)) { GetType(); Debug.WriteLine(String.Format("Bad iref: {0}", iref.ObjectID.ToString())); } Debug.Assert(ReferenceEquals(iref.Document, _document) || iref.Document == null, "External object detected!"); #if DEBUG_ if (iref.ObjectID.ObjectNumber == 23) { GetType(); } #endif if (!objects.ContainsKey(iref)) { PdfObject value = iref.Value; // Ignore unreachable objets. if (iref.Document != null) { // ... from trailer hack if (value == null) { iref = ObjectTable[iref.ObjectID]; Debug.Assert(iref.Value != null); value = iref.Value; } Debug.Assert(ReferenceEquals(iref.Document, _document)); objects.Add(iref, null); //Debug.WriteLine(String.Format("objects.Add('{0}', null);", iref.ObjectID.ToString())); if (value is PdfArray || value is PdfDictionary) { TransitiveClosureImplementation(objects, value /*, ref depth*/); } } //else //{ // objects2.Add(this[iref.ObjectID], null); //} } } else { PdfObject pdfObject28 = item as PdfObject; //if (pdfObject28 != null) // Debug.Assert(Object.ReferenceEquals(pdfObject28.Document, _document)); if (pdfObject28 != null && (pdfObject28 is PdfDictionary || pdfObject28 is PdfArray)) { TransitiveClosureImplementation(objects, pdfObject28 /*, ref depth*/); } } } } } finally { _nestingLevel--; } }
public void Write(PdfReference iref) { WriteSeparator(CharCat.Character); WriteRaw(iref.ToString()); this.lastCat = CharCat.Character; }
/// <summary> /// Reads the compressed object with the specified index. /// </summary> internal void ReadReferences(PdfCrossReferenceTable xrefTable) { ////// Create parser for stream. ////Parser parser = new Parser(_document, new MemoryStream(Stream.Value)); for (int idx = 0; idx < _header.Length; idx++) { int objectNumber = _header[idx][0]; int offset = _header[idx][1]; PdfObjectID objectID = new PdfObjectID(objectNumber); // HACK: -1 indicates compressed object. PdfReference iref = new PdfReference(objectID, -1); ////iref.ObjectID = objectID; ////iref.Value = xrefStream; if (!xrefTable.Contains(iref.ObjectID)) { xrefTable.Add(iref); } else { GetType(); } } }