Browse Source

Bugzilla #36520:

Cleaner transformation matrix handling.
SVG painting extracted into an XMLHandler subclass like for the other renderers.
Submitted by: Richard Wheeldon <richardw.at.geoquip-rnd.demon.co.uk>

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@279005 13f79535-47bb-0310-9956-ffa450edef68
pull/31/head
Jeremias Maerki 18 years ago
parent
commit
3225ad3675

+ 18
- 99
src/java/org/apache/fop/render/java2d/Java2DRenderer.java View File

@@ -46,10 +46,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.dom.svg.SVGDOMImplementation;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.area.Area;
@@ -75,11 +71,8 @@ import org.apache.fop.image.XMLImage;
import org.apache.fop.render.AbstractRenderer;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.pdf.CTMHelper;
import org.apache.fop.svg.SVGUserAgent;
import org.apache.fop.traits.BorderProps;
import org.w3c.dom.Document;
import org.w3c.dom.svg.SVGDocument;
import org.w3c.dom.svg.SVGSVGElement;

/**
* The <code>Java2DRenderer</code> class provides the abstract technical
@@ -159,6 +152,8 @@ public abstract class Java2DRenderer extends AbstractRenderer implements Printab
*/
public void setUserAgent(FOUserAgent foUserAgent) {
super.setUserAgent(foUserAgent);
Java2DSVGHandler xmlHandler = new Java2DSVGHandler();
userAgent.getXMLHandlerRegistry().addXMLHandler(xmlHandler);
userAgent.setRendererOverride(this); // for document regeneration
}

@@ -932,9 +927,9 @@ public abstract class Java2DRenderer extends AbstractRenderer implements Printab
}

/**
* draws an image
* Draws an image
*
* @param url URL of the bitmap
* @param pUrl URL of the bitmap
* @param pos Position of the bitmap
*/
protected void putImage(String pUrl, Rectangle2D pos) {
@@ -968,8 +963,9 @@ public abstract class Java2DRenderer extends AbstractRenderer implements Printab
return;
}
Document doc = ((XMLImage) fopimage).getDocument();
renderSVGDocument(doc, pos); // TODO check if ok.
String ns = ((XMLImage) fopimage).getNameSpace();

renderDocument(doc, ns, pos);
} else if ("image/eps".equals(mime)) {
log.warn("EPS images are not supported by this renderer");
currentBPPosition += (h * 1000);
@@ -1028,12 +1024,7 @@ public abstract class Java2DRenderer extends AbstractRenderer implements Printab
public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
Document doc = fo.getDocument();
String ns = fo.getNameSpace();
if (SVGDOMImplementation.SVG_NAMESPACE_URI.equals(ns)) {
renderSVGDocument(doc, pos);
} else {
renderDocument(doc, ns, pos);
}
// this.currentXPosition += area.getContentWidth();
renderDocument(doc, ns, pos);
}

/**
@@ -1047,90 +1038,18 @@ public abstract class Java2DRenderer extends AbstractRenderer implements Printab
RendererContext context;
context = new RendererContext(this, MIME_TYPE);
context.setUserAgent(userAgent);
// TODO implement
/*
* context.setProperty(PDFSVGHandler.PDF_DOCUMENT, pdfDoc);
* context.setProperty(PDFSVGHandler.OUTPUT_STREAM, ostream);
* context.setProperty(PDFSVGHandler.PDF_STATE, currentState);
* context.setProperty(PDFSVGHandler.PDF_PAGE, currentPage);
* context.setProperty(PDFSVGHandler.PDF_CONTEXT, currentContext == null ?
* currentPage : currentContext);
* context.setProperty(PDFSVGHandler.PDF_CONTEXT, currentContext);
* context.setProperty(PDFSVGHandler.PDF_STREAM, currentStream);
* context.setProperty(PDFSVGHandler.PDF_XPOS, new
* Integer(currentIPPosition + (int) pos.getX()));
* context.setProperty(PDFSVGHandler.PDF_YPOS, new
* Integer(currentBPPosition + (int) pos.getY()));
* context.setProperty(PDFSVGHandler.PDF_FONT_INFO, fontInfo);
* context.setProperty(PDFSVGHandler.PDF_FONT_NAME, currentFontName);
* context.setProperty(PDFSVGHandler.PDF_FONT_SIZE, new
* Integer(currentFontSize));
* context.setProperty(PDFSVGHandler.PDF_WIDTH, new Integer((int)
* pos.getWidth())); context.setProperty(PDFSVGHandler.PDF_HEIGHT, new
* Integer((int) pos.getHeight())); renderXML(userAgent, context, doc,
* ns);
*/
}

protected void renderSVGDocument(Document doc, Rectangle2D pos) {

int x = currentIPPosition; // TODO + area.getXOffset();
int y = currentBPPosition;

RendererContext context;
context = new RendererContext(this, MIME_TYPE);
context.setUserAgent(userAgent);

SVGUserAgent ua = new SVGUserAgent(context.getUserAgent()
.getPixelUnitToMillimeter(), new AffineTransform());

GVTBuilder builder = new GVTBuilder();
BridgeContext ctx = new BridgeContext(ua);

GraphicsNode root;
try {
root = builder.build(ctx, doc);
} catch (Exception e) {
log.error(
"svg graphic could not be built: " + e.getMessage(), e);
return;
}

// If no viewbox is defined in the svg file, a viewbox of 100x100 is
// assumed, as defined in SVGUserAgent.getViewportSize()
float iw = (float) ctx.getDocumentSize().getWidth() * 1000f;
float ih = (float) ctx.getDocumentSize().getHeight() * 1000f;

float w = (float) pos.getWidth();
float h = (float) pos.getHeight();

// correct integer roundoff
state.getGraph().translate(x / 1000, y / 1000);

SVGSVGElement svg = ((SVGDocument) doc).getRootElement();
// Aspect ratio preserved by layout engine, not here
AffineTransform at = AffineTransform.getScaleInstance(w / iw, h / ih);
AffineTransform inverse = null;
try {
inverse = at.createInverse();
} catch (NoninvertibleTransformException e) {
log.warn(e);
}
if (!at.isIdentity()) {
state.getGraph().transform(at);
}

try {
root.paint(state.getGraph());
} catch (Exception e) {
e.printStackTrace();
}

if (inverse != null && !inverse.isIdentity()) {
state.getGraph().transform(inverse);
}
// correct integer roundoff
state.getGraph().translate(-(x + 500) / 1000, -(y + 500) / 1000);
context.setProperty(Java2DSVGHandler.JAVA2D_STATE, state);
context.setProperty(Java2DSVGHandler.JAVA2D_XPOS,
new Integer(currentIPPosition + (int)pos.getX()));
context.setProperty(Java2DSVGHandler.JAVA2D_YPOS,
new Integer(currentBPPosition + (int)pos.getY()));
context.setProperty(Java2DSVGHandler.JAVA2D_WIDTH,
new Integer((int)pos.getWidth()));
context.setProperty(Java2DSVGHandler.JAVA2D_HEIGHT,
new Integer((int) pos.getHeight()));
renderXML(context, doc, ns);
}

/**

+ 209
- 0
src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java View File

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

/* $Id$ */

package org.apache.fop.render.java2d;

import org.apache.fop.render.XMLHandler;
import org.apache.fop.render.RendererContext;
import org.apache.fop.svg.SVGUserAgent;

// Commons-Logging
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/* org.w3c.dom.Document is not imported to avoid conflict with
org.apache.fop.apps.Document */

import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.dom.svg.SVGDOMImplementation;
import org.apache.batik.gvt.GraphicsNode;

import java.awt.geom.AffineTransform;

/**
* Java2D XML handler for SVG (uses Apache Batik).
* This handler handles XML for foreign objects when rendering to Java2D.
* The properties from the Java2D renderer are subject to change.
*/
public class Java2DSVGHandler implements XMLHandler {

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

/**
* The current Java2DGraphicsState.
*/
public static final String JAVA2D_STATE = "state";

/**
* The width of the svg image/document to render.
*/
public static final String JAVA2D_WIDTH = "width";

/**
* The height of the svg image/document to render.
*/
public static final String JAVA2D_HEIGHT = "height";

/**
* The x position that this is being drawn at.
*/
public static final String JAVA2D_XPOS = "xpos";

/**
* The y position that this is being drawn at.
*/
public static final String JAVA2D_YPOS = "ypos";

/**
* Create a new Java2D XML handler for use by the Java2D renderer.
*/
public Java2DSVGHandler() {
}

/** @see org.apache.fop.render.XMLHandler */
public void handleXML(RendererContext context,
org.w3c.dom.Document doc, String ns) throws Exception {
Java2DInfo pdfi = getJava2DInfo(context);

if (SVGDOMImplementation.SVG_NAMESPACE_URI.equals(ns)) {
SVGHandler svghandler = new SVGHandler();
svghandler.renderSVGDocument(context, doc, pdfi);
}
}

/**
* Get the pdf information from the render context.
*
* @param context the renderer context
* @return the pdf information retrieved from the context
*/
public static Java2DInfo getJava2DInfo(RendererContext context) {
Java2DInfo pdfi = new Java2DInfo();
pdfi.state = (Java2DGraphicsState)context.getProperty(JAVA2D_STATE);
pdfi.width = ((Integer)context.getProperty(JAVA2D_WIDTH)).intValue();
pdfi.height = ((Integer)context.getProperty(JAVA2D_HEIGHT)).intValue();
pdfi.currentXPosition = ((Integer)context.getProperty(JAVA2D_XPOS)).intValue();
pdfi.currentYPosition = ((Integer)context.getProperty(JAVA2D_YPOS)).intValue();
return pdfi;
}

/**
* Java2D information structure for drawing the XML document.
*/
public static class Java2DInfo {
/** see Java2D_STATE */
public Java2DGraphicsState state;
/** see Java2D_WIDTH */
public int width;
/** see Java2D_HEIGHT */
public int height;
/** see Java2D_XPOS */
public int currentXPosition;
/** see Java2D_YPOS */
public int currentYPosition;

/** @see java.lang.Object#toString() */
public String toString() {
return "Java2DInfo {"
+ "state = " + state + ", "
+ "width = " + width + ", "
+ "height = " + height + ", "
+ "currentXPosition = " + currentXPosition + ", "
+ "currentYPosition = " + currentYPosition + "}";
}
}
/**
* This method is placed in an inner class so that we don't get class
* loading errors if batik is not present.
*/
protected class SVGHandler {
/**
* Render the svg document.
* @param context the renderer context
* @param doc the svg document
* @param info the pdf information of the current context
*/
protected void renderSVGDocument(RendererContext context,
org.w3c.dom.Document doc,
Java2DInfo info) {

log.debug("renderSVGDocument(" + context + ", " + doc + ", " + info + ")");
int x = info.currentXPosition;
int y = info.currentYPosition;
float ptom = context.getUserAgent().getPixelUnitToMillimeter();
SVGUserAgent ua = new SVGUserAgent(ptom, new AffineTransform());
GVTBuilder builder = new GVTBuilder();
BridgeContext ctx = new BridgeContext(ua);
GraphicsNode root;
try {
root = builder.build(ctx, doc);
} catch (Exception e) {
log.error("SVG graphic could not be built: " + e.getMessage(), e);
return;
}
// If no viewbox is defined in the svg file, a viewbox of 100x100 is
// assumed, as defined in SVGUserAgent.getViewportSize()
float iw = (float) ctx.getDocumentSize().getWidth() * 1000f;
float ih = (float) ctx.getDocumentSize().getHeight() * 1000f;
float w = (float) info.width;
float h = (float) info.height;

AffineTransform origTransform = info.state.getGraph().getTransform();
// correct integer roundoff
info.state.getGraph().translate(x / 1000, y / 1000);
//SVGSVGElement svg = ((SVGDocument) doc).getRootElement();
// Aspect ratio preserved by layout engine, not here
AffineTransform at = AffineTransform.getScaleInstance(w / iw, h / ih);
if (!at.isIdentity()) {
info.state.getGraph().transform(at);
}

try {
root.paint(info.state.getGraph());
} catch (Exception e) {
log.error("Error while painting SVG", e);
}
info.state.getGraph().setTransform(origTransform);
}
}
/** @see org.apache.fop.render.XMLHandler#getMimeType() */
public String getMimeType() {
return Java2DRenderer.MIME_TYPE;
}

/** @see org.apache.fop.render.XMLHandler#getNamespace() */
public String getNamespace() {
return SVGDOMImplementation.SVG_NAMESPACE_URI;
}
}

Loading…
Cancel
Save