Browse Source

Added page master name to IFDocumentHandler.startPage() method.

Wired together the support for out-of-order rendering (only applicable to PDF) when the intermediate format is not used (in-memory rendering).
Fixed a logical bug in IFRenderer that caused some unneeded code. Glyph adjustments (kerning, letter/word space...) were not done right. All painters fixed/adjusted accordingly.
Started implementation of the PostScript painter: Supports only text and filled rectangles so far. Work in progress...

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign@719051 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-1_0
Jeremias Maerki 15 years ago
parent
commit
be4dc692db
23 changed files with 1498 additions and 214 deletions
  1. 2
    1
      src/java/META-INF/services/org.apache.fop.render.intermediate.IFDocumentHandler
  2. 2
    1
      src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java
  3. 15
    0
      src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
  4. 2
    1
      src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java
  5. 2
    1
      src/java/org/apache/fop/render/intermediate/IFParser.java
  6. 11
    7
      src/java/org/apache/fop/render/intermediate/IFRenderer.java
  7. 2
    1
      src/java/org/apache/fop/render/intermediate/IFSerializer.java
  8. 1
    1
      src/java/org/apache/fop/render/java2d/Java2DPainter.java
  9. 1
    1
      src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java
  10. 3
    3
      src/java/org/apache/fop/render/pcl/PCLPainter.java
  11. 0
    14
      src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
  12. 2
    1
      src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
  13. 5
    5
      src/java/org/apache/fop/render/pdf/PDFPainter.java
  14. 33
    0
      src/java/org/apache/fop/render/ps/PSConfigurationConstants.java
  15. 522
    0
      src/java/org/apache/fop/render/ps/PSDocumentHandler.java
  16. 59
    0
      src/java/org/apache/fop/render/ps/PSDocumentHandlerMaker.java
  17. 395
    0
      src/java/org/apache/fop/render/ps/PSPainter.java
  18. 27
    157
      src/java/org/apache/fop/render/ps/PSRenderer.java
  19. 69
    18
      src/java/org/apache/fop/render/ps/PSRendererConfigurator.java
  20. 59
    0
      src/java/org/apache/fop/render/ps/PSRenderingContext.java
  21. 282
    0
      src/java/org/apache/fop/render/ps/PSRenderingUtil.java
  22. 2
    1
      src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java
  23. 2
    1
      src/sandbox/org/apache/fop/render/svg/SVGPrintDocumentHandler.java

+ 2
- 1
src/java/META-INF/services/org.apache.fop.render.intermediate.IFDocumentHandler View File

@@ -1,3 +1,4 @@
org.apache.fop.render.pdf.PDFDocumentHandlerMaker
org.apache.fop.render.pcl.PCLDocumentHandlerMaker
org.apache.fop.render.bitmap.TIFFDocumentHandlerMaker
org.apache.fop.render.bitmap.TIFFDocumentHandlerMaker
org.apache.fop.render.ps.PSDocumentHandlerMaker

+ 2
- 1
src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java View File

@@ -166,7 +166,8 @@ public class TIFFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
}

/** {@inheritDoc} */
public void startPage(int index, String name, Dimension size) throws IFException {
public void startPage(int index, String name, String pageMasterName, Dimension size)
throws IFException {
this.pageCount++;
this.currentPageDimensions = new Dimension(size);
}

+ 15
- 0
src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java View File

@@ -350,4 +350,19 @@ public abstract class AbstractIFPainter implements IFPainter {
}
}

/**
* Converts a transformation matrix from millipoints to points.
* @param transform the transformation matrix (in millipoints)
* @return the converted transformation matrix (in points)
*/
public static AffineTransform toPoints(AffineTransform transform) {
final double[] matrix = new double[6];
transform.getMatrix(matrix);
//Convert from millipoints to points
matrix[4] /= 1000;
matrix[5] /= 1000;
return new AffineTransform(matrix);
}


}

+ 2
- 1
src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java View File

@@ -189,10 +189,11 @@ public interface IFDocumentHandler {
* Indicates the start of a new page.
* @param index the index of the page (0-based)
* @param name the page name (usually the formatted page number)
* @param pageMasterName the name of the simple-page-master that generated this page
* @param size the size of the page (equivalent to the MediaBox in PDF)
* @throws IFException if an error occurs while handling this event
*/
void startPage(int index, String name, Dimension size) throws IFException;
void startPage(int index, String name, String pageMasterName, Dimension size) throws IFException;

/**
* Indicates the end of a page

+ 2
- 1
src/java/org/apache/fop/render/intermediate/IFParser.java View File

@@ -332,9 +332,10 @@ public class IFParser implements IFConstants {
public void startElement(Attributes attributes) throws IFException {
int index = Integer.parseInt(attributes.getValue("index"));
String name = attributes.getValue("name");
String pageMasterName = attributes.getValue("page-master-name");
int width = Integer.parseInt(attributes.getValue("width"));
int height = Integer.parseInt(attributes.getValue("height"));
documentHandler.startPage(index, name, new Dimension(width, height));
documentHandler.startPage(index, name, pageMasterName, new Dimension(width, height));
}

public void endElement() throws IFException {

+ 11
- 7
src/java/org/apache/fop/render/intermediate/IFRenderer.java View File

@@ -195,6 +195,12 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
}
}

/** {@inheritDoc} */
public boolean supportsOutOfOrder() {
return (this.documentHandler != null
? this.documentHandler.supportsPagesOutOfOrder() : false);
}

/**
* Creates a default {@code IFDocumentHandler} when none has been set.
* @return the default IFDocumentHandler
@@ -492,7 +498,8 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
Dimension dim = new Dimension(
(int)Math.ceil(viewArea.getWidth()),
(int)Math.ceil(viewArea.getHeight()));
documentHandler.startPage(page.getPageIndex(), page.getPageNumberString(), dim);
documentHandler.startPage(page.getPageIndex(), page.getPageNumberString(),
page.getSimplePageMasterName(), dim);
documentHandler.startPageHeader();
//TODO Handle page header
documentHandler.endPageHeader();
@@ -867,8 +874,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
int tws = ((TextArea) space.getParentArea()).getTextWordSpaceAdjust()
+ 2 * textArea.getTextLetterSpaceAdjust();
if (tws != 0) {
float fontSize = font.getFontSize() / 1000f;
textUtil.adjust(Math.round(tws / fontSize * 10));
textUtil.adjust(tws);
}
}
super.renderSpace(space);
@@ -891,7 +897,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
for (int i = 0; i < l; i++) {
char ch = s.charAt(i);
textUtil.addChar(ch);
float glyphAdjust = 0;
int glyphAdjust = 0;
if (font.hasChar(ch)) {
int tls = (i < l - 1 ? parentArea.getTextLetterSpaceAdjust() : 0);
glyphAdjust += tls;
@@ -900,9 +906,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
glyphAdjust += letterAdjust[i];
}

float adjust = glyphAdjust / fontSize;

textUtil.adjust(Math.round(adjust * 10));
textUtil.adjust(glyphAdjust);
}
}


+ 2
- 1
src/java/org/apache/fop/render/intermediate/IFSerializer.java View File

@@ -191,11 +191,12 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler implements
}

/** {@inheritDoc} */
public void startPage(int index, String name, Dimension size) throws IFException {
public void startPage(int index, String name, String pageMasterName, Dimension size) throws IFException {
try {
AttributesImpl atts = new AttributesImpl();
addAttribute(atts, "index", Integer.toString(index));
addAttribute(atts, "name", name);
addAttribute(atts, "page-master-name", name);
addAttribute(atts, "width", Integer.toString(size.width));
addAttribute(atts, "height", Integer.toString(size.height));
handler.startElement(EL_PAGE, atts);

+ 1
- 1
src/java/org/apache/fop/render/java2d/Java2DPainter.java View File

@@ -233,7 +233,7 @@ public class Java2DPainter extends AbstractIFPainter {
glyphAdjust += dx[i + 1];
}

cursor.setLocation(cursor.getX() + cw - glyphAdjust, cursor.getY());
cursor.setLocation(cursor.getX() + cw + glyphAdjust, cursor.getY());
gv.setGlyphPosition(i + 1, cursor);
}
g2d.drawGlyphVector(gv, x, y);

+ 1
- 1
src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java View File

@@ -173,7 +173,7 @@ public class PCLDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
}

/** {@inheritDoc} */
public void startPage(int index, String name, Dimension size) throws IFException {
public void startPage(int index, String name, String pageMasterName, Dimension size) throws IFException {

try {
//TODO Add support for paper-source and duplex-mode

+ 3
- 3
src/java/org/apache/fop/render/pcl/PCLPainter.java View File

@@ -414,7 +414,7 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants {
glyphAdjust += dx[i + 1];
}

width += cw - glyphAdjust;
width += cw + glyphAdjust;
}
int extraWidth = font.getFontSize() / 3;
boundingRect.setSize(
@@ -447,14 +447,14 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants {
g2d.setBackground(Color.LIGHT_GRAY);
g2d.clearRect(0, 0, (int)area.getWidth(), (int)area.getHeight());
}
g2d.translate(0, -y + baselineOffset);
g2d.translate(-x, -y + baselineOffset);

if (DEBUG) {
Rectangle rect = new Rectangle(x, y - maxAscent, 3000, maxAscent);
g2d.draw(rect);
rect = new Rectangle(x, y - ascent, 2000, ascent);
g2d.draw(rect);
rect = new Rectangle(x, y, 1000, - descent);
rect = new Rectangle(x, y, 1000, -descent);
g2d.draw(rect);
}
Java2DPainter painter = new Java2DPainter(g2d,

+ 0
- 14
src/java/org/apache/fop/render/pdf/PDFContentGenerator.java View File

@@ -185,20 +185,6 @@ public class PDFContentGenerator {
}
}

/**
* Converts a transformation matrix from millipoints to points.
* @param transform the transformation matrix (in millipoints)
* @return the converted transformation matrix (in points)
*/
public AffineTransform toPoints(AffineTransform transform) {
final double[] matrix = new double[6];
transform.getMatrix(matrix);
//Convert from millipoints to points
matrix[4] /= 1000;
matrix[5] /= 1000;
return new AffineTransform(matrix);
}

/**
* Concatenates the given transformation matrix with the current one.
* @param transform the transformation matrix (in points)

+ 2
- 1
src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java View File

@@ -168,7 +168,8 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
}

/** {@inheritDoc} */
public void startPage(int index, String name, Dimension size) throws IFException {
public void startPage(int index, String name, String pageMasterName, Dimension size)
throws IFException {
this.pdfResources = this.pdfDoc.getResources();

this.currentPage = this.pdfDoc.getFactory().makePage(

+ 5
- 5
src/java/org/apache/fop/render/pdf/PDFPainter.java View File

@@ -100,7 +100,7 @@ public class PDFPainter extends AbstractIFPainter {
public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect)
throws IFException {
generator.saveGraphicsState();
generator.concatenate(generator.toPoints(transform));
generator.concatenate(toPoints(transform));
if (clipRect != null) {
clipRect(clipRect);
}
@@ -114,7 +114,7 @@ public class PDFPainter extends AbstractIFPainter {
/** {@inheritDoc} */
public void startGroup(AffineTransform transform) throws IFException {
generator.saveGraphicsState();
generator.concatenate(generator.toPoints(transform));
generator.concatenate(toPoints(transform));
}

/** {@inheritDoc} */
@@ -196,8 +196,8 @@ public class PDFPainter extends AbstractIFPainter {
if (fill == null) {
return;
}
generator.endTextObject();
if (rect.width != 0 && rect.height != 0) {
generator.endTextObject();
if (fill != null) {
if (fill instanceof Color) {
generator.updateColor((Color)fill, true, null);
@@ -302,7 +302,7 @@ public class PDFPainter extends AbstractIFPainter {
//Fixed width space are rendered as spaces so copy/paste works in a reader
ch = font.mapChar(CharUtilities.SPACE);
int spaceDiff = font.getCharWidth(ch) - font.getCharWidth(orgChar);
glyphAdjust = -(10 * spaceDiff / fontSize);
glyphAdjust = -spaceDiff;
} else {
ch = font.mapChar(orgChar);
}
@@ -314,7 +314,7 @@ public class PDFPainter extends AbstractIFPainter {
}

if (glyphAdjust != 0) {
textutil.adjustGlyphTJ(-glyphAdjust / 10f);
textutil.adjustGlyphTJ(-glyphAdjust / fontSize);
}

}

+ 33
- 0
src/java/org/apache/fop/render/ps/PSConfigurationConstants.java View File

@@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.ps;

/**
* Constants used for configuring PostScript output.
*/
public interface PSConfigurationConstants {

/** Controls the behaviour for landscape pages */
String AUTO_ROTATE_LANDSCAPE = "auto-rotate-landscape";
/** Controls whether resources are optimized (rather than inlined) */
String OPTIMIZE_RESOURCES = "optimize-resources";
/** Determines the PostScript language level to be generated */
String LANGUAGE_LEVEL = "language-level";
}

+ 522
- 0
src/java/org/apache/fop/render/ps/PSDocumentHandler.java View File

@@ -0,0 +1,522 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.ps;

import java.awt.Dimension;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.transform.Source;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.xmlgraphics.ps.DSCConstants;
import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.xmlgraphics.ps.PSPageDeviceDictionary;
import org.apache.xmlgraphics.ps.PSProcSets;
import org.apache.xmlgraphics.ps.PSResource;
import org.apache.xmlgraphics.ps.dsc.DSCException;
import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentBoundingBox;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentHiResBoundingBox;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.fonts.LazyFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFPainter;
import org.apache.fop.render.ps.extensions.PSExtensionAttachment;
import org.apache.fop.render.ps.extensions.PSSetPageDevice;

/**
* {@code IFDocumentHandler} implementation that produces PostScript.
*/
public class PSDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {

/** logging instance */
private static Log log = LogFactory.getLog(PSDocumentHandler.class);

/**
* Utility class which enables all sorts of features that are not directly connected to the
* normal rendering process.
*/
protected PSRenderingUtil psUtil;

/** The PostScript generator used to output the PostScript */
protected PSGenerator gen;

/** the temporary file in case of two-pass processing */
private File tempFile;

private int currentPageNumber = 0;

/** Is used to determine the document's bounding box */
private Rectangle2D documentBoundingBox;

/** Used to temporarily store PSSetupCode instance until they can be written. */
private List setupCodeList;

/** This is a map of PSResource instances of all fonts defined (key: font key) */
private Map fontResources;
/** This is a map of PSResource instances of all forms (key: uri) */
private Map formResources;

/** encapsulation of dictionary used in setpagedevice instruction **/
private PSPageDeviceDictionary pageDeviceDictionary;

/** This is a collection holding all document header comments */
private Collection headerComments;

/** This is a collection holding all document footer comments */
private Collection footerComments;

/**
* Default constructor.
*/
public PSDocumentHandler() {
}

/** {@inheritDoc} */
public boolean supportsPagesOutOfOrder() {
return false;
}

/** {@inheritDoc} */
public String getMimeType() {
return MimeConstants.MIME_POSTSCRIPT;
}

/** {@inheritDoc} */
public void setUserAgent(FOUserAgent ua) {
super.setUserAgent(ua);
this.psUtil = new PSRenderingUtil(ua);
}

/** {@inheritDoc} */
public IFDocumentHandlerConfigurator getConfigurator() {
return new PSRendererConfigurator(getUserAgent());
}

PSRenderingUtil getPSUtil() {
return this.psUtil;
}

/** {@inheritDoc} */
public void startDocument() throws IFException {
try {
if (getUserAgent() == null) {
throw new IllegalStateException(
"User agent must be set before starting PostScript generation");
}
if (this.outputStream == null) {
throw new IllegalStateException("OutputStream hasn't been set through setResult()");
}
OutputStream out;
if (psUtil.isOptimizeResources()) {
this.tempFile = File.createTempFile("fop", null);
out = new java.io.FileOutputStream(this.tempFile);
out = new java.io.BufferedOutputStream(out);
} else {
out = this.outputStream;
}

//Setup for PostScript generation
this.gen = new PSGenerator(out) {
/** Need to subclass PSGenerator to have better URI resolution */
public Source resolveURI(String uri) {
return getUserAgent().resolveURI(uri);
}
};
this.gen.setPSLevel(psUtil.getLanguageLevel());
this.currentPageNumber = 0;
this.documentBoundingBox = new Rectangle2D.Double();

//Initial default page device dictionary settings
this.pageDeviceDictionary = new PSPageDeviceDictionary();
pageDeviceDictionary.setFlushOnRetrieval(!psUtil.isDSCComplianceEnabled());
pageDeviceDictionary.put("/ImagingBBox", "null");
} catch (IOException e) {
throw new IFException("I/O error in startDocument()", e);
}
}

private void writeHeader() throws IOException {
//PostScript Header
gen.writeln(DSCConstants.PS_ADOBE_30);
gen.writeDSCComment(DSCConstants.CREATOR, new String[] {getUserAgent().getProducer()});
gen.writeDSCComment(DSCConstants.CREATION_DATE, new Object[] {new java.util.Date()});
gen.writeDSCComment(DSCConstants.LANGUAGE_LEVEL, new Integer(gen.getPSLevel()));
gen.writeDSCComment(DSCConstants.PAGES, new Object[] {DSCConstants.ATEND});
gen.writeDSCComment(DSCConstants.BBOX, DSCConstants.ATEND);
gen.writeDSCComment(DSCConstants.HIRES_BBOX, DSCConstants.ATEND);
gen.writeDSCComment(DSCConstants.DOCUMENT_SUPPLIED_RESOURCES,
new Object[] {DSCConstants.ATEND});
if (headerComments != null) {
for (Iterator iter = headerComments.iterator(); iter.hasNext();) {
PSExtensionAttachment comment = (PSExtensionAttachment)iter.next();
gen.writeln("%" + comment.getContent());
}
}
gen.writeDSCComment(DSCConstants.END_COMMENTS);

//Defaults
gen.writeDSCComment(DSCConstants.BEGIN_DEFAULTS);
gen.writeDSCComment(DSCConstants.END_DEFAULTS);

//Prolog and Setup written right before the first page-sequence, see startPageSequence()
//Do this only once, as soon as we have all the content for the Setup section!
//Prolog
gen.writeDSCComment(DSCConstants.BEGIN_PROLOG);
PSProcSets.writeStdProcSet(gen);
PSProcSets.writeEPSProcSet(gen);
gen.writeDSCComment(DSCConstants.END_PROLOG);

//Setup
gen.writeDSCComment(DSCConstants.BEGIN_SETUP);
PSRenderingUtil.writeSetupCodeList(gen, setupCodeList, "SetupCode");
if (!psUtil.isOptimizeResources()) {
this.fontResources = PSFontUtils.writeFontDict(gen, fontInfo);
} else {
gen.commentln("%FOPFontSetup"); //Place-holder, will be replaced in the second pass
}
gen.writeDSCComment(DSCConstants.END_SETUP);
}

/** {@inheritDoc} */
public void endDocumentHeader() throws IFException {
try {
writeHeader();
} catch (IOException ioe) {
throw new IFException("I/O error writing the PostScript header", ioe);
}
}

/** {@inheritDoc} */
public void endDocument() throws IFException {
try {
//Write trailer
gen.writeDSCComment(DSCConstants.TRAILER);
if (footerComments != null) {
for (Iterator iter = footerComments.iterator(); iter.hasNext();) {
PSExtensionAttachment comment = (PSExtensionAttachment)iter.next();
gen.commentln("%" + comment.getContent());
}
footerComments.clear();
}
gen.writeDSCComment(DSCConstants.PAGES, new Integer(this.currentPageNumber));
new DSCCommentBoundingBox(this.documentBoundingBox).generate(gen);
new DSCCommentHiResBoundingBox(this.documentBoundingBox).generate(gen);
gen.getResourceTracker().writeResources(false, gen);
gen.writeDSCComment(DSCConstants.EOF);
gen.flush();
log.debug("Rendering to PostScript complete.");
if (psUtil.isOptimizeResources()) {
IOUtils.closeQuietly(gen.getOutputStream());
rewritePostScriptFile();
}
if (footerComments != null) {
headerComments.clear();
}
if (pageDeviceDictionary != null) {
pageDeviceDictionary.clear();
}
} catch (IOException ioe) {
throw new IFException("I/O error in endDocument()", ioe);
}
super.endDocument();
}

/**
* Used for two-pass production. This will rewrite the PostScript file from the temporary
* file while adding all needed resources.
* @throws IOException In case of an I/O error.
*/
private void rewritePostScriptFile() throws IOException {
log.debug("Processing PostScript resources...");
long startTime = System.currentTimeMillis();
ResourceTracker resTracker = gen.getResourceTracker();
InputStream in = new java.io.FileInputStream(this.tempFile);
in = new java.io.BufferedInputStream(in);
try {
try {
ResourceHandler.process(getUserAgent(), in, this.outputStream,
this.fontInfo, resTracker, this.formResources,
this.currentPageNumber, this.documentBoundingBox);
this.outputStream.flush();
} catch (DSCException e) {
throw new RuntimeException(e.getMessage());
}
} finally {
IOUtils.closeQuietly(in);
if (!this.tempFile.delete()) {
this.tempFile.deleteOnExit();
log.warn("Could not delete temporary file: " + this.tempFile);
}
}
if (log.isDebugEnabled()) {
long duration = System.currentTimeMillis() - startTime;
log.debug("Resource Processing complete in " + duration + " ms.");
}
}

/** {@inheritDoc} */
public void startPageSequence(String id) throws IFException {
//nop
}

/** {@inheritDoc} */
public void endPageSequence() throws IFException {
//nop
}

/** {@inheritDoc} */
public void startPage(int index, String name, String pageMasterName, Dimension size)
throws IFException {
try {
if (this.currentPageNumber == 0) {
//writeHeader();
}

this.currentPageNumber++;

gen.getResourceTracker().notifyStartNewPage();
gen.getResourceTracker().notifyResourceUsageOnPage(PSProcSets.STD_PROCSET);
gen.writeDSCComment(DSCConstants.PAGE, new Object[]
{name,
new Integer(this.currentPageNumber)});

double pageWidth = size.width / 1000.0;
double pageHeight = size.height / 1000.0;
boolean rotate = false;
List pageSizes = new java.util.ArrayList();
if (this.psUtil.isAutoRotateLandscape() && (pageHeight < pageWidth)) {
rotate = true;
pageSizes.add(new Long(Math.round(pageHeight)));
pageSizes.add(new Long(Math.round(pageWidth)));
} else {
pageSizes.add(new Long(Math.round(pageWidth)));
pageSizes.add(new Long(Math.round(pageHeight)));
}
pageDeviceDictionary.put("/PageSize", pageSizes);

//TODO Handle extension attachments for the page!!!!!!!
/*
if (page.hasExtensionAttachments()) {
for (Iterator iter = page.getExtensionAttachments().iterator();
iter.hasNext();) {
ExtensionAttachment attachment = (ExtensionAttachment) iter.next();
if (attachment instanceof PSSetPageDevice) {*/
/**
* Extract all PSSetPageDevice instances from the
* attachment list on the s-p-m and add all
* dictionary entries to our internal representation
* of the the page device dictionary.
*//*
PSSetPageDevice setPageDevice = (PSSetPageDevice)attachment;
String content = setPageDevice.getContent();
if (content != null) {
try {
pageDeviceDictionary.putAll(PSDictionary.valueOf(content));
} catch (PSDictionaryFormatException e) {
PSEventProducer eventProducer = PSEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.postscriptDictionaryParseError(this, content, e);
}
}
}
}
}*/

if (setupCodeList != null) {
PSRenderingUtil.writeEnclosedExtensionAttachments(gen, setupCodeList);
setupCodeList.clear();
}
final Integer zero = new Integer(0);
Rectangle2D pageBoundingBox = new Rectangle2D.Double();
if (rotate) {
pageBoundingBox.setRect(0, 0, pageHeight, pageWidth);
gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] {
zero, zero, new Long(Math.round(pageHeight)),
new Long(Math.round(pageWidth)) });
gen.writeDSCComment(DSCConstants.PAGE_HIRES_BBOX, new Object[] {
zero, zero, new Double(pageHeight),
new Double(pageWidth) });
gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Landscape");
} else {
pageBoundingBox.setRect(0, 0, pageWidth, pageHeight);
gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] {
zero, zero, new Long(Math.round(pageWidth)),
new Long(Math.round(pageHeight)) });
gen.writeDSCComment(DSCConstants.PAGE_HIRES_BBOX, new Object[] {
zero, zero, new Double(pageWidth),
new Double(pageHeight) });
if (psUtil.isAutoRotateLandscape()) {
gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION,
"Portrait");
}
}
this.documentBoundingBox.add(pageBoundingBox);
gen.writeDSCComment(DSCConstants.PAGE_RESOURCES,
new Object[] {DSCConstants.ATEND});

gen.commentln("%FOPSimplePageMaster: " + pageMasterName);

gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP);

//TODO Handle extension attachments for the page!!!!!!!
/*
if (page.hasExtensionAttachments()) {
List extensionAttachments = page.getExtensionAttachments();
for (int i = 0; i < extensionAttachments.size(); i++) {
Object attObj = extensionAttachments.get(i);
if (attObj instanceof PSExtensionAttachment) {
PSExtensionAttachment attachment = (PSExtensionAttachment)attObj;
if (attachment instanceof PSCommentBefore) {
gen.commentln("%" + attachment.getContent());
} else if (attachment instanceof PSSetupCode) {
gen.writeln(attachment.getContent());
}
}
}
}*/

// Write any unwritten changes to page device dictionary
if (!pageDeviceDictionary.isEmpty()) {
String content = pageDeviceDictionary.getContent();
if (psUtil.isSafeSetPageDevice()) {
content += " SSPD";
} else {
content += " setpagedevice";
}
PSRenderingUtil.writeEnclosedExtensionAttachment(gen, new PSSetPageDevice(content));
}

if (rotate) {
gen.writeln(Math.round(pageHeight) + " 0 translate");
gen.writeln("90 rotate");
}
gen.concatMatrix(1, 0, 0, -1, 0, pageHeight);

gen.writeDSCComment(DSCConstants.END_PAGE_SETUP);
} catch (IOException ioe) {
throw new IFException("I/O error in startPage()", ioe);
}
}

/** {@inheritDoc} */
public IFPainter startPageContent() throws IFException {
return new PSPainter(this);
}

/** {@inheritDoc} */
public void endPageContent() throws IFException {
try {
//Show page
gen.writeln("showpage");
} catch (IOException ioe) {
throw new IFException("I/O error in endPageContent()", ioe);
}
}

/** {@inheritDoc} */
public void endPage() throws IFException {
try {
gen.writeDSCComment(DSCConstants.PAGE_TRAILER);

//TODO Handle extension attachments for the page!!!!!!!
/*
if (page.hasExtensionAttachments()) {
List extensionAttachments = page.getExtensionAttachments();
for (int i = 0; i < extensionAttachments.size(); i++) {
Object attObj = extensionAttachments.get(i);
if (attObj instanceof PSExtensionAttachment) {
PSExtensionAttachment attachment = (PSExtensionAttachment)attObj;
if (attachment instanceof PSCommentAfter) {
gen.commentln("%" + attachment.getContent());
}
}
}
}*/
gen.getResourceTracker().writeResources(true, gen);
} catch (IOException ioe) {
throw new IFException("I/O error in endPage()", ioe);
}
}

/** {@inheritDoc} */
public void handleExtensionObject(Object extension) throws IFException {
log.debug("Don't know how to handle extension object. Ignoring: "
+ extension + " (" + extension.getClass().getName() + ")");
}

private String getPostScriptNameForFontKey(String key) {
int pos = key.indexOf('_');
String postFix = null;
if (pos > 0) {
postFix = key.substring(pos);
key = key.substring(0, pos);
}
Map fonts = fontInfo.getFonts();
Typeface tf = (Typeface)fonts.get(key);
if (tf instanceof LazyFont) {
tf = ((LazyFont)tf).getRealFont();
}
if (tf == null) {
throw new IllegalStateException("Font not available: " + key);
}
if (postFix == null) {
return tf.getFontName();
} else {
return tf.getFontName() + postFix;
}
}

/**
* Returns the PSResource for the given font key.
* @param key the font key ("F*")
* @return the matching PSResource
*/
protected PSResource getPSResourceForFontKey(String key) {
PSResource res = null;
if (this.fontResources != null) {
res = (PSResource)this.fontResources.get(key);
} else {
this.fontResources = new java.util.HashMap();
}
if (res == null) {
res = new PSResource(PSResource.TYPE_FONT, getPostScriptNameForFontKey(key));
this.fontResources.put(key, res);
}
return res;
}

}

+ 59
- 0
src/java/org/apache/fop/render/ps/PSDocumentHandlerMaker.java View File

@@ -0,0 +1,59 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.ps;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.render.intermediate.AbstractIFDocumentHandlerMaker;
import org.apache.fop.render.intermediate.IFDocumentHandler;
import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;

/**
* Intermediate format document handler factory for PostScript output.
*/
public class PSDocumentHandlerMaker extends AbstractIFDocumentHandlerMaker {

//TODO Revert to normal MIME after stabilization!
private static final String[] MIMES = new String[]
{MimeConstants.MIME_POSTSCRIPT + ";mode=painter"};

/** {@inheritDoc} */
public IFDocumentHandler makeIFDocumentHandler(FOUserAgent ua) {
PSDocumentHandler handler = new PSDocumentHandler();
handler.setUserAgent(ua);
return handler;
}

/** {@inheritDoc} */
public boolean needsOutputStream() {
return true;
}

/** {@inheritDoc} */
public String[] getSupportedMimeTypes() {
return MIMES;
}

/** {@inheritDoc} */
public IFDocumentHandlerConfigurator getConfigurator(FOUserAgent userAgent) {
return new PSRendererConfigurator(userAgent);
}

}

+ 395
- 0
src/java/org/apache/fop/render/ps/PSPainter.java View File

@@ -0,0 +1,395 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.ps;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Paint;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.io.IOException;
import java.util.Map;

import org.w3c.dom.Document;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.xmlgraphics.ps.PSResource;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.LazyFont;
import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.render.RenderingContext;
import org.apache.fop.render.intermediate.AbstractIFPainter;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFState;
import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.RuleStyle;
import org.apache.fop.util.CharUtilities;

/**
* IFPainter implementation that produces PostScript.
*/
public class PSPainter extends AbstractIFPainter {

/** logging instance */
private static Log log = LogFactory.getLog(PSPainter.class);

private PSDocumentHandler documentHandler;

private boolean inTextMode = false;

/**
* Default constructor.
* @param documentHandler the parent document handler
*/
public PSPainter(PSDocumentHandler documentHandler) {
super();
this.documentHandler = documentHandler;
this.state = IFState.create();
}

/** {@inheritDoc} */
protected FOUserAgent getUserAgent() {
return this.documentHandler.getUserAgent();
}

PSRenderingUtil getPSUtil() {
return this.documentHandler.psUtil;
}

FontInfo getFontInfo() {
return this.documentHandler.getFontInfo();
}

private PSGenerator getGenerator() {
return this.documentHandler.gen;
}

/** {@inheritDoc} */
public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect)
throws IFException {
try {
PSGenerator generator = getGenerator();
saveGraphicsState();
generator.concatMatrix(toPoints(transform));
} catch (IOException ioe) {
throw new IFException("I/O error in startViewport()", ioe);
}
if (clipRect != null) {
clipRect(clipRect);
}
}

/** {@inheritDoc} */
public void endViewport() throws IFException {
try {
restoreGraphicsState();
} catch (IOException ioe) {
throw new IFException("I/O error in endViewport()", ioe);
}
}

/** {@inheritDoc} */
public void startGroup(AffineTransform transform) throws IFException {
try {
PSGenerator generator = getGenerator();
saveGraphicsState();
generator.concatMatrix(toPoints(transform));
} catch (IOException ioe) {
throw new IFException("I/O error in startGroup()", ioe);
}
}

/** {@inheritDoc} */
public void endGroup() throws IFException {
try {
restoreGraphicsState();
} catch (IOException ioe) {
throw new IFException("I/O error in endGroup()", ioe);
}
}

/** {@inheritDoc} */
public void drawImage(String uri, Rectangle rect, Map foreignAttributes) throws IFException {
//TODO Implement me
}

/** {@inheritDoc} */
protected RenderingContext createRenderingContext() {
PSRenderingContext psContext = new PSRenderingContext(
getUserAgent(), getFontInfo());
return psContext;
}

/** {@inheritDoc} */
public void drawImage(Document doc, Rectangle rect, Map foreignAttributes) throws IFException {
drawImageUsingDocument(doc, rect);
}

/** {@inheritDoc} */
public void clipRect(Rectangle rect) throws IFException {
try {
PSGenerator generator = getGenerator();
endTextObject();
generator.defineRect(rect.x / 1000.0, rect.y / 1000.0,
rect.width / 1000.0, rect.height / 1000.0);
generator.writeln("clip newpath");
} catch (IOException ioe) {
throw new IFException("I/O error in clipRect()", ioe);
}
}

/** {@inheritDoc} */
public void fillRect(Rectangle rect, Paint fill) throws IFException {
if (fill == null) {
return;
}
if (rect.width != 0 && rect.height != 0) {
try {
endTextObject();
PSGenerator generator = getGenerator();
if (fill != null) {
if (fill instanceof Color) {
generator.useColor((Color)fill);
} else {
throw new UnsupportedOperationException("Non-Color paints NYI");
}
}
generator.defineRect(rect.x / 1000.0, rect.y / 1000.0,
rect.width / 1000.0, rect.height / 1000.0);
generator.writeln("fill");
} catch (IOException ioe) {
throw new IFException("I/O error in fillRect()", ioe);
}
}
}

/** {@inheritDoc} */
public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after,
BorderProps start, BorderProps end) throws IFException {
if (before != null || after != null || start != null || end != null) {
try {
//TODO Implement me
endTextObject();
//this.borderPainter.drawBorders(rect, before, after, start, end);
} catch (IOException ioe) {
throw new IFException("I/O error in drawBorderRect()", ioe);
}
}
}

/** {@inheritDoc} */
public void drawLine(Point start, Point end, int width, Color color, RuleStyle style)
throws IFException {
try {
//TODO Implement me
endTextObject();
//this.borderPainter.drawLine(start, end, width, color, style);
} catch (IOException ioe) {
throw new IFException("I/O error in drawLine()", ioe);
}
}

private Typeface getTypeface(String fontName) {
if (fontName == null) {
throw new NullPointerException("fontName must not be null");
}
Typeface tf = (Typeface)getFontInfo().getFonts().get(fontName);
if (tf instanceof LazyFont) {
tf = ((LazyFont)tf).getRealFont();
}
return tf;
}

/**
* Saves the graphics state of the rendering engine.
* @throws IOException if an I/O error occurs
*/
protected void saveGraphicsState() throws IOException {
endTextObject();
getGenerator().saveGraphicsState();
}

/**
* Restores the last graphics state of the rendering engine.
* @throws IOException if an I/O error occurs
*/
protected void restoreGraphicsState() throws IOException {
endTextObject();
getGenerator().restoreGraphicsState();
}

/**
* Indicates the beginning of a text object.
* @throws IOException if an I/O error occurs
*/
protected void beginTextObject() throws IOException {
if (!inTextMode) {
PSGenerator generator = getGenerator();
generator.saveGraphicsState();
generator.writeln("BT");
inTextMode = true;
}
}

/**
* Indicates the end of a text object.
* @throws IOException if an I/O error occurs
*/
protected void endTextObject() throws IOException {
if (inTextMode) {
inTextMode = false;
PSGenerator generator = getGenerator();
generator.writeln("ET");
generator.restoreGraphicsState();
}
}

/** {@inheritDoc} */
public void drawText(int x, int y, int[] dx, int[] dy, String text) throws IFException {
try {
//Note: dy is currently ignored
PSGenerator generator = getGenerator();
generator.useColor(state.getTextColor());
beginTextObject();
FontTriplet triplet = new FontTriplet(
state.getFontFamily(), state.getFontStyle(), state.getFontWeight());
//TODO Ignored: state.getFontVariant()
//TODO Opportunity for font caching if font state is more heavily used
String fontKey = getFontInfo().getInternalFontKey(triplet);
int sizeMillipoints = state.getFontSize();
float fontSize = sizeMillipoints / 1000f;

// This assumes that *all* CIDFonts use a /ToUnicode mapping
Typeface tf = getTypeface(fontKey);
SingleByteFont singleByteFont = null;
if (tf instanceof SingleByteFont) {
singleByteFont = (SingleByteFont)tf;
}
Font font = getFontInfo().getFontInstance(triplet, sizeMillipoints);
//String fontName = font.getFontName();

PSResource res = this.documentHandler.getPSResourceForFontKey(fontKey);
generator.useFont("/" + res.getName(), fontSize);
generator.getResourceTracker().notifyResourceUsageOnPage(res);
//textutil.updateTf(fontKey, fontSize, tf.isMultiByte());

generator.writeln("1 0 0 -1 " + generator.formatDouble(x / 1000.0)
+ " " + generator.formatDouble(y / 1000.0) + " Tm");
//textutil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, x / 1000f, y / 1000f));

int textLen = text.length();
if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) {
//Analyze string and split up in order to paint in different sub-fonts/encodings
int start = 0;
int currentEncoding = -1;
for (int i = 0; i < textLen; i++) {
char c = text.charAt(i);
char mapped = tf.mapChar(c);
int encoding = mapped / 256;
if (currentEncoding != encoding) {
if (i > 0) {
writeText(text, start, i - start, dx, dy, font, tf);
}
if (encoding == 0) {
useFont(fontKey, sizeMillipoints);
} else {
useFont(fontKey + "_" + Integer.toString(encoding), sizeMillipoints);
}
currentEncoding = encoding;
start = i;
}
}
writeText(text, start, textLen - start, dx, dy, font, tf);
} else {
//Simple single-font painting
useFont(fontKey, sizeMillipoints);
writeText(text, 0, textLen, dx, dy, font, tf);
}
} catch (IOException ioe) {
throw new IFException("I/O error in drawText()", ioe);
}
}

private void writeText(String text, int start, int len, int[] dx, int[] dy,
Font font, Typeface tf) throws IOException {
PSGenerator generator = getGenerator();
int end = start + len;
int initialSize = len;
initialSize += initialSize / 2;
StringBuffer sb = new StringBuffer(initialSize);
sb.append("(");
int[] offsets = new int[len];
int dxl = (dx != null ? dx.length : 0);
for (int i = start; i < end; i++) {
char orgChar = text.charAt(i);
char ch;
int cw;
if (CharUtilities.isFixedWidthSpace(orgChar)) {
//Fixed width space are rendered as spaces so copy/paste works in a reader
ch = font.mapChar(CharUtilities.SPACE);
//int spaceDiff = font.getCharWidth(ch) - font.getCharWidth(orgChar);
//glyphAdjust = -(spaceDiff);
} else {
ch = font.mapChar(orgChar);
//cw = tf.getWidth(ch, font.getFontSize()) / 1000;
}

cw = font.getCharWidth(orgChar);
int glyphAdjust = 0;
if (dx != null && i < dxl - 1) {
glyphAdjust += dx[i + 1];
}
offsets[i - start] = cw + glyphAdjust;
char codepoint = (char)(ch % 256);
PSGenerator.escapeChar(codepoint, sb);
}
sb.append(")" + PSGenerator.LF + "[");
for (int i = 0; i < len; i++) {
if (i > 0) {
if (i % 8 == 0) {
sb.append(PSGenerator.LF);
} else {
sb.append(" ");
}
}
sb.append(generator.formatDouble(offsets[i] / 1000f));
}
sb.append("]" + PSGenerator.LF + "xshow");
generator.writeln(sb.toString());
}

private void useFont(String key, int size) throws IOException {
PSResource res = this.documentHandler.getPSResourceForFontKey(key);
PSGenerator generator = getGenerator();
generator.useFont("/" + res.getName(), size / 1000f);
generator.getResourceTracker().notifyResourceUsageOnPage(res);
}


}

+ 27
- 157
src/java/org/apache/fop/render/ps/PSRenderer.java View File

@@ -28,7 +28,6 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Iterator;
@@ -128,7 +127,7 @@ import org.apache.fop.util.ColorUtil;
* @version $Id$
*/
public class PSRenderer extends AbstractPathOrientedRenderer
implements ImageAdapter, PSSupportedFlavors {
implements ImageAdapter, PSSupportedFlavors, PSConfigurationConstants {

/** logging instance */
private static Log log = LogFactory.getLog(PSRenderer.class);
@@ -136,17 +135,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer
/** The MIME type for PostScript */
public static final String MIME_TYPE = "application/postscript";

private static final String AUTO_ROTATE_LANDSCAPE = "auto-rotate-landscape";
private static final String OPTIMIZE_RESOURCES = "optimize-resources";
private static final String LANGUAGE_LEVEL = "language-level";

/** The application producing the PostScript */
private int currentPageNumber = 0;

private final boolean enableComments = true;
private boolean autoRotateLandscape = false;
private int languageLevel = PSGenerator.DEFAULT_LANGUAGE_LEVEL;

/** the OutputStream the PS file is written to */
private OutputStream outputStream;
/** the temporary file in case of two-pass processing */
@@ -154,8 +145,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer

/** The PostScript generator used to output the PostScript */
protected PSGenerator gen;
/** Determines whether the PS file is generated in two passes to minimize file size */
private boolean twoPassGeneration = false;
private boolean ioTrouble = false;

private boolean inTextMode = false;
@@ -171,14 +160,11 @@ public class PSRenderer extends AbstractPathOrientedRenderer
/** encapsulation of dictionary used in setpagedevice instruction **/
private PSPageDeviceDictionary pageDeviceDictionary;

/** Whether or not the safe set page device macro will be used or not */
private boolean safeSetPageDevice = false;

/**
* Whether or not PostScript Document Structuring Conventions (DSC) compliant output are
* enforced.
* Utility class which enables all sorts of features that are not directly connected to the
* normal rendering process.
*/
private boolean dscCompliant = true;
protected PSRenderingUtil psUtil;

/** Is used to determine the document's bounding box */
private Rectangle2D documentBoundingBox;
@@ -192,39 +178,11 @@ public class PSRenderer extends AbstractPathOrientedRenderer
/** {@inheritDoc} */
public void setUserAgent(FOUserAgent agent) {
super.setUserAgent(agent);
Object obj;
obj = agent.getRendererOptions().get(AUTO_ROTATE_LANDSCAPE);
if (obj != null) {
setAutoRotateLandscape(booleanValueOf(obj));
}
obj = agent.getRendererOptions().get(LANGUAGE_LEVEL);
if (obj != null) {
setLanguageLevel(intValueOf(obj));
}
obj = agent.getRendererOptions().get(OPTIMIZE_RESOURCES);
if (obj != null) {
setOptimizeResources(booleanValueOf(obj));
}
this.psUtil = new PSRenderingUtil(getUserAgent());
}

private boolean booleanValueOf(Object obj) {
if (obj instanceof Boolean) {
return ((Boolean)obj).booleanValue();
} else if (obj instanceof String) {
return Boolean.valueOf((String)obj).booleanValue();
} else {
throw new IllegalArgumentException("Boolean or \"true\" or \"false\" expected.");
}
}

private int intValueOf(Object obj) {
if (obj instanceof Integer) {
return ((Integer)obj).intValue();
} else if (obj instanceof String) {
return Integer.parseInt((String)obj);
} else {
throw new IllegalArgumentException("Integer or String with a number expected.");
}
PSRenderingUtil getPSUtil() {
return this.psUtil;
}

/**
@@ -233,12 +191,12 @@ public class PSRenderer extends AbstractPathOrientedRenderer
* a "wider-than-long" page by 90 degrees.
*/
public void setAutoRotateLandscape(boolean value) {
this.autoRotateLandscape = value;
getPSUtil().setAutoRotateLandscape(value);
}

/** @return true if the renderer is configured to rotate landscape pages */
public boolean isAutoRotateLandscape() {
return this.autoRotateLandscape;
return getPSUtil().isAutoRotateLandscape();
}

/**
@@ -246,11 +204,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer
* @param level the language level (currently allowed: 2 or 3)
*/
public void setLanguageLevel(int level) {
if (level == 2 || level == 3) {
this.languageLevel = level;
} else {
throw new IllegalArgumentException("Only language levels 2 or 3 are allowed/supported");
}
getPSUtil().setLanguageLevel(level);
}

/**
@@ -258,7 +212,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer
* @return the language level
*/
public int getLanguageLevel() {
return this.languageLevel;
return getPSUtil().getLanguageLevel();
}

/**
@@ -268,12 +222,12 @@ public class PSRenderer extends AbstractPathOrientedRenderer
* @param value true to enable the resource optimization
*/
public void setOptimizeResources(boolean value) {
this.twoPassGeneration = value;
getPSUtil().setOptimizeResources(value);
}

/** @return true if the renderer does two passes to optimize PostScript resources */
public boolean isOptimizeResources() {
return this.twoPassGeneration;
return getPSUtil().isOptimizeResources();
}

/** {@inheritDoc} */
@@ -316,12 +270,15 @@ public class PSRenderer extends AbstractPathOrientedRenderer
* @param comment Comment to write
*/
protected void comment(String comment) {
if (this.enableComments) {
try {
if (comment.startsWith("%")) {
gen.commentln(comment);
writeln(comment);
} else {
writeln("%" + comment);
gen.commentln("%" + comment);
}
} catch (IOException ioe) {
handleIOTrouble(ioe);
}
}

@@ -931,7 +888,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer

//Initial default page device dictionary settings
this.pageDeviceDictionary = new PSPageDeviceDictionary();
pageDeviceDictionary.setFlushOnRetrieval(!this.dscCompliant);
pageDeviceDictionary.setFlushOnRetrieval(!getPSUtil().isDSCComplianceEnabled());
pageDeviceDictionary.put("/ImagingBBox", "null");
}

@@ -969,7 +926,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer

//Setup
gen.writeDSCComment(DSCConstants.BEGIN_SETUP);
writeSetupCodeList(setupCodeList, "SetupCode");
PSRenderingUtil.writeSetupCodeList(gen, setupCodeList, "SetupCode");
if (!isOptimizeResources()) {
this.fontResources = PSFontUtils.writeFontDict(gen, fontInfo);
} else {
@@ -980,16 +937,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer

/** {@inheritDoc} */
public void stopRenderer() throws IOException {
//Notify resource usage for font which are not supplied
/* done in useFont now
Map fonts = fontInfo.getUsedFonts();
Iterator e = fonts.keySet().iterator();
while (e.hasNext()) {
String key = (String)e.next();
PSResource res = (PSResource)this.fontResources.get(key);
gen.notifyResourceUsage(res);
}*/

//Write trailer
gen.writeDSCComment(DSCConstants.TRAILER);
if (footerComments != null) {
@@ -1102,34 +1049,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer
super.processOffDocumentItem(oDI);
}

/**
* Formats and writes a List of PSSetupCode instances to the output stream.
* @param setupCodeList a List of PSSetupCode instances
* @param type the type of code section
*/
private void writeSetupCodeList(List setupCodeList, String type) throws IOException {
if (setupCodeList != null) {
Iterator i = setupCodeList.iterator();
while (i.hasNext()) {
PSSetupCode setupCode = (PSSetupCode)i.next();
gen.commentln("%FOPBegin" + type + ": ("
+ (setupCode.getName() != null ? setupCode.getName() : "")
+ ")");
LineNumberReader reader = new LineNumberReader(
new java.io.StringReader(setupCode.getContent()));
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.length() > 0) {
gen.writeln(line.trim());
}
}
gen.commentln("%FOPEnd" + type);
i.remove();
}
}
}

/** {@inheritDoc} */
public void renderPage(PageViewport page)
throws IOException, FOPException {
@@ -1151,7 +1070,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer
double pageHeight = Math.round(page.getViewArea().getHeight()) / 1000f;
boolean rotate = false;
List pageSizes = new java.util.ArrayList();
if (this.autoRotateLandscape && (pageHeight < pageWidth)) {
if (getPSUtil().isAutoRotateLandscape() && (pageHeight < pageWidth)) {
rotate = true;
pageSizes.add(new Long(Math.round(pageHeight)));
pageSizes.add(new Long(Math.round(pageWidth)));
@@ -1189,7 +1108,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer

try {
if (setupCodeList != null) {
writeEnclosedExtensionAttachments(setupCodeList);
PSRenderingUtil.writeEnclosedExtensionAttachments(gen, setupCodeList);
setupCodeList.clear();
}
} catch (IOException e) {
@@ -1214,7 +1133,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer
gen.writeDSCComment(DSCConstants.PAGE_HIRES_BBOX, new Object[] {
zero, zero, new Double(pageWidth),
new Double(pageHeight) });
if (autoRotateLandscape) {
if (getPSUtil().isAutoRotateLandscape()) {
gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION,
"Portrait");
}
@@ -1245,12 +1164,12 @@ public class PSRenderer extends AbstractPathOrientedRenderer
// Write any unwritten changes to page device dictionary
if (!pageDeviceDictionary.isEmpty()) {
String content = pageDeviceDictionary.getContent();
if (safeSetPageDevice) {
if (getPSUtil().isSafeSetPageDevice()) {
content += " SSPD";
} else {
content += " setpagedevice";
}
writeEnclosedExtensionAttachment(new PSSetPageDevice(content));
PSRenderingUtil.writeEnclosedExtensionAttachment(gen, new PSSetPageDevice(content));
}

if (rotate) {
@@ -1632,55 +1551,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer
return MIME_TYPE;
}

/**
* Formats and writes a PSExtensionAttachment to the output stream.
*
* @param attachment an PSExtensionAttachment instance
*/
private void writeEnclosedExtensionAttachment(PSExtensionAttachment attachment)
throws IOException {
String info = "";
if (attachment instanceof PSSetupCode) {
PSSetupCode setupCodeAttach = (PSSetupCode)attachment;
String name = setupCodeAttach.getName();
if (name != null) {
info += ": (" + name + ")";
}
}
String type = attachment.getType();
gen.commentln("%FOPBegin" + type + info);
LineNumberReader reader = new LineNumberReader(
new java.io.StringReader(attachment.getContent()));
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.length() > 0) {
gen.writeln(line);
}
}
gen.commentln("%FOPEnd" + type);
}

/**
* Formats and writes a Collection of PSExtensionAttachment instances to
* the output stream.
*
* @param attachmentCollection
* a Collection of PSExtensionAttachment instances
*/
private void writeEnclosedExtensionAttachments(Collection attachmentCollection)
throws IOException {
Iterator iter = attachmentCollection.iterator();
while (iter.hasNext()) {
PSExtensionAttachment attachment = (PSExtensionAttachment)iter
.next();
if (attachment != null) {
writeEnclosedExtensionAttachment(attachment);
}
iter.remove();
}
}

/**
* Sets whether or not the safe set page device macro should be used
* (as opposed to directly invoking setpagedevice) when setting the
@@ -1694,7 +1564,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer
* device macro call (default is false).
*/
public void setSafeSetPageDevice(boolean safeSetPageDevice) {
this.safeSetPageDevice = safeSetPageDevice;
getPSUtil().setSafeSetPageDevice(safeSetPageDevice);
}

/**
@@ -1711,7 +1581,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer
* @param dscCompliant boolean value (default is true)
*/
public void setDSCCompliant(boolean dscCompliant) {
this.dscCompliant = dscCompliant;
getPSUtil().setDSCComplianceEnabled(dscCompliant);
}

}

+ 69
- 18
src/java/org/apache/fop/render/ps/PSRendererConfigurator.java View File

@@ -19,17 +19,33 @@

package org.apache.fop.render.ps;

import java.util.List;

import org.apache.avalon.framework.configuration.Configuration;

import org.apache.xmlgraphics.ps.PSGenerator;

import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fonts.CustomFontCollection;
import org.apache.fop.fonts.FontCollection;
import org.apache.fop.fonts.FontEventAdapter;
import org.apache.fop.fonts.FontEventListener;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.base14.Base14FontCollection;
import org.apache.fop.render.DefaultFontResolver;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.Renderer;
import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.fop.render.intermediate.IFDocumentHandler;
import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;

/**
* Postscript renderer config
*/
public class PSRendererConfigurator extends PrintRendererConfigurator {
public class PSRendererConfigurator extends PrintRendererConfigurator
implements IFDocumentHandlerConfigurator {

/**
* Default constructor
@@ -50,23 +66,58 @@ public class PSRendererConfigurator extends PrintRendererConfigurator {
super.configure(renderer);

PSRenderer psRenderer = (PSRenderer)renderer;
configure(psRenderer.getPSUtil(), cfg);
}
}

psRenderer.setAutoRotateLandscape(
cfg.getChild("auto-rotate-landscape").getValueAsBoolean(false));
Configuration child;
child = cfg.getChild("language-level");
if (child != null) {
psRenderer.setLanguageLevel(child.getValueAsInteger(
PSGenerator.DEFAULT_LANGUAGE_LEVEL));
}
child = cfg.getChild("optimize-resources");
if (child != null) {
psRenderer.setOptimizeResources(child.getValueAsBoolean(false));
}
psRenderer.setSafeSetPageDevice(
cfg.getChild("safe-set-page-device").getValueAsBoolean(false));
psRenderer.setDSCCompliant(
cfg.getChild("dsc-compliant").getValueAsBoolean(true));
private void configure(PSRenderingUtil psUtil, Configuration cfg) {
psUtil.setAutoRotateLandscape(
cfg.getChild("auto-rotate-landscape").getValueAsBoolean(false));
Configuration child;
child = cfg.getChild("language-level");
if (child != null) {
psUtil.setLanguageLevel(child.getValueAsInteger(
PSGenerator.DEFAULT_LANGUAGE_LEVEL));
}
child = cfg.getChild("optimize-resources");
if (child != null) {
psUtil.setOptimizeResources(child.getValueAsBoolean(false));
}
psUtil.setSafeSetPageDevice(
cfg.getChild("safe-set-page-device").getValueAsBoolean(false));
psUtil.setDSCComplianceEnabled(
cfg.getChild("dsc-compliant").getValueAsBoolean(true));
}

/** {@inheritDoc} */
public void configure(IFDocumentHandler documentHandler) throws FOPException {
Configuration cfg = super.getRendererConfig(documentHandler.getMimeType());
if (cfg != null) {
PSDocumentHandler psDocumentHandler = (PSDocumentHandler)documentHandler;
configure(psDocumentHandler.getPSUtil(), cfg);
}

}

/** {@inheritDoc} */
public void setupFontInfo(IFDocumentHandler documentHandler, FontInfo fontInfo)
throws FOPException {
FontManager fontManager = userAgent.getFactory().getFontManager();
List fontCollections = new java.util.ArrayList();
fontCollections.add(new Base14FontCollection(fontManager.isBase14KerningEnabled()));

Configuration cfg = super.getRendererConfig(documentHandler.getMimeType());
if (cfg != null) {
FontResolver fontResolver = new DefaultFontResolver(userAgent);
FontEventListener listener = new FontEventAdapter(
userAgent.getEventBroadcaster());
List fontList = buildFontList(cfg, fontResolver, listener);
fontCollections.add(new CustomFontCollection(fontResolver, fontList));
}

fontManager.setup(fontInfo,
(FontCollection[])fontCollections.toArray(
new FontCollection[fontCollections.size()]));
documentHandler.setFontInfo(fontInfo);
}
}

+ 59
- 0
src/java/org/apache/fop/render/ps/PSRenderingContext.java View File

@@ -0,0 +1,59 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.ps;

import org.apache.xmlgraphics.util.MimeConstants;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.render.AbstractRenderingContext;

/**
* Rendering context for PostScript production.
*/
public class PSRenderingContext extends AbstractRenderingContext {

private FontInfo fontInfo;

/**
* Main constructor.
* @param userAgent the user agent
* @param fontInfo the font list
*/
public PSRenderingContext(FOUserAgent userAgent,
FontInfo fontInfo) {
super(userAgent);
this.fontInfo = fontInfo;
}

/** {@inheritDoc} */
public String getMimeType() {
return MimeConstants.MIME_POSTSCRIPT;
}

/**
* Returns the font list.
* @return the font list
*/
public FontInfo getFontInfo() {
return this.fontInfo;
}

}

+ 282
- 0
src/java/org/apache/fop/render/ps/PSRenderingUtil.java View File

@@ -0,0 +1,282 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.ps;

import java.io.IOException;
import java.io.LineNumberReader;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.apache.xmlgraphics.ps.PSGenerator;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.render.ps.extensions.PSExtensionAttachment;
import org.apache.fop.render.ps.extensions.PSSetupCode;

/**
* Utility class which enables all sorts of features that are not directly connected to the
* normal rendering process.
*/
public class PSRenderingUtil implements PSConfigurationConstants {

private FOUserAgent userAgent;

/** Whether or not the safe set page device macro will be used or not */
private boolean safeSetPageDevice = false;

/**
* Whether or not PostScript Document Structuring Conventions (DSC) compliant output are
* enforced.
*/
private boolean dscCompliant = true;

private boolean autoRotateLandscape = false;
private int languageLevel = PSGenerator.DEFAULT_LANGUAGE_LEVEL;

/** Determines whether the PS file is generated in two passes to minimize file size */
private boolean optimizeResources = false;

PSRenderingUtil(FOUserAgent userAgent) {
this.userAgent = userAgent;
initialize();
}

private void initialize() {
Object obj;
obj = userAgent.getRendererOptions().get(AUTO_ROTATE_LANDSCAPE);
if (obj != null) {
setAutoRotateLandscape(booleanValueOf(obj));
}
obj = userAgent.getRendererOptions().get(LANGUAGE_LEVEL);
if (obj != null) {
setLanguageLevel(intValueOf(obj));
}
obj = userAgent.getRendererOptions().get(OPTIMIZE_RESOURCES);
if (obj != null) {
setOptimizeResources(booleanValueOf(obj));
}
}

private boolean booleanValueOf(Object obj) {
if (obj instanceof Boolean) {
return ((Boolean)obj).booleanValue();
} else if (obj instanceof String) {
return Boolean.valueOf((String)obj).booleanValue();
} else {
throw new IllegalArgumentException("Boolean or \"true\" or \"false\" expected.");
}
}

private int intValueOf(Object obj) {
if (obj instanceof Integer) {
return ((Integer)obj).intValue();
} else if (obj instanceof String) {
return Integer.parseInt((String)obj);
} else {
throw new IllegalArgumentException("Integer or String with a number expected.");
}
}

/**
* Formats and writes a List of PSSetupCode instances to the output stream.
* @param gen the PS generator
* @param setupCodeList a List of PSSetupCode instances
* @param type the type of code section
* @throws IOException if an I/O error occurs.
*/
public static void writeSetupCodeList(PSGenerator gen, List setupCodeList, String type)
throws IOException {
if (setupCodeList != null) {
Iterator i = setupCodeList.iterator();
while (i.hasNext()) {
PSSetupCode setupCode = (PSSetupCode)i.next();
gen.commentln("%FOPBegin" + type + ": ("
+ (setupCode.getName() != null ? setupCode.getName() : "")
+ ")");
LineNumberReader reader = new LineNumberReader(
new java.io.StringReader(setupCode.getContent()));
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.length() > 0) {
gen.writeln(line.trim());
}
}
gen.commentln("%FOPEnd" + type);
i.remove();
}
}
}

/**
* Formats and writes a Collection of PSExtensionAttachment instances to
* the output stream. The instances are removed from the collection when they
* have been written.
*
* @param gen the PS generator
* @param attachmentCollection
* a Collection of PSExtensionAttachment instances
* @throws IOException if an I/O error occurs.
*/
public static void writeEnclosedExtensionAttachments(PSGenerator gen,
Collection attachmentCollection) throws IOException {
Iterator iter = attachmentCollection.iterator();
while (iter.hasNext()) {
PSExtensionAttachment attachment = (PSExtensionAttachment)iter.next();
if (attachment != null) {
writeEnclosedExtensionAttachment(gen, attachment);
}
iter.remove();
}
}

/**
* Formats and writes a PSExtensionAttachment to the output stream.
*
* @param gen the PS generator
* @param attachment an PSExtensionAttachment instance
* @throws IOException if an I/O error occurs.
*/
public static void writeEnclosedExtensionAttachment(PSGenerator gen,
PSExtensionAttachment attachment) throws IOException {
String info = "";
if (attachment instanceof PSSetupCode) {
PSSetupCode setupCodeAttach = (PSSetupCode)attachment;
String name = setupCodeAttach.getName();
if (name != null) {
info += ": (" + name + ")";
}
}
String type = attachment.getType();
gen.commentln("%FOPBegin" + type + info);
LineNumberReader reader = new LineNumberReader(
new java.io.StringReader(attachment.getContent()));
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.length() > 0) {
gen.writeln(line);
}
}
gen.commentln("%FOPEnd" + type);
}

/**
* Sets whether or not PostScript Document Structuring Conventions (DSC) compliance are
* enforced.
* <p>
* It can cause problems (unwanted PostScript subsystem initgraphics/erasepage calls)
* on some printers when the pagedevice is set. If this causes problems on a
* particular implementation then use this setting with a 'false' value to try and
* minimize the number of setpagedevice calls in the PostScript document output.
* <p>
* Set this value to false if you experience unwanted blank pages in your
* PostScript output.
* @param value boolean value (default is true)
*/
public void setSafeSetPageDevice(boolean value) {
this.safeSetPageDevice = value;
}

/**
* Indicates whether the "safe setpagedevice" mode is active.
* See {@code #setSafeSetPageDevice(boolean)} for more information.
* @return true if active
*/
public boolean isSafeSetPageDevice() {
return this.safeSetPageDevice;
}

/**
* Sets whether or not the safe set page device macro should be used
* (as opposed to directly invoking setpagedevice) when setting the
* PostScript page device.
* <p>
* This option is a useful option when you want to guard against the possibility
* of invalid/unsupported PostScript key/values being placed in the page device.
* <p>
* @param value setting to false and the renderer will make a
* standard "setpagedevice" call, setting to true will make a safe set page
* device macro call (default is false).
*/
public void setDSCComplianceEnabled(boolean value) {
this.dscCompliant = value;
}

public boolean isDSCComplianceEnabled() {
return this.dscCompliant;
}

/**
* Controls whether landscape pages should be rotated.
* @param value true to enable the rotation
*/
public void setAutoRotateLandscape(boolean value) {
this.autoRotateLandscape = value;
}

/**
* Indicates whether landscape pages are rotated.
* @return true if landscape pages are to be rotated
*/
public boolean isAutoRotateLandscape() {
return autoRotateLandscape;
}

/**
* Sets the PostScript language level.
* @param level the PostScript language level (Only 2 and 3 are currently supported)
*/
public void setLanguageLevel(int level) {
if (level == 2 || level == 3) {
this.languageLevel = level;
} else {
throw new IllegalArgumentException("Only language levels 2 or 3 are allowed/supported");
}
}

/**
* Indicates the selected PostScript language level.
* @return the PostScript language level
*/
public int getLanguageLevel() {
return languageLevel;
}

/**
* Controls whether PostScript resources are optimized in a second pass over the document.
* Enable this to obtain smaller PostScript files.
* @param value true to enable resource optimization
*/
public void setOptimizeResources(boolean value) {
this.optimizeResources = value;
}

/**
* Indicates whether PostScript resources are optimized in a second pass over the document.
* @return true if resource optimization is enabled
*/
public boolean isOptimizeResources() {
return optimizeResources;
}


}

+ 2
- 1
src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java View File

@@ -149,7 +149,8 @@ public class SVGDocumentHandler extends AbstractSVGDocumentHandler {
}

/** {@inheritDoc} */
public void startPage(int index, String name, Dimension size) throws IFException {
public void startPage(int index, String name, String pageMasterName, Dimension size)
throws IFException {
OutputStream out;
try {
if (index == 0) {

+ 2
- 1
src/sandbox/org/apache/fop/render/svg/SVGPrintDocumentHandler.java View File

@@ -111,7 +111,8 @@ public class SVGPrintDocumentHandler extends AbstractSVGDocumentHandler {
}

/** {@inheritDoc} */
public void startPage(int index, String name, Dimension size) throws IFException {
public void startPage(int index, String name, String pageMasterName, Dimension size)
throws IFException {
try {
AttributesImpl atts = new AttributesImpl();
/*

Loading…
Cancel
Save