PDFWriterLowLevelTest.java0000644000175000017500000001303711343262371015073 0ustar user03user03package org.freehep.graphicsio.pdf.test; import java.io.*; import java.util.*; import org.freehep.graphicsio.pdf.*; /** * This class tests the lower-level PDF Writer interfaces. * It simply writes a document with several pages, including * some text and graphics. *

* @author Mark Donszelmann * @version $Id: PDFWriterLowLevelTest.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFWriterLowLevelTest { public static void main(String[] args) throws Exception { FileOutputStream out = new FileOutputStream("PDFWriterLowLevelTest.pdf"); // PDF file PDFWriter pdf = new PDFWriter(out, "1.3"); pdf.comment("PDFGraphicsTest file generated by PDFWriterLowLevelTest, Freehep lib"); // info PDFDictionary info = pdf.openDictionary("DocInfo"); info.entry("Title", "PDFWriter LowLevel Test Output"); info.entry("Author", "Mark Donszelmann"); info.entry("Subject", "LowLevel Test File of the PDFWriter of the FreeHEP library"); info.entry("Keywords", "PDFWriter; FreeHEP"); info.entry("Creator", "org.freehep.util.pdf.PDFWriter"); info.entry("CreationDate", Calendar.getInstance()); pdf.close(info); // catalog PDFDictionary catalog = pdf.openDictionary("Catalog"); catalog.entry("Type", pdf.name("Catalog")); catalog.entry("Outlines", pdf.ref("Outlines")); catalog.entry("Pages", pdf.ref("RootPage")); catalog.entry("PageMode", pdf.name("UseOutlines")); catalog.entry("ViewerPreferences", pdf.ref("Preferences")); pdf.close(catalog); // preferences PDFDictionary prefs = pdf.openDictionary("Preferences"); prefs.entry("FitWindow", false); prefs.entry("CenterWindow", false); pdf.close(prefs); // outlines PDFDictionary outlines = pdf.openDictionary("Outlines"); outlines.entry("Type", pdf.name("Outlines")); outlines.entry("Count", 0); pdf.close(outlines); // pages PDFDictionary pages = pdf.openDictionary("RootPage"); pages.entry("Type", pdf.name("Pages")); pages.entry("Kids", new Object[] {pdf.ref("FirstPage"), pdf.ref("SecondPage")}); pages.entry("Count", 2); pages.entry("MediaBox", new int[] {0, 0, 612, 792}); PDFDictionary resources = pages.openDictionary("Resources"); resources.entry("ProcSet", pdf.ref("OurPageProcSet")); PDFDictionary fontList = resources.openDictionary("Font"); fontList.entry("F1", pdf.ref("Helvetica")); resources.close(fontList); pages.close(resources); pdf.close(pages); // first page PDFDictionary firstPage = pdf.openDictionary("FirstPage"); firstPage.entry("Type", pdf.name("Page")); firstPage.entry("Parent", pdf.ref("RootPage")); firstPage.entry("Contents", pdf.ref("FirstPageContent")); pdf.close(firstPage); // first page content PDFStream first = pdf.openStream("FirstPageContent"); first.beginText(); first.font(pdf.name("F1"), 24); first.text(100, 100); first.show("Hello"); first.show(" World"); first.endText(); pdf.close(first); // second page PDFDictionary secondPage = pdf.openDictionary("SecondPage"); secondPage.entry("Type", pdf.name("Page")); secondPage.entry("Parent", pdf.ref("RootPage")); secondPage.entry("Contents", pdf.ref("SecondPageContent")); pdf.close(secondPage); // second page content PDFStream second = pdf.openStream("SecondPageContent"); second.comment("Draw a black line segment, using the default line width."); second.move(150, 250); second.line(150, 350); second.stroke(); second.comment("Draw a thicker, dashed line segment."); second.width(4); second.comment("Set line width to 4 points"); second.dash(new int[] {4,6}, 0); second.comment("Set dash pattern to 4 units on, 6 units off"); second.move(150, 250); second.line(400, 250); second.stroke(); second.dash(new int[0], 0); second.comment("Reset dash pattern to a solid line"); second.width(1); second.comment("Reset line width to 1 unit"); second.comment("Draw a rectangle with a 1 unit red border, filled with light blue."); second.colorSpaceStroke(1.0, 0.0, 0.0); second.comment("Red for stroke color"); second.colorSpace(0.5, 0.75, 1.0); second.comment("Light blue for fill color"); second.rectangle(200, 300, 50, 75); second.fillAndStroke(); second.comment("Draw a curve filled with gray and with a colored border."); second.colorSpaceStroke(0.5, 0.1, 0.2); second.colorSpace(0.7); second.move(300, 300); second.cubic(300, 400, 400, 400, 400, 300); second.closeFillAndStroke(); pdf.close(second); // our page proc set pdf.object("OurPageProcSet", new Object[] {pdf.name("PDF"), pdf.name("Text")}); // font PDFDictionary font = pdf.openDictionary("Helvetica"); font.entry("Type", pdf.name("Font")); font.entry("Subtype", pdf.name("Type1")); font.entry("Name", pdf.name("F1")); font.entry("BaseFont", pdf.name("Helvetica")); pdf.close(font); // write xref table and trailer pdf.close("Catalog", "DocInfo"); out.close(); } }PDFWriterTest.java0000644000175000017500000001720711343262374013427 0ustar user03user03package org.freehep.graphicsio.pdf.test; import java.awt.*; import java.io.*; import java.util.*; import org.freehep.graphicsio.pdf.*; import org.freehep.graphicsio.ImageConstants; import org.freehep.util.images.*; /** * This class tests the user-level PDF Writer interfaces. * It simply writes a document with several pages, including * some text and graphics. *

* @author Mark Donszelmann * @version $Id: PDFWriterTest.java 10270 2007-01-09 18:18:57Z duns $ */ public class PDFWriterTest { public static void main(String[] args) throws Exception { FileOutputStream out = new FileOutputStream("PDFWriterUserTest.pdf"); // PDF file PDFWriter pdf = new PDFWriter(out, "1.3"); pdf.comment("PDFGraphicsTest file generated by PDFWriterTest, Freehep lib"); // info PDFDocInfo info = pdf.openDocInfo("DocInfo"); info.setTitle("PDFWriter Test Output"); info.setAuthor("Mark Donszelmann"); info.setSubject("Test File of the PDFWriter of the FreeHEP library"); info.setKeywords("PDFWriter; FreeHEP"); info.setCreator("org.freehep.util.pdf.PDFWriter"); info.setCreationDate(Calendar.getInstance()); pdf.close(info); // catalog PDFCatalog catalog = pdf.openCatalog("Catalog", "RootPage"); catalog.setOutlines("Outlines"); catalog.setPageMode("UseOutlines"); catalog.setViewerPreferences("Preferences"); catalog.setOpenAction(new Object[] { pdf.ref("FirstPage"), pdf.name("Fit")}); pdf.close(catalog); // preferences PDFViewerPreferences prefs = pdf.openViewerPreferences("Preferences"); prefs.setFitWindow(true); prefs.setCenterWindow(false); pdf.close(prefs); // outlines PDFOutlineList outlines = pdf.openOutlineList("Outlines", "FirstOutline", "LastOutline"); pdf.close(outlines); // outline FIXME: need to connect still PDFOutline firstOutline = pdf.openOutline("FirstOutline", "Text Page", "Outlines", null, "SecondOutline"); firstOutline.setDest(new Object[] { pdf.ref("FirstPage"), pdf.name("Fit")}); pdf.close(firstOutline); PDFOutline secondOutline = pdf.openOutline("SecondOutline", "Graphics Page", "Outlines", "FirstOutline", "LastOutline"); secondOutline.setDest(new Object[] { pdf.ref("SecondPage"), pdf.name("Fit")}); pdf.close(secondOutline); PDFOutline lastOutline = pdf.openOutline("LastOutline", "Image Page", "Outlines", "SecondOutline", null); lastOutline.setDest(new Object[] { pdf.ref("ThirdPage"), pdf.name("Fit")}); pdf.close(lastOutline); // pages PDFPageTree pages = pdf.openPageTree("RootPage", null); pages.addPage("FirstPage"); pages.addPage("SecondPage"); pages.addPage("ThirdPage"); pages.setMediaBox(0, 0, 612, 792); pages.setResources("Resources"); pdf.close(pages); // resources PDFDictionary resources = pdf.openDictionary("Resources"); resources.entry("ProcSet", pdf.ref("OurPageProcSet")); PDFDictionary fontList = resources.openDictionary("Font"); fontList.entry("F1", pdf.ref("Helvetica")); resources.close(fontList); pdf.close(resources); // first page PDFPage firstPage = pdf.openPage("FirstPage", "RootPage"); firstPage.setContents("FirstPageContent"); pdf.close(firstPage); // first page content pdf.comment("hello word"); PDFStream first = pdf.openStream("FirstPageContent", new String[] { "Flate", "ASCIIHex" }); first.beginText(); first.font(pdf.name("F1"), 24); first.text(100, 100); first.show("Hello"); first.show(" World"); first.endText(); pdf.close(first); // second page PDFPage secondPage = pdf.openPage("SecondPage", "RootPage"); secondPage.setContents("SecondPageContent"); secondPage.setThumb("SecondPageThumbnail"); pdf.close(secondPage); // second page thumbnail PDFStream secondThumb = pdf.openStream("SecondPageThumbnail"); MediaTracker tracker = new MediaTracker(new Panel()); Image image1 = ImageHandler.getImage("../../test/images/BrokenCursor.gif", PDFWriterTest.class); Image image2 = ImageHandler.getImage("../../test/images/transparent-image.gif", PDFWriterTest.class); tracker.addImage(image1,0); tracker.addImage(image2,1); try { tracker.waitForAll(); } catch (Exception e) { e.printStackTrace(); } secondThumb.image( ImageUtilities.createRenderedImage( image2, null, Color.BLACK), Color.BLACK, ImageConstants.ZLIB); pdf.close(secondThumb); // second page content PDFStream second = pdf.openStream( "SecondPageContent", new String[] { ImageConstants.ENCODING_FLATE, ImageConstants.ENCODING_ASCII85 }); second.comment("Draw a black line segment, using the default line width."); second.move(150, 250); second.line(150, 350); second.stroke(); second.comment("Draw a thicker, dashed line segment."); second.width(4); second.comment("Set line width to 4 points"); second.dash(new int[] {4,6}, 0); second.comment("Set dash pattern to 4 units on, 6 units off"); second.move(150, 250); second.line(400, 250); second.stroke(); second.dash(new int[0], 0); second.comment("Reset dash pattern to a solid line"); second.width(1); second.comment("Reset line width to 1 unit"); second.comment("Draw a rectangle with a 1 unit red border, filled with light blue."); second.colorSpaceStroke(1.0, 0.0, 0.0); second.comment("Red for stroke color"); second.colorSpace(0.5, 0.75, 1.0); second.comment("Light blue for fill color"); second.rectangle(200, 300, 50, 75); second.fillAndStroke(); second.comment("Draw a curve filled with gray and with a colored border."); second.colorSpaceStroke(0.5, 0.1, 0.2); second.colorSpace(0.7); second.move(300, 300); second.cubic(300, 400, 400, 400, 400, 300); second.closeFillAndStroke(); pdf.close(second); // third page PDFPage thirdPage = pdf.openPage("ThirdPage", "RootPage"); thirdPage.setContents("ThirdPageContent"); pdf.close(thirdPage); // third page content PDFStream third = pdf.openStream("ThirdPageContent"); third.save(); third.matrix(32, 0, 0, 32, 298, 388); third.inlineImage( ImageUtilities.createRenderedImage(image1, null, Color.BLACK), Color.BLACK, ImageConstants.ZLIB); third.restore(); pdf.close(third); // our page proc set pdf.object("OurPageProcSet", new Object[] {pdf.name("PDF"), pdf.name("Text"), pdf.name("ImageC") }); // font PDFDictionary font = pdf.openDictionary("Helvetica"); font.entry("Type", pdf.name("Font")); font.entry("Subtype", pdf.name("Type1")); font.entry("Name", pdf.name("F1")); font.entry("BaseFont", pdf.name("Helvetica")); pdf.close(font); // close pdf pdf.close(); out.close(); System.exit(0); } } pom.xml0000644000175000017500000000227311344042422011417 0ustar user03user03 vectorgraphics org.freehep 2.1.1 4.0.0 org.freehep freehep-graphicsio-pdf FreeHEP PDF Driver FreeHEP Portable Document Format Driver freehep-maven Maven FreeHEP http://java.freehep.org/maven2 org.freehep freehep-graphicsio 2.1.1 org.freehep freehep-graphicsio-tests 2.1.1 junit junit src/0000700000175000017500000000000011343262370010660 5ustar user03user03src/test/0000700000175000017500000000000011344052302011630 5ustar user03user03src/test/java/0000700000175000017500000000000011343262370012560 5ustar user03user03src/test/java/org/0000700000175000017500000000000011343262370013347 5ustar user03user03src/test/java/org/freehep/0000700000175000017500000000000011343262370014765 5ustar user03user03src/test/java/org/freehep/graphicsio/0000700000175000017500000000000011343262370017115 5ustar user03user03src/test/java/org/freehep/graphicsio/pdf/0000700000175000017500000000000011343262370017666 5ustar user03user03src/test/java/org/freehep/graphicsio/pdf/test/0000700000175000017500000000000011343262370020645 5ustar user03user03src/test/java/org/freehep/graphicsio/pdf/test/PDFTestSuite.java0000644000175000017500000000212211343262370024002 0ustar user03user03// Copyright 2005, FreeHEP. package org.freehep.graphicsio.pdf.test; import org.freehep.graphicsio.test.TestSuite; /** * @author Mark Donszelmann * @version $Id: PDFTestSuite.java 12753 2007-06-12 22:32:31Z duns $ */ public class PDFTestSuite extends TestSuite { /* protected void addTests(String category, String fmt, String dir, String ext, boolean compare, Properties properties) { super.addTests(category, fmt, dir, ext, compare, properties); addTest(new TestCase( "org.freehep.graphicsio.pdf.test.PDFTestPreviewThumbnail", category, fmt, dir, ext, compare, null)); addTest(new TestCase( "org.freehep.graphicsio.pdf.test.PDFTestFontType1", category, fmt, dir, ext, compare, null)); addTest(new TestCase( "org.freehep.graphicsio.pdf.test.PDFTestFontType3", category, fmt, dir, ext, compare, null)); } */ public static TestSuite suite() { PDFTestSuite suite = new PDFTestSuite(); suite.addTests("PDF"); return suite; } } src/test/java/org/freehep/graphicsio/pdf/test/PDFTestFontType3.java0000644000175000017500000000202411343262370024545 0ustar user03user03// Copyright 2005, FreeHEP. package org.freehep.graphicsio.pdf.test; import java.util.Properties; import org.freehep.graphicsio.FontConstants; import org.freehep.graphicsio.pdf.PDFGraphics2D; import org.freehep.graphicsio.test.TestFontType3; import org.freehep.util.UserProperties; /** * @author Mark Donszelmann * @version $Id: PDFTestFontType3.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFTestFontType3 extends TestFontType3 { public PDFTestFontType3(String[] args) throws Exception { super(args); } public void runTest(Properties options) throws Exception { UserProperties user = (options == null) ? new UserProperties() : new UserProperties(options); user.setProperty(PDFGraphics2D.EMBED_FONTS, true); user.setProperty(PDFGraphics2D.EMBED_FONTS_AS, FontConstants.EMBED_FONTS_TYPE3); super.runTest(user); } public static void main(String[] args) throws Exception { new PDFTestFontType3(args).runTest(); } } src/test/java/org/freehep/graphicsio/pdf/test/PDFTestFontType1.java0000644000175000017500000000202411343262370024543 0ustar user03user03// Copyright 2005, FreeHEP. package org.freehep.graphicsio.pdf.test; import java.util.Properties; import org.freehep.graphicsio.FontConstants; import org.freehep.graphicsio.pdf.PDFGraphics2D; import org.freehep.graphicsio.test.TestFontType1; import org.freehep.util.UserProperties; /** * @author Mark Donszelmann * @version $Id: PDFTestFontType1.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFTestFontType1 extends TestFontType1 { public PDFTestFontType1(String[] args) throws Exception { super(args); } public void runTest(Properties options) throws Exception { UserProperties user = (options == null) ? new UserProperties() : new UserProperties(options); user.setProperty(PDFGraphics2D.EMBED_FONTS, true); user.setProperty(PDFGraphics2D.EMBED_FONTS_AS, FontConstants.EMBED_FONTS_TYPE1); super.runTest(user); } public static void main(String[] args) throws Exception { new PDFTestFontType1(args).runTest(); } } src/test/java/org/freehep/graphicsio/pdf/test/PDFTestPreviewThumbnail.java0000644000175000017500000000164711343262370026211 0ustar user03user03// Copyright 2005, FreeHEP. package org.freehep.graphicsio.pdf.test; import java.util.Properties; import org.freehep.graphicsio.pdf.PDFGraphics2D; import org.freehep.graphicsio.test.TestPreviewThumbnail; import org.freehep.util.UserProperties; /** * @author Mark Donszelmann * @version $Id: PDFTestPreviewThumbnail.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFTestPreviewThumbnail extends TestPreviewThumbnail { public PDFTestPreviewThumbnail(String[] args) throws Exception { super(args); } public void runTest(Properties options) throws Exception { UserProperties user = (options == null) ? new UserProperties() : new UserProperties(options); user.setProperty(PDFGraphics2D.THUMBNAILS, true); super.runTest(user); } public static void main(String[] args) throws Exception { new PDFTestPreviewThumbnail(args).runTest(); } } src/main/0000700000175000017500000000000011343262370011604 5ustar user03user03src/main/resources/0000700000175000017500000000000011343262370013616 5ustar user03user03src/main/resources/META-INF/0000700000175000017500000000000011343262370014756 5ustar user03user03src/main/resources/META-INF/services/0000700000175000017500000000000011343262370016601 5ustar user03user03src/main/resources/META-INF/services/org.freehep.util.export.ExportFileType0000644000175000017500000000005511343262370026160 0ustar user03user03org.freehep.graphicsio.pdf.PDFExportFileType src/main/java/0000700000175000017500000000000011343262370012525 5ustar user03user03src/main/java/overview.html0000644000175000017500000000012711343262370015273 0ustar user03user03 This is the API specification of the FreeHEP VectorGraphics package. src/main/java/org/0000700000175000017500000000000011343262370013314 5ustar user03user03src/main/java/org/freehep/0000700000175000017500000000000011343262370014732 5ustar user03user03src/main/java/org/freehep/graphicsio/0000700000175000017500000000000011343262370017062 5ustar user03user03src/main/java/org/freehep/graphicsio/pdf/0000700000175000017500000000000011343262370017633 5ustar user03user03src/main/java/org/freehep/graphicsio/pdf/PDFPageBase.java0000644000175000017500000000224211343262370022511 0ustar user03user03package org.freehep.graphicsio.pdf; import java.io.IOException; /** * Implements the Page Base Node to accomodate Inheritance of Page Attributes * (see Table 3.17) *

* * @author Mark Donszelmann * @version $Id: PDFPageBase.java 8584 2006-08-10 23:06:37Z duns $ */ public abstract class PDFPageBase extends PDFDictionary { protected PDFPageBase(PDF pdf, PDFByteWriter writer, PDFObject object, PDFRef parent) throws IOException { super(pdf, writer, object); entry("Parent", parent); } // // Inheritable items go here // public void setResources(String resources) throws IOException { entry("Resources", pdf.ref(resources)); } public void setMediaBox(double x, double y, double w, double h) throws IOException { double[] rectangle = { x, y, w, h }; entry("MediaBox", rectangle); } public void setCropBox(double x, double y, double w, double h) throws IOException { double[] rectangle = { x, y, w, h }; entry("CropBox", rectangle); } public void setRotate(int rotate) throws IOException { entry("Rotate", rotate); } } src/main/java/org/freehep/graphicsio/pdf/PDFPaintDelayQueue.java0000644000175000017500000002246211343262370024107 0ustar user03user03// Copyright 2001 freehep package org.freehep.graphicsio.pdf; import java.awt.GradientPaint; import java.awt.Paint; import java.awt.TexturePaint; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; /** * Delay Paint objects (gradient/texture, not color) for writing * pattern/shading/function dictionaries to the pdf file when the pageStream is * complete.
* TODO: - reuse pattern dictionaries if possible - cyclic function not working * yet (ps calculation) * * @author Simon Fischer * @version $Id: PDFPaintDelayQueue.java 10270 2007-01-09 18:18:57Z duns $ */ public class PDFPaintDelayQueue { private static int currentNumber = 0; private class Entry { private Paint paint; private String name; private AffineTransform trafo; private String writeAs; private boolean written; private Entry(Paint paint, AffineTransform trafo, String writeAs) { this.paint = paint; this.trafo = trafo; this.writeAs = writeAs; this.name = "Paint" + (currentNumber++); this.written = false; } } private List paintList; private PDFWriter pdf; // private PDFImageDelayQueue imageDelayQueue; private AffineTransform pageMatrix; /** Don't forget to call setPageMatrix(). */ public PDFPaintDelayQueue(PDFWriter pdf, PDFImageDelayQueue imageDelayQueue) { this.pdf = pdf; this.paintList = new LinkedList(); // this.imageDelayQueue = imageDelayQueue; this.pageMatrix = new AffineTransform(); } /** * Call this method in order to inform this class about the transformation * that is necessary to map the pattern's coordinate space to the default * coordinate system of the parent's content stream (in our case the * flipping of the page). */ public void setPageMatrix(AffineTransform t) { pageMatrix = new AffineTransform(t); } public PDFName delayPaint(Paint paint, AffineTransform transform, String writeAs) { Entry e = new Entry(paint, transform, writeAs); paintList.add(e); return pdf.name(e.name); } /** Creates a stream for every delayed image. */ public void processAll() throws IOException { ListIterator i = paintList.listIterator(); while (i.hasNext()) { Entry e = (Entry) i.next(); if (!e.written) { e.written = true; if (e.paint instanceof GradientPaint) { addGradientPaint(e); } else if (e.paint instanceof TexturePaint) { addTexturePaint(e); } else { System.err.println("PDFWriter: Paint of class '" + e.paint.getClass() + "' not supported."); // FIXME, we could write a color here, to keep the file // valid. } } } } /** * Adds all names to the dictionary which should be the value of the * resources dicionrary's /Pattern entry. */ public int addPatterns() throws IOException { if (paintList.size() > 0) { PDFDictionary patterns = pdf.openDictionary("Pattern"); ListIterator i = paintList.listIterator(); while (i.hasNext()) { Entry e = (Entry) i.next(); patterns.entry(e.name, pdf.ref(e.name)); } pdf.close(patterns); } return paintList.size(); } private void addGradientPaint(Entry e) throws IOException { GradientPaint gp = (GradientPaint) e.paint; // open the pattern dictionary PDFDictionary pattern = pdf.openDictionary(e.name); pattern.entry("Type", pdf.name("Pattern")); pattern.entry("PatternType", 2); setMatrix(pattern, e, 0, 0); // the shading subdictionary PDFDictionary shading = pattern.openDictionary("Shading"); shading.entry("ShadingType", 2); shading.entry("ColorSpace", pdf.name("DeviceRGB")); Point2D p1 = gp.getPoint1(); Point2D p2 = gp.getPoint2(); shading.entry("Coords", new double[] { p1.getX(), p1.getY(), p2.getX(), p2.getY() }); double[] domain = new double[] { 0, 1 }; shading.entry("Domain", domain); // the function subdictionary (necessarily by reference, because // the type 4 function is a stream) String functionRef = e.name + "Function"; shading.entry("Function", pdf.ref(functionRef)); shading.entry("Extend", new boolean[] { true, true }); pattern.close(shading); pdf.close(pattern); // get color components and generate the functions float[] col0 = new float[3]; gp.getColor1().getRGBColorComponents(col0); double c0[] = new double[] { col0[0], col0[1], col0[2] }; float[] col1 = new float[3]; gp.getColor2().getRGBColorComponents(col1); double c1[] = new double[] { col1[0], col1[1], col1[2] }; if (gp.isCyclic()) { // FIXME: cyclic function only eveluated between 0 and 1 for short // range, not repetitive. // addCyclicFunction(functionRef, c0, c1, domain); addLinearFunction(functionRef, c0, c1, domain); } else { addLinearFunction(functionRef, c0, c1, domain); } } /** Writes a type 2 (exponential) function (exponent N=1) to the pdf file. */ private void addLinearFunction(String functionRef, double[] c0, double[] c1, double[] dom) throws IOException { PDFDictionary function = pdf.openDictionary(functionRef); function.entry("FunctionType", 2); function.entry("Domain", dom); function.entry("Range", new double[] { 0., 1., 0., 1., 0., 1. }); function.entry("C0", c0); function.entry("C1", c1); function.entry("N", 1); pdf.close(function); } /** * Writes a type 4 (PostScript calculator) function that describes a * triangle function to the pdf file. */ // NOT USED protected void addCyclicFunction(String functionRef, double[] c0, double[] c1, double[] dom) throws IOException { // PDFStream function = pdf.openStream(functionRef, new String[] { // "Flate", "ASCII85" }); PDFStream function = pdf.openStream(functionRef); function.entry("FunctionType", 4); // function.entry("Domain", new double[] {-1000.0, 1000.0} ); function.entry("Domain", dom); function.entry("Range", new double[] { 0., 1., 0., 1., 0., 1. }); function.println("{"); /* * function.println("2 mod"); function.println("1 sub"); * function.println("abs"); function.println("1 exch sub"); */ // function.println("sin"); for (int i = 0; i < 3; i++) { if (i < 2) function.println("dup"); function.println((c1[i] - c0[i]) + " mul"); function.println(c0[i] + " add"); if (i < 2) function.println("exch"); } // function.println("pop 0.8 0.0 0.0"); function.println("}"); pdf.close(function); } private void addTexturePaint(Entry e) throws IOException { TexturePaint tp = (TexturePaint) e.paint; // open the pattern stream that also holds the inlined picture PDFStream pattern = pdf.openStream(e.name, null); // image is encoded. pattern.entry("Type", pdf.name("Pattern")); pattern.entry("PatternType", 1); pattern.entry("PaintType", 1); BufferedImage image = tp.getImage(); pattern.entry("TilingType", 1); double width = tp.getAnchorRect().getWidth(); double height = tp.getAnchorRect().getHeight(); double offsX = tp.getAnchorRect().getX(); double offsY = tp.getAnchorRect().getY(); pattern.entry("BBox", new double[] { 0, 0, width, height }); pattern.entry("XStep", width); pattern.entry("YStep", height); PDFDictionary resources = pattern.openDictionary("Resources"); resources.entry("ProcSet", new Object[] { pdf.name("PDF"), pdf.name("ImageC") }); pattern.close(resources); setMatrix(pattern, e, offsX, offsY); // scale the tiling image to the correct size pattern.matrix(width, 0, 0, -height, 0, height); pattern.inlineImage(image, null, e.writeAs); pdf.close(pattern); } /** * Sets both the page (flip) matrix and the actual transformation matrix * plus a translation offset (which may of course be be 0). */ private void setMatrix(PDFDictionary dict, Entry e, double translX, double translY) throws IOException { // concatenate the page matrix and the actual transformation matrix AffineTransform trafo = new AffineTransform(pageMatrix); trafo.concatenate(e.trafo); trafo.translate(translX, translY); double[] matrix = new double[6]; trafo.getMatrix(matrix); dict.entry("Matrix", new double[] { matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5] }); } } src/main/java/org/freehep/graphicsio/pdf/PDFCharTableWriter.java0000644000175000017500000000217111343262370024065 0ustar user03user03// Copyright 2001-2005 freehep package org.freehep.graphicsio.pdf; import java.io.IOException; import org.freehep.graphics2d.font.CharTable; import org.freehep.graphicsio.font.FontEmbedder; public class PDFCharTableWriter implements PDFRedundanceTracker.Writer { private static PDFCharTableWriter ctw; public static PDFCharTableWriter getInstance() { if (ctw == null) ctw = new PDFCharTableWriter(); return ctw; } public void writeObject(Object object, PDFRef ref, PDFWriter pdf) throws IOException { CharTable charTable = (CharTable) object; PDFDictionary encoding = pdf.openDictionary(ref.getName()); encoding.entry("Type", pdf.name("Encoding")); Object[] differences = new Object[257]; differences[0] = new Integer(0); for (int i = 0; i < 256; i++) { String charName = charTable.toName(i); differences[i + 1] = (charName != null) ? pdf.name(charName) : pdf .name(FontEmbedder.NOTDEF); } encoding.entry("Differences", differences); pdf.close(encoding); } } src/main/java/org/freehep/graphicsio/pdf/package.html0000644000175000017500000000227411343262370022133 0ustar user03user03

PDF (Portable Document File) Output Format.

It is based on the "PDF Reference: Second Edition, version 1.4", July 2001 by "Addison-Wesley".

It currently contains all classes for all PDF objects available in PDF. These are lower level classes such as PDFName, PDFObject, PDFRef, PDFDictionary and PDFStream. For the classes PDFString and PDFArray one should use the java String class and the java array respectively.

The user typically interacts with the PDFWriter class to create a PDF file. He can then create pages, open streams and use the latter to create the actual content of the page. The PDFWriter in combination with the PDFByteWriter takes care of keeping "logical" object references, building the cross-reference table and do some error checking.

An implementation of VectorGraphics also exist:

The following Limitations exist:

@status Stable. src/main/java/org/freehep/graphicsio/pdf/PDFImageDelayQueue.java0000644000175000017500000000674411343262370024063 0ustar user03user03// Copyright 2001-2005, FreeHEP package org.freehep.graphicsio.pdf; import java.awt.Color; import java.awt.image.RenderedImage; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * Delay Image objects for writing XObjects to the pdf file when the * pageStream is complete. Caches identical images to only write them once. * * @author Simon Fischer * @author Mark Donszelmann * @version $Id: PDFImageDelayQueue.java 10270 2007-01-09 18:18:57Z duns $ */ public class PDFImageDelayQueue { private int currentNumber = 0; private class Entry { private RenderedImage image; private String name, maskName; private Color bkg; private String writeAs; private boolean written; private Entry(RenderedImage image, Color bkg, String writeAs) { this.image = image; this.bkg = bkg; this.writeAs = writeAs; this.name = "Img" + (currentNumber++); if (image.getColorModel().hasAlpha() && (bkg == null)) { maskName = name + "Mask"; } else { maskName = null; } this.written = false; } } private Map/* */imageMap; private List/* */imageList; private PDFWriter pdf; public PDFImageDelayQueue(PDFWriter pdf) { this.pdf = pdf; this.imageMap = new HashMap(); this.imageList = new LinkedList(); } public PDFName delayImage(RenderedImage image, Color bkg, String writeAs) { Entry entry = (Entry) imageMap.get(image); if (entry == null) { entry = new Entry(image, bkg, writeAs); imageMap.put(image, entry); imageList.add(entry); } return pdf.name(entry.name); } /** Creates a stream for every delayed image that is not written yet. */ public void processAll() throws IOException { for (Iterator i = imageList.iterator(); i.hasNext();) { Entry entry = (Entry) i.next(); if (!entry.written) { entry.written = true; PDFStream img = pdf.openStream(entry.name); img.entry("Subtype", pdf.name("Image")); if (entry.maskName != null) img.entry("SMask", pdf.ref(entry.maskName)); img.image(entry.image, entry.bkg, entry.writeAs); pdf.close(img); if (entry.maskName != null) { PDFStream mask = pdf.openStream(entry.maskName); mask.entry("Subtype", pdf.name("Image")); mask.imageMask(entry.image, entry.writeAs); pdf.close(mask); } } } } /** * Adds all names to the dictionary which should be the value of the * resources dicionrary's /XObject entry. */ public int addXObjects() throws IOException { if (imageList.size() > 0) { PDFDictionary xobj = pdf.openDictionary("XObjects"); for (Iterator i = imageList.iterator(); i.hasNext();) { Entry entry = (Entry) i.next(); xobj.entry(entry.name, pdf.ref(entry.name)); if (entry.maskName != null) xobj.entry(entry.maskName, pdf.ref(entry.maskName)); } pdf.close(xobj); } return imageList.size(); } } src/main/java/org/freehep/graphicsio/pdf/PDFByteWriter.java0000644000175000017500000000474311343262370023152 0ustar user03user03package org.freehep.graphicsio.pdf; import java.io.IOException; import java.io.OutputStream; import org.freehep.util.io.CountedByteOutputStream; /** * Implements the real writer for the PDFWriter. This class does byte-counting * to eventually build the cross-reference table, block length counting for the * length of streams, and platform dependent end-of-line characters. *

* * @author Mark Donszelmann * @version $Id: PDFByteWriter.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFByteWriter extends CountedByteOutputStream implements PDFConstants { private int indent; private String indentString = " "; PDFByteWriter(OutputStream out) { super(out); indent = 0; } public void write(String s) throws IOException { write(s.getBytes("ISO-8859-1")); } public void close() throws IOException { out.close(); super.close(); } public void print(String string) throws IOException { for (int i = 0; i < indent; i++) { write(indentString); } printPlain(string); } public void printPlain(String string) throws IOException { write(string); } public void println() throws IOException { write(EOL); } public void indent() { indent++; } public void outdent() { if (indent > 0) { indent--; } } // Convenience methods public void println(String string) throws IOException { print(string); println(); } public void print(int number) throws IOException { print(Integer.toString(number)); } public void println(int number) throws IOException { print(number); println(); } public void printPlain(int number) throws IOException { printPlain(Integer.toString(number)); } public void print(double number) throws IOException { print(Double.toString(number)); } public void println(double number) throws IOException { print(number); println(); } public void printPlain(double number) throws IOException { printPlain(Double.toString(number)); } public void print(Object object) throws IOException { print(object.toString()); } public void println(Object object) throws IOException { print(object); println(); } public void printPlain(Object object) throws IOException { printPlain(object.toString()); } }src/main/java/org/freehep/graphicsio/pdf/PDFCatalog.java0000644000175000017500000000407511343262370022422 0ustar user03user03package org.freehep.graphicsio.pdf; import java.io.IOException; /** * Implements the Catalog Dictionary (see Table 3.15). *

* * @author Mark Donszelmann * @version $Id: PDFCatalog.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFCatalog extends PDFDictionary { PDFCatalog(PDF pdf, PDFByteWriter writer, PDFObject parent, PDFRef pageTree) throws IOException { super(pdf, writer, parent); entry("Type", pdf.name("Catalog")); entry("Pages", pageTree); } /* * public void setPageLabels(PDFNumberTree pageLabels) { entry("PageLabels", * pageLabels); } */ public void setNames(String names) throws IOException { entry("Names", pdf.ref(names)); } public void setDests(String dests) throws IOException { entry("Dests", pdf.ref(dests)); } public void setViewerPreferences(String viewerPreferences) throws IOException { entry("ViewerPreferences", pdf.ref(viewerPreferences)); } public void setPageLayout(String pageLayout) throws IOException { entry("PageLayout", pdf.name(pageLayout)); } public void setPageMode(String pageMode) throws IOException { entry("PageMode", pdf.name(pageMode)); } public void setOutlines(String outlines) throws IOException { entry("Outlines", pdf.ref(outlines)); } public void setThreads(String threads) throws IOException { entry("Threads", pdf.ref(threads)); } public void setOpenAction(Object[] openAction) throws IOException { entry("OpenAction", openAction); } public void setURI(String uri) throws IOException { entry("URI", pdf.ref(uri)); } public void setAcroForm(String acroForm) throws IOException { entry("AcroForm", pdf.ref(acroForm)); } public void setStructTreeRoot(String structTreeRoot) throws IOException { entry("StructTreeRoot", pdf.ref(structTreeRoot)); } public void setSpiderInfo(String spiderInfo) throws IOException { entry("SpiderInfo", pdf.ref(spiderInfo)); } } src/main/java/org/freehep/graphicsio/pdf/PDFName.java0000644000175000017500000000057111343262370021725 0ustar user03user03package org.freehep.graphicsio.pdf; /** * Specifies a PDFName object. *

* * @author Mark Donszelmann * @version $Id: PDFName.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFName implements PDFConstants { private String name; PDFName(String name) { this.name = name; } public String toString() { return "/" + name; } }src/main/java/org/freehep/graphicsio/pdf/PDFRedundanceTracker.java0000644000175000017500000000743211343262370024434 0ustar user03user03// Copyright 2001 freehep package org.freehep.graphicsio.pdf; import java.io.IOException; import java.util.Collection; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import java.util.Vector; /** * This class keeps track of all kinds of objects written to a pdf file and * avoids to write them several times instead of referencing the same object * several times. Right now only encoding tables are supported. * * An implementation for images and paint would be possible. * * @author Simon Fischer * @version $Id: PDFRedundanceTracker.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFRedundanceTracker { /** * To be implemented by Writers which write objects that may already have * been written. */ public interface Writer { public void writeObject(Object o, PDFRef reference, PDFWriter pdf) throws IOException; } private class Entry { private static final String REF_PREFIX = "PDF_RTObj"; private Object object; private Writer writer; private boolean written; private PDFRef reference; private Object groupID; private Entry(Object o, Object groupID, Writer w) { this.object = o; this.groupID = groupID; this.writer = w; this.written = false; this.reference = pdf.ref(REF_PREFIX + (refCount++)); } } private static int refCount = 1; private PDFWriter pdf; private Map objects; private Vector orderedObjects; // to keep order public PDFRedundanceTracker(PDFWriter pdf) { this.pdf = pdf; objects = new Hashtable(); orderedObjects = new Vector(); } /** * Returns a reference that points to object. When this method * is called several times for the same object (according to its hash code) * the same reference is returned. When writeAll() is called the * writer's writeObject() method will be called once with * object as argument.
* The groupID is only used for getGroup() */ public PDFRef getReference(Object object, Object groupID, Writer writer) { Object o = objects.get(object); if (o != null) { return ((Entry) o).reference; } else { Entry entry = new Entry(object, groupID, writer); objects.put(object, entry); orderedObjects.add(entry); return entry.reference; } } public PDFRef getReference(Object object, Writer writer) { return getReference(object, null, writer); } /** * Writes all objects that are not yet written. If the method is called * several times then each times only the new objects are written. */ public void writeAll() { Iterator i = orderedObjects.iterator(); while (i.hasNext()) { Entry entry = (Entry) i.next(); if (!entry.written) { try { // System.out.println("PDFRT: Writing: " + entry.object); entry.writer .writeObject(entry.object, entry.reference, pdf); entry.written = true; } catch (IOException e) { e.printStackTrace(); } } } } /** Returns all objects belonging to a particular group. */ public Collection getGroup(Object groupID) { Collection result = new LinkedList(); Iterator i = orderedObjects.iterator(); while (i.hasNext()) { Entry entry = (Entry) i.next(); if (groupID.equals(entry.groupID)) { result.add(entry.object); } } return result; } } src/main/java/org/freehep/graphicsio/pdf/PDFGraphics2D.java0000644000175000017500000007237611343262370023007 0ustar user03user03// Copyright 2000-2007, FreeHEP package org.freehep.graphicsio.pdf; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.Insets; import java.awt.Paint; import java.awt.Rectangle; import java.awt.Shape; import java.awt.Stroke; import java.awt.TexturePaint; import java.awt.font.LineMetrics; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import org.freehep.graphics2d.TagString; import org.freehep.graphics2d.font.FontUtilities; import org.freehep.graphics2d.font.Lookup; import org.freehep.graphicsio.AbstractVectorGraphicsIO; import org.freehep.graphicsio.FontConstants; import org.freehep.graphicsio.ImageConstants; import org.freehep.graphicsio.ImageGraphics2D; import org.freehep.graphicsio.InfoConstants; import org.freehep.graphicsio.MultiPageDocument; import org.freehep.graphicsio.PageConstants; import org.freehep.util.UserProperties; /** * Implementation of VectorGraphics that writes the output to a PDF * file. Users of this class have to generate a PDFWriter and create * an instance by invoking the factory method or the constructor. Document * specific settings like page size can then be made by the appropriate setter * methods. Before starting to draw, startExport() must be called. * When drawing is finished, call endExport(). * * @author Simon Fischer * @author Mark Donszelmann * @version $Id: PDFGraphics2D.java 10516 2007-02-06 21:11:19Z duns $ */ public class PDFGraphics2D extends AbstractVectorGraphicsIO implements MultiPageDocument, FontUtilities.ShowString { /* * ================================================================================ * Table of Contents: ------------------ 1. Constructors & Factory Methods * 2. Document Settings 3. Header, Trailer, Multipage & Comments 3.1 Header & * Trailer 3.2 MultipageDocument methods 4. Create & Dispose 5. Drawing * Methods 5.1. shapes (draw/fill) 5.1.1. lines, rectangles, round * rectangles 5.1.2. polylines, polygons 5.1.3. ovals, arcs 5.1.4. shapes * 5.2. Images 5.3. Strings 6. Transformations 7. Clipping 8. Graphics State / * Settings 8.1. stroke/linewidth 8.2. paint/color 8.3. font 8.4. rendering * hints 9. Private/Utility Methods 9.1. drawing, shape creation 9.2. font, * strings 9.3. images 9.4. transformations 10. Auxiliary * ================================================================================ */ private static final String rootKey = PDFGraphics2D.class.getName(); public static final String VERSION6 = "Acrobat Reader 6.x"; public static final String VERSION5 = "Acrobat Reader 5.x"; public static final String VERSION4 = "Acrobat Reader 4.x"; public static final String TRANSPARENT = rootKey + "." + PageConstants.TRANSPARENT; public static final String BACKGROUND = rootKey + "." + PageConstants.BACKGROUND; public static final String BACKGROUND_COLOR = rootKey + "." + PageConstants.BACKGROUND_COLOR; public static final String PAGE_SIZE = rootKey + "." + PageConstants.PAGE_SIZE; public static final String PAGE_MARGINS = rootKey + "." + PageConstants.PAGE_MARGINS; public static final String ORIENTATION = rootKey + "." + PageConstants.ORIENTATION; public static final String FIT_TO_PAGE = rootKey + "." + PageConstants.FIT_TO_PAGE; public static final String EMBED_FONTS = rootKey + "." + FontConstants.EMBED_FONTS; public static final String EMBED_FONTS_AS = rootKey + "." + FontConstants.EMBED_FONTS_AS; public static final String THUMBNAILS = rootKey + ".Thumbnails"; public static final String THUMBNAIL_SIZE = rootKey + ".ThumbnailSize"; public static final String COMPRESS = rootKey + ".Compress"; public static final String VERSION = rootKey + ".Version"; public static final String WRITE_IMAGES_AS = rootKey + "." + ImageConstants.WRITE_IMAGES_AS; public static final String AUTHOR = rootKey + "." + InfoConstants.AUTHOR; public static final String TITLE = rootKey + "." + InfoConstants.TITLE; public static final String SUBJECT = rootKey + "." + InfoConstants.SUBJECT; public static final String KEYWORDS = rootKey + "." + InfoConstants.KEYWORDS; private static final UserProperties defaultProperties = new UserProperties(); static { defaultProperties.setProperty(TRANSPARENT, true); defaultProperties.setProperty(BACKGROUND, false); defaultProperties.setProperty(BACKGROUND_COLOR, Color.GRAY); defaultProperties.setProperty(VERSION, VERSION5); defaultProperties.setProperty(COMPRESS, false); defaultProperties.setProperty(PAGE_SIZE, PageConstants.INTERNATIONAL); defaultProperties.setProperty(PAGE_MARGINS, PageConstants .getMargins(PageConstants.SMALL)); defaultProperties.setProperty(ORIENTATION, PageConstants.PORTRAIT); defaultProperties.setProperty(FIT_TO_PAGE, true); defaultProperties.setProperty(EMBED_FONTS, false); defaultProperties.setProperty(EMBED_FONTS_AS, FontConstants.EMBED_FONTS_TYPE3); defaultProperties.setProperty(THUMBNAILS, defaultProperties .getProperty(VERSION).equals(VERSION4)); defaultProperties.setProperty(THUMBNAIL_SIZE, new Dimension(128, 128)); defaultProperties.setProperty(WRITE_IMAGES_AS, ImageConstants.SMALLEST); defaultProperties.setProperty(AUTHOR, ""); defaultProperties.setProperty(TITLE, ""); defaultProperties.setProperty(SUBJECT, ""); defaultProperties.setProperty(KEYWORDS, ""); defaultProperties.setProperty(CLIP, true); defaultProperties.setProperty(TEXT_AS_SHAPES, true); } public static Properties getDefaultProperties() { return defaultProperties; } public static void setDefaultProperties(Properties newProperties) { defaultProperties.setProperties(newProperties); } public static final String version = "$Revision: 10516 $"; private static final String PDF_VERSION = "1.4"; private static final String[] COMPRESS_FILTERS = { ImageConstants.ENCODING_FLATE, ImageConstants.ENCODING_ASCII85}; private static final String[] NO_FILTERS = {}; private static final double FONTSIZE_CORRECTION = 1.0; /* * Not Used private static final CharTable STANDARD_CHAR_TABLES[] = { * Lookup.getInstance().getTable("PDFLatin"), * Lookup.getInstance().getTable("Symbol"), * Lookup.getInstance().getTable("Zapfdingbats") }; * * private static final Font STANDARD_FONT[] = { null, new Font("Symbol", * Font.PLAIN, 10), new Font("ZapfDingbats", Font.PLAIN, 10), }; */ // output private OutputStream ros; private PDFWriter os; private PDFStream pageStream; // remember some things to do private PDFFontTable fontTable; // remember which standard fonts were used private PDFImageDelayQueue delayImageQueue; // remember images XObjects to // include in the file private PDFPaintDelayQueue delayPaintQueue; // remember patterns to include // in the file // multipage private int currentPage; private boolean multiPage; private TagString[] headerText; private int headerUnderline; private Font headerFont; private TagString[] footerText; private int footerUnderline; private Font footerFont; private List titles; // extra pointers int alphaIndex; Map extGStates; /* * ================================================================================ | * 1. Constructors & Factory Methods * ================================================================================ */ public PDFGraphics2D(File file, Dimension size) throws FileNotFoundException { this(new FileOutputStream(file), size); } public PDFGraphics2D(File file, Component component) throws FileNotFoundException { this(new FileOutputStream(file), component); } public PDFGraphics2D(OutputStream ros, Dimension size) { super(size, false); init(ros); } public PDFGraphics2D(OutputStream ros, Component component) { super(component, false); init(ros); } private void init(OutputStream ros) { this.ros = new BufferedOutputStream(ros); currentPage = 0; multiPage = false; titles = new ArrayList(); initProperties(defaultProperties); } /** Cloneconstructor */ protected PDFGraphics2D(PDFGraphics2D graphics, boolean doRestoreOnDispose) { super(graphics, doRestoreOnDispose); this.os = graphics.os; this.pageStream = graphics.pageStream; this.delayImageQueue = graphics.delayImageQueue; this.delayPaintQueue = graphics.delayPaintQueue; this.fontTable = graphics.fontTable; this.currentPage = graphics.currentPage; this.multiPage = graphics.multiPage; this.titles = graphics.titles; this.alphaIndex = graphics.alphaIndex; this.extGStates = graphics.extGStates; } /* * ================================================================================ | * 2. Document Settings * ================================================================================ */ public void setMultiPage(boolean multiPage) { this.multiPage = multiPage; } public boolean isMultiPage() { return multiPage; } /** * Set the clipping enabled flag. This will affect all output operations * after this call completes. In some circumstances the clipping region is * set incorrectly (not yet understood; AWT seems to not correctly dispose * of graphic contexts). A workaround is to simply switch it off. */ public static void setClipEnabled(boolean enabled) { defaultProperties.setProperty(CLIP, enabled); } /* * ================================================================================ | * 3. Header, Trailer, Multipage & Comments * ================================================================================ */ /* 3.1 Header & Trailer */ /** * Writes the catalog, docinfo, preferences, and (as we use only single page * output the page tree. */ public void writeHeader() throws IOException { os = new PDFWriter(new BufferedOutputStream(ros), PDF_VERSION); delayImageQueue = new PDFImageDelayQueue(os); delayPaintQueue = new PDFPaintDelayQueue(os, delayImageQueue); fontTable = new PDFFontTable(os); String producer = getClass().getName(); if (!isDeviceIndependent()) { producer += " " + version.substring(1, version.length() - 1); } PDFDocInfo info = os.openDocInfo("DocInfo"); info.setTitle(getProperty(TITLE)); info.setAuthor(getProperty(AUTHOR)); info.setSubject(getProperty(SUBJECT)); info.setKeywords(getProperty(KEYWORDS)); info.setCreator(getCreator()); info.setProducer(producer); if (!isDeviceIndependent()) { Calendar now = Calendar.getInstance(); info.setCreationDate(now); info.setModificationDate(now); } info.setTrapped("False"); os.close(info); // catalog PDFCatalog catalog = os.openCatalog("Catalog", "RootPage"); catalog.setOutlines("Outlines"); catalog.setPageMode("UseOutlines"); catalog.setViewerPreferences("Preferences"); catalog.setOpenAction(new Object[] { os.ref("Page1"), os.name("Fit") }); os.close(catalog); // preferences PDFViewerPreferences prefs = os.openViewerPreferences("Preferences"); prefs.setFitWindow(true); prefs.setCenterWindow(false); os.close(prefs); // extra stuff alphaIndex = 1; extGStates = new HashMap(); // hide the multipage functionality to the user in case of single page // output by opening the first and only page immediately if (!isMultiPage()) openPage(getSize(), null, getComponent()); } public void writeBackground() { if (isProperty(TRANSPARENT)) { setBackground(null); } else if (isProperty(BACKGROUND)) { setBackground(getPropertyColor(BACKGROUND_COLOR)); clearRect(0.0, 0.0, getSize().width, getSize().height); } else { setBackground(getComponent() != null ? getComponent() .getBackground() : Color.WHITE); clearRect(0.0, 0.0, getSize().width, getSize().height); } } public void writeTrailer() throws IOException { if (!isMultiPage()) closePage(); // pages PDFPageTree pages = os.openPageTree("RootPage", null); for (int i = 1; i <= currentPage; i++) { pages.addPage("Page" + i); } Dimension pageSize = PageConstants.getSize(getProperty(PAGE_SIZE), getProperty(ORIENTATION)); pages.setMediaBox(0, 0, pageSize.getWidth(), pageSize.getHeight()); pages.setResources("Resources"); os.close(pages); // ProcSet os.object("PageProcSet", new Object[] { os.name("PDF"), os.name("Text"), os.name("ImageC") }); // Font int nFonts = fontTable.addFontDictionary(); // XObject int nXObjects = delayImageQueue.addXObjects(); // Pattern int nPatterns = delayPaintQueue.addPatterns(); // ExtGState if (extGStates.size() > 0) { PDFDictionary extGState = os.openDictionary("ExtGState"); for (Iterator i = extGStates.keySet().iterator(); i.hasNext();) { Float alpha = (Float) i.next(); String alphaName = (String) extGStates.get(alpha); PDFDictionary alphaDictionary = extGState .openDictionary(alphaName); alphaDictionary.entry("ca", alpha.floatValue()); alphaDictionary.entry("CA", alpha.floatValue()); alphaDictionary.entry("BM", os.name("Normal")); alphaDictionary.entry("AIS", false); extGState.close(alphaDictionary); } os.close(extGState); } // resources PDFDictionary resources = os.openDictionary("Resources"); resources.entry("ProcSet", os.ref("PageProcSet")); if (nFonts > 0) resources.entry("Font", os.ref("FontList")); if (nXObjects > 0) resources.entry("XObject", os.ref("XObjects")); if (nPatterns > 0) resources.entry("Pattern", os.ref("Pattern")); if (extGStates.size() > 0) resources.entry("ExtGState", os.ref("ExtGState")); os.close(resources); // outlines PDFOutlineList outlines = os.openOutlineList("Outlines", "Outline1", "Outline" + currentPage); os.close(outlines); for (int i = 1; i <= currentPage; i++) { String prev = i > 1 ? "Outline" + (i - 1) : null; String next = i < currentPage ? "Outline" + (i + 1) : null; PDFOutline outline = os.openOutline("Outline" + i, (String) titles .get(i - 1), "Outlines", prev, next); outline .setDest(new Object[] { os.ref("Page" + i), os.name("Fit") }); os.close(outline); } // delayed objects (images, patterns, fonts) processDelayed(); } public void closeStream() throws IOException { os.close(); } private void processDelayed() throws IOException { delayImageQueue.processAll(); delayPaintQueue.processAll(); fontTable.embedAll(getFontRenderContext(), isProperty(EMBED_FONTS), getProperty(EMBED_FONTS_AS)); } /* 3.2 MultipageDocument methods */ public void openPage(Component component) throws IOException { openPage(component.getSize(), component.getName(), component); } public void openPage(Dimension size, String title) throws IOException { openPage(size, title, null); } private void openPage(Dimension size, String title, Component component) throws IOException { if (size == null) size = component.getSize(); resetClip(new Rectangle(0, 0, size.width, size.height)); if (pageStream != null) { writeWarning("Page " + currentPage + " already open. " + "Call closePage() before starting a new one."); return; } BufferedImage thumbnail = null; // prepare thumbnail if possible if ((component != null) && isProperty(PDFGraphics2D.THUMBNAILS)) { thumbnail = ImageGraphics2D.generateThumbnail(component, getPropertyDimension(PDFGraphics2D.THUMBNAIL_SIZE)); } currentPage++; if (title == null) title = "Page " + currentPage + " (untitled)"; titles.add(title); PDFPage page = os.openPage("Page" + currentPage, "RootPage"); page.setContents("PageContents" + currentPage); if (thumbnail != null) page.setThumb("Thumb" + currentPage); os.close(page); if (thumbnail != null) { PDFStream thumbnailStream = os.openStream("Thumb" + currentPage); thumbnailStream.image(thumbnail, Color.black, ImageConstants.ZLIB); os.close(thumbnailStream); } pageStream = os.openStream("PageContents" + currentPage, isProperty(COMPRESS) ? COMPRESS_FILTERS : NO_FILTERS); // transform the coordinate system as necessary // 1. flip the coordinate system down and translate it upwards again // so that the origin is the upper left corner of the page. AffineTransform pageTrafo = new AffineTransform(); pageTrafo.scale(1, -1); Dimension pageSize = PageConstants.getSize(getProperty(PAGE_SIZE), getProperty(ORIENTATION)); Insets margins = PageConstants.getMargins( getPropertyInsets(PAGE_MARGINS), getProperty(ORIENTATION)); pageTrafo .translate(margins.left, -(pageSize.getHeight() - margins.top)); // in between write the header and footer (which should not be scaled!) writeHeadline(pageTrafo); writeFootline(pageTrafo); // 2. check whether we have to rescale the image to fit onto the page double scaleFactor = Math.min(getWidth() / size.width, getHeight() / size.height); if ((scaleFactor < 1) || isProperty(FIT_TO_PAGE)) { pageTrafo.scale(scaleFactor, scaleFactor); } else { scaleFactor = 1; } // 3. center the image on the page double dx = (getWidth() - size.width * scaleFactor) / 2 / scaleFactor; double dy = (getHeight() - size.height * scaleFactor) / 2 / scaleFactor; pageTrafo.translate(dx, dy); writeTransform(pageTrafo); // save the graphics context resets before setClip writeGraphicsSave(); clipRect(0, 0, size.width, size.height); // save the graphics context resets before setClip writeGraphicsSave(); delayPaintQueue.setPageMatrix(pageTrafo); writeGraphicsState(); writeBackground(); } public void closePage() throws IOException { if (pageStream == null) { writeWarning("Page " + currentPage + " already closed. " + "Call openPage() to start a new one."); return; } writeGraphicsRestore(); writeGraphicsRestore(); os.close(pageStream); pageStream = null; processDelayed(); // This does not work properly with acrobat reader // 4! } public void setHeader(Font font, TagString left, TagString center, TagString right, int underlineThickness) { this.headerFont = font; this.headerText = new TagString[3]; this.headerText[0] = left; this.headerText[1] = center; this.headerText[2] = right; this.headerUnderline = underlineThickness; } public void setFooter(Font font, TagString left, TagString center, TagString right, int underlineThickness) { this.footerFont = font; this.footerText = new TagString[3]; this.footerText[0] = left; this.footerText[1] = center; this.footerText[2] = right; this.footerUnderline = underlineThickness; } private void writeHeadline(AffineTransform pageTrafo) throws IOException { if (headerText != null) { LineMetrics metrics = headerFont.getLineMetrics("mM", getFontRenderContext()); writeLine(pageTrafo, headerFont, headerText, -metrics.getLeading() - headerFont.getSize2D() / 2, TEXT_BOTTOM, -headerFont .getSize2D() / 2, headerUnderline); } } private void writeFootline(AffineTransform pageTrafo) throws IOException { if (footerText != null) { LineMetrics metrics = footerFont.getLineMetrics("mM", getFontRenderContext()); double y = getHeight() + footerFont.getSize2D() / 2; writeLine(pageTrafo, footerFont, footerText, y + metrics.getLeading(), TEXT_TOP, y, footerUnderline); } } private void writeLine(AffineTransform trafo, Font font, TagString[] text, double ty, int yAlign, double ly, int underline) throws IOException { writeGraphicsSave(); setColor(Color.black); setFont(font); writeTransform(trafo); if (text[0] != null) drawString(text[0], 0, ty, TEXT_LEFT, yAlign); if (text[1] != null) drawString(text[1], getWidth() / 2, ty, TEXT_CENTER, yAlign); if (text[2] != null) drawString(text[2], getWidth(), ty, TEXT_RIGHT, yAlign); if (underline >= 0) { setLineWidth((double) underline); drawLine(0, ly, getWidth(), ly); } writeGraphicsRestore(); } /* * ================================================================================ | * 4. Create & Dispose * ================================================================================ */ public Graphics create() { try { writeGraphicsSave(); } catch (IOException e) { handleException(e); } return new PDFGraphics2D(this, true); } public Graphics create(double x, double y, double width, double height) { try { writeGraphicsSave(); } catch (IOException e) { handleException(e); } PDFGraphics2D graphics = new PDFGraphics2D(this, true); graphics.translate(x, y); graphics.clipRect(0, 0, width, height); return graphics; } protected void writeGraphicsSave() throws IOException { pageStream.save(); } protected void writeGraphicsRestore() throws IOException { pageStream.restore(); } /* * ================================================================================ | * 5. Drawing Methods * ================================================================================ /* * 5.1.4. shapes */ public void draw(Shape s) { try { if (getStroke() instanceof BasicStroke) { // in this case we've already handled the stroke pageStream.drawPath(s); pageStream.stroke(); } else { // otherwise handle it now pageStream.drawPath(getStroke().createStrokedShape(s)); pageStream.fill(); } } catch (IOException e) { handleException(e); } } public void fill(Shape s) { try { boolean eofill = pageStream.drawPath(s); if (eofill) { pageStream.fillEvenOdd(); } else { pageStream.fill(); } } catch (IOException e) { handleException(e); } } /* 5.2 Images */ public void copyArea(int x, int y, int width, int height, int dx, int dy) { writeWarning(getClass() + ": copyArea(int, int, int, int, int, int) not implemented."); } protected void writeImage(RenderedImage image, AffineTransform xform, Color bkg) throws IOException { PDFName ref = delayImageQueue.delayImage(image, bkg, getProperty(WRITE_IMAGES_AS)); AffineTransform imageTransform = new AffineTransform(image.getWidth(), 0.0, 0.0, -image.getHeight(), 0.0, image.getHeight()); xform.concatenate(imageTransform); writeGraphicsSave(); pageStream.matrix(xform); pageStream.xObject(ref); writeGraphicsRestore(); } /* 5.3. Strings */ protected void writeString(String str, double x, double y) throws IOException { // save the graphics context, especially the transformation matrix writeGraphicsSave(); // translate the offset to x and y AffineTransform at = new AffineTransform(1, 0, 0, 1, x, y); // transform for font at.concatenate(getFont().getTransform()); // mirror the matrix at.scale(1, -1); // write transform writeTransform(at); pageStream.beginText(); pageStream.text(0, 0); showCharacterCodes(str); pageStream.endText(); // restore the transformation matrix writeGraphicsRestore(); } /* * ================================================================================ | * 6. Transformations * ================================================================================ */ /** Write the given transformation matrix to the file. */ protected void writeTransform(AffineTransform t) throws IOException { pageStream.matrix(t); } /* * ================================================================================ | * 7. Clipping * ================================================================================ */ protected void writeSetClip(Shape s) throws IOException { // clear old clip try { AffineTransform at = getTransform(); Stroke stroke = getStroke(); writeGraphicsRestore(); writeGraphicsSave(); writeStroke(stroke); writeTransform(at); } catch (IOException e) { handleException(e); } // write clip writeClip(s); } protected void writeClip(Shape s) throws IOException { if (s == null || !isProperty(CLIP)) { return; } if (s instanceof Rectangle2D) { pageStream.move(((Rectangle2D) s).getMinX(), ((Rectangle2D) s) .getMinY()); pageStream.line(((Rectangle2D) s).getMaxX(), ((Rectangle2D) s) .getMinY()); pageStream.line(((Rectangle2D) s).getMaxX(), ((Rectangle2D) s) .getMaxY()); pageStream.line(((Rectangle2D) s).getMinX(), ((Rectangle2D) s) .getMaxY()); pageStream.closePath(); pageStream.clip(); pageStream.endPath(); } else { boolean eoclip = pageStream.drawPath(s); if (eoclip) { pageStream.clipEvenOdd(); } else { pageStream.clip(); } pageStream.endPath(); } } /* * ================================================================================ | * 8. Graphics State * ================================================================================ */ /* 8.1. stroke/linewidth */ protected void writeWidth(float width) throws IOException { pageStream.width(width); } protected void writeCap(int cap) throws IOException { switch (cap) { default: case BasicStroke.CAP_BUTT: pageStream.cap(0); break; case BasicStroke.CAP_ROUND: pageStream.cap(1); break; case BasicStroke.CAP_SQUARE: pageStream.cap(2); break; } } protected void writeJoin(int join) throws IOException { switch (join) { default: case BasicStroke.JOIN_MITER: pageStream.join(0); break; case BasicStroke.JOIN_ROUND: pageStream.join(1); break; case BasicStroke.JOIN_BEVEL: pageStream.join(2); break; } } protected void writeMiterLimit(float limit) throws IOException { pageStream.mitterLimit(limit); } protected void writeDash(float[] dash, float phase) throws IOException { pageStream.dash(dash, phase); } /* 8.2. paint/color */ public void setPaintMode() { writeWarning(getClass() + ": setPaintMode() not implemented."); } public void setXORMode(Color c1) { writeWarning(getClass() + ": setXORMode(Color) not implemented."); } protected void writePaint(Color c) throws IOException { float[] cc = c.getRGBComponents(null); // System.out.println("alpha = "+cc[3]); Float alpha = new Float(cc[3]); String alphaName = (String) extGStates.get(alpha); if (alphaName == null) { alphaName = "Alpha" + alphaIndex; alphaIndex++; extGStates.put(alpha, alphaName); } pageStream.state(os.name(alphaName)); pageStream.colorSpace(cc[0], cc[1], cc[2]); pageStream.colorSpaceStroke(cc[0], cc[1], cc[2]); } protected void writePaint(GradientPaint c) throws IOException { writePaint((Paint) c); } protected void writePaint(TexturePaint c) throws IOException { writePaint((Paint) c); } protected void writePaint(Paint paint) throws IOException { pageStream.colorSpace(os.name("Pattern")); pageStream.colorSpaceStroke(os.name("Pattern")); PDFName shadingName = delayPaintQueue.delayPaint(paint, getTransform(), getProperty(WRITE_IMAGES_AS)); pageStream.colorSpace(null, shadingName); pageStream.colorSpaceStroke(new double[] {}, shadingName); } protected void setNonStrokeColor(Color c) throws IOException { float[] cc = c.getRGBColorComponents(null); pageStream.colorSpace(cc[0], cc[1], cc[2]); } protected void setStrokeColor(Color c) throws IOException { float[] cc = c.getRGBColorComponents(null); pageStream.colorSpaceStroke(cc[0], cc[1], cc[2]); } /* 8.3. font */ protected void writeFont(Font font) throws IOException { // written when needed } /* * ================================================================================ | * 9. Auxiliary * ================================================================================ */ public GraphicsConfiguration getDeviceConfiguration() { writeWarning(getClass() + ": getDeviceConfiguration() not implemented."); return null; } public void writeComment(String comment) throws IOException { // comments are ignored and disabled, because they confuse compressed // streams } public String toString() { return "PDFGraphics2D"; } /* * ================================================================================ | * 10. Private/Utility * ================================================================================ */ public void showString(Font font, String str) throws IOException { String fontRef = fontTable.fontReference(font, isProperty(EMBED_FONTS), getProperty(EMBED_FONTS_AS)); pageStream.font(os.name(fontRef), font.getSize() * FONTSIZE_CORRECTION); pageStream.show(str); } /** * See the comment of VectorGraphicsUtitlies1. * * @see FontUtilities#showString(java.awt.Font, String, * org.freehep.graphics2d.font.CharTable, * org.freehep.graphics2d.font.FontUtilities.ShowString) */ private void showCharacterCodes(String str) throws IOException { FontUtilities.showString(getFont(), str, Lookup.getInstance().getTable( "PDFLatin"), this); } private double getWidth() { Dimension pageSize = PageConstants.getSize(getProperty(PAGE_SIZE), getProperty(ORIENTATION)); Insets margins = PageConstants.getMargins( getPropertyInsets(PAGE_MARGINS), getProperty(ORIENTATION)); return pageSize.getWidth() - margins.left - margins.right; } private double getHeight() { Dimension pageSize = PageConstants.getSize(getProperty(PAGE_SIZE), getProperty(ORIENTATION)); Insets margins = PageConstants.getMargins( getPropertyInsets(PAGE_MARGINS), getProperty(ORIENTATION)); return pageSize.getHeight() - margins.top - margins.bottom; } } src/main/java/org/freehep/graphicsio/pdf/PDFUtil.java0000644000175000017500000000355211343262370021764 0ustar user03user03// Copyright 2004, FreeHEP. package org.freehep.graphicsio.pdf; import java.text.DecimalFormat; import java.util.Calendar; import org.freehep.util.ScientificFormat; /** * Utility functions for the PDFWriter. This class handles escaping of strings, * formatting of dates, ... *

* * @author Mark Donszelmann * @version $Id: PDFUtil.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFUtil implements PDFConstants { // static class private PDFUtil() { } public static String escape(String string) { StringBuffer escape = new StringBuffer(); for (int i = 0; i < string.length(); i++) { char c = string.charAt(i); switch (c) { case '(': case ')': case '\\': escape.append('\\'); escape.append(c); break; default: escape.append(c); break; } } return escape.toString(); } public static String date(Calendar date) { int offset = date.get(Calendar.ZONE_OFFSET) + date.get(Calendar.DST_OFFSET); String tz; if (offset == 0) { tz = "Z"; } else { DecimalFormat fmt = new DecimalFormat("00"); int tzh = Math.abs(offset / 3600000); int tzm = Math.abs(offset % 3600000); if (offset > 0) { tz = "+" + fmt.format(tzh) + "'" + fmt.format(tzm) + "'"; } else { tz = "-" + fmt.format(tzh) + "'" + fmt.format(tzm) + "'"; } } return "(D:" + dateFormat.format(date.getTime()) + tz + ")"; } private static final ScientificFormat scientific = new ScientificFormat(5, 100, false); public static String fixedPrecision(double v) { return scientific.format(v); } } src/main/java/org/freehep/graphicsio/pdf/PDFWriter.java0000644000175000017500000001461611343262370022326 0ustar user03user03// Copyright 2000-2005 FreeHEP package org.freehep.graphicsio.pdf; import java.io.IOException; import java.io.OutputStream; /** * This class creates a PDF file/stream. It keeps track of all logical PDF * objects in the PDF file, will create a cross-reference table and do some * error checking while writing the file. *

* This class takes care of wrapping both PDFStreams and PDFDictionaries into * PDFObjects. *

* * @author Mark Donszelmann * @version $Id: PDFWriter.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFWriter extends PDF implements PDFConstants { private String open = null; public PDFWriter(OutputStream out) throws IOException { this(out, "1.3"); } public PDFWriter(OutputStream writer, String version) throws IOException { super(new PDFByteWriter(writer)); // PDF version out.println("%PDF-" + version); // Make sure intelligent readers understand that binary may be included out.print("%"); out.write(0xE2); out.write(0xE3); out.write(0xCF); out.write(0xD3); out.println(); out.println(); } public void close(String catalogName, String docInfoName) throws IOException { // FIXME, check for dangling references xref(); trailer(catalogName, docInfoName); startxref(); out.printPlain("%%EOF"); out.println(); out.close(); } public void comment(String comment) throws IOException { out.println("% " + comment); } public void object(String name, Object[] objs) throws IOException { PDFObject object = openObject(name); object.entry(objs); close(object); } public void object(String name, int number) throws IOException { PDFObject object = openObject(name); object.entry(number); close(object); } // public void object(String name, String string) throws IOException { // PDFObject object = openObject(name); // object.entry(string); // close(object); // } public PDFObject openObject(String name) throws IOException { // FIXME: check if name was already written! if (open != null) System.err .println("PDFWriter error: '" + open + "' was not closed"); open = "PDFObject: " + name; PDFRef ref = ref(name); int objectNumber = ref.getObjectNumber(); setXRef(objectNumber, out.getCount()); PDFObject obj = new PDFObject(this, out, objectNumber, ref .getGenerationNumber()); return obj; } public void close(PDFObject object) throws IOException { object.close(); open = null; } public PDFDictionary openDictionary(String name) throws IOException { PDFObject object = openObject(name); PDFDictionary dictionary = object.openDictionary(); return dictionary; } public void close(PDFDictionary dictionary) throws IOException { dictionary.close(); open = null; } private static final String lengthSuffix = "-length"; public PDFStream openStream(String name) throws IOException { return openStream(name, null); } public PDFStream openStream(String name, String[] encode) throws IOException { PDFObject object = openObject(name); PDFStream stream = object.openStream(name, encode); stream.entry("Length", ref(name + lengthSuffix)); return stream; } public void close(PDFStream stream) throws IOException { stream.close(); open = null; object(stream.getName() + lengthSuffix, stream.getLength()); } // // high level interface // private String catalogName; private String docInfoName; public void close() throws IOException { close(catalogName, docInfoName); } public PDFDocInfo openDocInfo(String name) throws IOException { docInfoName = name; PDFObject object = openObject(name); PDFDocInfo info = object.openDocInfo(this); return info; } public void close(PDFDocInfo info) throws IOException { info.close(); open = null; } public PDFCatalog openCatalog(String name, String pageTree) throws IOException { catalogName = name; PDFObject object = openObject(name); PDFCatalog catalog = object.openCatalog(this, ref(pageTree)); return catalog; } public void close(PDFCatalog catalog) throws IOException { catalog.close(); open = null; } public PDFPageTree openPageTree(String name, String parent) throws IOException { PDFObject object = openObject(name); PDFPageTree tree = object.openPageTree(this, ref(parent)); return tree; } public void close(PDFPageTree tree) throws IOException { tree.close(); open = null; } public PDFPage openPage(String name, String parent) throws IOException { PDFObject object = openObject(name); PDFPage page = object.openPage(this, ref(parent)); return page; } public void close(PDFPage page) throws IOException { page.close(); open = null; } public PDFViewerPreferences openViewerPreferences(String name) throws IOException { PDFObject object = openObject(name); PDFViewerPreferences prefs = object.openViewerPreferences(this); return prefs; } public void close(PDFViewerPreferences prefs) throws IOException { prefs.close(); open = null; } public PDFOutlineList openOutlineList(String name, String first, String next) throws IOException { PDFObject object = openObject(name); PDFOutlineList list = object.openOutlineList(this, ref(first), ref(next)); return list; } public void close(PDFOutlineList list) throws IOException { list.close(); open = null; } public PDFOutline openOutline(String name, String title, String parent, String prev, String next) throws IOException { PDFObject object = openObject(name); PDFOutline outline = object.openOutline(this, ref(parent), title, ref(prev), ref(next)); return outline; } public void close(PDFOutline outline) throws IOException { outline.close(); open = null; } } src/main/java/org/freehep/graphicsio/pdf/PDFExportFileType.java0000644000175000017500000001051211343262370023764 0ustar user03user03// Copyright 2001-2007, FreeHEP. package org.freehep.graphicsio.pdf; import java.awt.Component; import java.awt.Dimension; import java.io.IOException; import java.io.OutputStream; import java.util.Properties; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import org.freehep.graphics2d.VectorGraphics; import org.freehep.graphicsio.ImageConstants; import org.freehep.graphicsio.InfoConstants; import org.freehep.graphicsio.AbstractVectorGraphicsIO; import org.freehep.graphicsio.exportchooser.AbstractExportFileType; import org.freehep.graphicsio.exportchooser.BackgroundPanel; import org.freehep.graphicsio.exportchooser.FontPanel; import org.freehep.graphicsio.exportchooser.ImageTypePanel; import org.freehep.graphicsio.exportchooser.InfoPanel; import org.freehep.graphicsio.exportchooser.OptionCheckBox; import org.freehep.graphicsio.exportchooser.OptionComboBox; import org.freehep.graphicsio.exportchooser.OptionPanel; import org.freehep.graphicsio.exportchooser.PageLayoutPanel; import org.freehep.graphicsio.exportchooser.PageMarginPanel; import org.freehep.swing.layout.TableLayout; import org.freehep.util.UserProperties; /** * * @author Simon Fischer * @version $Id: PDFExportFileType.java 12753 2007-06-12 22:32:31Z duns $ */ public class PDFExportFileType extends AbstractExportFileType { final private static String[] versionList = { PDFGraphics2D.VERSION4, PDFGraphics2D.VERSION5 }; public String getDescription() { return "Portable Document Format"; } public String[] getExtensions() { return new String[] { "pdf" }; } public String[] getMIMETypes() { return new String[] { "application/pdf" }; } public boolean isMultipageCapable() { return true; } public boolean hasOptionPanel() { return true; } public JPanel createOptionPanel(Properties user) { UserProperties options = new UserProperties(user, PDFGraphics2D .getDefaultProperties()); OptionPanel format = new OptionPanel("Format"); OptionComboBox version = new OptionComboBox(options, PDFGraphics2D.VERSION, versionList); format.add(TableLayout.LEFT, new JLabel("PDF Version")); format.add(TableLayout.RIGHT, version); format.add(TableLayout.FULL, new OptionCheckBox(options, PDFGraphics2D.COMPRESS, "Compress")); JPanel preview = new OptionPanel("Preview"); JCheckBox thumbnails = new OptionCheckBox(options, PDFGraphics2D.THUMBNAILS, "Include Thumbnail"); thumbnails.setToolTipText("Thumbnails are automatically generated by " + "Acrobat Reader 5"); preview.add(TableLayout.FULL, thumbnails); version.selects(PDFGraphics2D.VERSION4, thumbnails); // rootKeys for FontProperties String rootKey = PDFGraphics2D.class.getName(); String abstractRootKey = AbstractVectorGraphicsIO.class.getName(); JPanel infoPanel = new InfoPanel(options, rootKey, new String[] { InfoConstants.AUTHOR, InfoConstants.TITLE, InfoConstants.SUBJECT, InfoConstants.KEYWORDS }); // TableLayout.LEFT Panel JPanel leftPanel = new OptionPanel(); leftPanel .add(TableLayout.COLUMN, new PageLayoutPanel(options, rootKey)); leftPanel .add(TableLayout.COLUMN, new PageMarginPanel(options, rootKey)); leftPanel.add(TableLayout.COLUMN_FILL, new JLabel()); // TableLayout.RIGHT Panel JPanel rightPanel = new OptionPanel(); rightPanel.add(TableLayout.COLUMN, format); rightPanel.add(TableLayout.COLUMN, preview); rightPanel.add(TableLayout.COLUMN, new BackgroundPanel(options, rootKey, true)); rightPanel.add(TableLayout.COLUMN, new ImageTypePanel(options, rootKey, new String[] { ImageConstants.SMALLEST, ImageConstants.ZLIB, ImageConstants.JPG })); rightPanel.add(TableLayout.COLUMN, new FontPanel(options, rootKey, abstractRootKey)); rightPanel.add(TableLayout.COLUMN_FILL, new JLabel()); // Make the full panel. OptionPanel optionsPanel = new OptionPanel(); optionsPanel.add("0 0 [5 5 5 5] wt", leftPanel); optionsPanel.add("1 0 [5 5 5 5] wt", rightPanel); optionsPanel.add("0 1 2 1 [5 5 5 5] wt", infoPanel); optionsPanel.add(TableLayout.COLUMN_FILL, new JLabel()); return optionsPanel; } public VectorGraphics getGraphics(OutputStream os, Component target) throws IOException { return new PDFGraphics2D(os, target); } public VectorGraphics getGraphics(OutputStream os, Dimension dimension) throws IOException { return new PDFGraphics2D(os, dimension); } } src/main/java/org/freehep/graphicsio/pdf/PDFFontEmbedder.java0000644000175000017500000000743111343262370023405 0ustar user03user03// Copyright 2001-2005 freehep package org.freehep.graphicsio.pdf; import java.awt.font.FontRenderContext; import java.io.IOException; import org.freehep.graphics2d.font.CharTable; import org.freehep.graphicsio.font.FontEmbedder; /** * Superclass of all FontEmbedders for PDF documents. Subclasses must implement * all abstract methods which are called in the following order: *

* * @author Simon Fischer * @version $Id: PDFFontEmbedder.java 8584 2006-08-10 23:06:37Z duns $ */ public abstract class PDFFontEmbedder extends FontEmbedder { /** sloppily declared protected */ protected PDFWriter pdf; private PDFDictionary fontDict; private String reference; private PDFRedundanceTracker redundanceTracker; public PDFFontEmbedder(FontRenderContext context, PDFWriter pdf, String reference, PDFRedundanceTracker tracker) { super(context); this.pdf = pdf; this.reference = reference; this.redundanceTracker = tracker; } /** Returns the font subtype (currently only Type3). */ protected abstract String getSubtype(); /** Add additional entries to the font Dictionary. */ protected abstract void addAdditionalEntries(PDFDictionary fontDict) throws IOException; /** * Add additional dicionaries to the PDFWriter which may be referenced by * entries generated by addAdditionalEntries() */ protected abstract void addAdditionalInitDicts() throws IOException; /** * Returns the reference String that identifies the font dictionary. Use * this reference plus underscore plus suffix for other dictionaries. */ protected String getReference() { return reference; } protected void openIncludeFont() throws IOException { fontDict = pdf.openDictionary(reference); fontDict.entry("Type", pdf.name("Font")); fontDict.entry("Subtype", pdf.name(getSubtype())); fontDict.entry("Name", pdf.name(getFontName())); fontDict.entry("FirstChar", 0); fontDict.entry("LastChar", 255); // fontDict.entry("Encoding", pdf.ref(reference+"Encoding")); fontDict.entry("Encoding", redundanceTracker.getReference( getEncodingTable(), PDFCharTableWriter.getInstance())); fontDict.entry("Widths", pdf.ref(reference + "Widths")); addAdditionalEntries(fontDict); pdf.close(fontDict); addAdditionalInitDicts(); } protected void closeEmbedFont() { } protected void writeWidths(double[] widths) throws IOException { Object[] widthsObj = new Object[256]; for (int i = 0; i < widthsObj.length; i++) { widthsObj[i] = new Double(widths[i]); } pdf.object(reference + "Widths", widthsObj); } protected void writeEncoding(CharTable charTable) throws IOException { // writeEncoding(pdf, reference+"Encoding", charTable); } public static void writeEncoding(PDFWriter pdf, String ref, CharTable charTable) throws IOException { PDFDictionary encoding = pdf.openDictionary(ref); encoding.entry("Type", pdf.name("Encoding")); Object[] differences = new Object[257]; differences[0] = new Integer(0); for (int i = 0; i < 256; i++) { String charName = charTable.toName(i); differences[i + 1] = (charName != null) ? pdf.name(charName) : pdf .name(NOTDEF); } encoding.entry("Differences", differences); pdf.close(encoding); } protected String createCharacterReference(String characterName) { return "Glyph_" + reference + ":" + characterName; } } src/main/java/org/freehep/graphicsio/pdf/PDF.java0000644000175000017500000000674411343262370021134 0ustar user03user03// Copyright 2000-2005 FreeHEP package org.freehep.graphicsio.pdf; import java.io.IOException; import java.text.DecimalFormat; import java.util.Hashtable; import java.util.Vector; /** * Implements the lookup tables. *

* * @author Mark Donszelmann * @version $Id: PDF.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDF { private int generationNumber = 0; private Hashtable refsByName = new Hashtable(); // of PDFRefs stored by name private Vector refsByNumber = new Vector(); // of PDFRefs stored by number private Vector xrefsByNumber = new Vector(); // of offsets stored by // refnumber private int startXref = 0; protected PDFByteWriter out; PDF(PDFByteWriter out) { this.out = out; // add dummy element to refsByNumber and xrefsByNumber refsByNumber.addElement(new PDFRef("Dummy", 0, 0)); xrefsByNumber.addElement(new Integer(999999)); } public PDFName name(String name) { return new PDFName(name); } public PDFRef ref(String name) { if (name == null) return null; PDFRef ref = (PDFRef) refsByName.get(name); if (ref == null) { int refNumber = refsByNumber.size(); ref = new PDFRef(name, refNumber, generationNumber); refsByName.put(name, ref); refsByNumber.add(ref); xrefsByNumber.add(null); } return ref; } public PDFRef[] ref(String[] names) { PDFRef[] refs = new PDFRef[names.length]; for (int i = 0; i < names.length; i++) { refs[i] = ref(names[i]); } return refs; } protected void setXRef(int objectNumber, int offset) { xrefsByNumber.set(objectNumber, new Integer(offset)); } protected void xref() throws IOException { DecimalFormat offsetFormat = new DecimalFormat("0000000000"); DecimalFormat linkFormat = new DecimalFormat("00000"); startXref = out.getCount(); out.printPlain("xref"); out.println(); out.printPlain(0 + " " + xrefsByNumber.size()); out.println(); // the free list header out.printPlain(offsetFormat.format(0) + " " + linkFormat.format(65535) + " f\r\n"); // the used list for (int i = 1; i < xrefsByNumber.size(); i++) { Integer offsetObject = (Integer) xrefsByNumber.get(i); if (offsetObject != null) { int offset = offsetObject.intValue(); out.printPlain(offsetFormat.format(offset) + " " + linkFormat.format(0) + " n\r\n"); } else { PDFRef ref = (PDFRef) refsByNumber.get(i); System.err.println("PDFWriter: PDFRef '" + ref.getName() + "' is used but not defined."); } } out.println(); } protected void trailer(String rootName, String docInfoName) throws IOException { out.println("trailer"); PDFDictionary dictionary = new PDFDictionary(this, out); dictionary.entry("Size", refsByName.size()); dictionary.entry("Root", ref(rootName)); if (docInfoName != null) dictionary.entry("Info", ref(docInfoName)); dictionary.close(); out.println(); } protected void startxref() throws IOException { out.println("startxref"); out.println(startXref); out.println(); } }src/main/java/org/freehep/graphicsio/pdf/PDFConstants.java0000644000175000017500000000251411343262370023020 0ustar user03user03package org.freehep.graphicsio.pdf; import java.text.SimpleDateFormat; /** * Specifies constants for use with the PDFWriter, PDFStream and PDFUtil. *

* * @author Mark Donszelmann * @version $Id: PDFConstants.java 8584 2006-08-10 23:06:37Z duns $ */ public interface PDFConstants { public final static String EOL = System.getProperty("line.separator"); // // Constants for PDFStream // // Line Cap Styles (see Table 4.4) public static final int CAP_BUTT = 0; public static final int CAP_ROUND = 1; public static final int CAP_SQUARE = 2; // Line Join Styles (see Table 4.5) public static final int JOIN_MITTER = 0; public static final int JOIN_ROUND = 1; public static final int JOIN_BEVEL = 2; // Rendering Modes (see Table 5.3) public static final int MODE_FILL = 0; public static final int MODE_STROKE = 1; public static final int MODE_FILL_STROKE = 2; public static final int MODE_INVISIBLE = 3; public static final int MODE_FILL_CLIP = 4; public static final int MODE_STROKE_CLIP = 5; public static final int MODE_FILL_STROKE_CLIP = 6; public static final int MODE_CLIP = 7; // Date Format for PDF: (D:YYYYMMDDHHmmSSOHH'mm') public static final SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyyMMddHHmmss"); } src/main/java/org/freehep/graphicsio/pdf/PDFFontEmbedderType1.java0000644000175000017500000001142211343262370024323 0ustar user03user03// Copyright 2001-2005 freehep package org.freehep.graphicsio.pdf; import java.awt.font.FontRenderContext; import java.awt.font.LineMetrics; import java.awt.geom.Rectangle2D; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.freehep.graphicsio.font.FontEmbedderType1; /** * Font embedder for type one fonts in pdf documents. * * @author Simon Fischer * @version $Id: PDFFontEmbedderType1.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFFontEmbedderType1 extends FontEmbedderType1 { private ByteArrayOutputStream byteBuffer; private String reference; private PDFWriter pdf; private PDFStream fontFile; private PDFRedundanceTracker redundanceTracker; public static PDFFontEmbedderType1 create(FontRenderContext context, PDFWriter pdf, String reference, PDFRedundanceTracker tracker) { return new PDFFontEmbedderType1(context, pdf, reference, new ByteArrayOutputStream(), tracker); } private PDFFontEmbedderType1(FontRenderContext context, PDFWriter pdf, String reference, ByteArrayOutputStream byteOut, PDFRedundanceTracker tracker) { super(context, byteOut, false); this.byteBuffer = byteOut; this.pdf = pdf; this.reference = reference; this.redundanceTracker = tracker; } private String getReference() { return reference; } // FIXME: The StemV entry is missing in the FontDescriptor dictionary, but // it // does not cause the Acrobat Reader to crash. protected void openIncludeFont() throws IOException { super.openIncludeFont(); PDFDictionary fontDict = pdf.openDictionary(reference); fontDict.entry("Type", pdf.name("Font")); fontDict.entry("Subtype", pdf.name("Type1")); fontDict.entry("Name", pdf.name(getFontName())); fontDict.entry("FirstChar", 0); fontDict.entry("LastChar", 255); // fontDict.entry("Encoding", pdf.ref(reference+"Encoding")); fontDict.entry("Encoding", redundanceTracker.getReference( getEncodingTable(), PDFCharTableWriter.getInstance())); fontDict.entry("Widths", pdf.ref(reference + "Widths")); fontDict.entry("BaseFont", pdf.name(getFontName())); // = FontName in // font program fontDict.entry("FontDescriptor", pdf.ref(getReference() + "FontDescriptor")); pdf.close(fontDict); PDFDictionary fontDescriptor = pdf.openDictionary(getReference() + "FontDescriptor"); fontDescriptor.entry("Type", pdf.name("FontDescriptor")); LineMetrics metrics = getFont().getLineMetrics("mM", getContext()); fontDescriptor.entry("Ascent", metrics.getAscent()); fontDescriptor.entry("Descent", metrics.getDescent()); fontDescriptor.entry("FontName", pdf.name(getFontName())); fontDescriptor.entry("Flags", 32); fontDescriptor.entry("CapHeight", metrics.getAscent()); fontDescriptor.entry("ItalicAngle", getFont().getItalicAngle()); // fontDescriptor.entry("StemV", 0); Rectangle2D boundingBox = getFontBBox(); double llx = boundingBox.getX(); double lly = boundingBox.getY(); double urx = boundingBox.getX() + boundingBox.getWidth(); double ury = boundingBox.getY() + boundingBox.getHeight(); fontDescriptor.entry("FontBBox", new double[] { llx, lly, urx, ury }); fontDescriptor.entry("FontFile", pdf.ref(getReference() + "FontFile")); pdf.close(fontDescriptor); } protected void writeWidths(double[] widths) throws IOException { super.writeWidths(widths); Object[] widthsObj = new Object[256]; for (int i = 0; i < widthsObj.length; i++) widthsObj[i] = new Integer((int) Math.round(widths[i])); pdf.object(reference + "Widths", widthsObj); } // protected void writeEncoding(CharTable charTable) throws IOException { // super.writeEncoding(charTable); // FontEmbedderPDF.writeEncoding(pdf, getReference()+"Encoding", charTable); // } protected void openGlyphs() throws IOException { super.openGlyphs(); } protected void closeEmbedFont() throws IOException { super.closeEmbedFont(); fontFile = pdf.openStream(getReference() + "FontFile", new String[] { "Flate", "ASCII85" }); fontFile.entry("Length1", getAsciiLength()); fontFile.entry("Length2", getEncryptedLength()); fontFile.entry("Length3", 0); // leave it to the viewer application to // add the 512 zeros String file = byteBuffer.toString("US-ASCII"); fontFile.print(file); pdf.close(fontFile); } } src/main/java/org/freehep/graphicsio/pdf/PDFObject.java0000644000175000017500000001313011343262370022246 0ustar user03user03package org.freehep.graphicsio.pdf; import java.io.IOException; /** * Implements a numbered PDFObject. *

* * @author Mark Donszelmann * @version $Id: PDFObject.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFObject implements PDFConstants { protected PDF pdf; private PDFByteWriter out; private String open; private boolean ok; PDFObject(PDF pdf, PDFByteWriter writer, int objectNumber, int generationNumber) throws IOException { this.pdf = pdf; out = writer; out.println(objectNumber + " " + generationNumber + " obj"); out.indent(); ok = true; } void close() throws IOException { out.outdent(); out.println("endobj"); out.println(); ok = false; } public void entry(int number) throws IOException { if (!ok) System.err.println("PDFWriter: 'PDFObject' was closed"); out.println(number); } public void entry(Object[] objs) throws IOException { if (!ok) System.err.println("PDFWriter: 'PDFObject' was closed"); out.print("["); for (int i = 0; i < objs.length; i++) { if (i != 0) out.printPlain(" "); out.printPlain(objs[i]); } out.printPlain("]"); out.println(); } // public void entry(String string) throws IOException { // if (!ok) System.err.println("PDFWriter: 'PDFObject' was closed"); // out.println("("+PDFUtil.escape(string)+")"); // } PDFDictionary openDictionary() throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDictionary' was closed"); if (open != null) System.err .println("PDFWriter error: '" + open + "' was not closed"); open = "PDFDictionary"; PDFDictionary dictionary = new PDFDictionary(pdf, out, this); return dictionary; } void close(PDFDictionary dictionary) throws IOException { dictionary.close(); open = null; } PDFStream openStream(String name, String[] encode) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFStream' was closed"); if (open != null) System.err .println("PDFWriter error: '" + open + "' was not closed"); open = "PDFStream"; PDFStream stream = new PDFStream(pdf, out, name, this, encode); return stream; } void close(PDFStream stream) throws IOException { stream.close(); open = null; } PDFDocInfo openDocInfo(PDF pdf) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDocInfo' was closed"); if (open != null) System.err .println("PDFWriter error: '" + open + "' was not closed"); open = "PDFDocInfo"; PDFDocInfo info = new PDFDocInfo(pdf, out, this); return info; } PDFCatalog openCatalog(PDF pdf, PDFRef pageTree) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFCatalog' was closed"); if (open != null) System.err .println("PDFWriter error: '" + open + "' was not closed"); open = "PDFCatalog"; PDFCatalog catalog = new PDFCatalog(pdf, out, this, pageTree); return catalog; } PDFPageTree openPageTree(PDF pdf, PDFRef parent) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFPageTree' was closed"); if (open != null) System.err .println("PDFWriter error: '" + open + "' was not closed"); open = "PDFPageTree"; PDFPageTree tree = new PDFPageTree(pdf, out, this, parent); return tree; } PDFPage openPage(PDF pdf, PDFRef parent) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFPage' was closed"); if (open != null) System.err .println("PDFWriter error: '" + open + "' was not closed"); open = "PDFPage"; PDFPage page = new PDFPage(pdf, out, this, parent); return page; } PDFViewerPreferences openViewerPreferences(PDF pdf) throws IOException { if (!ok) System.err .println("PDFWriter error: 'PDFViewerPreferences' was closed"); if (open != null) System.err .println("PDFWriter error: '" + open + "' was not closed"); open = "PDFViewerPreferences"; PDFViewerPreferences prefs = new PDFViewerPreferences(pdf, out, this); return prefs; } PDFOutlineList openOutlineList(PDF pdf, PDFRef first, PDFRef last) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFOutlineList' was closed"); if (open != null) System.err .println("PDFWriter error: '" + open + "' was not closed"); open = "PDFOutlineList"; PDFOutlineList list = new PDFOutlineList(pdf, out, this, first, last); return list; } PDFOutline openOutline(PDF pdf, PDFRef parent, String title, PDFRef prev, PDFRef next) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFOutline' was closed"); if (open != null) System.err .println("PDFWriter error: '" + open + "' was not closed"); open = "PDFOutline"; PDFOutline outline = new PDFOutline(pdf, out, this, parent, title, prev, next); return outline; } } src/main/java/org/freehep/graphicsio/pdf/PDFViewerPreferences.java0000644000175000017500000000235611343262370024473 0ustar user03user03package org.freehep.graphicsio.pdf; import java.io.IOException; /** * Implements the Viewer Preferences (see Table 7.1). *

* * @author Mark Donszelmann * @version $Id: PDFViewerPreferences.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFViewerPreferences extends PDFDictionary { PDFViewerPreferences(PDF pdf, PDFByteWriter writer, PDFObject object) throws IOException { super(pdf, writer, object); } public void setHideToolbar(boolean hide) throws IOException { entry("HideToolbar", hide); } public void setHideMenubar(boolean hide) throws IOException { entry("HideMenubar", hide); } public void setHideWindowUI(boolean hide) throws IOException { entry("HideWindowUI", hide); } public void setFitWindow(boolean fit) throws IOException { entry("FitWindow", fit); } public void setCenterWindow(boolean center) throws IOException { entry("CenterWindow", center); } public void setNonFullScreenPageMode(String mode) throws IOException { entry("NonFullScreenPageMode", pdf.name(mode)); } public void setDirection(String direction) throws IOException { entry("Direction", pdf.name(direction)); } } src/main/java/org/freehep/graphicsio/pdf/PDFDictionary.java0000644000175000017500000001200311343262370023143 0ustar user03user03package org.freehep.graphicsio.pdf; import java.io.IOException; import java.util.Calendar; /** * Implements a PDF Dictionary. All PDFObjects (including java Strings and * arrays) can be entered into the dictionary. *

* * @author Mark Donszelmann * @version $Id: PDFDictionary.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFDictionary implements PDFConstants { private String open = null; protected PDFByteWriter out; private boolean ok; private PDFObject object; protected PDF pdf; PDFDictionary(PDF pdf, PDFByteWriter writer) throws IOException { this(pdf, writer, null); } PDFDictionary(PDF pdf, PDFByteWriter writer, PDFObject parent) throws IOException { this.pdf = pdf; object = parent; out = writer; out.println("<< "); out.indent(); ok = true; } void close() throws IOException { if (open != null) System.err .println("PDFWriter error: '" + open + "' was not closed"); out.outdent(); out.println(">>"); if (object != null) object.close(); ok = false; } public void entry(String key, String string) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDictionary' was closed"); out.println("/" + key + " (" + PDFUtil.escape(string) + ")"); } public void entry(String key, PDFName name) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDictionary' was closed"); out.println("/" + key + " " + name); } public void entry(String key, int number) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDictionary' was closed"); out.println("/" + key + " " + number); } public void entry(String key, double number) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDictionary' was closed"); out.println("/" + key + " " + PDFUtil.fixedPrecision(number)); } public void entry(String key, boolean bool) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDictionary' was closed"); out.println("/" + key + " " + (bool ? "true" : "false")); } public void entry(String key, PDFRef ref) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDictionary' was closed"); out.println("/" + key + " " + ref); } public void entry(String key, Calendar date) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDictionary' was closed"); out.println("/" + key + " " + PDFUtil.date(date)); } public void entry(String key, Object[] objs) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDictionary' was closed"); out.print("/" + key + " ["); for (int i = 0; i < objs.length; i++) { if (i != 0) out.printPlain(" "); out.printPlain(objs[i]); } out.printPlain("]"); out.println(); } public void entry(String key, int[] numbers) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDictionary' was closed"); out.print("/" + key + " ["); for (int i = 0; i < numbers.length; i++) { if (i != 0) out.printPlain(" "); out.printPlain(numbers[i]); } out.printPlain("]"); out.println(); } public void entry(String key, double[] numbers) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDictionary' was closed"); out.print("/" + key + " ["); for (int i = 0; i < numbers.length; i++) { if (i != 0) out.printPlain(" "); out.printPlain(PDFUtil.fixedPrecision(numbers[i])); } out.printPlain("]"); out.println(); } public void entry(String key, boolean[] bool) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDictionary' was closed"); out.print("/" + key + " ["); for (int i = 0; i < bool.length; i++) { if (i != 0) out.printPlain(" "); out.printPlain(bool[i] ? "true" : "false"); } out.printPlain("]"); out.println(); } public PDFDictionary openDictionary(String name) throws IOException { if (!ok) System.err.println("PDFWriter error: 'PDFDictionary' was closed"); if (open != null) System.err .println("PDFWriter error: '" + open + "' was not closed"); open = "PDFDictionary: " + name; out.println("/" + name); PDFDictionary dictionary = new PDFDictionary(pdf, out); return dictionary; } public void close(PDFDictionary dictionary) throws IOException { dictionary.close(); open = null; } } src/main/java/org/freehep/graphicsio/pdf/PDFOutline.java0000644000175000017500000000254511343262370022467 0ustar user03user03package org.freehep.graphicsio.pdf; import java.io.IOException; /** * Implements the Outline Item Dictionary (see Table 7.4). *

* * @author Mark Donszelmann * @version $Id: PDFOutline.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFOutline extends PDFDictionary { PDFOutline(PDF pdf, PDFByteWriter writer, PDFObject object, PDFRef parent, String title, PDFRef prev, PDFRef next) throws IOException { super(pdf, writer, object); entry("Parent", parent); entry("Title", title); entry("Prev", prev); entry("Next", next); } public void setFirst(String first) throws IOException { entry("First", pdf.ref(first)); } public void setLast(String last) throws IOException { entry("Last", pdf.ref(last)); } public void setCount(int count) throws IOException { entry("Count", count); } public void setDest(PDFName dest) throws IOException { entry("Dest", dest); } public void setDest(String dest) throws IOException { entry("Dest", dest); } public void setDest(Object[] dest) throws IOException { entry("Dest", dest); } public void setA(String a) throws IOException { entry("A", pdf.ref(a)); } public void setSE(String se) throws IOException { entry("SE", pdf.ref(se)); } } src/main/java/org/freehep/graphicsio/pdf/PDFDocInfo.java0000644000175000017500000000262411343262370022367 0ustar user03user03package org.freehep.graphicsio.pdf; import java.io.IOException; import java.util.Calendar; /** * Implements the Document Information Dictionary (see Table 8.2). *

* * @author Mark Donszelmann * @version $Id: PDFDocInfo.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFDocInfo extends PDFDictionary { PDFDocInfo(PDF pdf, PDFByteWriter writer, PDFObject parent) throws IOException { super(pdf, writer, parent); } public void setTitle(String title) throws IOException { entry("Title", title); } public void setAuthor(String author) throws IOException { entry("Author", author); } public void setSubject(String subject) throws IOException { entry("Subject", subject); } public void setKeywords(String keywords) throws IOException { entry("Keywords", keywords); } public void setCreator(String creator) throws IOException { entry("Creator", creator); } public void setProducer(String producer) throws IOException { entry("Producer", producer); } public void setCreationDate(Calendar date) throws IOException { entry("CreationDate", date); } public void setModificationDate(Calendar date) throws IOException { entry("ModDate", date); } public void setTrapped(String name) throws IOException { entry("Trapped", pdf.name(name)); } } src/main/java/org/freehep/graphicsio/pdf/PDFFontIncluder.java0000644000175000017500000000772311343262370023447 0ustar user03user03// Copyright 2001-2005 freehep package org.freehep.graphicsio.pdf; import java.awt.Font; import java.awt.font.FontRenderContext; import java.io.IOException; import org.freehep.graphics2d.font.CharTable; import org.freehep.graphicsio.font.FontIncluder; /** * Includes one of the 14 Type1 fonts in PDF documents * * @author Simon Fischer * @version $id$ */ public class PDFFontIncluder extends FontIncluder { private static final int PLAIN = 0; private static final int BOLD = 1; private static final int ITALIC = 2; private static final int BOLDITALIC = 3; private static final int COURIER = 0; private static final int HELVETICA = 1; private static final int TIMES = 2; private static final int SYMBOL = 3; private static final int DINGBATS = 4; private static final String[][] STANDARD_FONT = { { "Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique" }, { "Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique" }, { "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic" }, { "Symbol" }, { "ZapfDingbats" } }; private PDFWriter pdf; private String reference; private PDFRedundanceTracker redundanceTracker; public PDFFontIncluder(FontRenderContext context, PDFWriter pdf, String reference, PDFRedundanceTracker redundanceTracker) { super(context); this.pdf = pdf; this.reference = reference; this.redundanceTracker = redundanceTracker; } protected void openIncludeFont() throws IOException { int style = getFontStyle(getFont()); int fontBaseIndex = getFontBaseIndex(getFont()); PDFDictionary font = pdf.openDictionary(reference); font.entry("Type", pdf.name("Font")); font.entry("Subtype", pdf.name("Type1")); font.entry("Name", pdf.name(reference)); font.entry("BaseFont", pdf.name(STANDARD_FONT[fontBaseIndex][style])); // font.entry("Encoding", pdf.ref(reference+"Encoding")); font.entry("Encoding", redundanceTracker.getReference( getEncodingTable(), PDFCharTableWriter.getInstance())); pdf.close(font); } protected void writeEncoding(CharTable charTable) throws IOException { } public static boolean isStandardFont(Font font) { String fontName = font.getName().toLowerCase(); return (fontName.indexOf("helvetica") >= 0) || (fontName.indexOf("times") >= 0) || (fontName.indexOf("courier") >= 0) || (fontName.indexOf("symbol") >= 0) || (fontName.indexOf("dingbats") >= 0); } /** Returns the index of the standard font according to STANDARD_FONT. */ private static int getFontBaseIndex(Font font) { String fontName = font.getName().toLowerCase(); if (fontName.indexOf("helvetica") >= 0) { return HELVETICA; } else if (fontName.indexOf("times") >= 0) { return TIMES; } else if (fontName.indexOf("courier") >= 0) { return COURIER; } else if (fontName.indexOf("symbol") >= 0) { return SYMBOL; } else if (fontName.indexOf("dingbats") >= 0) { return DINGBATS; } else { // use HELVETICA as default return HELVETICA; } } /** Returns the index of the respective entry in STANDARD_FONT[fontIndex]. */ private static int getFontStyle(Font font) { int fontBase = getFontBaseIndex(font); if ((fontBase >= 0) && (STANDARD_FONT[fontBase].length == 1)) return PLAIN; if (fontBase < 0) return -1; if (font.isBold()) { if (font.isItalic()) { return BOLDITALIC; } else { return BOLD; } } else { if (font.isItalic()) return ITALIC; } return PLAIN; } } src/main/java/org/freehep/graphicsio/pdf/PDFOutlineList.java0000644000175000017500000000122611343262370023316 0ustar user03user03package org.freehep.graphicsio.pdf; import java.io.IOException; /** * Implements the Outline Dictionary (see Table 7.3). *

* * @author Mark Donszelmann * @version $Id: PDFOutlineList.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFOutlineList extends PDFDictionary { PDFOutlineList(PDF pdf, PDFByteWriter writer, PDFObject object, PDFRef first, PDFRef last) throws IOException { super(pdf, writer, object); entry("Type", pdf.name("Outlines")); entry("First", first); entry("Last", last); } public void setCount(int count) throws IOException { entry("Count", count); } } src/main/java/org/freehep/graphicsio/pdf/ImageBytes.java0000644000175000017500000000732711343262370022552 0ustar user03user03// Copyright 2000-2007 FreeHEP package org.freehep.graphicsio.pdf; import org.freehep.graphicsio.ImageConstants; import org.freehep.graphicsio.ImageGraphics2D; import java.awt.image.RenderedImage; import java.awt.Color; import java.io.IOException; /** * PDF writes images as ZLIB or JPEG. This class converts an image to a * byte[]. If neither {@link ImageConstants#ZLIB} nor * {@link ImageConstants#JPEG} is passed the smallest size is stored * for {@link #getBytes()}. The method {@link #getFormat()} returns the * used format. * * @author Steffen Greiffenberg * @version $Revision$ */ class ImageBytes { /** * Used format during creation of bytes */ private String format; /** * Bytes in given format */ private byte[] bytes; /** * Encodes the passed image * * @param image image to convert * @param bkg background color * @param format format could be {@link ImageConstants#ZLIB} or {@link ImageConstants#JPEG} * @param colorModel e.g. {@link org.freehep.graphicsio.ImageConstants#COLOR_MODEL_RGB} * @throws IOException thrown by {@link org.freehep.graphicsio.ImageGraphics2D#toByteArray(java.awt.image.RenderedImage, String, String, java.util.Properties)} */ public ImageBytes(RenderedImage image, Color bkg, String format, String colorModel) throws IOException { // ZLIB encoding, transparent images allways require ZLIB if (ImageConstants.ZLIB.equals(format) || (image.getColorModel().hasAlpha() && (bkg == null))) { bytes = toZLIB(image, bkg, colorModel); this.format = ImageConstants.ZLIB; } // JPG encoding else if (ImageConstants.JPEG.equals(format)) { bytes = toJPG(image); this.format = ImageConstants.JPG; } else { // calculate both byte arrays byte[] jpgBytes = toJPG(image); byte[] zlibBytes = toZLIB(image, bkg, colorModel); // compare sizes to determine smalles format if (jpgBytes.length < 0.5 * zlibBytes.length) { bytes = jpgBytes; this.format = ImageConstants.JPG; } else { bytes = zlibBytes; this.format = ImageConstants.ZLIB; } } } /** * Creates the ZLIB Bytes for PDF images * * @param image image to convert * @param bkg background color * @param colorModel e.g. {@link org.freehep.graphicsio.ImageConstants#COLOR_MODEL_RGB} * @return bytes * @throws IOException thrown by {@link org.freehep.graphicsio.ImageGraphics2D#toByteArray(java.awt.image.RenderedImage, String, String, java.util.Properties)} */ private byte[] toZLIB(RenderedImage image, Color bkg, String colorModel) throws IOException { return ImageGraphics2D.toByteArray( image, ImageConstants.RAW, ImageConstants.ENCODING_FLATE_ASCII85, ImageGraphics2D.getRAWProperties(bkg, colorModel)); } /** * Creates the JPG bytes for PDF images * * @param image image to convert * @return bytes * @throws IOException thrown by {@link org.freehep.graphicsio.ImageGraphics2D#toByteArray(java.awt.image.RenderedImage, String, String, java.util.Properties)} */ private byte[] toJPG(RenderedImage image) throws IOException { return ImageGraphics2D.toByteArray( image, ImageConstants.JPG, ImageConstants.ENCODING_ASCII85, null); } /** * @return bytes */ public byte[] getBytes() { return bytes; } /** * @return used encoding format */ public String getFormat() { return format; } } /** * $Log$ */ src/main/java/org/freehep/graphicsio/pdf/PDFPageTree.java0000644000175000017500000000150711343262370022541 0ustar user03user03package org.freehep.graphicsio.pdf; import java.io.IOException; import java.util.Vector; /** * Implements the Page Tree Node (see Table 3.16). *

* * @author Mark Donszelmann * @version $Id: PDFPageTree.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFPageTree extends PDFPageBase { Vector pages = new Vector(); PDFPageTree(PDF pdf, PDFByteWriter writer, PDFObject object, PDFRef parent) throws IOException { super(pdf, writer, object, parent); entry("Type", pdf.name("Pages")); } public void addPage(String name) { pages.add(pdf.ref(name)); } void close() throws IOException { Object[] kids = new Object[pages.size()]; pages.copyInto(kids); entry("Kids", kids); entry("Count", kids.length); super.close(); } } src/main/java/org/freehep/graphicsio/pdf/PDFRef.java0000644000175000017500000000201411343262370021553 0ustar user03user03package org.freehep.graphicsio.pdf; /** * This class implements a numbered reference to a PDFObject. Internally the * class keeps track of the numbers. The user only sees its logical name. Only * generation 0 is used in this PDFWriter, since we do not allow for updates of * the PDF file. *

* * @author Mark Donszelmann * @version $Id: PDFRef.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFRef implements PDFConstants { private String name; private int objectNumber; private int generationNumber; PDFRef(String name, int objectNumber, int generationNumber) { this.name = name; this.objectNumber = objectNumber; this.generationNumber = generationNumber; } public String getName() { return name; } public int getObjectNumber() { return objectNumber; } public int getGenerationNumber() { return generationNumber; } public String toString() { return objectNumber + " " + generationNumber + " R"; } }src/main/java/org/freehep/graphicsio/pdf/PDFFontEmbedderType3.java0000644000175000017500000000601511343262370024327 0ustar user03user03// Copyright 2001-2005 freehep package org.freehep.graphicsio.pdf; import java.awt.Shape; import java.awt.font.FontRenderContext; import java.awt.font.GlyphMetrics; import java.awt.geom.Rectangle2D; import java.io.IOException; /** * @author Simon Fischer * @version $Id: PDFFontEmbedderType3.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFFontEmbedderType3 extends PDFFontEmbedder { public PDFFontEmbedderType3(FontRenderContext context, PDFWriter pdf, String reference, PDFRedundanceTracker tracker) { super(context, pdf, reference, tracker); } protected String getSubtype() { return "Type3"; } protected void addAdditionalEntries(PDFDictionary fontDict) throws IOException { Rectangle2D boundingBox = getFontBBox(); double llx = boundingBox.getX(); double lly = boundingBox.getY(); double urx = boundingBox.getX() + boundingBox.getWidth(); double ury = boundingBox.getY() + boundingBox.getHeight(); fontDict.entry("FontBBox", new double[] { llx, lly, urx, ury }); fontDict.entry("FontMatrix", new double[] { 1 / FONT_SIZE, 0, 0, 1 / FONT_SIZE, 0, 0 }); fontDict.entry("CharProcs", pdf.ref(getReference() + "CharProcs")); PDFDictionary resources = fontDict.openDictionary("Resources"); resources.entry("ProcSet", new Object[] { pdf.name("PDF") }); fontDict.close(resources); } protected void addAdditionalInitDicts() throws IOException { // CharProcs PDFDictionary charProcs = pdf.openDictionary(getReference() + "CharProcs"); // boolean undefined = false; for (int i = 0; i < 256; i++) { String charName = getEncodingTable().toName(i); if (charName != null) { charProcs.entry(charName, pdf .ref(createCharacterReference(charName))); } else { // undefined = true; } } // if (undefined) charProcs.entry(NOTDEF, pdf.ref(createCharacterReference(NOTDEF))); pdf.close(charProcs); } protected void writeGlyph(String characterName, Shape glyph, GlyphMetrics glyphMetrics) throws IOException { PDFStream glyphStream = pdf.openStream( createCharacterReference(characterName), new String[] { "Flate", "ASCII85" }); Rectangle2D bounds = glyphMetrics != null ? glyphMetrics.getBounds2D() : glyph.getBounds2D(); double advance = glyphMetrics != null ? glyphMetrics.getAdvance() : getUndefinedWidth(); glyphStream.glyph(advance, 0, bounds.getX(), bounds.getY(), bounds .getX() + bounds.getWidth(), bounds.getY() + bounds.getHeight()); boolean windingRule = glyphStream.drawPath(glyph); if (windingRule) { glyphStream.fillEvenOdd(); } else { glyphStream.fill(); } pdf.close(glyphStream); } } src/main/java/org/freehep/graphicsio/pdf/PDFPage.java0000644000175000017500000000472211343262370021723 0ustar user03user03package org.freehep.graphicsio.pdf; import java.io.IOException; import java.util.Calendar; /** * Implements the Page Object (see Table 3.17). Inheritable Page Attributes are * in PDFPageBase. *

* * @author Mark Donszelmann * @version $Id: PDFPage.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFPage extends PDFPageBase { PDFPage(PDF pdf, PDFByteWriter writer, PDFObject object, PDFRef parent) throws IOException { super(pdf, writer, object, parent); entry("Type", pdf.name("Page")); } public void setBleedBox(double x, double y, double w, double h) throws IOException { double[] rectangle = { x, y, w, h }; entry("BleedBox", rectangle); } public void setTrimBox(double x, double y, double w, double h) throws IOException { double[] rectangle = { x, y, w, h }; entry("TrimBox", rectangle); } public void setArtBox(double x, double y, double w, double h) throws IOException { double[] rectangle = { x, y, w, h }; entry("ArtBox", rectangle); } public void setContents(String content) throws IOException { entry("Contents", pdf.ref(content)); } public void setThumb(String thumb) throws IOException { entry("Thumb", pdf.ref(thumb)); } public void setB(String[] b) throws IOException { entry("B", pdf.ref(b)); } public void setDur(double dur) throws IOException { entry("Dur", dur); } public void setTrans(String trans) throws IOException { entry("Trans", pdf.ref(trans)); } public void setAnnots(String[] annots) throws IOException { entry("Annots", pdf.ref(annots)); } public void setAA(String aa) throws IOException { entry("AA", pdf.ref(aa)); } public void setPieceInfo(String pieceInfo) throws IOException { entry("PieceInfo", pdf.ref(pieceInfo)); } public void setLastModified(Calendar date) throws IOException { entry("LastModified", date); } public void setStructParents(int structParents) throws IOException { entry("StructParents", structParents); } public void setID(String id) throws IOException { entry("ID", id); } public void setPZ(double pz) throws IOException { entry("PZ", pz); } public void setSeparationInfo(String separationInfo) throws IOException { entry("SeparationInfo", pdf.ref(separationInfo)); } } src/main/java/org/freehep/graphicsio/pdf/PDFFontTable.java0000644000175000017500000001034411343262370022722 0ustar user03user03// Copyright 2001-2003, FreeHEP. package org.freehep.graphicsio.pdf; import java.awt.Font; import java.awt.font.FontRenderContext; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import java.util.Properties; import org.freehep.graphics2d.font.CharTable; import org.freehep.graphics2d.font.Lookup; import org.freehep.graphicsio.FontConstants; import org.freehep.graphicsio.font.FontIncluder; import org.freehep.graphicsio.font.FontTable; /** * A table to remember which fonts were used while writing a pdf document. * Entries to resource dictionaries and embedding of fonts can be done when the * drawing is finished by calling addAll(). * * @author Simon Fischer * @version $Id: PDFFontTable.java 9329 2006-11-14 22:29:00Z duns $ */ public class PDFFontTable extends FontTable { private int currentFontIndex = 1; private PDFWriter pdf; private PDFRedundanceTracker tracker; public PDFFontTable(PDFWriter pdf) { super(); this.pdf = pdf; this.tracker = new PDFRedundanceTracker(pdf); } /** Adds all fonts to a dictionary named "FontList". */ public int addFontDictionary() throws IOException { Collection fonts = getEntries(); if (fonts.size() > 0) { PDFDictionary fontList = pdf.openDictionary("FontList"); for (Iterator i = fonts.iterator(); i.hasNext();) { Entry e = (Entry) i.next(); fontList.entry(e.getReference(), pdf.ref(e.getReference())); } pdf.close(fontList); } return fonts.size(); } /** Embeds all not yet embedded fonts to the file. */ public void embedAll(FontRenderContext context, boolean embed, String embedAs) throws IOException { Collection col = getEntries(); Iterator i = col.iterator(); while (i.hasNext()) { Entry e = (Entry) i.next(); if (!e.isWritten()) { e.setWritten(true); FontIncluder fontIncluder = null; if (PDFFontIncluder.isStandardFont(e.getFont())) { embed = false; } if (embed) { if (embedAs.equals(FontConstants.EMBED_FONTS_TYPE3)) { fontIncluder = new PDFFontEmbedderType3(context, pdf, e .getReference(), tracker); } else if (embedAs.equals(FontConstants.EMBED_FONTS_TYPE1)) { fontIncluder = PDFFontEmbedderType1.create(context, pdf, e.getReference(), tracker); } else { System.out .println("PDFFontTable: invalid value for embedAs: " + embedAs); } } else { fontIncluder = new PDFFontIncluder(context, pdf, e .getReference(), tracker); } fontIncluder.includeFont(e.getFont(), e.getEncoding(), e .getReference()); } } tracker.writeAll(); } public CharTable getEncodingTable() { return Lookup.getInstance().getTable("PDFLatin"); } public void firstRequest(Entry e, boolean embed, String embedAs) { } private static final Properties replaceFonts = new Properties(); static { replaceFonts.setProperty("Dialog", "Helvetica"); replaceFonts.setProperty("DialogInput", "Courier"); replaceFonts.setProperty("Serif", "TimesRoman"); replaceFonts.setProperty("SansSerif", "Helvetica"); replaceFonts.setProperty("Monospaced", "Courier"); } protected Font substituteFont(Font font) { String fontName = replaceFonts.getProperty(font.getName(), null); if (fontName != null) { Font newFont = new Font(fontName, font.getSize(), font.getStyle()); font = newFont.deriveFont(font.getSize2D()); } return font; } /** * Creates the reference by numbering them. * * @return "F"+currentFontIndex */ protected String createFontReference(Font f) { return "F" + (currentFontIndex++); } } src/main/java/org/freehep/graphicsio/pdf/PDFPathConstructor.java0000644000175000017500000000205311343262370024204 0ustar user03user03// Copyright 2002 FreeHEP. package org.freehep.graphicsio.pdf; import java.io.IOException; import org.freehep.graphicsio.QuadToCubicPathConstructor; /** * @author Mark Donszelmann * @version $Id: PDFPathConstructor.java 8584 2006-08-10 23:06:37Z duns $ */ public class PDFPathConstructor extends QuadToCubicPathConstructor { private PDFStream stream; public PDFPathConstructor(PDFStream stream) { super(); this.stream = stream; } public void move(double x, double y) throws IOException { stream.move(x, y); super.move(x, y); } public void line(double x, double y) throws IOException { stream.line(x, y); super.line(x, y); } public void cubic(double x1, double y1, double x2, double y2, double x3, double y3) throws IOException { stream.cubic(x1, y1, x2, y2, x3, y3); super.cubic(x1, y1, x2, y2, x3, y3); } public void closePath(double x0, double y0) throws IOException { stream.closePath(); super.closePath(x0, y0); } } src/main/java/org/freehep/graphicsio/pdf/PDFStream.java0000644000175000017500000005720311343262370022304 0ustar user03user03// Copyright 2000-2007, FreeHEP package org.freehep.graphicsio.pdf; import java.awt.Color; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.image.RenderedImage; import java.io.IOException; import java.io.OutputStream; import org.freehep.graphicsio.ImageConstants; import org.freehep.util.io.ASCII85OutputStream; import org.freehep.util.io.ASCIIHexOutputStream; import org.freehep.util.io.CountedByteOutputStream; import org.freehep.util.io.FinishableOutputStream; import org.freehep.util.io.FlateOutputStream; /** * This class allows you to write/print into a PDFStream. Several methods are * available to specify the content of a page, image. This class performs some * error checking, while writing the stream. *

* The stream allows to write dictionary entries. The /Length entry is written * automatically, referencing an object which will also be written just after * the stream is closed and the length is calculated. *

* * @author Mark Donszelmann * @version $Id: PDFStream.java 12626 2007-06-08 22:23:13Z duns $ */ public class PDFStream extends PDFDictionary implements PDFConstants { private String name; private PDFObject object; private boolean dictionaryOpen; private OutputStream[] stream; private CountedByteOutputStream byteCountStream; private String[] encode; PDFStream(PDF pdf, PDFByteWriter writer, String name, PDFObject parent, String[] encode) throws IOException { super(pdf, writer); this.name = name; object = parent; if (object == null) System.err .println("PDFWriter: 'PDFStream' cannot have a null parent"); // first write the dictionary dictionaryOpen = true; this.encode = encode; } /** * Starts the stream, writes out the filters using the preset encoding, and * encodes the stream. */ private void startStream() throws IOException { startStream(encode); } /** * Starts the stream, writes out the filters using the given encoding, and * encodes the stream. */ private void startStream(String[] encode) throws IOException { if (dictionaryOpen) { PDFName[] filters = decodeFilters(encode); if (filters != null) entry("Filter", filters); super.close(); dictionaryOpen = false; out.printPlain("stream\n"); byteCountStream = new CountedByteOutputStream(out); stream = openFilters(byteCountStream, encode); } } private void write(int b) throws IOException { startStream(); stream[0].write(b); } private void write(byte[] b) throws IOException { for (int i = 0; i < b.length; i++) { write((int) b[i]); } } private static PDFName[] decodeFilters(String[] encode) { PDFName[] filters = null; if ((encode != null) && (encode.length != 0)) { filters = new PDFName[encode.length]; for (int i = 0; i < filters.length; i++) { filters[i] = new PDFName(encode[encode.length - i - 1] + "Decode"); } } return filters; } // open new stream using Standard Filters (see table 3.5) // stream[0] is the one to write to, the last one is s private static OutputStream[] openFilters(OutputStream s, String[] filters) { OutputStream[] os; if ((filters != null) && (filters.length != 0)) { os = new OutputStream[filters.length + 1]; os[os.length - 1] = s; for (int i = os.length - 2; i >= 0; i--) { if (filters[i].equals("ASCIIHex")) { os[i] = new ASCIIHexOutputStream(os[i + 1]); } else if (filters[i].equals("ASCII85")) { os[i] = new ASCII85OutputStream(os[i + 1]); } else if (filters[i].equals("Flate")) { os[i] = new FlateOutputStream(os[i + 1]); } else if (filters[i].equals("DCT")) { os[i] = os[i + 1]; } else { System.err.println("PDFWriter: unknown stream format: " + filters[i]); } } } else { os = new OutputStream[1]; os[0] = s; } return os; } // stream[0] is the first one to finish, the last one is not finished private static void closeFilters(OutputStream[] s) throws IOException { for (int i = 0; i < s.length - 1; i++) { s[i].flush(); if (s[i] instanceof FinishableOutputStream) { ((FinishableOutputStream) s[i]).finish(); } } s[s.length - 1].flush(); } private void write(String s) throws IOException { byte[] b = s.getBytes("ISO-8859-1"); for (int i = 0; i < b.length; i++) { write(b[i]); } } void close() throws IOException { closeFilters(stream); stream = null; out.printPlain("\nendstream"); out.println(); object.close(); if (gStates > 0) { System.err.println("PDFStream: unbalanced saves()/restores(), too many saves: "+gStates); } } String getName() { return name; } public int getLength() { return byteCountStream.getCount(); } public void print(String s) throws IOException { write(s); } public void println(String s) throws IOException { write(s); write(EOL); } public void comment(String comment) throws IOException { println("% " + comment); } // ========================================================================== // PDFStream Operators according to Table 4.1 // ========================================================================== // // Graphics State operators (see Table 4.7) // private int gStates = 0; public void save() throws IOException { println("q"); gStates++; } public void restore() throws IOException { if (gStates <= 0) { System.err.println("PDFStream: unbalanced saves()/restores(), too many restores"); } gStates--; println("Q"); } public void matrix(AffineTransform xform) throws IOException { matrix(xform.getScaleX(), xform.getShearY(), xform.getShearX(), xform .getScaleY(), xform.getTranslateX(), xform.getTranslateY()); } public void matrix(double m00, double m10, double m01, double m11, double m02, double m12) throws IOException { println(PDFUtil.fixedPrecision(m00) + " " + PDFUtil.fixedPrecision(m10) + " " + PDFUtil.fixedPrecision(m01) + " " + PDFUtil.fixedPrecision(m11) + " " + PDFUtil.fixedPrecision(m02) + " " + PDFUtil.fixedPrecision(m12) + " cm"); } public void width(double width) throws IOException { println(PDFUtil.fixedPrecision(width) + " w"); } public void cap(int capStyle) throws IOException { println(capStyle + " J"); } public void join(int joinStyle) throws IOException { println(joinStyle + " j"); } public void mitterLimit(double limit) throws IOException { println(PDFUtil.fixedPrecision(limit) + " M"); } public void dash(int[] dash, double phase) throws IOException { print("["); for (int i = 0; i < dash.length; i++) { print(" " + PDFUtil.fixedPrecision(dash[i])); } println("] " + PDFUtil.fixedPrecision(phase) + " d"); } public void dash(float[] dash, double phase) throws IOException { print("["); for (int i = 0; i < dash.length; i++) { print(" " + PDFUtil.fixedPrecision(dash[i])); } println("] " + PDFUtil.fixedPrecision(phase) + " d"); } public void flatness(double flatness) throws IOException { println(PDFUtil.fixedPrecision(flatness) + " i"); } public void state(PDFName stateDictionary) throws IOException { println(stateDictionary + " gs"); } // // Path Construction operators (see Table 4.9) // public void cubic(double x1, double y1, double x2, double y2, double x3, double y3) throws IOException { println(PDFUtil.fixedPrecision(x1) + " " + PDFUtil.fixedPrecision(y1) + " " + PDFUtil.fixedPrecision(x2) + " " + PDFUtil.fixedPrecision(y2) + " " + PDFUtil.fixedPrecision(x3) + " " + PDFUtil.fixedPrecision(y3) + " c"); } public void cubicV(double x2, double y2, double x3, double y3) throws IOException { println(PDFUtil.fixedPrecision(x2) + " " + PDFUtil.fixedPrecision(y2) + " " + PDFUtil.fixedPrecision(x3) + " " + PDFUtil.fixedPrecision(y3) + " v"); } public void cubicY(double x1, double y1, double x3, double y3) throws IOException { println(PDFUtil.fixedPrecision(x1) + " " + PDFUtil.fixedPrecision(y1) + " " + PDFUtil.fixedPrecision(x3) + " " + PDFUtil.fixedPrecision(y3) + " y"); } public void move(double x, double y) throws IOException { println(PDFUtil.fixedPrecision(x) + " " + PDFUtil.fixedPrecision(y) + " m"); } public void line(double x, double y) throws IOException { println(PDFUtil.fixedPrecision(x) + " " + PDFUtil.fixedPrecision(y) + " l"); } public void closePath() throws IOException { println("h"); } public void rectangle(double x, double y, double width, double height) throws IOException { println(PDFUtil.fixedPrecision(x) + " " + PDFUtil.fixedPrecision(y) + " " + PDFUtil.fixedPrecision(width) + " " + PDFUtil.fixedPrecision(height) + " re"); } // // Path Painting operators (see Table 4.10) // public void stroke() throws IOException { println("S"); } public void closeAndStroke() throws IOException { println("s"); } public void fill() throws IOException { println("f"); } public void fillEvenOdd() throws IOException { println("f*"); } public void fillAndStroke() throws IOException { println("B"); } public void fillEvenOddAndStroke() throws IOException { println("B*"); } public void closeFillAndStroke() throws IOException { println("b"); } public void closeFillEvenOddAndStroke() throws IOException { println("b*"); } public void endPath() throws IOException { println("n"); } // // Clipping Path operators (see Table 4.11) // public void clip() throws IOException { println("W"); } public void clipEvenOdd() throws IOException { println("W*"); } // // Text Object operators (see Table 5.4) // private boolean textOpen = false; public void beginText() throws IOException { if (textOpen) System.err.println("PDFStream: nested beginText() not allowed."); println("BT"); textOpen = true; } public void endText() throws IOException { if (!textOpen) System.err .println("PDFStream: unbalanced use of beginText()/endText()."); println("ET"); textOpen = false; } // // Text State operators (see Table 5.2) // public void charSpace(double charSpace) throws IOException { println(PDFUtil.fixedPrecision(charSpace) + " Tc"); } public void wordSpace(double wordSpace) throws IOException { println(PDFUtil.fixedPrecision(wordSpace) + " Tw"); } public void scale(double scale) throws IOException { println(PDFUtil.fixedPrecision(scale) + " Tz"); } public void leading(double leading) throws IOException { println(PDFUtil.fixedPrecision(leading) + " TL"); } private boolean fontWasSet = false; public void font(PDFName fontName, double size) throws IOException { println(fontName + " " + PDFUtil.fixedPrecision(size) + " Tf"); fontWasSet = true; } public void rendering(int mode) throws IOException { println(mode + " Tr"); } public void rise(double rise) throws IOException { println(PDFUtil.fixedPrecision(rise) + " Ts"); } // // Text Positioning operators (see Table 5.5) // public void text(double x, double y) throws IOException { println(PDFUtil.fixedPrecision(x) + " " + PDFUtil.fixedPrecision(y) + " Td"); } public void textLeading(double x, double y) throws IOException { println(PDFUtil.fixedPrecision(x) + " " + PDFUtil.fixedPrecision(y) + " TD"); } public void textMatrix(double a, double b, double c, double d, double e, double f) throws IOException { println(PDFUtil.fixedPrecision(a) + " " + PDFUtil.fixedPrecision(b) + " " + PDFUtil.fixedPrecision(c) + " " + PDFUtil.fixedPrecision(d) + " " + PDFUtil.fixedPrecision(e) + " " + PDFUtil.fixedPrecision(f) + " Tm"); } public void textLine() throws IOException { println("T*"); } // // Text Showing operators (see Table 5.6) // public void show(String text) throws IOException { if (!fontWasSet) System.err .println("PDFStream: cannot use Text Showing operator before font is set."); if (!textOpen) System.err .println("PDFStream: Text Showing operator only allowed inside Text section."); println("(" + PDFUtil.escape(text) + ") Tj"); } public void showLine(String text) throws IOException { if (!fontWasSet) System.err .println("PDFStream: cannot use Text Showing operator before font is set."); if (!textOpen) System.err .println("PDFStream: Text Showing operator only allowed inside Text section."); println("(" + PDFUtil.escape(text) + ") '"); } public void showLine(double wordSpace, double charSpace, String text) throws IOException { if (!fontWasSet) System.err .println("PDFStream: cannot use Text Showing operator before font is set."); if (!textOpen) System.err .println("PDFStream: Text Showing operator only allowed inside Text section."); println(PDFUtil.fixedPrecision(wordSpace) + " " + PDFUtil.fixedPrecision(charSpace) + " (" + PDFUtil.escape(text) + ") \""); } public void show(Object[] array) throws IOException { print("["); for (int i = 0; i < array.length; i++) { Object object = array[i]; if (object instanceof String) { print(" (" + PDFUtil.escape(object.toString()) + ")"); } else if (object instanceof Integer) { print(" " + ((Integer) object).intValue()); } else if (object instanceof Double) { print(" " + ((Double) object).doubleValue()); } else { System.err .println("PDFStream: input array of operator TJ may only contain objects of type 'String', 'Integer' or 'Double'"); } } println("] TJ"); } // // Type 3 Font operators (see Table 5.10) // public void glyph(double wx, double wy) throws IOException { println(PDFUtil.fixedPrecision(wx) + " " + PDFUtil.fixedPrecision(wy) + " d0"); } public void glyph(double wx, double wy, double llx, double lly, double urx, double ury) throws IOException { println(PDFUtil.fixedPrecision(wx) + " " + PDFUtil.fixedPrecision(wy) + " " + PDFUtil.fixedPrecision(llx) + " " + PDFUtil.fixedPrecision(lly) + " " + PDFUtil.fixedPrecision(urx) + " " + PDFUtil.fixedPrecision(ury) + " d1"); } // // Color operators (see Table 4.21) // public void colorSpace(PDFName colorSpace) throws IOException { println(colorSpace + " cs"); } public void colorSpaceStroke(PDFName colorSpace) throws IOException { println(colorSpace + " CS"); } public void colorSpace(double[] color) throws IOException { for (int i = 0; i < color.length; i++) { print(" " + color[i]); } println(" scn"); } public void colorSpaceStroke(double[] color) throws IOException { for (int i = 0; i < color.length; i++) { print(" " + color[i]); } println(" SCN"); } public void colorSpace(double[] color, PDFName name) throws IOException { if (color != null) { for (int i = 0; i < color.length; i++) { print(PDFUtil.fixedPrecision(color[i]) + " "); } } println(name + " scn"); } public void colorSpaceStroke(double[] color, PDFName name) throws IOException { if (color != null) { for (int i = 0; i < color.length; i++) { print(PDFUtil.fixedPrecision(color[i]) + " "); } } println(name + " SCN"); } public void colorSpace(double g) throws IOException { println(PDFUtil.fixedPrecision(g) + " g"); } public void colorSpaceStroke(double g) throws IOException { println(PDFUtil.fixedPrecision(g) + " G"); } public void colorSpace(double r, double g, double b) throws IOException { println(PDFUtil.fixedPrecision(r) + " " + PDFUtil.fixedPrecision(g) + " " + PDFUtil.fixedPrecision(b) + " rg"); } public void colorSpaceStroke(double r, double g, double b) throws IOException { println(PDFUtil.fixedPrecision(r) + " " + PDFUtil.fixedPrecision(g) + " " + PDFUtil.fixedPrecision(b) + " RG"); } public void colorSpace(double c, double m, double y, double k) throws IOException { println(PDFUtil.fixedPrecision(c) + " " + PDFUtil.fixedPrecision(m) + " " + PDFUtil.fixedPrecision(y) + " " + PDFUtil.fixedPrecision(k) + " k"); } public void colorSpaceStroke(double c, double m, double y, double k) throws IOException { println(PDFUtil.fixedPrecision(c) + " " + PDFUtil.fixedPrecision(m) + " " + PDFUtil.fixedPrecision(y) + " " + PDFUtil.fixedPrecision(k) + " K"); } // // Shading Pattern operator (see Table 4.24) // public void shade(PDFName name) throws IOException { println(name + " sh"); } /** * returns the decode-format for an image -format * * @param encode {@link ImageConstants#ZLIB} or {@link ImageConstants#JPG} * @return {@link #decodeFilters(String[])} */ private PDFName[] getFilterName(String encode) { if (ImageConstants.ZLIB.equals(encode)) { return decodeFilters(new String[] { ImageConstants.ENCODING_FLATE, ImageConstants.ENCODING_ASCII85}); } if (ImageConstants.JPG.equals(encode)) { return decodeFilters(new String[] { ImageConstants.ENCODING_DCT, ImageConstants.ENCODING_ASCII85}); } throw new IllegalArgumentException("unknown image encoding " + encode + " for PDFStream"); } /** * Image convenience function (see Table 4.35). Ouputs the data of the image * using "DeviceRGB" colorspace, and the requested encodings * * @param image Image to write * @param bkg Background color, null for transparent image * @param encode {@link org.freehep.graphicsio.ImageConstants#ZLIB} or {@link org.freehep.graphicsio.ImageConstants#JPG} * @throws java.io.IOException thrown by ImageBytes */ public void image(RenderedImage image, Color bkg, String encode) throws IOException { ImageBytes bytes = new ImageBytes(image, bkg, encode, ImageConstants.COLOR_MODEL_RGB); entry("Width", image.getWidth()); entry("Height", image.getHeight()); entry("ColorSpace", pdf.name("DeviceRGB")); entry("BitsPerComponent", 8); entry("Filter", getFilterName(bytes.getFormat())); write(bytes.getBytes()); } public void imageMask(RenderedImage image, String encode) throws IOException { ImageBytes bytes = new ImageBytes(image, null, encode, ImageConstants.COLOR_MODEL_A); entry("Width", image.getWidth()); entry("Height", image.getHeight()); entry("BitsPerComponent", 8); entry("ColorSpace", pdf.name("DeviceGray")); entry("Filter", getFilterName(bytes.getFormat())); write(bytes.getBytes()); } /** * Inline Image convenience function (see Table 4.39 and 4.40). Ouputs the * data of the image using "DeviceRGB" colorspace, and the requested * encoding. * @param image Image to write * @param bkg Background color, null for transparent image * @param encode {@link org.freehep.graphicsio.ImageConstants#ZLIB} or {@link org.freehep.graphicsio.ImageConstants#JPG} * @throws java.io.IOException thrown by ImageBytes */ public void inlineImage(RenderedImage image, Color bkg, String encode) throws IOException { ImageBytes bytes = new ImageBytes(image, bkg, ImageConstants.JPG, ImageConstants.COLOR_MODEL_RGB); println("BI"); imageInfo("Width", image.getWidth()); imageInfo("Height", image.getHeight()); imageInfo("ColorSpace", pdf.name("DeviceRGB")); imageInfo("BitsPerComponent", 8); imageInfo("Filter", getFilterName(bytes.getFormat())); print("ID\n"); write(bytes.getBytes()); println("\nEI"); } // // In-line Image operators (see Table 4.38) // private void imageInfo(String key, int number) throws IOException { println("/" + key + " " + number); } private void imageInfo(String key, PDFName name) throws IOException { println("/" + key + " " + name); } private void imageInfo(String key, Object[] array) throws IOException { print("/" + key + " ["); for (int i = 0; i < array.length; i++) { print(" " + array[i]); } println("]"); } /** * Draws the points of the shape using path construction * operators. The path is neither stroked nor filled. * * @return true if even-odd winding rule should be used, false if non-zero * winding rule should be used. */ public boolean drawPath(Shape s) throws IOException { PDFPathConstructor path = new PDFPathConstructor(this); return path.addPath(s); } // // XObject operators (see Table 4.34) // public void xObject(PDFName name) throws IOException { println(name + " Do"); } // // Marked Content operators (see Table 8.5) // // FIXME: missing all // // Compatibility operators (see Table 3.19) // private boolean compatibilityOpen = false; public void beginCompatibility() throws IOException { if (compatibilityOpen) System.err .println("PDFStream: nested use of Compatibility sections not allowed."); println("BX"); compatibilityOpen = true; } public void endCompatibility() throws IOException { if (!compatibilityOpen) System.err .println("PDFStream: unbalanced use of begin/endCompatibilty()."); println("EX"); compatibilityOpen = false; } } src/site/0000700000175000017500000000000011343262370011624 5ustar user03user03src/site/apt/0000700000175000017500000000000011343262370012410 5ustar user03user03src/site/site.xml0000644000175000017500000000173711343262370013334 0ustar user03user03 FreeHEP GraphicsIO PDF http://java.freehep.org/mvn/freehep-graphicsio-pdf FreeHEP http://java.freehep.org/images/sm-freehep.gif http://java.freehep.org/

TestPDFFontEmbedding.java0000644000175000017500000001130111343262371014642 0ustar user03user03// Copyright 2005, FreeHEP. package org.freehep.graphicsio.pdf.test; import java.awt.Rectangle; import java.awt.Font; import java.awt.font.FontRenderContext; import java.io.*; import java.util.Calendar; import org.freehep.graphics2d.font.CharTable; import org.freehep.graphics2d.font.Lookup; import org.freehep.graphicsio.font.FontEmbedder; import org.freehep.graphicsio.pdf.PDFFontEmbedderType1; import org.freehep.graphicsio.pdf.PDFFontEmbedderType3; import org.freehep.graphicsio.pdf.PDFWriter; import org.freehep.graphicsio.pdf.PDFDocInfo; import org.freehep.graphicsio.pdf.PDFCatalog; import org.freehep.graphicsio.pdf.PDFViewerPreferences; import org.freehep.graphicsio.pdf.PDFDictionary; import org.freehep.graphicsio.pdf.PDFPageTree; import org.freehep.graphicsio.pdf.PDFPage; import org.freehep.graphicsio.pdf.PDFStream; import org.freehep.graphicsio.pdf.PDFRedundanceTracker; public class TestPDFFontEmbedding { public static void main(String[] argv) { try { PDFWriter pdf = new PDFWriter(new FileOutputStream("fonttest.pdf")); pdf.comment("file generated by TestFontEmbedding, Freehep lib"); // info PDFDocInfo info = pdf.openDocInfo("DocInfo"); info.setTitle("Font Embedding Test"); info.setAuthor("Simon Fischer"); info.setSubject("Test File of the Font Embedding of the FreeHEP library"); info.setKeywords("PDFWriter; FreeHEP"); info.setCreator(TestPDFFontEmbedding.class.getName()); info.setCreationDate(Calendar.getInstance()); pdf.close(info); // catalog PDFCatalog catalog = pdf.openCatalog("Catalog", "RootPage"); catalog.setPageMode("UseOutlines"); catalog.setViewerPreferences("Preferences"); catalog.setOpenAction(new Object[] { pdf.ref("FontPage"), pdf.name("Fit")}); pdf.close(catalog); // preferences PDFViewerPreferences prefs = pdf.openViewerPreferences("Preferences"); prefs.setFitWindow(true); prefs.setCenterWindow(false); pdf.close(prefs); // pages PDFPageTree pages = pdf.openPageTree("RootPage", null); pages.addPage("FontPage"); pages.setMediaBox(0, 0, 612, 792); pages.setResources("Resources"); pdf.close(pages); // page PDFPage fontPage = pdf.openPage("FontPage", "RootPage"); fontPage.setContents("FontPageContent"); pdf.close(fontPage); // first page content PDFStream pageStream = pdf.openStream("FontPageContent", new String[] { "Flate", "ASCIIHex" }); pageStream.move(100,100); pageStream.line(200,200); pageStream.stroke(); pageStream.beginText(); pageStream.font(pdf.name("F1"), 12); pageStream.text(100, 200); pageStream.show("ABC abc!"); pageStream.endText(); CharTable table = Lookup.getInstance().getTable("PDFLatin"); String str = ""; double y = 500; for (int i=1; i<256; i++) { String name = table.toName(i); if (name != null) str += table.toUnicode(name); else str += "#"; if ((str.length() % 32 == 31) || (i == 255)) { pageStream.beginText(); pageStream.font(pdf.name("F1"), 12); pageStream.text(100, y); pageStream.show(str); pageStream.endText(); System.out.println(str); str = ""; y -= 20; } } pdf.close(pageStream); // resources PDFDictionary resources = pdf.openDictionary("Resources"); resources.entry("ProcSet", pdf.ref("OurPageProcSet")); PDFDictionary fontList = resources.openDictionary("Font"); fontList.entry("F1", pdf.ref("MyFont")); resources.close(fontList); pdf.close(resources); pdf.object("OurPageProcSet", new Object[] { pdf.name("PDF") }); PDFRedundanceTracker tracker = new PDFRedundanceTracker(pdf); // font embedding switch (3) { case 1: PDFDictionary fontDict = pdf.openDictionary("MyFont"); fontDict.entry("Type", pdf.name("Font")); fontDict.entry("Subtype", pdf.name("Type1")); fontDict.entry("Name", pdf.name("F1")); fontDict.entry("BaseFont", pdf.name("Helvetica")); pdf.close(fontDict); break; case 2: Font font = new Font("Monotype Corsiva", Font.PLAIN, 1000); FontRenderContext context = new FontRenderContext(null, true, true); FontEmbedder fe = new PDFFontEmbedderType3(context, pdf, "MyFont", tracker); fe.includeFont(font, Lookup.getInstance().getTable("PDFLatin"), "F1"); break; case 3: font = new Font("Impact", Font.PLAIN, 1000); context = new FontRenderContext(null, true, true); fe = PDFFontEmbedderType1.create(context, pdf, "MyFont", tracker); fe.includeFont(font, Lookup.getInstance().getTable("PDFLatin"), "F1"); break; } tracker.writeAll(); pdf.close(); System.exit(0); } catch (Exception e) { e.printStackTrace(); } } } TestPDFMultipage.java0000644000175000017500000000257011343262371014074 0ustar user03user03package org.freehep.graphicsio.pdf.test; import org.freehep.graphics2d.*; import java.awt.*; import java.io.*; import org.freehep.graphicsio.pdf.PDFGraphics2D; public class TestPDFMultipage { public static void main(String[] argv) throws Exception { PDFGraphics2D graphics = new PDFGraphics2D(new FileOutputStream("multi.pdf"), new Dimension(400, 600)); graphics.setMultiPage(true); Font font = new Font("Serif", Font.PLAIN, 12); graphics.startExport(); graphics.setHeader(font, new TagString("TEST DOCUMENT"), null, new TagString("Multipage"), 1); graphics.setFooter(font, null, new TagString("- %P% -"), null, -1); graphics.openPage(new Dimension(200, 400), "Page 1"); graphics.setColor(Color.black); graphics.setFont(font); graphics.drawRect(50, 100, 150, 20); graphics.drawString("Page 1", 60., 115); graphics.closePage(); graphics.openPage(new Dimension(200, 400), "Page 2"); graphics.setColor(Color.black); graphics.setFont(new Font("SansSerif", Font.PLAIN, 12)); graphics.drawRect(50, 100, 150, 20); graphics.drawString("Page 2", 60., 115); graphics.drawString(new TagString("This is Page 2 of 2"), 40.,150); graphics.closePage(); graphics.endExport(); System.exit(0); } }