/* * $Id$ * * Adapted from an example in C# from Christian Neuhold * published on the itext mailing list by Paulo Soares at 16. April 2007. * Changes by Paulo Soares to display without the need to click. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * */ package com.lowagie.toolbox.plugins; import java.io.*; import javax.swing.*; import com.lowagie.text.*; import com.lowagie.text.pdf.*; import com.lowagie.toolbox.AbstractTool; import com.lowagie.toolbox.arguments.*; import com.lowagie.toolbox.arguments.filters.PdfFilter; import com.lowagie.toolbox.arguments.filters.U3DFilter; import java.net.*; /** * This tool lets you add a embedded u3d 3d annotation to the first page of a document. Look for * sample files at http://u3d.svn.sourceforge.net/viewvc/u3d/trunk/Source/Samples/Data/ * @since 2.1.1 (imported from itexttoolbox project) */ public class Add3D extends AbstractTool { static { addVersion("$Id$"); } FileArgument destfile = null; public static final String PDF_NAME_3D = "3D"; public static final String PDF_NAME_3DD = "3DD"; public static final String PDF_NAME_3DV = "3DV"; public static final String PDF_NAME_3DVIEW = "3DView"; public static final String PDF_NAME_C2W = "C2W"; public static final String PDF_NAME_IN = "IN"; public static final String PDF_NAME_MS = "MS"; public static final String PDF_NAME_U3D = "U3D"; public static final String PDF_NAME_XN = "XN"; /** * This tool lets you add a embedded u3d 3d annotation to the first page of a document. */ public Add3D() { super(); menuoptions = MENU_EXECUTE | MENU_EXECUTE_SHOW; FileArgument inputfile = new FileArgument(this, "srcfile", "The file you want to add the u3d File", false, new PdfFilter()); arguments.add(inputfile); FileArgument u3dinputfile = new FileArgument(this, "srcu3dfile", "The u3d file you want to add", false, new U3DFilter()); arguments.add(u3dinputfile); StringArgument pagenumber = new StringArgument(this, "pagenumber", "The pagenumber where to add the u3d annotation"); pagenumber.setValue("1"); arguments.add(pagenumber); destfile = new FileArgument(this, "destfile", "The file that contains the u3d annotation after processing", true, new PdfFilter()); arguments.add(destfile); inputfile.addPropertyChangeListener(destfile); } /** * Creates the internal frame. * */ protected void createFrame() { internalFrame = new JInternalFrame("Add3D", true, true, true); internalFrame.setSize(300, 80); internalFrame.setJMenuBar(getMenubar()); System.out.println("=== Add3D OPENED ==="); } /** * Executes the tool (in most cases this generates a PDF file). * */ public void execute() { try { if (getValue("srcfile") == null) { throw new InstantiationException( "You need to choose a sourcefile"); } if (getValue("srcu3dfile") == null) { throw new InstantiationException( "You need to choose a u3d file"); } if (getValue("destfile") == null) { throw new InstantiationException( "You need to choose a destination file"); } int pagenumber = Integer.parseInt( (String) getValue("pagenumber")); // Create 3D annotation // Required definitions PdfIndirectReference streamRef; PdfIndirectObject objRef; PdfReader reader = new PdfReader(((File) getValue("srcfile")) .getAbsolutePath()); String u3dFileName = ((File) getValue("srcu3dfile")) .getAbsolutePath(); PdfStamper stamp = new PdfStamper(reader, new FileOutputStream( (File) getValue("destfile"))); PdfWriter wr = stamp.getWriter(); PdfContentByte cb = stamp.getUnderContent(pagenumber); Rectangle rectori = reader.getCropBox(pagenumber); Rectangle rect = new Rectangle(new Rectangle(100, rectori.getHeight() - 550, rectori.getWidth() - 100, rectori.getHeight() - 150)); PdfStream oni = new PdfStream(PdfEncodings.convertToBytes( "runtime.setCurrentTool(\"Rotate\");", null)); oni.flateCompress(); // Create stream to carry attachment PdfStream stream = new PdfStream(new FileInputStream(u3dFileName), wr); stream.put(new PdfName("OnInstantiate"), wr.addToBody(oni).getIndirectReference()); stream.put(PdfName.TYPE, new PdfName(PDF_NAME_3D)); // Mandatory keys stream.put(PdfName.SUBTYPE, new PdfName(PDF_NAME_U3D)); stream.flateCompress(); streamRef = wr.addToBody(stream).getIndirectReference(); // Write stream contents, get reference to stream object, write actual stream length stream.writeLength(); // Create 3D view dictionary // PDF documentation states that this can be left out, but without normally we will just get a blank 3D image because of wrong coordinate space transformations, etc. // Instead of providing camera-to-world transformation here, we could also reference view in U3D file itself (would be U3DPath key instead of C2W key, U3D value instead of M value for MS key), but i haven't tried up to now // We could also provide an activation dictionary (defining activation behavior), and field-of-view for P entry if needed PdfDictionary dict = new PdfDictionary(new PdfName(PDF_NAME_3DVIEW)); dict.put(new PdfName(PDF_NAME_XN), new PdfString("Default")); dict.put(new PdfName(PDF_NAME_IN), new PdfString("Unnamed")); dict.put(new PdfName(PDF_NAME_MS), PdfName.M); // States that we have to provide camera-to-world coordinate transformation dict.put(new PdfName(PDF_NAME_C2W), new PdfArray(new float[] {1, 0, 0, 0, 0, -1, 0, 1, 0, 3, -235, 28F})); // 3d transformation matrix (demo for teapot) dict.put(PdfName.CO, new PdfNumber(235)); // Camera distance along z-axis (demo for teapot) objRef = wr.addToBody(dict); // Write view dictionary, get reference // Create appearance PdfAppearance ap = cb.createAppearance(rect.getRight() - rect.getLeft(), rect.getTop() - rect.getBottom()); ap.setBoundingBox(rect); // Create annotation with reference to stream PdfAnnotation annot = new PdfAnnotation(wr, rect); annot.put(PdfName.CONTENTS, new PdfString("3D Model")); annot.put(PdfName.SUBTYPE, new PdfName(PDF_NAME_3D)); // Mandatory keys annot.put(PdfName.TYPE, PdfName.ANNOT); annot.put(new PdfName(PDF_NAME_3DD), streamRef); // Reference to stream object annot.put(new PdfName(PDF_NAME_3DV), objRef.getIndirectReference()); // Reference to view dictionary object annot.put(new PdfName("3DI"), PdfBoolean.PDFFALSE); PdfDictionary adi = new PdfDictionary(); adi.put(PdfName.A, new PdfName("PO")); adi.put(new PdfName("DIS"), PdfName.I); annot.put(new PdfName("3DA"), adi); annot.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, ap); // Assign appearance and page annot.setPage(); // Actually write annotation stamp.addAnnotation(annot, pagenumber); AddButton(100, 100, "Rotate", "im = this.getAnnots3D(0)[0].context3D;\rim.runtime.setCurrentTool(\"Rotate\");", "rotate.png", wr); AddButton(150, 100, "Pan", "im = this.getAnnots3D(0)[0].context3D;\rim.runtime.setCurrentTool(\"Pan\");", "translate.png", wr); AddButton(200, 100, "Zoom", "im = this.getAnnots3D(0)[0].context3D;\rim.runtime.setCurrentTool(\"Zoom\");", "zoom.png", wr); stamp.close(); } catch (Exception e) { JOptionPane.showMessageDialog(internalFrame, e.getMessage(), e .getClass().getName(), JOptionPane.ERROR_MESSAGE); System.err.println(e.getMessage()); } } public static void AddButton(float x, float y, String fname, String js, String image, PdfWriter wr) { try { // URL url=Add3D.class.getResource( // image); // PdfFileSpecification fs=PdfFileSpecification.fileEmbedded(wr,image,image,null); // wr.addAnnotation(PdfAnnotation.createScreen(wr,new Rectangle(x, y, x + img.plainWidth(), // y + img.plainHeight()))); Image img = Image.getInstance(image); PushbuttonField bt = new PushbuttonField(wr, new Rectangle(x, y, x + img.getPlainWidth(), y + img.getPlainHeight()), fname); bt.setLayout(PushbuttonField.LAYOUT_ICON_ONLY); bt.setImage(img); PdfFormField ff = bt.getField(); PdfAction ac = PdfAction.javaScript(js, wr); ff.setAction(ac); wr.addAnnotation(ff); } catch (MalformedURLException ex) { } catch (IOException ex) { } catch (BadElementException ex) { } catch (DocumentException ex) { } } /** * Gets the PDF file that should be generated (or null if the output isn't a * PDF file). * * @return the PDF file that should be generated * @throws InstantiationException */ protected File getDestPathPDF() throws InstantiationException { return (File) getValue("destfile"); } /** * Indicates that the value of an argument has changed. * * @param arg * the argument that has changed */ public void valueHasChanged(AbstractArgument arg) { if (internalFrame == null) { // if the internal frame is null, the tool was called from the // command line return; } if (destfile.getValue() == null && arg.getName().equalsIgnoreCase("srcfile")) { String filename = arg.getValue().toString(); String filenameout = filename.substring(0, filename.indexOf(".", filename.length() - 4)) + "_out.pdf"; destfile.setValue(filenameout); } } /** * This methods helps you running this tool as a standalone application. * @param args the srcfile and destfile */ public static void main(String[] args) { Add3D add3d = new Add3D(); if (args.length != 4) { System.err.println(add3d.getUsage()); } add3d.setMainArguments(args); add3d.execute(); } }