/** * Translate a PRIndirectReference to a PdfIndirectReference * In addition, translates the object numbers, and copies the * referenced object to the output file if it wasn't available * in the cache yet. If it's in the cache, the reference to * the already used stream is returned. * * NB: PRIndirectReferences (and PRIndirectObjects) really need to know what * file they came from, because each file has its own namespace. The translation * we do from their namespace to ours is *at best* heuristic, and guaranteed to * fail under some circumstances. */ protected override PdfIndirectReference CopyIndirect(PRIndirectReference inp) { PdfObject srcObj = PdfReader.GetPdfObjectRelease(inp); ByteStore streamKey = null; bool validStream = false; if (srcObj.IsStream()) { streamKey = new ByteStore((PRStream)srcObj); validStream = true; PdfIndirectReference streamRef = (PdfIndirectReference)streamMap[streamKey]; if (streamRef != null) { return(streamRef); } } PdfIndirectReference theRef; RefKey key = new RefKey(inp); IndirectReferences iRef = (IndirectReferences)indirects[key]; if (iRef != null) { theRef = iRef.Ref; if (iRef.Copied) { return(theRef); } } else { theRef = body.PdfIndirectReference; iRef = new IndirectReferences(theRef); indirects[key] = iRef; } if (srcObj != null && srcObj.IsDictionary()) { PdfObject type = PdfReader.GetPdfObjectRelease(((PdfDictionary)srcObj).Get(PdfName.TYPE)); if (type != null && PdfName.PAGE.Equals(type)) { return(theRef); } } iRef.SetCopied(); if (validStream) { streamMap[streamKey] = theRef; } PdfObject obj = CopyObject(srcObj); AddToBody(obj, theRef); return(theRef); }
protected void CloseIt() { for (int k = 0; k < readers.Count; ++k) { ((PdfReader)readers[k]).RemoveFields(); } for (int r = 0; r < readers.Count; ++r) { PdfReader reader = (PdfReader)readers[r]; for (int page = 1; page <= reader.NumberOfPages; ++page) { pageRefs.Add(GetNewReference(reader.GetPageOrigRef(page))); pageDics.Add(reader.GetPageN(page)); } } MergeFields(); CreateAcroForms(); for (int r = 0; r < readers.Count; ++r) { PdfReader reader = (PdfReader)readers[r]; for (int page = 1; page <= reader.NumberOfPages; ++page) { PdfDictionary dic = reader.GetPageN(page); PdfIndirectReference pageRef = GetNewReference(reader.GetPageOrigRef(page)); PdfIndirectReference parent = root.AddPageRef(pageRef); dic.Put(PdfName.PARENT, parent); Propagate(dic, pageRef, false); } } foreach (DictionaryEntry entry in readers2intrefs) { PdfReader reader = (PdfReader)entry.Key; try { file = reader.SafeFile; file.ReOpen(); IntHashtable t = (IntHashtable)entry.Value; int[] keys = t.ToOrderedKeys(); for (int k = 0; k < keys.Length; ++k) { PRIndirectReference refi = new PRIndirectReference(reader, keys[k]); AddToBody(PdfReader.GetPdfObjectRelease(refi), t[keys[k]]); } } finally { try { file.Close(); reader.Close(); } catch { // empty on purpose } } } pdf.Close(); }
/** * Checks if a reference refers to a page object. * @param ref the reference that needs to be checked * @return true is the reference refers to a page object. */ protected internal bool IsPage(PRIndirectReference refi) { IntHashtable refs = (IntHashtable)pages2intrefs[refi.Reader]; if (refs != null) { return(refs.ContainsKey(refi.Number)); } else { return(false); } }
/** * After reading, we index all of the fields. Recursive. * @param fieldlist An array of fields * @param fieldDict the last field dictionary we encountered (recursively) * @param title the pathname of the field, up to this point or null */ protected void IterateFields(PdfArray fieldlist, PRIndirectReference fieldDict, String title) { foreach (PRIndirectReference refi in fieldlist.ArrayList) { PdfDictionary dict = (PdfDictionary)PdfReader.GetPdfObjectRelease(refi); // if we are not a field dictionary, pass our parent's values PRIndirectReference myFieldDict = fieldDict; String myTitle = title; PdfString tField = (PdfString)dict.Get(PdfName.T); bool isFieldDict = tField != null; if (isFieldDict) { myFieldDict = refi; if (title == null) { myTitle = tField.ToString(); } else { myTitle = title + '.' + tField.ToString(); } } PdfArray kids = (PdfArray)dict.Get(PdfName.KIDS); if (kids != null) { PushAttrib(dict); IterateFields(kids, myFieldDict, myTitle); stack.RemoveAt(stack.Count - 1); // pop } else // leaf node { if (myFieldDict != null) { PdfDictionary mergedDict = (PdfDictionary)stack[stack.Count - 1]; if (isFieldDict) { mergedDict = MergeAttrib(mergedDict, dict); } mergedDict.Put(PdfName.T, new PdfString(myTitle)); FieldInformation fi = new FieldInformation(myTitle, mergedDict, myFieldDict); fields.Add(fi); fieldByName[myTitle] = fi; } } } }
/** * Sets a reference to "visited" in the copy process. * @param ref the reference that needs to be set to "visited" * @return true if the reference was set to visited */ protected internal bool SetVisited(PRIndirectReference refi) { IntHashtable refs = (IntHashtable)visited[refi.Reader]; if (refs != null) { int old = refs[refi.Number]; refs[refi.Number] = 1; return(old != 0); } else { return(false); } }
/** Creates a new instance of DocumentFont */ internal DocumentFont(PRIndirectReference refFont) { encoding = ""; fontSpecific = false; this.refFont = refFont; fontType = FONT_TYPE_DOCUMENT; font = (PdfDictionary)PdfReader.GetPdfObject(refFont); fontName = PdfName.DecodeName(font.GetAsName(PdfName.BASEFONT).ToString()); PdfName subType = font.GetAsName(PdfName.SUBTYPE); if (PdfName.TYPE1.Equals(subType) || PdfName.TRUETYPE.Equals(subType)) { DoType1TT(); } else { for (int k = 0; k < cjkNames.Length; ++k) { if (fontName.StartsWith(cjkNames[k])) { fontName = cjkNames[k]; cjkMirror = BaseFont.CreateFont(fontName, cjkEncs[k], false); return; } } String enc = PdfName.DecodeName(font.GetAsName(PdfName.ENCODING).ToString()); for (int k = 0; k < cjkEncs2.Length; ++k) { if (enc.StartsWith(cjkEncs2[k])) { if (k > 3) { k -= 4; } cjkMirror = BaseFont.CreateFont(cjkNames2[k], cjkEncs2[k], false); return; } } if (PdfName.TYPE0.Equals(subType) && enc.Equals("Identity-H")) { ProcessType0(font); isType0 = true; } } }
/** * convenience method. Given a reader, set our "globals" */ protected void SetFromReader(PdfReader reader) { this.reader = reader; indirects = (Hashtable)indirectMap[reader]; if (indirects == null) { indirects = new Hashtable(); indirectMap[reader] = indirects; PdfDictionary catalog = reader.Catalog; PRIndirectReference refi = null; PdfObject o = catalog.Get(PdfName.ACROFORM); if (o == null || o.Type != PdfObject.INDIRECT) { return; } refi = (PRIndirectReference)o; if (acroForm == null) { acroForm = body.PdfIndirectReference; } indirects[new RefKey(refi)] = new IndirectReferences(acroForm); } }
/** * Copy the acroform for an input document. Note that you can only have one, * we make no effort to merge them. * @param reader The reader of the input file that is being copied * @throws IOException, BadPdfFormatException */ public void CopyAcroForm(PdfReader reader) { SetFromReader(reader); PdfDictionary catalog = reader.Catalog; PRIndirectReference hisRef = null; PdfObject o = catalog.Get(PdfName.ACROFORM); if (o != null && o.Type == PdfObject.INDIRECT) { hisRef = (PRIndirectReference)o; } if (hisRef == null) { return; // bugfix by John Engla } RefKey key = new RefKey(hisRef); PdfIndirectReference myRef; IndirectReferences iRef = (IndirectReferences)indirects[key]; if (iRef != null) { acroForm = myRef = iRef.Ref; } else { acroForm = myRef = body.PdfIndirectReference; iRef = new IndirectReferences(myRef); indirects[key] = iRef; } if (!iRef.Copied) { iRef.SetCopied(); PdfDictionary theForm = CopyDictionary((PdfDictionary)PdfReader.GetPdfObject(hisRef)); AddToBody(theForm, myRef); } }
public int GetDestinationPage() { if (!IsInternal()) { return(0); } // here destination is something like // [132 0 R, /XYZ, 29.3898, 731.864502, null] PdfIndirectReference refi = destination.GetAsIndirectObject(0); PRIndirectReference pr = (PRIndirectReference)refi; PdfReader r = pr.Reader; for (int i = 1; i <= r.NumberOfPages; i++) { PRIndirectReference pp = r.GetPageOrigRef(i); if (pp.Generation == pr.Generation && pp.Number == pr.Number) { return(i); } } throw new ArgumentException("Page not found."); }
/** * Translate a PRIndirectReference to a PdfIndirectReference * In addition, translates the object numbers, and copies the * referenced object to the output file. * NB: PRIndirectReferences (and PRIndirectObjects) really need to know what * file they came from, because each file has its own namespace. The translation * we do from their namespace to ours is *at best* heuristic, and guaranteed to * fail under some circumstances. */ protected virtual PdfIndirectReference CopyIndirect(PRIndirectReference inp) { PdfIndirectReference theRef; RefKey key = new RefKey(inp); IndirectReferences iRef = (IndirectReferences)indirects[key] ; if (iRef != null) { theRef = iRef.Ref; if (iRef.Copied) { return theRef; } } else { theRef = body.PdfIndirectReference; iRef = new IndirectReferences(theRef); indirects[key] = iRef; } PdfObject obj = PdfReader.GetPdfObjectRelease(inp); if (obj != null && obj.IsDictionary()) { PdfObject type = PdfReader.GetPdfObjectRelease(((PdfDictionary)obj).Get(PdfName.TYPE)); if (type != null && PdfName.PAGE.Equals(type)) { return theRef; } } iRef.SetCopied(); obj = CopyObject(obj); AddToBody(obj, theRef); return theRef; }
/** * Translate a PRIndirectReference to a PdfIndirectReference * In addition, translates the object numbers, and copies the * referenced object to the output file if it wasn't available * in the cache yet. If it's in the cache, the reference to * the already used stream is returned. * * NB: PRIndirectReferences (and PRIndirectObjects) really need to know what * file they came from, because each file has its own namespace. The translation * we do from their namespace to ours is *at best* heuristic, and guaranteed to * fail under some circumstances. */ protected override PdfIndirectReference CopyIndirect(PRIndirectReference inp) { PdfObject srcObj = PdfReader.GetPdfObjectRelease(inp); ByteStore streamKey = null; bool validStream = false; if (srcObj.IsStream()) { streamKey = new ByteStore((PRStream)srcObj); validStream = true; PdfIndirectReference streamRef = (PdfIndirectReference) streamMap[streamKey]; if (streamRef != null) { return streamRef; } } PdfIndirectReference theRef; RefKey key = new RefKey(inp); IndirectReferences iRef = (IndirectReferences) indirects[key]; if (iRef != null) { theRef = iRef.Ref; if (iRef.Copied) { return theRef; } } else { theRef = body.PdfIndirectReference; iRef = new IndirectReferences(theRef); indirects[key] = iRef; } if (srcObj != null && srcObj.IsDictionary()) { PdfObject type = PdfReader.GetPdfObjectRelease(((PdfDictionary)srcObj).Get(PdfName.TYPE)); if (type != null && PdfName.PAGE.Equals(type)) { return theRef; } } iRef.SetCopied(); if (validStream) { streamMap[streamKey] = theRef; } PdfObject obj = CopyObject(srcObj); AddToBody(obj, theRef); return theRef; }
private static String GetCOName(PdfReader reader, PRIndirectReference refi) { String name = ""; while (refi != null) { PdfObject obj = PdfReader.GetPdfObject(refi); if (obj == null || obj.Type != PdfObject.DICTIONARY) break; PdfDictionary dic = (PdfDictionary)obj; PdfString t = dic.GetAsString(PdfName.T); if (t != null) { name = t.ToUnicodeString()+ "." + name; } refi = (PRIndirectReference)dic.Get(PdfName.PARENT); } if (name.EndsWith(".")) name = name.Substring(0, name.Length - 1); return name; }
protected PdfIndirectReference GetNewReference(PRIndirectReference refi) { return new PdfIndirectReference(0, GetNewObjectNumber(refi.Reader, refi.Number, 0)); }
/** * After reading, we index all of the fields. Recursive. * @param fieldlist An array of fields * @param fieldDict the last field dictionary we encountered (recursively) * @param title the pathname of the field, up to this point or null */ protected void IterateFields(PdfArray fieldlist, PRIndirectReference fieldDict, String title) { foreach (PRIndirectReference refi in fieldlist.ArrayList) { PdfDictionary dict = (PdfDictionary) PdfReader.GetPdfObjectRelease(refi); // if we are not a field dictionary, pass our parent's values PRIndirectReference myFieldDict = fieldDict; String myTitle = title; PdfString tField = (PdfString)dict.Get(PdfName.T); bool isFieldDict = tField != null; if (isFieldDict) { myFieldDict = refi; if (title == null) myTitle = tField.ToString(); else myTitle = title + '.' + tField.ToString(); } PdfArray kids = (PdfArray)dict.Get(PdfName.KIDS); if (kids != null) { PushAttrib(dict); IterateFields(kids, myFieldDict, myTitle); stack.RemoveAt(stack.Count - 1); // pop } else { // leaf node if (myFieldDict != null) { PdfDictionary mergedDict = (PdfDictionary)stack[stack.Count - 1]; if (isFieldDict) mergedDict = MergeAttrib(mergedDict, dict); mergedDict.Put(PdfName.T, new PdfString(myTitle)); FieldInformation fi = new FieldInformation(myTitle, mergedDict, myFieldDict); fields.Add(fi); fieldByName[myTitle] = fi; } } } }
private void OutlineTravel(PRIndirectReference outline) { while (outline != null) { PdfDictionary outlineR = (PdfDictionary)PdfReader.GetPdfObjectRelease(outline); PRIndirectReference first = (PRIndirectReference)outlineR.Get(PdfName.FIRST); if (first != null) { OutlineTravel(first); } PdfReader.KillIndirect(outlineR.Get(PdfName.DEST)); PdfReader.KillIndirect(outlineR.Get(PdfName.A)); PdfReader.KillIndirect(outline); outline = (PRIndirectReference)outlineR.Get(PdfName.NEXT); } }
internal void InsertPage(int pageNumber, Rectangle mediabox) { Rectangle media = new Rectangle(mediabox); int rotation = media.Rotation % 360; PdfDictionary page = new PdfDictionary(PdfName.PAGE); PdfDictionary resources = new PdfDictionary(); PdfArray procset = new PdfArray(); procset.Add(PdfName.PDF); procset.Add(PdfName.TEXT); procset.Add(PdfName.IMAGEB); procset.Add(PdfName.IMAGEC); procset.Add(PdfName.IMAGEI); resources.Put(PdfName.PROCSET, procset); page.Put(PdfName.RESOURCES, resources); page.Put(PdfName.ROTATE, new PdfNumber(rotation)); page.Put(PdfName.MEDIABOX, new PdfRectangle(media, rotation)); PRIndirectReference pref = reader.AddPdfObject(page); PdfDictionary parent; PRIndirectReference parentRef; if (pageNumber > reader.NumberOfPages) { PdfDictionary lastPage = reader.GetPageNRelease(reader.NumberOfPages); parentRef = (PRIndirectReference)lastPage.Get(PdfName.PARENT); parentRef = new PRIndirectReference(reader, parentRef.Number); parent = (PdfDictionary)PdfReader.GetPdfObject(parentRef); PdfArray kids = (PdfArray)PdfReader.GetPdfObject(parent.Get(PdfName.KIDS), parent); kids.Add(pref); MarkUsed(kids); reader.pageRefs.InsertPage(pageNumber, pref); } else { if (pageNumber < 1) pageNumber = 1; PdfDictionary firstPage = reader.GetPageN(pageNumber); PRIndirectReference firstPageRef = reader.GetPageOrigRef(pageNumber); reader.ReleasePage(pageNumber); parentRef = (PRIndirectReference)firstPage.Get(PdfName.PARENT); parentRef = new PRIndirectReference(reader, parentRef.Number); parent = (PdfDictionary)PdfReader.GetPdfObject(parentRef); PdfArray kids = (PdfArray)PdfReader.GetPdfObject(parent.Get(PdfName.KIDS), parent); int len = kids.Size; int num = firstPageRef.Number; for (int k = 0; k < len; ++k) { PRIndirectReference cur = (PRIndirectReference)kids[k]; if (num == cur.Number) { kids.Add(k, pref); break; } } if (len == kids.Size) throw new Exception("Internal inconsistence."); MarkUsed(kids); reader.pageRefs.InsertPage(pageNumber, pref); CorrectAcroFieldPages(pageNumber); } page.Put(PdfName.PARENT, parentRef); while (parent != null) { MarkUsed(parent); PdfNumber count = (PdfNumber)PdfReader.GetPdfObjectRelease(parent.Get(PdfName.COUNT)); parent.Put(PdfName.COUNT, new PdfNumber(count.IntValue + 1)); parent = parent.GetAsDict(PdfName.PARENT); } }
/** Creates a new instance of DocumentFont */ internal DocumentFont(PRIndirectReference refFont) { encoding = ""; fontSpecific = false; this.refFont = refFont; fontType = FONT_TYPE_DOCUMENT; font = (PdfDictionary)PdfReader.GetPdfObject(refFont); fontName = PdfName.DecodeName(font.GetAsName(PdfName.BASEFONT).ToString()); PdfName subType = font.GetAsName(PdfName.SUBTYPE); if (PdfName.TYPE1.Equals(subType) || PdfName.TRUETYPE.Equals(subType)) DoType1TT(); else { for (int k = 0; k < cjkNames.Length; ++k) { if (fontName.StartsWith(cjkNames[k])) { fontName = cjkNames[k]; cjkMirror = BaseFont.CreateFont(fontName, cjkEncs[k], false); return; } } String enc = PdfName.DecodeName(font.GetAsName(PdfName.ENCODING).ToString()); for (int k = 0; k < cjkEncs2.Length; ++k) { if (enc.StartsWith(cjkEncs2[k])) { if (k > 3) k -= 4; cjkMirror = BaseFont.CreateFont(cjkNames2[k], cjkEncs2[k], false); return; } } if (PdfName.TYPE0.Equals(subType) && enc.Equals("Identity-H")) { ProcessType0(font); isType0 = true; } } }
internal RefKey(PRIndirectReference refi) { num = refi.Number; gen = refi.Generation; }
internal void Propagate(PdfObject obj, PdfIndirectReference refo, bool restricted) { if (obj == null) { return; } // if (refo != null) // AddToBody(obj, refo); if (obj is PdfIndirectReference) { return; } switch (obj.Type) { case PdfObject.DICTIONARY: case PdfObject.STREAM: { PdfDictionary dic = (PdfDictionary)obj; foreach (PdfName key in dic.Keys) { if (restricted && (key.Equals(PdfName.PARENT) || key.Equals(PdfName.KIDS))) { continue; } PdfObject ob = dic.Get(key); if (ob != null && ob.IsIndirect()) { PRIndirectReference ind = (PRIndirectReference)ob; if (!SetVisited(ind) && !IsPage(ind)) { PdfIndirectReference refi = GetNewReference(ind); Propagate(PdfReader.GetPdfObjectRelease(ind), refi, restricted); } } else { Propagate(ob, null, restricted); } } break; } case PdfObject.ARRAY: { //PdfArray arr = new PdfArray(); for (ListIterator it = ((PdfArray)obj).GetListIterator(); it.HasNext();) { PdfObject ob = (PdfObject)it.Next(); if (ob != null && ob.IsIndirect()) { PRIndirectReference ind = (PRIndirectReference)ob; if (!IsVisited(ind) && !IsPage(ind)) { PdfIndirectReference refi = GetNewReference(ind); Propagate(PdfReader.GetPdfObjectRelease(ind), refi, restricted); } } else { Propagate(ob, null, restricted); } } break; } case PdfObject.INDIRECT: { throw new Exception("Reference pointing to reference."); } } }
internal FieldInformation(String name, PdfDictionary info, PRIndirectReference refi) { this.name = name; this.info = info; this.refi = refi; }
protected PdfIndirectReference GetNewReference(PRIndirectReference refi) { return(new PdfIndirectReference(0, GetNewObjectNumber(refi.Reader, refi.Number, 0))); }
/** * Checks if a reference has already been "visited" in the copy process. * @param ref the reference that needs to be checked * @return true if the reference was already visited */ protected internal bool IsVisited(PRIndirectReference refi) { IntHashtable refs = (IntHashtable)visited[refi.Reader]; if (refs != null) return refs.ContainsKey(refi.Number); else return false; }
/** * Reuses an existing image. * @param ref the reference to the image dictionary * @throws BadElementException on error * @return the image */ public static Image GetInstance(PRIndirectReference iref) { PdfDictionary dic = (PdfDictionary)PdfReader.GetPdfObjectRelease(iref); int width = ((PdfNumber)PdfReader.GetPdfObjectRelease(dic.Get(PdfName.WIDTH))).IntValue; int height = ((PdfNumber)PdfReader.GetPdfObjectRelease(dic.Get(PdfName.HEIGHT))).IntValue; Image imask = null; PdfObject obj = dic.Get(PdfName.SMASK); if (obj != null && obj.IsIndirect()) { imask = GetInstance((PRIndirectReference)obj); } else { obj = dic.Get(PdfName.MASK); if (obj != null && obj.IsIndirect()) { PdfObject obj2 = PdfReader.GetPdfObjectRelease(obj); if (obj2 is PdfDictionary) imask = GetInstance((PRIndirectReference)obj); } } Image img = new ImgRaw(width, height, 1, 1, null); img.imageMask = imask; img.directReference = iref; return img; }
/** * Sets a reference to "visited" in the copy process. * @param ref the reference that needs to be set to "visited" * @return true if the reference was set to visited */ protected internal bool SetVisited(PRIndirectReference refi) { IntHashtable refs = (IntHashtable)visited[refi.Reader]; if (refs != null) { int old = refs[refi.Number]; refs[refi.Number] = 1; return (old != 0); } else return false; }