Addition of an EPS transcoder git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@196990 13f79535-47bb-0310-9956-ffa450edef68pull/30/head
/* | |||||
* $Id$ | |||||
* ============================================================================ | |||||
* The Apache Software License, Version 1.1 | |||||
* ============================================================================ | |||||
* | |||||
* Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without modifica- | |||||
* tion, are permitted provided that the following conditions are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright notice, | |||||
* this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright notice, | |||||
* this list of conditions and the following disclaimer in the documentation | |||||
* and/or other materials provided with the distribution. | |||||
* | |||||
* 3. The end-user documentation included with the redistribution, if any, must | |||||
* include the following acknowledgment: "This product includes software | |||||
* developed by the Apache Software Foundation (http://www.apache.org/)." | |||||
* Alternately, this acknowledgment may appear in the software itself, if | |||||
* and wherever such third-party acknowledgments normally appear. | |||||
* | |||||
* 4. The names "FOP" and "Apache Software Foundation" must not be used to | |||||
* endorse or promote products derived from this software without prior | |||||
* written permission. For written permission, please contact | |||||
* apache@apache.org. | |||||
* | |||||
* 5. Products derived from this software may not be called "Apache", nor may | |||||
* "Apache" appear in their name, without prior written permission of the | |||||
* Apache Software Foundation. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, | |||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |||||
* APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- | |||||
* DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | |||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* ============================================================================ | |||||
* | |||||
* This software consists of voluntary contributions made by many individuals | |||||
* on behalf of the Apache Software Foundation and was originally created by | |||||
* James Tauber <jtauber@jtauber.com>. For more information on the Apache | |||||
* Software Foundation, please see <http://www.apache.org/>. | |||||
*/ | |||||
package org.apache.fop.render.ps; | |||||
//Java | |||||
import java.awt.Graphics; | |||||
import java.awt.Color; | |||||
import java.awt.Shape; | |||||
import java.awt.geom.AffineTransform; | |||||
import java.io.OutputStream; | |||||
import java.io.IOException; | |||||
//FOP | |||||
import org.apache.fop.apps.Document; | |||||
import org.apache.fop.fonts.Font; | |||||
import org.apache.fop.render.pdf.FontSetup; | |||||
/** | |||||
* This class is a wrapper for the <tt>PSGraphics2D</tt> that | |||||
* is used to create a full document around the PostScript rendering from | |||||
* <tt>PSGraphics2D</tt>. | |||||
* | |||||
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | |||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | |||||
* @version $Id$ | |||||
* @see org.apache.fop.render.ps.PSGraphics2D | |||||
*/ | |||||
public abstract class AbstractPSDocumentGraphics2D extends PSGraphics2D { | |||||
protected static final Integer ZERO = new Integer(0); | |||||
protected int width; | |||||
protected int height; | |||||
protected int pagecount; | |||||
protected boolean pagePending; | |||||
protected Shape initialClip; | |||||
protected AffineTransform initialTransform; | |||||
/** | |||||
* Create a new AbstractPSDocumentGraphics2D. | |||||
* This is used to create a new PostScript document, the height, | |||||
* width and output stream can be setup later. | |||||
* For use by the transcoder which needs font information | |||||
* for the bridge before the document size is known. | |||||
* The resulting document is written to the stream after rendering. | |||||
* | |||||
* @param textAsShapes set this to true so that text will be rendered | |||||
* using curves and not the font. | |||||
*/ | |||||
AbstractPSDocumentGraphics2D(boolean textAsShapes) { | |||||
super(textAsShapes); | |||||
if (!textAsShapes) { | |||||
this.document = new Document(null); | |||||
FontSetup.setup(this.document, null); | |||||
} | |||||
} | |||||
/** | |||||
* Setup the document. | |||||
* @param stream the output stream to write the document | |||||
* @param width the width of the page | |||||
* @param height the height of the page | |||||
* @throws IOException an io exception if there is a problem | |||||
* writing to the output stream | |||||
*/ | |||||
public void setupDocument(OutputStream stream, int width, int height) throws IOException { | |||||
this.width = width; | |||||
this.height = height; | |||||
this.pagecount = 0; | |||||
this.pagePending = false; | |||||
//Setup for PostScript generation | |||||
setPSGenerator(new PSGenerator(stream)); | |||||
writeFileHeader(); | |||||
} | |||||
protected abstract void writeFileHeader() throws IOException; | |||||
/** | |||||
* Create a new AbstractPSDocumentGraphics2D. | |||||
* This is used to create a new PostScript document of the given height | |||||
* and width. | |||||
* The resulting document is written to the stream after rendering. | |||||
* | |||||
* @param textAsShapes set this to true so that text will be rendered | |||||
* using curves and not the font. | |||||
* @param stream the stream that the final document should be written to. | |||||
* @param width the width of the document | |||||
* @param height the height of the document | |||||
* @throws IOException an io exception if there is a problem | |||||
* writing to the output stream | |||||
*/ | |||||
public AbstractPSDocumentGraphics2D(boolean textAsShapes, OutputStream stream, | |||||
int width, int height) throws IOException { | |||||
this(textAsShapes); | |||||
setupDocument(stream, width, height); | |||||
} | |||||
/** | |||||
* Get the context document. | |||||
* @return the context document | |||||
*/ | |||||
public Document getDocument() { | |||||
return this.document; | |||||
} | |||||
/** | |||||
* Set the dimensions of the SVG document that will be drawn. | |||||
* This is useful if the dimensions of the SVG document are different | |||||
* from the PostScript document that is to be created. | |||||
* The result is scaled so that the SVG fits correctly inside the | |||||
* PostScript document. | |||||
* @param w the width of the page | |||||
* @param h the height of the page | |||||
* @throws IOException in case of an I/O problem | |||||
*/ | |||||
public void setSVGDimension(float w, float h) throws IOException { | |||||
if (w != this.width || h != this.height) { | |||||
gen.concatMatrix(width / w, 0, 0, height / h, 0, 0); | |||||
} | |||||
} | |||||
/** | |||||
* Set the background of the PostScript document. | |||||
* This is used to set the background for the PostScript document | |||||
* Rather than leaving it as the default white. | |||||
* @param col the background colour to fill | |||||
*/ | |||||
public void setBackgroundColor(Color col) { | |||||
/**(todo) Implement this */ | |||||
/* | |||||
Color c = col; | |||||
PDFColor currentColour = new PDFColor(c.getRed(), c.getGreen(), c.getBlue()); | |||||
currentStream.write("q\n"); | |||||
currentStream.write(currentColour.getColorSpaceOut(true)); | |||||
currentStream.write("0 0 " + width + " " + height + " re\n"); | |||||
currentStream.write("f\n"); | |||||
currentStream.write("Q\n"); | |||||
*/ | |||||
} | |||||
public int getPageCount() { | |||||
return this.pagecount; | |||||
} | |||||
public void nextPage() throws IOException { | |||||
closePage(); | |||||
} | |||||
protected void closePage() throws IOException { | |||||
if (!this.pagePending) { | |||||
return; //ignore | |||||
} | |||||
//Finish page | |||||
writePageTrailer(); | |||||
this.pagePending = false; | |||||
} | |||||
/** | |||||
* Writes the page header for a page. | |||||
* @throws IOException In case an I/O error occurs | |||||
*/ | |||||
protected abstract void writePageHeader() throws IOException; | |||||
/** | |||||
* Writes the page trailer for a page. | |||||
* @throws IOException In case an I/O error occurs | |||||
*/ | |||||
protected abstract void writePageTrailer() throws IOException; | |||||
/** {@inheritDoc} */ | |||||
protected void preparePainting() { | |||||
if (this.pagePending) { | |||||
return; | |||||
} | |||||
try { | |||||
startPage(); | |||||
} catch (IOException ioe) { | |||||
handleIOException(ioe); | |||||
} | |||||
} | |||||
protected void startPage() throws IOException { | |||||
if (this.pagePending) { | |||||
throw new IllegalStateException("Close page first before starting another"); | |||||
} | |||||
//Start page | |||||
this.pagecount++; | |||||
if (this.initialTransform == null) { | |||||
//Save initial transformation matrix | |||||
this.initialTransform = getTransform(); | |||||
this.initialClip = getClip(); | |||||
} else { | |||||
//Reset transformation matrix | |||||
setTransform(this.initialTransform); | |||||
setClip(this.initialClip); | |||||
} | |||||
writePageHeader(); | |||||
gen.writeln("0.001 0.001 scale"); | |||||
gen.concatMatrix(1, 0, 0, -1, 0, this.height * 1000); | |||||
gen.writeDSCComment(DSCConstants.END_PAGE_SETUP); | |||||
this.pagePending = true; | |||||
} | |||||
/** | |||||
* The rendering process has finished. | |||||
* This should be called after the rendering has completed as there is | |||||
* no other indication it is complete. | |||||
* This will then write the results to the output stream. | |||||
* @throws IOException an io exception if there is a problem | |||||
* writing to the output stream | |||||
*/ | |||||
public void finish() throws IOException { | |||||
if (this.pagePending) { | |||||
closePage(); | |||||
} | |||||
//Finish document | |||||
gen.writeDSCComment(DSCConstants.TRAILER); | |||||
gen.writeDSCComment(DSCConstants.PAGES, new Integer(this.pagecount)); | |||||
gen.writeDSCComment(DSCConstants.EOF); | |||||
gen.flush(); | |||||
} | |||||
/** | |||||
* This constructor supports the create method | |||||
* @param g the PostScript document graphics to make a copy of | |||||
*/ | |||||
public AbstractPSDocumentGraphics2D(AbstractPSDocumentGraphics2D g) { | |||||
super(g); | |||||
} | |||||
} | |||||
/* | |||||
* $Id$ | |||||
* ============================================================================ | |||||
* The Apache Software License, Version 1.1 | |||||
* ============================================================================ | |||||
* | |||||
* Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without modifica- | |||||
* tion, are permitted provided that the following conditions are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright notice, | |||||
* this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright notice, | |||||
* this list of conditions and the following disclaimer in the documentation | |||||
* and/or other materials provided with the distribution. | |||||
* | |||||
* 3. The end-user documentation included with the redistribution, if any, must | |||||
* include the following acknowledgment: "This product includes software | |||||
* developed by the Apache Software Foundation (http://www.apache.org/)." | |||||
* Alternately, this acknowledgment may appear in the software itself, if | |||||
* and wherever such third-party acknowledgments normally appear. | |||||
* | |||||
* 4. The names "FOP" and "Apache Software Foundation" must not be used to | |||||
* endorse or promote products derived from this software without prior | |||||
* written permission. For written permission, please contact | |||||
* apache@apache.org. | |||||
* | |||||
* 5. Products derived from this software may not be called "Apache", nor may | |||||
* "Apache" appear in their name, without prior written permission of the | |||||
* Apache Software Foundation. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, | |||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |||||
* APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- | |||||
* DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | |||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* ============================================================================ | |||||
* | |||||
* This software consists of voluntary contributions made by many individuals | |||||
* on behalf of the Apache Software Foundation and was originally created by | |||||
* James Tauber <jtauber@jtauber.com>. For more information on the Apache | |||||
* Software Foundation, please see <http://www.apache.org/>. | |||||
*/ | |||||
package org.apache.fop.render.ps; | |||||
import java.awt.geom.AffineTransform; | |||||
import java.awt.geom.Rectangle2D; | |||||
import java.awt.Color; | |||||
import java.net.MalformedURLException; | |||||
import java.net.URL; | |||||
import java.io.IOException; | |||||
import org.apache.avalon.framework.configuration.Configuration; | |||||
import org.apache.avalon.framework.container.ContainerUtil; | |||||
import org.apache.batik.bridge.BridgeContext; | |||||
import org.apache.batik.bridge.BridgeException; | |||||
import org.apache.batik.bridge.GVTBuilder; | |||||
import org.apache.batik.bridge.ViewBox; | |||||
import org.apache.batik.dom.svg.SVGOMDocument; | |||||
import org.apache.batik.gvt.GraphicsNode; | |||||
import org.apache.batik.transcoder.TranscoderException; | |||||
import org.apache.batik.transcoder.TranscoderOutput; | |||||
import org.apache.batik.transcoder.image.resources.Messages; | |||||
import org.apache.batik.transcoder.image.ImageTranscoder; | |||||
import org.apache.fop.svg.AbstractFOPTranscoder; | |||||
import org.w3c.dom.Document; | |||||
import org.w3c.dom.svg.SVGDocument; | |||||
import org.w3c.dom.svg.SVGSVGElement; | |||||
/** | |||||
* This class enables to transcode an input to a PostScript document. | |||||
* | |||||
* <p>Two transcoding hints (<tt>KEY_WIDTH</tt> and | |||||
* <tt>KEY_HEIGHT</tt>) can be used to respectively specify the image | |||||
* width and the image height. If only one of these keys is specified, | |||||
* the transcoder preserves the aspect ratio of the original image. | |||||
* | |||||
* <p>The <tt>KEY_BACKGROUND_COLOR</tt> defines the background color | |||||
* to use for opaque image formats, or the background color that may | |||||
* be used for image formats that support alpha channel. | |||||
* | |||||
* <p>The <tt>KEY_AOI</tt> represents the area of interest to paint | |||||
* in device space. | |||||
* | |||||
* <p>Three additional transcoding hints that act on the SVG | |||||
* processor can be specified: | |||||
* | |||||
* <p><tt>KEY_LANGUAGE</tt> to set the default language to use (may be | |||||
* used by a <switch> SVG element for example), | |||||
* <tt>KEY_USER_STYLESHEET_URI</tt> to fix the URI of a user | |||||
* stylesheet, and <tt>KEY_PIXEL_TO_MM</tt> to specify the pixel to | |||||
* millimeter conversion factor. | |||||
* | |||||
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | |||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | |||||
* @version $Id$ | |||||
*/ | |||||
public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { | |||||
private Configuration cfg = null; | |||||
protected AbstractPSDocumentGraphics2D graphics = null; | |||||
/** | |||||
* Constructs a new <tt>AbstractPSTranscoder</tt>. | |||||
*/ | |||||
public AbstractPSTranscoder() { | |||||
super(); | |||||
} | |||||
protected abstract AbstractPSDocumentGraphics2D createDocumentGraphics2D(); | |||||
protected BridgeContext createBridgeContext() { | |||||
/*boolean stroke = true; | |||||
if (hints.containsKey(KEY_STROKE_TEXT)) { | |||||
stroke = ((Boolean)hints.get(KEY_STROKE_TEXT)).booleanValue(); | |||||
}*/ | |||||
BridgeContext ctx = new BridgeContext(userAgent); | |||||
PSTextPainter textPainter = new PSTextPainter(graphics.getDocument()); | |||||
ctx.setTextPainter(textPainter); | |||||
ctx.putBridge(new PSTextElementBridge(textPainter)); | |||||
//ctx.putBridge(new PSImageElementBridge()); | |||||
return ctx; | |||||
} | |||||
/** | |||||
* Transcodes the specified Document as an image in the specified output. | |||||
* | |||||
* @param document the document to transcode | |||||
* @param uri the uri of the document or null if any | |||||
* @param output the ouput where to transcode | |||||
* @exception TranscoderException if an error occured while transcoding | |||||
*/ | |||||
protected void transcode(Document document, String uri, | |||||
TranscoderOutput output) | |||||
throws TranscoderException { | |||||
graphics = createDocumentGraphics2D(); | |||||
ContainerUtil.enableLogging(graphics, getLogger()); | |||||
try { | |||||
if (this.cfg != null) { | |||||
ContainerUtil.configure(graphics, this.cfg); | |||||
} | |||||
ContainerUtil.initialize(graphics); | |||||
} catch (Exception e) { | |||||
throw new TranscoderException( | |||||
"Error while setting up PDFDocumentGraphics2D", e); | |||||
} | |||||
super.transcode(document, uri, output); | |||||
// prepare the image to be painted | |||||
int w = (int)(width + 0.5); | |||||
int h = (int)(height + 0.5); | |||||
try { | |||||
graphics.setupDocument(output.getOutputStream(), w, h); | |||||
graphics.setSVGDimension(width, height); | |||||
if (hints.containsKey(ImageTranscoder.KEY_BACKGROUND_COLOR)) { | |||||
graphics.setBackgroundColor | |||||
((Color)hints.get(ImageTranscoder.KEY_BACKGROUND_COLOR)); | |||||
} | |||||
graphics.setGraphicContext | |||||
(new org.apache.batik.ext.awt.g2d.GraphicContext()); | |||||
graphics.setTransform(curTxf); | |||||
this.root.paint(graphics); | |||||
graphics.finish(); | |||||
} catch (IOException ex) { | |||||
throw new TranscoderException(ex); | |||||
} | |||||
} | |||||
} |
/** Lead-in for a DSC-conformant PostScript file */ | /** Lead-in for a DSC-conformant PostScript file */ | ||||
public static final String PS_ADOBE_30 = "%!PS-Adobe-3.0"; | public static final String PS_ADOBE_30 = "%!PS-Adobe-3.0"; | ||||
/** Lead-in for an EPS file */ | |||||
public static final String EPSF_30 = "EPSF-3.0"; | |||||
/** Bounding box for the document */ | /** Bounding box for the document */ | ||||
public static final String BBOX = "BoundingBox"; | public static final String BBOX = "BoundingBox"; | ||||
/** High-resolution bounding box for the document */ | /** High-resolution bounding box for the document */ |
/* | |||||
* $Id$ | |||||
* ============================================================================ | |||||
* The Apache Software License, Version 1.1 | |||||
* ============================================================================ | |||||
* | |||||
* Copyright (C) 2003 The Apache Software Foundation. All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without modifica- | |||||
* tion, are permitted provided that the following conditions are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright notice, | |||||
* this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright notice, | |||||
* this list of conditions and the following disclaimer in the documentation | |||||
* and/or other materials provided with the distribution. | |||||
* | |||||
* 3. The end-user documentation included with the redistribution, if any, must | |||||
* include the following acknowledgment: "This product includes software | |||||
* developed by the Apache Software Foundation (http://www.apache.org/)." | |||||
* Alternately, this acknowledgment may appear in the software itself, if | |||||
* and wherever such third-party acknowledgments normally appear. | |||||
* | |||||
* 4. The names "FOP" and "Apache Software Foundation" must not be used to | |||||
* endorse or promote products derived from this software without prior | |||||
* written permission. For written permission, please contact | |||||
* apache@apache.org. | |||||
* | |||||
* 5. Products derived from this software may not be called "Apache", nor may | |||||
* "Apache" appear in their name, without prior written permission of the | |||||
* Apache Software Foundation. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, | |||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |||||
* APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- | |||||
* DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | |||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* ============================================================================ | |||||
* | |||||
* This software consists of voluntary contributions made by many individuals | |||||
* on behalf of the Apache Software Foundation and was originally created by | |||||
* James Tauber <jtauber@jtauber.com>. For more information on the Apache | |||||
* Software Foundation, please see <http://www.apache.org/>. | |||||
*/ | |||||
package org.apache.fop.render.ps; | |||||
import java.io.IOException; | |||||
/** | |||||
* This class is a wrapper for the <tt>AbstractPSDocumentGraphics2D</tt> that | |||||
* is used to create EPS (Encapsulated PostScript) files instead of PS file. | |||||
* | |||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | |||||
* @version $Id$ | |||||
* @see org.apache.fop.render.ps.PSGraphics2D | |||||
* @see org.apache.fop.render.ps.AbstractPSDocumentGraphics2D | |||||
*/ | |||||
public class EPSDocumentGraphics2D extends AbstractPSDocumentGraphics2D { | |||||
/** | |||||
* Create a new EPSDocumentGraphics2D. | |||||
* This is used to create a new EPS document, the height, | |||||
* width and output stream can be setup later. | |||||
* For use by the transcoder which needs font information | |||||
* for the bridge before the document size is known. | |||||
* The resulting document is written to the stream after rendering. | |||||
* | |||||
* @param textAsShapes set this to true so that text will be rendered | |||||
* using curves and not the font. | |||||
*/ | |||||
public EPSDocumentGraphics2D(boolean textAsShapes) { | |||||
super(textAsShapes); | |||||
} | |||||
protected void writeFileHeader() throws IOException { | |||||
final Long pagewidth = new Long(this.width); | |||||
final Long pageheight = new Long(this.height); | |||||
//PostScript Header | |||||
gen.writeln(DSCConstants.PS_ADOBE_30 + " " + DSCConstants.EPSF_30); | |||||
gen.writeDSCComment(DSCConstants.CREATOR, | |||||
new String[] {"FOP EPS Transcoder for SVG"}); | |||||
gen.writeDSCComment(DSCConstants.CREATION_DATE, | |||||
new Object[] {new java.util.Date()}); | |||||
gen.writeDSCComment(DSCConstants.PAGES, new Integer(0)); | |||||
gen.writeDSCComment(DSCConstants.BBOX, new Object[] | |||||
{ZERO, ZERO, pagewidth, pageheight}); | |||||
gen.writeDSCComment(DSCConstants.LANGUAGE_LEVEL, new Integer(2)); | |||||
gen.writeDSCComment(DSCConstants.END_COMMENTS); | |||||
//Prolog | |||||
gen.writeDSCComment(DSCConstants.BEGIN_PROLOG); | |||||
PSProcSets.writeFOPStdProcSet(gen); | |||||
PSProcSets.writeFOPEPSProcSet(gen); | |||||
if (document != null) { | |||||
PSProcSets.writeFontDict(gen, document); | |||||
} | |||||
gen.writeDSCComment(DSCConstants.END_PROLOG); | |||||
} | |||||
protected void writePageHeader() throws IOException { | |||||
Integer pageNumber = new Integer(this.pagecount); | |||||
gen.writeDSCComment(DSCConstants.PAGE, new Object[] | |||||
{pageNumber.toString(), pageNumber}); | |||||
gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] | |||||
{ZERO, ZERO, new Integer(width), new Integer(height)}); | |||||
gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP); | |||||
if (this.document != null) { | |||||
gen.writeln("FOPFonts begin"); | |||||
} | |||||
} | |||||
protected void writePageTrailer() throws IOException { | |||||
gen.writeDSCComment(DSCConstants.PAGE_TRAILER); | |||||
gen.writeDSCComment(DSCConstants.END_PAGE); | |||||
} | |||||
} |
/* | |||||
* $Id$ | |||||
* ============================================================================ | |||||
* The Apache Software License, Version 1.1 | |||||
* ============================================================================ | |||||
* | |||||
* Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without modifica- | |||||
* tion, are permitted provided that the following conditions are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright notice, | |||||
* this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright notice, | |||||
* this list of conditions and the following disclaimer in the documentation | |||||
* and/or other materials provided with the distribution. | |||||
* | |||||
* 3. The end-user documentation included with the redistribution, if any, must | |||||
* include the following acknowledgment: "This product includes software | |||||
* developed by the Apache Software Foundation (http://www.apache.org/)." | |||||
* Alternately, this acknowledgment may appear in the software itself, if | |||||
* and wherever such third-party acknowledgments normally appear. | |||||
* | |||||
* 4. The names "FOP" and "Apache Software Foundation" must not be used to | |||||
* endorse or promote products derived from this software without prior | |||||
* written permission. For written permission, please contact | |||||
* apache@apache.org. | |||||
* | |||||
* 5. Products derived from this software may not be called "Apache", nor may | |||||
* "Apache" appear in their name, without prior written permission of the | |||||
* Apache Software Foundation. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, | |||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |||||
* APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- | |||||
* DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | |||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* ============================================================================ | |||||
* | |||||
* This software consists of voluntary contributions made by many individuals | |||||
* on behalf of the Apache Software Foundation and was originally created by | |||||
* James Tauber <jtauber@jtauber.com>. For more information on the Apache | |||||
* Software Foundation, please see <http://www.apache.org/>. | |||||
*/ | |||||
package org.apache.fop.render.ps; | |||||
/** | |||||
* This class enables to transcode an input to a EPS document. | |||||
* | |||||
* <p>Two transcoding hints (<tt>KEY_WIDTH</tt> and | |||||
* <tt>KEY_HEIGHT</tt>) can be used to respectively specify the image | |||||
* width and the image height. If only one of these keys is specified, | |||||
* the transcoder preserves the aspect ratio of the original image. | |||||
* | |||||
* <p>The <tt>KEY_BACKGROUND_COLOR</tt> defines the background color | |||||
* to use for opaque image formats, or the background color that may | |||||
* be used for image formats that support alpha channel. | |||||
* | |||||
* <p>The <tt>KEY_AOI</tt> represents the area of interest to paint | |||||
* in device space. | |||||
* | |||||
* <p>Three additional transcoding hints that act on the SVG | |||||
* processor can be specified: | |||||
* | |||||
* <p><tt>KEY_LANGUAGE</tt> to set the default language to use (may be | |||||
* used by a <switch> SVG element for example), | |||||
* <tt>KEY_USER_STYLESHEET_URI</tt> to fix the URI of a user | |||||
* stylesheet, and <tt>KEY_PIXEL_TO_MM</tt> to specify the pixel to | |||||
* millimeter conversion factor. | |||||
* | |||||
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | |||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | |||||
* @version $Id$ | |||||
*/ | |||||
public class EPSTranscoder extends AbstractPSTranscoder { | |||||
/** | |||||
* Constructs a new <tt>EPSPSTranscoder</tt>. | |||||
*/ | |||||
public EPSTranscoder() { | |||||
super(); | |||||
} | |||||
protected AbstractPSDocumentGraphics2D createDocumentGraphics2D() { | |||||
return new EPSDocumentGraphics2D(false); | |||||
} | |||||
} |
/* | /* | ||||
* $Id: PDFDocumentGraphics2D.java,v 1.27 2003/03/07 09:51:26 jeremias Exp $ | |||||
* $Id$ | |||||
* ============================================================================ | * ============================================================================ | ||||
* The Apache Software License, Version 1.1 | * The Apache Software License, Version 1.1 | ||||
* ============================================================================ | * ============================================================================ | ||||
//Java | //Java | ||||
import java.awt.Graphics; | import java.awt.Graphics; | ||||
import java.awt.Font; | |||||
import java.awt.Color; | |||||
import java.awt.Shape; | |||||
import java.awt.font.FontRenderContext; | |||||
import java.awt.font.GlyphVector; | |||||
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
//FOP | //FOP | ||||
import org.apache.fop.render.pdf.FontSetup; | |||||
import org.apache.fop.apps.Document; | import org.apache.fop.apps.Document; | ||||
import org.apache.fop.render.pdf.FontSetup; | |||||
/** | /** | ||||
* This class is a wrapper for the <tt>PSGraphics2D</tt> that | * This class is a wrapper for the <tt>PSGraphics2D</tt> that | ||||
* | * | ||||
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | ||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | ||||
* @version $Id: PDFDocumentGraphics2D.java,v 1.27 2003/03/07 09:51:26 jeremias Exp $ | |||||
* @version $Id$ | |||||
* @see org.apache.fop.render.ps.PSGraphics2D | * @see org.apache.fop.render.ps.PSGraphics2D | ||||
*/ | */ | ||||
public class PSDocumentGraphics2D extends PSGraphics2D { | |||||
private int width; | |||||
private int height; | |||||
public class PSDocumentGraphics2D extends AbstractPSDocumentGraphics2D { | |||||
/** | /** | ||||
* Create a new PSDocumentGraphics2D. | |||||
* Create a new AbstractPSDocumentGraphics2D. | |||||
* This is used to create a new PostScript document, the height, | * This is used to create a new PostScript document, the height, | ||||
* width and output stream can be setup later. | * width and output stream can be setup later. | ||||
* For use by the transcoder which needs font information | * For use by the transcoder which needs font information | ||||
super(textAsShapes); | super(textAsShapes); | ||||
if (!textAsShapes) { | if (!textAsShapes) { | ||||
fontInfo = new Document(null); | |||||
FontSetup.setup(fontInfo, null); | |||||
//FontState fontState = new FontState("Helvetica", "normal", | |||||
// FontInfo.NORMAL, 12, 0); | |||||
this.document = new Document(null); | |||||
FontSetup.setup(this.document, null); | |||||
} | } | ||||
currentFontName = ""; | |||||
currentFontSize = 0; | |||||
} | } | ||||
/** | /** | ||||
* Setup the document. | |||||
* @param stream the output stream to write the document | |||||
* @param width the width of the page | |||||
* @param height the height of the page | |||||
* Create a new AbstractPSDocumentGraphics2D. | |||||
* This is used to create a new PostScript document of the given height | |||||
* and width. | |||||
* The resulting document is written to the stream after rendering. | |||||
* | |||||
* @param textAsShapes set this to true so that text will be rendered | |||||
* using curves and not the font. | |||||
* @param stream the stream that the final document should be written to. | |||||
* @param width the width of the document | |||||
* @param height the height of the document | |||||
* @throws IOException an io exception if there is a problem | * @throws IOException an io exception if there is a problem | ||||
* writing to the output stream | * writing to the output stream | ||||
*/ | */ | ||||
public void setupDocument(OutputStream stream, int width, int height) throws IOException { | |||||
this.width = width; | |||||
this.height = height; | |||||
public PSDocumentGraphics2D(boolean textAsShapes, OutputStream stream, | |||||
int width, int height) throws IOException { | |||||
this(textAsShapes); | |||||
setupDocument(stream, width, height); | |||||
} | |||||
final Integer zero = new Integer(0); | |||||
public void nextPage() throws IOException { | |||||
closePage(); | |||||
} | |||||
protected void writeFileHeader() throws IOException { | |||||
final Long pagewidth = new Long(this.width); | final Long pagewidth = new Long(this.width); | ||||
final Long pageheight = new Long(this.height); | final Long pageheight = new Long(this.height); | ||||
//Setup for PostScript generation | |||||
setPSGenerator(new PSGenerator(stream)); | |||||
//PostScript Header | //PostScript Header | ||||
gen.writeln(DSCConstants.PS_ADOBE_30); | gen.writeln(DSCConstants.PS_ADOBE_30); | ||||
gen.writeDSCComment(DSCConstants.CREATOR, | gen.writeDSCComment(DSCConstants.CREATOR, | ||||
new String[] {"FOP PostScript Transcoder for SVG"}); | new String[] {"FOP PostScript Transcoder for SVG"}); | ||||
gen.writeDSCComment(DSCConstants.CREATION_DATE, | gen.writeDSCComment(DSCConstants.CREATION_DATE, | ||||
new Object[] {new java.util.Date()}); | new Object[] {new java.util.Date()}); | ||||
gen.writeDSCComment(DSCConstants.PAGES, new Object[] {new Integer(1)}); | |||||
gen.writeDSCComment(DSCConstants.PAGES, PSGenerator.ATEND); | |||||
gen.writeDSCComment(DSCConstants.BBOX, new Object[] | gen.writeDSCComment(DSCConstants.BBOX, new Object[] | ||||
{zero, zero, pagewidth, pageheight}); | |||||
{ZERO, ZERO, pagewidth, pageheight}); | |||||
gen.writeDSCComment(DSCConstants.END_COMMENTS); | gen.writeDSCComment(DSCConstants.END_COMMENTS); | ||||
//Defaults | //Defaults | ||||
gen.writeDSCComment(DSCConstants.BEGIN_DEFAULTS); | gen.writeDSCComment(DSCConstants.BEGIN_DEFAULTS); | ||||
gen.writeDSCComment(DSCConstants.END_DEFAULTS); | gen.writeDSCComment(DSCConstants.END_DEFAULTS); | ||||
//Prolog | //Prolog | ||||
gen.writeDSCComment(DSCConstants.BEGIN_PROLOG); | gen.writeDSCComment(DSCConstants.BEGIN_PROLOG); | ||||
gen.writeDSCComment(DSCConstants.END_PROLOG); | gen.writeDSCComment(DSCConstants.END_PROLOG); | ||||
//Setup | //Setup | ||||
gen.writeDSCComment(DSCConstants.BEGIN_SETUP); | gen.writeDSCComment(DSCConstants.BEGIN_SETUP); | ||||
PSProcSets.writeFOPStdProcSet(gen); | PSProcSets.writeFOPStdProcSet(gen); | ||||
PSProcSets.writeFOPEPSProcSet(gen); | PSProcSets.writeFOPEPSProcSet(gen); | ||||
PSProcSets.writeFontDict(gen, fontInfo); | |||||
if (document != null) { | |||||
PSProcSets.writeFontDict(gen, document); | |||||
} | |||||
gen.writeDSCComment(DSCConstants.END_SETUP); | gen.writeDSCComment(DSCConstants.END_SETUP); | ||||
} | |||||
//Start page | |||||
Integer pageNumber = new Integer(1); | |||||
gen.writeDSCComment(DSCConstants.PAGE, new Object[] | |||||
protected void writePageHeader() throws IOException { | |||||
Integer pageNumber = new Integer(this.pagecount); | |||||
gen.writeDSCComment(DSCConstants.PAGE, new Object[] | |||||
{pageNumber.toString(), pageNumber}); | {pageNumber.toString(), pageNumber}); | ||||
gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] | gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] | ||||
{zero, zero, pagewidth, pageheight}); | |||||
{ZERO, ZERO, new Integer(width), new Integer(height)}); | |||||
gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP); | gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP); | ||||
gen.writeln("FOPFonts begin"); | |||||
gen.writeln("0.001 0.001 scale"); | |||||
gen.concatMatrix(1, 0, 0, -1, 0, pageheight.doubleValue() * 1000); | |||||
gen.writeDSCComment(DSCConstants.END_PAGE_SETUP); | |||||
} | |||||
/** | |||||
* Create a new PSDocumentGraphics2D. | |||||
* This is used to create a new PostScript document of the given height | |||||
* and width. | |||||
* The resulting document is written to the stream after rendering. | |||||
* | |||||
* @param textAsShapes set this to true so that text will be rendered | |||||
* using curves and not the font. | |||||
* @param stream the stream that the final document should be written to. | |||||
* @param width the width of the document | |||||
* @param height the height of the document | |||||
* @throws IOException an io exception if there is a problem | |||||
* writing to the output stream | |||||
*/ | |||||
public PSDocumentGraphics2D(boolean textAsShapes, OutputStream stream, | |||||
int width, int height) throws IOException { | |||||
this(textAsShapes); | |||||
setupDocument(stream, width, height); | |||||
} | |||||
/** | |||||
* Get the font info for this PostScript document. | |||||
* @return the font information | |||||
*/ | |||||
public Document getFontInfo() { | |||||
return fontInfo; | |||||
} | |||||
/** | |||||
* Set the dimensions of the SVG document that will be drawn. | |||||
* This is useful if the dimensions of the SVG document are different | |||||
* from the PostScript document that is to be created. | |||||
* The result is scaled so that the SVG fits correctly inside the | |||||
* PostScript document. | |||||
* @param w the width of the page | |||||
* @param h the height of the page | |||||
* @throws IOException in case of an I/O problem | |||||
*/ | |||||
public void setSVGDimension(float w, float h) throws IOException { | |||||
gen.concatMatrix(width / w, 0, 0, height / h, 0, 0); | |||||
} | |||||
/** | |||||
* Set the background of the PostScript document. | |||||
* This is used to set the background for the PostScript document | |||||
* Rather than leaving it as the default white. | |||||
* @param col the background colour to fill | |||||
*/ | |||||
public void setBackgroundColor(Color col) { | |||||
/**(todo) Implement this */ | |||||
/* | |||||
Color c = col; | |||||
PDFColor currentColour = new PDFColor(c.getRed(), c.getGreen(), c.getBlue()); | |||||
currentStream.write("q\n"); | |||||
currentStream.write(currentColour.getColorSpaceOut(true)); | |||||
currentStream.write("0 0 " + width + " " + height + " re\n"); | |||||
currentStream.write("f\n"); | |||||
currentStream.write("Q\n"); | |||||
*/ | |||||
gen.writeln("<<"); | |||||
gen.writeln("/PageSize [" + width + " " + height + "]"); | |||||
gen.writeln("/ImagingBBox null"); | |||||
gen.writeln(">> setpagedevice"); | |||||
if (this.document != null) { | |||||
gen.writeln("FOPFonts begin"); | |||||
} | |||||
} | } | ||||
/** | |||||
* The rendering process has finished. | |||||
* This should be called after the rendering has completed as there is | |||||
* no other indication it is complete. | |||||
* This will then write the results to the output stream. | |||||
* @throws IOException an io exception if there is a problem | |||||
* writing to the output stream | |||||
*/ | |||||
public void finish() throws IOException { | |||||
//Finish page | |||||
gen.writeln("showpage"); | |||||
protected void writePageTrailer() throws IOException { | |||||
gen.writeln("showpage"); | |||||
gen.writeDSCComment(DSCConstants.PAGE_TRAILER); | gen.writeDSCComment(DSCConstants.PAGE_TRAILER); | ||||
gen.writeDSCComment(DSCConstants.END_PAGE); | gen.writeDSCComment(DSCConstants.END_PAGE); | ||||
//Finish document | |||||
gen.writeDSCComment(DSCConstants.TRAILER); | |||||
gen.writeDSCComment(DSCConstants.EOF); | |||||
gen.flush(); | |||||
} | } | ||||
/** | /** | ||||
* This constructor supports the create method | * This constructor supports the create method | ||||
* @param g the PostScript document graphics to make a copy of | * @param g the PostScript document graphics to make a copy of | ||||
return new PSDocumentGraphics2D(this); | return new PSDocumentGraphics2D(this); | ||||
} | } | ||||
/** | |||||
* Draw a string to the PostScript document. | |||||
* This either draws the string directly or if drawing text as | |||||
* shapes it converts the string into shapes and draws that. | |||||
* @param s the string to draw | |||||
* @param x the x position | |||||
* @param y the y position | |||||
*/ | |||||
public void drawString(String s, float x, float y) { | |||||
if (super.textAsShapes) { | |||||
Font font = super.getFont(); | |||||
FontRenderContext frc = super.getFontRenderContext(); | |||||
GlyphVector gv = font.createGlyphVector(frc, s); | |||||
Shape glyphOutline = gv.getOutline(x, y); | |||||
super.fill(glyphOutline); | |||||
} else { | |||||
super.drawString(s, x, y); | |||||
} | |||||
} | |||||
} | } | ||||
*/ | */ | ||||
package org.apache.fop.render.ps; | package org.apache.fop.render.ps; | ||||
import java.awt.geom.AffineTransform; | |||||
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.text.DateFormat; | import java.text.DateFormat; | ||||
import java.text.DecimalFormat; | import java.text.DecimalFormat; | ||||
import java.text.NumberFormat; | |||||
import java.util.Date; | import java.util.Date; | ||||
import java.util.Stack; | import java.util.Stack; | ||||
* Indicator for the PostScript interpreter that the value is provided | * Indicator for the PostScript interpreter that the value is provided | ||||
* later in the document (mostly in the %%Trailer section). | * later in the document (mostly in the %%Trailer section). | ||||
*/ | */ | ||||
public static final AtendIndicator ATEND = new AtendIndicator() {}; | |||||
public static final AtendIndicator ATEND = new AtendIndicator() { | |||||
}; | |||||
private OutputStream out; | private OutputStream out; | ||||
private boolean commentsEnabled = true; | |||||
private Stack graphicsStateStack = new Stack(); | private Stack graphicsStateStack = new Stack(); | ||||
private PSState currentState; | private PSState currentState; | ||||
private DecimalFormat df = new DecimalFormat("0.000"); | |||||
private DecimalFormat df3 = new DecimalFormat("0.000"); | |||||
private DecimalFormat df1 = new DecimalFormat("0.#"); | |||||
private DecimalFormat df5 = new DecimalFormat("0.#####"); | |||||
private StringBuffer tempBuffer = new StringBuffer(256); | private StringBuffer tempBuffer = new StringBuffer(256); | ||||
this.currentState = new PSState(); | this.currentState = new PSState(); | ||||
this.graphicsStateStack.push(this.currentState); | this.graphicsStateStack.push(this.currentState); | ||||
} | } | ||||
/** | |||||
* Returns the OutputStream the PSGenerator writes to. | |||||
* @return the OutputStream | |||||
*/ | |||||
public OutputStream getOutputStream() { | |||||
return this.out; | |||||
} | |||||
/** | /** | ||||
* Writes a newline character to the OutputStream. | * Writes a newline character to the OutputStream. | ||||
* @return the formatted value | * @return the formatted value | ||||
*/ | */ | ||||
public String formatDouble(double value) { | public String formatDouble(double value) { | ||||
NumberFormat nf = new java.text.DecimalFormat("0.#"); | |||||
return nf.format(value); | |||||
return df1.format(value); | |||||
} | |||||
/** | |||||
* Formats a double value for PostScript output (higher resolution). | |||||
* | |||||
* @param value value to format | |||||
* @return the formatted value | |||||
*/ | |||||
public String formatDouble5(double value) { | |||||
return df5.format(value); | |||||
} | } | ||||
/** | /** | ||||
newLine(); | newLine(); | ||||
} | } | ||||
public void commentln(String comment) throws IOException { | |||||
if (this.commentsEnabled) { | |||||
writeln(comment); | |||||
} | |||||
} | |||||
/** | /** | ||||
* Writes encoded data to the PostScript stream. | * Writes encoded data to the PostScript stream. | ||||
* | * | ||||
} else if (params[i] instanceof AtendIndicator) { | } else if (params[i] instanceof AtendIndicator) { | ||||
tempBuffer.append("(atend)"); | tempBuffer.append("(atend)"); | ||||
} else if (params[i] instanceof Double) { | } else if (params[i] instanceof Double) { | ||||
tempBuffer.append(df.format(params[i])); | |||||
tempBuffer.append(df3.format(params[i])); | |||||
} else if (params[i] instanceof Number) { | } else if (params[i] instanceof Number) { | ||||
tempBuffer.append(params[i].toString()); | tempBuffer.append(params[i].toString()); | ||||
} else if (params[i] instanceof Date) { | } 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]))); | |||||
DateFormat datef = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); | |||||
tempBuffer.append(convertStringToDSC(datef.format((Date)params[i]))); | |||||
} else { | } else { | ||||
throw new IllegalArgumentException("Unsupported parameter type: " | throw new IllegalArgumentException("Unsupported parameter type: " | ||||
+ params[i].getClass().getName()); | + params[i].getClass().getName()); | ||||
public void concatMatrix(double a, double b, | public void concatMatrix(double a, double b, | ||||
double c, double d, | double c, double d, | ||||
double e, double f) throws IOException { | double e, double f) throws IOException { | ||||
writeln("[" + formatDouble(a) + " " | |||||
+ formatDouble(b) + " " | |||||
+ formatDouble(c) + " " | |||||
+ formatDouble(d) + " " | |||||
+ formatDouble(e) + " " | |||||
+ formatDouble(f) + "] concat"); | |||||
writeln("[" + formatDouble5(a) + " " | |||||
+ formatDouble5(b) + " " | |||||
+ formatDouble5(c) + " " | |||||
+ formatDouble5(d) + " " | |||||
+ formatDouble5(e) + " " | |||||
+ formatDouble5(f) + "] concat"); | |||||
} | } | ||||
/** | /** | ||||
matrix[4], matrix[5]); | matrix[4], matrix[5]); | ||||
} | } | ||||
/** | |||||
* Concats the transformations matric. | |||||
* @param at the AffineTransform whose matrix to use | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void concatMatrix(AffineTransform at) throws IOException { | |||||
double[] matrix = new double[6]; | |||||
at.getMatrix(matrix); | |||||
concatMatrix(matrix); | |||||
} | |||||
/** | |||||
* Adds a rectangle to the current path. | |||||
* @param x upper left corner | |||||
* @param y upper left corner | |||||
* @param w width | |||||
* @param h height | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void defineRect(double x, double y, double w, double h) | |||||
throws IOException { | |||||
writeln(formatDouble(x) | |||||
+ " " + formatDouble(y) | |||||
+ " " + formatDouble(w) | |||||
+ " " + formatDouble(h) | |||||
+ " re"); | |||||
} | |||||
/** | /** | ||||
* Returns the current graphics state. | * Returns the current graphics state. | ||||
* @return the current graphics state | * @return the current graphics state |
gen.writeln("/M/moveto ld"); | gen.writeln("/M/moveto ld"); | ||||
gen.writeln("/RM/rmoveto ld"); | gen.writeln("/RM/rmoveto ld"); | ||||
gen.writeln("/t/show ld"); | gen.writeln("/t/show ld"); | ||||
gen.writeln("/A/ashow ld"); | |||||
gen.writeln("/cp/closepath ld"); | |||||
gen.writeln("/re {4 2 roll M"); //define rectangle | |||||
gen.writeln("1 index 0 rlineto"); | |||||
gen.writeln("0 exch rlineto"); | |||||
gen.writeln("neg 0 rlineto"); | |||||
gen.writeln("cp } bd"); | |||||
gen.writeln("/_ctm matrix def"); //Holds the current matrix | gen.writeln("/_ctm matrix def"); //Holds the current matrix | ||||
gen.writeln("/_tm matrix def"); | gen.writeln("/_tm matrix def"); |
/** | /** | ||||
* Set up the font info | * Set up the font info | ||||
* | * | ||||
* @param fontInfo the font info object to set up | |||||
* @param foTreeControl the font info object to set up | |||||
*/ | */ | ||||
public void setupFontInfo(FOTreeControl foTreeControl) { | public void setupFontInfo(FOTreeControl foTreeControl) { | ||||
/* use PDF's font setup to get PDF metrics */ | /* use PDF's font setup to get PDF metrics */ | ||||
org.apache.fop.render.pdf.FontSetup.setup((Document)foTreeControl, null); | org.apache.fop.render.pdf.FontSetup.setup((Document)foTreeControl, null); | ||||
// TODO: what's this? | |||||
this.fontInfo = fontInfo; | |||||
this.fontInfo = (Document)foTreeControl; | |||||
} | } | ||||
/** | /** | ||||
* @param h height | * @param h height | ||||
* @param col color to fill with | * @param col color to fill with | ||||
*/ | */ | ||||
protected void fillRect(int x, int y, int w, int h, | |||||
protected void fillRect(float x, float y, float w, float h, | |||||
ColorType col) { | ColorType col) { | ||||
useColor(col); | useColor(col); | ||||
writeln(x + " " + y + " " + w + " " + h + " rectfill"); | |||||
writeln(gen.formatDouble(x) | |||||
+ " " + gen.formatDouble(y) | |||||
+ " " + gen.formatDouble(w) | |||||
+ " " + gen.formatDouble(h) | |||||
+ " rectfill"); | |||||
} | } | ||||
/** | /** | ||||
* @param w width | * @param w width | ||||
* @param h height | * @param h height | ||||
*/ | */ | ||||
protected void drawRect(int x, int y, int w, int h) { | |||||
writeln(x + " " + y + " " + w + " " + h + " rectstroke"); | |||||
protected void drawRect(float x, float y, float w, float h) { | |||||
writeln(gen.formatDouble(x) | |||||
+ " " + gen.formatDouble(y) | |||||
+ " " + gen.formatDouble(w) | |||||
+ " " + gen.formatDouble(h) | |||||
+ " rectstroke"); | |||||
} | } | ||||
/** | /** | ||||
private void useColor(float red, float green, float blue) { | private void useColor(float red, float green, float blue) { | ||||
if ((red != currRed) || (green != currGreen) || (blue != currBlue)) { | if ((red != currRed) || (green != currGreen) || (blue != currBlue)) { | ||||
writeln(red + " " + green + " " + blue + " setrgbcolor"); | |||||
writeln(gen.formatDouble(red) | |||||
+ " " + gen.formatDouble(green) | |||||
+ " " + gen.formatDouble(blue) | |||||
+ " setrgbcolor"); | |||||
currRed = red; | currRed = red; | ||||
currGreen = green; | currGreen = green; | ||||
currBlue = blue; | currBlue = blue; | ||||
int bl = currentBPPosition + area.getOffset(); | int bl = currentBPPosition + area.getOffset(); | ||||
useFont(fontname, fontsize); | useFont(fontname, fontsize); | ||||
ColorType ct = (ColorType)area.getTrait(Trait.COLOR); | |||||
if (ct != null) { | |||||
useColor(ct); | |||||
} | |||||
paintText(rx, bl, area.getTextArea(), f); | paintText(rx, bl, area.getTextArea(), f); | ||||
/* | /* | ||||
//saveGraphicsState(); | //saveGraphicsState(); | ||||
if (back.getColor() != null) { | if (back.getColor() != null) { | ||||
updateColor(back.getColor(), true, null); | |||||
writeln(startx + " " + starty + " " | |||||
+ width + " " + height + " rectfill"); | |||||
fillRect(startx, starty, width, height, back.getColor()); | |||||
} | } | ||||
if (back.getURL() != null) { | if (back.getURL() != null) { | ||||
ImageFactory fact = ImageFactory.getInstance(); | ImageFactory fact = ImageFactory.getInstance(); | ||||
} | } | ||||
float bwidth = bps.width; | float bwidth = bps.width; | ||||
updateColor(bps.color, false, null); | |||||
useColor(bps.color); | |||||
writeln(bwidth + " setlinewidth"); | writeln(bwidth + " setlinewidth"); | ||||
drawLine(startx, starty + bwidth / 2, endx, starty + bwidth / 2); | drawLine(startx, starty + bwidth / 2, endx, starty + bwidth / 2); | ||||
} | } | ||||
float bwidth = bps.width; | float bwidth = bps.width; | ||||
updateColor(bps.color, false, null); | |||||
useColor(bps.color); | |||||
writeln(bwidth + " setlinewidth"); | writeln(bwidth + " setlinewidth"); | ||||
drawLine(startx + bwidth / 2, starty, startx + bwidth / 2, endy); | drawLine(startx + bwidth / 2, starty, startx + bwidth / 2, endy); | ||||
} | } | ||||
float bwidth = bps.width; | float bwidth = bps.width; | ||||
updateColor(bps.color, false, null); | |||||
useColor(bps.color); | |||||
writeln(bwidth + " setlinewidth"); | writeln(bwidth + " setlinewidth"); | ||||
drawLine(startx, sy - bwidth / 2, endx, sy - bwidth / 2); | drawLine(startx, sy - bwidth / 2, endx, sy - bwidth / 2); | ||||
} | } | ||||
float bwidth = bps.width; | float bwidth = bps.width; | ||||
updateColor(bps.color, false, null); | |||||
useColor(bps.color); | |||||
writeln(bwidth + " setlinewidth"); | writeln(bwidth + " setlinewidth"); | ||||
drawLine(sx - bwidth / 2, starty, sx - bwidth / 2, endy); | drawLine(sx - bwidth / 2, starty, sx - bwidth / 2, endy); | ||||
} | } | ||||
writeln(startx + " " + starty + " M "); | writeln(startx + " " + starty + " M "); | ||||
writeln(endx + " " + endy + " lineto"); | writeln(endx + " " + endy + " lineto"); | ||||
} | } | ||||
private void updateColor(ColorType col, boolean fill, StringBuffer pdf) { | |||||
writeln(gen.formatDouble(col.getRed()) + " " | |||||
+ gen.formatDouble(col.getGreen()) + " " | |||||
+ gen.formatDouble(col.getBlue()) + " setrgbcolor"); | |||||
} | |||||
/** | /** | ||||
* @see org.apache.fop.render.AbstractRenderer#renderForeignObject(ForeignObject, Rectangle2D) | * @see org.apache.fop.render.AbstractRenderer#renderForeignObject(ForeignObject, Rectangle2D) | ||||
*/ | */ | ||||
context.setProperty(PSXMLHandler.PS_YPOS, | context.setProperty(PSXMLHandler.PS_YPOS, | ||||
new Integer(currentBPPosition + (int) pos.getY())); | new Integer(currentBPPosition + (int) pos.getY())); | ||||
//context.setProperty("strokeSVGText", options.get("strokeSVGText")); | //context.setProperty("strokeSVGText", options.get("strokeSVGText")); | ||||
/* | |||||
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())); | |||||
*/ | |||||
renderXML(userAgent, context, doc, ns); | renderXML(userAgent, context, doc, ns); | ||||
} | } | ||||
} | } |
*/ | */ | ||||
package org.apache.fop.render.ps; | package org.apache.fop.render.ps; | ||||
//import org.apache.batik.gvt.TextNode; | |||||
import org.apache.batik.bridge.SVGTextElementBridge; | import org.apache.batik.bridge.SVGTextElementBridge; | ||||
import org.apache.batik.bridge.BridgeContext; | import org.apache.batik.bridge.BridgeContext; | ||||
//import org.apache.batik.bridge.TextUtilities; | |||||
import org.apache.batik.gvt.GraphicsNode; | import org.apache.batik.gvt.GraphicsNode; | ||||
import org.apache.fop.apps.Document; | |||||
import org.apache.batik.gvt.TextNode; | |||||
import org.w3c.dom.Element; | import org.w3c.dom.Element; | ||||
import org.w3c.dom.Node; | import org.w3c.dom.Node; | ||||
* @version $Id: PSTextElementBridge.java,v 1.2 2003/03/07 09:46:30 jeremias Exp $ | * @version $Id: PSTextElementBridge.java,v 1.2 2003/03/07 09:46:30 jeremias Exp $ | ||||
*/ | */ | ||||
public class PSTextElementBridge extends SVGTextElementBridge { | public class PSTextElementBridge extends SVGTextElementBridge { | ||||
//private PSTextPainter textPainter; | |||||
private PSTextPainter textPainter; | |||||
/** | /** | ||||
* Constructs a new bridge for the <text> element. | * Constructs a new bridge for the <text> element. | ||||
* @param fi the font infomration | |||||
* @param textPainter the text painter to use | |||||
*/ | */ | ||||
public PSTextElementBridge(Document fi) { | |||||
//textPainter = new PSTextPainter(fi); | |||||
public PSTextElementBridge(PSTextPainter textPainter) { | |||||
this.textPainter = textPainter; | |||||
} | } | ||||
/** | /** | ||||
*/ | */ | ||||
public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) { | public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) { | ||||
GraphicsNode node = super.createGraphicsNode(ctx, e); | GraphicsNode node = super.createGraphicsNode(ctx, e); | ||||
/* | |||||
if (node != null && isSimple(ctx, e, node)) { | |||||
/* this code is worthless I think. PSTextPainter does a much better job | |||||
* at determining whether to stroke or not. */ | |||||
if (true/*node != null && isSimple(ctx, e, node)*/) { | |||||
((TextNode)node).setTextPainter(getTextPainter()); | ((TextNode)node).setTextPainter(getTextPainter()); | ||||
}*/ | |||||
} | |||||
return node; | return node; | ||||
} | } | ||||
/* | |||||
private PSTextPainter getTextPainter() { | private PSTextPainter getTextPainter() { | ||||
return textPainter; | |||||
return this.textPainter; | |||||
} | } | ||||
*/ | |||||
/** | /** | ||||
* Check if text element contains simple text. | * Check if text element contains simple text. | ||||
* easily rendered using normal drawString on the PDFGraphics2D | * easily rendered using normal drawString on the PDFGraphics2D | ||||
*/ | */ | ||||
private boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) { | private boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) { | ||||
/* | |||||
// Font size, in user space units. | |||||
float fs = TextUtilities.convertFontSize(element).floatValue(); | |||||
// PDF cannot display fonts over 36pt | |||||
if (fs > 36) { | |||||
return false; | |||||
} | |||||
*/ | |||||
for (Node n = element.getFirstChild(); | for (Node n = element.getFirstChild(); | ||||
n != null; | n != null; | ||||
n = n.getNextSibling()) { | n = n.getNextSibling()) { | ||||
case Node.ELEMENT_NODE: | case Node.ELEMENT_NODE: | ||||
if (n.getLocalName().equals(SVG_TSPAN_TAG) | if (n.getLocalName().equals(SVG_TSPAN_TAG) | ||||
|| n.getLocalName().equals(SVG_ALT_GLYPH_TAG)) { | |||||
|| n.getLocalName().equals(SVG_ALT_GLYPH_TAG)) { | |||||
return false; | return false; | ||||
} else if (n.getLocalName().equals(SVG_TEXT_PATH_TAG)) { | } else if (n.getLocalName().equals(SVG_TEXT_PATH_TAG)) { | ||||
return false; | return false; | ||||
break; | break; | ||||
case Node.TEXT_NODE: | case Node.TEXT_NODE: | ||||
case Node.CDATA_SECTION_NODE: | case Node.CDATA_SECTION_NODE: | ||||
default: | |||||
} | } | ||||
} | } | ||||
org.apache.fop.fonts.Font */ | org.apache.fop.fonts.Font */ | ||||
import java.text.AttributedCharacterIterator; | import java.text.AttributedCharacterIterator; | ||||
import java.text.CharacterIterator; | |||||
import java.awt.font.TextAttribute; | import java.awt.font.TextAttribute; | ||||
import java.awt.Shape; | import java.awt.Shape; | ||||
import java.awt.Paint; | import java.awt.Paint; | ||||
import java.util.List; | import java.util.List; | ||||
import java.util.Iterator; | import java.util.Iterator; | ||||
import org.apache.batik.dom.svg.SVGOMTextElement; | |||||
import org.apache.batik.gvt.text.Mark; | import org.apache.batik.gvt.text.Mark; | ||||
import org.apache.batik.gvt.TextPainter; | import org.apache.batik.gvt.TextPainter; | ||||
import org.apache.batik.gvt.TextNode; | import org.apache.batik.gvt.TextNode; | ||||
import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; | import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; | ||||
import org.apache.batik.gvt.text.TextPaintInfo; | import org.apache.batik.gvt.text.TextPaintInfo; | ||||
import org.apache.batik.gvt.font.GVTFontFamily; | import org.apache.batik.gvt.font.GVTFontFamily; | ||||
import org.apache.batik.bridge.SVGFontFamily; | |||||
import org.apache.batik.gvt.renderer.StrokingTextPainter; | import org.apache.batik.gvt.renderer.StrokingTextPainter; | ||||
import org.apache.fop.fonts.FontMetrics; | import org.apache.fop.fonts.FontMetrics; | ||||
import org.apache.fop.fonts.Font; | import org.apache.fop.fonts.Font; | ||||
import org.apache.fop.svg.ACIUtils; | |||||
import org.apache.fop.apps.Document; | import org.apache.fop.apps.Document; | ||||
/** | /** | ||||
* (todo) use drawString(AttributedCharacterIterator iterator...) for some | * (todo) use drawString(AttributedCharacterIterator iterator...) for some | ||||
* | * | ||||
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | ||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | |||||
* @version $Id: PSTextPainter.java,v 1.15 2003/01/08 14:03:55 jeremias Exp $ | * @version $Id: PSTextPainter.java,v 1.15 2003/01/08 14:03:55 jeremias Exp $ | ||||
*/ | */ | ||||
public class PSTextPainter implements TextPainter { | public class PSTextPainter implements TextPainter { | ||||
private Document fontInfo; | |||||
private Document document; | |||||
/** | /** | ||||
* Use the stroking text painter to get the bounds and shape. | * Use the stroking text painter to get the bounds and shape. | ||||
* Also used as a fallback to draw the string with strokes. | * Also used as a fallback to draw the string with strokes. | ||||
*/ | */ | ||||
protected static final TextPainter PROXY_PAINTER = | |||||
StrokingTextPainter.getInstance(); | |||||
protected static final TextPainter | |||||
PROXY_PAINTER = StrokingTextPainter.getInstance(); | |||||
/** | /** | ||||
* Create a new PS text painter with the given font information. | * Create a new PS text painter with the given font information. | ||||
* @param fi the fint info | |||||
* @param document the context document | |||||
*/ | */ | ||||
public PSTextPainter(Document fi) { | |||||
fontInfo = fi; | |||||
public PSTextPainter(Document document) { | |||||
this.document = document; | |||||
} | } | ||||
/** | /** | ||||
// System.out.println("PSText paint"); | // System.out.println("PSText paint"); | ||||
String txt = node.getText(); | String txt = node.getText(); | ||||
Point2D loc = node.getLocation(); | Point2D loc = node.getLocation(); | ||||
AttributedCharacterIterator aci = | |||||
node.getAttributedCharacterIterator(); | |||||
// reset position to start of char iterator | |||||
if (aci.getBeginIndex() == aci.getEndIndex()) { | |||||
return; | |||||
if (hasUnsupportedAttributes(node)) { | |||||
PROXY_PAINTER.paint(node, g2d); | |||||
} else { | |||||
paintTextRuns(node.getTextRuns(), g2d, loc); | |||||
} | } | ||||
char ch = aci.first(); | |||||
if (ch == AttributedCharacterIterator.DONE) { | |||||
return; | |||||
} | |||||
private boolean hasUnsupportedAttributes(TextNode node) { | |||||
Iterator i = node.getTextRuns().iterator(); | |||||
while (i.hasNext()) { | |||||
StrokingTextPainter.TextRun | |||||
run = (StrokingTextPainter.TextRun)i.next(); | |||||
AttributedCharacterIterator aci = run.getACI(); | |||||
boolean hasUnsupported = hasUnsupportedAttributes(aci); | |||||
if (hasUnsupported) { | |||||
return true; | |||||
} | |||||
} | } | ||||
return false; | |||||
} | |||||
private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) { | |||||
boolean hasunsupported = false; | |||||
TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute( | TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute( | ||||
GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO); | GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO); | ||||
if (tpi == null) { | |||||
return; | |||||
} | |||||
TextNode.Anchor anchor; | |||||
anchor = (TextNode.Anchor) aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE); | |||||
if ((tpi != null) | |||||
&& ((tpi.strokeStroke != null && tpi.strokePaint != null) | |||||
|| (tpi.strikethroughStroke != null) | |||||
|| (tpi.underlineStroke != null) | |||||
|| (tpi.overlineStroke != null))) { | |||||
hasunsupported = true; | |||||
} | |||||
List gvtFonts; | |||||
gvtFonts = (List) aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES); | |||||
Paint forg = tpi.fillPaint; | |||||
Paint strokePaint = tpi.strokePaint; | |||||
Float size = (Float) aci.getAttribute(TextAttribute.SIZE); | |||||
if (size == null) { | |||||
return; | |||||
//Alpha is not supported | |||||
Paint foreground = (Paint) aci.getAttribute(TextAttribute.FOREGROUND); | |||||
if (foreground instanceof Color) { | |||||
Color col = (Color)foreground; | |||||
if (col.getAlpha() != 255) { | |||||
hasunsupported = true; | |||||
} | |||||
} | } | ||||
Stroke stroke = tpi.strokeStroke; | |||||
/* | |||||
Float xpos = (Float) aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.X); | |||||
Float ypos = (Float) aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.Y); | |||||
*/ | |||||
Float posture = (Float) aci.getAttribute(TextAttribute.POSTURE); | |||||
Float taWeight = (Float) aci.getAttribute(TextAttribute.WEIGHT); | |||||
Object letSpace = aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING); | |||||
if (letSpace != null) { | |||||
hasunsupported = true; | |||||
} | |||||
boolean useStrokePainter = false; | |||||
Object wordSpace = aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING); | |||||
if (wordSpace != null) { | |||||
hasunsupported = true; | |||||
} | |||||
Object lengthAdjust = aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST); | |||||
if (lengthAdjust != null) { | |||||
hasunsupported = true; | |||||
} | |||||
if (forg instanceof Color) { | |||||
Color col = (Color) forg; | |||||
if (col.getAlpha() != 255) { | |||||
useStrokePainter = true; | |||||
} | |||||
g2d.setColor(col); | |||||
Object writeMod = aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE); | |||||
if (writeMod != null | |||||
&& !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals( | |||||
writeMod)) { | |||||
hasunsupported = true; | |||||
} | } | ||||
g2d.setPaint(forg); | |||||
g2d.setStroke(stroke); | |||||
if (strokePaint != null) { | |||||
// need to draw using AttributedCharacterIterator | |||||
useStrokePainter = true; | |||||
Object vertOr = aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION); | |||||
if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals( | |||||
vertOr)) { | |||||
hasunsupported = true; | |||||
} | } | ||||
Object rcDel = aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER); | |||||
if (!(rcDel instanceof SVGOMTextElement)) { | |||||
hasunsupported = true; //Filter spans | |||||
} | |||||
return hasunsupported; | |||||
} | |||||
if (hasUnsupportedAttributes(aci)) { | |||||
useStrokePainter = true; | |||||
/** | |||||
* Paint a list of text runs on the Graphics2D at a given location. | |||||
* @param textRuns the list of text runs | |||||
* @param g2d the Graphics2D to paint to | |||||
* @param loc the current location of the "cursor" | |||||
*/ | |||||
protected void paintTextRuns(List textRuns, Graphics2D g2d, Point2D loc) { | |||||
Point2D currentloc = loc; | |||||
Iterator i = textRuns.iterator(); | |||||
while (i.hasNext()) { | |||||
StrokingTextPainter.TextRun | |||||
run = (StrokingTextPainter.TextRun)i.next(); | |||||
currentloc = paintTextRun(run, g2d, currentloc); | |||||
} | } | ||||
} | |||||
// text contains unsupported information | |||||
if (useStrokePainter) { | |||||
PROXY_PAINTER.paint(node, g2d); | |||||
return; | |||||
/** | |||||
* Paint a single text run on the Graphics2D at a given location. | |||||
* @param run the text run to paint | |||||
* @param g2d the Graphics2D to paint to | |||||
* @param loc the current location of the "cursor" | |||||
* @return the new location of the "cursor" after painting the text run | |||||
*/ | |||||
protected Point2D paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d, Point2D loc) { | |||||
AttributedCharacterIterator aci = run.getACI(); | |||||
return paintACI(aci, g2d, loc); | |||||
} | |||||
/** | |||||
* Extract the raw text from an ACI. | |||||
* @param aci ACI to inspect | |||||
* @return the extracted text | |||||
*/ | |||||
protected String getText(AttributedCharacterIterator aci) { | |||||
StringBuffer sb = new StringBuffer(aci.getEndIndex() - aci.getBeginIndex()); | |||||
for (char c = aci.first(); c != CharacterIterator.DONE; c = aci.next()) { | |||||
sb.append(c); | |||||
} | } | ||||
return sb.toString(); | |||||
} | |||||
String style = ((posture != null) && (posture.floatValue() > 0.0)) | |||||
? "italic" : "normal"; | |||||
int weight = ((taWeight != null) | |||||
&& (taWeight.floatValue() > 1.0)) ? Font.BOLD | |||||
: Font.NORMAL; | |||||
/** | |||||
* Paint an ACI on a Graphics2D at a given location. The method has to | |||||
* update the location after painting. | |||||
* @param aci ACI to paint | |||||
* @param g2d Graphics2D to paint on | |||||
* @param loc start location | |||||
* @return new current location | |||||
*/ | |||||
protected Point2D paintACI(AttributedCharacterIterator aci, Graphics2D g2d, Point2D loc) { | |||||
//System.out.println("=============================================="); | |||||
//ACIUtils.dumpAttrs(aci); | |||||
aci.first(); | |||||
Font fontState = null; | |||||
Document fi = fontInfo; | |||||
boolean found = false; | |||||
String fontFamily = null; | |||||
if (gvtFonts != null) { | |||||
Iterator i = gvtFonts.iterator(); | |||||
while (i.hasNext()) { | |||||
GVTFontFamily fam = (GVTFontFamily) i.next(); | |||||
if (fam instanceof SVGFontFamily) { | |||||
PROXY_PAINTER.paint(node, g2d); | |||||
return; | |||||
} | |||||
fontFamily = fam.getFamilyName(); | |||||
if (fi.hasFont(fontFamily, style, weight)) { | |||||
String fname = fontInfo.fontLookup(fontFamily, style, | |||||
weight); | |||||
FontMetrics metrics = fontInfo.getMetricsFor(fname); | |||||
int fsize = (int)(size.floatValue() * 1000); | |||||
fontState = new Font(fname, metrics, fsize); | |||||
found = true; | |||||
break; | |||||
} | |||||
} | |||||
updateLocationFromACI(aci, loc); | |||||
TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO); | |||||
if (tpi == null) { | |||||
return loc; | |||||
} | } | ||||
if (!found) { | |||||
String fname = | |||||
fontInfo.fontLookup("any", style, Font.NORMAL); | |||||
FontMetrics metrics = fontInfo.getMetricsFor(fname); | |||||
int fsize = (int)(size.floatValue() * 1000); | |||||
fontState = new Font(fname, metrics, fsize); | |||||
} else { | |||||
if (g2d instanceof PSGraphics2D) { | |||||
((PSGraphics2D) g2d).setOverrideFontState(fontState); | |||||
} | |||||
TextNode.Anchor anchor = (TextNode.Anchor)aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE); | |||||
//Set up font | |||||
List gvtFonts = (List)aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES); | |||||
Paint foreground = tpi.fillPaint; | |||||
Paint strokePaint = tpi.strokePaint; | |||||
Stroke stroke = tpi.strokeStroke; | |||||
Float fontSize = (Float)aci.getAttribute(TextAttribute.SIZE); | |||||
if (fontSize == null) { | |||||
return loc; | |||||
} | } | ||||
int fStyle = java.awt.Font.PLAIN; | |||||
if (weight == Font.BOLD) { | |||||
if (style.equals("italic")) { | |||||
fStyle = java.awt.Font.BOLD | java.awt.Font.ITALIC; | |||||
} else { | |||||
fStyle = java.awt.Font.BOLD; | |||||
} | |||||
} else { | |||||
if (style.equals("italic")) { | |||||
fStyle = java.awt.Font.ITALIC; | |||||
} else { | |||||
fStyle = java.awt.Font.PLAIN; | |||||
} | |||||
Float posture = (Float)aci.getAttribute(TextAttribute.POSTURE); | |||||
Float taWeight = (Float)aci.getAttribute(TextAttribute.WEIGHT); | |||||
if (foreground instanceof Color) { | |||||
Color col = (Color)foreground; | |||||
g2d.setColor(col); | |||||
} | } | ||||
java.awt.Font font = new java.awt.Font(fontFamily, fStyle, | |||||
(int)(fontState.getFontSize() / 1000)); | |||||
g2d.setPaint(foreground); | |||||
g2d.setStroke(stroke); | |||||
Font font = makeFont(aci); | |||||
java.awt.Font awtFont = makeAWTFont(aci, font); | |||||
g2d.setFont(font); | |||||
g2d.setFont(awtFont); | |||||
float advance = getStringWidth(txt, fontState); | |||||
String txt = getText(aci); | |||||
float advance = getStringWidth(txt, font); | |||||
float tx = 0; | float tx = 0; | ||||
if (anchor != null) { | if (anchor != null) { | ||||
switch (anchor.getType()) { | switch (anchor.getType()) { | ||||
break; | break; | ||||
case TextNode.Anchor.ANCHOR_END: | case TextNode.Anchor.ANCHOR_END: | ||||
tx = -advance; | tx = -advance; | ||||
break; | |||||
default: //nop | |||||
} | |||||
} | |||||
//Finally draw text | |||||
if (g2d instanceof PSGraphics2D) { | |||||
((PSGraphics2D) g2d).setOverrideFont(font); | |||||
} | |||||
try { | |||||
g2d.drawString(txt, (float)(loc.getX() + tx), (float)(loc.getY())); | |||||
} finally { | |||||
if (g2d instanceof PSGraphics2D) { | |||||
((PSGraphics2D) g2d).setOverrideFont(null); | |||||
} | } | ||||
} | } | ||||
g2d.drawString(txt, (float)(loc.getX() + tx), (float)(loc.getY())); | |||||
loc.setLocation(loc.getX() + (double)advance, loc.getY()); | |||||
return loc; | |||||
} | } | ||||
private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) { | |||||
boolean hasunsupported = false; | |||||
Object letSpace = aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING); | |||||
if (letSpace != null) { | |||||
hasunsupported = true; | |||||
private void updateLocationFromACI( | |||||
AttributedCharacterIterator aci, | |||||
Point2D loc) { | |||||
//Adjust position of span | |||||
Float xpos = (Float)aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.X); | |||||
Float ypos = (Float)aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.Y); | |||||
Float dxpos = (Float)aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.DX); | |||||
Float dypos = (Float)aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.DY); | |||||
if (xpos != null) { | |||||
loc.setLocation(xpos.doubleValue(), loc.getY()); | |||||
} | } | ||||
if (ypos != null) { | |||||
loc.setLocation(loc.getX(), ypos.doubleValue()); | |||||
} | |||||
if (dxpos != null) { | |||||
loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY()); | |||||
} | |||||
if (dypos != null) { | |||||
loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue()); | |||||
} | |||||
} | |||||
Object wordSpace = aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING); | |||||
if (wordSpace != null) { | |||||
hasunsupported = true; | |||||
} | |||||
private String getStyle(AttributedCharacterIterator aci) { | |||||
Float posture = (Float)aci.getAttribute(TextAttribute.POSTURE); | |||||
return ((posture != null) && (posture.floatValue() > 0.0)) | |||||
? "italic" | |||||
: "normal"; | |||||
} | |||||
AttributedCharacterIterator.Attribute key; | |||||
key = GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE; | |||||
Object writeMod = aci.getAttribute(key); | |||||
if (!GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals( | |||||
writeMod)) { | |||||
hasunsupported = true; | |||||
private int getWeight(AttributedCharacterIterator aci) { | |||||
Float taWeight = (Float)aci.getAttribute(TextAttribute.WEIGHT); | |||||
return ((taWeight != null) && (taWeight.floatValue() > 1.0)) | |||||
? Font.BOLD | |||||
: Font.NORMAL; | |||||
} | |||||
private Font makeFont(AttributedCharacterIterator aci) { | |||||
Float fontSize = (Float)aci.getAttribute(TextAttribute.SIZE); | |||||
String style = getStyle(aci); | |||||
int weight = getWeight(aci); | |||||
boolean found = false; | |||||
String fontFamily = null; | |||||
List gvtFonts = (List) aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES); | |||||
if (gvtFonts != null) { | |||||
Iterator i = gvtFonts.iterator(); | |||||
while (i.hasNext()) { | |||||
GVTFontFamily fam = (GVTFontFamily) i.next(); | |||||
/* (todo) Enable SVG Font painting | |||||
if (fam instanceof SVGFontFamily) { | |||||
PROXY_PAINTER.paint(node, g2d); | |||||
return; | |||||
}*/ | |||||
fontFamily = fam.getFamilyName(); | |||||
if (document.hasFont(fontFamily, style, weight)) { | |||||
String fname = document.fontLookup( | |||||
fontFamily, style, weight); | |||||
FontMetrics metrics = document.getMetricsFor(fname); | |||||
int fsize = (int)(fontSize.floatValue() * 1000); | |||||
return new Font(fname, metrics, fsize); | |||||
} | |||||
} | |||||
} | } | ||||
String fname = document.fontLookup( | |||||
"any", style, Font.NORMAL); | |||||
FontMetrics metrics = document.getMetricsFor(fname); | |||||
int fsize = (int)(fontSize.floatValue() * 1000); | |||||
return new Font(fname, metrics, fsize); | |||||
} | |||||
Object vertOr = aci.getAttribute( | |||||
GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION); | |||||
if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals( | |||||
vertOr)) { | |||||
hasunsupported = true; | |||||
private java.awt.Font makeAWTFont(AttributedCharacterIterator aci, Font font) { | |||||
final String style = getStyle(aci); | |||||
final int weight = getWeight(aci); | |||||
int fStyle = java.awt.Font.PLAIN; | |||||
if (weight == Font.BOLD) { | |||||
fStyle |= java.awt.Font.BOLD; | |||||
} | } | ||||
return hasunsupported; | |||||
if ("italic".equals(style)) { | |||||
fStyle |= java.awt.Font.ITALIC; | |||||
} | |||||
return new java.awt.Font(font.getFontName(), fStyle, | |||||
(int)(font.getFontSize() / 1000)); | |||||
} | } | ||||
private float getStringWidth(String str, Font fontState) { | |||||
private float getStringWidth(String str, Font font) { | |||||
float wordWidth = 0; | float wordWidth = 0; | ||||
float whitespaceWidth = fontState.getWidth(fontState.mapChar(' ')); | |||||
float whitespaceWidth = font.getWidth(font.mapChar(' ')); | |||||
for (int i = 0; i < str.length(); i++) { | for (int i = 0; i < str.length(); i++) { | ||||
float charWidth; | float charWidth; | ||||
char c = str.charAt(i); | char c = str.charAt(i); | ||||
if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) { | if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) { | ||||
charWidth = fontState.getWidth(fontState.mapChar(c)); | |||||
charWidth = font.getWidth(font.mapChar(c)); | |||||
if (charWidth <= 0) { | if (charWidth <= 0) { | ||||
charWidth = whitespaceWidth; | charWidth = whitespaceWidth; | ||||
} | } | ||||
* @return the bounds of the text | * @return the bounds of the text | ||||
*/ | */ | ||||
public Rectangle2D getBounds2D(TextNode node) { | public Rectangle2D getBounds2D(TextNode node) { | ||||
/* (todo) getBounds2D() is too slow | |||||
* because it uses the StrokingTextPainter. We should implement this | |||||
* method ourselves. */ | |||||
return PROXY_PAINTER.getBounds2D(node); | return PROXY_PAINTER.getBounds2D(node); | ||||
} | } | ||||
/* | /* | ||||
* $Id: PDFTranscoder.java,v 1.24 2003/03/07 09:51:26 jeremias Exp $ | |||||
* $Id$ | |||||
* ============================================================================ | * ============================================================================ | ||||
* The Apache Software License, Version 1.1 | * The Apache Software License, Version 1.1 | ||||
* ============================================================================ | * ============================================================================ | ||||
package org.apache.fop.render.ps; | package org.apache.fop.render.ps; | ||||
import java.awt.geom.AffineTransform; | |||||
import java.awt.geom.Rectangle2D; | |||||
import java.awt.Color; | |||||
import java.net.MalformedURLException; | |||||
import java.net.URL; | |||||
import java.io.IOException; | |||||
import org.apache.batik.bridge.BridgeContext; | |||||
import org.apache.batik.bridge.BridgeException; | |||||
import org.apache.batik.bridge.GVTBuilder; | |||||
import org.apache.batik.bridge.SVGTextElementBridge; | |||||
import org.apache.batik.bridge.ViewBox; | |||||
import org.apache.batik.dom.svg.SVGOMDocument; | |||||
import org.apache.batik.gvt.GraphicsNode; | |||||
import org.apache.batik.transcoder.TranscoderException; | |||||
import org.apache.batik.transcoder.TranscoderOutput; | |||||
import org.apache.batik.transcoder.image.resources.Messages; | |||||
import org.apache.batik.transcoder.image.ImageTranscoder; | |||||
import org.apache.fop.svg.AbstractFOPTranscoder; | |||||
import org.apache.batik.gvt.TextPainter; | |||||
import org.apache.batik.gvt.renderer.StrokingTextPainter; | |||||
import org.w3c.dom.Document; | |||||
import org.w3c.dom.svg.SVGDocument; | |||||
import org.w3c.dom.svg.SVGSVGElement; | |||||
/** | /** | ||||
* This class enables to transcode an input to a PostScript document. | * This class enables to transcode an input to a PostScript document. | ||||
* | * | ||||
* | * | ||||
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | ||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | ||||
* @version $Id: PDFTranscoder.java,v 1.24 2003/03/07 09:51:26 jeremias Exp $ | |||||
* @version $Id$ | |||||
*/ | */ | ||||
public class PSTranscoder extends AbstractFOPTranscoder { | |||||
protected PSDocumentGraphics2D graphics = null; | |||||
public class PSTranscoder extends AbstractPSTranscoder { | |||||
/** | /** | ||||
* Constructs a new <tt>PSTranscoder</tt>. | * Constructs a new <tt>PSTranscoder</tt>. | ||||
super(); | super(); | ||||
} | } | ||||
/** | |||||
* Transcodes the specified Document as an image in the specified output. | |||||
* | |||||
* @param document the document to transcode | |||||
* @param uri the uri of the document or null if any | |||||
* @param output the ouput where to transcode | |||||
* @exception TranscoderException if an error occured while transcoding | |||||
*/ | |||||
protected void transcode(Document document, String uri, | |||||
TranscoderOutput output) | |||||
throws TranscoderException { | |||||
graphics = new PSDocumentGraphics2D(false); | |||||
super.transcode(document, uri, output); | |||||
// prepare the image to be painted | |||||
int w = (int)(width+.5); | |||||
int h = (int)(height+.5); | |||||
try { | |||||
graphics.setupDocument(output.getOutputStream(), w, h); | |||||
graphics.setSVGDimension(width, height); | |||||
if (hints.containsKey(ImageTranscoder.KEY_BACKGROUND_COLOR)) { | |||||
graphics.setBackgroundColor | |||||
((Color)hints.get(ImageTranscoder.KEY_BACKGROUND_COLOR)); | |||||
} | |||||
graphics.setGraphicContext | |||||
(new org.apache.batik.ext.awt.g2d.GraphicContext()); | |||||
graphics.setTransform(curTxf); | |||||
this.root.paint(graphics); | |||||
graphics.finish(); | |||||
} catch (IOException ex) { | |||||
throw new TranscoderException(ex); | |||||
} | |||||
} | |||||
protected BridgeContext createBridgeContext() { | |||||
BridgeContext ctx = new BridgeContext(userAgent); | |||||
TextPainter textPainter = null; | |||||
textPainter = new StrokingTextPainter(); | |||||
ctx.setTextPainter(textPainter); | |||||
SVGTextElementBridge textElementBridge = | |||||
new PSTextElementBridge(graphics.getFontInfo()); | |||||
ctx.putBridge(textElementBridge); | |||||
//PDFAElementBridge pdfAElementBridge = new PDFAElementBridge(); | |||||
//AffineTransform currentTransform = new AffineTransform(1, 0, 0, 1, 0, 0); | |||||
//pdfAElementBridge.setCurrentTransform(currentTransform); | |||||
//ctx.putBridge(pdfAElementBridge); | |||||
//ctx.putBridge(new PSImageElementBridge()); | |||||
return ctx; | |||||
protected AbstractPSDocumentGraphics2D createDocumentGraphics2D() { | |||||
return new PSDocumentGraphics2D(false); | |||||
} | } | ||||
} | } |
SVGHandler svghandler = new SVGHandler(); | SVGHandler svghandler = new SVGHandler(); | ||||
svghandler.renderSVGDocument(context, doc, psi); | svghandler.renderSVGDocument(context, doc, psi); | ||||
} else { | } else { | ||||
//nop | |||||
} | } | ||||
} | } | ||||
GVTBuilder builder = new GVTBuilder(); | GVTBuilder builder = new GVTBuilder(); | ||||
BridgeContext ctx = new BridgeContext(ua); | BridgeContext ctx = new BridgeContext(ua); | ||||
PSTextElementBridge tBridge = new PSTextElementBridge(psInfo.getFontInfo()); | |||||
PSTextPainter textPainter = new PSTextPainter(psInfo.getFontInfo()); | |||||
ctx.setTextPainter(textPainter); | |||||
PSTextElementBridge tBridge = new PSTextElementBridge(textPainter); | |||||
ctx.putBridge(tBridge); | ctx.putBridge(tBridge); | ||||
//PSAElementBridge aBridge = new PSAElementBridge(); | //PSAElementBridge aBridge = new PSAElementBridge(); | ||||
//aBridge.setCurrentTransform(transform); | //aBridge.setCurrentTransform(transform); | ||||
//ctx.putBridge(aBridge); | //ctx.putBridge(aBridge); | ||||
TextPainter textPainter = new PSTextPainter(psInfo.getFontInfo()); | |||||
ctx.setTextPainter(textPainter); | |||||
GraphicsNode root; | GraphicsNode root; | ||||
try { | try { | ||||
root = builder.build(ctx, doc); | root = builder.build(ctx, doc); | ||||
try { | try { | ||||
gen.writeln("%SVG graphic start ---"); | gen.writeln("%SVG graphic start ---"); | ||||
gen.saveGraphicsState(); | |||||
/* | /* | ||||
* Clip to the svg area. | * Clip to the svg area. | ||||
* Note: To have the svg overlay (under) a text area then use | * Note: To have the svg overlay (under) a text area then use | ||||
* an fo:block-container | * an fo:block-container | ||||
*/ | */ | ||||
gen.saveGraphicsState(); | |||||
gen.writeln("newpath"); | |||||
gen.defineRect(xOffset, yOffset, w, h); | |||||
gen.writeln("clip"); | |||||
// transform so that the coordinates (0,0) is from the top left | // transform so that the coordinates (0,0) is from the top left | ||||
// and positive is down and to the right. (0,0) is where the | // and positive is down and to the right. (0,0) is where the | ||||
// viewBox puts it. | // viewBox puts it. | ||||
if (psInfo.pdfContext == null) { | if (psInfo.pdfContext == null) { | ||||
psInfo.pdfContext = psInfo.pdfPage; | psInfo.pdfContext = psInfo.pdfPage; | ||||
}*/ | }*/ | ||||
PSGraphics2D graphics = new PSGraphics2D(true, gen); | |||||
final boolean textAsShapes = false; | |||||
PSGraphics2D graphics = new PSGraphics2D(textAsShapes, gen); | |||||
graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext()); | graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext()); | ||||
//psInfo.pdfState.push(); | //psInfo.pdfState.push(); | ||||
transform = new AffineTransform(); | transform = new AffineTransform(); |