Obtained from: Keiron Liddle Submitted by: Steve Coffman Reviewed by: Steve Coffman This updates Keiron's branch that uses Batik for SVG. Adds a few files missing. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/fop-0_17_0_batikSVG@194240 13f79535-47bb-0310-9956-ffa450edef68fop-0_17_0_batikSVG
@@ -12,9 +12,9 @@ if [ "$JAVA_HOME" = "" ] ; then | |||
echo "location of the Java Virtual Machine you want to use." | |||
exit 1 | |||
fi | |||
LOCALCLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/classes.zip:./lib/ant.jar:./lib/buildtools.jar:./lib/batik.jar | |||
ANT_HOME=./lib | |||
LIBDIR=lib | |||
LOCALCLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/classes.zip:$LIBDIR/ant.jar:$LIBDIR/batik.jar:$LIBDIR/buildtools.jar:$LIBDIR/xerces-1.2.3.jar:$LIBDIR/xalan-2.0.0.jar:$LIBDIR/xalanj1compat.jar:$LIBDIR/bsf.jar:$LIBDIR/jimi-1.0.jar | |||
ANT_HOME=$LIBDIR | |||
echo Building with classpath $CLASSPATH:$LOCALCLASSPATH | |||
echo |
@@ -13,7 +13,7 @@ if [ "$JAVA_HOME" = "" ] ; then | |||
exit 1 | |||
fi | |||
LOCALCLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/classes.zip:../../../lib/ant.jar:../../../lib/w3c.jar:../../../lib/buildtools.jar:../../../build/fop.jar:../../../lib/batik.jar | |||
LOCALCLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/classes.zip:../../../lib/ant.jar:../../../lib/xerces-1.2.3.jar:../../../lib/buildtools.jar:../../../build/fop.jar:../../../lib/batik.jar:../../../lib/xalan-2.0.0.jar | |||
ANT_HOME=../../../lib | |||
echo Building with classpath $CLASSPATH:$LOCALCLASSPATH |
@@ -1,3 +1,3 @@ | |||
#!/bin/sh | |||
java -cp fop.jar:lib/w3c.jar:lib/xalan-2.0.0.jar:lib/xerces-1.2.3.jar:lib/jimi-1.0.jar org.apache.fop.apps.Fop "$@" | |||
java -cp build/fop.jar:lib/w3c.jar:lib/xalan-2.0.0.jar:lib/xerces-1.2.3.jar:lib/jimi-1.0.jar org.apache.fop.apps.Fop "$@" | |||
@@ -84,7 +84,7 @@ public class AWTStarter extends CommandLineStarter { | |||
frame = createPreviewDialog(renderer, resource); | |||
renderer.setProgressListener(frame); | |||
renderer.setComponent(frame); | |||
MessageHandler.setOutputMethod(MessageHandler.EVENT); | |||
MessageHandler.setOutputMethod(MessageHandler.NONE); | |||
MessageHandler.addListener(frame); | |||
} | |||
@@ -60,7 +60,7 @@ public class CommandLineStarter extends Starter { | |||
if (errorDump) { | |||
e.printStackTrace(); | |||
} | |||
System.exit(1); | |||
System.exit(0); | |||
} | |||
} | |||
@@ -75,4 +75,9 @@ public class KeepValue { | |||
{ | |||
return type; | |||
} | |||
public String toString() | |||
{ | |||
return type; | |||
} | |||
} |
@@ -915,11 +915,13 @@ public class PDFDocument { | |||
contents, | |||
pagewidth, pageheight); | |||
if(currentPage != null) { | |||
Enumeration enum=currentPage.getIDList().elements(); | |||
while ( enum.hasMoreElements() ) { | |||
String id=enum.nextElement().toString(); | |||
idReferences.setInternalGoToPageReference(id,page.referencePDF()); | |||
} | |||
} | |||
/* add it to the list of objects */ | |||
this.objects.addElement(page); |
@@ -27,6 +27,7 @@ import org.apache.batik.swing.gvt.*; | |||
import org.apache.batik.gvt.*; | |||
import org.apache.batik.gvt.renderer.*; | |||
import org.apache.batik.gvt.filter.*; | |||
import org.apache.batik.gvt.event.*; | |||
import java.awt.*; | |||
import java.awt.Image; | |||
@@ -690,6 +691,7 @@ public class AWTRenderer implements Renderer, Printable, Pageable { | |||
BridgeContext ctx = new BridgeContext(userAgent, rc); | |||
GraphicsNode root; | |||
graphics.translate(x / 1000f, pageHeight - y / 1000f); | |||
graphics.setRenderingHints(rc.getRenderingHints()); | |||
try { | |||
root = builder.build(ctx, doc); | |||
root.paint(graphics, rc); | |||
@@ -927,5 +929,20 @@ public class AWTRenderer implements Renderer, Printable, Pageable { | |||
{ | |||
return new Dimension(100, 100); | |||
} | |||
public EventDispatcher getEventDispatcher() | |||
{ | |||
return null; | |||
} | |||
public boolean supportExtension(String str) | |||
{ | |||
return false; | |||
} | |||
public boolean hasFeature(String str) | |||
{ | |||
return false; | |||
} | |||
} | |||
} |
@@ -75,6 +75,7 @@ import org.apache.batik.swing.gvt.*; | |||
import org.apache.batik.gvt.*; | |||
import org.apache.batik.gvt.renderer.*; | |||
import org.apache.batik.gvt.filter.*; | |||
import org.apache.batik.gvt.event.*; | |||
import org.w3c.dom.*; | |||
import org.w3c.dom.svg.*; | |||
@@ -574,6 +575,7 @@ public class PDFRenderer implements Renderer { | |||
case Overflow.HIDDEN: | |||
break; | |||
} | |||
area.getObject().render(this); | |||
currentStream.add("Q\n"); | |||
currentStream.add("BT\n"); | |||
@@ -628,10 +630,12 @@ public class PDFRenderer implements Renderer { | |||
GraphicsNodeRenderContext rc = getRenderContext(); | |||
BridgeContext ctx = new BridgeContext(userAgent, rc); | |||
GraphicsNode root; | |||
//System.out.println("creating PDFGraphics2D"); | |||
PDFGraphics2D graphics = new PDFGraphics2D(true, area.getFontState(), pdfDoc, | |||
currentFontName, currentFontSize, currentXPosition, | |||
currentYPosition); | |||
graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext()); | |||
graphics.setRenderingHints(rc.getRenderingHints()); | |||
try { | |||
root = builder.build(ctx, doc); | |||
root.paint(graphics, rc); | |||
@@ -1277,5 +1281,20 @@ public class PDFRenderer implements Renderer { | |||
{ | |||
return new Dimension(100, 100); | |||
} | |||
public EventDispatcher getEventDispatcher() | |||
{ | |||
return null; | |||
} | |||
public boolean supportExtension(String str) | |||
{ | |||
return false; | |||
} | |||
public boolean hasFeature(String str) | |||
{ | |||
return false; | |||
} | |||
} | |||
} |
@@ -0,0 +1,120 @@ | |||
/***************************************************************************** | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. * | |||
* ------------------------------------------------------------------------- * | |||
* This software is published under the terms of the Apache Software License * | |||
* version 1.1, a copy of which has been included with this distribution in * | |||
* the LICENSE file. * | |||
*****************************************************************************/ | |||
package org.apache.fop.svg; | |||
import org.apache.fop.pdf.*; | |||
import org.apache.fop.layout.*; | |||
import org.apache.fop.fonts.*; | |||
import org.apache.fop.render.pdf.*; | |||
import org.apache.fop.image.*; | |||
import org.apache.fop.datatypes.ColorSpace; | |||
import org.apache.batik.ext.awt.g2d.*; | |||
import java.text.AttributedCharacterIterator; | |||
import java.awt.*; | |||
import java.awt.Font; | |||
import java.awt.Image; | |||
import java.awt.image.*; | |||
import java.awt.font.*; | |||
import java.awt.geom.*; | |||
import java.awt.image.renderable.*; | |||
import java.io.*; | |||
import java.util.Map; | |||
/** | |||
* This concrete implementation of <tt>AbstractGraphics2D</tt> is a | |||
* simple help to programmers to get started with their own | |||
* implementation of <tt>Graphics2D</tt>. | |||
* <tt>DefaultGraphics2D</tt> implements all the abstract methods | |||
* is <tt>AbstractGraphics2D</tt> and makes it easy to start | |||
* implementing a <tt>Graphic2D</tt> piece-meal. | |||
* | |||
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a> | |||
* @version $Id$ | |||
* @see org.apache.batik.ext.awt.g2d.AbstractGraphics2D | |||
*/ | |||
public class PDFDocumentGraphics2D extends PDFGraphics2D { | |||
OutputStream stream; | |||
PDFStream pdfStream; | |||
int width; | |||
int height; | |||
/** | |||
* Create a new PDFGraphics2D with the given pdf document info. | |||
* This is used to create a Graphics object for use inside an already | |||
* existing document. | |||
* Maybe this could be handled as a subclass (PDFDocumentGraphics2d) | |||
*/ | |||
public PDFDocumentGraphics2D(boolean textAsShapes, OutputStream stream, int width, int height) | |||
{ | |||
super(textAsShapes); | |||
standalone = true; | |||
this.stream = stream; | |||
this.pdfDoc = new PDFDocument(); | |||
this.pdfDoc.setProducer("FOP SVG Renderer"); | |||
pdfStream = this.pdfDoc.makeStream(); | |||
this.width = width; | |||
this.height = height; | |||
currentFontName = ""; | |||
currentFontSize = 0; | |||
currentYPosition = 0; | |||
currentXPosition = 0; | |||
// fontState = fs; | |||
currentStream.write("1 0 0 -1 0 " + height + " cm\n"); | |||
// end part | |||
/* | |||
FontSetup.addToResources(this.pdfDoc, fontInfo); | |||
*/ | |||
} | |||
public void finish() throws IOException | |||
{ | |||
pdfStream.add(getString()); | |||
PDFResources pdfResources = this.pdfDoc.getResources(); | |||
PDFPage currentPage = this.pdfDoc.makePage(pdfResources, pdfStream, | |||
width, | |||
height, null); | |||
this.pdfDoc.output(stream); | |||
} | |||
public String getString() { | |||
return currentStream.toString(); | |||
} | |||
public void setGraphicContext(GraphicContext c) | |||
{ | |||
gc = c; | |||
} | |||
/** | |||
* This constructor supports the create method | |||
*/ | |||
public PDFDocumentGraphics2D(PDFDocumentGraphics2D g){ | |||
super(g); | |||
} | |||
/** | |||
* Creates a new <code>Graphics</code> object that is | |||
* a copy of this <code>Graphics</code> object. | |||
* @return a new graphics context that is a copy of | |||
* this graphics context. | |||
*/ | |||
public Graphics create(){ | |||
return new PDFDocumentGraphics2D(this); | |||
} | |||
} |
@@ -12,6 +12,8 @@ import org.apache.fop.pdf.*; | |||
import org.apache.fop.layout.*; | |||
import org.apache.fop.fonts.*; | |||
import org.apache.fop.render.pdf.*; | |||
import org.apache.fop.image.*; | |||
import org.apache.fop.datatypes.ColorSpace; | |||
import org.apache.batik.ext.awt.g2d.*; | |||
@@ -40,18 +42,20 @@ import java.util.Map; | |||
* @see org.apache.batik.ext.awt.g2d.AbstractGraphics2D | |||
*/ | |||
public class PDFGraphics2D extends AbstractGraphics2D { | |||
protected PDFDocument pdfDoc; | |||
protected FontState fontState; | |||
boolean standalone = false; | |||
/** the PDF Document being created */ | |||
protected PDFDocument pdfDoc; | |||
//protected PDFDocument pdfDoc; | |||
protected FontState fontState; | |||
//protected FontState fontState; | |||
/** the current stream to add PDF commands to */ | |||
StringWriter currentStream = new StringWriter(); | |||
PDFStream pdfStream; | |||
/** the current (internal) font name */ | |||
protected String currentFontName; | |||
@@ -65,9 +69,9 @@ public class PDFGraphics2D extends AbstractGraphics2D { | |||
protected int currentXPosition = 0; | |||
/** the current colour for use in svg */ | |||
private PDFColor currentColour = new PDFColor(0, 0, 0); | |||
PDFColor currentColour = new PDFColor(0, 0, 0); | |||
private FontInfo fontInfo; | |||
FontInfo fontInfo; | |||
/** | |||
* Create a new PDFGraphics2D with the given pdf document info. | |||
@@ -85,38 +89,10 @@ public class PDFGraphics2D extends AbstractGraphics2D { | |||
fontState = fs; | |||
} | |||
/** | |||
* Create a new PDFGraphics2D with the given pdf document info. | |||
* This is used to create a Graphics object for use inside an already | |||
* existing document. | |||
* Maybe this could be handled as a subclass (PDFDocumentGraphics2d) | |||
*/ | |||
public PDFGraphics2D(boolean textAsShapes, OutputStream stream) | |||
public PDFGraphics2D(boolean textAsShapes) | |||
{ | |||
super(textAsShapes); | |||
standalone = true; | |||
this.pdfDoc = new PDFDocument(); | |||
this.pdfDoc.setProducer("FOP SVG Renderer"); | |||
pdfStream = this.pdfDoc.makeStream(); | |||
currentFontName = ""; | |||
currentFontSize = 0; | |||
currentYPosition = 0; | |||
currentXPosition = 0; | |||
// fontState = fs; | |||
// end part | |||
/* | |||
FontSetup.addToResources(this.pdfDoc, fontInfo); | |||
pdfStream.write(getString()) | |||
this.pdfResources = this.pdfDoc.getResources(); | |||
currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream, | |||
page.getWidth() / 1000, | |||
page.getHeight() / 1000, page); | |||
this.pdfDoc.output(stream); | |||
*/ | |||
} | |||
} | |||
public String getString() { | |||
return currentStream.toString(); | |||
@@ -144,13 +120,6 @@ public class PDFGraphics2D extends AbstractGraphics2D { | |||
return new PDFGraphics2D(this); | |||
} | |||
public void setColor(Color c){ | |||
super.setColor(c); | |||
currentColour = new PDFColor(c.getRed(), c.getGreen(), c.getBlue()); | |||
currentStream.write(currentColour.getColorSpaceOut(false)); | |||
currentStream.write(currentColour.getColorSpaceOut(true)); | |||
} | |||
/** | |||
* Draws as much of the specified image as is currently available. | |||
* The image is drawn with its top-left corner at | |||
@@ -176,20 +145,161 @@ public class PDFGraphics2D extends AbstractGraphics2D { | |||
* @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) | |||
*/ | |||
public boolean drawImage(Image img, int x, int y, ImageObserver observer){ | |||
System.err.println("drawImage"); | |||
/* int width = img.getWidth(observer); | |||
int height = img.getHeight(observer); | |||
FopImage fopimg = new FopImage() { | |||
}; | |||
System.err.println("drawImage:x, y"); | |||
final int width = img.getWidth(observer); | |||
final int height = img.getHeight(observer); | |||
if(width == -1 || height == -1) { | |||
return false; | |||
} | |||
Dimension size = new Dimension(width, height); | |||
BufferedImage buf = buildBufferedImage(size); | |||
java.awt.Graphics2D g = buf.createGraphics(); | |||
g.setComposite(AlphaComposite.SrcOver); | |||
g.setBackground(new Color(1, 1, 1, 0)); | |||
g.setPaint(new Color(1, 1, 1, 0)); | |||
g.fillRect(0, 0, width, height); | |||
g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight())); | |||
if(!g.drawImage(img, 0, 0, observer)) { | |||
return false; | |||
} | |||
g.dispose(); | |||
final byte[] result = new byte[buf.getWidth() * buf.getHeight() * 3]; | |||
Raster raster = buf.getData(); | |||
DataBuffer bd = raster.getDataBuffer(); | |||
int count = 0; | |||
switch(bd.getDataType()) { | |||
case DataBuffer.TYPE_INT: | |||
int[][] idata = ((DataBufferInt)bd).getBankData(); | |||
for(int i = 0; i < idata.length; i++) { | |||
for(int j = 0; j < idata[i].length; j++) { | |||
//System.out.println("data:" + ((idata[i][j] >> 24) & 0xFF)); | |||
if(((idata[i][j] >> 24) & 0xFF) != 255) { | |||
System.out.println("data:" + ((idata[i][j] >> 24) & 0xFF)); | |||
result[count++] = (byte)0xFF; | |||
result[count++] = (byte)0xFF; | |||
result[count++] = (byte)0xFF; | |||
} else { | |||
result[count++] = (byte)((idata[i][j] >> 16) & 0xFF); | |||
result[count++] = (byte)((idata[i][j] >> 8) & 0xFF); | |||
result[count++] = (byte)((idata[i][j]) & 0xFF); | |||
} | |||
} | |||
} | |||
break; | |||
default: | |||
// error | |||
break; | |||
} | |||
try { | |||
FopImage fopimg = new TempImage(width, height, result); | |||
int xObjectNum = this.pdfDoc.addImage(fopimg); | |||
currentStream.add("q\n" + (((float) w) / 1000f) + | |||
" 0 0 " + (((float) h) / 1000f) + " " + | |||
/*currentStream.write("q\n" + (((float) width)) + | |||
" 0 0 " + (((float) height)) + " " + | |||
x + " " + | |||
((float)(y - h)) + " cm\n" + "/Im" + | |||
((float)(y - height)) + " cm\n" + "/Im" + | |||
xObjectNum + " Do\nQ\n");*/ | |||
AffineTransform at = getTransform(); | |||
double[] matrix = new double[6]; | |||
at.getMatrix(matrix); | |||
currentStream.write("q\n" + matrix[0] + | |||
" " + matrix[1] + " " + matrix[2] + " " + matrix[3] + " " + | |||
matrix[4] + " " + | |||
matrix[5] + " cm\n"); | |||
currentStream.write("" + width + | |||
" 0 0 " + (-height) + " " + | |||
x + " " + | |||
(y + height) + " cm\n" + "/Im" + | |||
xObjectNum + " Do\nQ\n"); | |||
} catch(Exception e) { | |||
e.printStackTrace(); | |||
} | |||
return true; | |||
} | |||
public BufferedImage buildBufferedImage(Dimension size) { | |||
return new BufferedImage(size.width, size.height, | |||
BufferedImage.TYPE_INT_ARGB); | |||
} | |||
class TempImage implements FopImage { | |||
int m_height; | |||
int m_width; | |||
int m_bitsPerPixel; | |||
ColorSpace m_colorSpace; | |||
int m_bitmapSiye; | |||
byte[] m_bitmaps; | |||
PDFColor transparent = new PDFColor(255, 255, 255); | |||
TempImage(int width, int height, byte[] result) throws FopImageException | |||
{ | |||
this.m_height = height; | |||
this.m_width = width; | |||
this.m_bitsPerPixel = 8; | |||
this.m_colorSpace = new ColorSpace(ColorSpace.DEVICE_RGB); | |||
//this.m_isTransparent = false; | |||
//this.m_bitmapsSize = this.m_width * this.m_height * 3; | |||
this.m_bitmaps = result; | |||
} | |||
public String getURL() {return "" + m_bitmaps;} | |||
// image size | |||
public int getWidth() throws FopImageException | |||
{ | |||
return m_width; | |||
} | |||
public int getHeight() throws FopImageException | |||
{return m_height;} | |||
// DeviceGray, DeviceRGB, or DeviceCMYK | |||
public ColorSpace getColorSpace() throws FopImageException | |||
{return m_colorSpace;} | |||
// bits per pixel | |||
public int getBitsPerPixel() throws FopImageException | |||
{return m_bitsPerPixel;} | |||
// For transparent images | |||
public boolean isTransparent() throws FopImageException | |||
{return transparent != null;} | |||
public PDFColor getTransparentColor() throws FopImageException | |||
{return transparent;} | |||
// get the image bytes, and bytes properties | |||
// get uncompressed image bytes | |||
public byte[] getBitmaps() throws FopImageException | |||
{return m_bitmaps;} | |||
// width * (bitsPerPixel / 8) * height, no ? | |||
public int getBitmapsSize() throws FopImageException | |||
{return m_width * m_height * 3;} | |||
// get compressed image bytes | |||
// I don't know if we really need it, nor if it | |||
// should be changed... | |||
public byte[] getRessourceBytes() throws FopImageException | |||
{return null;} | |||
public int getRessourceBytesSize() throws FopImageException | |||
{return 0;} | |||
// return null if no corresponding PDFFilter | |||
public PDFFilter getPDFFilter() throws FopImageException | |||
{return null;} | |||
// release memory | |||
public void close() {} | |||
} | |||
/** | |||
* Draws as much of the specified image as has already been scaled | |||
* to fit inside the specified rectangle. | |||
@@ -278,10 +388,17 @@ public class PDFGraphics2D extends AbstractGraphics2D { | |||
* @see #setComposite | |||
*/ | |||
public void draw(Shape s){ | |||
System.out.println("draw(Shape)"); | |||
//System.out.println("draw(Shape)"); | |||
Color c = getColor(); | |||
currentColour = new PDFColor(c.getRed(), c.getGreen(), c.getBlue()); | |||
currentStream.write(currentColour.getColorSpaceOut(true)); | |||
c = getBackground(); | |||
PDFColor col = new PDFColor(c.getRed(), c.getGreen(), c.getBlue()); | |||
currentStream.write(col.getColorSpaceOut(false)); | |||
PDFNumber pdfNumber = new PDFNumber(); | |||
PathIterator iter = s.getPathIterator(new AffineTransform()); | |||
PathIterator iter = s.getPathIterator(getTransform()); | |||
while(!iter.isDone()) { | |||
double vals[] = new double[6]; | |||
int type = iter.currentSegment(vals); | |||
@@ -427,8 +544,6 @@ public class PDFGraphics2D extends AbstractGraphics2D { | |||
System.err.println("drawString(AttributedCharacterIterator)"); | |||
} | |||
/** | |||
* Fills the interior of a <code>Shape</code> using the settings of the | |||
* <code>Graphics2D</code> context. The rendering attributes applied | |||
@@ -444,10 +559,17 @@ public class PDFGraphics2D extends AbstractGraphics2D { | |||
* @see #setClip | |||
*/ | |||
public void fill(Shape s){ | |||
System.err.println("fill"); | |||
//System.err.println("fill"); | |||
Color c = getColor(); | |||
currentColour = new PDFColor(c.getRed(), c.getGreen(), c.getBlue()); | |||
currentStream.write(currentColour.getColorSpaceOut(true)); | |||
c = getBackground(); | |||
PDFColor col = new PDFColor(c.getRed(), c.getGreen(), c.getBlue()); | |||
currentStream.write(col.getColorSpaceOut(false)); | |||
PDFNumber pdfNumber = new PDFNumber(); | |||
PathIterator iter = s.getPathIterator(new AffineTransform()); | |||
PathIterator iter = s.getPathIterator(getTransform()); | |||
while(!iter.isDone()) { | |||
double vals[] = new double[6]; | |||
int type = iter.currentSegment(vals); | |||
@@ -503,7 +625,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { | |||
*/ | |||
public GraphicsConfiguration getDeviceConfiguration(){ | |||
System.out.println("getDeviceConviguration"); | |||
return null; | |||
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); | |||
} | |||
/** |
@@ -0,0 +1,655 @@ | |||
/***************************************************************************** | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. * | |||
* ------------------------------------------------------------------------- * | |||
* This software is published under the terms of the Apache Software License * | |||
* version 1.1, a copy of which has been included with this distribution in * | |||
* the LICENSE file. * | |||
*****************************************************************************/ | |||
package org.apache.fop.svg; | |||
import java.awt.AlphaComposite; | |||
import java.awt.Cursor; | |||
import java.awt.Dimension; | |||
import java.awt.Graphics2D; | |||
import java.awt.Paint; | |||
import java.awt.Point; | |||
import java.awt.Rectangle; | |||
import java.awt.Shape; | |||
import java.awt.geom.AffineTransform; | |||
import java.awt.geom.Dimension2D; | |||
import java.awt.geom.Rectangle2D; | |||
import java.awt.image.BufferedImage; | |||
import java.awt.*; | |||
import java.awt.event.*; | |||
import java.awt.geom.*; | |||
import java.awt.font.*; | |||
import java.net.MalformedURLException; | |||
import java.net.URL; | |||
import java.util.HashSet; | |||
import java.util.Set; | |||
import org.apache.batik.transcoder.*; | |||
import org.apache.batik.bridge.BridgeContext; | |||
import org.apache.batik.bridge.BridgeException; | |||
import org.apache.batik.bridge.GVTBuilder; | |||
import org.apache.batik.bridge.UserAgent; | |||
import org.apache.batik.bridge.ViewBox; | |||
import org.apache.batik.dom.svg.DefaultSVGContext; | |||
import org.apache.batik.dom.svg.SAXSVGDocumentFactory; | |||
import org.apache.batik.dom.svg.SVGDOMImplementation; | |||
import org.apache.batik.dom.svg.SVGOMDocument; | |||
import org.apache.batik.dom.util.DocumentFactory; | |||
import org.apache.batik.ext.awt.image.GraphicsUtil; | |||
import org.apache.batik.gvt.GraphicsNode; | |||
import org.apache.batik.gvt.GraphicsNodeRenderContext; | |||
import org.apache.batik.gvt.event.EventDispatcher; | |||
import org.apache.batik.gvt.renderer.ImageRenderer; | |||
import org.apache.batik.gvt.renderer.ImageRendererFactory; | |||
import org.apache.batik.transcoder.TranscoderException; | |||
import org.apache.batik.transcoder.TranscoderOutput; | |||
import org.apache.batik.transcoder.TranscodingHints; | |||
import org.apache.batik.transcoder.XMLAbstractTranscoder; | |||
import org.apache.batik.transcoder.image.resources.Messages; | |||
import org.apache.batik.transcoder.keys.BooleanKey; | |||
import org.apache.batik.transcoder.keys.FloatKey; | |||
import org.apache.batik.transcoder.keys.LengthKey; | |||
import org.apache.batik.transcoder.keys.PaintKey; | |||
import org.apache.batik.transcoder.keys.PaintKey; | |||
import org.apache.batik.transcoder.keys.Rectangle2DKey; | |||
import org.apache.batik.transcoder.keys.StringKey; | |||
import org.apache.batik.transcoder.*; | |||
import org.apache.batik.util.SVGConstants; | |||
import org.apache.batik.bridge.*; | |||
import org.apache.batik.swing.svg.*; | |||
import org.apache.batik.swing.gvt.*; | |||
import org.apache.batik.gvt.*; | |||
import org.apache.batik.gvt.renderer.*; | |||
import org.apache.batik.gvt.filter.*; | |||
import org.apache.batik.gvt.event.*; | |||
import org.w3c.dom.*; | |||
import org.w3c.dom.svg.*; | |||
import org.w3c.dom.css.*; | |||
import org.w3c.dom.svg.SVGLength; | |||
import org.apache.fop.svg.*; | |||
import org.w3c.dom.DOMException; | |||
import org.w3c.dom.DOMImplementation; | |||
import org.w3c.dom.Document; | |||
import org.w3c.dom.svg.SVGAElement; | |||
import org.w3c.dom.svg.SVGDocument; | |||
import org.w3c.dom.svg.SVGSVGElement; | |||
// <!> FIXME : Those import clauses will change with new design | |||
import org.apache.batik.gvt.renderer.StaticRendererFactory; | |||
/** | |||
* This class enables to transcode an input to an image of any format. | |||
* | |||
* <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:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a> | |||
* @version $Id$ | |||
*/ | |||
public class PDFTranscoder extends XMLAbstractTranscoder { | |||
/** The user agent dedicated to an <tt>ImageTranscoder</tt>. */ | |||
protected UserAgent userAgent = new ImageTranscoderUserAgent(); | |||
/** | |||
* Constructs a new <tt>ImageTranscoder</tt>. | |||
*/ | |||
public PDFTranscoder() { | |||
hints.put(KEY_DOCUMENT_ELEMENT_NAMESPACE_URI, | |||
SVGConstants.SVG_NAMESPACE_URI); | |||
hints.put(KEY_DOCUMENT_ELEMENT, | |||
SVGConstants.SVG_SVG_TAG); | |||
hints.put(KEY_DOM_IMPLEMENTATION, | |||
SVGDOMImplementation.getDOMImplementation()); | |||
} | |||
/** | |||
* 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 { | |||
if (!(document instanceof SVGOMDocument)) { | |||
throw new TranscoderException( | |||
Messages.formatMessage("notsvg", null)); | |||
} | |||
SVGDocument svgDoc = (SVGDocument)document; | |||
SVGSVGElement root = svgDoc.getRootElement(); | |||
// initialize the SVG document with the appropriate context | |||
String parserClassname = (String)hints.get(KEY_XML_PARSER_CLASSNAME); | |||
DefaultSVGContext svgCtx = new DefaultSVGContext(); | |||
svgCtx.setPixelToMM(userAgent.getPixelToMM()); | |||
((SVGOMDocument)document).setSVGContext(svgCtx); | |||
// build the GVT tree | |||
GVTBuilder builder = new GVTBuilder(); | |||
ImageRendererFactory rendFactory = new StaticRendererFactory(); | |||
GraphicsNodeRenderContext rc = getRenderContext(); | |||
BridgeContext ctx = new BridgeContext(userAgent, rc); | |||
GraphicsNode gvtRoot; | |||
try { | |||
gvtRoot = builder.build(ctx, svgDoc); | |||
} catch (BridgeException ex) { | |||
throw new TranscoderException(ex); | |||
} | |||
// get the 'width' and 'height' attributes of the SVG document | |||
float docWidth = (float)ctx.getDocumentSize().getWidth(); | |||
float docHeight = (float)ctx.getDocumentSize().getHeight(); | |||
ctx = null; | |||
builder = null; | |||
// compute the image's width and height according the hints | |||
float imgWidth = -1; | |||
if (hints.containsKey(KEY_WIDTH)) { | |||
imgWidth = ((Float)hints.get(KEY_WIDTH)).floatValue(); | |||
} | |||
float imgHeight = -1; | |||
if (hints.containsKey(KEY_HEIGHT)) { | |||
imgHeight = ((Float)hints.get(KEY_HEIGHT)).floatValue(); | |||
} | |||
float width, height; | |||
if (imgWidth > 0 && imgHeight > 0) { | |||
width = imgWidth; | |||
height = imgHeight; | |||
} else if (imgHeight > 0) { | |||
width = (docWidth * imgHeight) / docHeight; | |||
height = imgHeight; | |||
} else if (imgWidth > 0) { | |||
width = imgWidth; | |||
height = (docHeight * imgWidth) / docWidth; | |||
} else { | |||
width = docWidth; | |||
height = docHeight; | |||
} | |||
// compute the preserveAspectRatio matrix | |||
AffineTransform Px; | |||
String ref = null; | |||
try { | |||
ref = new URL(uri).getRef(); | |||
} catch (MalformedURLException ex) { | |||
// nothing to do, catched previously | |||
} | |||
try { | |||
Px = ViewBox.getViewTransform(ref, root, width, height); | |||
} catch (BridgeException ex) { | |||
throw new TranscoderException(ex); | |||
} | |||
if (Px.isIdentity() && (width != docWidth || height != docHeight)) { | |||
// The document has no viewBox, we need to resize it by hand. | |||
// we want to keep the document size ratio | |||
float d = Math.max(docWidth, docHeight); | |||
float dd = Math.max(width, height); | |||
float scale = dd/d; | |||
Px = AffineTransform.getScaleInstance(scale, scale); | |||
} | |||
// take the AOI into account if any | |||
if (hints.containsKey(KEY_AOI)) { | |||
Rectangle2D aoi = (Rectangle2D)hints.get(KEY_AOI); | |||
// transform the AOI into the image's coordinate system | |||
aoi = Px.createTransformedShape(aoi).getBounds2D(); | |||
AffineTransform Mx = new AffineTransform(); | |||
double sx = width / aoi.getWidth(); | |||
double sy = height / aoi.getHeight(); | |||
Mx.scale(sx, sy); | |||
double tx = -aoi.getX(); | |||
double ty = -aoi.getY(); | |||
Mx.translate(tx, ty); | |||
// take the AOI transformation matrix into account | |||
// we apply first the preserveAspectRatio matrix | |||
Px.preConcatenate(Mx); | |||
} | |||
// prepare the image to be painted | |||
int w = (int)width; | |||
int h = (int)height; | |||
PDFDocumentGraphics2D graphics = new PDFDocumentGraphics2D(true, output.getOutputStream(), w, h); | |||
// GraphicsNodeRenderContext rc = getRenderContext(); | |||
graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext()); | |||
graphics.setRenderingHints(rc.getRenderingHints()); | |||
gvtRoot.paint(graphics, rc); | |||
try { | |||
graphics.finish(); | |||
} catch (Exception ex) { | |||
ex.printStackTrace(); | |||
throw new TranscoderException(ex); | |||
} | |||
/* | |||
// paint the SVG document using the bridge package | |||
// create the appropriate renderer | |||
ImageRenderer renderer = rendFactory.createImageRenderer(); | |||
renderer.updateOffScreen(w, h); | |||
renderer.setTransform(Px); | |||
renderer.setTree(gvtRoot); | |||
gvtRoot = null; // We're done with it... | |||
try { | |||
// now we are sure that the aoi is the image size | |||
Shape raoi = new Rectangle2D.Float(0, 0, width, height); | |||
// Warning: the renderer's AOI must be in user space | |||
renderer.repaint(Px.createInverse().createTransformedShape(raoi)); | |||
BufferedImage rend = renderer.getOffScreen(); | |||
renderer = null; // We're done with it... | |||
// BufferedImage dest = createImage(w, h); | |||
//Graphics2D g2d = GraphicsUtil.createGraphics(dest); | |||
//g2d.drawRenderedImage(rend, new AffineTransform()); | |||
} catch (Exception ex) { | |||
throw new TranscoderException(ex); | |||
} | |||
*/ | |||
} | |||
public GraphicsNodeRenderContext getRenderContext() { | |||
GraphicsNodeRenderContext nodeRenderContext = null; | |||
if (nodeRenderContext == null) { | |||
RenderingHints hints = new RenderingHints(null); | |||
hints.put(RenderingHints.KEY_ANTIALIASING, | |||
RenderingHints.VALUE_ANTIALIAS_ON); | |||
hints.put(RenderingHints.KEY_INTERPOLATION, | |||
RenderingHints.VALUE_INTERPOLATION_BILINEAR); | |||
FontRenderContext fontRenderContext = | |||
new FontRenderContext(new AffineTransform(), true, true); | |||
TextPainter textPainter = new StrokingTextPainter(); | |||
GraphicsNodeRableFactory gnrFactory = | |||
new ConcreteGraphicsNodeRableFactory(); | |||
nodeRenderContext = | |||
new GraphicsNodeRenderContext(new AffineTransform(), | |||
null, | |||
hints, | |||
fontRenderContext, | |||
textPainter, | |||
gnrFactory); | |||
nodeRenderContext.setTextPainter(textPainter); | |||
} | |||
return nodeRenderContext; | |||
} | |||
/** | |||
* Creates a <tt>DocumentFactory</tt> that is used to create an SVG DOM | |||
* tree. The specified DOM Implementation is ignored and the Batik | |||
* SVG DOM Implementation is automatically used. | |||
* | |||
* @param domImpl the DOM Implementation (not used) | |||
* @param parserClassname the XML parser classname | |||
*/ | |||
protected DocumentFactory createDocumentFactory(DOMImplementation domImpl, | |||
String parserClassname) { | |||
return new SAXSVGDocumentFactory(parserClassname); | |||
} | |||
// -------------------------------------------------------------------- | |||
// UserAgent implementation | |||
// -------------------------------------------------------------------- | |||
/** | |||
* A user agent implementation for <tt>ImageTranscoder</tt>. | |||
*/ | |||
protected class ImageTranscoderUserAgent implements UserAgent { | |||
/** | |||
* Returns the default size of this user agent (400x400). | |||
*/ | |||
public Dimension2D getViewportSize() { | |||
return new Dimension(400, 400); | |||
} | |||
/** | |||
* Displays the specified error message using the <tt>ErrorHandler</tt>. | |||
*/ | |||
public void displayError(String message) { | |||
try { | |||
getErrorHandler().error(new TranscoderException(message)); | |||
} catch (TranscoderException ex) { | |||
throw new RuntimeException(); | |||
} | |||
} | |||
/** | |||
* Displays the specified error using the <tt>ErrorHandler</tt>. | |||
*/ | |||
public void displayError(Exception e) { | |||
try { | |||
getErrorHandler().error(new TranscoderException(e)); | |||
} catch (TranscoderException ex) { | |||
throw new RuntimeException(); | |||
} | |||
} | |||
/** | |||
* Displays the specified message using the <tt>ErrorHandler</tt>. | |||
*/ | |||
public void displayMessage(String message) { | |||
try { | |||
getErrorHandler().warning(new TranscoderException(message)); | |||
} catch (TranscoderException ex) { | |||
throw new RuntimeException(); | |||
} | |||
} | |||
/** | |||
* Returns the pixel to millimeter conversion factor specified in the | |||
* <tt>TranscodingHints</tt> or 0.3528 if any. | |||
*/ | |||
public float getPixelToMM() { | |||
if (getTranscodingHints().containsKey(KEY_PIXEL_TO_MM)) { | |||
return ((Float)getTranscodingHints().get(KEY_PIXEL_TO_MM)).floatValue(); | |||
} else { | |||
// return 0.3528f; // 72 dpi | |||
return 0.26458333333333333333333333333333f; // 96dpi | |||
} | |||
} | |||
/** | |||
* Returns the user language specified in the | |||
* <tt>TranscodingHints</tt> or "en" (english) if any. | |||
*/ | |||
public String getLanguages() { | |||
if (getTranscodingHints().containsKey(KEY_LANGUAGE)) { | |||
return (String)getTranscodingHints().get(KEY_LANGUAGE); | |||
} else { | |||
return "en"; | |||
} | |||
} | |||
/** | |||
* Returns the user stylesheet specified in the | |||
* <tt>TranscodingHints</tt> or null if any. | |||
*/ | |||
public String getUserStyleSheetURI() { | |||
return (String)getTranscodingHints().get(KEY_USER_STYLESHEET_URI); | |||
} | |||
/** | |||
* Returns the XML parser to use from the TranscodingHints. | |||
*/ | |||
public String getXMLParserClassName() { | |||
return (String)getTranscodingHints().get(KEY_XML_PARSER_CLASSNAME); | |||
} | |||
/** | |||
* Unsupported operation. | |||
*/ | |||
public EventDispatcher getEventDispatcher() { | |||
return null; | |||
} | |||
/** | |||
* Unsupported operation. | |||
*/ | |||
public void openLink(SVGAElement elt) { } | |||
/** | |||
* Unsupported operation. | |||
*/ | |||
public void setSVGCursor(Cursor cursor) { } | |||
/** | |||
* Unsupported operation. | |||
*/ | |||
public void runThread(Thread t) { } | |||
/** | |||
* Unsupported operation. | |||
*/ | |||
public AffineTransform getTransform() { | |||
return null; | |||
} | |||
/** | |||
* Unsupported operation. | |||
*/ | |||
public Point getClientAreaLocationOnScreen() { | |||
return new Point(); | |||
} | |||
/** | |||
* Tells whether the given feature is supported by this | |||
* user agent. | |||
*/ | |||
public boolean hasFeature(String s) { | |||
return FEATURES.contains(s); | |||
} | |||
/** | |||
* Tells whether the given extension is supported by this | |||
* user agent. | |||
*/ | |||
public boolean supportExtension(String s) { | |||
return false; | |||
} | |||
} | |||
protected final static Set FEATURES = new HashSet(); | |||
static { | |||
FEATURES.add(SVGConstants.SVG_ORG_W3C_SVG_FEATURE); | |||
FEATURES.add(SVGConstants.SVG_ORG_W3C_SVG_LANG_FEATURE); | |||
FEATURES.add(SVGConstants.SVG_ORG_W3C_SVG_STATIC_FEATURE); | |||
} | |||
// -------------------------------------------------------------------- | |||
// Keys definition | |||
// -------------------------------------------------------------------- | |||
/** | |||
* The image width key. | |||
* <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1"> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH> | |||
* <TD VALIGN="TOP">KEY_WIDTH</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH> | |||
* <TD VALIGN="TOP">Float</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH> | |||
* <TD VALIGN="TOP">The width of the top most svg element</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH> | |||
* <TD VALIGN="TOP">No</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH> | |||
* <TD VALIGN="TOP">Specify the width of the image to create.</TD></TR> | |||
* </TABLE> */ | |||
public static final TranscodingHints.Key KEY_WIDTH | |||
= new LengthKey(); | |||
/** | |||
* The image height key. | |||
* <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1"> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH> | |||
* <TD VALIGN="TOP">KEY_HEIGHT</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH> | |||
* <TD VALIGN="TOP">Float</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH> | |||
* <TD VALIGN="TOP">The height of the top most svg element</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH> | |||
* <TD VALIGN="TOP">No</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH> | |||
* <TD VALIGN="TOP">Specify the height of the image to create.</TD></TR> | |||
* </TABLE> */ | |||
public static final TranscodingHints.Key KEY_HEIGHT | |||
= new LengthKey(); | |||
/** | |||
* The area of interest key. | |||
* <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1"> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH> | |||
* <TD VALIGN="TOP">KEY_AOI</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH> | |||
* <TD VALIGN="TOP">Rectangle2D</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH> | |||
* <TD VALIGN="TOP">The document's size</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH> | |||
* <TD VALIGN="TOP">No</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH> | |||
* <TD VALIGN="TOP">Specify the area of interest to render. The | |||
* rectangle coordinates must be specified in pixels and in the | |||
* document coordinates system.</TD></TR> | |||
* </TABLE> | |||
*/ | |||
public static final TranscodingHints.Key KEY_AOI | |||
= new Rectangle2DKey(); | |||
/** | |||
* The language key. | |||
* <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1"> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH> | |||
* <TD VALIGN="TOP">KEY_LANGUAGE</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH> | |||
* <TD VALIGN="TOP">String</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH> | |||
* <TD VALIGN="TOP">"en"</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH> | |||
* <TD VALIGN="TOP">No</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH> | |||
* <TD VALIGN="TOP">Specify the preferred language of the document. | |||
* </TD></TR> | |||
* </TABLE> | |||
*/ | |||
public static final TranscodingHints.Key KEY_LANGUAGE | |||
= new StringKey(); | |||
/** | |||
* The user stylesheet URI key. | |||
* <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1"> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH> | |||
* <TD VALIGN="TOP">KEY_USER_STYLESHEET_URI</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH> | |||
* <TD VALIGN="TOP">String</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH> | |||
* <TD VALIGN="TOP">null</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH> | |||
* <TD VALIGN="TOP">No</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH> | |||
* <TD VALIGN="TOP">Specify the user style sheet.</TD></TR> | |||
* </TABLE> | |||
*/ | |||
public static final TranscodingHints.Key KEY_USER_STYLESHEET_URI | |||
= new StringKey(); | |||
/** | |||
* The pixel to millimeter conversion factor key. | |||
* <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1"> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH> | |||
* <TD VALIGN="TOP">KEY_PIXEL_TO_MM</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH> | |||
* <TD VALIGN="TOP">Float</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH> | |||
* <TD VALIGN="TOP">0.33</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH> | |||
* <TD VALIGN="TOP">No</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH> | |||
* <TD VALIGN="TOP">Specify the pixel to millimeter conversion factor. | |||
* </TD></TR> | |||
* </TABLE> | |||
*/ | |||
public static final TranscodingHints.Key KEY_PIXEL_TO_MM | |||
= new FloatKey(); | |||
/** | |||
* The image background paint key. | |||
* <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1"> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH> | |||
* <TD VALIGN="TOP">KEY_BACKGROUND_COLOR</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH> | |||
* <TD VALIGN="TOP">Paint</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH> | |||
* <TD VALIGN="TOP">null</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH> | |||
* <TD VALIGN="TOP">No</TD></TR> | |||
* <TR> | |||
* <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH> | |||
* <TD VALIGN="TOP">Specify the background color to use. | |||
* The color is required by opaque image formats and is used by | |||
* image formats that support alpha channel.</TD></TR> | |||
* </TABLE> | |||
*/ | |||
public static final TranscodingHints.Key KEY_BACKGROUND_COLOR | |||
= new PaintKey(); | |||
} |
@@ -64,6 +64,8 @@ import org.w3c.dom.*; | |||
import org.w3c.dom.svg.*; | |||
import org.w3c.dom.svg.SVGLength; | |||
import java.io.File; | |||
/** | |||
* class representing svg:svg pseudo flow object. | |||
*/ | |||
@@ -329,6 +331,10 @@ public class SVG extends SVGObj implements GraphicsCreator { | |||
/* create an SVG area */ | |||
/* if width and height are zero, may want to get the bounds of the content. */ | |||
SVGOMDocument doc = new SVGOMDocument(null, SVGDOMImplementation.getDOMImplementation()); | |||
try { | |||
doc.setURLObject(new File(".").toURL()); | |||
} catch(Exception e) { | |||
} | |||
DefaultSVGContext dc = new DefaultSVGContext() { | |||
public float getPixelToMM() { |
@@ -106,5 +106,11 @@ public class SVGElementMapping implements ElementMapping { | |||
builder.addMapping(uri, "animateTransform", AnimateTransform.maker()); | |||
builder.addMapping(uri, "cursor", Cursor.maker()); | |||
builder.addMapping(uri, "filter", Filter.maker()); | |||
builder.addMapping(uri, "feFlood", FeFlood.maker()); | |||
builder.addMapping(uri, "feGaussianBlur", FeGaussianBlur.maker()); | |||
builder.addMapping(uri, "feOffset", FeOffset.maker()); | |||
builder.addMapping(uri, "feMerge", FeMerge.maker()); | |||
builder.addMapping(uri, "feMergeNode", FeMergeNode.maker()); | |||
} | |||
} |
@@ -62,6 +62,8 @@ import org.apache.batik.dom.svg.*; | |||
import org.w3c.dom.svg.*; | |||
import org.w3c.dom.*; | |||
import java.util.*; | |||
/** | |||
* Since SVG objects are not layed out then this class checks | |||
* that this element is not being layed out inside some incorrect | |||
@@ -80,14 +82,28 @@ public abstract class SVGObj extends FObj implements GraphicsCreator { | |||
super(parent, propertyList); | |||
} | |||
protected static Hashtable ns = new Hashtable(); | |||
public void addGraphic(Document doc, Element parent) { | |||
Element element = doc.createElementNS("http://www.w3.org/2000/svg", tagName); | |||
// Element element = doc.createElement(tagName); | |||
for(int count = 0; count < props.length; count++) { | |||
if(this.properties.get(props[count]) != null) { | |||
String rf = this.properties.get(props[count]).getString(); | |||
if(rf != null) | |||
element.setAttribute(props[count], rf); | |||
if(rf != null) { | |||
if(props[count].indexOf(":") == -1) { | |||
element.setAttribute(props[count], rf); | |||
} else { | |||
String pref = props[count].substring(0, props[count].indexOf(":")); | |||
System.out.println(pref); | |||
if(pref.equals("xmlns")) { | |||
ns.put(props[count].substring(props[count].indexOf(":") + 1), rf); | |||
System.out.println(ns); | |||
} | |||
ns.put("xlink", "http://www.w3.org/1999/xlink"); | |||
element.setAttributeNS((String)ns.get(pref), props[count], rf); | |||
} | |||
} | |||
} | |||
} | |||
parent.appendChild(element); |