/** * Processes a dictionary. * In case of font dictionaries, the dictionary is processed. */ public void UnembedTTF(PdfDictionary dict) { // we ignore all dictionaries that aren't font dictionaries if (!dict.IsFont()) { return; } // we only remove TTF fonts if (dict.GetAsDict(PdfName.FONTFILE2) != null) { return; } // check if a subset was used (in which case we remove the prefix) PdfName baseFont = dict.GetAsName(PdfName.BASEFONT); if (baseFont.GetBytes()[7] == '+') { baseFont = new PdfName(baseFont.ToString().Substring(8)); dict.Put(PdfName.BASEFONT, baseFont); } // we check if there's a font descriptor PdfDictionary fontDescriptor = dict.GetAsDict(PdfName.FONTDESCRIPTOR); if (fontDescriptor == null) { return; } // is there is, we replace the fontname and remove the font file fontDescriptor.Put(PdfName.FONTNAME, baseFont); fontDescriptor.Remove(PdfName.FONTFILE2); }
/** * 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; } }
/** * Converts an annotation structure item to a Form XObject annotation. * @param item the structure item * @throws IOException */ virtual 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; }