/** * 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 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( "A string '" + s + " was passed in state. Only 'ON', 'OFF' and 'Toggle' are allowed."); a.add(name); } else throw new IllegalArgumentException( "Invalid type was passed in state: " + o.getClass().getName()); } action.put(PdfName.STATE, a); if (!preserveRB) action.put(PdfName.PRESERVERB, PdfBoolean.PDFFALSE); return action; }
protected static PdfArray processOptions(String options[]) { PdfArray array = new PdfArray(); for (int k = 0; k < options.length; ++k) { array.add(new PdfString(options[k], PdfObject.TEXT_UNICODE)); } return array; }
/** 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 i = in.listIterator(); i.hasNext(); ) { PdfObject value = (PdfObject) i.next(); out.add(copyObject(value)); } return out; }
protected static PdfArray processOptions(String options[][]) { PdfArray array = new PdfArray(); for (int k = 0; k < options.length; ++k) { String subOption[] = options[k]; PdfArray ar2 = new PdfArray(new PdfString(subOption[0], PdfObject.TEXT_UNICODE)); ar2.add(new PdfString(subOption[1], PdfObject.TEXT_UNICODE)); array.add(ar2); } return array; }
/** * 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); } }
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("The array must contain String or PdfAnnotation."); } return array; }
public void setUsed() { used = true; if (parent != null) put(PdfName.PARENT, parent.getIndirectReference()); if (kids != null) { PdfArray array = new PdfArray(); for (int k = 0; k < kids.size(); ++k) array.add(kids.get(k).getIndirectReference()); put(PdfName.KIDS, array); } if (templates == null) return; PdfDictionary dic = new PdfDictionary(); for (PdfTemplate template : templates) { mergeResources(dic, (PdfDictionary) template.getResources()); } put(PdfName.DR, dic); }
/** * 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) { for (Iterator it = fieldlist.getArrayList().iterator(); it.hasNext(); ) { PRIndirectReference ref = (PRIndirectReference) it.next(); PdfDictionary dict = (PdfDictionary) PdfReader.getPdfObjectRelease(ref); // 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); boolean isFieldDict = tField != null; if (isFieldDict) { myFieldDict = ref; 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.remove(stack.size() - 1); // pop } else { // leaf node if (myFieldDict != null) { PdfDictionary mergedDict = (PdfDictionary) stack.get(stack.size() - 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.put(myTitle, fi); } } } }
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()); }
/** extracts attachments from PDF File */ @SuppressWarnings("unchecked") protected Map extractAttachments(PdfReader reader) throws IOException { Map fileMap = new HashMap(); PdfDictionary catalog = reader.getCatalog(); PdfDictionary names = (PdfDictionary) PdfReader.getPdfObject(catalog.get(PdfName.NAMES)); if (names != null) { PdfDictionary embFiles = (PdfDictionary) PdfReader.getPdfObject(names.get(new PdfName("EmbeddedFiles"))); if (embFiles != null) { HashMap embMap = PdfNameTree.readTree(embFiles); for (Iterator i = embMap.values().iterator(); i.hasNext(); ) { PdfDictionary filespec = (PdfDictionary) PdfReader.getPdfObject((PdfObject) i.next()); Object fileInfo[] = unpackFile(reader, filespec); if (fileMap.containsKey(fileInfo[0])) { throw new RuntimeException(DUPLICATE_FILE_NAMES); } fileMap.put(fileInfo[0], fileInfo[1]); } } } for (int k = 1; k <= reader.getNumberOfPages(); ++k) { PdfArray annots = (PdfArray) PdfReader.getPdfObject(reader.getPageN(k).get(PdfName.ANNOTS)); if (annots == null) { continue; } for (Iterator i = annots.getArrayList().listIterator(); i.hasNext(); ) { PdfDictionary annot = (PdfDictionary) PdfReader.getPdfObject((PdfObject) i.next()); PdfName subType = (PdfName) PdfReader.getPdfObject(annot.get(PdfName.SUBTYPE)); if (!PdfName.FILEATTACHMENT.equals(subType)) { continue; } PdfDictionary filespec = (PdfDictionary) PdfReader.getPdfObject(annot.get(PdfName.FS)); Object fileInfo[] = unpackFile(reader, filespec); if (fileMap.containsKey(fileInfo[0])) { throw new RuntimeException(DUPLICATE_FILE_NAMES); } fileMap.put(fileInfo[0], fileInfo[1]); } } return fileMap; }
/** * Reads an array. When this is called, we have already read the ArrayStart token, and arrayDepth * has been incremented to reflect this. */ public PdfArray readArray() throws IOException, PdfException { PdfArray arr = new PdfArray(); for (; ; ) { PdfObject obj = null; try { obj = readObject(); arr.add(obj); } // We detect the end of an array by a PdfException being thrown // when readObject encounters the close bracket. When we get // the end of the array, collapse the vector before returning the object. catch (PdfException e) { Token tok = e.getToken(); if (tok instanceof ArrayEnd) { collapseObjectVector(arr.getContent()); return arr; } else { throw e; // real error } } } }
/** * Generates the font dictionary for this font. * * @return the PdfDictionary containing the font dictionary * @param firstChar the first valid character * @param lastChar the last valid character * @param shortTag a 256 bytes long <CODE>byte</CODE> array where each unused byte is represented * by 0 * @param fontDescriptor the indirect reference to a PdfDictionary containing the font descriptor * or <CODE>null</CODE> */ private PdfDictionary getFontBaseType( PdfIndirectReference fontDescriptor, int firstChar, int lastChar, byte shortTag[]) { PdfDictionary dic = new PdfDictionary(PdfName.FONT); dic.put(PdfName.SUBTYPE, PdfName.TYPE1); dic.put(PdfName.BASEFONT, new PdfName(FontName)); boolean stdEncoding = encoding.equals("Cp1252") || encoding.equals("MacRoman"); if (!fontSpecific || specialMap != null) { for (int k = firstChar; k <= lastChar; ++k) { if (!differences[k].equals(notdef)) { firstChar = k; break; } } if (stdEncoding) dic.put( PdfName.ENCODING, encoding.equals("Cp1252") ? PdfName.WIN_ANSI_ENCODING : PdfName.MAC_ROMAN_ENCODING); else { PdfDictionary enc = new PdfDictionary(PdfName.ENCODING); PdfArray dif = new PdfArray(); boolean gap = true; for (int k = firstChar; k <= lastChar; ++k) { if (shortTag[k] != 0) { if (gap) { dif.add(new PdfNumber(k)); gap = false; } dif.add(new PdfName(differences[k])); } else gap = true; } enc.put(PdfName.DIFFERENCES, dif); dic.put(PdfName.ENCODING, enc); } } if (specialMap != null || forceWidthsOutput || !(builtinFont && (fontSpecific || stdEncoding))) { dic.put(PdfName.FIRSTCHAR, new PdfNumber(firstChar)); dic.put(PdfName.LASTCHAR, new PdfNumber(lastChar)); PdfArray wd = new PdfArray(); for (int k = firstChar; k <= lastChar; ++k) { if (shortTag[k] == 0) wd.add(new PdfNumber(0)); else wd.add(new PdfNumber(widths[k])); } dic.put(PdfName.WIDTHS, wd); } if (!builtinFont && fontDescriptor != null) dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor); return dic; }
static PdfArray createDestinationArray(String value, PdfWriter writer) { PdfArray ar = new PdfArray(); StringTokenizer tk = new StringTokenizer(value); int n = Integer.parseInt(tk.nextToken()); ar.add(writer.getPageReference(n)); if (!tk.hasMoreTokens()) { ar.add(PdfName.XYZ); ar.add(new float[] {0, 10000, 0}); } else { String fn = tk.nextToken(); if (fn.startsWith("/")) fn = fn.substring(1); ar.add(new PdfName(fn)); for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) { fn = tk.nextToken(); if (fn.equals("null")) ar.add(PdfNull.PDFNULL); else ar.add(new PdfNumber(fn)); } } return ar; }
protected PdfObject getSpotObject(PdfWriter writer) throws IOException { PdfArray array = new PdfArray(PdfName.SEPARATION); array.add(name); PdfFunction func = null; if (altcs instanceof ExtendedColor) { int type = ((ExtendedColor) altcs).type; // ssteward // having trouble with unreachable bytecode in switch default (per gcj 4.4) // so try a clumsier workaround boolean handled_b = false; switch (type) { case ExtendedColor.TYPE_GRAY: array.add(PdfName.DEVICEGRAY); func = PdfFunction.type2( writer, new float[] {0, 1}, null, new float[] {0}, new float[] {((GrayColor) altcs).getGray()}, 1); handled_b = true; break; case ExtendedColor.TYPE_CMYK: array.add(PdfName.DEVICECMYK); CMYKColor cmyk = (CMYKColor) altcs; func = PdfFunction.type2( writer, new float[] {0, 1}, null, new float[] {0, 0, 0, 0}, new float[] { cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack() }, 1); handled_b = true; break; // default: // throw new RuntimeException("Only RGB, Gray and CMYK are supported as // alternative color spaces."); } if (!handled_b) { throw new RuntimeException( "Only RGB, Gray and CMYK are supported as alternative color spaces."); } } else { array.add(PdfName.DEVICERGB); func = PdfFunction.type2( writer, new float[] {0, 1}, null, new float[] {1, 1, 1}, new float[] { (float) altcs.getRed() / 255, (float) altcs.getGreen() / 255, (float) altcs.getBlue() / 255 }, 1); } array.add(func.getReference()); return array; }
public void addAnnotation(PdfAnnotation annot) { try { ArrayList allAnnots = new ArrayList(); if (annot.isForm()) { PdfFormField field = (PdfFormField) annot; if (field.getParent() != null) return; expandFields(field, allAnnots); if (cstp.fieldTemplates == null) cstp.fieldTemplates = new HashMap(); } else allAnnots.add(annot); for (int k = 0; k < allAnnots.size(); ++k) { annot = (PdfAnnotation) allAnnots.get(k); if (annot.isForm()) { if (!annot.isUsed()) { HashMap templates = annot.getTemplates(); if (templates != null) cstp.fieldTemplates.putAll(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); } }