Java/2D Graphics GUI/PDF PostScript

Материал из Java эксперт
Версия от 09:56, 1 июня 2010; Admin (обсуждение | вклад) (1 версия)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Output to PDF file

<source lang="java"> /*

* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java 
* language and environment is gratefully acknowledged.
* 
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/

import java.io.*; import java.text.*; import java.util.*;

/** A simple text test of SPDF package

*/

public class PDFDemo {

 public static void main(String[] argv) throws IOException {
   PrintWriter pout;
   if (argv.length == 0) {
     pout = new PrintWriter(System.out);
   } else {
     if (new File(argv[0]).exists()) {
       throw new IOException(
       "Output file " + argv[0] + " already exists");
     }
     pout = new PrintWriter(new FileWriter(argv[0]));
   }
   PDF p = new PDF(pout);
   Page p1 = new Page(p);
   p1.add(new MoveTo(p, 100, 600));
   p1.add(new Text(p, "Hello world, live on the web."));
   p1.add(new Text(p, "Hello world, line 2 on the web."));
   p.add(p1);
   p.setAuthor("Ian F. Darwin");
   p.writePDF();
 }

} /** The main class for the Darwin Open Systems

* {Simple,Stupid,Simplistic} PDF API.
* PDF is Adobe"s Portable Document Format, and is probably a trademark
* of Adobe Systems Inc, Mountain View, California.
* The Adobe PDF Specification which they publish grants everyone
* permission to write code to generate and/or process PDF files.
* A PDF Object represents one PDF file.
* @author Ian F. Darwin, http://www.darwinsys.ru/
* @version $Id: PDF.java,v 1.6 2004/02/09 03:34:02 ian Exp $
*/

class PDF {

 /** The output writer */
 protected PrintWriter out;
 /** The list of pages */
 protected ArrayList pages;
 /** The list of object xrefs */
 protected ArrayList xrefs;
 /** The root object */
 PDFObject rootObj = new RootObject(this);
 /** The Info object */
 InfoObject infoObj = new InfoObject(this);
 /** The outlines (outline font) object */
 OutlinesObject outlinesObj = new OutlinesObject(this);
 /** The Pages object */
 PagesObject pagesObj = new PagesObject(this);
 /** The Font Dictionary */
 FontDict fontDict = new FontDict(this);
 /** The object number of the current object */
 protected int currObj = 1;
 /** A flag to avoid writing twice */
 protected boolean startedWriting = false;
 /** A magic number that identifies the output as a PDF file */
 protected final static String PDF_MAGIC = "%PDF-1.0";
 /** Constructor */
 public PDF(PrintWriter o) {
   out = o;
   pages = new ArrayList();
   xrefs = new ArrayList();
 }
 public void add(Page p) {
   pages.add(p);
 }
 public void insertPage(int where, Page p) {
   pages.add(where, p);
 }
 // OUTPUT METHODS -- we provide our own print/println, so we
 // can keep track of file offsets (it was either that, or kludgily
 // use a RandomAccessFile and the getFilePointer() method).
 long offset = 0;
 /** Print a String */
 protected void print(String s){
   out.print(s);
   offset += s.length();
 }
 /** Println a String */
 protected void println(String s) {
   print(s);
   print("\n");
 }
 /** Print an Object */
 protected void print(Object o) {
   print(o.toString());
 }
 /** Println an Object */
 protected void println(Object o) {
   println(o.toString());
 }
 /** Print an int */
 protected void print(int i) {
   String s = Integer.toString(i);
   print(s);
 }
 /** Println an int */
 protected void println(int i) {
   String s = Integer.toString(i);
   print(s);
 }
 /** Println with no args */
 protected void println() {
   print("\n");
 }
 // END OF OUTPUT METHODS 
 /** Add an entry into the offset table */
 protected void addXref() {
   xrefs.add(new Long(offset));
 }
 /** Write the entire output */
 public void writePDF() {
   if (startedWriting) {
     throw new IllegalStateException(
       "writePDF() can only be called once.");
   }
   startedWriting = true;
   writePDFHeader();
   writePDFbody();
   writeXrefs();
   writePDFTrailer();
   out.flush();
   out.close();
 }
 protected void writePDFHeader() {
   println(PDF_MAGIC);
   rootObj.print();  // 1
   infoObj.print();  // 2
   outlinesObj.print(); // 3
   pagesObj.print();  // 4
 }
 protected void writePDFbody() {
   for (int i=0; i<pages.size(); i++) {
      ((Page)pages.get(i)).print();    // 5, 6
   }
   addXref();
   print(currObj++); println(" 0 obj");
   println("[/PDF /Text]");
   println("endobj");
   fontDict.print();    // 8
 }
 DecimalFormat nf10 = new DecimalFormat("0000000000");
 DecimalFormat nf5 = new DecimalFormat("00000");
 /** Write one Xref, in the format 0000000000 65535 f */
 protected void printXref(long n, int where, char inUse) {
   println(nf10.format(n) + " " +  nf5.format(where) + " " + inUse);
 }
 long xrefStart;
 /** Write all the xrefs, using the format above */
 protected void writeXrefs() {
   xrefStart = offset;
   println("xref");
   print(0);
   print(" ");
   print(xrefs.size() + 1);
   println();
   // "fake" entry at 0, always 0, -1, f(free).
   printXref(0, 65535, "f");
   // Remaining xref entries are for real objects.
   for (int i=0; i<xrefs.size(); i++) {
     Long lo = (Long)xrefs.get(i);
     long l = lo.longValue();
     printXref(l, 0, "n");
   }
 }
 protected void writePDFTrailer() {
   println("trailer");
   println("<<");
   println("/Size " + (xrefs.size() + 1));
   println("/Root 1 0 R");
   println("/Info 2 0 R");
   println(">>");
   println("% startxref");
   println("% " + xrefStart);
   println("%%EOF");
 }
 class RootObject extends PDFDict {
   protected RootObject(PDF m) {
     super(m);
     dict.put("Type", "/Catalog");
     dict.put("Outlines", "3 0 R");
     dict.put("Pages", "4 0 R");
   }
 }
 class InfoObject extends PDFDict {
   protected InfoObject(PDF m) {
     super(m);
     dict.put("Title", "(Sample PDF by SPDF)");
     dict.put("Creator", "(Darwin Open Systems SPDF Software)");
     dict.put("Created", "(D:20000516010203)");
   }
 }
 
 public void setAuthor(String au) {
   infoObj.dict.put("Author", "(" + au + ")");
 }
 class OutlinesObject extends PDFDict {
   protected OutlinesObject(PDF m) {
     super(m);
     dict.put("Type", "/Outlines");
     dict.put("Count", "0");
   }
 }
 class PagesObject extends PDFDict {
   protected PagesObject(PDF m) {
     super(m);
     dict.put("Type", "/Pages");
     dict.put("Count", "1");
     dict.put("Kids", "[5 0 R]");
   }
 }
 class FontDict extends PDFDict {
   protected FontDict(PDF m) {
     super(m);
     dict.put("Type", "/Font");
     dict.put("Subtype", "/Type1");
     dict.put("Name", "/F1");
     dict.put("BaseFont", "/Helvetica");
     dict.put("Encoding", "/MacRomanEncoding");
   }
 }

} /** A PDFDict ias a PDFObject that is all, or mostly, a Dictionary.

* @author Ian Darwin, http://www.darwinsys.ru/
*/

abstract class PDFDict extends PDFObject {

 /** The Dictionary is a HashTable. Put the keys without a 
  * leading slash, since they always have it. Values can
  * be /names, (strings), or whatever.
  */
 protected Hashtable dict;
 PDFDict(PDF m) {
   super(m);
   dict = new Hashtable();
 }
 /** Write the object to the Output Writer. The default implementation
  * of this method in PDFDict just calls startObj, printDict, and endObj.
  */
 protected void print() {
   startObj();
   printDict();
   endObj();
 }
 protected void startObj() {
   // Record the starting position of this Obj in the xref table
   master.addXref();
   // Print out e.g., "42 0 obj"
   master.print(master.currObj++);
    master.print(" 0 obj");
   master.println();
 }
 protected void endObj() {
   master.println("endobj");
 }
 protected void printDict() {
   master.println("<<");
   Enumeration e = dict.keys();
   while (e.hasMoreElements()) {
     master.print("\t/");
     String key = (String)e.nextElement();
     master.print(key);
     master.print(" ");
     master.print(dict.get(key));
     master.println();
   }
   master.println(">>");
 }

} /** Represent one Text object in a PDF file. */ class Text extends PDFObject {

 protected int x, y;
 protected String text;
 public Text(PDF m, String s) {
   super(m);
   text = s;
 }
 public void print() {
   throw new IllegalStateException("print() called on a Text obj");
 }
 public void print(StringBuffer sb) {
   sb.append("0 -18 Td (");
   sb.append(text);  // TODO must substitute escaped characters
   sb.append(") Tj\n");
 }

} /** A PDFObject represents one node in the tree of a PDF file.

* @author Ian Darwin, http://www.darwinsys.ru/
*/

abstract class PDFObject extends java.lang.Object {

 /** The containing PDF file */
 protected PDF master;
 PDFObject(PDF m) {
   master = m;
 }
 /** Write the object to the Output Writer */
 protected abstract void print();
 protected void startObj() {
   // Record the starting position of this Obj in the xref table
   master.addXref();
   // Print out e.g., "42 0 obj"
   master.print(master.currObj++);
    master.print(" 0 obj");
   master.println();
 }
 protected void endObj() {
   master.println("endobj");
 }

} /** Represent one Move object ("moveto") in a PDF file. */ class MoveTo extends PDFObject {

 protected int x, y;
 public MoveTo(PDF m, int x, int y) {
   super(m);
   this.x = x;
   this.y = y;
 }
 public void print() {
   throw new IllegalStateException("print() called on a Text obj");
 }
 public void print(StringBuffer sb) {
   sb.append(x);
   sb.append(" ");
   sb.append(y);
   sb.append(" Td\n");
 }

} /** Represent one Page of a PDF file. */ class Page extends PDFDict {

 protected ArrayList objects = new ArrayList();
 public Page(PDF m) {
   super(m);
   dict.put("Type", "/Page");
   dict.put("Parent", "4 0 R");
   dict.put("Resources", "<< /Font << /F1 8 0 R >> /ProcSet 7 0 R >>");
   dict.put("MediaBox", "[0 0 612 792]");
   dict.put("Contents", "6 0 R");
   
 }
 public void add(PDFObject po) {
   objects.add(po);
 }
 /** Print all the objects on the page.
  * For now, just print all the Text objects, as one Stream.
  */
 protected void print() {
   // Print the Page object
   super.print();
   // Now do the Text objects as one PDF obj
   master.addXref();
   startObj();
   StringBuffer sb = new StringBuffer();
   sb.append("BT\n");
   sb.append("/F1 12 Tf\n");
   for (int i=0; i<objects.size(); i++) {
     PDFObject po = (PDFObject)objects.get(i);
     if (po instanceof Text)
       ((Text)po).print(sb);
     else if (po instanceof MoveTo)
       ((MoveTo)po).print(sb);
     // else if (po instanceof Font)
     //  ...
     else
       System.err.println("PDFPage: ignoring " + po);
   }
   sb.append("ET\n");
   master.println("<< /Length " + sb.length() + " >>");
   master.println("stream");
   master.print(sb);
   master.println("endstream");
   endObj();
 }

}


      </source>   



Text to Postscript

<source lang="java"> /*

* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java 
* language and environment is gratefully acknowledged.
* 
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/

import java.io.*; /** Text to PS */ public class PSFormatter {

 /** The current input source */
 protected BufferedReader br;
 /** The current page number */
 protected int pageNum;
 /** The current X and Y on the page */
 protected int curX, curY;
 /** The current line number on page */
 protected int lineNum;
 /** The current tab setting */
 protected int tabPos = 0;
 public static final int INCH = 72;  // PS constant: 72 pts/inch
 // Page parameters
 /** The left margin indent */
 protected int leftMargin = 50;
 /** The top of page indent */
 protected int topMargin = 750;
 /** The bottom of page indent */
 protected int botMargin = 50;
 // FORMATTING PARAMETERS
 protected int points = 12;
 protected int leading = 14;
 public static void main(String[] av) throws IOException {
   if (av.length == 0) 
     new PSFormatter(
       new InputStreamReader(System.in)).process();
   else for (int i = 0; i < av.length; i++) {
     new PSFormatter(av[i]).process();
   }
 }
 public PSFormatter(String fileName) throws IOException {
   br = new BufferedReader(new FileReader(fileName));
 }
 public PSFormatter(Reader in) throws IOException {
   if (in instanceof BufferedReader)
     br = (BufferedReader)in;
   else
     br = new BufferedReader(in);
 }
 /** Main processing of the current input source. */
 protected void process() throws IOException {
   String line;
   prologue();      // emit PostScript prologue, once.
   startPage();    // emit top-of-page (ending previous)
   while ((line = br.readLine()) != null) {
     if (line.startsWith("\f") || line.trim().equals(".bp")) {
       startPage();
       continue;
     }
     doLine(line);
   }
   // finish last page, if not already done.
   if (lineNum != 0)
     println("showpage");
 }
 /** Handle start of page details. */
 protected void startPage() {
   if (pageNum++ > 0)
     println("showpage");
   lineNum = 0;
   moveTo(leftMargin, topMargin);
 }
 /** Process one line from the current input */
 protected void doLine(String line) {
   tabPos = 0;
   // count leading (not imbedded) tabs.
   for (int i=0; i<line.length(); i++) {
     if (line.charAt(i)=="\t")
       tabPos++;
     else
       break;
   }
   String l = line.trim(); // removes spaces AND tabs
   if (l.length() == 0) {
     ++lineNum;
     return;
   }
   moveTo(leftMargin + (tabPos * INCH),
     topMargin-(lineNum++ * leading));
   println("(" + toPSString(l)+ ") show");
   // If we just hit the bottom, start a new page
   if (curY <= botMargin)
     startPage();
 }
 /** Overly-simplistic conversion to PS, e.g., breaks on "foo\)bar" */
 protected String toPSString(String o) {
   StringBuffer sb = new StringBuffer();
   for (int i=0; i<o.length(); i++) {
     char c = o.charAt(i);
     switch(c) {
       case "(":  sb.append("\\("); break;
       case ")":  sb.append("\\)"); break;
       default:  sb.append(c); break;
     }
   }
   return sb.toString();
 }
 protected void println(String s) {
   System.out.println(s);
 }
 protected void moveTo(int x, int y) {
   curX = x;
   curY = y;
   println(x + " " + y + " " + "moveto");
 }
 void prologue() {
   println("%!PS-Adobe");
   println("/Courier findfont " + points + " scalefont setfont ");
 }

}


      </source>