Просмотр исходного кода

Substantial refactoring of the PS transcoder (especially the text painting, less painting using the StrokingTextPainter, therefore more speed and smaller output files)

Addition of an EPS transcoder


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@196990 13f79535-47bb-0310-9956-ffa450edef68
pull/30/head
Jeremias Maerki 20 лет назад
Родитель
Сommit
eeb5c41112

+ 293
- 0
src/java/org/apache/fop/render/ps/AbstractPSDocumentGraphics2D.java Просмотреть файл

@@ -0,0 +1,293 @@
/*
* $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);
}

}


+ 195
- 0
src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java Просмотреть файл

@@ -0,0 +1,195 @@
/*
* $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 &lt;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);
}
}


}

+ 3
- 0
src/java/org/apache/fop/render/ps/DSCConstants.java Просмотреть файл

@@ -64,6 +64,9 @@ public class DSCConstants {
/** Lead-in for a DSC-conformant PostScript file */
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 */
public static final String BBOX = "BoundingBox";
/** High-resolution bounding box for the document */

+ 124
- 0
src/java/org/apache/fop/render/ps/EPSDocumentGraphics2D.java Просмотреть файл

@@ -0,0 +1,124 @@
/*
* $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);
}

}

+ 94
- 0
src/java/org/apache/fop/render/ps/EPSTranscoder.java Просмотреть файл

@@ -0,0 +1,94 @@
/*
* $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 &lt;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);
}

}

+ 52
- 147
src/java/org/apache/fop/render/ps/PSDocumentGraphics2D.java Просмотреть файл

@@ -1,5 +1,5 @@
/*
* $Id: PDFDocumentGraphics2D.java,v 1.27 2003/03/07 09:51:26 jeremias Exp $
* $Id$
* ============================================================================
* The Apache Software License, Version 1.1
* ============================================================================
@@ -52,17 +52,12 @@ package org.apache.fop.render.ps;

//Java
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.IOException;

//FOP
import org.apache.fop.render.pdf.FontSetup;
import org.apache.fop.apps.Document;
import org.apache.fop.render.pdf.FontSetup;

/**
* This class is a wrapper for the <tt>PSGraphics2D</tt> that
@@ -71,16 +66,14 @@ import org.apache.fop.apps.Document;
*
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</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
*/
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,
* width and output stream can be setup later.
* For use by the transcoder which needs font information
@@ -94,158 +87,90 @@ public class PSDocumentGraphics2D extends PSGraphics2D {
super(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
* 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 pageheight = new Long(this.height);

//Setup for PostScript generation
setPSGenerator(new PSGenerator(stream));

//PostScript Header
gen.writeln(DSCConstants.PS_ADOBE_30);
gen.writeDSCComment(DSCConstants.CREATOR,
new String[] {"FOP PostScript Transcoder for SVG"});
gen.writeDSCComment(DSCConstants.CREATION_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[]
{zero, zero, pagewidth, pageheight});
{ZERO, ZERO, pagewidth, pageheight});
gen.writeDSCComment(DSCConstants.END_COMMENTS);
//Defaults
gen.writeDSCComment(DSCConstants.BEGIN_DEFAULTS);
gen.writeDSCComment(DSCConstants.END_DEFAULTS);
//Prolog
gen.writeDSCComment(DSCConstants.BEGIN_PROLOG);
gen.writeDSCComment(DSCConstants.END_PROLOG);
//Setup
gen.writeDSCComment(DSCConstants.BEGIN_SETUP);
PSProcSets.writeFOPStdProcSet(gen);
PSProcSets.writeFOPEPSProcSet(gen);
PSProcSets.writeFontDict(gen, fontInfo);
if (document != null) {
PSProcSets.writeFontDict(gen, document);
}
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});
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.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.END_PAGE);

//Finish document
gen.writeDSCComment(DSCConstants.TRAILER);
gen.writeDSCComment(DSCConstants.EOF);
gen.flush();
}
/**
* This constructor supports the create method
* @param g the PostScript document graphics to make a copy of
@@ -264,25 +189,5 @@ public class PSDocumentGraphics2D extends PSGraphics2D {
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);
}
}

}


+ 69
- 14
src/java/org/apache/fop/render/ps/PSGenerator.java Просмотреть файл

@@ -50,11 +50,11 @@
*/
package org.apache.fop.render.ps;

import java.awt.geom.AffineTransform;
import java.io.OutputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Date;
import java.util.Stack;

@@ -71,13 +71,17 @@ public class PSGenerator {
* Indicator for the PostScript interpreter that the value is provided
* later in the document (mostly in the %%Trailer section).
*/
public static final AtendIndicator ATEND = new AtendIndicator() {};
public static final AtendIndicator ATEND = new AtendIndicator() {
};

private OutputStream out;
private boolean commentsEnabled = true;
private Stack graphicsStateStack = new Stack();
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);

@@ -87,6 +91,14 @@ public class PSGenerator {
this.currentState = new PSState();
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.
@@ -104,8 +116,17 @@ public class PSGenerator {
* @return the formatted 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);
}

/**
@@ -132,6 +153,12 @@ public class PSGenerator {
newLine();
}

public void commentln(String comment) throws IOException {
if (this.commentsEnabled) {
writeln(comment);
}
}

/**
* Writes encoded data to the PostScript stream.
*
@@ -290,12 +317,12 @@ public class PSGenerator {
} else if (params[i] instanceof AtendIndicator) {
tempBuffer.append("(atend)");
} else if (params[i] instanceof Double) {
tempBuffer.append(df.format(params[i]));
tempBuffer.append(df3.format(params[i]));
} else if (params[i] instanceof Number) {
tempBuffer.append(params[i].toString());
} else if (params[i] instanceof Date) {
DateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
tempBuffer.append(convertStringToDSC(df.format((Date)params[i])));
DateFormat datef = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
tempBuffer.append(convertStringToDSC(datef.format((Date)params[i])));
} else {
throw new IllegalArgumentException("Unsupported parameter type: "
+ params[i].getClass().getName());
@@ -340,12 +367,12 @@ public class PSGenerator {
public void concatMatrix(double a, double b,
double c, double d,
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");
}
/**
@@ -359,6 +386,34 @@ public class PSGenerator {
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.
* @return the current graphics state

+ 350
- 334
src/java/org/apache/fop/render/ps/PSGraphics2D.java
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 8
- 0
src/java/org/apache/fop/render/ps/PSProcSets.java Просмотреть файл

@@ -85,6 +85,14 @@ public final class PSProcSets {
gen.writeln("/M/moveto ld");
gen.writeln("/RM/rmoveto 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("/_tm matrix def");

+ 29
- 50
src/java/org/apache/fop/render/ps/PSRenderer.java Просмотреть файл

@@ -259,13 +259,12 @@ public class PSRenderer extends AbstractRenderer {
/**
* 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) {
/* use PDF's font setup to get PDF metrics */
org.apache.fop.render.pdf.FontSetup.setup((Document)foTreeControl, null);
// TODO: what's this?
this.fontInfo = fontInfo;
this.fontInfo = (Document)foTreeControl;
}

/**
@@ -276,10 +275,14 @@ public class PSRenderer extends AbstractRenderer {
* @param h height
* @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) {
useColor(col);
writeln(x + " " + y + " " + w + " " + h + " rectfill");
writeln(gen.formatDouble(x)
+ " " + gen.formatDouble(y)
+ " " + gen.formatDouble(w)
+ " " + gen.formatDouble(h)
+ " rectfill");
}

/**
@@ -289,8 +292,12 @@ public class PSRenderer extends AbstractRenderer {
* @param w width
* @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");
}

/**
@@ -325,7 +332,10 @@ public class PSRenderer extends AbstractRenderer {

private void useColor(float red, float green, float blue) {
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;
currGreen = green;
currBlue = blue;
@@ -480,7 +490,10 @@ public class PSRenderer extends AbstractRenderer {
int bl = currentBPPosition + area.getOffset();

useFont(fontname, fontsize);

ColorType ct = (ColorType)area.getTrait(Trait.COLOR);
if (ct != null) {
useColor(ct);
}
paintText(rx, bl, area.getTextArea(), f);

/*
@@ -713,9 +726,7 @@ public class PSRenderer extends AbstractRenderer {
//saveGraphicsState();

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) {
ImageFactory fact = ImageFactory.getInstance();
@@ -748,7 +759,7 @@ public class PSRenderer extends AbstractRenderer {
}

float bwidth = bps.width;
updateColor(bps.color, false, null);
useColor(bps.color);
writeln(bwidth + " setlinewidth");

drawLine(startx, starty + bwidth / 2, endx, starty + bwidth / 2);
@@ -765,7 +776,7 @@ public class PSRenderer extends AbstractRenderer {
}

float bwidth = bps.width;
updateColor(bps.color, false, null);
useColor(bps.color);
writeln(bwidth + " setlinewidth");

drawLine(startx + bwidth / 2, starty, startx + bwidth / 2, endy);
@@ -783,7 +794,7 @@ public class PSRenderer extends AbstractRenderer {
}

float bwidth = bps.width;
updateColor(bps.color, false, null);
useColor(bps.color);
writeln(bwidth + " setlinewidth");

drawLine(startx, sy - bwidth / 2, endx, sy - bwidth / 2);
@@ -801,7 +812,7 @@ public class PSRenderer extends AbstractRenderer {
}

float bwidth = bps.width;
updateColor(bps.color, false, null);
useColor(bps.color);
writeln(bwidth + " setlinewidth");
drawLine(sx - bwidth / 2, starty, sx - bwidth / 2, endy);
}
@@ -825,13 +836,7 @@ public class PSRenderer extends AbstractRenderer {
writeln(startx + " " + starty + " M ");
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)
*/
@@ -863,34 +868,8 @@ public class PSRenderer extends AbstractRenderer {
context.setProperty(PSXMLHandler.PS_YPOS,
new Integer(currentBPPosition + (int) pos.getY()));
//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);

}




}

+ 13
- 26
src/java/org/apache/fop/render/ps/PSTextElementBridge.java Просмотреть файл

@@ -50,13 +50,10 @@
*/
package org.apache.fop.render.ps;

//import org.apache.batik.gvt.TextNode;
import org.apache.batik.bridge.SVGTextElementBridge;
import org.apache.batik.bridge.BridgeContext;
//import org.apache.batik.bridge.TextUtilities;
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.Node;
@@ -70,15 +67,15 @@ import org.w3c.dom.Node;
* @version $Id: PSTextElementBridge.java,v 1.2 2003/03/07 09:46:30 jeremias Exp $
*/
public class PSTextElementBridge extends SVGTextElementBridge {
//private PSTextPainter textPainter;
private PSTextPainter textPainter;

/**
* Constructs a new bridge for the &lt;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;
}

/**
@@ -90,18 +87,17 @@ public class PSTextElementBridge extends SVGTextElementBridge {
*/
public GraphicsNode createGraphicsNode(BridgeContext ctx, Element 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());
}*/
}
return node;
}

/*
private PSTextPainter getTextPainter() {
return textPainter;
return this.textPainter;
}
*/

/**
* Check if text element contains simple text.
@@ -118,16 +114,6 @@ public class PSTextElementBridge extends SVGTextElementBridge {
* easily rendered using normal drawString on the PDFGraphics2D
*/
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();
n != null;
n = n.getNextSibling()) {
@@ -136,7 +122,7 @@ public class PSTextElementBridge extends SVGTextElementBridge {
case Node.ELEMENT_NODE:

if (n.getLocalName().equals(SVG_TSPAN_TAG)
|| n.getLocalName().equals(SVG_ALT_GLYPH_TAG)) {
|| n.getLocalName().equals(SVG_ALT_GLYPH_TAG)) {
return false;
} else if (n.getLocalName().equals(SVG_TEXT_PATH_TAG)) {
return false;
@@ -146,6 +132,7 @@ public class PSTextElementBridge extends SVGTextElementBridge {
break;
case Node.TEXT_NODE:
case Node.CDATA_SECTION_NODE:
default:
}
}


+ 272
- 141
src/java/org/apache/fop/render/ps/PSTextPainter.java Просмотреть файл

@@ -57,6 +57,7 @@ import java.awt.geom.Rectangle2D;
org.apache.fop.fonts.Font */

import java.text.AttributedCharacterIterator;
import java.text.CharacterIterator;
import java.awt.font.TextAttribute;
import java.awt.Shape;
import java.awt.Paint;
@@ -65,17 +66,18 @@ import java.awt.Color;
import java.util.List;
import java.util.Iterator;

import org.apache.batik.dom.svg.SVGOMTextElement;
import org.apache.batik.gvt.text.Mark;
import org.apache.batik.gvt.TextPainter;
import org.apache.batik.gvt.TextNode;
import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
import org.apache.batik.gvt.text.TextPaintInfo;
import org.apache.batik.gvt.font.GVTFontFamily;
import org.apache.batik.bridge.SVGFontFamily;
import org.apache.batik.gvt.renderer.StrokingTextPainter;

import org.apache.fop.fonts.FontMetrics;
import org.apache.fop.fonts.Font;
import org.apache.fop.svg.ACIUtils;
import org.apache.fop.apps.Document;

/**
@@ -90,24 +92,26 @@ import org.apache.fop.apps.Document;
* (todo) use drawString(AttributedCharacterIterator iterator...) for some
*
* @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 $
*/
public class PSTextPainter implements TextPainter {
private Document fontInfo;
private Document document;

/**
* Use the stroking text painter to get the bounds and shape.
* 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.
* @param fi the fint info
* @param document the context document
*/
public PSTextPainter(Document fi) {
fontInfo = fi;
public PSTextPainter(Document document) {
this.document = document;
}

/**
@@ -120,137 +124,188 @@ public class PSTextPainter implements TextPainter {
// System.out.println("PSText paint");
String txt = node.getText();
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(
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;
if (anchor != null) {
switch (anchor.getType()) {
@@ -259,51 +314,124 @@ public class PSTextPainter implements TextPainter {
break;
case TextNode.Anchor.ANCHOR_END:
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 whitespaceWidth = fontState.getWidth(fontState.mapChar(' '));
float whitespaceWidth = font.getWidth(font.mapChar(' '));

for (int i = 0; i < str.length(); i++) {
float charWidth;
char c = str.charAt(i);
if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
charWidth = fontState.getWidth(fontState.mapChar(c));
charWidth = font.getWidth(font.mapChar(c));
if (charWidth <= 0) {
charWidth = whitespaceWidth;
}
@@ -336,6 +464,9 @@ public class PSTextPainter implements TextPainter {
* @return the bounds of the text
*/
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);
}


+ 5
- 97
src/java/org/apache/fop/render/ps/PSTranscoder.java Просмотреть файл

@@ -1,5 +1,5 @@
/*
* $Id: PDFTranscoder.java,v 1.24 2003/03/07 09:51:26 jeremias Exp $
* $Id$
* ============================================================================
* The Apache Software License, Version 1.1
* ============================================================================
@@ -51,41 +51,6 @@
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.
*
@@ -112,11 +77,9 @@ import org.w3c.dom.svg.SVGSVGElement;
*
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</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>.
@@ -125,63 +88,8 @@ public class PSTranscoder extends AbstractFOPTranscoder {
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);
}

}

+ 11
- 5
src/java/org/apache/fop/render/ps/PSXMLHandler.java Просмотреть файл

@@ -137,6 +137,7 @@ public class PSXMLHandler implements XMLHandler {
SVGHandler svghandler = new SVGHandler();
svghandler.renderSVGDocument(context, doc, psi);
} else {
//nop
}
}

@@ -295,7 +296,9 @@ public class PSXMLHandler implements XMLHandler {

GVTBuilder builder = new GVTBuilder();
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);

//PSAElementBridge aBridge = new PSAElementBridge();
@@ -305,8 +308,6 @@ public class PSXMLHandler implements XMLHandler {
//aBridge.setCurrentTransform(transform);
//ctx.putBridge(aBridge);

TextPainter textPainter = new PSTextPainter(psInfo.getFontInfo());
ctx.setTextPainter(textPainter);
GraphicsNode root;
try {
root = builder.build(ctx, doc);
@@ -327,12 +328,16 @@ public class PSXMLHandler implements XMLHandler {

try {
gen.writeln("%SVG graphic start ---");
gen.saveGraphicsState();
/*
* Clip to the svg area.
* Note: To have the svg overlay (under) a text area then use
* 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
// and positive is down and to the right. (0,0) is where the
// viewBox puts it.
@@ -351,7 +356,8 @@ public class PSXMLHandler implements XMLHandler {
if (psInfo.pdfContext == null) {
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());
//psInfo.pdfState.push();
transform = new AffineTransform();

Загрузка…
Отмена
Сохранить