SVGException
without detail message.
+ * @param element
+ */
+ public SVGElementException(SVGElement element)
+ {
+ this(element, null, null);
+ }
+
+
+ /**
+ * Constructs an instance of SVGException
with the specified detail message.
+ * @param element
+ * @param msg the detail message.
+ */
+ public SVGElementException(SVGElement element, String msg)
+ {
+ this(element, msg, null);
+ }
+
+ public SVGElementException(SVGElement element, String msg, Throwable cause)
+ {
+ super(msg, cause);
+ this.element = element;
+ }
+
+ public SVGElementException(SVGElement element, Throwable cause)
+ {
+ this(element, null, cause);
+ }
+
+ public SVGElement getElement()
+ {
+ return element;
+ }
+}
diff --git a/graphics-svg/src/main/java/org/xbib/graphics/svg/SVGException.java b/graphics-svg/src/main/java/org/xbib/graphics/svg/SVGException.java
new file mode 100644
index 0000000..1dfb776
--- /dev/null
+++ b/graphics-svg/src/main/java/org/xbib/graphics/svg/SVGException.java
@@ -0,0 +1,73 @@
+/*
+ * SVG Salamander
+ * Copyright (c) 2004, Mark McKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * - 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS 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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, 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.
+ *
+ * Mark McKay can be contacted at mark@kitfox.com. Salamander and other
+ * projects can be found at http://www.kitfox.com
+ *
+ * Created on May 12, 2005, 11:32 PM
+ */
+
+package org.xbib.graphics.svg;
+
+/**
+ *
+ * @author kitfox
+ */
+public class SVGException extends java.lang.Exception
+{
+ public static final long serialVersionUID = 0;
+
+ /**
+ * Creates a new instance of SVGException
without detail message.
+ */
+ public SVGException()
+ {
+ }
+
+
+ /**
+ * Constructs an instance of SVGException
with the specified detail message.
+ * @param msg the detail message.
+ */
+ public SVGException(String msg)
+ {
+ super(msg);
+ }
+
+ public SVGException(String msg, Throwable cause)
+ {
+ super(msg, cause);
+ }
+
+ public SVGException(Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/graphics-svg/src/main/java/org/xbib/graphics/svg/SVGLoader.java b/graphics-svg/src/main/java/org/xbib/graphics/svg/SVGLoader.java
new file mode 100644
index 0000000..107a539
--- /dev/null
+++ b/graphics-svg/src/main/java/org/xbib/graphics/svg/SVGLoader.java
@@ -0,0 +1,308 @@
+/*
+ * SVG Salamander
+ * Copyright (c) 2004, Mark McKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * - 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS 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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, 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.
+ *
+ * Mark McKay can be contacted at mark@kitfox.com. Salamander and other
+ * projects can be found at http://www.kitfox.com
+ *
+ * Created on February 18, 2004, 5:09 PM
+ */
+
+package org.xbib.graphics.svg;
+
+
+import java.util.*;
+import java.net.*;
+
+import org.xbib.graphics.svg.animation.Animate;
+import org.xbib.graphics.svg.animation.AnimateColor;
+import org.xbib.graphics.svg.animation.AnimateMotion;
+import org.xbib.graphics.svg.animation.AnimateTransform;
+import org.xbib.graphics.svg.animation.SetSmil;
+import org.xml.sax.*;
+import org.xml.sax.helpers.DefaultHandler;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author Mark McKay
+ * @author Mark McKay
+ */
+public class SVGLoader extends DefaultHandler
+{
+ final HashMapSVGException
without detail message.
+ */
+ public SVGParseException()
+ {
+ }
+
+
+ /**
+ * Constructs an instance of SVGException
with the specified detail message.
+ * @param msg the detail message.
+ */
+ public SVGParseException(String msg)
+ {
+ super(msg);
+ }
+
+ public SVGParseException(String msg, Throwable cause)
+ {
+ super(msg, cause);
+ }
+
+ public SVGParseException(Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/graphics-svg/src/main/java/org/xbib/graphics/svg/SVGRoot.java b/graphics-svg/src/main/java/org/xbib/graphics/svg/SVGRoot.java
new file mode 100644
index 0000000..3fa9544
--- /dev/null
+++ b/graphics-svg/src/main/java/org/xbib/graphics/svg/SVGRoot.java
@@ -0,0 +1,496 @@
+/*
+ * SVG Salamander
+ * Copyright (c) 2004, Mark McKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * - 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS 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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, 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.
+ *
+ * Mark McKay can be contacted at mark@kitfox.com. Salamander and other
+ * projects can be found at http://www.kitfox.com
+ *
+ * Created on February 18, 2004, 5:33 PM
+ */
+
+package org.xbib.graphics.svg;
+
+import org.xbib.graphics.svg.xml.NumberWithUnits;
+import org.xbib.graphics.svg.xml.StyleAttribute;
+import org.xbib.graphics.svg.xml.StyleSheet;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.List;
+
+/**
+ * The root element of an SVG tree.
+ *
+ * @author Mark McKay
+ * @author Mark McKay
+ */
+public class SVGRoot extends Group
+{
+ public static final String TAG_NAME = "svg";
+
+ NumberWithUnits x;
+ NumberWithUnits y;
+ NumberWithUnits width;
+ NumberWithUnits height;
+
+ Rectangle2D.Float viewBox = null;
+
+ public static final int PA_X_NONE = 0;
+ public static final int PA_X_MIN = 1;
+ public static final int PA_X_MID = 2;
+ public static final int PA_X_MAX = 3;
+
+ public static final int PA_Y_NONE = 0;
+ public static final int PA_Y_MIN = 1;
+ public static final int PA_Y_MID = 2;
+ public static final int PA_Y_MAX = 3;
+
+ public static final int PS_MEET = 0;
+ public static final int PS_SLICE = 1;
+
+ int parSpecifier = PS_MEET;
+ int parAlignX = PA_X_MID;
+ int parAlignY = PA_Y_MID;
+
+ final AffineTransform viewXform = new AffineTransform();
+ final Rectangle2D.Float clipRect = new Rectangle2D.Float();
+
+ private StyleSheet styleSheet;
+
+ /** Creates a new instance of SVGRoot */
+ public SVGRoot()
+ {
+ }
+
+ @Override
+ public String getTagName()
+ {
+ return TAG_NAME;
+ }
+
+ @Override
+ public void build() throws SVGException
+ {
+ super.build();
+
+ StyleAttribute sty = new StyleAttribute();
+
+ if (getPres(sty.setName("x")))
+ {
+ x = sty.getNumberWithUnits();
+ }
+
+ if (getPres(sty.setName("y")))
+ {
+ y = sty.getNumberWithUnits();
+ }
+
+ if (getPres(sty.setName("width")))
+ {
+ width = sty.getNumberWithUnits();
+ }
+
+ if (getPres(sty.setName("height")))
+ {
+ height = sty.getNumberWithUnits();
+ }
+
+ if (getPres(sty.setName("viewBox")))
+ {
+ float[] coords = sty.getFloatList();
+ viewBox = new Rectangle2D.Float(coords[0], coords[1], coords[2], coords[3]);
+ }
+
+ if (getPres(sty.setName("preserveAspectRatio")))
+ {
+ String preserve = sty.getStringValue();
+
+ if (contains(preserve, "none")) { parAlignX = PA_X_NONE; parAlignY = PA_Y_NONE; }
+ else if (contains(preserve, "xMinYMin")) { parAlignX = PA_X_MIN; parAlignY = PA_Y_MIN; }
+ else if (contains(preserve, "xMidYMin")) { parAlignX = PA_X_MID; parAlignY = PA_Y_MIN; }
+ else if (contains(preserve, "xMaxYMin")) { parAlignX = PA_X_MAX; parAlignY = PA_Y_MIN; }
+ else if (contains(preserve, "xMinYMid")) { parAlignX = PA_X_MIN; parAlignY = PA_Y_MID; }
+ else if (contains(preserve, "xMidYMid")) { parAlignX = PA_X_MID; parAlignY = PA_Y_MID; }
+ else if (contains(preserve, "xMaxYMid")) { parAlignX = PA_X_MAX; parAlignY = PA_Y_MID; }
+ else if (contains(preserve, "xMinYMax")) { parAlignX = PA_X_MIN; parAlignY = PA_Y_MAX; }
+ else if (contains(preserve, "xMidYMax")) { parAlignX = PA_X_MID; parAlignY = PA_Y_MAX; }
+ else if (contains(preserve, "xMaxYMax")) { parAlignX = PA_X_MAX; parAlignY = PA_Y_MAX; }
+
+ if (contains(preserve, "meet"))
+ {
+ parSpecifier = PS_MEET;
+ }
+ else if (contains(preserve, "slice"))
+ {
+ parSpecifier = PS_SLICE;
+ }
+ }
+
+ prepareViewport();
+ }
+
+ private boolean contains(String text, String find)
+ {
+ return (text.indexOf(find) != -1);
+ }
+
+ @Override
+ public SVGRoot getRoot()
+ {
+ return this;
+ }
+
+ protected void prepareViewport()
+ {
+ Rectangle deviceViewport = diagram.getDeviceViewport();
+
+ Rectangle2D defaultBounds;
+ try
+ {
+ defaultBounds = getBoundingBox();
+ }
+ catch (SVGException ex)
+ {
+ defaultBounds= new Rectangle2D.Float();
+ }
+
+ //Determine destination rectangle
+ float xx, yy, ww, hh;
+ if (width != null)
+ {
+ xx = (x == null) ? 0 : StyleAttribute.convertUnitsToPixels(x.getUnits(), x.getValue());
+ if (width.getUnits() == NumberWithUnits.UT_PERCENT)
+ {
+ ww = width.getValue() * deviceViewport.width;
+ }
+ else
+ {
+ ww = StyleAttribute.convertUnitsToPixels(width.getUnits(), width.getValue());
+ }
+ }
+ else if (viewBox != null)
+ {
+ xx = viewBox.x;
+ ww = viewBox.width;
+ width = new NumberWithUnits(ww, NumberWithUnits.UT_PX);
+ x = new NumberWithUnits(xx, NumberWithUnits.UT_PX);
+ }
+ else
+ {
+ //Estimate size from scene bounding box
+ xx = (float)defaultBounds.getX();
+ ww = (float)defaultBounds.getWidth();
+ width = new NumberWithUnits(ww, NumberWithUnits.UT_PX);
+ x = new NumberWithUnits(xx, NumberWithUnits.UT_PX);
+ }
+
+ if (height != null)
+ {
+ yy = (y == null) ? 0 : StyleAttribute.convertUnitsToPixels(y.getUnits(), y.getValue());
+ if (height.getUnits() == NumberWithUnits.UT_PERCENT)
+ {
+ hh = height.getValue() * deviceViewport.height;
+ }
+ else
+ {
+ hh = StyleAttribute.convertUnitsToPixels(height.getUnits(), height.getValue());
+ }
+ }
+ else if (viewBox != null)
+ {
+ yy = viewBox.y;
+ hh = viewBox.height;
+ height = new NumberWithUnits(hh, NumberWithUnits.UT_PX);
+ y = new NumberWithUnits(yy, NumberWithUnits.UT_PX);
+ }
+ else
+ {
+ //Estimate size from scene bounding box
+ yy = (float)defaultBounds.getY();
+ hh = (float)defaultBounds.getHeight();
+ height = new NumberWithUnits(hh, NumberWithUnits.UT_PX);
+ y = new NumberWithUnits(yy, NumberWithUnits.UT_PX);
+ }
+
+ clipRect.setRect(xx, yy, ww, hh);
+ }
+
+ public void renderToViewport(Graphics2D g) throws SVGException
+ {
+ render(g);
+ }
+
+ @Override
+ protected void doRender(Graphics2D g) throws SVGException
+ {
+ prepareViewport();
+
+ Rectangle targetViewport = g.getClipBounds();
+//
+// if (targetViewport == null)
+// {
+// Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
+// targetViewport = new Rectangle(0, 0, size.width, size.height);
+// }
+// clipRect.setRect(targetViewport);
+
+
+ Rectangle deviceViewport = diagram.getDeviceViewport();
+ if (width != null && height != null)
+ {
+ float xx, yy, ww, hh;
+
+ xx = (x == null) ? 0 : StyleAttribute.convertUnitsToPixels(x.getUnits(), x.getValue());
+ if (width.getUnits() == NumberWithUnits.UT_PERCENT)
+ {
+ ww = width.getValue() * deviceViewport.width;
+ }
+ else
+ {
+ ww = StyleAttribute.convertUnitsToPixels(width.getUnits(), width.getValue());
+ }
+
+ yy = (y == null) ? 0 : StyleAttribute.convertUnitsToPixels(y.getUnits(), y.getValue());
+ if (height.getUnits() == NumberWithUnits.UT_PERCENT)
+ {
+ hh = height.getValue() * deviceViewport.height;
+ }
+ else
+ {
+ hh = StyleAttribute.convertUnitsToPixels(height.getUnits(), height.getValue());
+ }
+
+ targetViewport = new Rectangle((int)xx, (int)yy, (int)ww, (int)hh);
+ }
+ else
+ {
+ targetViewport = new Rectangle(deviceViewport);
+ }
+ clipRect.setRect(targetViewport);
+
+ viewXform.setTransform(calcViewportTransform(targetViewport));
+
+ AffineTransform cachedXform = g.getTransform();
+ g.transform(viewXform);
+
+ super.doRender(g);
+
+ g.setTransform(cachedXform);
+ }
+
+ public AffineTransform calcViewportTransform(Rectangle targetViewport)
+ {
+ AffineTransform xform = new AffineTransform();
+
+ if (viewBox == null)
+ {
+ xform.setToIdentity();
+ }
+ else
+ {
+ xform.setToIdentity();
+ xform.setToTranslation(targetViewport.x, targetViewport.y);
+ xform.scale(targetViewport.width, targetViewport.height);
+ xform.scale(1 / viewBox.width, 1 / viewBox.height);
+ xform.translate(-viewBox.x, -viewBox.y);
+ }
+
+ return xform;
+ }
+
+ @Override
+ public void doPick(Rectangle2D pickArea, AffineTransform ltw, boolean boundingBox, ListA unique name for this document. It will be used to + * construct a unique URI to refer to this document and perform resolution + * with relative URIs within this document.
For example, a name of + * "/myScene" will produce the URI svgSalamander:/myScene. + * "/maps/canada/toronto" will produce svgSalamander:/maps/canada/toronto. + * If this second document then contained the href "../uk/london", it would + * resolve by default to svgSalamander:/maps/uk/london. That is, SVG + * Salamander defines the URI scheme svgSalamander for it's own internal use + * and uses it for uniquely identfying documents loaded by stream.
If + * you need to link to documents outside of this scheme, you can either + * supply full hrefs (eg, href="url(http://www.kitfox.com/index.html)") or + * put the xml:base attribute in a tag to change the defaultbase URIs are + * resolved against
If a name does not start with the character '/', + * it will be automatically prefixed to it.
+ * @param forceLoad - if true, ignore cached diagram and reload + * + * @return - The URI that refers to the loaded document + */ + public URI loadSVG(Reader reader, String name, boolean forceLoad) + { +//System.err.println(url.toString()); + //Synthesize URI for this stream + URI uri = getStreamBuiltURI(name); + if (uri == null) + { + return null; + } + if (loadedDocs.containsKey(uri) && !forceLoad) + { + return uri; + } + + return loadSVG(uri, new InputSource(reader)); + } + + /** + * Synthesize a URI for an SVGDiagram constructed from a stream. + * + * @param name - Name given the document constructed from a stream. + */ + public URI getStreamBuiltURI(String name) + { + if (name == null || name.length() == 0) + { + return null; + } + + if (name.charAt(0) != '/') + { + name = '/' + name; + } + + try + { + //Dummy URL for SVG documents built from image streams + return new URI(INPUTSTREAM_SCHEME, name, null); + } catch (Exception e) + { + Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, + "Could not parse", e); + return null; + } + } + + static ThreadLocalin.close()
.
+ *
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ @Override
+ public void close() throws IOException {
+ reachedEOF = true;
+ in.close();
+ }
+
+ /**
+ * Reads the next byte of data from this input stream. The value
+ * byte is returned as an int
in the range
+ * 0
to 255
. If no byte is available
+ * because the end of the stream has been reached, the value
+ * -1
is returned. This method blocks until input data
+ * is available, the end of the stream is detected, or an exception
+ * is thrown.
+ *
+ * This method
+ * simply performs in.read()
and returns the result.
+ *
+ * @return the next byte of data, or -1
if the end of the
+ * stream is reached.
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ @Override
+ public int read() throws IOException
+ {
+ final byte[] b = new byte[1];
+ int retVal = read(b, 0, 1);
+ if (retVal == -1) return -1;
+ return b[0];
+ }
+
+ /**
+ * Reads up to byte.length
bytes of data from this
+ * input stream into an array of bytes. This method blocks until some
+ * input is available.
+ *
+ * This method simply performs the call
+ * read(b, 0, b.length)
and returns
+ * the result. It is important that it does
+ * not do in.read(b)
instead;
+ * certain subclasses of FilterInputStream
+ * depend on the implementation strategy actually
+ * used.
+ *
+ * @param b the buffer into which the data is read.
+ * @return the total number of bytes read into the buffer, or
+ * -1
if there is no more data because the end of
+ * the stream has been reached.
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterInputStream#read(byte[], int, int)
+ */
+ @Override
+ public int read(byte[] b) throws IOException
+ {
+ return read(b, 0, b.length);
+ }
+
+ /**
+ * Reads up to len
bytes of data from this input stream
+ * into an array of bytes. This method blocks until some input is
+ * available.
+ *
+ * This method simply performs in.read(b, off, len)
+ * and returns the result.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset of the data.
+ * @param len the maximum number of bytes read.
+ * @return the total number of bytes read into the buffer, or
+ * -1
if there is no more data because the end of
+ * the stream has been reached.
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ if (reachedEOF) return -1;
+
+ if (xlateMode == XL_PLAIN)
+ {
+ int count = 0;
+ //Write header if appropriate
+ while (headPtr < headSize && len > 0)
+ {
+ b[off++] = head[headPtr++];
+ count++;
+ len--;
+ }
+
+ return (len == 0) ? count : count + in.read(b, off, len);
+ }
+
+ //Decrypt and inflate
+ if (inflater.needsInput() && !decryptChunk())
+ {
+ reachedEOF = true;
+
+ //Read remaining bytes
+ int numRead;
+ try {
+ numRead = inflater.inflate(b, off, len);
+ }
+ catch (Exception e)
+ {
+ Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
+ return -1;
+ }
+
+ if (!inflater.finished())
+ {
+ Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
+ "Inflation imncomplete");
+ }
+
+ return numRead == 0 ? -1 : numRead;
+ }
+
+ try
+ {
+ return inflater.inflate(b, off, len);
+ }
+ catch (DataFormatException e)
+ {
+ Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
+ return -1;
+ }
+ }
+
+
+ /**
+ * Call when inflater indicates that it needs more bytes.
+ * @return - true if we decrypted more bytes to deflate, false if we
+ * encountered the end of stream
+ * @throws java.io.IOException
+ */
+ protected boolean decryptChunk() throws IOException
+ {
+ while (inflater.needsInput())
+ {
+ int numInBytes = in.read(inBuffer);
+ if (numInBytes == -1) return false;
+// int numDecryptBytes = cipher.update(inBuffer, 0, numInBytes, decryptBuffer);
+// inflater.setInput(decryptBuffer, 0, numDecryptBytes);
+inflater.setInput(inBuffer, 0, numInBytes);
+ }
+
+ return true;
+ }
+
+ /**
+ * This method returns 1 if we've not reached EOF, 0 if we have. Programs
+ * should not rely on this to determine the number of bytes that can be
+ * read without blocking.
+ */
+ @Override
+ public int available() { return reachedEOF ? 0 : 1; }
+
+ /**
+ * Skips bytes by reading them into a cached buffer
+ */
+ @Override
+ public long skip(long n) throws IOException
+ {
+ int skipSize = (int)n;
+ if (skipSize > inBuffer.length) skipSize = inBuffer.length;
+ return read(inBuffer, 0, skipSize);
+ }
+
+}
+
+/*
+ import java.security.KeyPairGenerator;
+ import java.security.KeyPair;
+ import java.security.KeyPairGenerator;
+ import java.security.PrivateKey;
+ import java.security.PublicKey;
+ import java.security.SecureRandom;
+ import java.security.Cipher;
+
+ ....
+
+ java.security.Security.addProvider(new cryptix.provider.Cryptix());
+
+ SecureRandom random = new SecureRandom(SecureRandom.getSeed(30));
+ KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
+ keygen.initialize(1024, random);
+ keypair = keygen.generateKeyPair();
+
+ PublicKey pubkey = keypair.getPublic();
+ PrivateKey privkey = keypair.getPrivate();
+ */
+
+/*
+ *
+ *Generate key pairs
+KeyPairGenerator keyGen =
+ KeyPairGenerator.getInstance("DSA");
+KeyGen.initialize(1024, new SecureRandom(userSeed));
+KeyPair pair = KeyGen.generateKeyPair();
+ */
\ No newline at end of file
diff --git a/graphics-svg/src/main/java/org/xbib/graphics/svg/xml/cpx/CPXOutputStream.java b/graphics-svg/src/main/java/org/xbib/graphics/svg/xml/cpx/CPXOutputStream.java
new file mode 100644
index 0000000..0e55f54
--- /dev/null
+++ b/graphics-svg/src/main/java/org/xbib/graphics/svg/xml/cpx/CPXOutputStream.java
@@ -0,0 +1,190 @@
+/*
+ * SVG Salamander
+ * Copyright (c) 2004, Mark McKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * - 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS 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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, 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.
+ *
+ * Mark McKay can be contacted at mark@kitfox.com. Salamander and other
+ * projects can be found at http://www.kitfox.com
+ *
+ * Created on February 12, 2004, 12:50 PM
+ */
+
+package org.xbib.graphics.svg.xml.cpx;
+
+import java.io.*;
+import java.util.zip.*;
+
+/**
+ * @author Mark McKay
+ * @author Mark McKay
+ */
+public class CPXOutputStream extends FilterOutputStream implements CPXConsts {
+
+ Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
+
+ /**
+ * Creates a new instance of CPXOutputStream
+ * @param os
+ * @throws java.io.IOException
+ */
+ public CPXOutputStream(OutputStream os) throws IOException {
+ super(os);
+
+ //Write magic number
+ os.write(MAGIC_NUMBER);
+ }
+
+ /**
+ * Writes the specified byte
to this output stream.
+ *
+ * The write
method of FilterOutputStream
+ * calls the write
method of its underlying output stream,
+ * that is, it performs out.write(b).
+ *
+ * Implements the abstract write method of OutputStream.
+ *
+ * @param b the byte
.
+ * @exception IOException if an I/O error occurs.
+ */
+ @Override
+ public void write(int b) throws IOException {
+ final byte[] buf = new byte[1];
+ buf[0] = (byte)b;
+ write(buf, 0, 1);
+ }
+
+ /**
+ * Writes b.length
bytes to this output stream.
+ *
+ * The write
method of FilterOutputStream
+ * calls its write
method of three arguments with the
+ * arguments b
, 0
, and
+ * b.length
.
+ *
+ * Note that this method does not call the one-argument
+ * write
method of its underlying stream with the single
+ * argument b
.
+ *
+ * @param b the data to be written.
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterOutputStream#write(byte[], int, int)
+ */
+ @Override
+ public void write(byte b[]) throws IOException {
+ write(b, 0, b.length);
+ }
+
+ byte[] deflateBuffer = new byte[2048];
+
+ /**
+ * Writes len
bytes from the specified
+ * byte
array starting at offset off
to
+ * this output stream.
+ *
+ * The write
method of FilterOutputStream
+ * calls the write
method of one argument on each
+ * byte
to output.
+ *
+ * Note that this method does not call the write
method
+ * of its underlying input stream with the same arguments. Subclasses
+ * of FilterOutputStream
should provide a more efficient
+ * implementation of this method.
+ *
+ * @param b the data.
+ * @param off the start offset in the data.
+ * @param len the number of bytes to write.
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterOutputStream#write(int)
+ */
+ @Override
+ public void write(byte b[], int off, int len) throws IOException
+ {
+ deflater.setInput(b, off, len);
+
+ processAllData();
+ /*
+ int numDeflatedBytes;
+ while ((numDeflatedBytes = deflater.deflate(deflateBuffer)) != 0)
+ {
+// byte[] cipherBuf = cipher.update(deflateBuffer, 0, numDeflatedBytes);
+// out.write(cipherBytes);
+out.write(deflateBuffer, 0, numDeflatedBytes);
+ }
+ */
+ }
+
+ protected void processAllData() throws IOException
+ {
+ int numDeflatedBytes;
+ while ((numDeflatedBytes = deflater.deflate(deflateBuffer)) != 0)
+ {
+// byte[] cipherBuf = cipher.update(deflateBuffer, 0, numDeflatedBytes);
+// out.write(cipherBytes);
+out.write(deflateBuffer, 0, numDeflatedBytes);
+ }
+ }
+
+ /**
+ * Flushes this output stream and forces any buffered output bytes
+ * to be written out to the stream.
+ *
+ * The flush
method of FilterOutputStream
+ * calls the flush
method of its underlying output stream.
+ *
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterOutputStream#out
+ */
+ @Override
+ public void flush() throws IOException {
+ out.flush();
+ }
+
+ /**
+ * Closes this output stream and releases any system resources
+ * associated with the stream.
+ *
+ * The close
method of FilterOutputStream
+ * calls its flush
method, and then calls the
+ * close
method of its underlying output stream.
+ *
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterOutputStream#flush()
+ * @see java.io.FilterOutputStream#out
+ */
+ @Override
+ public void close() throws IOException {
+ deflater.finish();
+ processAllData();
+
+ try {
+ flush();
+ } catch (IOException ignored) {
+ }
+ out.close();
+ }
+}
diff --git a/graphics-svg/src/main/java/org/xbib/graphics/svg/xml/cpx/CPXTest.java b/graphics-svg/src/main/java/org/xbib/graphics/svg/xml/cpx/CPXTest.java
new file mode 100644
index 0000000..6d9015c
--- /dev/null
+++ b/graphics-svg/src/main/java/org/xbib/graphics/svg/xml/cpx/CPXTest.java
@@ -0,0 +1,112 @@
+/*
+ * SVG Salamander
+ * Copyright (c) 2004, Mark McKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * - 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS 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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, 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.
+ *
+ * Mark McKay can be contacted at mark@kitfox.com. Salamander and other
+ * projects can be found at http://www.kitfox.com
+ *
+ * Created on February 12, 2004, 2:45 PM
+ */
+
+package org.xbib.graphics.svg.xml.cpx;
+
+import org.xbib.graphics.svg.SVGConst;
+import java.io.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author Mark McKay
+ * @author Mark McKay
+ */
+public class CPXTest {
+
+ /** Creates a new instance of CPXTest */
+ public CPXTest() {
+
+// FileInputStream fin = new FileInputStream();
+ writeTest();
+ readTest();
+ }
+
+ public void writeTest()
+ {
+ try {
+
+ InputStream is = CPXTest.class.getResourceAsStream("/data/readme.txt");
+//System.err.println("Is " + is);
+
+ FileOutputStream fout = new FileOutputStream("C:\\tmp\\cpxFile.cpx");
+ CPXOutputStream cout = new CPXOutputStream(fout);
+
+ byte[] buffer = new byte[1024];
+ int numBytes;
+ while ((numBytes = is.read(buffer)) != -1)
+ {
+ cout.write(buffer, 0, numBytes);
+ }
+ cout.close();
+ }
+ catch (Exception e)
+ {
+ Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
+ }
+ }
+
+ public void readTest()
+ {
+ try {
+
+// InputStream is = CPXTest.class.getResourceAsStream("/rawdata/test/cpx/text.txt");
+// InputStream is = CPXTest.class.getResourceAsStream("/rawdata/test/cpx/cpxFile.cpx");
+ FileInputStream is = new FileInputStream("C:\\tmp\\cpxFile.cpx");
+ CPXInputStream cin = new CPXInputStream(is);
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(cin));
+ String line;
+ while ((line = br.readLine()) != null)
+ {
+ System.err.println(line);
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
+ }
+ }
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String[] args)
+ {
+ new CPXTest();
+ }
+
+}
diff --git a/graphics-svg/src/test/res/1C2EC147.png b/graphics-svg/src/test/res/1C2EC147.png
new file mode 100644
index 0000000..e33dd29
Binary files /dev/null and b/graphics-svg/src/test/res/1C2EC147.png differ
diff --git a/graphics-svg/src/test/res/1C2EC148.png b/graphics-svg/src/test/res/1C2EC148.png
new file mode 100644
index 0000000..e33dd29
Binary files /dev/null and b/graphics-svg/src/test/res/1C2EC148.png differ
diff --git a/graphics-svg/src/test/res/AdamTagletClasses.svg b/graphics-svg/src/test/res/AdamTagletClasses.svg
new file mode 100644
index 0000000..ac5b85f
--- /dev/null
+++ b/graphics-svg/src/test/res/AdamTagletClasses.svg
@@ -0,0 +1,104 @@
+
+
+]>
+
+
+
diff --git a/graphics-svg/src/test/res/Monitor.svg b/graphics-svg/src/test/res/Monitor.svg
new file mode 100644
index 0000000..9e07a3f
--- /dev/null
+++ b/graphics-svg/src/test/res/Monitor.svg
@@ -0,0 +1,84 @@
+
+
+
\ No newline at end of file
diff --git a/graphics-svg/src/test/res/bad_alias.svg b/graphics-svg/src/test/res/bad_alias.svg
new file mode 100644
index 0000000..4adc92d
--- /dev/null
+++ b/graphics-svg/src/test/res/bad_alias.svg
@@ -0,0 +1,131 @@
+
+
+
+
+]>
+
diff --git a/graphics-svg/src/test/res/bad_alias2.svg b/graphics-svg/src/test/res/bad_alias2.svg
new file mode 100644
index 0000000..81fc016
--- /dev/null
+++ b/graphics-svg/src/test/res/bad_alias2.svg
@@ -0,0 +1,229 @@
+
+
+
+
+]>
+
diff --git a/graphics-svg/src/test/res/bad_alias3.svg b/graphics-svg/src/test/res/bad_alias3.svg
new file mode 100644
index 0000000..a74e8bd
--- /dev/null
+++ b/graphics-svg/src/test/res/bad_alias3.svg
@@ -0,0 +1,5689 @@
+
+
+
+
+]>
+
diff --git a/graphics-svg/src/test/res/data-uri-scheme-test-image.svg b/graphics-svg/src/test/res/data-uri-scheme-test-image.svg
new file mode 100644
index 0000000..a6356be
--- /dev/null
+++ b/graphics-svg/src/test/res/data-uri-scheme-test-image.svg
@@ -0,0 +1,23 @@
+
+
+
+
+]>
+
diff --git a/graphics-svg/src/test/res/drawing.svg b/graphics-svg/src/test/res/drawing.svg
new file mode 100644
index 0000000..77a6dc1
--- /dev/null
+++ b/graphics-svg/src/test/res/drawing.svg
@@ -0,0 +1,9361 @@
+
+
+
+
+]>
+
diff --git a/graphics-svg/src/test/res/embed_image.svg b/graphics-svg/src/test/res/embed_image.svg
new file mode 100644
index 0000000..92bc10a
--- /dev/null
+++ b/graphics-svg/src/test/res/embed_image.svg
@@ -0,0 +1,5689 @@
+
+
+
+
+]>
+
diff --git a/graphics-svg/src/test/res/embed_image.svgz b/graphics-svg/src/test/res/embed_image.svgz
new file mode 100644
index 0000000..fe74789
Binary files /dev/null and b/graphics-svg/src/test/res/embed_image.svgz differ
diff --git a/graphics-svg/src/test/res/missing.svg b/graphics-svg/src/test/res/missing.svg
new file mode 100644
index 0000000..d540986
--- /dev/null
+++ b/graphics-svg/src/test/res/missing.svg
@@ -0,0 +1,1090 @@
+
+
+
+
+]>
+
diff --git a/graphics-svg/src/test/res/missing.svgz b/graphics-svg/src/test/res/missing.svgz
new file mode 100644
index 0000000..051d5e7
Binary files /dev/null and b/graphics-svg/src/test/res/missing.svgz differ
diff --git a/graphics-svg/src/test/res/round_path.svg b/graphics-svg/src/test/res/round_path.svg
new file mode 100644
index 0000000..b7e9e05
--- /dev/null
+++ b/graphics-svg/src/test/res/round_path.svg
@@ -0,0 +1,20 @@
+
+
+
+
+]>
+
+
+
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index a70f27a..464a7eb 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,4 +1,5 @@
include 'graphics-png'
+include 'graphics-svg'
include 'graphics-vector'
include 'graphics-vector-eps'
include 'graphics-vector-pdf'