/** * Computes the number of unfiltered bytes that each row of the image will contain. * If the number of bytes results in a partial terminating byte, this number is rounded up * per the PDF specification * @param imageDictionary the dictionary of the inline image * @return the number of bytes per row of the image */ private static int ComputeBytesPerRow(PdfDictionary imageDictionary, PdfDictionary colorSpaceDic) { PdfNumber wObj = imageDictionary.GetAsNumber(PdfName.WIDTH); PdfNumber bpcObj = imageDictionary.GetAsNumber(PdfName.BITSPERCOMPONENT); int cpp = GetComponentsPerPixel(imageDictionary.GetAsName(PdfName.COLORSPACE), colorSpaceDic); int w = wObj.IntValue; int bpc = bpcObj != null ? bpcObj.IntValue : 1; int bytesPerRow = (w * bpc * cpp + 7) / 8; return(bytesPerRow); }
/// <summary>Creates a Type 3 font based on an existing font dictionary, which must be an indirect object.</summary> /// <param name="fontDictionary">a dictionary of type <code>/Font</code>, must have an indirect reference.</param> internal PdfType3Font(PdfDictionary fontDictionary) : base(fontDictionary) { subset = true; embedded = true; fontProgram = new Type3Font(false); CMapToUnicode toUni = FontUtil.ProcessToUnicode(fontDictionary.Get(PdfName.ToUnicode)); fontEncoding = DocFontEncoding.CreateDocFontEncoding(fontDictionary.Get(PdfName.Encoding), toUni); PdfDictionary charProcsDic = GetPdfObject().GetAsDictionary(PdfName.CharProcs); PdfArray fontMatrixArray = GetPdfObject().GetAsArray(PdfName.FontMatrix); if (GetPdfObject().ContainsKey(PdfName.FontBBox)) { PdfArray fontBBox = GetPdfObject().GetAsArray(PdfName.FontBBox); fontProgram.GetFontMetrics().SetBbox(fontBBox.GetAsNumber(0).IntValue(), fontBBox.GetAsNumber(1).IntValue( ), fontBBox.GetAsNumber(2).IntValue(), fontBBox.GetAsNumber(3).IntValue()); } else { fontProgram.GetFontMetrics().SetBbox(0, 0, 0, 0); } int firstChar = NormalizeFirstLastChar(fontDictionary.GetAsNumber(PdfName.FirstChar), 0); int lastChar = NormalizeFirstLastChar(fontDictionary.GetAsNumber(PdfName.LastChar), 255); for (int i = firstChar; i <= lastChar; i++) { shortTag[i] = 1; } int[] widths = FontUtil.ConvertSimpleWidthsArray(fontDictionary.GetAsArray(PdfName.Widths), firstChar, 0); double[] fontMatrix = new double[6]; for (int i = 0; i < fontMatrixArray.Size(); i++) { fontMatrix[i] = ((PdfNumber)fontMatrixArray.Get(i)).GetValue(); } SetFontMatrix(fontMatrix); foreach (PdfName glyphName in charProcsDic.KeySet()) { int unicode = AdobeGlyphList.NameToUnicode(glyphName.GetValue()); if (unicode != -1 && fontEncoding.CanEncode(unicode)) { int code = fontEncoding.ConvertToByte(unicode); ((Type3Font)GetFontProgram()).AddGlyph(code, unicode, widths[code], null, new Type3Glyph(charProcsDic.GetAsStream (glyphName), GetDocument())); } } FillFontDescriptor(fontDictionary.GetAsDictionary(PdfName.FontDescriptor)); }
public void Rotate(string inputfile, float desiredRot) { var outputpath = FileUtilities.GetOutputPath(inputfile, Libraries.CommonUtilities.Models.ActionType.ROTATE, additionalData: desiredRot.ToString()); FileStream outStream = new FileStream(outputpath, FileMode.Create); PdfReader reader = new PdfReader(inputfile); PdfStamper stamper = new PdfStamper(reader, outStream); int pageCount = reader.NumberOfPages; for (int n = 1; n <= pageCount; n++) { PdfDictionary pageDict = reader.GetPageN(n); PdfNumber rotation = pageDict.GetAsNumber(PdfName.ROTATE); float rotationrequired = desiredRot; if (rotation != null) { rotationrequired += rotation.IntValue; rotationrequired %= 360; // must be 0, 90, 180, or 270 } pageDict.Put(PdfName.ROTATE, new PdfNumber(rotationrequired)); } stamper.Close(); reader.Close(); Console.WriteLine("Rotated {0} pages of {1}", pageCount, Path.GetFileName(outputpath)); }
/** * @see com.lowagie.text.pdf.interfaces.PdfVersion#addDeveloperExtension(com.lowagie.text.pdf.PdfDeveloperExtension) * @since 2.1.6 */ public void AddDeveloperExtension(PdfDeveloperExtension de) { if (extensions == null) { extensions = new PdfDictionary(); } else { PdfDictionary extension = extensions.GetAsDict(de.Prefix); if (extension != null) { int diff = de.Baseversion.CompareTo(extension.GetAsName(PdfName.BASEVERSION)); if (diff < 0) { return; } diff = de.ExtensionLevel - extension.GetAsNumber(PdfName.EXTENSIONLEVEL).IntValue; if (diff <= 0) { return; } } } extensions.Put(de.Prefix, de.GetDeveloperExtensions()); }
internal static TrueTypeFont CreateFontProgram(PdfDictionary fontDictionary, FontEncoding fontEncoding) { iText.Kernel.Font.DocTrueTypeFont fontProgram = new iText.Kernel.Font.DocTrueTypeFont(fontDictionary); FillFontDescriptor(fontProgram, fontDictionary.GetAsDictionary(PdfName.FontDescriptor)); PdfNumber firstCharNumber = fontDictionary.GetAsNumber(PdfName.FirstChar); int firstChar = firstCharNumber != null?Math.Max(firstCharNumber.IntValue(), 0) : 0; int[] widths = FontUtil.ConvertSimpleWidthsArray(fontDictionary.GetAsArray(PdfName.Widths), firstChar, fontProgram .GetMissingWidth()); fontProgram.avgWidth = 0; int glyphsWithWidths = 0; for (int i = 0; i < 256; i++) { Glyph glyph = new Glyph(i, widths[i], fontEncoding.GetUnicode(i)); fontProgram.codeToGlyph[i] = glyph; //FontEncoding.codeToUnicode table has higher priority if (glyph.HasValidUnicode() && fontEncoding.ConvertToByte(glyph.GetUnicode()) == i) { fontProgram.unicodeToGlyph[glyph.GetUnicode()] = glyph; } if (widths[i] > 0) { glyphsWithWidths++; fontProgram.avgWidth += widths[i]; } } if (glyphsWithWidths != 0) { fontProgram.avgWidth /= glyphsWithWidths; } return(fontProgram); }
public static void RotatePDF180(Stream inputFile, string outputFile) { using (FileStream outStream = new FileStream(outputFile, FileMode.Create)) { PdfReader reader = new PdfReader(inputFile); PdfStamper stamper = new PdfStamper(reader, outStream); int pageCount = reader.NumberOfPages; for (int n = 1; n <= pageCount; n++) { PdfDictionary pageDict = reader.GetPageN(n); int desiredRot = 180; // PdfNumber rotation = pageDict.GetAsNumber(PdfName.ROTATE); if (rotation != null) { desiredRot += rotation.IntValue; desiredRot %= 360; // must be 0, 90, 180, or 270 } pageDict.Put(PdfName.ROTATE, new PdfNumber(desiredRot)); } stamper.Close(); reader.Close(); MessageBox.Show("Rotated 180° and saved with PAVS extension!"); } }
public static string RotateIfNecessary(string pdfFile) { using (PdfReader reader = new PdfReader(pdfFile)) { Rectangle pagesize = reader.GetPageSizeWithRotation(reader.GetPageN(1)); if (pagesize.Width < pagesize.Height) { for (int n = 1; n <= reader.NumberOfPages; n++) { PdfDictionary page = reader.GetPageN(n); PdfNumber rotate = page.GetAsNumber(PdfName.ROTATE); int rotation = rotate == null ? 90 : (rotate.IntValue + 90) % 360; page.Put(PdfName.ROTATE, new PdfNumber(rotation)); } string rotatedFileName = Path.GetDirectoryName(pdfFile) + @"\" + Path.GetFileNameWithoutExtension(pdfFile) + "_rotated.pdf"; using (FileStream fs = new FileStream(rotatedFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { PdfStamper stamper = new PdfStamper(reader, fs); stamper.Close(); } return(rotatedFileName); } else { return(pdfFile); } } }
public virtual void RegisterMcr(PdfMcr mcr) { SortedDictionary <int, PdfMcr> pageMcrs = pageToPageMcrs.Get(mcr.GetPageObject().GetIndirectReference()); if (pageMcrs == null) { pageMcrs = new SortedDictionary <int, PdfMcr>(); pageToPageMcrs[mcr.GetPageObject().GetIndirectReference()] = pageMcrs; } if (mcr is PdfObjRef) { PdfDictionary obj = ((PdfDictionary)mcr.GetPdfObject()).GetAsDictionary(PdfName.Obj); if (obj == null || obj.IsFlushed()) { throw new PdfException(PdfException.WhenAddingObjectReferenceToTheTagTreeItMustBeConnectedToNotFlushedObject ); } PdfNumber n = obj.GetAsNumber(PdfName.StructParent); if (n != null) { pageMcrs[StructParentIndexIntoKey(n.IntValue())] = mcr; } else { throw new PdfException(PdfException.StructParentIndexNotFoundInTaggedObject); } } else { pageMcrs[mcr.GetMcid()] = mcr; } }
public virtual void SetAnnotationTest() { using (PdfDocument document = new PdfDocument(new PdfWriter(new MemoryStream()))) { PdfFileAttachmentAnnotation annotation0 = new PdfFileAttachmentAnnotation(new Rectangle(0, 0, 20, 20)); PdfFileAttachmentAnnotation annotation1 = new PdfFileAttachmentAnnotation(new Rectangle(1, 1, 21, 21)); PdfFileAttachmentAnnotation annotation2 = new PdfFileAttachmentAnnotation(new Rectangle(2, 2, 22, 22)); document.AddNewPage(); document.GetPage(1).AddAnnotation(annotation0); document.GetPage(1).AddAnnotation(annotation1); document.GetPage(1).AddAnnotation(annotation2); PdfTarget target = PdfTarget.Create(new PdfDictionary()); target.SetAnnotation(annotation2, document); PdfDictionary dictionary = target.GetPdfObject(); NUnit.Framework.Assert.AreEqual(0, dictionary.GetAsNumber(PdfName.P).IntValue()); NUnit.Framework.Assert.AreEqual(2, dictionary.GetAsNumber(PdfName.A).IntValue()); } }
public override void EventOccurred(IEventData data, EventType type) { if (data is TextRenderInfo renderInfo) { var oFont = renderInfo.GetFont(); PdfDictionary fontDescriptor = oFont.GetPdfObject().GetAsDictionary(PdfName.FontDescriptor); PdfNumber number = fontDescriptor?.GetAsNumber(PdfName.FontWeight); double? weight = number?.GetValue();
/** * @see com.itextpdf.text.pdf.mc.MCParser.PdfOperator#process(com.itextpdf.text.pdf.ocg.OCGParser, com.itextpdf.text.pdf.PdfLiteral, java.util.List) */ public void Process(MCParser parser, PdfLiteral opr, IList <PdfObject> operands) { if (operands[1].IsDictionary()) { PdfDictionary dict = (PdfDictionary)operands[1]; parser.DealWithMcid(dict.GetAsNumber(PdfName.MCID)); } parser.PrintOperator(opr, operands); }
/** * Deletes redact annotations from the page and substitutes them with either OverlayText or RO object if it's needed. */ private void DeleteRedactAnnots(int pageNum) { HashSet2 <String> indirRefs; redactAnnotIndirRefs.TryGetValue(pageNum, out indirRefs); if (indirRefs == null || indirRefs.Count == 0) { return; } PdfReader reader = pdfStamper.Reader; PdfContentByte canvas = pdfStamper.GetOverContent(pageNum); PdfDictionary pageDict = reader.GetPageN(pageNum); PdfArray annotsArray = pageDict.GetAsArray(PdfName.ANNOTS); // j is for access annotRect (i can be decreased, so we need to store additional index, // indicating current position in ANNOTS array in case if we don't remove anything for (int i = 0, j = 0; i < annotsArray.Size; ++i, ++j) { PdfIndirectReference annotIndRef = annotsArray.GetAsIndirectObject(i); PdfDictionary annotDict = annotsArray.GetAsDict(i); if (indirRefs.Contains(annotIndRef.ToString()) || indirRefs.Contains(GetParentIndRefStr(annotDict))) { PdfStream formXObj = annotDict.GetAsStream(PdfName.RO); PdfString overlayText = annotDict.GetAsString(PdfName.OVERLAYTEXT); if (FillCleanedArea && formXObj != null) { PdfArray rectArray = annotDict.GetAsArray(PdfName.RECT); Rectangle annotRect = new Rectangle(rectArray.GetAsNumber(0).FloatValue, rectArray.GetAsNumber(1).FloatValue, rectArray.GetAsNumber(2).FloatValue, rectArray.GetAsNumber(3).FloatValue); InsertFormXObj(canvas, pageDict, formXObj, clippingRects[j], annotRect); } else if (FillCleanedArea && overlayText != null && overlayText.ToUnicodeString().Length > 0) { DrawOverlayText(canvas, clippingRects[j], overlayText, annotDict.GetAsString(PdfName.DA), annotDict.GetAsNumber(PdfName.Q), annotDict.GetAsBoolean(PdfName.REPEAT)); } annotsArray.Remove(i--); // array size is changed, so we need to decrease i } } if (annotsArray.Size == 0) { pageDict.Remove(PdfName.ANNOTS); } }
/** * Gets the MCID value If the Marked Content contains * an MCID entry, returns that value. Otherwise, a {@link NullPointerException} is thrown. * @return the MCID value * @throws NullPointerException if there is no MCID (see {@link MarkedContentInfo#hasMcid()}) */ virtual public int GetMcid() { PdfNumber id = dictionary.GetAsNumber(PdfName.MCID); if (id == null) { throw new InvalidOperationException("MarkedContentInfo does not contain MCID"); } return(id.IntValue); }
public virtual void PutTest() { PdfName key1 = new PdfName("Key1"); PdfName key2 = new PdfName("Key2"); PdfDictionary dictionary = new PdfDictionary(); PdfTarget target = PdfTarget.Create(dictionary); target.Put(key1, new PdfNumber(23)).Put(key2, new PdfString("Hello, world!")); NUnit.Framework.Assert.AreEqual(23, dictionary.GetAsNumber(key1).IntValue()); NUnit.Framework.Assert.AreEqual("Hello, world!", dictionary.GetAsString(key2).GetValue()); }
public void HandleEvent(Event currentEvent) { PdfDocumentEvent docEvent = (PdfDocumentEvent)currentEvent; PdfPage page = docEvent.GetPage(); page.Put(PdfName.Rotate, pageDict.GetAsNumber(PdfName.Rotate)); // The MediaBox value defines the full size of the page. ScaleDown(page, pageDict, PdfName.MediaBox, scale); // The CropBox value defines the visible size of the page. ScaleDown(page, pageDict, PdfName.CropBox, scale); }
/** * Parses the samples of the image from the underlying content parser, ignoring all filters. * The parser must be positioned immediately after the ID operator that ends the inline image's dictionary. * The parser will be left positioned immediately following the EI operator. * This is primarily useful if no filters have been applied. * @param imageDictionary the dictionary of the inline image * @param ps the content parser * @return the samples of the image * @throws IOException if anything bad happens during parsing */ private static byte[] ParseUnfilteredSamples(PdfDictionary imageDictionary, PdfDictionary colorSpaceDic, PdfContentParser ps) { // special case: when no filter is specified, we just read the number of bits // per component, multiplied by the width and height. if (imageDictionary.Contains(PdfName.FILTER)) { throw new ArgumentException("Dictionary contains filters"); } PdfNumber h = imageDictionary.GetAsNumber(PdfName.HEIGHT); int bytesToRead = ComputeBytesPerRow(imageDictionary, colorSpaceDic) * h.IntValue; byte[] bytes = new byte[bytesToRead]; PRTokeniser tokeniser = ps.GetTokeniser(); int shouldBeWhiteSpace = tokeniser.Read(); // skip next character (which better be a whitespace character - I suppose we could check for this) // from the PDF spec: Unless the image uses ASCIIHexDecode or ASCII85Decode as one of its filters, the ID operator shall be followed by a single white-space character, and the next character shall be interpreted as the first byte of image data. // unfortunately, we've seen some PDFs where there is no space following the ID, so we have to capture this case and handle it int startIndex = 0; if (!PRTokeniser.IsWhitespace(shouldBeWhiteSpace) || shouldBeWhiteSpace == 0) // tokeniser treats 0 as whitespace, but for our purposes, we shouldn't) { bytes[0] = (byte)shouldBeWhiteSpace; startIndex++; } for (int i = startIndex; i < bytesToRead; i++) { int ch = tokeniser.Read(); if (ch == -1) { throw new InlineImageParseException("End of content stream reached before end of image data"); } bytes[i] = (byte)ch; } PdfObject ei = ps.ReadPRObject(); if (!ei.ToString().Equals("EI")) { // Some PDF producers seem to add another non-whitespace character after the image data. // Let's try to handle that case here. PdfObject ei2 = ps.ReadPRObject(); if (!ei2.ToString().Equals("EI")) { throw new InlineImageParseException("EI not found after end of image data"); } } return(bytes); }
/// <summary> /// Creates an object that can inform you about the type of signature /// in a signature dictionary as well as some of the permissions /// defined by the signature. /// </summary> public SignaturePermissions(PdfDictionary sigDict, SignaturePermissions previous) { if (previous != null) { annotationsAllowed &= previous.IsAnnotationsAllowed(); fillInAllowed &= previous.IsFillInAllowed(); fieldLocks.AddAll(previous.GetFieldLocks()); } PdfArray @ref = sigDict.GetAsArray(PdfName.Reference); if (@ref != null) { for (int i = 0; i < @ref.Size(); i++) { PdfDictionary dict = @ref.GetAsDictionary(i); PdfDictionary @params = dict.GetAsDictionary(PdfName.TransformParams); if (PdfName.DocMDP.Equals(dict.GetAsName(PdfName.TransformMethod))) { certification = true; } PdfName action = @params.GetAsName(PdfName.Action); if (action != null) { fieldLocks.Add(new SignaturePermissions.FieldLock(this, action, @params.GetAsArray(PdfName.Fields))); } PdfNumber p = @params.GetAsNumber(PdfName.P); if (p == null) { continue; } switch (p.IntValue()) { default: { break; } case 1: { fillInAllowed &= false; goto case 2; } case 2: { annotationsAllowed &= false; break; } } } } }
private void FillFontDescriptor(PdfDictionary fontDesc) { if (fontDesc == null) { return; } PdfNumber v = fontDesc.GetAsNumber(PdfName.ItalicAngle); if (v != null) { SetItalicAngle(v.IntValue()); } v = fontDesc.GetAsNumber(PdfName.FontWeight); if (v != null) { SetFontWeight(v.IntValue()); } PdfName fontStretch = fontDesc.GetAsName(PdfName.FontStretch); if (fontStretch != null) { SetFontStretch(fontStretch.GetValue()); } PdfName fontName = fontDesc.GetAsName(PdfName.FontName); if (fontName != null) { SetFontName(fontName.GetValue()); } PdfString fontFamily = fontDesc.GetAsString(PdfName.FontFamily); if (fontFamily != null) { SetFontFamily(fontFamily.GetValue()); } }
protected void ManipulatePdf(String dest) { PdfDocument pdfDoc = new PdfDocument(new PdfReader(SRC), new PdfWriter(dest)); for (int p = 1; p <= pdfDoc.GetNumberOfPages(); p++) { PdfDictionary page = pdfDoc.GetPage(p).GetPdfObject(); if (page.GetAsNumber(PdfName.UserUnit) == null) { page.Put(PdfName.UserUnit, new PdfNumber(2.5f)); } page.Remove(PdfName.Rotate); } pdfDoc.Close(); }
public virtual void UnregisterMcr(PdfMcr mcrToUnregister) { PdfDictionary pageDict = mcrToUnregister.GetPageObject(); if (pageDict == null) { // invalid mcr, ignore return; } if (pageDict.IsFlushed()) { throw new PdfException(PdfException.CannotRemoveMarkedContentReferenceBecauseItsPageWasAlreadyFlushed); } IDictionary <int, PdfMcr> pageMcrs = pageToPageMcrs.Get(pageDict.GetIndirectReference()); if (pageMcrs != null) { if (mcrToUnregister is PdfObjRef) { PdfDictionary obj = ((PdfDictionary)mcrToUnregister.GetPdfObject()).GetAsDictionary(PdfName.Obj); if (obj != null && !obj.IsFlushed()) { PdfNumber n = obj.GetAsNumber(PdfName.StructParent); if (n != null) { pageMcrs.JRemove(StructParentIndexIntoKey(n.IntValue())); structTreeRoot.SetModified(); return; } } foreach (KeyValuePair <int, PdfMcr> entry in pageMcrs) { if (entry.Value.GetPdfObject() == mcrToUnregister.GetPdfObject()) { pageMcrs.JRemove(entry.Key); structTreeRoot.SetModified(); break; } } } else { pageMcrs.JRemove(mcrToUnregister.GetMcid()); structTreeRoot.SetModified(); } } }
public PageInfo(PdfReader reader, int pageNumber) { PageNumber = pageNumber; ImagesInfo = new ImagesInfo(); TextsInfo = new TextsInfo(); _reader = reader; _page = reader.GetPageN(pageNumber); PageUnits = _page.Contains(PdfName.USERUNIT) ? _page.GetAsNumber(PdfName.USERUNIT).FloatValue : 72; Rectangle mediabox = reader.GetPageSize(_page); PageWidth = Utilities.PointsToMillimeters(mediabox.Width); PageHeight = Utilities.PointsToMillimeters(mediabox.Height); _RenderPage(PageNumber, PageUnits); }
/** * When an XObject with a StructParent is encountered, * we want to remove it from the stack. * @param xobj the name of an XObject */ protected void DealWithXObj(PdfName xobj) { PdfDictionary dict = xobjects.GetAsStream(xobj); PdfNumber structParent = dict.GetAsNumber(PdfName.STRUCTPARENT); LOGGER.Info(String.Format("Encountered StructParent {0} in content", structParent)); if (structParent == null) { return; } StructureItem item = items[0]; if (item.CheckStructParent(pageref.Number, structParent.IntValue) == 1) { items.RemoveAt(0); } }
/** * Creates an object that can inform you about the type of signature * in a signature dictionary as well as some of the permissions * defined by the signature. */ public SignaturePermissions(PdfDictionary sigDict, SignaturePermissions previous) { if (previous != null) { annotationsAllowed &= previous.AnnotationsAllowed; fillInAllowed &= previous.FillInAllowed; fieldLocks.AddRange(previous.FieldLocks); } PdfArray reference = sigDict.GetAsArray(PdfName.REFERENCE); if (reference != null) { for (int i = 0; i < reference.Size; i++) { PdfDictionary dict = reference.GetAsDict(i); PdfDictionary parameters = dict.GetAsDict(PdfName.TRANSFORMPARAMS); if (PdfName.DOCMDP.Equals(dict.GetAsName(PdfName.TRANSFORMMETHOD))) { certification = true; } PdfName action = parameters.GetAsName(PdfName.ACTION); if (action != null) { fieldLocks.Add(new FieldLock(action, parameters.GetAsArray(PdfName.FIELDS))); } PdfNumber p = parameters.GetAsNumber(PdfName.P); if (p == null) { continue; } switch (p.IntValue) { case 1: fillInAllowed = false; break; case 2: annotationsAllowed = false; break; } } } }
private void RegisterMcr(PdfMcr mcr, bool registeringOnInit) { PdfDictionary mcrPageObject = mcr.GetPageObject(); if (mcrPageObject == null || (!(mcr is PdfObjRef) && mcr.GetMcid() < 0)) { ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Pdf.Tagging.ParentTreeHandler)); logger.Error(iText.IO.LogMessageConstant.ENCOUNTERED_INVALID_MCR); return; } SortedDictionary <int, PdfMcr> pageMcrs = pageToPageMcrs.Get(mcrPageObject.GetIndirectReference()); if (pageMcrs == null) { pageMcrs = new SortedDictionary <int, PdfMcr>(); pageToPageMcrs.Put(mcrPageObject.GetIndirectReference(), pageMcrs); } if (mcr is PdfObjRef) { PdfDictionary obj = ((PdfDictionary)mcr.GetPdfObject()).GetAsDictionary(PdfName.Obj); if (obj == null || obj.IsFlushed()) { throw new PdfException(PdfException.WhenAddingObjectReferenceToTheTagTreeItMustBeConnectedToNotFlushedObject ); } PdfNumber n = obj.GetAsNumber(PdfName.StructParent); if (n != null) { pageMcrs.Put(StructParentIndexIntoKey(n.IntValue()), mcr); } else { throw new PdfException(PdfException.StructParentIndexNotFoundInTaggedObject); } } else { pageMcrs.Put(mcr.GetMcid(), mcr); } if (!registeringOnInit) { structTreeRoot.SetModified(); } }
/// <summary>Creates a Type3 font based on an existing font dictionary, which must be an indirect object.</summary> /// <param name="fontDictionary">a dictionary of type <code>/Font</code>, must have an indirect reference.</param> internal PdfType3Font(PdfDictionary fontDictionary) : base(fontDictionary) { EnsureObjectIsAddedToDocument(fontDictionary); CheckFontDictionary(fontDictionary, PdfName.Type3); subset = true; embedded = true; fontProgram = new Type3FontProgram(false); fontEncoding = DocFontEncoding.CreateDocFontEncoding(fontDictionary.Get(PdfName.Encoding), null, false); PdfDictionary charProcsDic = GetPdfObject().GetAsDictionary(PdfName.CharProcs); PdfArray fontMatrixArray = GetPdfObject().GetAsArray(PdfName.FontMatrix); if (GetPdfObject().ContainsKey(PdfName.FontBBox)) { PdfArray fontBBox = GetPdfObject().GetAsArray(PdfName.FontBBox); fontProgram.GetFontMetrics().SetBbox(fontBBox.GetAsNumber(0).IntValue(), fontBBox.GetAsNumber(1).IntValue( ), fontBBox.GetAsNumber(2).IntValue(), fontBBox.GetAsNumber(3).IntValue()); } else { fontProgram.GetFontMetrics().SetBbox(0, 0, 0, 0); } PdfNumber firstCharNumber = fontDictionary.GetAsNumber(PdfName.FirstChar); int firstChar = firstCharNumber != null?Math.Max(firstCharNumber.IntValue(), 0) : 0; int[] widths = FontUtil.ConvertSimpleWidthsArray(fontDictionary.GetAsArray(PdfName.Widths), firstChar); double[] fontMatrix = new double[6]; for (int i = 0; i < fontMatrixArray.Size(); i++) { fontMatrix[i] = ((PdfNumber)fontMatrixArray.Get(i)).GetValue(); } SetFontMatrix(fontMatrix); foreach (PdfName glyphName in charProcsDic.KeySet()) { int unicode = (int)AdobeGlyphList.NameToUnicode(glyphName.GetValue()); if (unicode != -1 && fontEncoding.CanEncode(unicode)) { int code = fontEncoding.ConvertToByte(unicode); ((Type3FontProgram)GetFontProgram()).AddGlyph(code, unicode, widths[code], null, new Type3Glyph(charProcsDic .GetAsStream(glyphName), GetDocument())); } } }
/** * Parses the samples of the image from the underlying content parser, ignoring all filters. * The parser must be positioned immediately after the ID operator that ends the inline image's dictionary. * The parser will be left positioned immediately following the EI operator. * This is primarily useful if no filters have been applied. * @param imageDictionary the dictionary of the inline image * @param ps the content parser * @return the samples of the image * @throws IOException if anything bad happens during parsing */ private static byte[] ParseUnfilteredSamples(PdfDictionary imageDictionary, PdfContentParser ps) { // special case: when no filter is specified, we just read the number of bits // per component, multiplied by the width and height. if (imageDictionary.Contains(PdfName.FILTER)) { throw new ArgumentException("Dictionary contains filters"); } PdfNumber h = imageDictionary.GetAsNumber(PdfName.HEIGHT); int bytesToRead = ComputeBytesPerRow(imageDictionary) * h.IntValue; byte[] bytes = new byte[bytesToRead]; PRTokeniser tokeniser = ps.GetTokeniser(); tokeniser.Read(); // skip next character (which better be a whitespace character - I suppose we could check for this) for (int i = 0; i < bytesToRead; i++) { int ch = tokeniser.Read(); if (ch == -1) { throw new InlineImageParseException("End of content stream reached before end of image data"); } bytes[i] = (byte)ch; } PdfObject ei = ps.ReadPRObject(); if (!ei.ToString().Equals("EI")) { throw new InlineImageParseException("EI not found after end of image data"); } return(bytes); }
/** * Creates a StructurItem using an MCR dictionary. * @param dict an MCR dictionary */ public StructureMCID(PdfDictionary mcr) { mcid = mcr.GetAsNumber(PdfName.MCID).IntValue; pageref = mcr.GetAsIndirectObject(PdfName.PG).Number; }
private void InitKeyAndReadDictionary(PdfDictionary encryptionDictionary, byte[] password) { try { if (password == null) { password = new byte[0]; } else { if (password.Length > 127) { password = JavaUtil.ArraysCopyOf(password, 127); } } isPdf2 = encryptionDictionary.GetAsNumber(PdfName.R).GetValue() == 6; byte[] oValue = GetIsoBytes(encryptionDictionary.GetAsString(PdfName.O)); byte[] uValue = GetIsoBytes(encryptionDictionary.GetAsString(PdfName.U)); byte[] oeValue = GetIsoBytes(encryptionDictionary.GetAsString(PdfName.OE)); byte[] ueValue = GetIsoBytes(encryptionDictionary.GetAsString(PdfName.UE)); byte[] perms = GetIsoBytes(encryptionDictionary.GetAsString(PdfName.Perms)); PdfNumber pValue = (PdfNumber)encryptionDictionary.Get(PdfName.P); this.permissions = pValue.LongValue(); byte[] hash; hash = ComputeHash(password, oValue, VALIDATION_SALT_OFFSET, SALT_LENGTH, uValue); usedOwnerPassword = CompareArray(hash, oValue, 32); if (usedOwnerPassword) { hash = ComputeHash(password, oValue, KEY_SALT_OFFSET, SALT_LENGTH, uValue); AESCipherCBCnoPad ac = new AESCipherCBCnoPad(false, hash); nextObjectKey = ac.ProcessBlock(oeValue, 0, oeValue.Length); } else { hash = ComputeHash(password, uValue, VALIDATION_SALT_OFFSET, SALT_LENGTH); if (!CompareArray(hash, uValue, 32)) { throw new BadPasswordException(PdfException.BadUserPassword); } hash = ComputeHash(password, uValue, KEY_SALT_OFFSET, SALT_LENGTH); AESCipherCBCnoPad ac = new AESCipherCBCnoPad(false, hash); nextObjectKey = ac.ProcessBlock(ueValue, 0, ueValue.Length); } nextObjectKeySize = 32; AESCipherCBCnoPad ac_1 = new AESCipherCBCnoPad(false, nextObjectKey); byte[] decPerms = ac_1.ProcessBlock(perms, 0, perms.Length); if (decPerms[9] != (byte)'a' || decPerms[10] != (byte)'d' || decPerms[11] != (byte)'b') { throw new BadPasswordException(PdfException.BadUserPassword); } int permissionsDecoded = (decPerms[0] & 0xff) | ((decPerms[1] & 0xff) << 8) | ((decPerms[2] & 0xff) << 16) | ((decPerms[3] & 0xff) << 24); bool encryptMetadata = decPerms[8] == (byte)'T'; bool?encryptMetadataEntry = encryptionDictionary.GetAsBool(PdfName.EncryptMetadata); if (permissionsDecoded != permissions || encryptMetadataEntry != null && encryptMetadata != encryptMetadataEntry ) { ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Crypto.Securityhandler.StandardHandlerUsingAes256)); logger.Error(iText.IO.LogMessageConstant.ENCRYPTION_ENTRIES_P_AND_ENCRYPT_METADATA_NOT_CORRESPOND_PERMS_ENTRY ); } this.permissions = permissionsDecoded; this.encryptMetadata = encryptMetadata; } catch (BadPasswordException ex) { throw; } catch (Exception ex) { throw new PdfException(PdfException.PdfEncryption, ex); } }
/** * Converts an annotation structure item to a Form XObject annotation. * @param item the structure item * @throws IOException */ protected void ConvertToXObject(StructureObject item) { PdfDictionary structElem = item.GetStructElem(); if (structElem == null) { return; } PdfDictionary dict = item.GetObjAsDict(); if (dict == null || !dict.CheckType(PdfName.ANNOT)) { return; } PdfDictionary ap = dict.GetAsDict(PdfName.AP); if (ap == null) { return; } PdfNumber structParent = dict.GetAsNumber(PdfName.STRUCTPARENT); if (structParent == null) { return; } PdfStream stream = ap.GetAsStream(PdfName.N); if (stream == null) { return; } stream.Put(PdfName.STRUCTPARENT, structParent); PdfIndirectReference xobjr = ap.GetAsIndirectObject(PdfName.N); if (xobjr == null) { return; } // remove the annotation from the page for (int i = 0; i < annots.Length; i++) { PdfIndirectReference annotref = annots.GetAsIndirectObject(i); if (item.GetObjRef().Number == annotref.Number) { annots.Remove(i); break; } } // replace the existing attributes by a PrintField attribute PdfDictionary attribute = new PdfDictionary(); attribute.Put(PdfName.O, PdfName.PRINTFIELD); PdfString description = dict.GetAsString(PdfName.TU); if (description == null) { description = dict.GetAsString(PdfName.T); } if (PdfName.BTN.Equals(dict.Get(PdfName.FT))) { PdfNumber fflags = dict.GetAsNumber(PdfName.FF); if (fflags != null) { int ff = fflags.IntValue; if ((ff & PdfFormField.FF_PUSHBUTTON) != 0) { attribute.Put(PdfName.ROLE, PdfName.PB); } // I don't think the condition below will ever be true if ((ff & PdfFormField.FF_RADIO) != 0) { attribute.Put(PdfName.ROLE, PdfName.rb); } else { attribute.Put(PdfName.ROLE, PdfName.CB); } } } else { attribute.Put(PdfName.ROLE, PdfName.TV); } attribute.Put(PdfName.DESC, description); // Updating the values of the StructElem dictionary PdfString t = structElem.GetAsString(PdfName.T); if (t == null || t.ToString().Trim().Length == 0) { structElem.Put(PdfName.T, dict.GetAsString(PdfName.T)); } structElem.Put(PdfName.A, attribute); structElem.Put(PdfName.S, PdfName.P); structElem.Put(PdfName.PG, pageref); // Defining a new MCID int mcid = items.ProcessMCID(structParents, item.GetRef()); LOGGER.Info("Using MCID " + mcid); structElem.Put(PdfName.K, new PdfNumber(mcid)); // removing the annotation from the parent tree items.RemoveFromParentTree(structParent); // Adding the XObject to the page PdfName xobj = new PdfName("XObj" + structParent.IntValue); LOGGER.Info("Creating XObject with name " + xobj); xobjects.Put(xobj, xobjr); PdfArray array = dict.GetAsArray(PdfName.RECT); // Getting the position of the annotation Rectangle rect = new Rectangle( array.GetAsNumber(0).FloatValue, array.GetAsNumber(1).FloatValue, array.GetAsNumber(2).FloatValue, array.GetAsNumber(3).FloatValue); rect.Normalize(); // A Do operator is forbidden inside a text block if (inText && !btWrite) { LOGGER.Debug("Introducing extra ET"); byte[] bytes = Encoding.ASCII.GetBytes("ET\n"); baos.Write(bytes, 0, bytes.Length); etExtra = true; } // Writing the marked-content sequence with the Do operator // Note that the position assumes that the CTM wasn't changed in the graphics state // TODO: do the math if the CTM did change! ByteBuffer buf = new ByteBuffer(); buf.Append("/P <</MCID "); buf.Append(mcid); buf.Append(">> BDC\n"); buf.Append("q 1 0 0 1 "); buf.Append(rect.Left.ToString(CultureInfo.InvariantCulture)); buf.Append(" "); buf.Append(rect.Bottom.ToString(CultureInfo.InvariantCulture)); buf.Append(" cm "); buf.Append(xobj.GetBytes()); buf.Append(" Do Q\n"); buf.Append("EMC\n"); buf.Flush(); buf.WriteTo(baos); // if we were inside a text block, we've introduced an ET, so we'll need to write a BT if (inText) { btWrite = true; } }
/** * Parses the content of a page, replacing appearances of annotations * with Form XObjects. * @param page a page dictionary * @throws IOException */ virtual public void Parse(PdfDictionary page, PdfIndirectReference pageref) { LOGGER.Info("Parsing page with reference " + pageref); // initializing member variables baos = new MemoryStream(); this.page = page; this.pageref = pageref; structParents = page.GetAsNumber(PdfName.STRUCTPARENTS); if(structParents == null) throw new DocumentException(MessageLocalization.GetComposedMessage("can.t.read.document.structure")); annots = page.GetAsArray(PdfName.ANNOTS); if(annots == null) annots = new PdfArray(); PdfDictionary resources = page.GetAsDict(PdfName.RESOURCES); xobjects = resources.GetAsDict(PdfName.XOBJECT); if (xobjects == null) { xobjects = new PdfDictionary(); resources.Put(PdfName.XOBJECT, xobjects); } // parsing the content stream of the page PRStream stream = (PRStream) page.GetAsStream(PdfName.CONTENTS); byte[] contentBytes = PdfReader.GetStreamBytes(stream); PRTokeniser tokeniser = new PRTokeniser(new RandomAccessFileOrArray(RASFACTORY.CreateSource(contentBytes))); PdfContentParser ps = new PdfContentParser(tokeniser); List<PdfObject> operands = new List<PdfObject>(); while (ps.Parse(operands).Count > 0) { PdfLiteral opr = (PdfLiteral) operands[operands.Count - 1]; ProcessOperator(opr, operands); } // dealing with orphans while (items.Count > 0 && items[0].GetPageref() == pageref.Number) { StructureItem item = items[0]; if (item is StructureObject) { ConvertToXObject((StructureObject) item); items.RemoveAt(0); } } if(annots.Length == 0) { page.Remove(PdfName.ANNOTS); } else { PdfDictionary annot; for(int i = 0; i < annots.Size; i++) { annot = annots.GetAsDict(i); if(annot.GetAsNumber(PdfName.STRUCTPARENT) == null) throw new DocumentException(MessageLocalization.GetComposedMessage("could.not.flatten.file.untagged.annotations.found")); } } // replacing the content stream baos.Flush(); baos.Close(); stream.SetData(baos.ToArray()); // showing how many items are left LOGGER.Info(String.Format("There are {0} items left for processing", items.Count)); }
/** * Parses the content of a page, replacing appearances of annotations * with Form XObjects. * @param page a page dictionary * @throws IOException */ public void Parse(PdfDictionary page, PdfIndirectReference pageref) { LOGGER.Info("Parsing page with reference " + pageref); // initializing member variables baos = new MemoryStream(); this.page = page; this.pageref = pageref; structParents = page.GetAsNumber(PdfName.STRUCTPARENTS); if (structParents == null) { throw new DocumentException(MessageLocalization.GetComposedMessage("can.t.read.document.structure")); } annots = page.GetAsArray(PdfName.ANNOTS); if (annots == null) { annots = new PdfArray(); } PdfDictionary resources = page.GetAsDict(PdfName.RESOURCES); xobjects = resources.GetAsDict(PdfName.XOBJECT); if (xobjects == null) { xobjects = new PdfDictionary(); resources.Put(PdfName.XOBJECT, xobjects); } // parsing the content stream of the page PRStream stream = (PRStream)page.GetAsStream(PdfName.CONTENTS); byte[] contentBytes = PdfReader.GetStreamBytes(stream); PRTokeniser tokeniser = new PRTokeniser(new RandomAccessFileOrArray(RASFACTORY.CreateSource(contentBytes))); PdfContentParser ps = new PdfContentParser(tokeniser); List <PdfObject> operands = new List <PdfObject>(); while (ps.Parse(operands).Count > 0) { PdfLiteral opr = (PdfLiteral)operands[operands.Count - 1]; ProcessOperator(opr, operands); } // dealing with orphans while (items.Count > 0 && items[0].GetPageref() == pageref.Number) { StructureItem item = items[0]; if (item is StructureObject) { ConvertToXObject((StructureObject)item); items.RemoveAt(0); } } if (annots.Length == 0) { page.Remove(PdfName.ANNOTS); } else { PdfDictionary annot; for (int i = 0; i < annots.Size; i++) { annot = annots.GetAsDict(i); if (annot.GetAsNumber(PdfName.STRUCTPARENT) == null) { throw new DocumentException(MessageLocalization.GetComposedMessage("could.not.flatten.file.untagged.annotations.found")); } } } // replacing the content stream baos.Flush(); baos.Close(); stream.SetData(baos.ToArray()); // showing how many items are left LOGGER.Info(String.Format("There are {0} items left for processing", items.Count)); }
/** * Computes the number of unfiltered bytes that each row of the image will contain. * If the number of bytes results in a partial terminating byte, this number is rounded up * per the PDF specification * @param imageDictionary the dictionary of the inline image * @return the number of bytes per row of the image */ private static int ComputeBytesPerRow(PdfDictionary imageDictionary, PdfDictionary colorSpaceDic){ PdfNumber wObj = imageDictionary.GetAsNumber(PdfName.WIDTH); PdfNumber bpcObj = imageDictionary.GetAsNumber(PdfName.BITSPERCOMPONENT); int cpp = GetComponentsPerPixel(imageDictionary.GetAsName(PdfName.COLORSPACE), colorSpaceDic); int w = wObj.IntValue; int bpc = bpcObj != null ? bpcObj.IntValue : 1; int bytesPerRow = (w * bpc * cpp + 7) / 8; return bytesPerRow; }
/** * Parses the samples of the image from the underlying content parser, ignoring all filters. * The parser must be positioned immediately after the ID operator that ends the inline image's dictionary. * The parser will be left positioned immediately following the EI operator. * This is primarily useful if no filters have been applied. * @param imageDictionary the dictionary of the inline image * @param ps the content parser * @return the samples of the image * @throws IOException if anything bad happens during parsing */ private static byte[] ParseUnfilteredSamples(PdfDictionary imageDictionary, PdfDictionary colorSpaceDic, PdfContentParser ps) { // special case: when no filter is specified, we just read the number of bits // per component, multiplied by the width and height. if (imageDictionary.Contains(PdfName.FILTER)) throw new ArgumentException("Dictionary contains filters"); PdfNumber h = imageDictionary.GetAsNumber(PdfName.HEIGHT); int bytesToRead = ComputeBytesPerRow(imageDictionary, colorSpaceDic) * h.IntValue; byte[] bytes = new byte[bytesToRead]; PRTokeniser tokeniser = ps.GetTokeniser(); int shouldBeWhiteSpace = tokeniser.Read(); // skip next character (which better be a whitespace character - I suppose we could check for this) // from the PDF spec: Unless the image uses ASCIIHexDecode or ASCII85Decode as one of its filters, the ID operator shall be followed by a single white-space character, and the next character shall be interpreted as the first byte of image data. // unfortunately, we've seen some PDFs where there is no space following the ID, so we have to capture this case and handle it int startIndex = 0; if (!PRTokeniser.IsWhitespace(shouldBeWhiteSpace) || shouldBeWhiteSpace == 0){ // tokeniser treats 0 as whitespace, but for our purposes, we shouldn't) bytes[0] = (byte)shouldBeWhiteSpace; startIndex++; } for (int i = startIndex; i < bytesToRead; i++){ int ch = tokeniser.Read(); if (ch == -1) throw new InlineImageParseException("End of content stream reached before end of image data"); bytes[i] = (byte)ch; } PdfObject ei = ps.ReadPRObject(); if (!ei.ToString().Equals("EI")) throw new InlineImageParseException("EI not found after end of image data"); return bytes; }
/// <summary>Creates a Type 3 font based on an existing font dictionary, which must be an indirect object.</summary> /// <param name="fontDictionary">a dictionary of type <c>/Font</c>, must have an indirect reference.</param> internal PdfType3Font(PdfDictionary fontDictionary) : base(fontDictionary) { subset = true; embedded = true; fontProgram = new Type3Font(false); fontEncoding = DocFontEncoding.CreateDocFontEncoding(fontDictionary.Get(PdfName.Encoding), toUnicode); PdfDictionary charProcsDic = GetPdfObject().GetAsDictionary(PdfName.CharProcs); PdfArray fontMatrixArray = GetPdfObject().GetAsArray(PdfName.FontMatrix); if (GetPdfObject().ContainsKey(PdfName.FontBBox)) { PdfArray fontBBox = GetPdfObject().GetAsArray(PdfName.FontBBox); fontProgram.GetFontMetrics().SetBbox(fontBBox.GetAsNumber(0).IntValue(), fontBBox.GetAsNumber(1).IntValue( ), fontBBox.GetAsNumber(2).IntValue(), fontBBox.GetAsNumber(3).IntValue()); } else { fontProgram.GetFontMetrics().SetBbox(0, 0, 0, 0); } int firstChar = NormalizeFirstLastChar(fontDictionary.GetAsNumber(PdfName.FirstChar), 0); int lastChar = NormalizeFirstLastChar(fontDictionary.GetAsNumber(PdfName.LastChar), 255); for (int i = firstChar; i <= lastChar; i++) { shortTag[i] = 1; } int[] widths = FontUtil.ConvertSimpleWidthsArray(fontDictionary.GetAsArray(PdfName.Widths), firstChar, 0); double[] fontMatrix = new double[6]; for (int i = 0; i < fontMatrixArray.Size(); i++) { fontMatrix[i] = ((PdfNumber)fontMatrixArray.Get(i)).GetValue(); } SetFontMatrix(fontMatrix); if (toUnicode != null && toUnicode.HasByteMappings() && fontEncoding.HasDifferences()) { for (int i = 0; i < 256; i++) { int unicode = fontEncoding.GetUnicode(i); PdfName glyphName = new PdfName(fontEncoding.GetDifference(i)); if (unicode != -1 && !FontEncoding.NOTDEF.Equals(glyphName.GetValue()) && charProcsDic.ContainsKey(glyphName )) { ((Type3Font)GetFontProgram()).AddGlyph(i, unicode, widths[i], null, new Type3Glyph(charProcsDic.GetAsStream (glyphName), GetDocument())); } } } IDictionary <int, int?> unicodeToCode = null; if (toUnicode != null) { try { unicodeToCode = toUnicode.CreateReverseMapping(); } catch (Exception) { } } foreach (PdfName glyphName in charProcsDic.KeySet()) { int unicode = AdobeGlyphList.NameToUnicode(glyphName.GetValue()); int code = -1; if (fontEncoding.CanEncode(unicode)) { code = fontEncoding.ConvertToByte(unicode); } else { if (unicodeToCode != null && unicodeToCode.ContainsKey(unicode)) { code = (int)unicodeToCode.Get(unicode); } } if (code != -1 && GetFontProgram().GetGlyphByCode(code) == null) { ((Type3Font)GetFontProgram()).AddGlyph(code, unicode, widths[code], null, new Type3Glyph(charProcsDic.GetAsStream (glyphName), GetDocument())); } } FillFontDescriptor(fontDictionary.GetAsDictionary(PdfName.FontDescriptor)); }