--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2003 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+package org.apache.fop.render.ps;
+
+/**
+ * This class defines constants with Strings for the DSC specification.
+ *
+ * @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
+ * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
+ * @version $Id$
+ */
+public class DSCConstants {
+
+ // ----==== General Header Comments ====----
+
+ /** Lead-in for a DSC-conformant PostScript file */
+ public static final String PS_ADOBE_30 = "%!PS-Adobe-3.0";
+
+ /** Bounding box for the document */
+ public static final String BBOX = "BoundingBox";
+ /** Copyright information associated with the document or resource */
+ public static final String COPYRIGHT = "Copyright";
+ /** Creator of the document */
+ public static final String CREATOR = "Creator";
+ /** Date and time when the document was created */
+ public static final String CREATION_DATE = "CreationDate";
+ /** Type of data */
+ public static final String DOCUMENT_DATA = "BoundingBox";
+ /** Use for inidicating an emulator being invoked in the document */
+ public static final String EMULATION = "Emulation";
+ /** Explicit end of comments */
+ public static final String END_COMMENTS = "EndComments";
+ /** Required PostScript Level 1 extension for this document */
+ public static final String EXTENSIONS = "Extensions";
+ /** Indicates who is this document printed for */
+ public static final String FOR = "For";
+ /** Indicates the PostScript language level used in the document */
+ public static final String LANGUAGE_LEVEL = "LanguageLevel";
+ /** Indicates the orientation of the document */
+ public static final String ORIENTATION = "Orientation";
+ /** Number of pages in the document */
+ public static final String PAGES = "Pages";
+ /** Indicates the order of the pages */
+ public static final String PAGE_ORDER = "PageOrder";
+ /** Indicates how the document should be routed back to its owner */
+ public static final String ROUTING = "Routing";
+ /** Title of the document */
+ public static final String TITLE = "Title";
+ /** Version of the document */
+ public static final String VERSION = "Version";
+
+ // ----==== General Body Comments ====----
+
+ /** Indicates a continued line */
+ public static final String NEXT_LINE = "+ ";
+
+ //Skipping BeginBinary/EndBinary. They are deprecated.
+
+ /** Indicates the start of a data section*/
+ public static final String BEGIN_DATA = "BeginData";
+ /** Indicates the end of a data section*/
+ public static final String END_DATA = "EndData";
+
+ /** Indicates the start of the defaults section */
+ public static final String BEGIN_DEFAULTS = "BeginDefaults";
+ /** Indicates the end of the defaults section */
+ public static final String END_DEFAULTS = "EndDefaults";
+
+ /** Indicates the start of a non-PostScript section */
+ public static final String BEGIN_EMULATION = "BeginEmulation";
+ /** Indicates the end of a non-PostScript section */
+ public static final String END_EMULATION = "EndEmulation";
+
+ /** Indicates the start of a preview section (EPS only)*/
+ public static final String BEGIN_PREVIEW = "BeginPreview";
+ /** Indicates the end of a preview section (EPS only)*/
+ public static final String END_PREVIEW = "EndPreview";
+
+ /** Indicates the start of the prolog */
+ public static final String BEGIN_PROLOG = "BeginProlog";
+ /** Indicates the end of the prolog */
+ public static final String END_PROLOG = "EndProlog";
+
+ /** Indicates the start of the document setup */
+ public static final String BEGIN_SETUP = "BeginSetup";
+ /** Indicates the end of the document setup */
+ public static final String END_SETUP = "EndSetup";
+
+
+ // ----==== General Page Comments ====----
+
+ /** Indicates the start of a graphic object */
+ public static final String BEGIN_OBJECT = "BeginObject";
+ /** Indicates the end of a graphic object */
+ public static final String END_OBJECT = "EndObject";
+
+ /** Indicates the start of the page setup section */
+ public static final String BEGIN_PAGE_SETUP = "BeginPageSetup";
+ /** Indicates the end of the page setup section */
+ public static final String END_PAGE_SETUP = "EndPageSetup";
+
+ /** Indicates a page number */
+ public static final String PAGE = "Page";
+ /** Bounding box for a page */
+ public static final String PAGE_BBOX = "PageBoundingBox";
+ /** Bounding box for a page */
+ public static final String PAGE_ORIENTATION = "PageOrientation";
+
+
+ // ----==== General Trailer Comments ====----
+
+ /** Indicates the start of the page trailer */
+ public static final String PAGE_TRAILER = "PageTrailer";
+ /** Indicates the start of the document trailer */
+ public static final String TRAILER = "Trailer";
+ /** Indicates the end of a page (NON-STANDARD!) */
+ public static final String END_PAGE = "EndPage";
+ /** Indicates the end of the document */
+ public static final String EOF = "EOF";
+
+
+ // ----==== Requirements Conventions ====----
+
+ /**@todo Add the missing comments */
+
+ // ----==== Requirement Body Comments ====----
+
+ /** Indicates the start of an embedded document */
+ public static final String BEGIN_DOCUMENT = "BeginDocument";
+ /** Indicates the end of an embedded document */
+ public static final String END_DOCUMENT = "EndDocument";
+ /** Indicates a referenced embedded document */
+ public static final String INCLUDE_DOCUMENT = "IncludeDocument";
+
+ /** Indicates the start of a PPD feature */
+ public static final String BEGIN_FEATURE = "BeginFeature";
+ /** Indicates the end of a PPD feature */
+ public static final String END_FEATURE = "EndFeature";
+ /** Indicates a referenced a PPD feature */
+ public static final String INCLUDE_FEATURE = "IncludeFeature";
+
+ //Skipping BeginFile/EndFile/IncludeFile. They are deprecated.
+ //Skipping BeginFont/EndFont/IncludeFont. They are deprecated.
+ //Skipping BeginProcSet/EndProcSet/IncludeProcSet. They are deprecated.
+
+ /** Indicates the start of a resource (font, file, procset) */
+ public static final String BEGIN_RESOURCE = "BeginResource";
+ /** Indicates the end of a resource (font, file, procset) */
+ public static final String END_RESOURCE = "EndResource";
+ /** Indicates a referenced a resource (font, file, procset) */
+ public static final String INCLUDE_RESOURCE = "IncludeResource";
+
+
+}
--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2001-2002 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+package org.apache.fop.render.ps;
+
+import java.io.OutputStream;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.util.Date;
+
+/**
+ * This class is used to output PostScript code to an OutputStream.
+ *
+ * @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
+ * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
+ * @version $Id$
+ */
+public class PSGenerator {
+
+ /**
+ * Indicator for the PostScript interpreter that the value is provided
+ * later in the document (mostly in the %%Trailer section).
+ */
+ public static final AtendIndicator ATEND = new AtendIndicator() {};
+
+ private OutputStream out;
+
+ private StringBuffer tempBuffer = new StringBuffer(256);
+
+ /** @see java.io.FilterOutputStream **/
+ public PSGenerator(OutputStream out) {
+ this.out = out;
+ }
+
+ /**
+ * Writes a newline character to the OutputStream.
+ *
+ * @throws IOException In case of an I/O problem
+ */
+ public final void newLine() throws IOException {
+ out.write('\n');
+ }
+
+ /**
+ * Formats a double value for PostScript output.
+ *
+ * @param value value to format
+ * @return the formatted value
+ */
+ public String formatDouble(double value) {
+ NumberFormat nf = new java.text.DecimalFormat("0.#");
+ return nf.format(value);
+ }
+
+ /**
+ * Writes a PostScript command to the stream.
+ *
+ * @param cmd The PostScript code to be written.
+ * @exception IOException In case of an I/O problem
+ */
+ public void write(String cmd) throws IOException {
+ if (cmd.length() > 255) {
+ throw new RuntimeException("PostScript command exceeded limit of 255 characters");
+ }
+ out.write(cmd.getBytes("US-ASCII"));
+ }
+
+ /**
+ * Writes a PostScript command to the stream and ends the line.
+ *
+ * @param cmd The PostScript code to be written.
+ * @exception IOException In case of an I/O problem
+ */
+ public void writeln(String cmd) throws IOException {
+ write(cmd);
+ newLine();
+ }
+
+ /**
+ * Writes encoded data to the PostScript stream.
+ *
+ * @param cmd The encoded PostScript code to be written.
+ * @exception IOException In case of an I/O problem
+ */
+ public void writeByteArr(byte[] cmd) throws IOException {
+ out.write(cmd);
+ newLine();
+ }
+
+
+ /**
+ * Flushes the OutputStream.
+ *
+ * @exception IOException In case of an I/O problem
+ */
+ public void flush() throws IOException {
+ out.flush();
+ }
+
+
+ /**
+ * Escapes a character conforming to the rules established in the PostScript
+ * Language Reference (Search for "Literal Text Strings").
+ * @param c character to escape
+ * @param target target StringBuffer to write the escaped character to
+ */
+ public static final void escapeChar(char c, StringBuffer target) {
+ if (c > 127) {
+ target.append("\\");
+ target.append(Integer.toOctalString(c));
+ } else {
+ switch (c) {
+ case '\n':
+ target.append("\\n");
+ break;
+ case '\r':
+ target.append("\\r");
+ break;
+ case '\t':
+ target.append("\\t");
+ break;
+ case '\b':
+ target.append("\\b");
+ break;
+ case '\f':
+ target.append("\\f");
+ break;
+ case '\\':
+ target.append("\\\\");
+ break;
+ case '(':
+ target.append("\\(");
+ break;
+ case ')':
+ target.append("\\)");
+ break;
+ default:
+ target.append(c);
+ }
+ }
+ }
+
+
+ /**
+ * Converts text by applying escaping rules established in the DSC specs.
+ * @param text Text to convert
+ * @return String The resulting String
+ */
+ public static final String convertStringToDSC(String text) {
+ return convertStringToDSC(text, false);
+ }
+
+
+ /**
+ * Converts text by applying escaping rules established in the DSC specs.
+ * @param text Text to convert
+ * @param forceParentheses Force the use of parentheses
+ * @return String The resulting String
+ */
+ public static final String convertStringToDSC(String text,
+ boolean forceParentheses) {
+ if ((text == null) || (text.length() == 0)) {
+ return "()";
+ } else {
+ int initialSize = text.length();
+ initialSize += initialSize / 2;
+ StringBuffer sb = new StringBuffer(initialSize);
+ if ((Long.getLong(text) != null)
+ || (text.indexOf(" ") >= 0)
+ || forceParentheses) {
+
+ sb.append("(");
+ for (int i = 0; i < text.length(); i++) {
+ final char c = text.charAt(i);
+ escapeChar(c, sb);
+ }
+ sb.append(")");
+ return sb.toString();
+ } else {
+ return text;
+ }
+ }
+ }
+
+
+ /**
+ * Writes a DSC comment to the output stream.
+ * @param name Name of the DSC comment
+ * @exception IOException In case of an I/O problem
+ * @see org.apache.fop.render.ps.DSCConstants
+ */
+ public void writeDSCComment(String name) throws IOException {
+ writeln("%%" + name);
+ }
+
+
+ /**
+ * Writes a DSC comment to the output stream. The parameter to the DSC
+ * comment can be any object. The object is converted to a String as
+ * necessary.
+ * @param name Name of the DSC comment
+ * @param param Single parameter to the DSC comment
+ * @exception IOException In case of an I/O problem
+ * @see org.apache.fop.render.ps.DSCConstants
+ */
+ public void writeDSCComment(String name, Object param) throws IOException {
+ writeDSCComment(name, new Object[] {param});
+ }
+
+
+ /**
+ * Writes a DSC comment to the output stream. The parameters to the DSC
+ * comment can be any object. The objects are converted to Strings as
+ * necessary. Please see the source code to find out what parameters are
+ * currently supported.
+ * @param name Name of the DSC comment
+ * @param params Array of parameters to the DSC comment
+ * @exception IOException In case of an I/O problem
+ * @see org.apache.fop.render.ps.DSCConstants
+ */
+ public void writeDSCComment(String name, Object[] params) throws IOException {
+ tempBuffer.setLength(0);
+ tempBuffer.append("%%");
+ tempBuffer.append(name);
+ if ((params != null) && (params.length > 0)) {
+ tempBuffer.append(": ");
+ for (int i = 0; i < params.length; i++) {
+ if (i > 0) {
+ tempBuffer.append(" ");
+ }
+
+ if (params[i] instanceof String) {
+ tempBuffer.append(convertStringToDSC((String)params[i]));
+ } else if (params[i] instanceof AtendIndicator) {
+ tempBuffer.append("(atend)");
+ } else if (params[i] instanceof Number) {
+ tempBuffer.append(params[i].toString());
+ } else if (params[i] instanceof Date) {
+ DateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+ tempBuffer.append(convertStringToDSC(df.format((Date)params[i])));
+ } else {
+ throw new IllegalArgumentException("Unsupported parameter type: "
+ + params[i].getClass().getName());
+ }
+ }
+ }
+ writeln(tempBuffer.toString());
+ }
+
+
+ /** Used for the ATEND constant. See there. */
+ private static interface AtendIndicator {
+ }
+
+}
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage;
+import java.io.IOException;
// FOP
import org.apache.fop.layout.FontInfo;
import org.apache.fop.layout.FontState;
-import org.apache.fop.pdf.PDFColor;
-//import org.apache.fop.pdf.PDFColorSpace;
-import org.apache.fop.pdf.PDFNumber;
// Batik
import org.apache.batik.ext.awt.g2d.AbstractGraphics2D;
private boolean standalone = false;
/**
- * the PDF Document being created
+ * the PostScript genertaor being created
*/
- protected PSRenderer psRenderer;
+ protected PSGenerator gen;
/** Currently valid FontState */
protected FontState fontState;
/**
* the current colour for use in svg
*/
- protected PDFColor currentColour = new PDFColor(0, 0, 0);
+ protected Color currentColour = new Color(0, 0, 0);
/** FontInfo containing all available fonts */
protected FontInfo fontInfo;
* Create a new Graphics2D that generates PostScript code.
* @param textAsShapes True if text should be rendered as graphics
* @param fs currently valid FontState object
- * @param ren PostScript renderer
+ * @param gen PostScript generator to use for output
* @param font current font name
* @param size current font size
* @param xpos current x pos
* @param ypos current y pos
* @see org.apache.batik.ext.awt.g2d.AbstractGraphics2D#AbstractGraphics2D(boolean)
*/
- public PSGraphics2D(boolean textAsShapes, FontState fs, PSRenderer ren,
+ public PSGraphics2D(boolean textAsShapes, FontState fs, PSGenerator gen,
String font, int size, int xpos, int ypos) {
super(textAsShapes);
- psRenderer = ren;
+ this.gen = gen;
currentFontName = font;
currentFontSize = size;
currentYPosition = ypos;
return new PSGraphics2D(this);
}
+ /**
+ * Central handler for IOExceptions for this class.
+ * @param ioe IOException to handle
+ */
+ protected void handleIOException(IOException ioe) {
+ ioe.printStackTrace();
+ }
+
/**
* Draws as much of the specified image as is currently available.
* The image is drawn with its top-left corner at
*/
public void dispose() {
// System.out.println("dispose");
- psRenderer = null;
+ this.gen = null;
fontState = null;
currentFontName = null;
currentColour = null;
* @see #setComposite
*/
public void draw(Shape s) {
- // System.out.println("draw(Shape)");
- psRenderer.write("gsave");
- Shape imclip = getClip();
- writeClip(imclip);
- Color c = getColor();
- psRenderer.write(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
- + " setrgbcolor");
-
- applyPaint(getPaint(), false);
- applyStroke(getStroke());
-
- psRenderer.write("newpath");
- PathIterator iter = s.getPathIterator(getTransform());
- while (!iter.isDone()) {
- double vals[] = new double[6];
- int type = iter.currentSegment(vals);
- switch (type) {
- case PathIterator.SEG_CUBICTO:
- psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
- + PDFNumber.doubleOut(1000 * vals[1]) + " "
- + PDFNumber.doubleOut(1000 * vals[2]) + " "
- + PDFNumber.doubleOut(1000 * vals[3]) + " "
- + PDFNumber.doubleOut(1000 * vals[4]) + " "
- + PDFNumber.doubleOut(1000 * vals[5])
- + " curveto");
- break;
- case PathIterator.SEG_LINETO:
- psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
- + PDFNumber.doubleOut(1000 * vals[1])
- + " lineto");
- break;
- case PathIterator.SEG_MOVETO:
- psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
- + PDFNumber.doubleOut(1000 * vals[1])
- + " M");
- break;
- case PathIterator.SEG_QUADTO:
- // psRenderer.write((1000 * PDFNumber.doubleOut(vals[0])) +
- // " " + (1000 * PDFNumber.doubleOut(vals[1])) + " " +
- // (1000 * PDFNumber.doubleOut(vals[2])) + " " +
- // (1000 * PDFNumber.doubleOut(vals[3])) + " y\n");
- break;
- case PathIterator.SEG_CLOSE:
- psRenderer.write("closepath");
- break;
- default:
- break;
+ try {
+ // System.out.println("draw(Shape)");
+ gen.writeln("gsave");
+ Shape imclip = getClip();
+ writeClip(imclip);
+ Color c = getColor();
+ gen.writeln(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
+ + " setrgbcolor");
+
+ applyPaint(getPaint(), false);
+ applyStroke(getStroke());
+
+ gen.writeln("newpath");
+ PathIterator iter = s.getPathIterator(getTransform());
+ while (!iter.isDone()) {
+ double vals[] = new double[6];
+ int type = iter.currentSegment(vals);
+ switch (type) {
+ case PathIterator.SEG_CUBICTO:
+ gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+ + gen.formatDouble(1000 * vals[1]) + " "
+ + gen.formatDouble(1000 * vals[2]) + " "
+ + gen.formatDouble(1000 * vals[3]) + " "
+ + gen.formatDouble(1000 * vals[4]) + " "
+ + gen.formatDouble(1000 * vals[5])
+ + " curveto");
+ break;
+ case PathIterator.SEG_LINETO:
+ gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+ + gen.formatDouble(1000 * vals[1])
+ + " lineto");
+ break;
+ case PathIterator.SEG_MOVETO:
+ gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+ + gen.formatDouble(1000 * vals[1])
+ + " M");
+ break;
+ case PathIterator.SEG_QUADTO:
+ // psRenderer.write((1000 * PDFNumber.doubleOut(vals[0])) +
+ // " " + (1000 * PDFNumber.doubleOut(vals[1])) + " " +
+ // (1000 * PDFNumber.doubleOut(vals[2])) + " " +
+ // (1000 * PDFNumber.doubleOut(vals[3])) + " y\n");
+ break;
+ case PathIterator.SEG_CLOSE:
+ gen.writeln("closepath");
+ break;
+ default:
+ break;
+ }
+ iter.next();
}
- iter.next();
+ doDrawing(false, true, false);
+ gen.writeln("grestore");
+ } catch (IOException ioe) {
+ handleIOException(ioe);
}
- doDrawing(false, true, false);
- psRenderer.write("grestore");
}
/**
* @param s Shape defining the clipping region
*/
protected void writeClip(Shape s) {
- PathIterator iter = s.getPathIterator(getTransform());
- psRenderer.write("newpath");
- while (!iter.isDone()) {
- double vals[] = new double[6];
- int type = iter.currentSegment(vals);
- switch (type) {
- case PathIterator.SEG_CUBICTO:
- psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
- + PDFNumber.doubleOut(1000 * vals[1]) + " "
- + PDFNumber.doubleOut(1000 * vals[2]) + " "
- + PDFNumber.doubleOut(1000 * vals[3]) + " "
- + PDFNumber.doubleOut(1000 * vals[4]) + " "
- + PDFNumber.doubleOut(1000 * vals[5])
- + " curveto");
- break;
- case PathIterator.SEG_LINETO:
- psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
- + PDFNumber.doubleOut(1000 * vals[1])
- + " lineto");
- break;
- case PathIterator.SEG_MOVETO:
- psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
- + PDFNumber.doubleOut(1000 * vals[1])
- + " M");
- break;
- case PathIterator.SEG_QUADTO:
- // psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
- // " " + 1000 * PDFNumber.doubleOut(vals[1]) + " " +
- // 1000 * PDFNumber.doubleOut(vals[2]) + " " +
- // 1000 * PDFNumber.doubleOut(vals[3]) + " y\n");
- break;
- case PathIterator.SEG_CLOSE:
- psRenderer.write("closepath");
- break;
- default:
- break;
+ try {
+ PathIterator iter = s.getPathIterator(getTransform());
+ gen.writeln("newpath");
+ while (!iter.isDone()) {
+ double vals[] = new double[6];
+ int type = iter.currentSegment(vals);
+ switch (type) {
+ case PathIterator.SEG_CUBICTO:
+ gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+ + gen.formatDouble(1000 * vals[1]) + " "
+ + gen.formatDouble(1000 * vals[2]) + " "
+ + gen.formatDouble(1000 * vals[3]) + " "
+ + gen.formatDouble(1000 * vals[4]) + " "
+ + gen.formatDouble(1000 * vals[5])
+ + " curveto");
+ break;
+ case PathIterator.SEG_LINETO:
+ gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+ + gen.formatDouble(1000 * vals[1])
+ + " lineto");
+ break;
+ case PathIterator.SEG_MOVETO:
+ gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+ + gen.formatDouble(1000 * vals[1])
+ + " M");
+ break;
+ case PathIterator.SEG_QUADTO:
+ // psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
+ // " " + 1000 * PDFNumber.doubleOut(vals[1]) + " " +
+ // 1000 * PDFNumber.doubleOut(vals[2]) + " " +
+ // 1000 * PDFNumber.doubleOut(vals[3]) + " y\n");
+ break;
+ case PathIterator.SEG_CLOSE:
+ gen.writeln("closepath");
+ break;
+ default:
+ break;
+ }
+ iter.next();
}
- iter.next();
+ // clip area
+ gen.writeln("clippath");
+ } catch (IOException ioe) {
+ handleIOException(ioe);
}
- // clip area
- psRenderer.write("clippath");
}
/**
List someColors = new java.util.ArrayList();
- PDFColor color1 = new PDFColor(c1.getRed(), c1.getGreen(),
+ Color color1 = new Color(c1.getRed(), c1.getGreen(),
c1.getBlue());
someColors.add(color1);
- PDFColor color2 = new PDFColor(c2.getRed(), c2.getGreen(),
+ Color color2 = new Color(c2.getRed(), c2.getGreen(),
c2.getBlue());
someColors.add(color2);
* @param stroke Stroke object to use
*/
protected void applyStroke(Stroke stroke) {
- if (stroke instanceof BasicStroke) {
- BasicStroke bs = (BasicStroke)stroke;
-
- float[] da = bs.getDashArray();
- if (da != null) {
- psRenderer.write("[");
- for (int count = 0; count < da.length; count++) {
- psRenderer.write("" + (1000 * (int)da[count]));
- if (count < da.length - 1) {
- psRenderer.write(" ");
+ try {
+ if (stroke instanceof BasicStroke) {
+ BasicStroke bs = (BasicStroke)stroke;
+
+ float[] da = bs.getDashArray();
+ if (da != null) {
+ gen.writeln("[");
+ for (int count = 0; count < da.length; count++) {
+ gen.writeln("" + (1000 * (int)da[count]));
+ if (count < da.length - 1) {
+ gen.writeln(" ");
+ }
}
+ gen.writeln("] ");
+ float offset = bs.getDashPhase();
+ gen.writeln((1000 * (int)offset) + " setdash");
}
- psRenderer.write("] ");
- float offset = bs.getDashPhase();
- psRenderer.write((1000 * (int)offset) + " setdash");
- }
- int ec = bs.getEndCap();
- switch (ec) {
- case BasicStroke.CAP_BUTT:
- psRenderer.write(0 + " setlinecap");
- break;
- case BasicStroke.CAP_ROUND:
- psRenderer.write(1 + " setlinecap");
- break;
- case BasicStroke.CAP_SQUARE:
- psRenderer.write(2 + " setlinecap");
- break;
- }
-
- int lj = bs.getLineJoin();
- switch (lj) {
- case BasicStroke.JOIN_MITER:
- psRenderer.write(0 + " setlinejoin");
- break;
- case BasicStroke.JOIN_ROUND:
- psRenderer.write(1 + " setlinejoin");
- break;
- case BasicStroke.JOIN_BEVEL:
- psRenderer.write(2 + " setlinejoin");
- break;
+ int ec = bs.getEndCap();
+ switch (ec) {
+ case BasicStroke.CAP_BUTT:
+ gen.writeln(0 + " setlinecap");
+ break;
+ case BasicStroke.CAP_ROUND:
+ gen.writeln(1 + " setlinecap");
+ break;
+ case BasicStroke.CAP_SQUARE:
+ gen.writeln(2 + " setlinecap");
+ break;
+ }
+
+ int lj = bs.getLineJoin();
+ switch (lj) {
+ case BasicStroke.JOIN_MITER:
+ gen.writeln("0 setlinejoin");
+ break;
+ case BasicStroke.JOIN_ROUND:
+ gen.writeln("1 setlinejoin");
+ break;
+ case BasicStroke.JOIN_BEVEL:
+ gen.writeln("2 setlinejoin");
+ break;
+ }
+ float lw = bs.getLineWidth();
+ gen.writeln(gen.formatDouble(1000 * lw) + " setlinewidth");
+
+ float ml = bs.getMiterLimit();
+ gen.writeln(gen.formatDouble(1000 * ml) + " setmiterlimit");
}
- float lw = bs.getLineWidth();
- psRenderer.write(PDFNumber.doubleOut(1000 * lw)
- + " setlinewidth");
-
- float ml = bs.getMiterLimit();
- psRenderer.write(PDFNumber.doubleOut(1000 * ml)
- + " setmiterlimit");
+ } catch (IOException ioe) {
+ handleIOException(ioe);
}
}
* @see #setClip
*/
public void drawString(String s, float x, float y) {
- System.out.println("drawString(String)");
- psRenderer.write("BT");
- Shape imclip = getClip();
- writeClip(imclip);
- Color c = getColor();
- psRenderer.write(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
- + " setrgbcolor");
-
- AffineTransform trans = getTransform();
- trans.translate(x, y);
- double[] vals = new double[6];
- trans.getMatrix(vals);
-
- psRenderer.write(PDFNumber.doubleOut(vals[0]) + " "
- + PDFNumber.doubleOut(vals[1]) + " "
- + PDFNumber.doubleOut(vals[2]) + " "
- + PDFNumber.doubleOut(vals[3]) + " "
- + PDFNumber.doubleOut(vals[4]) + " "
- + PDFNumber.doubleOut(vals[5]) + " "
- + PDFNumber.doubleOut(vals[6]) + " Tm [" + s + "]");
-
- psRenderer.write("ET");
+ try {
+ System.out.println("drawString(String)");
+ gen.writeln("BT");
+ Shape imclip = getClip();
+ writeClip(imclip);
+ Color c = getColor();
+ gen.writeln(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
+ + " setrgbcolor");
+
+ AffineTransform trans = getTransform();
+ trans.translate(x, y);
+ double[] vals = new double[6];
+ trans.getMatrix(vals);
+
+ gen.writeln(gen.formatDouble(vals[0]) + " "
+ + gen.formatDouble(vals[1]) + " "
+ + gen.formatDouble(vals[2]) + " "
+ + gen.formatDouble(vals[3]) + " "
+ + gen.formatDouble(vals[4]) + " "
+ + gen.formatDouble(vals[5]) + " "
+ + gen.formatDouble(vals[6]) + " Tm [" + s + "]");
+
+ gen.writeln("ET");
+ } catch (IOException ioe) {
+ handleIOException(ioe);
+ }
}
/**
*/
public void drawString(AttributedCharacterIterator iterator, float x,
float y) {
- System.err.println("drawString(AttributedCharacterIterator)");
-
- psRenderer.write("BT");
- Shape imclip = getClip();
- writeClip(imclip);
- Color c = getColor();
- currentColour = new PDFColor(c.getRed(), c.getGreen(), c.getBlue());
- psRenderer.write(currentColour.getColorSpaceOut(true));
- c = getBackground();
- PDFColor col = new PDFColor(c.getRed(), c.getGreen(), c.getBlue());
- psRenderer.write(col.getColorSpaceOut(false));
-
- AffineTransform trans = getTransform();
- trans.translate(x, y);
- double[] vals = new double[6];
- trans.getMatrix(vals);
-
- for (char ch = iterator.first(); ch != CharacterIterator.DONE;
- ch = iterator.next()) {
- //Map attr = iterator.getAttributes();
-
- psRenderer.write(PDFNumber.doubleOut(vals[0]) + " "
- + PDFNumber.doubleOut(vals[1]) + " "
- + PDFNumber.doubleOut(vals[2]) + " "
- + PDFNumber.doubleOut(vals[3]) + " "
- + PDFNumber.doubleOut(vals[4]) + " "
- + PDFNumber.doubleOut(vals[5]) + " "
- + PDFNumber.doubleOut(vals[6]) + " Tm [" + ch
- + "]");
+ try {
+ System.err.println("drawString(AttributedCharacterIterator)");
+
+ gen.writeln("BT");
+ Shape imclip = getClip();
+ writeClip(imclip);
+ Color c = getColor();
+ currentColour = new Color(c.getRed(), c.getGreen(), c.getBlue());
+ //gen.writeln(currentColour.getColorSpaceOut(true));
+ c = getBackground();
+ Color col = new Color(c.getRed(), c.getGreen(), c.getBlue());
+ //gen.writeln(col.getColorSpaceOut(false));
+
+ AffineTransform trans = getTransform();
+ trans.translate(x, y);
+ double[] vals = new double[6];
+ trans.getMatrix(vals);
+
+ for (char ch = iterator.first(); ch != CharacterIterator.DONE;
+ ch = iterator.next()) {
+ //Map attr = iterator.getAttributes();
+
+ gen.writeln(gen.formatDouble(vals[0]) + " "
+ + gen.formatDouble(vals[1]) + " "
+ + gen.formatDouble(vals[2]) + " "
+ + gen.formatDouble(vals[3]) + " "
+ + gen.formatDouble(vals[4]) + " "
+ + gen.formatDouble(vals[5]) + " "
+ + gen.formatDouble(vals[6]) + " Tm [" + ch
+ + "]");
+ }
+
+ gen.writeln("ET");
+ } catch (IOException ioe) {
+ handleIOException(ioe);
}
-
- psRenderer.write("ET");
}
/**
* @see #setClip
*/
public void fill(Shape s) {
- // System.err.println("fill");
- psRenderer.write("gsave");
- Shape imclip = getClip();
- writeClip(imclip);
- Color c = getColor();
- psRenderer.write(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
- + " setrgbcolor");
-
- applyPaint(getPaint(), true);
-
- psRenderer.write("newpath");
- PathIterator iter = s.getPathIterator(getTransform());
- while (!iter.isDone()) {
- double vals[] = new double[6];
- int type = iter.currentSegment(vals);
- switch (type) {
- case PathIterator.SEG_CUBICTO:
- psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
- + PDFNumber.doubleOut(1000 * vals[1]) + " "
- + PDFNumber.doubleOut(1000 * vals[2]) + " "
- + PDFNumber.doubleOut(1000 * vals[3]) + " "
- + PDFNumber.doubleOut(1000 * vals[4]) + " "
- + PDFNumber.doubleOut(1000 * vals[5])
- + " curveto");
- break;
- case PathIterator.SEG_LINETO:
- psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
- + PDFNumber.doubleOut(1000 * vals[1])
- + " lineto");
- break;
- case PathIterator.SEG_MOVETO:
- psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
- + PDFNumber.doubleOut(1000 * vals[1])
- + " M");
- break;
- case PathIterator.SEG_QUADTO:
- // psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
- // " " + 1000 * PDFNumber.doubleOut(vals[1]) + " " +
- // 1000 * PDFNumber.doubleOut(vals[2]) + " " +
- // 1000 * PDFNumber.doubleOut(vals[3]) + " y\n");
- break;
- case PathIterator.SEG_CLOSE:
- psRenderer.write("closepath");
- break;
- default:
- break;
+ try {
+ // System.err.println("fill");
+ gen.writeln("gsave");
+ Shape imclip = getClip();
+ writeClip(imclip);
+ Color c = getColor();
+ gen.writeln(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
+ + " setrgbcolor");
+
+ applyPaint(getPaint(), true);
+
+ gen.writeln("newpath");
+ PathIterator iter = s.getPathIterator(getTransform());
+ while (!iter.isDone()) {
+ double vals[] = new double[6];
+ int type = iter.currentSegment(vals);
+ switch (type) {
+ case PathIterator.SEG_CUBICTO:
+ gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+ + gen.formatDouble(1000 * vals[1]) + " "
+ + gen.formatDouble(1000 * vals[2]) + " "
+ + gen.formatDouble(1000 * vals[3]) + " "
+ + gen.formatDouble(1000 * vals[4]) + " "
+ + gen.formatDouble(1000 * vals[5])
+ + " curveto");
+ break;
+ case PathIterator.SEG_LINETO:
+ gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+ + gen.formatDouble(1000 * vals[1])
+ + " lineto");
+ break;
+ case PathIterator.SEG_MOVETO:
+ gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+ + gen.formatDouble(1000 * vals[1])
+ + " M");
+ break;
+ case PathIterator.SEG_QUADTO:
+ // psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
+ // " " + 1000 * PDFNumber.doubleOut(vals[1]) + " " +
+ // 1000 * PDFNumber.doubleOut(vals[2]) + " " +
+ // 1000 * PDFNumber.doubleOut(vals[3]) + " y\n");
+ break;
+ case PathIterator.SEG_CLOSE:
+ gen.writeln("closepath");
+ break;
+ default:
+ break;
+ }
+ iter.next();
}
- iter.next();
+ doDrawing(true, false,
+ iter.getWindingRule() == PathIterator.WIND_EVEN_ODD);
+ gen.writeln("grestore");
+ } catch (IOException ioe) {
+ handleIOException(ioe);
}
- doDrawing(true, false,
- iter.getWindingRule() == PathIterator.WIND_EVEN_ODD);
- psRenderer.write("grestore");
}
/**
* Commits a painting operation.
* @param fill filling
* @param stroke stroking
+ * @param nonzero ???
+ * @exception IOException In case of an I/O problem
*/
- protected void doDrawing(boolean fill, boolean stroke, boolean nonzero) {
+ protected void doDrawing(boolean fill, boolean stroke, boolean nonzero)
+ throws IOException {
if (fill) {
if (stroke) {
if (!nonzero) {
- psRenderer.write("stroke");
+ gen.writeln("stroke");
} else {
- psRenderer.write("stroke");
+ gen.writeln("stroke");
}
} else {
if (!nonzero) {
- psRenderer.write("fill");
+ gen.writeln("fill");
} else {
- psRenderer.write("fill");
+ gen.writeln("fill");
}
}
} else {
// if(stroke)
- psRenderer.write("stroke");
+ gen.writeln("stroke");
}
}
--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2001-2003 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+package org.apache.fop.render.ps;
+
+import java.io.IOException;
+
+/**
+ * This class defines the basic resources (procsets) used by FOP's PostScript
+ * renderer and SVG transcoder.
+ *
+ * @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
+ * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
+ * @version $Id$
+ */
+public final class PSProcSets {
+
+ /**
+ * Generates a resource defining standard procset for FOP.
+ * @param gen PSGenerator to use for output
+ * @throws IOException In case of an I/O problem
+ */
+ public static final void writeFOPStdProcSet(PSGenerator gen) throws IOException {
+ gen.writeln("%%BeginResource: procset (Apache FOP Std ProcSet) 1.0 0");
+ gen.writeln("%%Version: 1.0 0");
+ gen.writeln("%%Copyright: Copyright (C) 2001-2003 "
+ + "The Apache Software Foundation. All rights reserved.");
+ gen.writeln("%%Title: Basic set of procedures used by FOP");
+
+ gen.writeln("/bd{bind def}bind def");
+ gen.writeln("/ld{load def}bd");
+ gen.writeln("/M/moveto ld");
+ gen.writeln("/RM/rmoveto ld");
+ gen.writeln("/t/show ld");
+
+ gen.writeln("/_ctm matrix def"); //Holds the current matrix
+ gen.writeln("/_tm matrix def");
+ //BT: save currentmatrix, set _tm to identitymatrix and move to 0/0
+ gen.writeln("/BT { _ctm currentmatrix pop matrix _tm copy pop 0 0 moveto } bd");
+ //ET: restore last currentmatrix
+ gen.writeln("/ET { _ctm setmatrix } bd");
+ gen.writeln("/iTm { _ctm setmatrix _tm concat } bd");
+ gen.writeln("/Tm { _tm astore pop iTm 0 0 moveto } bd");
+
+ gen.writeln("/ux 0.0 def");
+ gen.writeln("/uy 0.0 def");
+
+ // <font> <size> F
+ gen.writeln("/F {");
+ gen.writeln(" /Tp exch def");
+ // gen.writeln(" currentdict exch get");
+ gen.writeln(" /Tf exch def");
+ gen.writeln(" Tf findfont Tp scalefont setfont");
+ gen.writeln(" /cf Tf def /cs Tp def /cw ( ) stringwidth pop def");
+ gen.writeln("} bd");
+
+ gen.writeln("/ULS {currentpoint /uy exch def /ux exch def} bd");
+ gen.writeln("/ULE {");
+ gen.writeln(" /Tcx currentpoint pop def");
+ gen.writeln(" gsave");
+ gen.writeln(" newpath");
+ gen.writeln(" cf findfont cs scalefont dup");
+ gen.writeln(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
+ gen.writeln(" /UnderlinePosition get Ts mul /To exch def");
+ gen.writeln(" /UnderlineThickness get Ts mul /Tt exch def");
+ gen.writeln(" ux uy To add moveto Tcx uy To add lineto");
+ gen.writeln(" Tt setlinewidth stroke");
+ gen.writeln(" grestore");
+ gen.writeln("} bd");
+
+ gen.writeln("/OLE {");
+ gen.writeln(" /Tcx currentpoint pop def");
+ gen.writeln(" gsave");
+ gen.writeln(" newpath");
+ gen.writeln(" cf findfont cs scalefont dup");
+ gen.writeln(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
+ gen.writeln(" /UnderlinePosition get Ts mul /To exch def");
+ gen.writeln(" /UnderlineThickness get Ts mul /Tt exch def");
+ gen.writeln(" ux uy To add cs add moveto Tcx uy To add cs add lineto");
+ gen.writeln(" Tt setlinewidth stroke");
+ gen.writeln(" grestore");
+ gen.writeln("} bd");
+
+ gen.writeln("/SOE {");
+ gen.writeln(" /Tcx currentpoint pop def");
+ gen.writeln(" gsave");
+ gen.writeln(" newpath");
+ gen.writeln(" cf findfont cs scalefont dup");
+ gen.writeln(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
+ gen.writeln(" /UnderlinePosition get Ts mul /To exch def");
+ gen.writeln(" /UnderlineThickness get Ts mul /Tt exch def");
+ gen.writeln(" ux uy To add cs 10 mul 26 idiv add moveto "
+ + "Tcx uy To add cs 10 mul 26 idiv add lineto");
+ gen.writeln(" Tt setlinewidth stroke");
+ gen.writeln(" grestore");
+ gen.writeln("} bd");
+
+ gen.writeln("%%EndResource");
+ }
+
+
+ /**
+ * Generates a resource defining a procset for including EPS graphics.
+ * @param gen PSGenerator to use for output
+ * @throws IOException In case of an I/O problem
+ */
+ public static final void writeFOPEPSProcSet(PSGenerator gen) throws IOException {
+ gen.writeln("%%BeginResource: procset (Apache FOP EPS ProcSet) 1.0 0");
+ gen.writeln("%%Version: 1.0 0");
+ gen.writeln("%%Copyright: Copyright (C) 2002-2003 "
+ + "The Apache Software Foundation. All rights reserved.");
+ gen.writeln("%%Title: EPS procedures used by FOP");
+
+ gen.writeln("/BeginEPSF { %def");
+ gen.writeln("/b4_Inc_state save def % Save state for cleanup");
+ gen.writeln("/dict_count countdictstack def % Count objects on dict stack");
+ gen.writeln("/op_count count 1 sub def % Count objects on operand stack");
+ gen.writeln("userdict begin % Push userdict on dict stack");
+ gen.writeln("/showpage { } def % Redefine showpage, { } = null proc");
+ gen.writeln("0 setgray 0 setlinecap % Prepare graphics state");
+ gen.writeln("1 setlinewidth 0 setlinejoin");
+ gen.writeln("10 setmiterlimit [ ] 0 setdash newpath");
+ gen.writeln("/languagelevel where % If level not equal to 1 then");
+ gen.writeln("{pop languagelevel % set strokeadjust and");
+ gen.writeln("1 ne % overprint to their defaults.");
+ gen.writeln("{false setstrokeadjust false setoverprint");
+ gen.writeln("} if");
+ gen.writeln("} if");
+ gen.writeln("} bd");
+
+ gen.writeln("/EndEPSF { %def");
+ gen.writeln("count op_count sub {pop} repeat % Clean up stacks");
+ gen.writeln("countdictstack dict_count sub {end} repeat");
+ gen.writeln("b4_Inc_state restore");
+ gen.writeln("} bd");
+
+ gen.writeln("%%EndResource");
+ }
+
+}
package org.apache.fop.render.ps;
// Java
+import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
// FOP
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.area.Block;
+import org.apache.fop.area.BlockViewport;
+import org.apache.fop.area.CTM;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.area.Trait;
+import org.apache.fop.area.inline.ForeignObject;
+import org.apache.fop.area.inline.Word;
import org.apache.fop.datatypes.ColorType;
import org.apache.fop.fonts.Font;
import org.apache.fop.layout.FontInfo;
import org.apache.fop.render.AbstractRenderer;
+import org.apache.fop.render.RendererContext;
+import org.w3c.dom.Document;
/**
* sure to also follow the DSC to make it simpler to programmatically modify
* the generated Postscript files (ex. extract pages etc.).
* <br>
+ * The PS renderer operates in millipoints as the layout engine. Since PostScript
+ * initially uses points, scaling is applied as needed.
* @todo Rebuild the PostScript renderer
+ *
+ * @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
+ * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
+ * @version $Id$
*/
public class PSRenderer extends AbstractRenderer {
- /**
- * the application producing the PostScript
- */
+ /** The MIME type for PostScript */
+ public static final String MIME_TYPE = "application/postscript";
+
+ /** The application producing the PostScript */
protected String producer;
+ private int currentPageNumber = 0;
private boolean enableComments = true;
- /**
- * the stream used to output the PostScript
- */
- protected PSStream out;
+ /** The PostScript generator used to output the PostScript */
+ protected PSGenerator gen;
private boolean ioTrouble = false;
private String currentFontName;
* Write out a command
* @param cmd PostScript command
*/
- protected void write(String cmd) {
+ protected void writeln(String cmd) {
try {
- out.write(cmd);
- } catch (IOException e) {
- if (!ioTrouble) {
- e.printStackTrace();
- }
+ gen.writeln(cmd);
+ } catch (IOException ioe) {
+ handleIOTrouble(ioe);
+ }
+ }
+
+ protected void handleIOTrouble(IOException ioe) {
+ if (!ioTrouble) {
+ getLogger().error("Error while writing to target file", ioe);
ioTrouble = true;
}
}
*/
protected void comment(String comment) {
if (this.enableComments) {
- write(comment);
+ writeln(comment);
}
}
* @param fontInfo available fonts
*/
protected void writeFontDict(FontInfo fontInfo) {
- write("%%BeginResource: procset FOPFonts");
- write("%%Title: Font setup (shortcuts) for this file");
- write("/FOPFonts 100 dict dup begin");
- write("/bd{bind def}bind def");
- write("/ld{load def}bd");
- write("/M/moveto ld");
- write("/RM/rmoveto ld");
- write("/t/show ld");
-
- write("/ux 0.0 def");
- write("/uy 0.0 def");
- // write("/cf /Helvetica def");
- // write("/cs 12000 def");
-
- // <font> <size> F
- write("/F {");
- write(" /Tp exch def");
- // write(" currentdict exch get");
- write(" /Tf exch def");
- write(" Tf findfont Tp scalefont setfont");
- write(" /cf Tf def /cs Tp def /cw ( ) stringwidth pop def");
- write("} bd");
-
- write("/ULS {currentpoint /uy exch def /ux exch def} bd");
- write("/ULE {");
- write(" /Tcx currentpoint pop def");
- write(" gsave");
- write(" newpath");
- write(" cf findfont cs scalefont dup");
- write(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
- write(" /UnderlinePosition get Ts mul /To exch def");
- write(" /UnderlineThickness get Ts mul /Tt exch def");
- write(" ux uy To add moveto Tcx uy To add lineto");
- write(" Tt setlinewidth stroke");
- write(" grestore");
- write("} bd");
-
- write("/OLE {");
- write(" /Tcx currentpoint pop def");
- write(" gsave");
- write(" newpath");
- write(" cf findfont cs scalefont dup");
- write(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
- write(" /UnderlinePosition get Ts mul /To exch def");
- write(" /UnderlineThickness get Ts mul /Tt exch def");
- write(" ux uy To add cs add moveto Tcx uy To add cs add lineto");
- write(" Tt setlinewidth stroke");
- write(" grestore");
- write("} bd");
-
- write("/SOE {");
- write(" /Tcx currentpoint pop def");
- write(" gsave");
- write(" newpath");
- write(" cf findfont cs scalefont dup");
- write(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
- write(" /UnderlinePosition get Ts mul /To exch def");
- write(" /UnderlineThickness get Ts mul /Tt exch def");
- write(" ux uy To add cs 10 mul 26 idiv add moveto "
- + "Tcx uy To add cs 10 mul 26 idiv add lineto");
- write(" Tt setlinewidth stroke");
- write(" grestore");
- write("} bd");
-
-
+ writeln("%%BeginResource: procset FOPFonts");
+ writeln("%%Title: Font setup (shortcuts) for this file");
+ writeln("/FOPFonts 100 dict dup begin");
// write("/gfF1{/Helvetica findfont} bd");
// write("/gfF3{/Helvetica-Bold findfont} bd");
while (enum.hasNext()) {
String key = (String)enum.next();
Font fm = (Font)fonts.get(key);
- write("/" + key + " /" + fm.getFontName() + " def");
+ writeln("/" + key + " /" + fm.getFontName() + " def");
}
- write("end def");
- write("%%EndResource");
+ writeln("end def");
+ writeln("%%EndResource");
enum = fonts.keySet().iterator();
while (enum.hasNext()) {
String key = (String)enum.next();
Font fm = (Font)fonts.get(key);
- write("/" + fm.getFontName() + " findfont");
- write("dup length dict begin");
- write(" {1 index /FID ne {def} {pop pop} ifelse} forall");
- write(" /Encoding ISOLatin1Encoding def");
- write(" currentdict");
- write("end");
- write("/" + fm.getFontName() + " exch definefont pop");
+ writeln("/" + fm.getFontName() + " findfont");
+ writeln("dup length dict begin");
+ writeln(" {1 index /FID ne {def} {pop pop} ifelse} forall");
+ writeln(" /Encoding ISOLatin1Encoding def");
+ writeln(" currentdict");
+ writeln("end");
+ writeln("/" + fm.getFontName() + " exch definefont pop");
}
}
* Make sure the cursor is in the right place.
*/
protected void movetoCurrPosition() {
- write(this.currentIPPosition + " " + this.currentBPPosition + " M");
+ moveTo(this.currentIPPosition, this.currentBPPosition);
}
+ /**
+ * Moves the cursor.
+ * @param x X coordinate
+ * @param y Y coordinate
+ */
+ protected void moveTo(int x, int y) {
+ writeln(x + " " + y + " M");
+ }
+
+ /** Saves the graphics state of the rendering engine. */
+ protected void saveGraphicsState() {
+ writeln("gsave");
+ }
+
+ /** Restores the last graphics state of the rendering engine. */
+ protected void restoreGraphicsState() {
+ writeln("grestore");
+ }
+
+ /** Indicates the beginning of a text object. */
+ protected void beginTextObject() {
+ writeln("BT");
+ }
+
+ /** Indicates the end of a text object. */
+ protected void endTextObject() {
+ writeln("ET");
+ }
+
/**
* Set up the font info
*
* @param h height
* @param col color to fill with
*/
- protected void addFilledRect(int x, int y, int w, int h,
+ protected void fillRect(int x, int y, int w, int h,
ColorType col) {
- write("newpath");
- write(x + " " + y + " M");
- write(w + " 0 rlineto");
- write("0 " + (-h) + " rlineto");
- write((-w) + " 0 rlineto");
- write("0 " + h + " rlineto");
- write("closepath");
useColor(col);
- write("fill");
+ writeln(x + " " + y + " " + w + " " + h + " rectfill");
+ }
+
+ protected void drawRect(int x, int y, int w, int h) {
+ writeln(x + " " + y + " " + w + " " + h + " rectstroke");
+ }
+
+ /**
+ * Clip an area.
+ * Write a clipping operation given coordinates in the current
+ * transform.
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param width the width of the area
+ * @param height the height of the area
+ */
+ protected void clip(float x, float y, float width, float height) {
+ writeln(x + " " + y + " " + width + " " + height + " rectclip");
}
/**
*/
public void useFont(String name, int size) {
if ((currentFontName != name) || (currentFontSize != size)) {
- write(name + " " + size + " F");
+ writeln(name + " " + size + " F");
currentFontName = name;
currentFontSize = size;
}
private void useColor(float red, float green, float blue) {
if ((red != currRed) || (green != currGreen) || (blue != currBlue)) {
- write(red + " " + green + " " + blue + " setrgbcolor");
+ writeln(red + " " + green + " " + blue + " setrgbcolor");
currRed = red;
currGreen = green;
currBlue = blue;
* @see org.apache.fop.render.Renderer#startRenderer(OutputStream)
*/
public void startRenderer(OutputStream outputStream)
- throws IOException {
+ throws IOException {
getLogger().debug("rendering areas to PostScript");
- this.out = new PSStream(outputStream);
- write("%!PS-Adobe-3.0");
- write("%%Creator: " + this.producer);
- write("%%DocumentProcessColors: Black");
- write("%%DocumentSuppliedResources: procset FOPFonts");
- write("%%EndComments");
- write("%%BeginDefaults");
- write("%%EndDefaults");
- write("%%BeginProlog");
- write("%%EndProlog");
- write("%%BeginSetup");
+ //Setup for PostScript generation
+ this.gen = new PSGenerator(outputStream);
+ this.currentPageNumber = 0;
+
+ //PostScript Header
+ writeln(DSCConstants.PS_ADOBE_30);
+ gen.writeDSCComment(DSCConstants.CREATOR, new String[] {"FOP " + this.producer});
+ gen.writeDSCComment(DSCConstants.CREATION_DATE, new Object[] {new java.util.Date()});
+ gen.writeDSCComment(DSCConstants.PAGES, new Object[] {PSGenerator.ATEND});
+ gen.writeDSCComment(DSCConstants.END_COMMENTS);
+
+ //Defaults
+ gen.writeDSCComment(DSCConstants.BEGIN_DEFAULTS);
+ gen.writeDSCComment(DSCConstants.END_DEFAULTS);
+
+ //Prolog
+ gen.writeDSCComment(DSCConstants.BEGIN_PROLOG);
+ gen.writeDSCComment(DSCConstants.END_PROLOG);
+
+ //Setup
+ gen.writeDSCComment(DSCConstants.BEGIN_SETUP);
+ PSProcSets.writeFOPStdProcSet(gen);
+ PSProcSets.writeFOPEPSProcSet(gen);
writeFontDict(fontInfo);
-
- /* Write proc for including EPS */
- write("%%BeginResource: procset EPSprocs");
- write("%%Title: EPS encapsulation procs");
-
- write("/BeginEPSF { %def");
- write("/b4_Inc_state save def % Save state for cleanup");
- write("/dict_count countdictstack def % Count objects on dict stack");
- write("/op_count count 1 sub def % Count objects on operand stack");
- write("userdict begin % Push userdict on dict stack");
- write("/showpage { } def % Redefine showpage, { } = null proc");
- write("0 setgray 0 setlinecap % Prepare graphics state");
- write("1 setlinewidth 0 setlinejoin");
- write("10 setmiterlimit [ ] 0 setdash newpath");
- write("/languagelevel where % If level not equal to 1 then");
- write("{pop languagelevel % set strokeadjust and");
- write("1 ne % overprint to their defaults.");
- write("{false setstrokeadjust false setoverprint");
- write("} if");
- write("} if");
- write("} bind def");
-
- write("/EndEPSF { %def");
- write("count op_count sub {pop} repeat % Clean up stacks");
- write("countdictstack dict_count sub {end} repeat");
- write("b4_Inc_state restore");
- write("} bind def");
- write("%%EndResource");
-
- write("%%EndSetup");
- write("FOPFonts begin");
+ gen.writeDSCComment(DSCConstants.END_SETUP);
}
/**
* @see org.apache.fop.render.Renderer#stopRenderer()
*/
public void stopRenderer() throws IOException {
- write("%%Trailer");
- write("%%EOF");
- this.out.flush();
+ gen.writeDSCComment(DSCConstants.TRAILER);
+ gen.writeDSCComment(DSCConstants.PAGES, new Integer(this.currentPageNumber));
+ gen.writeDSCComment(DSCConstants.EOF);
+ gen.flush();
+ }
+
+ /**
+ * @see org.apache.fop.render.Renderer#renderPage(PageViewport)
+ */
+ public void renderPage(PageViewport page)
+ throws IOException, FOPException {
+ getLogger().debug("renderPage(): " + page);
+
+ this.currentPageNumber++;
+ gen.writeDSCComment(DSCConstants.PAGE, new Object[]
+ {page.getPageNumber(),
+ new Integer(this.currentPageNumber)});
+ final Integer zero = new Integer(0);
+ final Long pagewidth = new Long(Math.round(page.getViewArea().getWidth() / 1000f));
+ final Long pageheight = new Long(Math.round(page.getViewArea().getHeight() / 1000f));
+ gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[]
+ {zero, zero, pagewidth, pageheight});
+ gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP);
+ gen.writeln("FOPFonts begin");
+ gen.writeln("[1 0 0 -1 0 " + pageheight + "] concat");
+ gen.writeln("0.001 0.001 scale");
+ gen.writeDSCComment(DSCConstants.END_PAGE_SETUP);
+
+ //Process page
+ super.renderPage(page);
+
+ writeln("showpage");
+ gen.writeDSCComment(DSCConstants.PAGE_TRAILER);
+ gen.writeDSCComment(DSCConstants.END_PAGE);
+ }
+
+ protected void paintText(int rx, int bl, String text, Font font) {
+ saveGraphicsState();
+ writeln("1 0 0 -1 " + rx + " " + bl + " Tm");
+
+ int initialSize = text.length();
+ initialSize += initialSize / 2;
+ StringBuffer sb = new StringBuffer(initialSize);
+ sb.append("(");
+ for (int i = 0; i < text.length(); i++) {
+ final char c = text.charAt(i);
+ final char mapped = font.mapChar(c);
+ gen.escapeChar(mapped, sb);
+ }
+ sb.append(") t");
+ writeln(sb.toString());
+ restoreGraphicsState();
+ }
+
+ /**
+ * @see org.apache.fop.render.Renderer#renderWord(Word)
+ */
+ public void renderWord(Word area) {
+ String fontname = (String)area.getTrait(Trait.FONT_NAME);
+ int fontsize = area.getTraitAsInteger(Trait.FONT_SIZE);
+
+ // This assumes that *all* CIDFonts use a /ToUnicode mapping
+ Font f = (Font)fontInfo.getFonts().get(fontname);
+
+ //Determine position
+ int rx = currentBlockIPPosition;
+ int bl = currentBPPosition + area.getOffset();
+
+ useFont(fontname, fontsize);
+
+ paintText(rx, bl, area.getWord(), f);
+
+/*
+ String psString = null;
+ if (area.getFontState().getLetterSpacing() > 0) {
+ //float f = area.getFontState().getLetterSpacing() * 1000 / this.currentFontSize;
+ float f = area.getFontState().getLetterSpacing();
+ psString = (new StringBuffer().append(f).append(" 0.0 (")
+ .append(sb.toString()).append(") A")).toString();
+ } else {
+ psString = (new StringBuffer("(").append(sb.toString())
+ .append(") t")).toString();
+ }
+
+
+ // System.out.println("["+s+"] --> ["+sb.toString()+"]");
+
+ // comment("% --- InlineArea font-weight="+fontWeight+": " + sb.toString());
+ useFont(fs.getFontName(), fs.getFontSize());
+ useColor(area.getRed(), area.getGreen(), area.getBlue());
+ if (area.getUnderlined() || area.getLineThrough()
+ || area.getOverlined())
+ write("ULS");
+ write(psString);
+ if (area.getUnderlined())
+ write("ULE");
+ if (area.getLineThrough())
+ write("SOE");
+ if (area.getOverlined())
+ write("OLE");
+ this.currentXPosition += area.getContentWidth();
+ */
+ super.renderWord(area); //Updates IPD
}
+
+ /**
+ * @see org.apache.fop.render.AbstractRenderer#renderBlockViewport(BlockViewport, List)
+ */
+ protected void renderBlockViewport(BlockViewport bv, List children) {
+ // clip and position viewport if necessary
+
+ // save positions
+ int saveIP = currentIPPosition;
+ int saveBP = currentBPPosition;
+ String saveFontName = currentFontName;
+
+ CTM ctm = bv.getCTM();
+
+ if (bv.getPositioning() == Block.ABSOLUTE) {
+
+ currentIPPosition = 0;
+ currentBPPosition = 0;
+
+ //closeText();
+ endTextObject();
+
+ if (bv.getClip()) {
+ saveGraphicsState();
+ int x = bv.getXOffset() + containingIPPosition;
+ int y = bv.getYOffset() + containingBPPosition;
+ int width = bv.getWidth();
+ int height = bv.getHeight();
+ clip(x, y, width, height);
+ }
+
+ CTM tempctm = new CTM(containingIPPosition, containingBPPosition);
+ ctm = tempctm.multiply(ctm);
+
+ startVParea(ctm);
+ handleBlockTraits(bv);
+ renderBlocks(children);
+ endVParea();
+
+ if (bv.getClip()) {
+ restoreGraphicsState();
+ }
+ beginTextObject();
+
+ // clip if necessary
+
+ currentIPPosition = saveIP;
+ currentBPPosition = saveBP;
+ } else {
+
+ if (ctm != null) {
+ currentIPPosition = 0;
+ currentBPPosition = 0;
+
+ //closeText();
+ endTextObject();
+
+ double[] vals = ctm.toArray();
+ //boolean aclock = vals[2] == 1.0;
+ if (vals[2] == 1.0) {
+ ctm = ctm.translate(-saveBP - bv.getHeight(), -saveIP);
+ } else if (vals[0] == -1.0) {
+ ctm = ctm.translate(-saveIP - bv.getWidth(), -saveBP - bv.getHeight());
+ } else {
+ ctm = ctm.translate(saveBP, saveIP - bv.getWidth());
+ }
+ }
+
+ // clip if necessary
+ if (bv.getClip()) {
+ if (ctm == null) {
+ //closeText();
+ endTextObject();
+ }
+ saveGraphicsState();
+ int x = bv.getXOffset();
+ int y = bv.getYOffset();
+ int width = bv.getWidth();
+ int height = bv.getHeight();
+ clip(x, y, width, height);
+ }
+
+ if (ctm != null) {
+ startVParea(ctm);
+ }
+ handleBlockTraits(bv);
+ renderBlocks(children);
+ if (ctm != null) {
+ endVParea();
+ }
+
+ if (bv.getClip()) {
+ restoreGraphicsState();
+ if (ctm == null) {
+ beginTextObject();
+ }
+ }
+ if (ctm != null) {
+ beginTextObject();
+ }
+
+ currentIPPosition = saveIP;
+ currentBPPosition = saveBP;
+ currentBPPosition += (int)(bv.getHeight());
+ }
+ currentFontName = saveFontName;
+ }
+
+ /**
+ * @see org.apache.fop.render.AbstractRenderer#startVParea(CTM)
+ */
+ protected void startVParea(CTM ctm) {
+ // Set the given CTM in the graphics state
+ //currentState.push();
+ //currentState.setTransform(new AffineTransform(CTMHelper.toPDFArray(ctm)));
+
+ saveGraphicsState();
+ // multiply with current CTM
+ //currentStream.add(CTMHelper.toPDFString(ctm) + " cm\n");
+ final double matrix[] = ctm.toArray();
+ writeln("[" + gen.formatDouble(matrix[0])
+ + " " + gen.formatDouble(matrix[1])
+ + " " + gen.formatDouble(matrix[2])
+ + " " + gen.formatDouble(matrix[3])
+ + " " + gen.formatDouble(matrix[4])
+ + " " + gen.formatDouble(matrix[5]) + "] concat");
+
+ // Set clip?
+ beginTextObject();
+ }
+
+ /**
+ * @see org.apache.fop.render.AbstractRenderer#endVParea()
+ */
+ protected void endVParea() {
+ endTextObject();
+ restoreGraphicsState();
+ //currentState.pop();
+ }
+
+
+ /**
+ * @see org.apache.fop.render.AbstractRenderer#renderForeignObject(ForeignObject, Rectangle2D)
+ */
+ public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
+ Document doc = fo.getDocument();
+ String ns = fo.getNameSpace();
+ renderDocument(doc, ns, pos);
+ }
+
+ public void renderDocument(Document doc, String ns, Rectangle2D pos) {
+ RendererContext context;
+ context = new RendererContext(MIME_TYPE);
+ context.setUserAgent(userAgent);
+
+ /*
+ context.setProperty(PDFXMLHandler.PDF_DOCUMENT, pdfDoc);
+ context.setProperty(PDFXMLHandler.OUTPUT_STREAM, ostream);
+ context.setProperty(PDFXMLHandler.PDF_STATE, currentState);
+ context.setProperty(PDFXMLHandler.PDF_PAGE, currentPage);
+ context.setProperty(PDFXMLHandler.PDF_CONTEXT,
+ currentContext == null ? currentPage: currentContext);
+ context.setProperty(PDFXMLHandler.PDF_CONTEXT, currentContext);
+ context.setProperty(PDFXMLHandler.PDF_STREAM, currentStream);
+ context.setProperty(PDFXMLHandler.PDF_XPOS,
+ new Integer(currentBlockIPPosition + (int) pos.getX()));
+ context.setProperty(PDFXMLHandler.PDF_YPOS,
+ new Integer(currentBPPosition + (int) pos.getY()));
+ context.setProperty(PDFXMLHandler.PDF_FONT_INFO, fontInfo);
+ context.setProperty(PDFXMLHandler.PDF_FONT_NAME, currentFontName);
+ context.setProperty(PDFXMLHandler.PDF_FONT_SIZE,
+ new Integer(currentFontSize));
+ context.setProperty(PDFXMLHandler.PDF_WIDTH,
+ new Integer((int) pos.getWidth()));
+ context.setProperty(PDFXMLHandler.PDF_HEIGHT,
+ new Integer((int) pos.getHeight()));
+ */
+ userAgent.renderXML(context, doc, ns);
+
+ }
+
+
+
+
}
+++ /dev/null
-/*
- * $Id$
- * Copyright (C) 2001-2002 The Apache Software Foundation. All rights reserved.
- * For details on use and redistribution please refer to the
- * LICENSE file included with these sources.
- */
-package org.apache.fop.render.ps;
-
-import java.io.OutputStream;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-
-/**
- * PSStream is used to to output PostScript code from the PostScript renderer.
- */
-public class PSStream extends FilterOutputStream {
-
- /** @see java.io.FilterOutputStream **/
- public PSStream(OutputStream out) {
- super(out);
- }
-
-
- /**
- * Writes a PostScript command to the stream.
- *
- * @param cmd The PostScript code to be written.
- * @exception IOException In case of an I/O problem
- */
- public void write(String cmd) throws IOException {
- if (cmd.length() > 255) {
- throw new RuntimeException("PostScript command exceeded limit of 255 characters");
- }
- write(cmd.getBytes("US-ASCII"));
- write('\n');
- }
-
-
- /**
- * Writes encoded data to the PostScript stream.
- *
- * @param cmd The encoded PostScript code to be written.
- * @exception IOException In case of an I/O problem
- */
- public void writeByteArr(byte[] cmd) throws IOException {
- write(cmd);
- write('\n');
- }
-
-}