Index: sources/org/apache/batik/apps/rasterizer/DestinationType.java
===================================================================
--- sources/org/apache/batik/apps/rasterizer/DestinationType.java (revision 694374)
+++ sources/org/apache/batik/apps/rasterizer/DestinationType.java (working copy)
@@ -22,6 +22,7 @@
import org.apache.batik.transcoder.image.JPEGTranscoder;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.apache.batik.transcoder.image.TIFFTranscoder;
+import org.apache.batik.transcoder.imagemap.ImageMapTranscoder;
/**
* Describes the type of destination for an SVGConverter
@@ -36,16 +37,19 @@
public static final String JPEG_STR = "image/jpeg";
public static final String TIFF_STR = "image/tiff";
public static final String PDF_STR = "application/pdf";
+ public static final String IMGMAP_STR = "text/xml";
public static final int PNG_CODE = 0;
public static final int JPEG_CODE = 1;
public static final int TIFF_CODE = 2;
public static final int PDF_CODE = 3;
+ public static final int IMGMAP_CODE = 4;
public static final String PNG_EXTENSION = ".png";
public static final String JPEG_EXTENSION = ".jpg";
public static final String TIFF_EXTENSION = ".tif";
public static final String PDF_EXTENSION = ".pdf";
+ public static final String IMGMAP_EXTENSION = ".xml";
public static final DestinationType PNG
= new DestinationType(PNG_STR, PNG_CODE, PNG_EXTENSION);
@@ -55,6 +59,8 @@
= new DestinationType(TIFF_STR, TIFF_CODE, TIFF_EXTENSION);
public static final DestinationType PDF
= new DestinationType(PDF_STR, PDF_CODE, PDF_EXTENSION);
+ public static final DestinationType IMGMAP
+ = new DestinationType(IMGMAP_STR, IMGMAP_CODE, IMGMAP_EXTENSION);
private String type;
private int code;
@@ -98,6 +104,8 @@
} catch(Exception e) {
return null;
}
+ case IMGMAP_CODE:
+ return new ImageMapTranscoder();
default:
return null;
}
@@ -110,7 +118,7 @@
* @return Array of valid values as strings.
*/
public DestinationType[] getValues() {
- return new DestinationType[]{PNG, JPEG, TIFF, PDF};
+ return new DestinationType[]{PNG, JPEG, TIFF, PDF, IMGMAP};
}
public Object readResolve(){
@@ -123,6 +131,8 @@
return TIFF;
case PDF_CODE:
return PDF;
+ case IMGMAP_CODE:
+ return IMGMAP;
default:
throw new Error("unknown code:" + code );
}
Index: sources/org/apache/batik/apps/rasterizer/Main.java
===================================================================
--- sources/org/apache/batik/apps/rasterizer/Main.java (revision 694374)
+++ sources/org/apache/batik/apps/rasterizer/Main.java (working copy)
@@ -534,6 +534,7 @@
mimeTypeMap.put("image/png", DestinationType.PNG);
mimeTypeMap.put("application/pdf", DestinationType.PDF);
mimeTypeMap.put("image/tiff", DestinationType.TIFF);
+ mimeTypeMap.put("text/xml", DestinationType.IMGMAP);
optionMap.put(CL_OPTION_OUTPUT,
new SingleValueOptionHandler(){
Index: sources/org/apache/batik/transcoder/imagemap/ImageMapTranscoder.java
===================================================================
--- sources/org/apache/batik/transcoder/imagemap/ImageMapTranscoder.java (revision 0)
+++ sources/org/apache/batik/transcoder/imagemap/ImageMapTranscoder.java (revision 0)
@@ -0,0 +1,289 @@
+/*****************************************************************************
+ * 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.batik.transcoder.imagemap;
+
+import org.apache.batik.transcoder.SVGAbstractTranscoder;
+import org.apache.batik.transcoder.TranscoderOutput;
+import org.apache.batik.transcoder.TranscoderException;
+import org.apache.batik.bridge.SVGUtilities;
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.gvt.GraphicsNode;
+import org.apache.batik.dom.svg.SVGOMDocument;
+
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+
+import java.awt.geom.PathIterator;
+import java.awt.geom.AffineTransform;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.traversal.DocumentTraversal;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+import org.w3c.dom.svg.SVGAElement;
+import org.w3c.dom.svg.SVGDocument;
+import org.w3c.dom.svg.SVGElement;
+
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.SAXException;
+
+/**
+ * This class transcodes an input to a html imagemap.
+ *
+ * @author Torsten Knodt
+ */
+public class ImageMapTranscoder extends SVGAbstractTranscoder {
+
+ private final String XHTML_URI = "http://www.w3.org/1999/xhtml";;
+ private final String CDATA = "CDATA";
+ private final String AREA_TAG = "area";
+ private final String MAP_TAG = "map";
+ private final String TITLE_ATTR = "title";
+ private final String ALT_ATTR = "alt";
+ private final String AREA_TAG_SHAPE_ATTR = "shape";
+ private final String AREA_TAG_SHAPE_ATTR_POLY = "poly";
+ private final String AREA_TAG_COORDS_ATTR = "coords";
+ private final String AREA_TAG_HREF_ATTR = "href";
+ private final String XHTML_SYSID = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";;
+ private final String XHTML_PUBID = "-//W3C//DTD XHTML 1.0 Strict//EN";
+
+ /**
+ * Constructs a new ImageMapTranscoder.
+ */
+ public ImageMapTranscoder() {
+ }
+
+ /**
+ * Get SAX Transformer factory
+ *
+ * @result SAX Transformer factory to use
+ */
+ private SAXTransformerFactory getTransformerHandlerFactory()
+ {
+ return (SAXTransformerFactory) SAXTransformerFactory.newInstance();
+ }
+
+ /**
+ * Get SAX Transformer from Factory
+ *
+ * @param output the output where to transcode
+ * @result the transformer handler
+ */
+ private TransformerHandler getTransformerHandler(TranscoderOutput output)
+ throws TransformerConfigurationException
+ {
+ SAXTransformerFactory tfactory = getTransformerHandlerFactory();
+ if (tfactory.getFeature(SAXSource.FEATURE) && tfactory.getFeature(StreamResult.FEATURE))
+ {
+ TransformerHandler ch = tfactory.newTransformerHandler();
+ ch.setResult (new StreamResult (output.getOutputStream()));
+ return ch;
+ }
+ return null;
+ }
+
+ /**
+ * Configure the SAX transformer handler
+ *
+ * @param th the SAX transformer handler
+ */
+ private void configureTransformerHandler(TransformerHandler th)
+ {
+ // th.setSystemId (XHTML_SYSID);
+ // FIXME: ID/ name attribute must be added to map element to make output valid
+ }
+
+ /**
+ * Configure the SAX transformer
+ *
+ * @param th the SAX transformer
+ */
+ private void configureTransformer(Transformer t)
+ {
+ // t.setOutputProperty (OutputKeys.DOCTYPE_PUBLIC, XHTML_PUBID);
+ // t.setOutputProperty (OutputKeys.DOCTYPE_SYSTEM, XHTML_SYSID);
+ // FIXME: ID/ name attribute must be added to map element to make output valid
+ t.setOutputProperty (OutputKeys.INDENT, "yes");
+ t.setOutputProperty (OutputKeys.MEDIA_TYPE, "text/xml");
+ t.setOutputProperty (OutputKeys.STANDALONE, "no");
+ t.setOutputProperty (OutputKeys.OMIT_XML_DECLARATION, "no");
+ t.setOutputProperty (OutputKeys.METHOD, "xml");
+ }
+
+ /**
+ * Sets the title attribute for an element
+ *
+ * @param element the element to fetch the title for
+ * @param att the Attribute Implementation to use
+ */
+ private void setTitle(SVGElement element, AttributesImpl att)
+ {
+ // We could also use xlink:title, but I think svg:desc is better.
+ String s = SVGUtilities.getDescription (element);
+ if (s != null)
+ if (! s.equals (""))
+ att.addAttribute("", TITLE_ATTR, TITLE_ATTR, CDATA, s);
+ }
+
+ /**
+ * Sets the alt attribute for an element
+ *
+ * @param element the element to fetch the title for
+ * @param att the Attribute Implementation to use
+ */
+ private void setAlt(SVGElement element, AttributesImpl att)
+ {
+ // Here svg:title should be used instead of svg:desc, I think. Perhaps xlink:title would also be an idea.
+ String s = SVGUtilities.getDescription (element);
+ if (s == null)
+ s = "";
+ att.addAttribute("", ALT_ATTR, ALT_ATTR, CDATA, s);
+ }
+
+ /**
+ * Reimplemented here to set the dynamic flag so the BridgeContext
+ * tracks the DOM node <-> gvt node association.
+ * @param doc the SVG document to create the BridgeContext for
+ * @return the newly instantiated BridgeContext
+ */
+ protected BridgeContext createBridgeContext(SVGOMDocument doc) {
+ BridgeContext c = super.createBridgeContext(doc);
+ c.setDynamicState(BridgeContext.DYNAMIC);
+ return c;
+ }
+
+ /**
+ * 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
+ {
+ super.transcode(document, uri, output);
+
+ TransformerHandler filter;
+ try {
+ filter = getTransformerHandler(output);
+ }
+ catch (TransformerConfigurationException ex) {
+ throw new TranscoderException (ex);
+ }
+ configureTransformerHandler (filter);
+ configureTransformer (filter.getTransformer());
+
+ AttributesImpl myatt = new AttributesImpl();
+ setTitle ((SVGElement) (document.getDocumentElement()), myatt);
+ try {
+ filter.startDocument();
+ // filter.startDTD(MAP_TAG, XHTML_PUBID, XHTML_SYSID);
+ // filter.endDTD();
+ // FIXME: ID/ name attribute must be added to map element to make output valid
+ filter.startElement (XHTML_URI, MAP_TAG, MAP_TAG, myatt);
+ }
+ catch (SAXException ex) {
+ throw new TranscoderException (ex);
+ }
+
+ NodeIterator i = ((DocumentTraversal) document).createNodeIterator(document, NodeFilter.SHOW_ELEMENT, null, true);
+ Node node;
+ while ((node = i.nextNode()) != null)
+ {
+ SVGAElement e;
+ try {
+ e = (SVGAElement) node;
+ }
+ catch (ClassCastException ex) {
+ continue;
+ }
+
+ GraphicsNode gn = ctx.getGraphicsNode(e);
+ System.out.println("Node: " + e + ", GraphicsNode: " + gn);
+ AffineTransform tx = gn.getGlobalTransform();
+ tx.preConcatenate(curTxf);
+
+ int state = PathIterator.SEG_CLOSE;
+ String coords = "";
+ int[] lastpoints = null;
+
+ for ( PathIterator path = gn.getOutline().getPathIterator(tx, 1.0);
+ ! path.isDone();
+ path.next() )
+ {
+ float[] points = new float[6];
+ int seg = path.currentSegment (points);
+ int[] newpoints = { Math.round(points[0]), Math.round(points[1]) };
+
+ switch (seg)
+ {
+ case PathIterator.SEG_CLOSE:
+ // End of path segment, so push out Tag
+ if (! coords.equals(""))
+ {
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", AREA_TAG_SHAPE_ATTR, AREA_TAG_SHAPE_ATTR, CDATA, AREA_TAG_SHAPE_ATTR_POLY);
+ att.addAttribute("", AREA_TAG_COORDS_ATTR, AREA_TAG_COORDS_ATTR, CDATA, coords);
+ att.addAttribute("", AREA_TAG_HREF_ATTR, AREA_TAG_HREF_ATTR, CDATA, e.getHref().getBaseVal());
+ setTitle (e, att);
+ setAlt (e, att);
+ try {
+ filter.startElement(XHTML_URI, AREA_TAG, AREA_TAG, att);
+ filter.endElement(XHTML_URI, AREA_TAG, AREA_TAG);
+ } catch (SAXException ex) { throw new TranscoderException (ex); }
+ coords = "";
+ lastpoints = null;
+ }
+ break;
+ case PathIterator.SEG_CUBICTO:
+ // Cubic segment not allowed in flattened path
+ throw new TranscoderException ("Cubic segment not allowed in flattened path");
+ case PathIterator.SEG_QUADTO:
+ // Quad segment not allowed in flattened path
+ throw new TranscoderException ("Quad segment not allowed in flattened path");
+ case PathIterator.SEG_LINETO:
+ if (coords.equals(""))
+ throw new TranscoderException ("Line segment not allowed at begin of path");
+ // Add line segment to polygon coords
+ if (! lastpoints.equals (newpoints))
+ coords = coords + "," + newpoints[0] + "," + newpoints[1];
+ break;
+ case PathIterator.SEG_MOVETO:
+ if (! coords.equals(""))
+ throw new TranscoderException ("Move segment only allowed at begin of path");
+ // Use move segment as polygon start coords
+ coords = newpoints[0] + "," + newpoints[1];
+ break;
+ default:
+ throw new TranscoderException ("Unknown segment with type number " + seg);
+ }
+
+ lastpoints = newpoints;
+ }
+ }
+ try {
+ filter.endElement (XHTML_URI, MAP_TAG, MAP_TAG);
+ filter.endDocument();
+ }
+ catch (SAXException ex) {
+ throw new TranscoderException (ex);
+ }
+ }
+
+}