/// <summary> /// Appends a new content stream and returns it. /// </summary> public PdfContent AppendContent() { Debug.Assert(this.Owner != null); SetModified(); PdfContent content = new PdfContent(this.Owner); Owner.irefTable.Add(content); Debug.Assert(content.Reference != null); Elements.Add(content.Reference); return content; }
/// <summary> /// Prepends a new content stream and returns it. /// </summary> public PdfContent PrependContent() { Debug.Assert(Owner != null); SetModified(); PdfContent content = new PdfContent(Owner); Owner.irefTable.Add(content); Debug.Assert(content.Reference != null); Elements.Insert(0, content.Reference); return(content); }
/// <summary> /// Replaces the current content of the page with the specified bytes. /// </summary> PdfContent ReplaceContent(byte[] contentBytes) { Debug.Assert(Owner != null); PdfContent content = new PdfContent(Owner); content.CreateStream(contentBytes); Owner._irefTable.Add(content); Elements.Clear(); Elements.Add(content.Reference); return(content); }
void SetModified() { if (!modified) { modified = true; int count = Elements.Count; if (count == 1) { PdfContent content = (PdfContent)((PdfReference)Elements[0]).Value; content.PreserveGraphicsState(); } else if (count > 1) { // Surround content streams with q/Q operations byte[] value; int length; PdfContent content = (PdfContent)((PdfReference)Elements[0]).Value; if (content != null && content.Stream != null) { length = content.Stream.Length; value = new byte[length + 2]; value[0] = (byte)'q'; value[1] = (byte)'\n'; Array.Copy(content.Stream.Value, 0, value, 2, length); content.Stream.Value = value; content.Elements.SetInteger("/Length", length + 2); } content = (PdfContent)((PdfReference)Elements[count - 1]).Value; if (content != null && content.Stream != null) { length = content.Stream.Length; value = new byte[length + 3]; Array.Copy(content.Stream.Value, 0, value, 0, length); value[length] = (byte)' '; value[length + 1] = (byte)'Q'; value[length + 2] = (byte)'\n'; content.Stream.Value = value; content.Elements.SetInteger("/Length", length + 3); } } } }
/// <summary> /// Creates a single content stream with the bytes from the array of the content streams. /// This operation does not modify any of the content streams in this array. /// </summary> public PdfContent CreateSingleContent() { byte[] bytes = new byte[0]; byte[] bytes1; byte[] bytes2; foreach (PdfItem iref in Elements) { PdfDictionary cont = (PdfDictionary)((PdfReference)iref).Value; bytes1 = bytes; bytes2 = cont.Stream.UnfilteredValue; bytes = new byte[bytes1.Length + bytes2.Length + 1]; bytes1.CopyTo(bytes, 0); bytes[bytes1.Length] = (byte)'\n'; bytes2.CopyTo(bytes, bytes1.Length + 1); } PdfContent content = new PdfContent(Owner); content.Stream = new PdfDictionary.PdfStream(bytes, content); return(content); }
internal PdfFormXObject(PdfDocument thisDocument, PdfImportedObjectTable importedObjectTable, XPdfForm form) : base(thisDocument) { 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; } Debug.Assert(importedObjectTable != null); 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 ealier 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); int rotate = importPage.Elements.GetInteger(PdfPage.Keys.Rotate); //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)); if (rotate != 180) { // Translate the image such that its center lies on the center of the rotated bounding box double offset = (height - width) / 2; if (height > width) { matrix.TranslatePrepend(offset, offset); } else { matrix.TranslatePrepend(-offset, -offset); } } //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> /// Creates a single content stream with the bytes from the array of the content streams. /// This operation does not modify any of the content streams in this array. /// </summary> public PdfContent CreateSingleContent() { byte[] bytes = new byte[0]; byte[] bytes1; byte[] bytes2; foreach (PdfItem iref in Elements) { PdfDictionary cont = (PdfDictionary)((PdfReference)iref).Value; bytes1 = bytes; bytes2 = cont.Stream.UnfilteredValue; bytes = new byte[bytes1.Length + bytes2.Length + 1]; bytes1.CopyTo(bytes, 0); bytes[bytes1.Length] = (byte)'\n'; bytes2.CopyTo(bytes, bytes1.Length + 1); } PdfContent content = new PdfContent(this.Owner); content.Stream = new PdfDictionary.PdfStream(bytes, content); return content; }