/** * Extracts document level attachments * * @param filename a file from which document level attachments will be extracted * @throws IOException */ public void extractDocLevelAttachments(String filename) throws IOException { PdfReader reader = new PdfReader(filename); PdfDictionary root = reader.getCatalog(); PdfDictionary documentnames = root.getAsDict(PdfName.NAMES); PdfDictionary embeddedfiles = documentnames.getAsDict(PdfName.EMBEDDEDFILES); PdfArray filespecs = embeddedfiles.getAsArray(PdfName.NAMES); PdfDictionary filespec; PdfDictionary refs; FileOutputStream fos; PRStream stream; for (int i = 0; i < filespecs.size(); ) { filespecs.getAsString(i++); filespec = filespecs.getAsDict(i++); refs = filespec.getAsDict(PdfName.EF); for (PdfName key : refs.getKeys()) { fos = new FileOutputStream(String.format(PATH, filespec.getAsString(key).toString())); stream = (PRStream) PdfReader.getPdfObject(refs.getAsIndirectObject(key)); fos.write(PdfReader.getStreamBytes(stream)); fos.flush(); fos.close(); } } reader.close(); }
public PdfObject getPdfObject(PdfWriter writer) { PdfArray array = new PdfArray(PdfName.LAB); PdfDictionary dictionary = new PdfDictionary(); if (whitePoint == null || whitePoint.length != 3 || whitePoint[0] < 0.000001f || whitePoint[2] < 0.000001f || whitePoint[1] < 0.999999f || whitePoint[1] > 1.000001f) throw new RuntimeException(MessageLocalization.getComposedMessage("lab.cs.white.point")); dictionary.put(PdfName.WHITEPOINT, new PdfArray(whitePoint)); if (blackPoint != null) { if (blackPoint.length != 3 || blackPoint[0] < -0.000001f || blackPoint[1] < -0.000001f || blackPoint[2] < -0.000001f) throw new RuntimeException(MessageLocalization.getComposedMessage("lab.cs.black.point")); dictionary.put(PdfName.BLACKPOINT, new PdfArray(blackPoint)); } if (range != null) { if (range.length != 4 || range[0] > range[1] || range[2] > range[3]) throw new RuntimeException(MessageLocalization.getComposedMessage("lab.cs.range")); dictionary.put(PdfName.RANGE, new PdfArray(range)); } array.add(dictionary); return array; }
/** * Searches for a tag in a page. * * @param tag the name of the tag * @param object an identifier to find the marked content * @param page a page dictionary * @throws IOException */ public void parseTag(String tag, PdfObject object, PdfDictionary page) throws IOException { PRStream stream = (PRStream) page.getAsStream(PdfName.CONTENTS); // if the identifier is a number, we can extract the content right away if (object instanceof PdfNumber) { PdfNumber mcid = (PdfNumber) object; RenderFilter filter = new MarkedContentRenderFilter(mcid.intValue()); TextExtractionStrategy strategy = new SimpleTextExtractionStrategy(); FilteredTextRenderListener listener = new FilteredTextRenderListener(strategy, filter); PdfContentStreamProcessor processor = new PdfContentStreamProcessor(listener); processor.processContent(PdfReader.getStreamBytes(stream), page.getAsDict(PdfName.RESOURCES)); out.print(SimpleXMLParser.escapeXML(listener.getResultantText(), true)); } // if the identifier is an array, we call the parseTag method // recursively else if (object instanceof PdfArray) { PdfArray arr = (PdfArray) object; int n = arr.size(); for (int i = 0; i < n; i++) { parseTag(tag, arr.getPdfObject(i), page); if (i < n - 1) out.println(); } } // if the identifier is a dictionary, we get the resources from the // dictionary else if (object instanceof PdfDictionary) { PdfDictionary mcr = (PdfDictionary) object; parseTag(tag, mcr.getDirectObject(PdfName.MCID), mcr.getAsDict(PdfName.PG)); } }
/** * A set-OCG-state action (PDF 1.5) sets the state of one or more optional content groups. * * @param state an array consisting of any number of sequences beginning with a <CODE>PdfName * </CODE> or <CODE>String</CODE> (ON, OFF, or Toggle) followed by one or more optional * content group dictionaries <CODE>PdfLayer</CODE> or a <CODE>PdfIndirectReference</CODE> to * a <CODE>PdfLayer</CODE>.<br> * The array elements are processed from left to right; each name is applied to the subsequent * groups until the next name is encountered: * <ul> * <li>ON sets the state of subsequent groups to ON * <li>OFF sets the state of subsequent groups to OFF * <li>Toggle reverses the state of subsequent groups * </ul> * * @param preserveRB if <CODE>true</CODE>, indicates that radio-button state relationships between * optional content groups (as specified by the RBGroups entry in the current configuration * dictionary) should be preserved when the states in the <CODE>state</CODE> array are * applied. That is, if a group is set to ON (either by ON or Toggle) during processing of the * <CODE>state</CODE> array, any other groups belong to the same radio-button group are turned * OFF. If a group is set to OFF, there is no effect on other groups.<br> * If <CODE>false</CODE>, radio-button state relationships, if any, are ignored * @return the action */ public static PdfAction setOCGstate(ArrayList<Object> state, boolean preserveRB) { PdfAction action = new PdfAction(); action.put(PdfName.S, PdfName.SETOCGSTATE); PdfArray a = new PdfArray(); for (int k = 0; k < state.size(); ++k) { Object o = state.get(k); if (o == null) continue; if (o instanceof PdfIndirectReference) a.add((PdfIndirectReference) o); else if (o instanceof PdfLayer) a.add(((PdfLayer) o).getRef()); else if (o instanceof PdfName) a.add((PdfName) o); else if (o instanceof String) { PdfName name = null; String s = (String) o; if (s.equalsIgnoreCase("on")) name = PdfName.ON; else if (s.equalsIgnoreCase("off")) name = PdfName.OFF; else if (s.equalsIgnoreCase("toggle")) name = PdfName.TOGGLE; else throw new IllegalArgumentException( MessageLocalization.getComposedMessage( "a.string.1.was.passed.in.state.only.on.off.and.toggle.are.allowed", s)); a.add(name); } else throw new IllegalArgumentException( MessageLocalization.getComposedMessage( "invalid.type.was.passed.in.state.1", o.getClass().getName())); } action.put(PdfName.STATE, a); if (!preserveRB) action.put(PdfName.PRESERVERB, PdfBoolean.PDFFALSE); return action; }
private void adjustTabOrder(PdfArray annots, PdfIndirectReference ind, PdfNumber nn) { int v = nn.intValue(); ArrayList<Integer> t = tabOrder.get(annots); if (t == null) { t = new ArrayList<Integer>(); int size = annots.size() - 1; for (int k = 0; k < size; ++k) { t.add(zero); } t.add(Integer.valueOf(v)); tabOrder.put(annots, t); annots.add(ind); } else { int size = t.size() - 1; for (int k = size; k >= 0; --k) { if (t.get(k).intValue() <= v) { t.add(k + 1, Integer.valueOf(v)); annots.add(k + 1, ind); size = -2; break; } } if (size != -2) { t.add(0, Integer.valueOf(v)); annots.add(0, ind); } } }
/** Translate a PRArray to a PdfArray. Also translate all of the objects contained in it */ protected PdfArray copyArray(PdfArray in) throws IOException, BadPdfFormatException { PdfArray out = new PdfArray(); for (Iterator<PdfObject> i = in.listIterator(); i.hasNext(); ) { PdfObject value = i.next(); out.add(copyObject(value)); } return out; }
/** * Add a chained action. * * @param na the next action */ public void next(PdfAction na) { PdfObject nextAction = get(PdfName.NEXT); if (nextAction == null) put(PdfName.NEXT, na); else if (nextAction.isDictionary()) { PdfArray array = new PdfArray(nextAction); array.add(na); put(PdfName.NEXT, array); } else { ((PdfArray) nextAction).add(na); } }
/** * Gets a list of X509CRL objects from a Document Security Store. * * @return a list of CRLs * @throws GeneralSecurityException * @throws IOException */ public List<X509CRL> getCRLsFromDSS() throws GeneralSecurityException, IOException { List<X509CRL> crls = new ArrayList<X509CRL>(); if (dss == null) return crls; PdfArray crlarray = dss.getAsArray(PdfName.CRLS); if (crlarray == null) return crls; CertificateFactory cf = CertificateFactory.getInstance("X.509"); for (int i = 0; i < crlarray.size(); i++) { PRStream stream = (PRStream) crlarray.getAsStream(i); X509CRL crl = (X509CRL) cf.generateCRL(new ByteArrayInputStream(PdfReader.getStreamBytes(stream))); crls.add(crl); } return crls; }
static PdfArray buildArray(Object names[]) { PdfArray array = new PdfArray(); for (int k = 0; k < names.length; ++k) { Object obj = names[k]; if (obj instanceof String) array.add(new PdfString((String) obj)); else if (obj instanceof PdfAnnotation) array.add(((PdfAnnotation) obj).getIndirectReference()); else throw new RuntimeException( MessageLocalization.getComposedMessage( "the.array.must.contain.string.or.pdfannotation")); } return array; }
private Image indexedModel(byte bdata[], int bpc, int paletteEntries) throws BadElementException { Image img = new ImgRaw(width, height, 1, bpc, bdata); PdfArray colorspace = new PdfArray(); colorspace.add(PdfName.INDEXED); colorspace.add(PdfName.DEVICERGB); byte np[] = getPalette(paletteEntries); int len = np.length; colorspace.add(new PdfNumber(len / 3 - 1)); colorspace.add(new PdfString(np)); PdfDictionary ad = new PdfDictionary(); ad.put(PdfName.COLORSPACE, colorspace); img.setAdditional(ad); return img; }
/** @since 2.1.5; before 2.1.5 the method was private */ protected void updateCalculationOrder(PdfReader reader) { PdfDictionary catalog = reader.getCatalog(); PdfDictionary acro = catalog.getAsDict(PdfName.ACROFORM); if (acro == null) return; PdfArray co = acro.getAsArray(PdfName.CO); if (co == null || co.size() == 0) return; AcroFields af = reader.getAcroFields(); for (int k = 0; k < co.size(); ++k) { PdfObject obj = co.getPdfObject(k); if (obj == null || !obj.isIndirect()) continue; String name = getCOName(reader, (PRIndirectReference) obj); if (af.getFieldItem(name) == null) continue; name = "." + name; if (calculationOrder.contains(name)) continue; calculationOrder.add(name); } }
/** * Gets OCSP responses from the Document Security Store. * * @return a list of BasicOCSPResp objects * @throws IOException * @throws GeneralSecurityException */ public List<BasicOCSPResp> getOCSPResponsesFromDSS() throws IOException, GeneralSecurityException { List<BasicOCSPResp> ocsps = new ArrayList<BasicOCSPResp>(); if (dss == null) return ocsps; PdfArray ocsparray = dss.getAsArray(PdfName.OCSPS); if (ocsparray == null) return ocsps; for (int i = 0; i < ocsparray.size(); i++) { PRStream stream = (PRStream) ocsparray.getAsStream(i); OCSPResp ocspResponse = new OCSPResp(PdfReader.getStreamBytes(stream)); if (ocspResponse.getStatus() == 0) try { ocsps.add((BasicOCSPResp) ocspResponse.getResponseObject()); } catch (OCSPException e) { throw new GeneralSecurityException(e); } } return ocsps; }
public void alterContents() throws IOException { if (over == null && under == null) return; PdfArray ar = null; PdfObject content = PdfReader.getPdfObject(pageN.get(PdfName.CONTENTS), pageN); if (content == null) { ar = new PdfArray(); pageN.put(PdfName.CONTENTS, ar); } else if (content.isArray()) { ar = (PdfArray) content; } else if (content.isStream()) { ar = new PdfArray(); ar.add(pageN.get(PdfName.CONTENTS)); pageN.put(PdfName.CONTENTS, ar); } else { ar = new PdfArray(); pageN.put(PdfName.CONTENTS, ar); } ByteBuffer out = new ByteBuffer(); if (under != null) { out.append(PdfContents.SAVESTATE); applyRotation(pageN, out); out.append(under.getInternalBuffer()); out.append(PdfContents.RESTORESTATE); } if (over != null) out.append(PdfContents.SAVESTATE); PdfStream stream = new PdfStream(out.toByteArray()); stream.flateCompress(cstp.getCompressionLevel()); PdfIndirectReference ref1 = cstp.addToBody(stream).getIndirectReference(); ar.addFirst(ref1); out.reset(); if (over != null) { out.append(' '); out.append(PdfContents.RESTORESTATE); out.append(PdfContents.SAVESTATE); applyRotation(pageN, out); out.append(over.getInternalBuffer()); out.append(PdfContents.RESTORESTATE); stream = new PdfStream(out.toByteArray()); stream.flateCompress(cstp.getCompressionLevel()); ar.add(cstp.addToBody(stream).getIndirectReference()); } pageN.put(PdfName.RESOURCES, pageResources.getResources()); }
protected void createAcroForms() throws IOException { if (fieldTree.isEmpty()) return; form = new PdfDictionary(); form.put(PdfName.DR, resources); propagate(resources, null, false); if (needAppearances) { form.put(PdfName.NEEDAPPEARANCES, PdfBoolean.PDFTRUE); } form.put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g ")); tabOrder = new HashMap<PdfArray, ArrayList<Integer>>(); calculationOrderRefs = new ArrayList<Object>(calculationOrder); form.put(PdfName.FIELDS, branchForm(fieldTree, null, "")); if (hasSignature) form.put(PdfName.SIGFLAGS, new PdfNumber(3)); PdfArray co = new PdfArray(); for (int k = 0; k < calculationOrderRefs.size(); ++k) { Object obj = calculationOrderRefs.get(k); if (obj instanceof PdfIndirectReference) co.add((PdfIndirectReference) obj); } if (co.size() > 0) form.put(PdfName.CO, co); }
private void processType0(PdfDictionary font) { try { PdfObject toUniObject = PdfReader.getPdfObjectRelease(font.get(PdfName.TOUNICODE)); PdfArray df = (PdfArray) PdfReader.getPdfObjectRelease(font.get(PdfName.DESCENDANTFONTS)); PdfDictionary cidft = (PdfDictionary) PdfReader.getPdfObjectRelease(df.getPdfObject(0)); PdfNumber dwo = (PdfNumber) PdfReader.getPdfObjectRelease(cidft.get(PdfName.DW)); int dw = 1000; if (dwo != null) dw = dwo.intValue(); IntHashtable widths = readWidths((PdfArray) PdfReader.getPdfObjectRelease(cidft.get(PdfName.W))); PdfDictionary fontDesc = (PdfDictionary) PdfReader.getPdfObjectRelease(cidft.get(PdfName.FONTDESCRIPTOR)); fillFontDesc(fontDesc); if (toUniObject instanceof PRStream) { fillMetrics(PdfReader.getStreamBytes((PRStream) toUniObject), widths, dw); } } catch (Exception e) { throw new ExceptionConverter(e); } }
public static PdfShading type2( PdfWriter writer, BaseColor colorSpace, float coords[], float domain[], PdfFunction function, boolean extend[]) { PdfShading sp = new PdfShading(writer); sp.shading = new PdfDictionary(); sp.shadingType = 2; sp.shading.put(PdfName.SHADINGTYPE, new PdfNumber(sp.shadingType)); sp.setColorSpace(colorSpace); sp.shading.put(PdfName.COORDS, new PdfArray(coords)); if (domain != null) sp.shading.put(PdfName.DOMAIN, new PdfArray(domain)); sp.shading.put(PdfName.FUNCTION, function.getReference()); if (extend != null && (extend[0] || extend[1])) { PdfArray array = new PdfArray(extend[0] ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE); array.add(extend[1] ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE); sp.shading.put(PdfName.EXTEND, array); } return sp; }
private void fillFontDesc(PdfDictionary fontDesc) { if (fontDesc == null) return; PdfNumber v = fontDesc.getAsNumber(PdfName.ASCENT); if (v != null) ascender = v.floatValue(); v = fontDesc.getAsNumber(PdfName.CAPHEIGHT); if (v != null) capHeight = v.floatValue(); v = fontDesc.getAsNumber(PdfName.DESCENT); if (v != null) descender = v.floatValue(); v = fontDesc.getAsNumber(PdfName.ITALICANGLE); if (v != null) italicAngle = v.floatValue(); v = fontDesc.getAsNumber(PdfName.FONTWEIGHT); if (v != null) { fontWeight = v.floatValue(); } PdfArray bbox = fontDesc.getAsArray(PdfName.FONTBBOX); if (bbox != null) { llx = bbox.getAsNumber(0).floatValue(); lly = bbox.getAsNumber(1).floatValue(); urx = bbox.getAsNumber(2).floatValue(); ury = bbox.getAsNumber(3).floatValue(); if (llx > urx) { float t = llx; llx = urx; urx = t; } if (lly > ury) { float t = lly; lly = ury; ury = t; } } float maxAscent = Math.max(ury, ascender); float minDescent = Math.min(lly, descender); ascender = maxAscent * 1000 / (maxAscent - minDescent); descender = minDescent * 1000 / (maxAscent - minDescent); }
private IntHashtable readWidths(PdfArray ws) { IntHashtable hh = new IntHashtable(); if (ws == null) return hh; for (int k = 0; k < ws.size(); ++k) { int c1 = ((PdfNumber) PdfReader.getPdfObjectRelease(ws.getPdfObject(k))).intValue(); PdfObject obj = PdfReader.getPdfObjectRelease(ws.getPdfObject(++k)); if (obj.isArray()) { PdfArray a2 = (PdfArray) obj; for (int j = 0; j < a2.size(); ++j) { int c2 = ((PdfNumber) PdfReader.getPdfObjectRelease(a2.getPdfObject(j))).intValue(); hh.put(c1++, c2); } } else { int c2 = ((PdfNumber) obj).intValue(); int w = ((PdfNumber) PdfReader.getPdfObjectRelease(ws.getPdfObject(++k))).intValue(); for (; c1 <= c2; ++c1) hh.put(c1, w); } } return hh; }
private void doType1TT() { CMapToUnicode toUnicode = null; PdfObject enc = PdfReader.getPdfObject(font.get(PdfName.ENCODING)); if (enc == null) { fillEncoding(null); try { toUnicode = processToUnicode(); if (toUnicode != null) { Map<Integer, Integer> rm = toUnicode.createReverseMapping(); for (Map.Entry<Integer, Integer> kv : rm.entrySet()) { uni2byte.put(kv.getKey().intValue(), kv.getValue().intValue()); } } } catch (Exception ex) { throw new ExceptionConverter(ex); } } else { if (enc.isName()) fillEncoding((PdfName) enc); else if (enc.isDictionary()) { PdfDictionary encDic = (PdfDictionary) enc; enc = PdfReader.getPdfObject(encDic.get(PdfName.BASEENCODING)); if (enc == null) fillEncoding(null); else fillEncoding((PdfName) enc); PdfArray diffs = encDic.getAsArray(PdfName.DIFFERENCES); if (diffs != null) { diffmap = new IntHashtable(); int currentNumber = 0; for (int k = 0; k < diffs.size(); ++k) { PdfObject obj = diffs.getPdfObject(k); if (obj.isNumber()) currentNumber = ((PdfNumber) obj).intValue(); else { int c[] = GlyphList.nameToUnicode(PdfName.decodeName(((PdfName) obj).toString())); if (c != null && c.length > 0) { uni2byte.put(c[0], currentNumber); diffmap.put(c[0], currentNumber); } else { if (toUnicode == null) { toUnicode = processToUnicode(); if (toUnicode == null) { toUnicode = new CMapToUnicode(); } } final String unicode = toUnicode.lookup(new byte[] {(byte) currentNumber}, 0, 1); if ((unicode != null) && (unicode.length() == 1)) { this.uni2byte.put(unicode.charAt(0), currentNumber); this.diffmap.put(unicode.charAt(0), currentNumber); } } ++currentNumber; } } } } } PdfArray newWidths = font.getAsArray(PdfName.WIDTHS); PdfNumber first = font.getAsNumber(PdfName.FIRSTCHAR); PdfNumber last = font.getAsNumber(PdfName.LASTCHAR); if (BuiltinFonts14.containsKey(fontName)) { BaseFont bf; try { bf = BaseFont.createFont(fontName, WINANSI, false); } catch (Exception e) { throw new ExceptionConverter(e); } int e[] = uni2byte.toOrderedKeys(); for (int k = 0; k < e.length; ++k) { int n = uni2byte.get(e[k]); widths[n] = bf.getRawWidth(n, GlyphList.unicodeToName(e[k])); } if (diffmap != null) { // widths for diffmap must override existing ones e = diffmap.toOrderedKeys(); for (int k = 0; k < e.length; ++k) { int n = diffmap.get(e[k]); widths[n] = bf.getRawWidth(n, GlyphList.unicodeToName(e[k])); } diffmap = null; } ascender = bf.getFontDescriptor(ASCENT, 1000); capHeight = bf.getFontDescriptor(CAPHEIGHT, 1000); descender = bf.getFontDescriptor(DESCENT, 1000); italicAngle = bf.getFontDescriptor(ITALICANGLE, 1000); fontWeight = bf.getFontDescriptor(FONT_WEIGHT, 1000); llx = bf.getFontDescriptor(BBOXLLX, 1000); lly = bf.getFontDescriptor(BBOXLLY, 1000); urx = bf.getFontDescriptor(BBOXURX, 1000); ury = bf.getFontDescriptor(BBOXURY, 1000); } if (first != null && last != null && newWidths != null) { int f = first.intValue(); int nSize = f + newWidths.size(); if (widths.length < nSize) { int[] tmp = new int[nSize]; System.arraycopy(widths, 0, tmp, 0, f); widths = tmp; } for (int k = 0; k < newWidths.size(); ++k) { widths[f + k] = newWidths.getAsNumber(k).intValue(); } } fillFontDesc(font.getAsDict(PdfName.FONTDESCRIPTOR)); }
private void fillMetrics(byte[] touni, IntHashtable widths, int dw) { try { PdfContentParser ps = new PdfContentParser(new PRTokeniser(touni)); PdfObject ob = null; boolean notFound = true; int nestLevel = 0; int maxExc = 50; while ((notFound || nestLevel > 0)) { try { ob = ps.readPRObject(); } catch (Exception ex) { if (--maxExc < 0) break; continue; } if (ob == null) break; if (ob.type() == PdfContentParser.COMMAND_TYPE) { if (ob.toString().equals("begin")) { notFound = false; nestLevel++; } else if (ob.toString().equals("end")) { nestLevel--; } else if (ob.toString().equals("beginbfchar")) { while (true) { PdfObject nx = ps.readPRObject(); if (nx.toString().equals("endbfchar")) break; String cid = decodeString((PdfString) nx); String uni = decodeString((PdfString) ps.readPRObject()); if (uni.length() == 1) { int cidc = cid.charAt(0); int unic = uni.charAt(uni.length() - 1); int w = dw; if (widths.containsKey(cidc)) w = widths.get(cidc); metrics.put(Integer.valueOf(unic), new int[] {cidc, w}); } } } else if (ob.toString().equals("beginbfrange")) { while (true) { PdfObject nx = ps.readPRObject(); if (nx.toString().equals("endbfrange")) break; String cid1 = decodeString((PdfString) nx); String cid2 = decodeString((PdfString) ps.readPRObject()); int cid1c = cid1.charAt(0); int cid2c = cid2.charAt(0); PdfObject ob2 = ps.readPRObject(); if (ob2.isString()) { String uni = decodeString((PdfString) ob2); if (uni.length() == 1) { int unic = uni.charAt(uni.length() - 1); for (; cid1c <= cid2c; cid1c++, unic++) { int w = dw; if (widths.containsKey(cid1c)) w = widths.get(cid1c); metrics.put(Integer.valueOf(unic), new int[] {cid1c, w}); } } } else { PdfArray a = (PdfArray) ob2; for (int j = 0; j < a.size(); ++j, ++cid1c) { String uni = decodeString(a.getAsString(j)); if (uni.length() == 1) { int unic = uni.charAt(uni.length() - 1); int w = dw; if (widths.containsKey(cid1c)) w = widths.get(cid1c); metrics.put(Integer.valueOf(unic), new int[] {cid1c, w}); } } } } } } } } catch (Exception e) { throw new ExceptionConverter(e); } }
@SuppressWarnings("unchecked") protected PdfArray branchForm( HashMap<String, Object> level, PdfIndirectReference parent, String fname) throws IOException { PdfArray arr = new PdfArray(); for (Map.Entry<String, Object> entry : level.entrySet()) { String name = entry.getKey(); Object obj = entry.getValue(); PdfIndirectReference ind = getPdfIndirectReference(); PdfDictionary dic = new PdfDictionary(); if (parent != null) dic.put(PdfName.PARENT, parent); dic.put(PdfName.T, new PdfString(name, PdfObject.TEXT_UNICODE)); String fname2 = fname + "." + name; int coidx = calculationOrder.indexOf(fname2); if (coidx >= 0) calculationOrderRefs.set(coidx, ind); if (obj instanceof HashMap) { dic.put(PdfName.KIDS, branchForm((HashMap<String, Object>) obj, ind, fname2)); arr.add(ind); addToBody(dic, ind); } else { ArrayList<Object> list = (ArrayList<Object>) obj; dic.mergeDifferent((PdfDictionary) list.get(0)); if (list.size() == 3) { dic.mergeDifferent((PdfDictionary) list.get(2)); int page = ((Integer) list.get(1)).intValue(); PdfDictionary pageDic = pageDics.get(page - 1); PdfArray annots = pageDic.getAsArray(PdfName.ANNOTS); if (annots == null) { annots = new PdfArray(); pageDic.put(PdfName.ANNOTS, annots); } PdfNumber nn = (PdfNumber) dic.get(iTextTag); dic.remove(iTextTag); adjustTabOrder(annots, ind, nn); } else { PdfArray kids = new PdfArray(); for (int k = 1; k < list.size(); k += 2) { int page = ((Integer) list.get(k)).intValue(); PdfDictionary pageDic = pageDics.get(page - 1); PdfArray annots = pageDic.getAsArray(PdfName.ANNOTS); if (annots == null) { annots = new PdfArray(); pageDic.put(PdfName.ANNOTS, annots); } PdfDictionary widget = new PdfDictionary(); widget.merge((PdfDictionary) list.get(k + 1)); widget.put(PdfName.PARENT, ind); PdfNumber nn = (PdfNumber) widget.get(iTextTag); widget.remove(iTextTag); PdfIndirectReference wref = addToBody(widget).getIndirectReference(); adjustTabOrder(annots, wref, nn); kids.add(wref); propagate(widget, null, false); } dic.put(PdfName.KIDS, kids); } arr.add(ind); addToBody(dic, ind); propagate(dic, null, false); } } return arr; }
public void addAnnotation(PdfAnnotation annot) { try { ArrayList<PdfAnnotation> allAnnots = new ArrayList<PdfAnnotation>(); if (annot.isForm()) { PdfFormField field = (PdfFormField) annot; if (field.getParent() != null) return; expandFields(field, allAnnots); if (cstp.fieldTemplates == null) cstp.fieldTemplates = new HashSet<PdfTemplate>(); } else allAnnots.add(annot); for (int k = 0; k < allAnnots.size(); ++k) { annot = allAnnots.get(k); if (annot.isForm()) { if (!annot.isUsed()) { HashSet<PdfTemplate> templates = annot.getTemplates(); if (templates != null) cstp.fieldTemplates.addAll(templates); } PdfFormField field = (PdfFormField) annot; if (field.getParent() == null) addDocumentField(field.getIndirectReference()); } if (annot.isAnnotation()) { PdfObject pdfobj = PdfReader.getPdfObject(pageN.get(PdfName.ANNOTS), pageN); PdfArray annots = null; if (pdfobj == null || !pdfobj.isArray()) { annots = new PdfArray(); pageN.put(PdfName.ANNOTS, annots); } else annots = (PdfArray) pdfobj; annots.add(annot.getIndirectReference()); if (!annot.isUsed()) { PdfRectangle rect = (PdfRectangle) annot.get(PdfName.RECT); if (rect != null && (rect.left() != 0 || rect.right() != 0 || rect.top() != 0 || rect.bottom() != 0)) { int rotation = reader.getPageRotation(pageN); Rectangle pageSize = reader.getPageSizeWithRotation(pageN); switch (rotation) { case 90: annot.put( PdfName.RECT, new PdfRectangle( pageSize.getTop() - rect.bottom(), rect.left(), pageSize.getTop() - rect.top(), rect.right())); break; case 180: annot.put( PdfName.RECT, new PdfRectangle( pageSize.getRight() - rect.left(), pageSize.getTop() - rect.bottom(), pageSize.getRight() - rect.right(), pageSize.getTop() - rect.top())); break; case 270: annot.put( PdfName.RECT, new PdfRectangle( rect.bottom(), pageSize.getRight() - rect.left(), rect.top(), pageSize.getRight() - rect.right())); break; } } } } if (!annot.isUsed()) { annot.setUsed(); cstp.addToBody(annot, annot.getIndirectReference()); } } } catch (IOException e) { throw new ExceptionConverter(e); } }
/** * If the child of a structured element is an array, we need to loop over the elements. * * @param k the child array to inspect */ public void inspectChildArray(PdfArray k) throws IOException { if (k == null) return; for (int i = 0; i < k.size(); i++) { inspectChild(k.getDirectObject(i)); } }